|
|
|
@ -768,22 +768,22 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
const pointerViewportCoords: SceneState["remotePointerViewportCoords"] = {};
|
|
|
|
|
const remoteSelectedElementIds: SceneState["remoteSelectedElementIds"] = {};
|
|
|
|
|
const pointerUsernames: { [id: string]: string } = {};
|
|
|
|
|
this.state.collaborators.forEach((user, socketID) => {
|
|
|
|
|
this.state.collaborators.forEach((user, socketId) => {
|
|
|
|
|
if (user.selectedElementIds) {
|
|
|
|
|
for (const id of Object.keys(user.selectedElementIds)) {
|
|
|
|
|
if (!(id in remoteSelectedElementIds)) {
|
|
|
|
|
remoteSelectedElementIds[id] = [];
|
|
|
|
|
}
|
|
|
|
|
remoteSelectedElementIds[id].push(socketID);
|
|
|
|
|
remoteSelectedElementIds[id].push(socketId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!user.pointer) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (user.username) {
|
|
|
|
|
pointerUsernames[socketID] = user.username;
|
|
|
|
|
pointerUsernames[socketId] = user.username;
|
|
|
|
|
}
|
|
|
|
|
pointerViewportCoords[socketID] = sceneCoordsToViewportCoords(
|
|
|
|
|
pointerViewportCoords[socketId] = sceneCoordsToViewportCoords(
|
|
|
|
|
{
|
|
|
|
|
sceneX: user.pointer.x,
|
|
|
|
|
sceneY: user.pointer.y,
|
|
|
|
@ -792,7 +792,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
this.canvas,
|
|
|
|
|
window.devicePixelRatio,
|
|
|
|
|
);
|
|
|
|
|
cursorButton[socketID] = user.button;
|
|
|
|
|
cursorButton[socketId] = user.button;
|
|
|
|
|
});
|
|
|
|
|
const elements = this.scene.getElements();
|
|
|
|
|
const { atLeastOneVisibleElement, scrollBars } = renderScene(
|
|
|
|
@ -1294,8 +1294,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
break;
|
|
|
|
|
case "MOUSE_LOCATION": {
|
|
|
|
|
const {
|
|
|
|
|
socketID,
|
|
|
|
|
pointerCoords,
|
|
|
|
|
socketId,
|
|
|
|
|
pointer,
|
|
|
|
|
button,
|
|
|
|
|
username,
|
|
|
|
|
selectedElementIds,
|
|
|
|
@ -1303,15 +1303,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
// NOTE purposefully mutating collaborators map in case of
|
|
|
|
|
// pointer updates so as not to trigger LayerUI rerender
|
|
|
|
|
this.setState((state) => {
|
|
|
|
|
if (!state.collaborators.has(socketID)) {
|
|
|
|
|
state.collaborators.set(socketID, {});
|
|
|
|
|
if (!state.collaborators.has(socketId)) {
|
|
|
|
|
state.collaborators.set(socketId, {});
|
|
|
|
|
}
|
|
|
|
|
const user = state.collaborators.get(socketID)!;
|
|
|
|
|
user.pointer = pointerCoords;
|
|
|
|
|
const user = state.collaborators.get(socketId)!;
|
|
|
|
|
user.pointer = pointer;
|
|
|
|
|
user.button = button;
|
|
|
|
|
user.selectedElementIds = selectedElementIds;
|
|
|
|
|
user.username = username;
|
|
|
|
|
state.collaborators.set(socketID, user);
|
|
|
|
|
state.collaborators.set(socketId, user);
|
|
|
|
|
return state;
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
@ -1337,11 +1337,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
setCollaborators(sockets: string[]) {
|
|
|
|
|
this.setState((state) => {
|
|
|
|
|
const collaborators: typeof state.collaborators = new Map();
|
|
|
|
|
for (const socketID of sockets) {
|
|
|
|
|
if (state.collaborators.has(socketID)) {
|
|
|
|
|
collaborators.set(socketID, state.collaborators.get(socketID)!);
|
|
|
|
|
for (const socketId of sockets) {
|
|
|
|
|
if (state.collaborators.has(socketId)) {
|
|
|
|
|
collaborators.set(socketId, state.collaborators.get(socketId)!);
|
|
|
|
|
} else {
|
|
|
|
|
collaborators.set(socketID, {});
|
|
|
|
|
collaborators.set(socketId, {});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
@ -1352,15 +1352,15 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private broadcastMouseLocation = (payload: {
|
|
|
|
|
pointerCoords: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointerCoords"];
|
|
|
|
|
pointer: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointer"];
|
|
|
|
|
button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
|
|
|
|
|
}) => {
|
|
|
|
|
if (this.portal.socket?.id) {
|
|
|
|
|
const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
|
|
|
|
|
type: "MOUSE_LOCATION",
|
|
|
|
|
payload: {
|
|
|
|
|
socketID: this.portal.socket.id,
|
|
|
|
|
pointerCoords: payload.pointerCoords,
|
|
|
|
|
socketId: this.portal.socket.id,
|
|
|
|
|
pointer: payload.pointer,
|
|
|
|
|
button: payload.button || "up",
|
|
|
|
|
selectedElementIds: this.state.selectedElementIds,
|
|
|
|
|
username: this.state.username,
|
|
|
|
@ -3647,14 +3647,14 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
if (!x || !y) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const pointerCoords = viewportCoordsToSceneCoords(
|
|
|
|
|
const pointer = viewportCoordsToSceneCoords(
|
|
|
|
|
{ clientX: x, clientY: y },
|
|
|
|
|
this.state,
|
|
|
|
|
this.canvas,
|
|
|
|
|
window.devicePixelRatio,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (isNaN(pointerCoords.x) || isNaN(pointerCoords.y)) {
|
|
|
|
|
if (isNaN(pointer.x) || isNaN(pointer.y)) {
|
|
|
|
|
// sometimes the pointer goes off screen
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -3662,7 +3662,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
|
|
|
|
// do not broadcast when more than 1 pointer since that shows flickering on the other side
|
|
|
|
|
gesture.pointers.size < 2 &&
|
|
|
|
|
this.broadcastMouseLocation({
|
|
|
|
|
pointerCoords,
|
|
|
|
|
pointer,
|
|
|
|
|
button,
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|