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 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // @flow
  2. import React from 'react';
  3. import { toArray } from 'react-emoji-render';
  4. import Linkify from 'react-linkify';
  5. import { translate } from '../../../base/i18n';
  6. import AbstractChatMessage, {
  7. type Props
  8. } from '../AbstractChatMessage';
  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 } = this.props;
  21. const messageToDisplay = message.messageType === 'error'
  22. ? this.props.t('chat.error', {
  23. error: message.error,
  24. originalText: message.message
  25. })
  26. : message.message;
  27. // replace links and smileys
  28. // Strophe already escapes special symbols on sending,
  29. // so we escape here only tags to avoid double &amp;
  30. const escMessage = messageToDisplay.replace(/</g, '&lt;')
  31. .replace(/>/g, '&gt;')
  32. .replace(/\n/g, '<br/>');
  33. const processedMessage = [];
  34. // content is an array of text and emoji components
  35. const content = toArray(escMessage, { className: 'smiley' });
  36. content.forEach(i => {
  37. if (typeof i === 'string') {
  38. processedMessage.push(
  39. <Linkify
  40. key = { i }
  41. properties = {{
  42. rel: 'noopener noreferrer',
  43. target: '_blank'
  44. }}>{ i }</Linkify>);
  45. } else {
  46. processedMessage.push(i);
  47. }
  48. });
  49. return (
  50. <div className = 'chatmessage-wrapper'>
  51. <div className = 'chatmessage'>
  52. { this.props.showDisplayName && this._renderDisplayName() }
  53. <div className = 'usermessage'>
  54. { processedMessage }
  55. </div>
  56. </div>
  57. { this.props.showTimestamp && this._renderTimestamp() }
  58. </div>
  59. );
  60. }
  61. _getFormattedTimestamp: () => string;
  62. /**
  63. * Renders the display name of the sender.
  64. *
  65. * @returns {React$Element<*>}
  66. */
  67. _renderDisplayName() {
  68. return (
  69. <div className = 'display-name'>
  70. { this.props.message.displayName }
  71. </div>
  72. );
  73. }
  74. /**
  75. * Renders the time at which the message was sent.
  76. *
  77. * @returns {React$Element<*>}
  78. */
  79. _renderTimestamp() {
  80. return (
  81. <div className = 'timestamp'>
  82. { this._getFormattedTimestamp() }
  83. </div>
  84. );
  85. }
  86. }
  87. export default translate(ChatMessage);