From e340103250b59f3a7def8b69e56b39a356566863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arno=C5=A1t=20Pleskot?= Date: Thu, 15 Jun 2023 10:19:53 +0200 Subject: [PATCH] feat: firebase fallback for resume collaboration --- src/excalidraw-app/app_constants.ts | 1 + src/excalidraw-app/collab/Collab.tsx | 39 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/excalidraw-app/app_constants.ts b/src/excalidraw-app/app_constants.ts index e8a2516ce..cfd91c92e 100644 --- a/src/excalidraw-app/app_constants.ts +++ b/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) diff --git a/src/excalidraw-app/collab/Collab.tsx b/src/excalidraw-app/collab/Collab.tsx index 8cf15d3b4..477efd1bf 100644 --- a/src/excalidraw-app/collab/Collab.tsx +++ b/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 { } }; + fallbackResumeTimeout: null | ReturnType = null; + onPauseCollaborationChange = (state: PauseCollaborationState) => { switch (state) { case PauseCollaborationState.PAUSED: { @@ -345,7 +349,37 @@ class Collab extends PureComponent { 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 { appState: { viewModeEnabled: false }, }); this.excalidrawAPI.setToast(null); + + if (this.fallbackResumeTimeout) { + clearTimeout(this.fallbackResumeTimeout); + this.fallbackResumeTimeout = null; + } } } }