task(CAD-14): phase 2 - stale closure fix (onElementCreatedRef), debug expose docCount/announcedCount, overlay handles for pixi mode

This commit is contained in:
Agent Zero
2026-09-16 18:28:27 +02:00
parent 02ed6a5ff0
commit f9c67a7d78
+11 -2
View File
@@ -41,8 +41,11 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
const pixiRendererRef = useRef<PixiRenderer | null>(null); const pixiRendererRef = useRef<PixiRenderer | null>(null);
/** CAD-13-fix: Bereits in Pixi gespiegelte Bestands-Elemente (id -> Referenz). */ /** CAD-13-fix: Bereits in Pixi gespiegelte Bestands-Elemente (id -> Referenz). */
const pixiMirrorRef = useRef<Map<string, CADElement>>(new Map()); const pixiMirrorRef = useRef<Map<string, CADElement>>(new Map());
/** Bereits an onElementCreated gemeldete V2-Element-IDs (verhindert Doppelmeldung bei jedem onChanged-Frame). */ /** CAD-14: Bereits an onElementCreated gemeldete V2-Element-IDs (verhindert Doppelmeldung bei jedem onChanged-Frame). */
const announcedV2Ids = useRef<Set<string>>(new Set()); const announcedV2Ids = useRef<Set<string>>(new Set());
/** CAD-14: Frische Prop-Referenz gegen Stale-Closure (Dispatcher/onChanged sind einmalig registriert). */
const onElementCreatedRef = useRef(onElementCreated);
onElementCreatedRef.current = onElementCreated;
const spatialIndexRef = useRef<SpatialIndex | null>(null); const spatialIndexRef = useRef<SpatialIndex | null>(null);
const layerManagerRef = useRef<LayerManager | null>(null); const layerManagerRef = useRef<LayerManager | null>(null);
const selectionEngineRef = useRef<SelectionEngine | null>(null); const selectionEngineRef = useRef<SelectionEngine | null>(null);
@@ -92,6 +95,8 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
(window as unknown as { __v2Debug: unknown }).__v2Debug = { (window as unknown as { __v2Debug: unknown }).__v2Debug = {
renderer: pixi, renderer: pixi,
info: () => pixiRendererRef.current?.getDebugInfo() ?? null, info: () => pixiRendererRef.current?.getDebugInfo() ?? null,
docCount: () => v2Doc.getAllElements().length,
announcedCount: () => announcedV2Ids.current.size,
}; };
}).catch((err) => { }).catch((err) => {
logger.warn('Pixi init failed — V2-Overlay deaktiviert:', err); logger.warn('Pixi init failed — V2-Overlay deaktiviert:', err);
@@ -146,7 +151,9 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
for (const el of v2Doc.getAllElements()) { for (const el of v2Doc.getAllElements()) {
if (!announcedV2Ids.current.has(el.id)) { if (!announcedV2Ids.current.has(el.id)) {
announcedV2Ids.current.add(el.id); announcedV2Ids.current.add(el.id);
onElementCreated(el); // CAD-14: ueber Ref — die eingefrorene Prop haette eine alte
// drawingId-Closure (still kein DB-Save nach Spaet-Mount).
onElementCreatedRef.current(el);
} }
} }
syncPixi(); // Task C2: V2-Elemente in den PixiJS-Overlay-Renderer spiegeln syncPixi(); // Task C2: V2-Elemente in den PixiJS-Overlay-Renderer spiegeln
@@ -322,6 +329,8 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
} as never; } as never;
for (const el of elements) { for (const el of elements) {
currentIds.add(el.id); currentIds.add(el.id);
// CAD-14: V2-stämmige Elemente zeichnet syncPixi (v2Doc.onChanged) —
// hier NUR noch Aktualisierung des Spiegels, kein doppeltes drawElement.
if (mirror.get(el.id) !== el) { if (mirror.get(el.id) !== el) {
mirror.set(el.id, el); mirror.set(el.id, el);
const layer = layers.find((l) => l.id === el.layerId) ?? layerFallback; const layer = layers.find((l) => l.id === el.layerId) ?? layerFallback;