2017-11-21 14:55:50 +00:00
import React from 'react' ;
import PropTypes from 'prop-types' ;
2018-01-09 17:12:55 +00:00
import { View , TouchableHighlight , Text , TouchableOpacity , Animated } from 'react-native' ;
2017-11-21 14:55:50 +00:00
import { connect } from 'react-redux' ;
2017-12-13 15:00:26 +00:00
import Icon from 'react-native-vector-icons/MaterialIcons' ;
2017-12-11 20:37:33 +00:00
import moment from 'moment' ;
2017-11-21 14:55:50 +00:00
2017-12-13 15:00:26 +00:00
import { actionsShow , errorActionsShow } from '../../actions/messages' ;
2017-12-02 13:19:58 +00:00
import Image from './Image' ;
2017-11-21 14:55:50 +00:00
import User from './User' ;
import Avatar from '../Avatar' ;
2017-12-02 13:19:58 +00:00
import Audio from './Audio' ;
import Video from './Video' ;
import Markdown from './Markdown' ;
import Url from './Url' ;
import Reply from './Reply' ;
2017-12-13 15:00:26 +00:00
import messageStatus from '../../constants/messagesStatus' ;
2018-01-09 17:12:55 +00:00
import styles from './styles' ;
const avatar = { marginRight : 10 } ;
const flex = { flexDirection : 'row' , flex : 1 } ;
2017-11-21 14:55:50 +00:00
@ connect ( state => ( {
message : state . messages . message ,
2017-11-24 20:44:52 +00:00
editing : state . messages . editing
2017-11-21 14:55:50 +00:00
} ) , dispatch => ( {
2017-12-13 15:00:26 +00:00
actionsShow : actionMessage => dispatch ( actionsShow ( actionMessage ) ) ,
errorActionsShow : actionMessage => dispatch ( errorActionsShow ( actionMessage ) )
2017-11-21 14:55:50 +00:00
} ) )
export default class Message extends React . Component {
static propTypes = {
item : PropTypes . object . isRequired ,
baseUrl : PropTypes . string . isRequired ,
Message _TimeFormat : PropTypes . string . isRequired ,
2017-11-24 20:44:52 +00:00
message : PropTypes . object . isRequired ,
2017-12-02 13:19:58 +00:00
user : PropTypes . object . isRequired ,
2017-11-24 20:44:52 +00:00
editing : PropTypes . bool ,
2017-12-13 15:00:26 +00:00
actionsShow : PropTypes . func ,
2018-01-09 17:12:55 +00:00
errorActionsShow : PropTypes . func ,
animate : PropTypes . bool
}
componentWillMount ( ) {
this . _visibility = new Animated . Value ( this . props . animate ? 0 : 1 ) ;
}
componentDidMount ( ) {
if ( this . props . animate ) {
Animated . timing ( this . _visibility , {
toValue : 1 ,
duration : 300
} ) . start ( ) ;
}
}
componentWillReceiveProps ( ) {
this . extraStyle = this . extraStyle || { } ;
if ( this . props . item . status === messageStatus . TEMP || this . props . item . status === messageStatus . ERROR ) {
this . extraStyle . opacity = 0.3 ;
}
}
shouldComponentUpdate ( nextProps ) {
return this . props . item . _updatedAt . toGMTString ( ) !== nextProps . item . _updatedAt . toGMTString ( ) || this . props . item . status !== nextProps . item . status ;
2017-11-21 14:55:50 +00:00
}
2017-11-24 20:44:52 +00:00
onLongPress ( ) {
const { item } = this . props ;
this . props . actionsShow ( JSON . parse ( JSON . stringify ( item ) ) ) ;
2017-11-21 14:55:50 +00:00
}
2017-12-13 15:00:26 +00:00
onErrorPress ( ) {
const { item } = this . props ;
this . props . errorActionsShow ( JSON . parse ( JSON . stringify ( item ) ) ) ;
}
2017-12-19 15:43:17 +00:00
getInfoMessage ( ) {
let message = '' ;
const messageType = this . props . item . t ;
if ( messageType === 'rm' ) {
message = 'Message removed' ;
} else if ( messageType === 'uj' ) {
message = 'Has joined the channel.' ;
} else if ( messageType === 'r' ) {
message = ` Room name changed to: ${ this . props . item . msg } by ${ this . props . item . u . username } ` ;
} else if ( messageType === 'message_pinned' ) {
message = 'Message pinned' ;
} else if ( messageType === 'ul' ) {
message = 'Has left the channel.' ;
} else if ( messageType === 'ru' ) {
message = ` User ${ this . props . item . msg } removed by ${ this . props . item . u . username } ` ;
} else if ( messageType === 'au' ) {
message = ` User ${ this . props . item . msg } added by ${ this . props . item . u . username } ` ;
} else if ( messageType === 'user-muted' ) {
message = ` User ${ this . props . item . msg } muted by ${ this . props . item . u . username } ` ;
} else if ( messageType === 'user-unmuted' ) {
message = ` User ${ this . props . item . msg } unmuted by ${ this . props . item . u . username } ` ;
}
return message ;
2017-12-02 13:19:58 +00:00
}
2017-12-19 15:43:17 +00:00
isInfoMessage ( ) {
return [ 'r' , 'au' , 'ru' , 'ul' , 'uj' , 'rm' , 'user-muted' , 'user-unmuted' , 'message_pinned' ] . includes ( this . props . item . t ) ;
}
isDeleted ( ) {
return this . props . item . t === 'rm' ;
2017-11-21 14:55:50 +00:00
}
2017-12-13 15:00:26 +00:00
hasError ( ) {
return this . props . item . status === messageStatus . ERROR ;
}
2017-11-21 14:55:50 +00:00
attachments ( ) {
2017-12-02 13:19:58 +00:00
if ( this . props . item . attachments . length === 0 ) {
return null ;
}
const file = this . props . item . attachments [ 0 ] ;
const { baseUrl , user } = this . props ;
if ( file . image _type ) {
return < Image file = { file } baseUrl = { baseUrl } user = { user } / > ;
} else if ( file . audio _type ) {
return < Audio file = { file } baseUrl = { baseUrl } user = { user } / > ;
} else if ( file . video _type ) {
return < Video file = { file } baseUrl = { baseUrl } user = { user } / > ;
}
return < Reply attachment = { file } timeFormat = { this . props . Message _TimeFormat } / > ;
2017-11-21 14:55:50 +00:00
}
renderMessageContent ( ) {
2017-12-19 15:43:17 +00:00
if ( this . isInfoMessage ( ) ) {
return < Text style = { styles . textInfo } > { this . getInfoMessage ( ) } < / T e x t > ;
2017-11-21 14:55:50 +00:00
}
2017-12-02 13:19:58 +00:00
return < Markdown msg = { this . props . item . msg } / > ;
}
2017-11-21 14:55:50 +00:00
2017-12-02 13:19:58 +00:00
renderUrl ( ) {
if ( this . props . item . urls . length === 0 ) {
return null ;
}
return this . props . item . urls . map ( url => (
< Url url = { url } key = { url . _id } / >
) ) ;
2017-11-21 14:55:50 +00:00
}
2017-12-13 15:00:26 +00:00
renderError = ( ) => {
if ( ! this . hasError ( ) ) {
return null ;
}
return (
< TouchableOpacity onPress = { ( ) => this . onErrorPress ( ) } >
< Icon name = 'error-outline' color = 'red' size = { 20 } style = { { padding : 10 , paddingRight : 12 , paddingLeft : 0 } } / >
< / T o u c h a b l e O p a c i t y >
) ;
}
2017-11-21 14:55:50 +00:00
render ( ) {
2017-11-24 20:44:52 +00:00
const {
2017-12-13 15:00:26 +00:00
item , message , editing , baseUrl
2017-11-24 20:44:52 +00:00
} = this . props ;
2017-11-21 14:55:50 +00:00
2018-01-09 17:12:55 +00:00
const marginLeft = this . _visibility . interpolate ( {
inputRange : [ 0 , 1 ] ,
outputRange : [ - 30 , 0 ]
} ) ;
const opacity = this . _visibility . interpolate ( {
inputRange : [ 0 , 1 ] ,
outputRange : [ 0 , 1 ]
} ) ;
2017-11-21 14:55:50 +00:00
const username = item . alias || item . u . username ;
2017-11-24 20:44:52 +00:00
const isEditing = message . _id === item . _id && editing ;
2017-11-21 14:55:50 +00:00
2017-12-11 20:37:33 +00:00
const accessibilityLabel = ` Message from ${ item . alias || item . u . username } at ${ moment ( item . ts ) . format ( this . props . Message _TimeFormat ) } , ${ this . props . item . msg } ` ;
2017-11-21 14:55:50 +00:00
return (
2017-12-13 15:00:26 +00:00
< TouchableHighlight
2017-11-24 20:44:52 +00:00
onLongPress = { ( ) => this . onLongPress ( ) }
2017-12-13 15:00:26 +00:00
disabled = { this . isDeleted ( ) || this . hasError ( ) }
underlayColor = '#FFFFFF'
activeOpacity = { 0.3 }
style = { [ styles . message , isEditing ? styles . editing : null ] }
2017-12-11 20:37:33 +00:00
accessibilityLabel = { accessibilityLabel }
2017-11-21 14:55:50 +00:00
>
2018-01-09 17:12:55 +00:00
< Animated . View style = { [ flex , { opacity , marginLeft } ] } >
2017-12-13 15:00:26 +00:00
{ this . renderError ( ) }
2018-01-09 17:12:55 +00:00
< View style = { [ this . extraStyle , flex ] } >
2017-12-13 15:00:26 +00:00
< Avatar
2018-01-09 17:12:55 +00:00
style = { avatar }
2017-12-13 15:00:26 +00:00
text = { item . avatar ? '' : username }
size = { 40 }
baseUrl = { baseUrl }
avatar = { item . avatar }
/ >
< View style = { [ styles . content ] } >
< User
onPress = { this . _onPress }
item = { item }
Message _TimeFormat = { this . props . Message _TimeFormat }
baseUrl = { baseUrl }
/ >
{ this . renderMessageContent ( ) }
{ this . attachments ( ) }
{ this . renderUrl ( ) }
< / V i e w >
< / V i e w >
2018-01-09 17:12:55 +00:00
< / A n i m a t e d . V i e w >
2017-12-13 15:00:26 +00:00
< / T o u c h a b l e H i g h l i g h t >
2017-11-21 14:55:50 +00:00
) ;
}
}