diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6684c73..1d9ebd9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -293,11 +293,13 @@ const CADEditor: React.FC = ({ projectId, token, onNavigateBack }, [collab.elements, collab.layers, collab.blocks, collab.status]); const handleElementCreated = useCallback((el: CADElement) => { - const newElements = [...elements, el]; - historyManagerRef.current.pushSnapshot({ - elements: newElements, layers, blocks, groups, bgConfig, - }, 'Element erstellt'); - setElements(newElements); + setElements((prev) => { + const newElements = [...prev, el]; + historyManagerRef.current.pushSnapshot({ + elements: newElements, layers, blocks, groups, bgConfig, + }, 'Element erstellt'); + return newElements; + }); syncHistory(); // Push to Yjs CRDT for real-time sync collab.setElement(el); @@ -311,14 +313,16 @@ const CADEditor: React.FC = ({ projectId, token, onNavigateBack setSavedStatus('Fehler beim Speichern'); }); } - }, [elements, layers, blocks, groups, bgConfig, syncHistory, drawingId, token, collab]); + }, [layers, blocks, groups, bgConfig, syncHistory, drawingId, token, collab]); const handleElementsDeleted = useCallback((ids: string[]) => { - const newElements = elements.filter((e) => !ids.includes(e.id)); - historyManagerRef.current.pushSnapshot({ - elements: newElements, layers, blocks, groups, bgConfig, - }, `${ids.length} Element(e) gelöscht`); - setElements(newElements); + setElements((prev) => { + const newElements = prev.filter((e) => !ids.includes(e.id)); + historyManagerRef.current.pushSnapshot({ + elements: newElements, layers, blocks, groups, bgConfig, + }, `${ids.length} Element(e) gelöscht`); + return newElements; + }); syncHistory(); // Push deletions to Yjs CRDT for real-time sync ids.forEach(id => collab.deleteElement(id)); @@ -335,14 +339,16 @@ const CADEditor: React.FC = ({ projectId, token, onNavigateBack }, [elements, layers, blocks, groups, bgConfig, syncHistory, token, collab]); const handleElementsModified = useCallback((modified: CADElement[]) => { - const newElements = elements.map((e) => { - const found = modified.find((m) => m.id === e.id); - return found ?? e; + setElements((prev) => { + const newElements = prev.map((e) => { + const found = modified.find((m) => m.id === e.id); + return found ?? e; + }); + historyManagerRef.current.pushSnapshot({ + elements: newElements, layers, blocks, groups, bgConfig, + }, `${modified.length} Element(e) geändert`); + return newElements; }); - historyManagerRef.current.pushSnapshot({ - elements: newElements, layers, blocks, groups, bgConfig, - }, `${modified.length} Element(e) geändert`); - setElements(newElements); syncHistory(); // Push modifications to Yjs CRDT for real-time sync modified.forEach(el => collab.setElement(el)); @@ -356,7 +362,7 @@ const CADEditor: React.FC = ({ projectId, token, onNavigateBack setSavedStatus('Fehler beim Speichern'); }); } - }, [elements, layers, blocks, groups, bgConfig, syncHistory, token, collab]); + }, [layers, blocks, groups, bgConfig, syncHistory, token, collab]); const lastCursorUpdateRef = useRef(0); const handleCursorMoved = useCallback((x: number, y: number) => { diff --git a/frontend/src/components/CanvasArea.tsx b/frontend/src/components/CanvasArea.tsx index 3a28f55..5a80fb5 100644 --- a/frontend/src/components/CanvasArea.tsx +++ b/frontend/src/components/CanvasArea.tsx @@ -72,6 +72,23 @@ const CanvasArea: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + // Update callbacks when they change (avoids stale closures) + useEffect(() => { + const interaction = interactionRef.current; + if (!interaction) return; + interaction.setCallbacks({ + onElementCreated, + onElementsDeleted, + onElementsModified, + onCursorMoved, + onToolStateChanged, + onTextEdit, + onCommandTrigger, + onSelectionChange, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [onElementCreated, onElementsDeleted, onElementsModified, onCursorMoved, onToolStateChanged, onTextEdit, onCommandTrigger, onSelectionChange]); + // Resize canvas to fill container useEffect(() => { const canvas = canvasRef.current;