UNPKG

react-native-gifted-chat-video-support

Version:

The most complete chat UI for React Native , now support send video thanks to react-native-video-player

295 lines (274 loc) 7.86 kB
/* eslint no-use-before-define: ["error", { "variables": false }] */ import PropTypes from 'prop-types'; import React from 'react'; import { Text, Clipboard, StyleSheet, TouchableWithoutFeedback, View, ViewPropTypes } from 'react-native'; import MessageText from './MessageText'; import MessageImage from './MessageImage'; import Time from './Time'; import Color from './Color'; import { isSameUser, isSameDay } from './utils'; import MessageVideo from './MessageVideo'; export default class Bubble extends React.PureComponent { constructor(props) { super(props); this.onLongPress = this.onLongPress.bind(this); } onLongPress() { if (this.props.onLongPress) { this.props.onLongPress(this.context, this.props.currentMessage); } else if (this.props.currentMessage.text) { const options = ['Copy Text', 'Cancel']; const cancelButtonIndex = options.length - 1; this.context.actionSheet().showActionSheetWithOptions( { options, cancelButtonIndex, }, (buttonIndex) => { switch (buttonIndex) { case 0: Clipboard.setString(this.props.currentMessage.text); break; default: break; } }, ); } } handleBubbleToNext() { if ( isSameUser(this.props.currentMessage, this.props.nextMessage) && isSameDay(this.props.currentMessage, this.props.nextMessage) ) { return StyleSheet.flatten([ styles[this.props.position].containerToNext, this.props.containerToNextStyle[this.props.position], ]); } return null; } handleBubbleToPrevious() { if ( isSameUser(this.props.currentMessage, this.props.previousMessage) && isSameDay(this.props.currentMessage, this.props.previousMessage) ) { return StyleSheet.flatten([ styles[this.props.position].containerToPrevious, this.props.containerToPreviousStyle[this.props.position], ]); } return null; } renderMessageText() { if (this.props.currentMessage.text) { const { containerStyle, wrapperStyle, ...messageTextProps } = this.props; if (this.props.renderMessageText) { return this.props.renderMessageText(messageTextProps); } return <MessageText {...messageTextProps} />; } return null; } renderMessageImage() { if (this.props.currentMessage.image) { const { containerStyle, wrapperStyle, ...messageImageProps } = this.props; if (this.props.renderMessageImage) { return this.props.renderMessageImage(messageImageProps); } return <MessageImage {...messageImageProps} />; } return null; } renderMessageVideo() { if (this.props.currentMessage.video) { const { containerStyle, wrapperStyle, ...messageVideoProps } = this.props; if (this.props.renderMessageVideo) { return this.props.renderMessageVideo(messageVideoProps); } return <MessageVideo {...messageVideoProps} />; } return null; } renderTicks() { const { currentMessage } = this.props; if (this.props.renderTicks) { return this.props.renderTicks(currentMessage); } if (currentMessage.user._id !== this.props.user._id) { return null; } if (currentMessage.sent || currentMessage.received) { return ( <View style={styles.tickView}> {currentMessage.sent && <Text style={[styles.tick, this.props.tickStyle]}>✓</Text>} {currentMessage.received && <Text style={[styles.tick, this.props.tickStyle]}>✓</Text>} </View> ); } return null; } renderTime() { if (this.props.currentMessage.createdAt) { const { containerStyle, wrapperStyle, ...timeProps } = this.props; if (this.props.renderTime) { return this.props.renderTime(timeProps); } return <Time {...timeProps} />; } return null; } renderCustomView() { if (this.props.renderCustomView) { return this.props.renderCustomView(this.props); } return null; } render() { return ( <View style={[styles[this.props.position].container, this.props.containerStyle[this.props.position]]}> <View style={[ styles[this.props.position].wrapper, this.props.wrapperStyle[this.props.position], this.handleBubbleToNext(), this.handleBubbleToPrevious(), ]} > <TouchableWithoutFeedback onLongPress={this.onLongPress} accessibilityTraits="text" {...this.props.touchableProps} > <View> {this.renderCustomView()} {this.renderMessageImage()} {this.renderMessageVideo()} {this.renderMessageText()} <View style={[styles.bottom, this.props.bottomContainerStyle[this.props.position]]}> {this.renderTime()} {this.renderTicks()} </View> </View> </TouchableWithoutFeedback> </View> </View> ); } } const styles = { left: StyleSheet.create({ container: { flex: 1, alignItems: 'flex-start', }, wrapper: { borderRadius: 15, backgroundColor: Color.leftBubbleBackground, marginRight: 60, minHeight: 20, justifyContent: 'flex-end', }, containerToNext: { borderBottomLeftRadius: 3, }, containerToPrevious: { borderTopLeftRadius: 3, }, }), right: StyleSheet.create({ container: { flex: 1, alignItems: 'flex-end', }, wrapper: { borderRadius: 15, backgroundColor: Color.defaultBlue, marginLeft: 60, minHeight: 20, justifyContent: 'flex-end', }, containerToNext: { borderBottomRightRadius: 3, }, containerToPrevious: { borderTopRightRadius: 3, }, }), bottom: { flexDirection: 'row', justifyContent: 'flex-end', }, tick: { fontSize: 10, backgroundColor: Color.backgroundTransparent, color: Color.white, }, tickView: { flexDirection: 'row', marginRight: 10, }, }; Bubble.contextTypes = { actionSheet: PropTypes.func, }; Bubble.defaultProps = { touchableProps: {}, onLongPress: null, renderMessageImage: null, renderMessageVideo: null, renderMessageText: null, renderCustomView: null, renderTicks: null, renderTime: null, position: 'left', currentMessage: { text: null, createdAt: null, image: null, }, nextMessage: {}, previousMessage: {}, containerStyle: {}, wrapperStyle: {}, bottomContainerStyle: {}, tickStyle: {}, containerToNextStyle: {}, containerToPreviousStyle: {}, }; Bubble.propTypes = { user: PropTypes.object.isRequired, touchableProps: PropTypes.object, onLongPress: PropTypes.func, renderMessageImage: PropTypes.func, renderMessageVideo: PropTypes.func, renderMessageText: PropTypes.func, renderCustomView: PropTypes.func, renderTime: PropTypes.func, renderTicks: PropTypes.func, position: PropTypes.oneOf(['left', 'right']), currentMessage: PropTypes.object, nextMessage: PropTypes.object, previousMessage: PropTypes.object, containerStyle: PropTypes.shape({ left: ViewPropTypes.style, right: ViewPropTypes.style, }), wrapperStyle: PropTypes.shape({ left: ViewPropTypes.style, right: ViewPropTypes.style, }), bottomContainerStyle: PropTypes.shape({ left: ViewPropTypes.style, right: ViewPropTypes.style, }), tickStyle: Text.propTypes.style, containerToNextStyle: PropTypes.shape({ left: ViewPropTypes.style, right: ViewPropTypes.style, }), containerToPreviousStyle: PropTypes.shape({ left: ViewPropTypes.style, right: ViewPropTypes.style, }), };