fix(web): dedupe tree keys and guard against circular JSON

Key tree nodes by their index path instead of GUID, since TTS saves can
contain duplicate GUIDs. Skip the Parent back-reference in the default
viewer and stringify with a circular-reference guard.
This commit is contained in:
2026-08-08 12:23:48 +08:00
parent 08c767f399
commit f126bf7993
2 changed files with 44 additions and 18 deletions
+9 -4
View File
@@ -9,11 +9,12 @@ interface Props {
export default function ObjectTree({ nodes, selectedGuid, onSelect }: Props) {
return (
<ul className="space-y-0.5">
{nodes.map((node) => (
{nodes.map((node, index) => (
<TreeNode
key={node.object.GUID}
key={index}
node={node}
depth={0}
path={`${index}`}
selectedGuid={selectedGuid}
onSelect={onSelect}
/>
@@ -25,11 +26,14 @@ export default function ObjectTree({ nodes, selectedGuid, onSelect }: Props) {
function TreeNode({
node,
depth,
path,
selectedGuid,
onSelect,
}: {
node: ObjectTreeNode;
depth: number;
/** Index path from the root, used as a stable unique key. */
path: string;
selectedGuid: string | null;
onSelect: (guid: string) => void;
}) {
@@ -52,11 +56,12 @@ function TreeNode({
</button>
{node.children.length > 0 && (
<ul>
{node.children.map((child) => (
{node.children.map((child, index) => (
<TreeNode
key={child.object.GUID}
key={`${path}-${index}`}
node={child}
depth={depth + 1}
path={`${path}-${index}`}
selectedGuid={selectedGuid}
onSelect={onSelect}
/>