tldraw/state/coop/coop-state.ts

91 lines
2.5 KiB
TypeScript
Raw Normal View History

2021-06-30 20:31:29 +00:00
import { createSelectorHook, createState } from '@state-designer/react'
import { CoopPresence } from 'types'
import { User } from '@liveblocks/client'
2021-07-02 12:04:45 +00:00
import CoopClient from 'state/coop/client-liveblocks'
2021-06-30 20:31:29 +00:00
type ConnectionState =
| 'closed'
| 'authenticating'
| 'unavailable'
| 'failed'
| 'open'
| 'connecting'
const coopState = createState({
data: {
2021-07-02 12:04:45 +00:00
client: undefined as CoopClient | undefined,
2021-06-30 20:31:29 +00:00
status: 'closed' as ConnectionState,
others: {} as Record<string, User<CoopPresence>>,
},
2021-07-02 12:04:45 +00:00
initial: 'offline',
states: {
offline: {
on: {
2021-07-07 13:02:48 +00:00
OPENED_ROOM: { to: 'online' },
2021-07-02 12:04:45 +00:00
},
},
online: {
2021-07-07 13:02:48 +00:00
onEnter: ['createClient', 'connectToRoom'],
2021-07-02 12:04:45 +00:00
on: {
MOVED_CURSOR: 'updateCursor',
JOINED_ROOM: 'setOthers',
2021-07-07 13:02:48 +00:00
OPENED_ROOM: 'connectToRoom',
2021-07-02 12:04:45 +00:00
CHANGED_CONNECTION_STATUS: 'setStatus',
OTHER_USER_ENTERED: 'addOtherUser',
OTHER_USER_LEFT: 'removeOtherUser',
OTHER_USER_UPDATED: 'updateOtherUser',
RESET_OTHER_USERS: 'resetOtherUsers',
LEFT_ROOM: 'disconnectFromRoom',
},
},
},
conditions: {
hasClient(data) {
return data.client !== undefined
},
2021-06-30 20:31:29 +00:00
},
actions: {
2021-07-02 12:04:45 +00:00
createClient(data) {
data.client = new CoopClient()
},
2021-06-30 20:31:29 +00:00
connectToRoom(data, payload: { id: string }) {
2021-07-02 12:04:45 +00:00
data.client.connect(payload.id)
},
disconnectFromRoom(data) {
data.client.disconnect()
2021-06-30 20:31:29 +00:00
},
2021-07-02 12:04:45 +00:00
updateCursor(data, payload: { pageId: string; point: number[] }) {
data.client.moveCursor(payload.pageId, payload.point)
2021-06-30 20:31:29 +00:00
},
setStatus(data, payload: { status: ConnectionState }) {
2021-07-02 12:04:45 +00:00
data.status = payload?.status
2021-06-30 20:31:29 +00:00
},
setOthers(data, payload: { others: User<CoopPresence>[] }) {
const { others } = payload
2021-07-04 20:27:57 +00:00
if (!others) return
2021-06-30 20:31:29 +00:00
data.others = Object.fromEntries(
others.map((user) => [user.connectionId, user])
)
},
addOtherUser(data, payload: { user: User<CoopPresence> }) {
const { user } = payload
data.others[user.connectionId] = user
},
removeOtherUser(data, payload: { user: User<CoopPresence> }) {
const { user } = payload
delete data.others[user.connectionId]
},
updateOtherUser(data, payload: { user: User<CoopPresence>; changes: any }) {
const { user } = payload
data.others[user.connectionId] = user
},
resetOtherUsers(data) {
data.others = {}
},
},
})
export const useCoopSelector = createSelectorHook(coopState)
export default coopState