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.

functions.ts 4.2KB

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