tldraw/state/coop/client-pusher.ts
2021-06-29 13:12:30 +01:00

123 lines
3 KiB
TypeScript

import Pusher from 'pusher-js'
import * as PusherTypes from 'pusher-js'
import state from 'state/state'
import { Shape } from 'types'
class RoomClient {
room: string
pusher: Pusher
channel: PusherTypes.PresenceChannel
lastCursorEventTime = 0
id: string
constructor() {
// Create pusher instance and bind events
this.pusher = new Pusher('5dc87c88b8684bda655a', {
cluster: 'eu',
authEndpoint: 'http://localhost:3000/api/pusher-auth',
})
this.pusher.connection.bind('connecting', () =>
state.send('RT_CHANGED_STATUS', { status: 'connecting' })
)
this.pusher.connection.bind('connected', () =>
state.send('RT_CHANGED_STATUS', { status: 'connected' })
)
this.pusher.connection.bind('unavailable', () =>
state.send('RT_CHANGED_STATUS', { status: 'unavailable' })
)
this.pusher.connection.bind('failed', () => {
state.send('RT_CHANGED_STATUS', { status: 'failed' })
})
this.pusher.connection.bind('disconnected', () => {
state.send('RT_CHANGED_STATUS', { status: 'disconnected' })
})
}
connect(roomId: string) {
this.room = 'presence-' + roomId
// Subscribe to channel
this.channel = this.pusher.subscribe(
this.room
) as PusherTypes.PresenceChannel
this.channel.bind('pusher:subscription_error', (err: string) => {
console.warn(err)
state.send('RT_CHANGED_STATUS', { status: 'subscription-error' })
})
this.channel.bind('pusher:subscription_succeeded', () => {
const me = this.channel.members.me
const userId = me.id
this.id = userId
state.send('RT_CHANGED_STATUS', { status: 'subscribed' })
})
this.channel.bind(
'created_shape',
(payload: { id: string; pageId: string; shape: Shape }) => {
if (payload.id === this.id) return
state.send('RT_CREATED_SHAPE', payload)
}
)
this.channel.bind(
'deleted_shape',
(payload: { id: string; pageId: string; shape: Shape }) => {
if (payload.id === this.id) return
state.send('RT_DELETED_SHAPE', payload)
}
)
this.channel.bind(
'edited_shape',
(payload: { id: string; pageId: string; change: Partial<Shape> }) => {
if (payload.id === this.id) return
state.send('RT_EDITED_SHAPE', payload)
}
)
this.channel.bind(
'client-moved-cursor',
(payload: { id: string; pageId: string; point: number[] }) => {
if (payload.id === this.id) return
state.send('RT_MOVED_CURSOR', payload)
}
)
}
disconnect() {
this.pusher.unsubscribe(this.room)
}
reconnect() {
this.pusher.subscribe(this.room)
}
moveCursor(pageId: string, point: number[]) {
if (!this.channel) return
const now = Date.now()
if (now - this.lastCursorEventTime > 200) {
this.lastCursorEventTime = now
this.channel?.trigger('client-moved-cursor', {
id: this.id,
pageId,
point,
})
}
}
}
export default new RoomClient()