react-native-lifetime-livechat
Version:
LiveChat implementation for LifeTime application
220 lines (193 loc) • 5.61 kB
JavaScript
/* eslint
no-console: 0,
no-param-reassign: 0,
no-use-before-define: ["error", { "variables": false }],
no-return-assign: 0,
react/no-string-refs: 0,
react/sort-comp: 0
*/
import PropTypes from 'prop-types';
import React from 'react';
import {FlatList, View, StyleSheet, TouchableOpacity, Text} from 'react-native';
import LoadEarlier from './LoadEarlier';
import LoadAfter from './LoadAfter';
import Message from './Message';
export default class MessageContainer extends React.PureComponent {
state = {
showScrollBottom: false,
};
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.renderFooter = this.renderFooter.bind(this);
this.renderLoadEarlier = this.renderLoadEarlier.bind(this);
this.renderHeaderWrapper = this.renderHeaderWrapper.bind(this);
}
handleOnScroll = (event) => {
if (event.nativeEvent.contentOffset.y > this.props.scrollToBottomOffset) {
this.setState({ showScrollBottom: true });
} else {
this.setState({ showScrollBottom: false });
}
};
renderFooter() {
const loadAfterProps = {
...this.props,
};
if (!this.props.loadAfter) return null;
return (
<View style={styles.headerWrapper}>
<LoadAfter key={Math.random()} {...loadAfterProps} />
</View>
);
}
renderLoadEarlier() {
if (this.props.loadEarlier === true) {
const loadEarlierProps = {
...this.props,
};
if (this.props.renderLoadEarlier) {
return this.props.renderLoadEarlier(loadEarlierProps);
}
return <LoadEarlier key={Math.random()} {...loadEarlierProps} />;
}
return null;
}
scrollTo(index) {
if (this.flatListRef) {
this.flatListRef.scrollToOffset({index: index});
}
}
scrollToOffset(options) {
if (this.flatListRef && options) {
this.flatListRef.scrollToOffset(options);
}
}
renderRow({ item, index }) {
if (!item._id && item._id !== 0) {
console.warn('GiftedChat: `_id` is missing for message', JSON.stringify(item));
}
if (!item.user) {
if (!item.system) {
console.warn('GiftedChat: `user` is missing for message', JSON.stringify(item));
}
item.user = {};
}
const { messages, ...restProps } = this.props;
const previousMessage = messages[index + 1] || {};
const nextMessage = messages[index - 1] || {};
const messageProps = {
...restProps,
key: item._id,
currentMessage: item,
previousMessage,
nextMessage,
position: item.user._id === this.props.user._id ? 'right' : 'left',
};
if (this.props.renderMessage) {
return this.props.renderMessage(messageProps);
}
return <Message {...messageProps} />;
}
renderHeaderWrapper() {
return <View style={styles.headerWrapper}>
{this.renderLoadEarlier()}
</View>;
}
scrollToBottom = () => {
if (this.props.onJumpBackClicked) {
this.props.onJumpBackClicked();
}
this.scrollTo({ offset: 0, animated: 'true' });
};
renderScrollToBottomWrapper() {
return (
<View style={styles.scrollToBottomStyle}>
<TouchableOpacity onPress={this.scrollToBottom} hitSlop={{ top: 5, left: 5, right: 5, bottom: 5 }}>
<Text>Jump back</Text>
</TouchableOpacity>
</View>
);
}
render() {
if (this.props.messages.length === 0) {
return <View style={styles.container} />;
}
return (
<View style={styles.container}>
{this.state.showScrollBottom && this.props.scrollToBottom ? this.renderScrollToBottomWrapper() : null}
<FlatList
ref={(ref) => (this.flatListRef = ref)}
keyExtractor={(item) => item._id}
enableEmptySections
automaticallyAdjustContentInsets={false}
inverted={this.props.inverted}
data={this.props.messages}
style={styles.listStyle}
onScroll={this.handleOnScroll}
contentContainerStyle={styles.contentContainerStyle}
renderItem={this.renderRow}
{...this.props.invertibleScrollViewProps}
ListFooterComponent={this.renderHeaderWrapper()}
ListHeaderComponent={this.renderFooter()}
{...this.props.listViewProps}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
contentContainerStyle: {
justifyContent: 'flex-end',
},
headerWrapper: {
flex: 1,
},
listStyle: {
flex: 1,
},
scrollToBottomStyle: {
opacity: 0.8,
position: 'absolute',
paddingHorizontal: 15,
paddingVertical: 8,
right: 10,
bottom: 30,
zIndex: 999,
height: 40,
//width: 40,
fontSize: 10,
borderRadius: 20,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
shadowColor: 'black',
shadowOpacity: 0.5,
shadowOffset: { width: 0, height: 0 },
shadowRadius: 1,
},
});
MessageContainer.defaultProps = {
messages: [],
user: {},
renderMessage: null,
onLoadEarlier: () => {},
inverted: true,
loadEarlier: false,
listViewProps: {},
invertibleScrollViewProps: {}, // TODO: support or not?
};
MessageContainer.propTypes = {
messages: PropTypes.arrayOf(PropTypes.object),
user: PropTypes.object,
renderMessage: PropTypes.func,
renderLoadEarlier: PropTypes.func,
onLoadEarlier: PropTypes.func,
listViewProps: PropTypes.object,
inverted: PropTypes.bool,
loadEarlier: PropTypes.bool,
invertibleScrollViewProps: PropTypes.object, // TODO: support or not?
};