فهرست منبع

feat: firebase fallback for resume collaboration

Arnošt Pleskot 2 سال پیش
والد
کامیت
e340103250
2فایلهای تغییر یافته به همراه40 افزوده شده و 0 حذف شده
  1. 1 0
      src/excalidraw-app/app_constants.ts
  2. 39 0
      src/excalidraw-app/collab/Collab.tsx

+ 1 - 0
src/excalidraw-app/app_constants.ts

@@ -8,6 +8,7 @@ export const SYNC_BROWSER_TABS_TIMEOUT = 50;
 export const CURSOR_SYNC_TIMEOUT = 33; // ~30fps
 export const DELETED_ELEMENT_TIMEOUT = 24 * 60 * 60 * 1000; // 1 day
 export const PAUSE_COLLABORATION_TIMEOUT = 30000;
+export const RESUME_FALLBACK_TIMEOUT = 5000;
 
 export const FILE_UPLOAD_MAX_BYTES = 3 * 1024 * 1024; // 3 MiB
 // 1 year (https://stackoverflow.com/a/25201898/927631)

+ 39 - 0
src/excalidraw-app/collab/Collab.tsx

@@ -27,10 +27,12 @@ import {
   PAUSE_COLLABORATION_TIMEOUT,
   WS_SCENE_EVENT_TYPES,
   SYNC_FULL_SCENE_INTERVAL_MS,
+  RESUME_FALLBACK_TIMEOUT,
 } from "../app_constants";
 import {
   generateCollaborationLinkData,
   getCollaborationLink,
+  getCollaborationLinkData,
   getCollabServer,
   getSyncableElements,
   SocketUpdateDataSource,
@@ -320,6 +322,8 @@ class Collab extends PureComponent<Props, CollabState> {
     }
   };
 
+  fallbackResumeTimeout: null | ReturnType<typeof setTimeout> = null;
+
   onPauseCollaborationChange = (state: PauseCollaborationState) => {
     switch (state) {
       case PauseCollaborationState.PAUSED: {
@@ -345,7 +349,37 @@ class Collab extends PureComponent<Props, CollabState> {
             spinner: true,
             closable: false,
           });
+
+          // Fallback to fetch data from firebase when reconnecting to scene without collaborators
+          const fallbackResumeHandler = async () => {
+            const roomLinkData = getCollaborationLinkData(
+              this.state.activeRoomLink,
+            );
+            if (!roomLinkData) {
+              return;
+            }
+            const elements = await loadFromFirebase(
+              roomLinkData.roomId,
+              roomLinkData.roomKey,
+              this.portal.socket,
+            );
+            if (elements) {
+              this.setLastBroadcastedOrReceivedSceneVersion(
+                getSceneVersion(elements),
+              );
+
+              this.excalidrawAPI.updateScene({
+                elements,
+              });
+            }
+            this.onPauseCollaborationChange(PauseCollaborationState.SYNCED);
+          };
+          this.fallbackResumeTimeout = setTimeout(
+            fallbackResumeHandler,
+            RESUME_FALLBACK_TIMEOUT,
+          );
         }
+
         break;
       }
       case PauseCollaborationState.SYNCED: {
@@ -356,6 +390,11 @@ class Collab extends PureComponent<Props, CollabState> {
             appState: { viewModeEnabled: false },
           });
           this.excalidrawAPI.setToast(null);
+
+          if (this.fallbackResumeTimeout) {
+            clearTimeout(this.fallbackResumeTimeout);
+            this.fallbackResumeTimeout = null;
+          }
         }
       }
     }