mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-10-31 02:44:50 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into fix_multiplayer_concurrency
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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(); | ||||
| @@ -348,11 +346,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; | ||||
|           } | ||||
| @@ -364,8 +365,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({ | ||||
| @@ -2133,17 +2147,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, | ||||
|   | ||||
| @@ -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} | ||||
|                       /> | ||||
|   | ||||
| @@ -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} | ||||
|               /> | ||||
|   | ||||
| @@ -116,7 +116,7 @@ export function RoomDialog({ | ||||
|   onRoomDestroy, | ||||
| }: { | ||||
|   isCollaborating: AppState["isCollaborating"]; | ||||
|   collaboratorCount: AppState["collaboratorCount"]; | ||||
|   collaboratorCount: number; | ||||
|   onRoomCreate: () => void; | ||||
|   onRoomDestroy: () => void; | ||||
| }) { | ||||
|   | ||||
| @@ -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 | ||||
|     } | ||||
|   | ||||
| @@ -34,8 +34,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<{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 dwelle
					dwelle