123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- import React, { Component } from 'react';
- import { Text, View, ViewStyle } from 'react-native';
- import { connect } from 'react-redux';
-
- import { IReduxState } from '../../../app/types';
- import Avatar from '../../../base/avatar/components/Avatar';
- import { translate } from '../../../base/i18n/functions';
- import Linkify from '../../../base/react/components/native/Linkify';
- import { isGifMessage } from '../../../gifs/functions.native';
- import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL } from '../../constants';
- import {
- getCanReplyToMessage,
- getFormattedTimestamp,
- getMessageText,
- getPrivateNoticeMessage,
- replaceNonUnicodeEmojis
- } from '../../functions';
- import { IChatMessageProps } from '../../types';
-
- import GifMessage from './GifMessage';
- import PrivateMessageButton from './PrivateMessageButton';
- import styles from './styles';
-
-
- /**
- * Renders a single chat message.
- */
- class ChatMessage extends Component<IChatMessageProps> {
- /**
- * Implements {@code Component#render}.
- *
- * @inheritdoc
- */
- render() {
- const { message, knocking } = this.props;
- const localMessage = message.messageType === MESSAGE_TYPE_LOCAL;
- const { privateMessage, lobbyChat } = message;
-
- // Style arrays that need to be updated in various scenarios, such as
- // error messages or others.
- const detailsWrapperStyle: ViewStyle[] = [
- styles.detailsWrapper as ViewStyle
- ];
- const messageBubbleStyle: ViewStyle[] = [
- styles.messageBubble as ViewStyle
- ];
-
- if (localMessage) {
- // This is a message sent by the local participant.
-
- // The wrapper needs to be aligned to the right.
- detailsWrapperStyle.push(styles.ownMessageDetailsWrapper as ViewStyle);
-
- // The bubble needs some additional styling
- messageBubbleStyle.push(styles.localMessageBubble);
- } else if (message.messageType === MESSAGE_TYPE_ERROR) {
- // This is a system message.
-
- // The bubble needs some additional styling
- messageBubbleStyle.push(styles.systemMessageBubble);
- } else {
- // This is a remote message sent by a remote participant.
-
- // The bubble needs some additional styling
- messageBubbleStyle.push(styles.remoteMessageBubble);
- }
-
- if (privateMessage) {
- messageBubbleStyle.push(styles.privateMessageBubble);
- }
-
- if (lobbyChat && !knocking) {
- messageBubbleStyle.push(styles.lobbyMessageBubble);
- }
-
- const messageText = replaceNonUnicodeEmojis(getMessageText(this.props.message));
-
- return (
- <View style = { styles.messageWrapper as ViewStyle } >
- { this._renderAvatar() }
- <View style = { detailsWrapperStyle }>
- <View style = { messageBubbleStyle }>
- <View style = { styles.textWrapper as ViewStyle } >
- { this._renderDisplayName() }
- { isGifMessage(messageText)
- ? <GifMessage message = { messageText } />
- : (
- <Linkify
- linkStyle = { styles.chatLink }
- style = { styles.chatMessage }>
- { messageText }
- </Linkify>
- )}
- { this._renderPrivateNotice() }
- </View>
- { this._renderPrivateReplyButton() }
- </View>
- { this._renderTimestamp() }
- </View>
- </View>
- );
- }
-
- /**
- * Renders the avatar of the sender.
- *
- * @returns {React$Element<*>}
- */
- _renderAvatar() {
- const { message } = this.props;
-
- return (
- <View style = { styles.avatarWrapper }>
- { this.props.showAvatar && <Avatar
- displayName = { message.displayName }
- participantId = { message.participantId }
- size = { styles.avatarWrapper.width } />
- }
- </View>
- );
- }
-
- /**
- * Renders the display name of the sender if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderDisplayName() {
- const { message, showDisplayName } = this.props;
-
- if (!showDisplayName) {
- return null;
- }
-
- return (
- <Text style = { styles.senderDisplayName }>
- { message.displayName }
- </Text>
- );
- }
-
- /**
- * Renders the message privacy notice, if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderPrivateNotice() {
- const { message, knocking } = this.props;
-
- if (!(message.privateMessage || (message.lobbyChat && !knocking))) {
- return null;
- }
-
- return (
- <Text style = { message.lobbyChat ? styles.lobbyMsgNotice : styles.privateNotice }>
- { getPrivateNoticeMessage(this.props.message) }
- </Text>
- );
- }
-
- /**
- * Renders the private reply button, if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderPrivateReplyButton() {
- const { message, canReply } = this.props;
- const { lobbyChat } = message;
-
- if (!canReply) {
- return null;
- }
-
- return (
- <View style = { styles.replyContainer as ViewStyle }>
- <PrivateMessageButton
- isLobbyMessage = { lobbyChat }
- participantID = { message.participantId }
- reply = { true }
- showLabel = { false }
- toggledStyles = { styles.replyStyles } />
- </View>
- );
- }
-
- /**
- * Renders the time at which the message was sent, if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderTimestamp() {
- if (!this.props.showTimestamp) {
- return null;
- }
-
- return (
- <Text style = { styles.timeText }>
- { getFormattedTimestamp(this.props.message) }
- </Text>
- );
- }
- }
-
- /**
- * Maps part of the redux state to the props of this component.
- *
- * @param {Object} state - The Redux state.
- * @returns {IProps}
- */
- function _mapStateToProps(state: IReduxState, { message }: IChatMessageProps) {
- return {
- canReply: getCanReplyToMessage(state, message),
- knocking: state['features/lobby'].knocking
- };
- }
-
- export default translate(connect(_mapStateToProps)(ChatMessage));
|