@pusher/chatkit
Version:
Pusher Chatkit client library for browsers and react native
94 lines (85 loc) • 2.45 kB
JavaScript
import { head, isEmpty } from 'ramda'
import { parseBasicMessage } from './parsers'
import { urlEncode } from './utils'
import { Message } from './message'
export class MessageSubscription {
constructor (options) {
this.roomId = options.roomId
this.hooks = options.hooks
this.messageLimit = options.messageLimit
this.userId = options.userId
this.instance = options.instance
this.userStore = options.userStore
this.roomStore = options.roomStore
this.typingIndicators = options.typingIndicators
this.messageBuffer = [] // { message, ready }
this.logger = options.logger
}
connect () {
return new Promise((resolve, reject) => {
this.sub = this.instance.subscribeResuming({
path: `/rooms/${this.roomId}?${urlEncode({
message_limit: this.messageLimit
})}`,
listeners: {
onOpen: resolve,
onError: reject,
onEvent: this.onEvent
}
})
})
}
cancel () {
try {
this.sub && this.sub.unsubscribe()
} catch (err) {
this.logger.debug('error when cancelling message subscription', err)
}
}
onEvent = ({ body }) => {
switch (body.event_name) {
case 'new_message':
this.onNewMessage(body.data)
break
case 'is_typing':
this.onIsTyping(body.data)
break
}
}
onNewMessage = data => {
const pending = {
message: new Message(
parseBasicMessage(data),
this.userStore,
this.roomStore
),
ready: false
}
this.messageBuffer.push(pending)
this.userStore.fetchMissingUsers([pending.message.senderId])
.catch(err => {
this.logger.error('error fetching missing user information:', err)
})
.then(() => {
pending.ready = true
this.flushBuffer()
})
}
flushBuffer = () => {
while (!isEmpty(this.messageBuffer) && head(this.messageBuffer).ready) {
const message = this.messageBuffer.shift().message
if (
this.hooks.rooms[this.roomId] &&
this.hooks.rooms[this.roomId].onNewMessage
) {
this.hooks.rooms[this.roomId].onNewMessage(message)
}
}
}
onIsTyping = ({ user_id: userId }) => {
if (userId !== this.userId) {
Promise.all([this.roomStore.get(this.roomId), this.userStore.get(userId)])
.then(([room, user]) => this.typingIndicators.onIsTyping(room, user))
}
}
}