|
@@ -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;
|
|
}
|
|
}
|