From 92dd4c047ecf2101948b0626fe67831a1c7d2aeb Mon Sep 17 00:00:00 2001 From: Denis Krivosheev Date: Fri, 17 Nov 2017 11:23:59 +0300 Subject: [PATCH] WIP --- example/App.js | 24 ++++- example/data/new_messages.js | 169 +++++++++++++++++++++++++++++++++++ example/package.json | 1 + src/GiftedChat.js | 2 + src/MessageContainer.js | 21 ++++- 5 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 example/data/new_messages.js diff --git a/example/App.js b/example/App.js index 8eeafbb15..058cd0e62 100644 --- a/example/App.js +++ b/example/App.js @@ -9,6 +9,7 @@ import { import {GiftedChat, Actions, Bubble} from 'react-native-gifted-chat'; import CustomActions from './CustomActions'; import CustomView from './CustomView'; +import _ from 'lodash'; export default class Example extends React.Component { constructor(props) { @@ -27,6 +28,7 @@ export default class Example extends React.Component { this.renderBubble = this.renderBubble.bind(this); this.renderFooter = this.renderFooter.bind(this); this.onLoadEarlier = this.onLoadEarlier.bind(this); + this.onLoadNewer = this.onLoadNewer.bind(this); this._isAlright = null; } @@ -40,6 +42,10 @@ export default class Example extends React.Component { }); } + componentDidMount() { + this.onLoadNewer(); + } + componentWillUnmount() { this._isMounted = false; } @@ -55,7 +61,7 @@ export default class Example extends React.Component { if (this._isMounted === true) { this.setState((previousState) => { return { - messages: GiftedChat.prepend(previousState.messages, require('./data/old_messages.js')), + messages: require('./data/old_messages.js').concat(previousState.messages), loadEarlier: false, isLoadingEarlier: false, }; @@ -64,6 +70,19 @@ export default class Example extends React.Component { }, 1000); // simulating network } + onLoadNewer() { + setTimeout(() => { + if (this._isMounted) { + this.setState((previousState) => { + return { + messages: _.cloneDeep(previousState.messages).concat(require('./data/new_messages')()), + }; + }); + } + }, 1000); + } + + onSend(messages = []) { this.setState((previousState) => { return { @@ -80,7 +99,7 @@ export default class Example extends React.Component { if ((messages[0].image || messages[0].location) || !this._isAlright) { this.setState((previousState) => { return { - typingText: 'React Native is typing' + typingText: 'React Native is typing', }; }); } @@ -193,6 +212,7 @@ export default class Example extends React.Component { onSend={this.onSend} loadEarlier={this.state.loadEarlier} onLoadEarlier={this.onLoadEarlier} + onLoadNewer={this.onLoadNewer} isLoadingEarlier={this.state.isLoadingEarlier} user={{ diff --git a/example/data/new_messages.js b/example/data/new_messages.js new file mode 100644 index 000000000..6f7d60031 --- /dev/null +++ b/example/data/new_messages.js @@ -0,0 +1,169 @@ +module.exports = function () { + return [ + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + { + _id: Math.round(Math.random() * 1000000), + text: 'New message', + createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)), + user: { + _id: 1, + name: 'Developer', + }, + sent: true, + received: true, + // location: { + // latitude: 48.864601, + // longitude: 2.398704 + // }, + }, + ]; +} diff --git a/example/package.json b/example/package.json index a3a4533a9..780cb3a70 100644 --- a/example/package.json +++ b/example/package.json @@ -10,6 +10,7 @@ "sync": "rm -rf ./node_modules/react-native-gifted-chat; sane '/usr/bin/rsync -v -a --exclude .git --exclude example --exclude __tests__ --exclude node_modules ../ ./node_modules/react-native-gifted-chat/' .. --glob='{**/*.json,**/*.js}'" }, "dependencies": { + "lodash": "^4.17.4", "prop-types": "15.5.10", "react": "16.0.0-alpha.12", "react-native": "0.46.3", diff --git a/src/GiftedChat.js b/src/GiftedChat.js index b3ffc33fe..68a3d893a 100644 --- a/src/GiftedChat.js +++ b/src/GiftedChat.js @@ -553,6 +553,7 @@ GiftedChat.defaultProps = { }), loadEarlier: false, onLoadEarlier: () => {}, + onLoadNewer: () => {}, isLoadingEarlier: false, renderLoading: null, renderLoadEarlier: null, @@ -603,6 +604,7 @@ GiftedChat.propTypes = { isAnimated: PropTypes.bool, loadEarlier: PropTypes.bool, onLoadEarlier: PropTypes.func, + onLoadNewer: PropTypes.func, isLoadingEarlier: PropTypes.bool, renderLoading: PropTypes.func, renderLoadEarlier: PropTypes.func, diff --git a/src/MessageContainer.js b/src/MessageContainer.js index 7b5d2bee3..7321f8632 100644 --- a/src/MessageContainer.js +++ b/src/MessageContainer.js @@ -14,9 +14,11 @@ export default class MessageContainer extends React.Component { this.renderRow = this.renderRow.bind(this); this.renderFooter = this.renderFooter.bind(this); this.renderLoadEarlier = this.renderLoadEarlier.bind(this); + this.onScroll = this.onScroll.bind(this); this.state = { messages: this.prepareMessages(props.messages), + isLoadingNewer: false, }; } @@ -112,6 +114,17 @@ export default class MessageContainer extends React.Component { return ; } + async onScroll({nativeEvent}) { + const offset = nativeEvent.contentSize.height - nativeEvent.contentOffset.y; + const threshold = offset / nativeEvent.layoutMeasurement.height - 1; + if (!this.state.isLoadingNewer && threshold <= this.props.onTopReachedThreshold) { + await this.setState({isLoadingNewer: true}); + await this.props.onLoadNewer(); + await this.setState({isLoadingNewer: false}); + //console.log('!!!!!!!!!!!!!!', offset, threshold); + } + } + keyExtractor = (item, index) => item._id; render() { @@ -131,6 +144,8 @@ export default class MessageContainer extends React.Component { ListFooterComponent={this.renderLoadEarlier} onEndReached={this.props.onTopReached} onEndReachedThreshold={this.props.onTopReachedThreshold} + onScroll={this.onScroll} + scrollEventThrottle={500} /> ); @@ -142,8 +157,9 @@ MessageContainer.defaultProps = { user: {}, renderFooter: null, renderMessage: null, - onLoadEarlier: () => { - }, + onLoadEarlier: () => {}, + onLoadNewer: () => {}, + onTopReachedThreshold: 0.5, }; MessageContainer.propTypes = { @@ -152,6 +168,7 @@ MessageContainer.propTypes = { renderFooter: PropTypes.func, renderMessage: PropTypes.func, onLoadEarlier: PropTypes.func, + onLoadNewer: PropTypes.func, flatListProps: PropTypes.object, flatListKeyboardProps: PropTypes.object, onTopReached: PropTypes.func,