dappros/ethora

View on GitHub
client-reactnative/src/components/Chat/MessageBody.tsx

Summary

Maintainability
A
3 hrs
Test Coverage
/*
Copyright 2019-2022 (c) Dappros Ltd, registered in England & Wales, registration number 11455432. All rights reserved.
You may not use this file except in compliance with the License.
You may obtain a copy of the License at https://github.com/dappros/ethora/blob/main/LICENSE.
Note: linked open-source libraries and components may be subject to their own licenses.
*/

import PropTypes from 'prop-types';
import React from 'react';
import {View, ViewPropTypes, StyleSheet} from 'react-native';

import {Avatar, Day, utils, SystemMessage} from 'react-native-gifted-chat';
import {textStyles} from '../../../docs/config';
import Bubble from './MessageBubble';

const {isSameUser, isSameDay} = utils;
export default class Message extends React.Component {
  shouldComponentUpdate(nextProps) {
    const next = nextProps.currentMessage;
    const current = this.props.currentMessage;

    const nextPropsPreviousMessage = nextProps.previousMessage;
    if (next.tokenAmount !== current.tokenAmount) return true;

    if (next.numberOfReplies !== current.numberOfReplies) return true;

    if (next.text !== current.text) return true;

    return false;
  }
  getInnerComponentProps() {
    const {containerStyle, ...props} = this.props;
    return {
      ...props,
      isSameUser,
      isSameDay,
      containerStyle,
    };
  }

  renderDay() {
    if (this.props.currentMessage.createdAt) {
      const dayProps = this.getInnerComponentProps();
      if (this.props.renderDay) {
        return this.props.renderDay(dayProps);
      }
      return <Day {...dayProps} />;
    }
    return null;
  }

  renderBubble() {
    const {containerStyle, ...props} = this.props;
    if (this.props.renderBubble) {
      return this.props.renderBubble(props);
    }
    // @ts-ignore
    return (
      <Bubble usernameStyle={{fontFamily: textStyles.regularFont}} {...props} />
    );
  }

  renderAvatar() {
    const {containerStyle, ...props} = this.props;
    return (
      <View accessibilityLabel="User photo (tap to view profile)">
        <Avatar {...props} />
      </View>
    );
  }

  renderSystemMessage() {
    const {containerStyle, ...props} = this.props;
    if (this.props.renderSystemMessage) {
      return this.props.renderSystemMessage(props);
    }
    return <SystemMessage {...props} textStyle={{textAlign: 'center'}} />;
  }

  render() {
    const {currentMessage, nextMessage, position, containerStyle} = this.props;
    if (currentMessage) {
      const sameUser = isSameUser(currentMessage, nextMessage);
      return (
        <View accessibilityLabel="Message (long tap to interact)">
          {this.renderDay()}
          {currentMessage.system ? (
            this.renderSystemMessage()
          ) : (
            <View
              style={[
                styles[position].container,
                {marginBottom: sameUser ? 2 : 10},
                !this.props.inverted && {marginBottom: 2},
                containerStyle && containerStyle[position],
              ]}>
              {this.props.position === 'left' ? this.renderAvatar() : null}
              {this.renderBubble()}
              {this.props.position === 'right' ? this.renderAvatar() : null}
            </View>
          )}
        </View>
      );
    }
    return null;
  }
}

const styles = {
  left: StyleSheet.create({
    container: {
      flexDirection: 'row',
      alignItems: 'flex-end',
      justifyContent: 'flex-start',
      marginLeft: 8,
      marginRight: 0,
      fontFamily: textStyles.regularFont,
    },
  }),
  right: StyleSheet.create({
    container: {
      flexDirection: 'row',
      alignItems: 'flex-end',
      justifyContent: 'flex-end',
      marginLeft: 0,
      marginRight: 8,
      fontFamily: textStyles.regularFont,
    },
  }),
};

Message.defaultProps = {
  renderAvatar: undefined,
  renderBubble: null,
  renderDay: null,
  renderSystemMessage: null,
  position: 'left',
  currentMessage: {},
  nextMessage: {},
  previousMessage: {},
  user: {},
  containerStyle: {},
  showUserAvatar: false,
  inverted: true,
  shouldUpdateMessage: undefined,
};

Message.propTypes = {
  renderAvatar: PropTypes.func,
  renderBubble: PropTypes.func,
  renderDay: PropTypes.func,
  currentMessage: PropTypes.object,
  nextMessage: PropTypes.object,
  previousMessage: PropTypes.object,
  user: PropTypes.object,
  containerStyle: PropTypes.shape({
    left: ViewPropTypes.style,
    right: ViewPropTypes.style,
  }),
};