UNPKG

zl-react-native-gifted-chat

Version:

The most complete chat UI for React Native, based on 'react-native-gifted-chat'

179 lines (157 loc) 4.67 kB
import React from 'react'; import { ListView, View, } from 'react-native'; import shallowequal from 'shallowequal'; import InvertibleScrollView from 'react-native-invertible-scroll-view'; import md5 from 'md5'; import LoadEarlier from './LoadEarlier'; import Message from './Message'; export default class MessageContainer extends React.Component { constructor(props) { super(props); this.renderRow = this.renderRow.bind(this); this.renderFooter = this.renderFooter.bind(this); this.renderLoadEarlier = this.renderLoadEarlier.bind(this); this.renderScrollComponent = this.renderScrollComponent.bind(this); const dataSource = new ListView.DataSource({ rowHasChanged: (r1, r2) => { return r1.hash !== r2.hash; } }); const messagesData = this.prepareMessages(props.messages); this.state = { dataSource: dataSource.cloneWithRows(messagesData.blob, messagesData.keys) }; } prepareMessages(messages) { return { keys: messages.map(m => m._id), blob: messages.reduce((o, m, i) => { const previousMessage = messages[i + 1] || {}; const nextMessage = messages[i - 1] || {}; // add next and previous messages to hash to ensure updates const toHash = JSON.stringify(m) + previousMessage._id + nextMessage._id; o[m._id] = { ...m, previousMessage, nextMessage, hash: md5(toHash) }; return o; }, {}) }; } shouldComponentUpdate(nextProps, nextState) { if (!shallowequal(this.props, nextProps)) { return true; } if (!shallowequal(this.state, nextState)) { return true; } return false; } componentWillReceiveProps(nextProps) { if (this.props.messages === nextProps.messages) { return; } const messagesData = this.prepareMessages(nextProps.messages); this.setState({ dataSource: this.state.dataSource.cloneWithRows(messagesData.blob, messagesData.keys) }); } renderFooter() { if (this.props.renderFooter) { const footerProps = { ...this.props, }; return this.props.renderFooter(footerProps); } return null; } renderLoadEarlier() { if (this.props.loadEarlier === true) { const loadEarlierProps = { ...this.props, }; if (this.props.renderLoadEarlier) { return this.props.renderLoadEarlier(loadEarlierProps); } return ( <LoadEarlier {...loadEarlierProps}/> ); } return null; } scrollTo(options) { this._invertibleScrollViewRef.scrollTo(options); } renderRow(message, sectionId, rowId) { if (!message._id) { console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(message)); } if (!message.user) { console.warn('GiftedChat: `user` is missing for message', JSON.stringify(message)); message.user = {}; } const messageProps = { ...this.props, key: message._id, currentMessage: message, previousMessage: message.previousMessage, nextMessage: message.nextMessage, position: message.user._id === this.props.user._id ? 'right' : 'left', }; if (this.props.renderMessage) { return this.props.renderMessage(messageProps); } return <Message {...messageProps}/>; } renderScrollComponent(props) { const invertibleScrollViewProps = this.props.invertibleScrollViewProps; console.log('invert') return ( <InvertibleScrollView {...props} {...invertibleScrollViewProps} keyboardShouldPersistTaps={false} keyboardDismissMode={'on-drag'} ref={component => this._invertibleScrollViewRef = component} /> ); } render() { return ( <View ref='container' style={{flex:1}}> <ListView enableEmptySections={true} automaticallyAdjustContentInsets={false} initialListSize={20} pageSize={20} dataSource={this.state.dataSource} renderRow={this.renderRow} renderHeader={this.renderFooter} renderFooter={this.renderLoadEarlier} renderScrollComponent={this.renderScrollComponent} {...this.props.listViewProps} /> </View> ); } } MessageContainer.defaultProps = { messages: [], user: {}, renderFooter: null, renderMessage: null, onLoadEarlier: () => { }, }; MessageContainer.propTypes = { messages: React.PropTypes.array, user: React.PropTypes.object, renderFooter: React.PropTypes.func, renderMessage: React.PropTypes.func, onLoadEarlier: React.PropTypes.func, };