Skip to content

Instantly share code, notes, and snippets.

@patrick-samy
Created June 6, 2021 15:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patrick-samy/823556da81fc837c339f75ef725ae6d6 to your computer and use it in GitHub Desktop.
Save patrick-samy/823556da81fc837c339f75ef725ae6d6 to your computer and use it in GitHub Desktop.
Sendbird issue with SyncManager
import SendBird from 'sendbird'
import '@react-native-firebase/messaging'
import Firebase from '@react-native-firebase/app'
import { fetchQuery, graphql } from 'react-relay'
import SendBirdSyncManager from 'sendbird-syncmanager'
import { CometChat } from '@cometchat-pro/react-native-chat'
import AsyncStorage from '@react-native-async-storage/async-storage'
import React, { Component, createContext, PureComponent } from 'react'
import Environment from './environment'
export const ChatContext = createContext()
export class ChatProvider extends PureComponent {
constructor() {
super()
this.state = {
login: this.login,
logout: this.logout,
send: this.send,
getMessages: this.getMessages,
}
this.collections = {}
this.messages = {}
this.init()
}
async init() {
try {
this.sendbird = new SendBird({ appId: 'XXXXXXXXXX' })
console.log('Chat initialization completed successfully')
} catch (e) {
console.log('Chat initialization failed with error:', e)
}
}
login = async () => {
try {
const viewer = await new Promise((resolve, reject) => {
let data = {}
fetchQuery(Environment, graphql`
query chatQuery {
viewer {
...
}
}
`).subscribe({
next: (d) => { data = d },
complete: () => resolve(data),
error: (error) => reject(),
})
}).then((res) => res?.viewer)
if (!viewer?.chat?.token) {
return
}
const options = new SendBirdSyncManager.Options()
options.messageResendPolicy = 'automatic'
SendBirdSyncManager.sendBird = this.sendbird
SendBirdSyncManager.useReactNative(AsyncStorage)
await SendBirdSyncManager.setup(viewer.id)
SendBird.setLogLevel(SendBird.LogLevel.VERBOSE)
const handler = new this.sendbird.ConnectionHandler()
handler.onReconnectStarted = () => { alert('pauseSync'); SendBirdSyncManager.pauseSync() }
handler.onReconnectSucceeded = () => { alert('pauseSync'); SendBirdSyncManager.resumeSync() }
handler.onReconnectFailed = () => {alert('reconnectFailed');}
this.sendbird.addConnectionHandler(viewer.id, handler)
this.sendbird.connect(viewer.id, viewer.chat.token, async (user, error) => {
if (error) {
alert(error)
console.log('Chat login failed with error: ', error)
return
}
console.log('Login Successful:', user)
this.setState({ user })
await this.fetchConversations()
await this.registerPushToken()
})
} catch (e) {
console.log('Chat login failed with error:', e)
}
}
fetchConversations = async () => {
var listQuery = this.sendbird.GroupChannel.createMyGroupChannelListQuery()
listQuery.includeEmpty = true
listQuery.includeMetaData = true
listQuery.memberStateFilter = 'joined_only'
const collection = new SendBirdSyncManager.ChannelCollection(listQuery)
const handler = new SendBirdSyncManager.ChannelCollection.CollectionHandler()
handler.onChannelEvent = (action, conversations) => {
switch (action) {
case 'insert':
console.log("Conversations list received:", conversations)
this.setState({ conversations })
conversations.map(async c => await this.fetchMessages(c))
break
case 'update':
console.log("Conversations list received:", conversations)
this.setState({ conversations })
break
case 'move':
console.log("Conversations list received:", conversations)
this.setState({ conversations })
break
}
}
collection.setCollectionHandler(handler)
collection.fetch()
}
fetchMessages = async (channel) => {
const collection = new SendBirdSyncManager.MessageCollection(channel)
const handler = new SendBirdSyncManager.MessageCollection.CollectionHandler()
collection.limit = 1000
handler.onSucceededMessageEvent = (messages, action) => {
console.log('onSucceededMessageEvent', messages, action)
switch (action) {
case 'insert':
// Here: only called with initial cached messages, doesn't update with new messages
alert(messages.length)
console.log("Messages inserted:", messages)
this.messages[channel.url] = messages
break
case 'update':
console.log("Messages updated:", messages)
this.messages[channel.url] = messages
break
case 'remove':
console.log("Messages removed:", messages)
this.messages[channel.url] = messages
break
}
}
handler.onPendingMessageEvent = (messages, action, reason) => {
console.log('onPendingMessageEvent', messages, action, reason)
switch (action) {
case 'insert':
console.log("Pending messages inserted:", messages)
this.messages[channel.url] = messages
break
case 'update':
console.log("Pending messages updated:", messages)
this.messages[channel.url] = messages
break
case 'remove':
console.log("Pending messages removed:", messages)
this.messages[channel.url] = messages
break
}
}
SendBirdSyncManager.loggerLevel = 98765
collection.setCollectionHandler(handler)
channel.markAsRead()
collection.fetchSucceededMessages('prev', err => {
collection.fetchSucceededMessages('next', err => {
collection.fetchFailedMessages(err => {})
})
})
this.collections[channel.url] = collection
this.messages[channel.url] = []
}
getMessages = (channel) => {
return this.messages[channel.url]
}
send = (channel, message) => {
const collection = this.collections[channel.url]
if (!collection) {
return
}
const params = new this.sendbird.UserMessageParams()
params.message = message
const pendingMessage = channel.sendUserMessage(params, (m, error) => {
collection.handleSendMessageResponse(error, m)
})
collection.appendMessage(pendingMessage)
}
logout = async () => {
try {
this.sendbird.disconnect()
} catch (e) {
console.log(e)
}
}
render() {
const { children } = this.props
return <ChatContext.Provider value={this.state}>{children}</ChatContext.Provider>
}
}
export const withChatHOC = (Component) => (props) => (
<ChatContext.Consumer>{(state) => <Component {...props} chat={state} />}</ChatContext.Consumer>
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment