ignite-boilerplate-andross-typescript
Version:
Customized version of ignite Andross With TypeScript Support.
278 lines (260 loc) • 7.57 kB
JavaScript
/* 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'
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
}
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.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,
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,
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
})
}