improves multiplayer presence (#160)
This commit is contained in:
parent
3e7d2c3ad9
commit
abcdcd8dae
7 changed files with 137 additions and 94 deletions
|
@ -80,7 +80,9 @@ export function Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
hideHandles={hideHandles}
|
hideHandles={hideHandles}
|
||||||
meta={meta}
|
meta={meta}
|
||||||
/>
|
/>
|
||||||
{users && userId && <UsersIndicators userId={userId} users={users} meta={meta} />}
|
{users && userId && (
|
||||||
|
<UsersIndicators userId={userId} users={users} page={page} meta={meta} />
|
||||||
|
)}
|
||||||
{pageState.brush && <Brush brush={pageState.brush} />}
|
{pageState.brush && <Brush brush={pageState.brush} />}
|
||||||
{users && <Users userId={userId} users={users} />}
|
{users && <Users userId={userId} users={users} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import type { TLBinding, TLPage, TLPageState, TLShape, TLShapeUtil } from '+types'
|
import type { TLBinding, TLPage, TLPageState, TLShape, TLShapeUtil } from '+types'
|
||||||
import { useSelection, useShapeTree, useHandles, useTLContext } from '+hooks'
|
import { useSelection, useShapeTree, useTLContext } from '+hooks'
|
||||||
import { Bounds } from '+components/bounds'
|
import { Bounds } from '+components/bounds'
|
||||||
import { BoundsBg } from '+components/bounds/bounds-bg'
|
import { BoundsBg } from '+components/bounds/bounds-bg'
|
||||||
import { Handles } from '+components/handles'
|
import { Handles } from '+components/handles'
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { ShapeIndicator } from '+components/shape-indicator'
|
import { ShapeIndicator } from '+components/shape-indicator'
|
||||||
import type { TLShape, TLUsers } from '+types'
|
import type { TLPage, TLShape, TLUsers } from '+types'
|
||||||
import Utils from '+utils'
|
import Utils from '+utils'
|
||||||
import { useTLContext } from '+hooks'
|
import { useTLContext } from '+hooks'
|
||||||
|
|
||||||
interface UserIndicatorProps<T extends TLShape> {
|
interface UserIndicatorProps<T extends TLShape> {
|
||||||
|
page: TLPage<any, any>
|
||||||
userId: string
|
userId: string
|
||||||
users: TLUsers<T>
|
users: TLUsers<T>
|
||||||
meta: any
|
meta: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UsersIndicators<T extends TLShape>({ userId, users, meta }: UserIndicatorProps<T>) {
|
export function UsersIndicators<T extends TLShape>({
|
||||||
|
userId,
|
||||||
|
users,
|
||||||
|
meta,
|
||||||
|
page,
|
||||||
|
}: UserIndicatorProps<T>) {
|
||||||
const { shapeUtils } = useTLContext()
|
const { shapeUtils } = useTLContext()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -20,7 +26,9 @@ export function UsersIndicators<T extends TLShape>({ userId, users, meta }: User
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.filter((user) => user.id !== userId && user.selectedIds.length > 0)
|
.filter((user) => user.id !== userId && user.selectedIds.length > 0)
|
||||||
.map((user) => {
|
.map((user) => {
|
||||||
const shapes = user.activeShapes //.map((id) => page.shapes[id])
|
const shapes = user.selectedIds.map((id) => page.shapes[id]).filter(Boolean)
|
||||||
|
|
||||||
|
if (shapes.length === 0) return null
|
||||||
|
|
||||||
const bounds = Utils.getCommonBounds(
|
const bounds = Utils.getCommonBounds(
|
||||||
shapes.map((shape) => shapeUtils[shape.type].getBounds(shape))
|
shapes.map((shape) => shapeUtils[shape.type].getBounds(shape))
|
||||||
|
|
|
@ -11,7 +11,7 @@ export function Users({ userId, users }: UserProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.values(users)
|
{Object.values(users)
|
||||||
.filter((user) => user.id !== userId)
|
.filter((user) => user && user.id !== userId)
|
||||||
.map((user) => (
|
.map((user) => (
|
||||||
<User key={user.id} user={user} />
|
<User key={user.id} user={user} />
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -66,23 +66,26 @@ function TLDrawWrapper() {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.tlstate = tlstate
|
window.tlstate = tlstate
|
||||||
|
|
||||||
|
tlstate.loadRoom(ROOM_ID)
|
||||||
|
|
||||||
setTlstate(tlstate)
|
setTlstate(tlstate)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleChange = React.useCallback(
|
const handleChange = React.useCallback(
|
||||||
(_tlstate: TLDrawState, state: Data, reason: string) => {
|
(_tlstate: TLDrawState, state: Data, reason: string) => {
|
||||||
// If the client updates its document, update the room's document
|
// If the client updates its document, update the room's document
|
||||||
if (reason.startsWith('command')) {
|
if (reason.startsWith('command') || reason.startsWith('undo') || reason.startsWith('redo')) {
|
||||||
doc?.update({ uuid: docId, document: state.document })
|
doc?.update({ uuid: docId, document: state.document })
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the client updates its presence, update the room
|
// When the client updates its presence, update the room
|
||||||
if (state.room && (reason === 'patch:room:self:update' || reason === 'patch:selected')) {
|
// if (state.room && (reason === 'patch:room:self:update' || reason === 'patch:selected')) {
|
||||||
const room = client.getRoom(ROOM_ID)
|
// const room = client.getRoom(ROOM_ID)
|
||||||
if (!room) return
|
// if (!room) return
|
||||||
const { userId, users } = state.room
|
// const { userId, users } = state.room
|
||||||
room.updatePresence({ id: userId, user: users[userId] })
|
// room.updatePresence({ id: userId, user: users[userId] })
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
[docId, doc]
|
[docId, doc]
|
||||||
)
|
)
|
||||||
|
@ -93,9 +96,11 @@ function TLDrawWrapper() {
|
||||||
if (!room) return
|
if (!room) return
|
||||||
if (!doc) return
|
if (!doc) return
|
||||||
if (!tlstate) return
|
if (!tlstate) return
|
||||||
|
if (!tlstate.state.room) return
|
||||||
|
|
||||||
// Update the user's presence with the user from state
|
// Update the user's presence with the user from state
|
||||||
const { users, userId } = tlstate.state.room
|
const { users, userId } = tlstate.state.room
|
||||||
|
|
||||||
room.updatePresence({ id: userId, user: users[userId] })
|
room.updatePresence({ id: userId, user: users[userId] })
|
||||||
|
|
||||||
// Subscribe to presence changes; when others change, update the state
|
// Subscribe to presence changes; when others change, update the state
|
||||||
|
@ -118,6 +123,7 @@ function TLDrawWrapper() {
|
||||||
function handleDocumentUpdates() {
|
function handleDocumentUpdates() {
|
||||||
if (!doc) return
|
if (!doc) return
|
||||||
if (!tlstate) return
|
if (!tlstate) return
|
||||||
|
if (!tlstate.state.room) return
|
||||||
|
|
||||||
const docObject = doc.toObject()
|
const docObject = doc.toObject()
|
||||||
|
|
||||||
|
@ -127,13 +133,13 @@ function TLDrawWrapper() {
|
||||||
} else {
|
} else {
|
||||||
tlstate.updateUsers(
|
tlstate.updateUsers(
|
||||||
Object.values(tlstate.state.room.users).map((user) => {
|
Object.values(tlstate.state.room.users).map((user) => {
|
||||||
const activeShapes = user.activeShapes
|
// const activeShapes = user.activeShapes
|
||||||
.map((shape) => docObject.document.pages[tlstate.currentPageId].shapes[shape.id])
|
// .map((shape) => docObject.document.pages[tlstate.currentPageId].shapes[shape.id])
|
||||||
.filter(Boolean)
|
// .filter(Boolean)
|
||||||
return {
|
return {
|
||||||
...user,
|
...user,
|
||||||
activeShapes: activeShapes,
|
// activeShapes: activeShapes,
|
||||||
selectedIds: activeShapes.map((shape) => shape.id),
|
selectedIds: user.selectedIds, // activeShapes.map((shape) => shape.id),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -141,7 +147,8 @@ function TLDrawWrapper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleExit() {
|
function handleExit() {
|
||||||
room?.broadcastEvent({ name: 'exit', userId: tlstate?.state.room.userId })
|
if (!(tlstate && tlstate.state.room)) return
|
||||||
|
room?.broadcastEvent({ name: 'exit', userId: tlstate.state.room.userId })
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('beforeunload', handleExit)
|
window.addEventListener('beforeunload', handleExit)
|
||||||
|
@ -158,13 +165,26 @@ function TLDrawWrapper() {
|
||||||
}
|
}
|
||||||
}, [doc, docId, tlstate])
|
}, [doc, docId, tlstate])
|
||||||
|
|
||||||
|
const handleUserChange = React.useCallback(
|
||||||
|
(tlstate: TLDrawState, user: TLDrawUser) => {
|
||||||
|
const room = client.getRoom(ROOM_ID)
|
||||||
|
room?.updatePresence({ id: tlstate.state.room?.userId, user })
|
||||||
|
},
|
||||||
|
[client]
|
||||||
|
)
|
||||||
|
|
||||||
if (error) return <div>Error: {error.message}</div>
|
if (error) return <div>Error: {error.message}</div>
|
||||||
|
|
||||||
if (doc === null) return <div>Loading...</div>
|
if (doc === null) return <div>Loading...</div>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tldraw">
|
<div className="tldraw">
|
||||||
<TLDraw onChange={handleChange} onMount={handleMount} showPages={false} />
|
<TLDraw
|
||||||
|
onMount={handleMount}
|
||||||
|
onChange={handleChange}
|
||||||
|
onUserChange={handleUserChange}
|
||||||
|
showPages={false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as React from 'react'
|
||||||
import { IdProvider } from '@radix-ui/react-id'
|
import { IdProvider } from '@radix-ui/react-id'
|
||||||
import { Renderer } from '@tldraw/core'
|
import { Renderer } from '@tldraw/core'
|
||||||
import css from '~styles'
|
import css from '~styles'
|
||||||
import { Data, TLDrawDocument, TLDrawStatus } from '~types'
|
import { Data, TLDrawDocument, TLDrawStatus, TLDrawUser } from '~types'
|
||||||
import { TLDrawState } from '~state'
|
import { TLDrawState } from '~state'
|
||||||
import {
|
import {
|
||||||
TLDrawContext,
|
TLDrawContext,
|
||||||
|
@ -83,6 +83,8 @@ export interface TLDrawProps {
|
||||||
* (optional) A callback to run when the component's state changes.
|
* (optional) A callback to run when the component's state changes.
|
||||||
*/
|
*/
|
||||||
onChange?: TLDrawState['_onChange']
|
onChange?: TLDrawState['_onChange']
|
||||||
|
|
||||||
|
onUserChange?: (state: TLDrawState, user: TLDrawUser) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TLDraw({
|
export function TLDraw({
|
||||||
|
@ -94,16 +96,19 @@ export function TLDraw({
|
||||||
showPages = true,
|
showPages = true,
|
||||||
onMount,
|
onMount,
|
||||||
onChange,
|
onChange,
|
||||||
|
onUserChange,
|
||||||
}: TLDrawProps) {
|
}: TLDrawProps) {
|
||||||
const [sId, setSId] = React.useState(id)
|
const [sId, setSId] = React.useState(id)
|
||||||
|
|
||||||
const [tlstate, setTlstate] = React.useState(() => new TLDrawState(id, onChange, onMount))
|
const [tlstate, setTlstate] = React.useState(
|
||||||
|
() => new TLDrawState(id, onMount, onChange, onUserChange)
|
||||||
|
)
|
||||||
const [context, setContext] = React.useState(() => ({ tlstate, useSelector: tlstate.useStore }))
|
const [context, setContext] = React.useState(() => ({ tlstate, useSelector: tlstate.useStore }))
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (id === sId) return
|
if (id === sId) return
|
||||||
// If a new id is loaded, replace the entire state
|
// If a new id is loaded, replace the entire state
|
||||||
const newState = new TLDrawState(id, onChange, onMount)
|
const newState = new TLDrawState(id, onMount, onChange, onUserChange)
|
||||||
setTlstate(newState)
|
setTlstate(newState)
|
||||||
setContext({ tlstate: newState, useSelector: newState.useStore })
|
setContext({ tlstate: newState, useSelector: newState.useStore })
|
||||||
setSId(id)
|
setSId(id)
|
||||||
|
|
|
@ -48,8 +48,9 @@ import type { BaseTool } from './tool/BaseTool'
|
||||||
const uuid = Utils.uniqueId()
|
const uuid = Utils.uniqueId()
|
||||||
|
|
||||||
export class TLDrawState extends StateManager<Data> {
|
export class TLDrawState extends StateManager<Data> {
|
||||||
private _onChange?: (tlstate: TLDrawState, data: Data, reason: string) => void
|
|
||||||
private _onMount?: (tlstate: TLDrawState) => void
|
private _onMount?: (tlstate: TLDrawState) => void
|
||||||
|
private _onChange?: (tlstate: TLDrawState, data: Data, reason: string) => void
|
||||||
|
private _onUserChange?: (tlstate: TLDrawState, user: TLDrawUser) => void
|
||||||
|
|
||||||
inputs?: Inputs
|
inputs?: Inputs
|
||||||
|
|
||||||
|
@ -81,6 +82,9 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
height: 480,
|
height: 480,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The most recent pointer location
|
||||||
|
pointerPoint: number[] = [0, 0]
|
||||||
|
|
||||||
private pasteInfo = {
|
private pasteInfo = {
|
||||||
center: [0, 0],
|
center: [0, 0],
|
||||||
offset: [0, 0],
|
offset: [0, 0],
|
||||||
|
@ -88,11 +92,12 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id?: string,
|
id?: string,
|
||||||
|
onMount?: (tlstate: TLDrawState) => void,
|
||||||
onChange?: (tlstate: TLDrawState, data: Data, reason: string) => void,
|
onChange?: (tlstate: TLDrawState, data: Data, reason: string) => void,
|
||||||
onMount?: (tlstate: TLDrawState) => void
|
onUserChange?: (tlstate: TLDrawState, user: TLDrawUser) => void
|
||||||
) {
|
) {
|
||||||
super(TLDrawState.defaultState, id, TLDrawState.version, (prev, next) => {
|
super(TLDrawState.defaultState, id, TLDrawState.version, (prev, next) => {
|
||||||
console.log('Migrating to a new version.')
|
console.warn('Migrating to a new version.')
|
||||||
return {
|
return {
|
||||||
...next,
|
...next,
|
||||||
document: { ...next.document, ...prev.document },
|
document: { ...next.document, ...prev.document },
|
||||||
|
@ -101,6 +106,7 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
|
|
||||||
this._onChange = onChange
|
this._onChange = onChange
|
||||||
this._onMount = onMount
|
this._onMount = onMount
|
||||||
|
this._onUserChange = onUserChange
|
||||||
|
|
||||||
this.session = undefined
|
this.session = undefined
|
||||||
}
|
}
|
||||||
|
@ -278,31 +284,33 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
|
|
||||||
const currentPageId = data.appState.currentPageId
|
const currentPageId = data.appState.currentPageId
|
||||||
|
|
||||||
const currentPage = data.document.pages[currentPageId]
|
|
||||||
|
|
||||||
const currentPageState = data.document.pageStates[currentPageId]
|
const currentPageState = data.document.pageStates[currentPageId]
|
||||||
|
|
||||||
if (data.room && prev.room && data.room !== prev.room) {
|
if (data.room && data.room !== prev.room) {
|
||||||
const room = { ...data.room, users: { ...data.room.users } }
|
const room = { ...data.room, users: { ...data.room.users } }
|
||||||
|
|
||||||
// Remove any exited users
|
// Remove any exited users
|
||||||
Object.values(prev.room.users).forEach((user) => {
|
if (prev.room) {
|
||||||
|
Object.values(prev.room.users)
|
||||||
|
.filter(Boolean)
|
||||||
|
.forEach((user) => {
|
||||||
if (room.users[user.id] === undefined) {
|
if (room.users[user.id] === undefined) {
|
||||||
delete room.users[user.id]
|
delete room.users[user.id]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update the room presence selected ids
|
|
||||||
// Update the room presence active shapes
|
|
||||||
room.users[room.userId] = {
|
|
||||||
...room.users[room.userId],
|
|
||||||
selectedIds: currentPageState.selectedIds,
|
|
||||||
activeShapes: currentPageState.selectedIds.map((id) => currentPage.shapes[id]),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.room = room
|
data.room = room
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.room) {
|
||||||
|
data.room.users[data.room.userId] = {
|
||||||
|
...data.room.users[data.room.userId],
|
||||||
|
point: this.pointerPoint,
|
||||||
|
selectedIds: currentPageState.selectedIds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply selected style change, if any
|
// Apply selected style change, if any
|
||||||
|
|
||||||
const newSelectedStyle = TLDR.getSelectedStyle(data, currentPageId)
|
const newSelectedStyle = TLDR.getSelectedStyle(data, currentPageId)
|
||||||
|
@ -721,6 +729,28 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
return this.replaceState(nextState, `${reason}:${document.id}`)
|
return this.replaceState(nextState, `${reason}:${document.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a fresh room into the state.
|
||||||
|
* @param roomId
|
||||||
|
*/
|
||||||
|
loadRoom = (roomId: string) => {
|
||||||
|
this.patchState({
|
||||||
|
room: {
|
||||||
|
id: roomId,
|
||||||
|
userId: uuid,
|
||||||
|
users: {
|
||||||
|
[uuid]: {
|
||||||
|
id: uuid,
|
||||||
|
color: sample(USER_COLORS),
|
||||||
|
point: [100, 100],
|
||||||
|
selectedIds: [],
|
||||||
|
activeShapes: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a new document.
|
* Load a new document.
|
||||||
* @param document The document to load
|
* @param document The document to load
|
||||||
|
@ -1474,47 +1504,29 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
private setSelectedIds = (ids: string[], push = false): this => {
|
private setSelectedIds = (ids: string[], push = false): this => {
|
||||||
const nextIds = push ? [...this.pageState.selectedIds, ...ids] : [...ids]
|
const nextIds = push ? [...this.pageState.selectedIds, ...ids] : [...ids]
|
||||||
|
|
||||||
if (this.currentUser) {
|
if (this.state.room) {
|
||||||
return this.patchState(
|
const { users, userId } = this.state.room
|
||||||
{
|
this._onUserChange?.(this, {
|
||||||
appState: {
|
...users[userId],
|
||||||
activeTool: 'select',
|
|
||||||
},
|
|
||||||
document: {
|
|
||||||
pageStates: {
|
|
||||||
[this.currentPageId]: {
|
|
||||||
selectedIds: nextIds,
|
selectedIds: nextIds,
|
||||||
},
|
})
|
||||||
},
|
|
||||||
},
|
|
||||||
room: {
|
|
||||||
users: {
|
|
||||||
[this.currentUser.id]: {
|
|
||||||
...this.currentUser,
|
|
||||||
selectedIds: nextIds,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`selected`
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return this.patchState(
|
|
||||||
{
|
|
||||||
appState: {
|
|
||||||
activeTool: 'select',
|
|
||||||
},
|
|
||||||
document: {
|
|
||||||
pageStates: {
|
|
||||||
[this.currentPageId]: {
|
|
||||||
selectedIds: nextIds,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
`selected`
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.patchState(
|
||||||
|
{
|
||||||
|
appState: {
|
||||||
|
activeTool: 'select',
|
||||||
|
},
|
||||||
|
document: {
|
||||||
|
pageStates: {
|
||||||
|
[this.currentPageId]: {
|
||||||
|
selectedIds: nextIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
`selected`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2161,9 +2173,9 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
|
|
||||||
this.pan(delta)
|
this.pan(delta)
|
||||||
|
|
||||||
if (!info.spaceKey) {
|
|
||||||
// onPan is called by onPointerMove when spaceKey is pressed,
|
// onPan is called by onPointerMove when spaceKey is pressed,
|
||||||
// so we shouldn't call this again.
|
// so we shouldn't call this again.
|
||||||
|
if (!info.spaceKey) {
|
||||||
this.onPointerMove(info, e as unknown as React.PointerEvent)
|
this.onPointerMove(info, e as unknown as React.PointerEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2180,20 +2192,16 @@ export class TLDrawState extends StateManager<Data> {
|
||||||
// Several events (e.g. pan) can trigger the same "pointer move" behavior
|
// Several events (e.g. pan) can trigger the same "pointer move" behavior
|
||||||
this.currentTool.onPointerMove?.(info, e)
|
this.currentTool.onPointerMove?.(info, e)
|
||||||
|
|
||||||
|
this.pointerPoint = this.getPagePoint(info.point)
|
||||||
|
|
||||||
|
// Move this to an emitted event
|
||||||
if (this.state.room) {
|
if (this.state.room) {
|
||||||
const { users, userId } = this.state.room
|
const { users, userId } = this.state.room
|
||||||
|
|
||||||
if (Object.values(users).length === 1) return
|
this._onUserChange?.(this, {
|
||||||
|
|
||||||
this.updateUsers(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
...users[userId],
|
...users[userId],
|
||||||
point: this.getPagePoint(info.point),
|
point: this.getPagePoint(info.point),
|
||||||
},
|
})
|
||||||
],
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue