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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // @flow
  2. import React from 'react';
  3. import { translate } from '../../../base/i18n';
  4. import Message from '../../../base/react/components/web/Message';
  5. import { connect } from '../../../base/redux';
  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, knocking } = this.props;
  21. return (
  22. <div
  23. className = 'chatmessage-wrapper'
  24. id = { this.props.message.messageId }
  25. tabIndex = { -1 }>
  26. <div
  27. className = { `chatmessage ${message.privateMessage ? 'privatemessage' : ''} ${
  28. message.lobbyChat && !knocking ? 'lobbymessage' : ''}` }>
  29. <div className = 'replywrapper'>
  30. <div className = 'messagecontent'>
  31. { this.props.showDisplayName && this._renderDisplayName() }
  32. <div className = 'usermessage'>
  33. <span className = 'sr-only'>
  34. { this.props.message.displayName === this.props.message.recipient
  35. ? t('chat.messageAccessibleTitleMe')
  36. : t('chat.messageAccessibleTitle',
  37. { user: this.props.message.displayName }) }
  38. </span>
  39. <Message text = { this._getMessageText() } />
  40. </div>
  41. { (message.privateMessage || (message.lobbyChat && !knocking))
  42. && this._renderPrivateNotice() }
  43. </div>
  44. { (message.privateMessage || (message.lobbyChat && !knocking))
  45. && message.messageType !== MESSAGE_TYPE_LOCAL
  46. && (
  47. <div
  48. className = { `messageactions ${
  49. message.lobbyChat ? 'lobbychatmessageactions' : ''}` }>
  50. <PrivateMessageButton
  51. isLobbyMessage = { message.lobbyChat }
  52. participantID = { message.id }
  53. reply = { true }
  54. showLabel = { false } />
  55. </div>
  56. ) }
  57. </div>
  58. </div>
  59. { this.props.showTimestamp && this._renderTimestamp() }
  60. </div>
  61. );
  62. }
  63. _getFormattedTimestamp: () => string;
  64. _getMessageText: () => string;
  65. _getPrivateNoticeMessage: () => string;
  66. /**
  67. * Renders the display name of the sender.
  68. *
  69. * @returns {React$Element<*>}
  70. */
  71. _renderDisplayName() {
  72. return (
  73. <div
  74. aria-hidden = { true }
  75. className = 'display-name'>
  76. { this.props.message.displayName }
  77. </div>
  78. );
  79. }
  80. /**
  81. * Renders the message privacy notice.
  82. *
  83. * @returns {React$Element<*>}
  84. */
  85. _renderPrivateNotice() {
  86. return (
  87. <div className = 'privatemessagenotice'>
  88. { this._getPrivateNoticeMessage() }
  89. </div>
  90. );
  91. }
  92. /**
  93. * Renders the time at which the message was sent.
  94. *
  95. * @returns {React$Element<*>}
  96. */
  97. _renderTimestamp() {
  98. return (
  99. <div className = 'timestamp'>
  100. { this._getFormattedTimestamp() }
  101. </div>
  102. );
  103. }
  104. }
  105. /**
  106. * Maps part of the Redux store to the props of this component.
  107. *
  108. * @param {Object} state - The Redux state.
  109. * @returns {Props}
  110. */
  111. function _mapStateToProps(state: Object): $Shape<Props> {
  112. const { knocking } = state['features/lobby'];
  113. return {
  114. knocking
  115. };
  116. }
  117. export default translate(connect(_mapStateToProps)(ChatMessage));