Skip to content

Instantly share code, notes, and snippets.

@dereknelson
Last active June 18, 2019 22:31
Show Gist options
  • Save dereknelson/2226951d7badf38c259a817b1d984950 to your computer and use it in GitHub Desktop.
Save dereknelson/2226951d7badf38c259a817b1d984950 to your computer and use it in GitHub Desktop.
sendbird mounting
var sb = null;
export default class Chat extends Component {
constructor(props) {
super(props);
sb = SendBird.getInstance();
this.state = {
channel: props.channel, channelUrl: props.channelUrl, name: props.name, messageQuery: '', channel: '', name: '', messages: props.channel.messageList || [],
};
}
componentDidMount() {
AppState.addEventListener('change', this.handleAppStateChange);
this.getChannel();
if (this.state.messages == null && this.textInput) this.textInput.focus()
else if (this.state.messages.length < 5 && this.textInput) this.textInput.focus()
}
getChannel = () => {
if (sb == null) return setTimeout(() => {
this.getChannel()
}, 1000)
const channel = sb.GroupChannel.getChannel(this.state.channelUrl, (channel, error) => {
if (error) {
setTimeout(() => {
return this.getChannel()
}, 1000)
} else {
this.handleMounting(channel, error)
}
})
}
handleMounting = (channel, error) => {
channel.markAsRead();
var messageQuery = channel.createPreviousMessageListQuery()
messageQuery.load(20, true, (messageList, error) => {
channel.messageList = messageList
this.setState({ messages: messageList, channel, error, messageQuery, fetchedOld: true, loading: false, fetched: true, })
})
if (!this.state.hasRendered) {
this.setState({ hasRendered: true })
this._getChannelMessage(false)
if (this.state.channel.channelType == 'group') {
this.state.channel.markAsRead();
}
}
// channel handler
var ChannelHandler = new sb.ChannelHandler();
ChannelHandler.onMessageReceived = (channel, message) => {
if (channel.url == this.state.channel.url) {
var messages = [message];
this.setState({
messages: messages.concat(this.state.messages)
});
this.state.lastMessage = message;
if (this.state.channel.channelType == 'group') {
this.state.channel.markAsRead();
}
}
}
sb.addChannelHandler('ChatView', ChannelHandler);
var ConnectionHandler = new sb.ConnectionHandler();
ConnectionHandler.onReconnectSucceeded = function () {
this._getChannelMessage(true);
this.state.channel.refresh();
}
}
render() {
return (
<KeyboardAvoidingView style={styles.container} behavior="padding" >
<View style={[styles.chatContainer, { transform: [{ scaleY: -1 }] }]}>
<FlatList
enableEmptySections={true}
onEndReached={() => this._getChannelMessage(false)}
onEndReachedThreshold={.5}
ListFooterComponent={() =>
this.state.messageQuery.isLoading ?
<ActivityIndicator size="large" animating={true} style={{ transform: [{ scaleY: -1 }] }} />
: null
}
refreshing={this.state.messageQuery.isLoading}
data={this.state.messages}
removeClippedSubviews={true}
initialNumToRender={15}
ListEmptyComponent={this.loading}
keyExtractor={(item, index) => item.messageId}
renderItem={this.renderItem}
/>
</View>
<View style={styles.inputContainer} >
<this.image />
<View style={{ flexDirection: 'row', }} >
<TouchableOpacity style={styles.photoButton} hitSlop={{ top: 5, bottom: 5, left: 10, right: 5 }} onPress={this._onPhoto}>
<Text style={{ fontSize: 20 }} > + </Text>
</TouchableOpacity>
<TextInput
style={styles.textInput}
placeholder={'Message'}
ref={ref => this.textInput = ref}
multiline={true}
onChangeText={this._onChangeText}
value={this.state.text}
blurOnSubmit={false}
/>
<TouchableOpacity style={styles.sendButton} onPress={this._onSend} disabled={this.state.disabled}>
<Text>Send</Text>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
)
}
renderItem = ({ item, index }) => {
/* * * * *
* *
* NOTE *
* *
/* * * * *
The entire flatlist has an inverse y-axis, effectively inverting the flatlist without also inverting refresh control, so some of the above/below comparisons have seemingly reversed logic */
const { messages } = this.state
if (messages[index] == null) {
return
}
let aboveIndex = index + 1
let belowIndex = index - 1
if (belowIndex == -1) belowIndex = index
if (aboveIndex >= this.state.messages.length) aboveIndex = index
if (messages[index]._sender == null) messages[index]._sender = { userId: '' }
if (messages[aboveIndex]._sender == null) messages[aboveIndex]._sender = { userId: '' }
if (messages[belowIndex]._sender == null) messages[belowIndex]._sender = { userId: '' }
const isYou = item._sender.userId == this.props.user.info.id
let changesSidesAbove = messages[aboveIndex]._sender.userId != messages[index]._sender.userId
let changesSidesBelow = messages[belowIndex]._sender.userId != messages[index]._sender.userId
let thisTime = moment(messages[index].createdAt)
let aboveTime = moment(messages[aboveIndex].createdAt)
let aboveDifference = thisTime.diff(aboveTime, 'h')
let belowTime = moment(messages[belowIndex].createdAt)
let belowDifference = belowTime.diff(thisTime, 'h')
const difference = { aboveDifference, belowDifference, thisTime, }
let changed = false
if (aboveDifference > 1) {
changesSidesAbove = true
changed = true
}
const borderRadius = item.messageType == 'file' ? 15 : 25
let borderRadii = { borderBottomLeftRadius: isYou ? borderRadius : 0, borderTopLeftRadius: isYou ? borderRadius : changesSidesAbove ? borderRadius - 5 : 0, borderBottomRightRadius: isYou ? 0 : borderRadius, borderTopRightRadius: isYou ? changesSidesAbove ? borderRadius - 5 : 0 : borderRadius }
if (changed) changesSidesAbove = false
let displayTime = (changesSidesBelow && aboveDifference < 1) || (index == 0 && aboveDifference < 1) || belowDifference > 1
let displayImage = false
if (changesSidesBelow) displayImage = true
else if (aboveDifference > 1 && (changesSidesBelow || belowDifference > 1)) displayImage = true
else if (belowDifference > 1) displayImage = true
else if (index == 0) displayImage = true
return (
<Message item={item} index={index} isYou={isYou} changesSidesAbove={changesSidesAbove} difference={difference} users={this.state.users} changesSidesBelow={changesSidesBelow} borderRadii={borderRadii}
displayTime={displayTime} displayImage={displayImage} navigation={this.props.navigation}
imageModalVisible={this.state.imageModalVisible} showImage={this.showImage} dismissImage={this.dismissImage} />
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment