You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ChatMessage.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // @flow
  2. import React from 'react';
  3. import { toArray } from 'react-emoji-render';
  4. import { translate } from '../../../base/i18n';
  5. import { Linkify } from '../../../base/react';
  6. import { MESSAGE_TYPE_LOCAL } from '../../constants';
  7. import AbstractChatMessage, { type Props } from '../AbstractChatMessage';
  8. import PrivateMessageButton from './PrivateMessageButton';
  9. /**
  10. * Renders a single chat message.
  11. */
  12. class ChatMessage extends AbstractChatMessage<Props> {
  13. /**
  14. * Implements React's {@link Component#render()}.
  15. *
  16. * @inheritdoc
  17. * @returns {ReactElement}
  18. */
  19. render() {
  20. const { message, t } = this.props;
  21. const processedMessage = [];
  22. const txt = this._getMessageText();
  23. // Tokenize the text in order to avoid emoji substitution for URLs.
  24. const tokens = txt.split(' ');
  25. // Content is an array of text and emoji components
  26. const content = [];
  27. for (const token of tokens) {
  28. if (token.includes('://')) {
  29. // It contains a link, bypass the emojification.
  30. content.push(token);
  31. } else {
  32. content.push(...toArray(token, { className: 'smiley' }));
  33. }
  34. content.push(' ');
  35. }
  36. content.forEach(i => {
  37. if (typeof i === 'string' && i !== ' ') {
  38. processedMessage.push(<Linkify key = { i }>{ i }</Linkify>);
  39. } else {
  40. processedMessage.push(i);
  41. }
  42. });
  43. return (
  44. <div
  45. className = 'chatmessage-wrapper'
  46. tabIndex = { -1 }>
  47. <div className = { `chatmessage ${message.privateMessage ? 'privatemessage' : ''}` }>
  48. <div className = 'replywrapper'>
  49. <div className = 'messagecontent'>
  50. { this.props.showDisplayName && this._renderDisplayName() }
  51. <div className = 'usermessage'>
  52. <span className = 'sr-only'>
  53. { this.props.message.displayName === this.props.message.recipient
  54. ? t('chat.messageAccessibleTitleMe')
  55. : t('chat.messageAccessibleTitle',
  56. { user: this.props.message.displayName }) }
  57. </span>
  58. { processedMessage }
  59. </div>
  60. { message.privateMessage && this._renderPrivateNotice() }
  61. </div>
  62. { message.privateMessage && message.messageType !== MESSAGE_TYPE_LOCAL
  63. && (
  64. <div className = 'messageactions'>
  65. <PrivateMessageButton
  66. participantID = { message.id }
  67. reply = { true }
  68. showLabel = { false } />
  69. </div>
  70. ) }
  71. </div>
  72. </div>
  73. { this.props.showTimestamp && this._renderTimestamp() }
  74. </div>
  75. );
  76. }
  77. _getFormattedTimestamp: () => string;
  78. _getMessageText: () => string;
  79. _getPrivateNoticeMessage: () => string;
  80. /**
  81. * Renders the display name of the sender.
  82. *
  83. * @returns {React$Element<*>}
  84. */
  85. _renderDisplayName() {
  86. return (
  87. <div
  88. aria-hidden = { true }
  89. className = 'display-name'>
  90. { this.props.message.displayName }
  91. </div>
  92. );
  93. }
  94. /**
  95. * Renders the message privacy notice.
  96. *
  97. * @returns {React$Element<*>}
  98. */
  99. _renderPrivateNotice() {
  100. return (
  101. <div className = 'privatemessagenotice'>
  102. { this._getPrivateNoticeMessage() }
  103. </div>
  104. );
  105. }
  106. /**
  107. * Renders the time at which the message was sent.
  108. *
  109. * @returns {React$Element<*>}
  110. */
  111. _renderTimestamp() {
  112. return (
  113. <div className = 'timestamp'>
  114. { this._getFormattedTimestamp() }
  115. </div>
  116. );
  117. }
  118. }
  119. export default translate(ChatMessage);