Преглед изворни кода

feat: use userId instead of socketId

Arnošt Pleskot пре 2 година
родитељ
комит
2bdf09153c

+ 27 - 20
src/excalidraw-app/collab/Collab.tsx

@@ -16,6 +16,7 @@ import { Collaborator, Gesture } from "../../types";
 import {
 import {
   preventUnload,
   preventUnload,
   resolvablePromise,
   resolvablePromise,
+  upsertMap,
   withBatchedUpdates,
   withBatchedUpdates,
 } from "../../utils";
 } from "../../utils";
 import {
 import {
@@ -74,6 +75,7 @@ import { resetBrowserStateVersions } from "../data/tabSync";
 import { LocalData } from "../data/LocalData";
 import { LocalData } from "../data/LocalData";
 import { atom, useAtom } from "jotai";
 import { atom, useAtom } from "jotai";
 import { appJotaiStore } from "../app-jotai";
 import { appJotaiStore } from "../app-jotai";
+import { nanoid } from "nanoid";
 
 
 export const collabAPIAtom = atom<CollabAPI | null>(null);
 export const collabAPIAtom = atom<CollabAPI | null>(null);
 export const collabDialogShownAtom = atom(false);
 export const collabDialogShownAtom = atom(false);
@@ -85,6 +87,7 @@ interface CollabState {
   errorMessage: string;
   errorMessage: string;
   username: string;
   username: string;
   activeRoomLink: string;
   activeRoomLink: string;
+  userId: string;
 }
 }
 
 
 type CollabInstance = InstanceType<typeof Collab>;
 type CollabInstance = InstanceType<typeof Collab>;
@@ -125,6 +128,7 @@ class Collab extends PureComponent<Props, CollabState> {
       errorMessage: "",
       errorMessage: "",
       username: importUsernameFromLocalStorage() || "",
       username: importUsernameFromLocalStorage() || "",
       activeRoomLink: "",
       activeRoomLink: "",
+      userId: nanoid(),
     };
     };
     this.portal = new Portal(this);
     this.portal = new Portal(this);
     this.fileManager = new FileManager({
     this.fileManager = new FileManager({
@@ -644,33 +648,36 @@ class Collab extends PureComponent<Props, CollabState> {
             );
             );
             break;
             break;
           case "MOUSE_LOCATION": {
           case "MOUSE_LOCATION": {
-            const { pointer, button, username, selectedElementIds } =
+            const { pointer, button, username, selectedElementIds, userId } =
               decryptedData.payload;
               decryptedData.payload;
-            const socketId: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["socketId"] =
-              decryptedData.payload.socketId ||
-              // @ts-ignore legacy, see #2094 (#2097)
-              decryptedData.payload.socketID;
-
-            const collaborators = new Map(this.collaborators);
-            const user = collaborators.get(socketId) || {}!;
-            user.pointer = pointer;
-            user.button = button;
-            user.selectedElementIds = selectedElementIds;
-            user.username = username;
-            collaborators.set(socketId, user);
+            const collaborators = upsertMap(
+              userId,
+              {
+                username,
+                pointer,
+                button,
+                selectedElementIds,
+              },
+              this.collaborators,
+            );
             this.excalidrawAPI.updateScene({
             this.excalidrawAPI.updateScene({
-              collaborators,
+              collaborators: new Map(collaborators),
             });
             });
             break;
             break;
           }
           }
           case "IDLE_STATUS": {
           case "IDLE_STATUS": {
-            const { userState, socketId, username } = decryptedData.payload;
-            const collaborators = new Map(this.collaborators);
-            const user = collaborators.get(socketId) || {}!;
-            user.userState = userState;
-            user.username = username;
+            const { userState, username, userId } = decryptedData.payload;
+            const collaborators = upsertMap(
+              userId,
+              {
+                username,
+                userState,
+                userId,
+              },
+              this.collaborators,
+            );
             this.excalidrawAPI.updateScene({
             this.excalidrawAPI.updateScene({
-              collaborators,
+              collaborators: new Map(collaborators),
             });
             });
             break;
             break;
           }
           }

+ 4 - 7
src/excalidraw-app/collab/Portal.tsx

@@ -74,9 +74,6 @@ class Portal {
         /* syncAll */ true,
         /* syncAll */ true,
       );
       );
     });
     });
-    this.socket.on("room-user-change", (clients: string[]) => {
-      this.collab.setCollaborators(clients);
-    });
   }
   }
 
 
   isOpen() {
   isOpen() {
@@ -189,13 +186,13 @@ class Portal {
   };
   };
 
 
   broadcastIdleChange = (userState: UserIdleState) => {
   broadcastIdleChange = (userState: UserIdleState) => {
-    if (this.socket?.id) {
+    if (this.socket) {
       const data: SocketUpdateDataSource["IDLE_STATUS"] = {
       const data: SocketUpdateDataSource["IDLE_STATUS"] = {
         type: "IDLE_STATUS",
         type: "IDLE_STATUS",
         payload: {
         payload: {
-          socketId: this.socket.id,
           userState,
           userState,
           username: this.collab.state.username,
           username: this.collab.state.username,
+          userId: this.collab.state.userId,
         },
         },
       };
       };
       return this._broadcastSocketData(
       return this._broadcastSocketData(
@@ -209,16 +206,16 @@ class Portal {
     pointer: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointer"];
     pointer: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointer"];
     button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
     button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
   }) => {
   }) => {
-    if (this.socket?.id) {
+    if (this.socket) {
       const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
       const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
         type: "MOUSE_LOCATION",
         type: "MOUSE_LOCATION",
         payload: {
         payload: {
-          socketId: this.socket.id,
           pointer: payload.pointer,
           pointer: payload.pointer,
           button: payload.button || "up",
           button: payload.button || "up",
           selectedElementIds:
           selectedElementIds:
             this.collab.excalidrawAPI.getAppState().selectedElementIds,
             this.collab.excalidrawAPI.getAppState().selectedElementIds,
           username: this.collab.state.username,
           username: this.collab.state.username,
+          userId: this.collab.state.userId,
         },
         },
       };
       };
       return this._broadcastSocketData(
       return this._broadcastSocketData(

+ 2 - 2
src/excalidraw-app/data/index.ts

@@ -106,19 +106,19 @@ export type SocketUpdateDataSource = {
   MOUSE_LOCATION: {
   MOUSE_LOCATION: {
     type: "MOUSE_LOCATION";
     type: "MOUSE_LOCATION";
     payload: {
     payload: {
-      socketId: string;
       pointer: { x: number; y: number };
       pointer: { x: number; y: number };
       button: "down" | "up";
       button: "down" | "up";
       selectedElementIds: AppState["selectedElementIds"];
       selectedElementIds: AppState["selectedElementIds"];
       username: string;
       username: string;
+      userId: string;
     };
     };
   };
   };
   IDLE_STATUS: {
   IDLE_STATUS: {
     type: "IDLE_STATUS";
     type: "IDLE_STATUS";
     payload: {
     payload: {
-      socketId: string;
       userState: UserIdleState;
       userState: UserIdleState;
       username: string;
       username: string;
+      userId: string;
     };
     };
   };
   };
 };
 };

+ 2 - 2
src/renderer/renderScene.ts

@@ -619,8 +619,8 @@ export const _renderScene = ({
           if (renderConfig.remoteSelectedElementIds[element.id]) {
           if (renderConfig.remoteSelectedElementIds[element.id]) {
             selectionColors.push(
             selectionColors.push(
               ...renderConfig.remoteSelectedElementIds[element.id].map(
               ...renderConfig.remoteSelectedElementIds[element.id].map(
-                (socketId) => {
-                  const background = getClientColor(socketId);
+                (userId) => {
+                  const background = getClientColor(userId);
                   return background;
                   return background;
                 },
                 },
               ),
               ),

+ 12 - 0
src/utils.ts

@@ -20,6 +20,7 @@ import { unstable_batchedUpdates } from "react-dom";
 import { SHAPES } from "./shapes";
 import { SHAPES } from "./shapes";
 import { isEraserActive, isHandToolActive } from "./appState";
 import { isEraserActive, isHandToolActive } from "./appState";
 import { ResolutionType } from "./utility-types";
 import { ResolutionType } from "./utility-types";
+import { reconcileElements } from "./excalidraw-app/collab/reconciliation";
 
 
 let mockDateTime: string | null = null;
 let mockDateTime: string | null = null;
 
 
@@ -907,3 +908,14 @@ export const isOnlyExportingSingleFrame = (
     )
     )
   );
   );
 };
 };
+
+export const upsertMap = <T>(key: T, value: object, map: Map<T, object>) => {
+  if (!map.has(key)) {
+    map.set(key, value);
+  } else {
+    const old = map.get(key);
+    map.set(key, { ...old, ...value });
+  }
+
+  return map;
+};