perf(vue): patch layer tree node updates

This commit is contained in:
Danila Poyarkov 2026-06-30 21:50:05 +03:00
parent cde9cd4610
commit 7f99638e65

View file

@ -7,6 +7,7 @@ import { provideLayerTree } from '#vue/primitives/LayerTree/context'
import { useLayerDrag } from '#vue/primitives/LayerTree/useLayerDrag'
import type { LayerNode } from '#vue/primitives/LayerTree/context'
import type { SceneNode } from '@open-pencil/scene-graph'
const { indentPerLevel = 16 } = defineProps<{
indentPerLevel?: number
@ -32,6 +33,17 @@ const { draggingId, instruction, instructionTargetId, setupItem } = useLayerDrag
expandNode
)
function nodeToLayerNode(node: SceneNode): LayerNode {
return {
id: node.id,
name: node.name,
type: node.type,
layoutMode: node.layoutMode,
visible: node.visible,
locked: node.locked
}
}
function buildTree(parentId: string): LayerNode[] {
const parent = editor.graph.getNode(parentId)
if (!parent) return []
@ -39,12 +51,7 @@ function buildTree(parentId: string): LayerNode[] {
.map((cid) => editor.graph.getNode(cid))
.filter((n): n is NonNullable<typeof n> => !!n)
.map((node) => ({
id: node.id,
name: node.name,
type: node.type,
layoutMode: node.layoutMode,
visible: node.visible,
locked: node.locked,
...nodeToLayerNode(node),
children: node.childIds.length > 0 ? buildTree(node.id) : undefined
}))
}
@ -59,6 +66,46 @@ function rebuildTree() {
treeVersion.value++
}
function replaceLayerNode(nodes: LayerNode[], replacement: LayerNode): LayerNode[] | null {
let changed = false
const next = nodes.map((node) => {
if (node.id === replacement.id) {
changed = true
return { ...replacement, children: node.children }
}
if (!node.children) return node
const children = replaceLayerNode(node.children, replacement)
if (!children) return node
changed = true
return { ...node, children }
})
return changed ? next : null
}
function patchLayerNode(id: string, changes: Partial<SceneNode>) {
if ('childIds' in changes || 'parentId' in changes) {
rebuildTree()
return
}
if (
!(
'name' in changes ||
'type' in changes ||
'layoutMode' in changes ||
'visible' in changes ||
'locked' in changes
)
) {
return
}
const node = editor.graph.getNode(id)
if (!node) return
const next = replaceLayerNode(items.value, nodeToLayerNode(node))
if (next) items.value = next
}
const unsubscribe = [
editor.onEditorEvent('graph:replaced', rebuildTree),
editor.onEditorEvent('page:changed', rebuildTree),
@ -66,7 +113,7 @@ const unsubscribe = [
editor.onEditorEvent('node:deleted', rebuildTree),
editor.onEditorEvent('node:reparented', rebuildTree),
editor.onEditorEvent('node:reordered', rebuildTree),
editor.onEditorEvent('node:updated', rebuildTree)
editor.onEditorEvent('node:updated', patchLayerNode)
]
onScopeDispose(() => {