123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- // @flow
-
- import React from 'react';
- import { Text, View } from 'react-native';
-
- import { Avatar } from '../../../base/avatar';
- import { ColorSchemeRegistry } from '../../../base/color-scheme';
- import { translate } from '../../../base/i18n';
- import { Linkify } from '../../../base/react';
- import { connect } from '../../../base/redux';
- import { type StyleType } from '../../../base/styles';
-
- import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL } from '../../constants';
- import { replaceNonUnicodeEmojis } from '../../functions';
-
- import AbstractChatMessage, { type Props as AbstractProps } from '../AbstractChatMessage';
- import PrivateMessageButton from '../PrivateMessageButton';
-
- import styles from './styles';
-
- type Props = AbstractProps & {
-
- /**
- * The color-schemed stylesheet of the feature.
- */
- _styles: StyleType
- };
-
- /**
- * Renders a single chat message.
- */
- class ChatMessage extends AbstractChatMessage<Props> {
- /**
- * Implements {@code Component#render}.
- *
- * @inheritdoc
- */
- render() {
- const { _styles, message } = this.props;
- const localMessage = message.messageType === MESSAGE_TYPE_LOCAL;
- const { privateMessage } = message;
-
- // Style arrays that need to be updated in various scenarios, such as
- // error messages or others.
- const detailsWrapperStyle = [
- styles.detailsWrapper
- ];
- const messageBubbleStyle = [
- styles.messageBubble
- ];
-
- if (localMessage) {
- // This is a message sent by the local participant.
-
- // The wrapper needs to be aligned to the right.
- detailsWrapperStyle.push(styles.ownMessageDetailsWrapper);
-
- // 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);
- }
-
- return (
- <View style = { styles.messageWrapper } >
- { this._renderAvatar() }
- <View style = { detailsWrapperStyle }>
- <View style = { messageBubbleStyle }>
- <View style = { styles.textWrapper } >
- { this._renderDisplayName() }
- <Linkify linkStyle = { styles.chatLink }>
- { replaceNonUnicodeEmojis(this._getMessageText()) }
- </Linkify>
- { this._renderPrivateNotice() }
- </View>
- { this._renderPrivateReplyButton() }
- </View>
- { this._renderTimestamp() }
- </View>
- </View>
- );
- }
-
- _getFormattedTimestamp: () => string;
-
- _getMessageText: () => string;
-
- _getPrivateNoticeMessage: () => string;
-
- /**
- * 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.id }
- size = { styles.avatarWrapper.width } />
- }
- </View>
- );
- }
-
- /**
- * Renders the display name of the sender if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderDisplayName() {
- const { _styles, message, showDisplayName } = this.props;
-
- if (!showDisplayName) {
- return null;
- }
-
- return (
- <Text style = { _styles.displayName }>
- { message.displayName }
- </Text>
- );
- }
-
- /**
- * Renders the message privacy notice, if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderPrivateNotice() {
- const { _styles, message } = this.props;
-
- if (!message.privateMessage) {
- return null;
- }
-
- return (
- <Text style = { _styles.privateNotice }>
- { this._getPrivateNoticeMessage() }
- </Text>
- );
- }
-
- /**
- * Renders the private reply button, if necessary.
- *
- * @returns {React$Element<*> | null}
- */
- _renderPrivateReplyButton() {
- const { _styles, message } = this.props;
- const { messageType, privateMessage } = message;
-
- if (!privateMessage || messageType === MESSAGE_TYPE_LOCAL) {
- return null;
- }
-
- return (
- <View style = { _styles.replyContainer }>
- <PrivateMessageButton
- participantID = { message.id }
- 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 }>
- { this._getFormattedTimestamp() }
- </Text>
- );
- }
- }
-
- /**
- * Maps part of the redux state to the props of this component.
- *
- * @param {Object} state - The Redux state.
- * @returns {Props}
- */
- function _mapStateToProps(state) {
- return {
- _styles: ColorSchemeRegistry.get(state, 'Chat')
- };
- }
-
- export default translate(connect(_mapStateToProps)(ChatMessage));
|