Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

functions.ts 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // @ts-expect-error
  2. import aliases from 'react-emoji-render/data/aliases';
  3. // eslint-disable-next-line lines-around-comment
  4. // @ts-expect-error
  5. import emojiAsciiAliases from 'react-emoji-render/data/asciiAliases';
  6. import { IReduxState } from '../app/types';
  7. import { getLocalizedDateFormatter } from '../base/i18n/dateUtil';
  8. import i18next from '../base/i18n/i18next';
  9. import { escapeRegexp } from '../base/util/helpers';
  10. import { MESSAGE_TYPE_ERROR, MESSAGE_TYPE_LOCAL, TIMESTAMP_FORMAT } from './constants';
  11. import { IMessage } from './types';
  12. /**
  13. * An ASCII emoticon regexp array to find and replace old-style ASCII
  14. * emoticons (such as :O) with the new Unicode representation, so that
  15. * devices and browsers that support them can render these natively
  16. * without a 3rd party component.
  17. *
  18. * NOTE: this is currently only used on mobile, but it can be used
  19. * on web too once we drop support for browsers that don't support
  20. * unicode emoji rendering.
  21. */
  22. const ASCII_EMOTICON_REGEXP_ARRAY: Array<[RegExp, string]> = [];
  23. /**
  24. * An emoji regexp array to find and replace alias emoticons
  25. * (such as :smiley:) with the new Unicode representation, so that
  26. * devices and browsers that support them can render these natively
  27. * without a 3rd party component.
  28. *
  29. * NOTE: this is currently only used on mobile, but it can be used
  30. * on web too once we drop support for browsers that don't support
  31. * unicode emoji rendering.
  32. */
  33. const SLACK_EMOJI_REGEXP_ARRAY: Array<[RegExp, string]> = [];
  34. (function() {
  35. for (const [ key, value ] of Object.entries(aliases)) {
  36. // Add ASCII emoticons
  37. const asciiEmoticons = emojiAsciiAliases[key];
  38. if (asciiEmoticons) {
  39. const asciiEscapedValues = asciiEmoticons.map((v: string) => escapeRegexp(v));
  40. const asciiRegexp = `(${asciiEscapedValues.join('|')})`;
  41. // Escape urls
  42. const formattedAsciiRegexp = key === 'confused'
  43. ? `(?=(${asciiRegexp}))(:(?!//).)`
  44. : asciiRegexp;
  45. ASCII_EMOTICON_REGEXP_ARRAY.push([ new RegExp(formattedAsciiRegexp, 'g'), value as string ]);
  46. }
  47. // Add slack-type emojis
  48. const emojiRegexp = `\\B(${escapeRegexp(`:${key}:`)})\\B`;
  49. SLACK_EMOJI_REGEXP_ARRAY.push([ new RegExp(emojiRegexp, 'g'), value as string ]);
  50. }
  51. })();
  52. /**
  53. * Replaces ASCII and other non-unicode emoticons with unicode emojis to let the emojis be rendered
  54. * by the platform native renderer.
  55. *
  56. * @param {string} message - The message to parse and replace.
  57. * @returns {string}
  58. */
  59. export function replaceNonUnicodeEmojis(message: string) {
  60. let replacedMessage = message;
  61. for (const [ regexp, replaceValue ] of SLACK_EMOJI_REGEXP_ARRAY) {
  62. replacedMessage = replacedMessage.replace(regexp, replaceValue);
  63. }
  64. for (const [ regexp, replaceValue ] of ASCII_EMOTICON_REGEXP_ARRAY) {
  65. replacedMessage = replacedMessage.replace(regexp, replaceValue);
  66. }
  67. return replacedMessage;
  68. }
  69. /**
  70. * Selector for calculating the number of unread chat messages.
  71. *
  72. * @param {IReduxState} state - The redux state.
  73. * @returns {number} The number of unread messages.
  74. */
  75. export function getUnreadCount(state: IReduxState) {
  76. const { lastReadMessage, messages } = state['features/chat'];
  77. const messagesCount = messages.length;
  78. if (!messagesCount) {
  79. return 0;
  80. }
  81. let reactionMessages = 0;
  82. let lastReadIndex;
  83. if (navigator.product === 'ReactNative') {
  84. // React native stores the messages in a reversed order.
  85. lastReadIndex = messages.indexOf(<IMessage>lastReadMessage);
  86. for (let i = 0; i < lastReadIndex; i++) {
  87. if (messages[i].isReaction) {
  88. reactionMessages++;
  89. }
  90. }
  91. return lastReadIndex - reactionMessages;
  92. }
  93. lastReadIndex = messages.lastIndexOf(<IMessage>lastReadMessage);
  94. for (let i = lastReadIndex + 1; i < messagesCount; i++) {
  95. if (messages[i].isReaction) {
  96. reactionMessages++;
  97. }
  98. }
  99. return messagesCount - (lastReadIndex + 1) - reactionMessages;
  100. }
  101. /**
  102. * Get whether the chat smileys are disabled or not.
  103. *
  104. * @param {IReduxState} state - The redux state.
  105. * @returns {boolean} The disabled flag.
  106. */
  107. export function areSmileysDisabled(state: IReduxState) {
  108. const disableChatSmileys = state['features/base/config']?.disableChatSmileys === true;
  109. return disableChatSmileys;
  110. }
  111. /**
  112. * Returns the timestamp to display for the message.
  113. *
  114. * @param {IMessage} message - The message from which to get the timestamp.
  115. * @returns {string}
  116. */
  117. export function getFormattedTimestamp(message: IMessage) {
  118. return getLocalizedDateFormatter(new Date(message.timestamp))
  119. .format(TIMESTAMP_FORMAT);
  120. }
  121. /**
  122. * Generates the message text to be rendered in the component.
  123. *
  124. * @param {IMessage} message - The message from which to get the text.
  125. * @returns {string}
  126. */
  127. export function getMessageText(message: IMessage) {
  128. return message.messageType === MESSAGE_TYPE_ERROR
  129. ? i18next.t('chat.error', {
  130. error: message.message
  131. })
  132. : message.message;
  133. }
  134. /**
  135. * Returns the message that is displayed as a notice for private messages.
  136. *
  137. * @param {IMessage} message - The message to be checked.
  138. * @returns {string}
  139. */
  140. export function getPrivateNoticeMessage(message: IMessage) {
  141. return i18next.t('chat.privateNotice', {
  142. recipient: message.messageType === MESSAGE_TYPE_LOCAL ? message.recipient : i18next.t('chat.you')
  143. });
  144. }