@@ -72,6 +72,7 @@ class Collab extends PureComponent<CollabProps, CollabState> {
7272 private unsubExcalidrawPointerUp : ( ( ) => void ) | null = null ;
7373 private unsubExcalidrawSceneChange : ( ( ) => void ) | null = null ;
7474 private lastBroadcastedSceneVersion : number = - 1 ;
75+ private isInitialLoad : boolean = true ;
7576
7677 props : any ;
7778
@@ -82,7 +83,7 @@ class Collab extends PureComponent<CollabProps, CollabState> {
8283 connectionStatus : 'Uninstantiated' ,
8384 username : props . user ?. username || props . user ?. id || '' ,
8485 collaborators : new Map ( ) ,
85- lastProcessedSceneVersion : - 1 , // Version of the scene after applying remote changes
86+ lastProcessedSceneVersion : - 1 ,
8687 } ;
8788
8889 this . portal = new Portal (
@@ -131,7 +132,6 @@ class Collab extends PureComponent<CollabProps, CollabState> {
131132
132133 // Compare each field dynamically, but exclude collaborators field
133134 allKeys . forEach ( field => {
134- // Skip collaborators field - those are updates about other users, not changes by this user
135135 if ( field === 'collaborators' ) return ;
136136
137137 const oldValue = oldState [ field as keyof AppState ] ;
@@ -213,6 +213,8 @@ class Collab extends PureComponent<CollabProps, CollabState> {
213213 if ( ENABLE_PERIODIC_FULL_SYNC ) {
214214 this . startPeriodicFullSync ( ) ;
215215 }
216+
217+ this . isInitialLoad = false ;
216218 }
217219
218220 componentDidUpdate ( prevProps : CollabProps , prevState : CollabState ) {
@@ -229,22 +231,19 @@ class Collab extends PureComponent<CollabProps, CollabState> {
229231 // Portal's updatePadId will handle disconnection from old and connection to new
230232 this . debouncedBroadcastAppState . cancel ( ) ; // Cancel any pending app state updates for the old pad
231233 this . lastSentAppState = null ; // Reset last sent app state for the new pad
234+
235+ // Reset versions immediately when switching pads
236+ this . lastBroadcastedSceneVersion = - 1 ;
237+ // Mark as initial load for the new pad
238+ this . isInitialLoad = true ;
239+
232240 this . portal . updatePadId ( this . props . padId ) ;
233241 this . setState ( {
234242 collaborators : new Map ( ) ,
235243 lastProcessedSceneVersion : - 1 ,
236244 username : this . props . user ?. username || this . props . user ?. id || '' ,
237245 // connectionStatus will be updated by portal's callbacks
238246 } ) ;
239- this . lastBroadcastedSceneVersion = - 1 ;
240-
241- // Listeners might need to be re-evaluated if excalidrawAPI instance changes with padId
242- // For now, assuming excalidrawAPI is stable or re-bound by parent
243- if ( this . props . excalidrawAPI ) {
244- const initialElements = this . props . excalidrawAPI . getSceneElementsIncludingDeleted ( ) ;
245- this . lastBroadcastedSceneVersion = getSceneVersion ( initialElements ) ;
246- this . setState ( { lastProcessedSceneVersion : this . lastBroadcastedSceneVersion } ) ;
247- }
248247 }
249248
250249 if ( this . state . collaborators !== prevState . collaborators ) {
@@ -366,6 +365,31 @@ class Collab extends PureComponent<CollabProps, CollabState> {
366365 const allCurrentElements = this . props . excalidrawAPI . getSceneElementsIncludingDeleted ( ) ;
367366 const currentSceneVersion = getSceneVersion ( allCurrentElements ) ;
368367
368+ if ( allCurrentElements . length === 0 && this . isInitialLoad ) {
369+ // No elements in the scene is the temporary scene
370+ return ;
371+ }
372+
373+ // Handle version initialization (either fresh pad or loading from backend)
374+ if ( this . lastBroadcastedSceneVersion === - 1 || this . state . lastProcessedSceneVersion === - 1 ) {
375+ // Initialize versions
376+ this . lastBroadcastedSceneVersion = currentSceneVersion ;
377+ this . setState ( { lastProcessedSceneVersion : currentSceneVersion } ) ;
378+
379+ // Only broadcast if this is NOT an initial load (i.e., it's a genuinely fresh pad with user changes)
380+ // and there are elements to broadcast
381+ if ( ! this . isInitialLoad && allCurrentElements . length > 0 ) {
382+ this . portal . broadcastSceneUpdate ( 'SCENE_UPDATE' , allCurrentElements , false ) ;
383+ }
384+
385+ // Mark initial load as complete if it was an initial load
386+ if ( this . isInitialLoad ) {
387+ this . isInitialLoad = false ;
388+ }
389+
390+ return ;
391+ }
392+
369393 // Avoid broadcasting if the scene version hasn't actually increased from what this client last broadcasted
370394 // and isn't newer than what this client last processed from a remote update (prevents echo).
371395 if ( currentSceneVersion > this . lastBroadcastedSceneVersion && currentSceneVersion > this . state . lastProcessedSceneVersion ) {
@@ -495,7 +519,17 @@ class Collab extends PureComponent<CollabProps, CollabState> {
495519 ) ;
496520
497521 this . props . excalidrawAPI . updateScene ( { elements : reconciled as ExcalidrawElementType [ ] , commitToHistory : false } ) ;
498- this . setState ( { lastProcessedSceneVersion : getSceneVersion ( reconciled ) } ) ;
522+
523+ const reconciledVersion = getSceneVersion ( reconciled ) ;
524+ this . setState ( { lastProcessedSceneVersion : reconciledVersion } ) ;
525+
526+ // If this is a fresh pad (lastBroadcastedSceneVersion is -1), initialize it
527+ if ( this . lastBroadcastedSceneVersion === - 1 ) {
528+ console . debug ( '[pad.ws] Initializing lastBroadcastedSceneVersion from remote scene update' ) ;
529+ this . lastBroadcastedSceneVersion = reconciledVersion ;
530+ // Mark initial load as complete since we received remote data
531+ this . isInitialLoad = false ;
532+ }
499533 }
500534 break ;
501535 }
0 commit comments