Last active
March 1, 2021 09:41
-
-
Save vishalnarkhede/5712c0922e12f927ad65053f9ce3fe25 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {useEffect, useState} from 'react'; | |
import { | |
SafeAreaView, | |
StyleSheet, | |
Text, | |
Touchable, | |
TouchableOpacity, | |
View, | |
} from 'react-native'; | |
import {FlatList} from 'react-native-bidirectional-infinite-scroll'; | |
import {MessageBubble} from './MessageBubble'; | |
import {queryMoreMessages} from './utils'; | |
// Counter to keep track of how many times `loadMoreRecentMessages` function has been called. | |
// We want to simulate a UX where user has scrolled till the most recent message available in | |
// chat. So for our example, we are going stop querying (and appending) new messages to the screen, | |
// once loadMoreRecentCounter is greater than 2. | |
// In real chat applications, you generally receive a flag from pagination api, which tells the app | |
// if user is at the most recent message in chat or not. | |
let loadMoreRecentCounter = 0; | |
const App = () => { | |
const [messages, setMessages] = useState(); | |
const [enableAutoscrollToTop, setEnableAutoscrollToTop] = useState(false); | |
useEffect(() => { | |
// When app is opened, we are going to render 50 messages on screen. | |
// Generally this is where you connect to chat server and query first batch of messages. | |
const initChat = async () => { | |
const initialMessages = await queryMoreMessages(50, 0); | |
setMessages(initialMessages); | |
}; | |
initChat(); | |
}, []); | |
// Add 10 more messages to end of the list. | |
// In real chat application, this is where you have your pagination logic. | |
const loadMoreOlderMessages = async () => { | |
const newMessages = await queryMoreMessages(10); | |
setMessages((m) => { | |
return m.concat(newMessages); | |
}); | |
}; | |
// Add 10 more messages to beginning of the list. | |
// In real chat application, this is where you have your pagination logic. | |
const loadMoreRecentMessages = async () => { | |
if (loadMoreRecentCounter > 2) { | |
// User is at the most recent message in chat. | |
!enableAutoscrollToTop && setEnableAutoscrollToTop(true); | |
return; | |
} | |
const newMessages = await queryMoreMessages(10); | |
setMessages((m) => { | |
return newMessages.concat(m); | |
}); | |
loadMoreRecentCounter += 1; | |
}; | |
/** | |
* Simulates a send message feature of Chat applications. It simply adds a randomly | |
* generated message at beginning of the list - it can either be a sent or received message. | |
*/ | |
const sendMessage = async () => { | |
const newMessages = await queryMoreMessages(1, 0); | |
setMessages((m) => { | |
return newMessages.concat(m); | |
}); | |
}; | |
if (!messages) { | |
// If the messages are not ready, lets not show anything. | |
// Generally you can render some kind of loading indicator in this case. | |
return null; | |
} | |
/** | |
* NOTE: | |
* | |
* - You can also control the scroll offset, at which `onEndReached` and `onStartReached` | |
* should be called, using props - onEndReachedThreshold and onStartReachedThrehols | |
* - We are using `inverted` FlatList, since thats a common UX for Chat applications. | |
*/ | |
return ( | |
<SafeAreaView style={styles.safeArea}> | |
<View style={styles.header}> | |
<Text style={styles.headerTitle}>Chat between two users</Text> | |
</View> | |
<FlatList | |
data={messages} | |
inverted | |
enableAutoscrollToTop={enableAutoscrollToTop} | |
onEndReached={loadMoreOlderMessages} | |
onStartReached={loadMoreRecentMessages} | |
renderItem={MessageBubble} | |
/> | |
<TouchableOpacity onPress={sendMessage} style={styles.sendMessageButton}> | |
<Text style={styles.sendButtonTitle}>Send message</Text> | |
</TouchableOpacity> | |
</SafeAreaView> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
header: { | |
alignItems: 'center', | |
paddingVertical: 10, | |
borderBottomColor: '#BEBEBE', | |
borderBottomWidth: 1, | |
}, | |
headerTitle: {fontSize: 20, fontWeight: 'bold'}, | |
safeArea: { | |
flex: 1, | |
}, | |
sendMessageButton: { | |
width: '100%', | |
padding: 20, | |
backgroundColor: '#FF4500', | |
alignItems: 'center', | |
}, | |
sendButtonTitle: { | |
color: 'white', | |
fontSize: 15, | |
fontWeight: 'bold', | |
}, | |
}); | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment