Procházet zdrojové kódy

fix: disconnect from and reconnect to socket server when visibilitychange

Ryan Di před 3 roky
rodič
revize
f8c9f63650

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

@@ -7,6 +7,7 @@ export const SYNC_FULL_SCENE_INTERVAL_MS = 20000;
 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 HIDDEN_DISCONNECT_TIMEOUT = 30000;
 
 export const FILE_UPLOAD_MAX_BYTES = 3 * 1024 * 1024; // 3 MiB
 // 1 year (https://stackoverflow.com/a/25201898/927631)

+ 28 - 0
src/excalidraw-app/index.tsx

@@ -43,6 +43,7 @@ import {
 } from "../utils";
 import {
   FIREBASE_STORAGE_PREFIXES,
+  HIDDEN_DISCONNECT_TIMEOUT,
   STORAGE_KEYS,
   SYNC_BROWSER_TABS_TIMEOUT,
 } from "./app_constants";
@@ -452,6 +453,8 @@ const ExcalidrawWrapper = () => {
       LocalData.flushSave();
     };
 
+    let disconnectTimeout: ReturnType<typeof setTimeout>;
+
     const visibilityChange = (event: FocusEvent | Event) => {
       if (event.type === EVENT.BLUR || document.hidden) {
         LocalData.flushSave();
@@ -461,6 +464,31 @@ const ExcalidrawWrapper = () => {
         event.type === EVENT.FOCUS
       ) {
         syncData();
+
+        const disconnect = () => {
+          disconnectTimeout = setTimeout(
+            () => collabAPI.stopCollaboration(false),
+            HIDDEN_DISCONNECT_TIMEOUT,
+          );
+        };
+        const cancelPrevDisconnect = () => clearTimeout(disconnectTimeout);
+
+        if (document.hidden && collabAPI.isCollaborating()) {
+          if (!disconnectTimeout) {
+            disconnect();
+          } else {
+            cancelPrevDisconnect();
+            disconnect();
+          }
+        } else {
+          cancelPrevDisconnect();
+          if (!collabAPI.isCollaborating()) {
+            initializeScene({ collabAPI, excalidrawAPI }).then(async (data) => {
+              loadImages(data, /* isInitialLoad */ true);
+              initialStatePromiseRef.current.promise.resolve(data.scene);
+            });
+          }
+        }
       }
     };