diff --git a/example/src/multiplayer/multiplayer.tsx b/example/src/multiplayer/multiplayer.tsx index 66def6778..ccf80bfaa 100644 --- a/example/src/multiplayer/multiplayer.tsx +++ b/example/src/multiplayer/multiplayer.tsx @@ -22,21 +22,23 @@ export function Multiplayer() { return ( - + ) } -function TldrawWrapper() { +function Editor({ roomId }: { roomId: string }) { const [docId] = React.useState(() => Utils.uniqueId()) - const [error, setError] = React.useState() - const [app, setApp] = React.useState() + const [error, setError] = React.useState() + useErrorListener((err) => setError(err)) + // Setup document + const doc = useObject<{ uuid: string; document: TDDocument }>('doc', { uuid: docId, document: { @@ -46,13 +48,10 @@ function TldrawWrapper() { }) // Put the state into the window, for debugging. - const handleMount = React.useCallback( - (app: TldrawApp) => { - window.app = app - setApp(app) - }, - [roomId] - ) + const handleMount = React.useCallback((app: TldrawApp) => { + window.app = app + setApp(app) + }, []) React.useEffect(() => { const room = client.getRoom(roomId) @@ -80,8 +79,7 @@ function TldrawWrapper() { function handleDocumentUpdates() { if (!doc) return - if (!app) return - if (!app.room) return + if (!app?.room) return const docObject = doc.toObject() @@ -101,7 +99,7 @@ function TldrawWrapper() { } function handleExit() { - if (!(app && app.room)) return + if (!app?.room) return room?.broadcastEvent({ name: 'exit', userId: app.room.userId }) } diff --git a/packages/tldraw/src/state/TldrawApp.ts b/packages/tldraw/src/state/TldrawApp.ts index 3e6a738bd..fb873104e 100644 --- a/packages/tldraw/src/state/TldrawApp.ts +++ b/packages/tldraw/src/state/TldrawApp.ts @@ -922,7 +922,7 @@ export class TldrawApp extends StateManager { * Load a fresh room into the state. * @param roomId */ - loadRoom = (roomId: string) => { + loadRoom = (roomId: string): this => { this.patchState({ room: { id: roomId, @@ -938,6 +938,7 @@ export class TldrawApp extends StateManager { }, }, }) + return this } /** diff --git a/www/components/MultiplayerEditor.tsx b/www/components/MultiplayerEditor.tsx index 2cd25d14b..3d8c45b46 100644 --- a/www/components/MultiplayerEditor.tsx +++ b/www/components/MultiplayerEditor.tsx @@ -29,7 +29,7 @@ export default function MultiplayerEditor({ }) { return ( - + @@ -57,6 +57,12 @@ function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: bool }, }) + // Put the state into the window, for debugging. + const handleMount = React.useCallback((app: TldrawApp) => { + window.app = app + setApp(app) + }, []) + // Setup client React.useEffect(() => { @@ -64,12 +70,9 @@ function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: bool if (!room) return if (!doc) return - if (!app?.room) return + if (!app) return - // Update the user's presence with the user from state - const { users, userId } = app.room - - room.updatePresence({ id: userId, user: users[userId] }) + app.loadRoom(roomId) // Subscribe to presence changes; when others change, update the state room.subscribe('others', (others) => { @@ -124,6 +127,13 @@ function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: bool if (newDocument) { app.loadDocument(newDocument) + app.loadRoom(roomId) + + // Update the user's presence with the user from state + if (app.state.room) { + const { users, userId } = app.state.room + room.updatePresence({ id: userId, user: users[userId] }) + } } return () => { @@ -132,15 +142,6 @@ function Editor({ roomId, isSponsor }: { roomId: string; isUser; isSponsor: bool } }, [doc, docId, app, roomId]) - const handleMount = React.useCallback( - (app: TldrawApp) => { - window.app = app - app.loadRoom(roomId) - setApp(app) - }, - [roomId] - ) - const handlePersist = React.useCallback( (app: TldrawApp) => { doc?.update({ uuid: docId, document: app.document })