@tldraw/tlschema
Version:
A tiny little drawing app (schema).
91 lines (83 loc) • 2.63 kB
text/typescript
import { Signal, computed } from '@tldraw/state'
import { TLStore } from './TLStore'
import { CameraRecordType } from './records/TLCamera'
import { TLINSTANCE_ID } from './records/TLInstance'
import { InstancePageStateRecordType } from './records/TLPageState'
import { TLPOINTER_ID } from './records/TLPointer'
import { InstancePresenceRecordType, TLInstancePresence } from './records/TLPresence'
/**
* The information about a user which is used for multiplayer features.
* @public
*/
export interface TLPresenceUserInfo {
/**
* id - A unique identifier for the user. This should be the same across all devices and sessions.
*/
id: string
/**
* The user's display name.
*/
name?: string | null
/**
* The user's color. If not given, a random color will be assigned.
*/
color?: string | null
}
/**
* Creates a derivation that represents the current presence state of the current user.
* @public
*/
export function createPresenceStateDerivation(
$user: Signal<TLPresenceUserInfo>,
instanceId?: TLInstancePresence['id']
) {
return (store: TLStore): Signal<TLInstancePresence | null> => {
return computed('instancePresence', () => {
const user = $user.get()
if (!user) return null
const state = getDefaultUserPresence(store, user)
if (!state) return null
return InstancePresenceRecordType.create({
...state,
id: instanceId ?? InstancePresenceRecordType.createId(store.id),
})
})
}
}
/** @public */
export type TLPresenceStateInfo = Parameters<(typeof InstancePresenceRecordType)['create']>[0]
/** @public */
export function getDefaultUserPresence(store: TLStore, user: TLPresenceUserInfo) {
const instance = store.get(TLINSTANCE_ID)
const pageState = store.get(InstancePageStateRecordType.createId(instance?.currentPageId))
const camera = store.get(CameraRecordType.createId(instance?.currentPageId))
const pointer = store.get(TLPOINTER_ID)
if (!pageState || !instance || !camera || !pointer) {
return null
}
return {
selectedShapeIds: pageState.selectedShapeIds,
brush: instance.brush,
scribbles: instance.scribbles,
userId: user.id,
userName: user.name ?? '',
followingUserId: instance.followingUserId,
camera: {
x: camera.x,
y: camera.y,
z: camera.z,
},
color: user.color ?? '#FF0000',
currentPageId: instance.currentPageId,
cursor: {
x: pointer.x,
y: pointer.y,
rotation: instance.cursor.rotation,
type: instance.cursor.type,
},
lastActivityTimestamp: pointer.lastActivityTimestamp,
screenBounds: instance.screenBounds,
chatMessage: instance.chatMessage,
meta: {},
} satisfies TLPresenceStateInfo
}