Bladeren bron

Merge pull request #915 from excalidraw/fix_remote_pointers

remove remote pointers on client disconnect
Edwin Lin 5 jaren geleden
bovenliggende
commit
37284c9174
7 gewijzigde bestanden met toevoegingen van 41 en 25 verwijderingen
  1. 3 2
      src/appState.ts
  2. 33 17
      src/components/App.tsx
  3. 1 1
      src/components/LayerUI.tsx
  4. 1 1
      src/components/MobileMenu.tsx
  5. 1 1
      src/components/RoomDialog.tsx
  6. 1 1
      src/data/localStorage.ts
  7. 1 2
      src/types.ts

+ 3 - 2
src/appState.ts

@@ -34,8 +34,7 @@ export function getDefaultAppState(): AppState {
     openMenu: null,
     lastPointerDownWith: "mouse",
     selectedElementIds: {},
-    remotePointers: {},
-    collaboratorCount: 0,
+    collaborators: new Map(),
   };
 }
 
@@ -47,6 +46,8 @@ export function clearAppStateForLocalStorage(appState: AppState) {
     editingElement,
     selectionElement,
     isResizing,
+    collaborators,
+    isCollaborating,
     ...exportedState
   } = appState;
   return exportedState;

+ 33 - 17
src/components/App.tsx

@@ -193,8 +193,7 @@ export class App extends React.Component<any, AppState> {
       this.setState(state => ({
         ...res.appState,
         isCollaborating: state.isCollaborating,
-        remotePointers: state.remotePointers,
-        collaboratorCount: state.collaboratorCount,
+        collaborators: state.collaborators,
       }));
     }
   };
@@ -234,8 +233,7 @@ export class App extends React.Component<any, AppState> {
   private destroySocketClient = () => {
     this.setState({
       isCollaborating: false,
-      remotePointers: {},
-      collaboratorCount: 0,
+      collaborators: new Map(),
     });
     if (this.socket) {
       this.socket.close();
@@ -321,11 +319,14 @@ export class App extends React.Component<any, AppState> {
               break;
             case "MOUSE_LOCATION":
               const { socketID, pointerCoords } = decryptedData.payload;
-              this.setState({
-                remotePointers: {
-                  ...this.state.remotePointers,
-                  [socketID]: pointerCoords,
-                },
+              this.setState(state => {
+                if (state.collaborators.has(socketID)) {
+                  const user = state.collaborators.get(socketID)!;
+                  user.pointer = pointerCoords;
+                  state.collaborators.set(socketID, user);
+                  return state;
+                }
+                return null;
               });
               break;
           }
@@ -337,8 +338,21 @@ export class App extends React.Component<any, AppState> {
         }
         this.socketInitialized = true;
       });
-      this.socket.on("room-user-count", (collaboratorCount: number) => {
-        this.setState({ collaboratorCount });
+      this.socket.on("room-user-change", (clients: string[]) => {
+        this.setState(state => {
+          const collaborators: typeof state.collaborators = new Map();
+          for (const socketID of clients) {
+            if (state.collaborators.has(socketID)) {
+              collaborators.set(socketID, state.collaborators.get(socketID)!);
+            } else {
+              collaborators.set(socketID, {});
+            }
+          }
+          return {
+            ...state,
+            collaborators,
+          };
+        });
       });
       this.socket.on("new-user", async (socketID: string) => {
         this.broadcastSocketData({
@@ -2095,17 +2109,19 @@ export class App extends React.Component<any, AppState> {
     const pointerViewportCoords: {
       [id: string]: { x: number; y: number };
     } = {};
-    for (const clientId in this.state.remotePointers) {
-      const remotePointerCoord = this.state.remotePointers[clientId];
-      pointerViewportCoords[clientId] = sceneCoordsToViewportCoords(
+    this.state.collaborators.forEach((user, socketID) => {
+      if (!user.pointer) {
+        return;
+      }
+      pointerViewportCoords[socketID] = sceneCoordsToViewportCoords(
         {
-          sceneX: remotePointerCoord.x,
-          sceneY: remotePointerCoord.y,
+          sceneX: user.pointer.x,
+          sceneY: user.pointer.y,
         },
         this.state,
         this.canvas,
       );
-    }
+    });
     const { atLeastOneVisibleElement, scrollBars } = renderScene(
       elements,
       this.state,

+ 1 - 1
src/components/LayerUI.tsx

@@ -116,7 +116,7 @@ export const LayerUI = React.memo(
                       {actionManager.renderAction("clearCanvas")}
                       <RoomDialog
                         isCollaborating={appState.isCollaborating}
-                        collaboratorCount={appState.collaboratorCount}
+                        collaboratorCount={appState.collaborators.size}
                         onRoomCreate={onRoomCreate}
                         onRoomDestroy={onRoomDestroy}
                       />

+ 1 - 1
src/components/MobileMenu.tsx

@@ -47,7 +47,7 @@ export function MobileMenu({
               {actionManager.renderAction("clearCanvas")}
               <RoomDialog
                 isCollaborating={appState.isCollaborating}
-                collaboratorCount={appState.collaboratorCount}
+                collaboratorCount={appState.collaborators.size}
                 onRoomCreate={onRoomCreate}
                 onRoomDestroy={onRoomDestroy}
               />

+ 1 - 1
src/components/RoomDialog.tsx

@@ -116,7 +116,7 @@ export function RoomDialog({
   onRoomDestroy,
 }: {
   isCollaborating: AppState["isCollaborating"];
-  collaboratorCount: AppState["collaboratorCount"];
+  collaboratorCount: number;
   onRoomCreate: () => void;
   onRoomDestroy: () => void;
 }) {

+ 1 - 1
src/data/localStorage.ts

@@ -36,7 +36,7 @@ export function restoreFromLocalStorage() {
       appState = JSON.parse(savedState) as AppState;
       // If we're retrieving from local storage, we should not be collaborating
       appState.isCollaborating = false;
-      appState.collaboratorCount = 0;
+      appState.collaborators = new Map();
     } catch {
       // Do nothing because appState is already null
     }

+ 1 - 2
src/types.ts

@@ -35,8 +35,7 @@ export type AppState = {
   openMenu: "canvas" | "shape" | null;
   lastPointerDownWith: PointerType;
   selectedElementIds: { [id: string]: boolean };
-  remotePointers: { [id: string]: { x: number; y: number } };
-  collaboratorCount: number;
+  collaborators: Map<string, { pointer?: { x: number; y: number } }>;
 };
 
 export type PointerCoords = Readonly<{