@@ -124,7 +124,7 @@ export const Editor: React.FC = () => {
124124 const latestFilesRef = useRef < any > ( null ) ;
125125 const lastSyncedFilesRef = useRef < Record < string , any > > ( { } ) ;
126126 const latestAppStateRef = useRef < any > ( null ) ;
127- const debouncedSaveRef = useRef < ( ( elements : readonly any [ ] , appState : any ) => void ) | null > ( null ) ;
127+ const debouncedSaveRef = useRef < ( ( drawingId : string , elements : readonly any [ ] , appState : any ) => void ) | null > ( null ) ;
128128
129129 const emitFilesDeltaIfNeeded = useCallback (
130130 ( nextFiles : Record < string , any > ) => {
@@ -361,13 +361,13 @@ export const Editor: React.FC = () => {
361361 const didEmit = emitFilesDeltaIfNeeded ( nextFiles ) ;
362362
363363 // Persist after file data becomes available so new tabs (tab3) load correctly.
364- if ( didEmit && latestAppStateRef . current && debouncedSaveRef . current ) {
365- debouncedSaveRef . current ( latestElementsRef . current , latestAppStateRef . current ) ;
364+ if ( didEmit && id && latestAppStateRef . current && debouncedSaveRef . current ) {
365+ debouncedSaveRef . current ( id , latestElementsRef . current , latestAppStateRef . current ) ;
366366 }
367367 } ;
368368 }
369369 setIsReady ( true ) ;
370- } , [ emitFilesDeltaIfNeeded ] ) ;
370+ } , [ emitFilesDeltaIfNeeded , id ] ) ;
371371
372372 // Handle #addLibrary URL hash parameter for importing libraries from links
373373 useEffect ( ( ) => {
@@ -428,12 +428,12 @@ export const Editor: React.FC = () => {
428428 scrollToContent : true ,
429429 } ) , [ ] ) ;
430430
431- const saveDataRef = useRef < ( ( elements : readonly any [ ] , appState : any ) => Promise < void > ) | null > ( null ) ;
432- const savePreviewRef = useRef < ( ( elements : readonly any [ ] , appState : any , files : any ) => Promise < void > ) | null > ( null ) ;
431+ const saveDataRef = useRef < ( ( drawingId : string , elements : readonly any [ ] , appState : any ) => Promise < void > ) | null > ( null ) ;
432+ const savePreviewRef = useRef < ( ( drawingId : string , elements : readonly any [ ] , appState : any , files : any ) => Promise < void > ) | null > ( null ) ;
433433 const saveLibraryRef = useRef < ( ( items : any [ ] ) => Promise < void > ) | null > ( null ) ;
434434
435- saveDataRef . current = async ( elements : readonly any [ ] , appState : any ) => {
436- if ( ! id ) return ;
435+ saveDataRef . current = async ( drawingId : string , elements : readonly any [ ] , appState : any ) => {
436+ if ( ! drawingId ) return ;
437437
438438 try {
439439 const persistableAppState = {
@@ -446,27 +446,27 @@ export const Editor: React.FC = () => {
446446 const persistableElements = Array . isArray ( snapshot ) ? snapshot : [ ] ;
447447
448448 console . log ( "[Editor] Saving drawing" , {
449- drawingId : id ,
449+ drawingId,
450450 elementCount : persistableElements . length ,
451451 hasRenderableElements : persistableElements . some ( ( el : any ) => ! el ?. isDeleted ) ,
452452 appState : persistableAppState ,
453453 } ) ;
454454
455- await api . updateDrawing ( id , {
455+ await api . updateDrawing ( drawingId , {
456456 elements : persistableElements ,
457457 appState : persistableAppState ,
458458 files : latestFilesRef . current || { } ,
459459 } ) ;
460460
461- console . log ( "[Editor] Save complete" , { drawingId : id } ) ;
461+ console . log ( "[Editor] Save complete" , { drawingId } ) ;
462462 } catch ( err ) {
463463 console . error ( 'Failed to save drawing' , err ) ;
464464 toast . error ( "Failed to save changes" ) ;
465465 }
466466 } ;
467467
468- savePreviewRef . current = async ( elements : readonly any [ ] , appState : any , files : any ) => {
469- if ( ! id ) return ;
468+ savePreviewRef . current = async ( drawingId : string , elements : readonly any [ ] , appState : any , files : any ) => {
469+ if ( ! drawingId ) return ;
470470
471471 try {
472472 const currentSnapshot = latestElementsRef . current ?? elements ;
@@ -484,13 +484,13 @@ export const Editor: React.FC = () => {
484484 const preview = svg . outerHTML ;
485485
486486 console . log ( "[Editor] Saving preview" , {
487- drawingId : id ,
487+ drawingId,
488488 elementCount : currentSnapshot . length ,
489489 } ) ;
490490
491- await api . updateDrawing ( id , { preview } ) ;
491+ await api . updateDrawing ( drawingId , { preview } ) ;
492492
493- console . log ( "[Editor] Preview save complete" , { drawingId : id } ) ;
493+ console . log ( "[Editor] Preview save complete" , { drawingId } ) ;
494494 } catch ( err ) {
495495 console . error ( 'Failed to save preview' , err ) ;
496496 }
@@ -509,19 +509,19 @@ export const Editor: React.FC = () => {
509509
510510
511511 const debouncedSave = useCallback (
512- debounce ( ( elements , appState ) => {
512+ debounce ( ( drawingId , elements , appState ) => {
513513 if ( saveDataRef . current ) {
514- saveDataRef . current ( elements , appState ) ;
514+ saveDataRef . current ( drawingId , elements , appState ) ;
515515 }
516516 } , 1000 ) ,
517517 [ ] // Empty dependency array = Stable across renders
518518 ) ;
519519 // Allow non-hook code (e.g., Excalidraw API wrappers) to trigger debounced saves.
520520 debouncedSaveRef . current = debouncedSave ;
521521 const debouncedSavePreview = useCallback (
522- debounce ( ( elements , appState , files ) => {
522+ debounce ( ( drawingId , elements , appState , files ) => {
523523 if ( savePreviewRef . current ) {
524- savePreviewRef . current ( elements , appState , files ) ;
524+ savePreviewRef . current ( drawingId , elements , appState , files ) ;
525525 }
526526 } , 10000 ) ,
527527 [ ]
@@ -536,6 +536,13 @@ export const Editor: React.FC = () => {
536536 [ ]
537537 ) ;
538538
539+ useEffect ( ( ) => {
540+ return ( ) => {
541+ debouncedSave . cancel ( ) ;
542+ debouncedSavePreview . cancel ( ) ;
543+ } ;
544+ } , [ debouncedSave , debouncedSavePreview ] ) ;
545+
539546 const broadcastChanges = useCallback (
540547 throttle ( ( elements : readonly any [ ] , currentFiles ?: Record < string , any > ) => {
541548 if ( ! socketRef . current || ! id ) return ;
@@ -670,8 +677,9 @@ export const Editor: React.FC = () => {
670677 const files = excalidrawAPI . current . getFiles ( ) || { } ;
671678 latestElementsRef . current = elements ;
672679 latestFilesRef . current = files ;
673- await saveDataRef . current ( elements , appState ) ;
674- savePreviewRef . current ( elements , appState , files ) ;
680+ if ( ! id ) return ;
681+ await saveDataRef . current ( id , elements , appState ) ;
682+ savePreviewRef . current ( id , elements , appState , files ) ;
675683 toast . success ( "Saved changes to server" ) ;
676684 }
677685 }
@@ -739,7 +747,9 @@ export const Editor: React.FC = () => {
739747 elementCount : allElements . length ,
740748 hasRenderableElements,
741749 } ) ;
742- debouncedSave ( allElements , appState ) ;
750+ if ( id ) {
751+ debouncedSave ( id , allElements , appState ) ;
752+ }
743753
744754 // Trigger Slow Preview Gen
745755 const filesSnapshot = currentFiles ;
@@ -748,8 +758,10 @@ export const Editor: React.FC = () => {
748758 drawingId : id ,
749759 fileCount : Object . keys ( filesSnapshot ) . length ,
750760 } ) ;
751- debouncedSavePreview ( allElements , appState , filesSnapshot ) ;
752- } , [ debouncedSave , debouncedSavePreview , broadcastChanges ] ) ;
761+ if ( id ) {
762+ debouncedSavePreview ( id , allElements , appState , filesSnapshot ) ;
763+ }
764+ } , [ debouncedSave , debouncedSavePreview , broadcastChanges , id ] ) ;
753765
754766 // Ensure file-only updates (e.g. pasted image dataURL arriving asynchronously)
755767 // are still broadcast to collaborators AND persisted to the server.
@@ -767,7 +779,7 @@ export const Editor: React.FC = () => {
767779
768780 // Persist after file data becomes available (covers the "tab 3" case).
769781 if ( didEmit && latestAppStateRef . current && debouncedSaveRef . current ) {
770- debouncedSaveRef . current ( latestElementsRef . current , latestAppStateRef . current ) ;
782+ debouncedSaveRef . current ( id , latestElementsRef . current , latestAppStateRef . current ) ;
771783 }
772784 } , 1000 ) ;
773785
@@ -803,15 +815,16 @@ export const Editor: React.FC = () => {
803815 // Save drawing and generate preview before navigating
804816 try {
805817 if ( excalidrawAPI . current && saveDataRef . current && savePreviewRef . current ) {
818+ if ( ! id ) return ;
806819 const elements = excalidrawAPI . current . getSceneElementsIncludingDeleted ( ) ;
807820 const appState = excalidrawAPI . current . getAppState ( ) ;
808821 const files = excalidrawAPI . current . getFiles ( ) || { } ;
809822 latestElementsRef . current = elements ;
810823 latestFilesRef . current = files ;
811824
812825 await Promise . all ( [
813- saveDataRef . current ( elements , appState ) ,
814- savePreviewRef . current ( elements , appState , files )
826+ saveDataRef . current ( id , elements , appState ) ,
827+ savePreviewRef . current ( id , elements , appState , files )
815828 ] ) ;
816829 console . log ( "[Editor] Saved on back navigation" , { drawingId : id } ) ;
817830 }
0 commit comments