stream-chat-react 12.9.0 → 12.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/dist/components/Attachment/Attachment.js +2 -1
  2. package/dist/components/Attachment/AttachmentContainer.d.ts +1 -1
  3. package/dist/components/Attachment/AttachmentContainer.js +2 -2
  4. package/dist/components/Attachment/Card.js +3 -3
  5. package/dist/components/Attachment/VoiceRecording.d.ts +1 -1
  6. package/dist/components/Attachment/VoiceRecording.js +2 -2
  7. package/dist/components/Attachment/attachment-sizing.js +2 -1
  8. package/dist/components/Attachment/components/FileSizeIndicator.d.ts +1 -1
  9. package/dist/components/Attachment/components/FileSizeIndicator.js +1 -1
  10. package/dist/components/Attachment/components/WaveProgressBar.js +1 -1
  11. package/dist/components/Attachment/hooks/useAudioController.d.ts +1 -1
  12. package/dist/components/Attachment/hooks/useAudioController.js +4 -2
  13. package/dist/components/Attachment/utils.d.ts +1 -1
  14. package/dist/components/Attachment/utils.js +12 -3
  15. package/dist/components/AutoCompleteTextarea/List.js +3 -2
  16. package/dist/components/AutoCompleteTextarea/Textarea.js +3 -7
  17. package/dist/components/AutoCompleteTextarea/utils.js +3 -7
  18. package/dist/components/Avatar/ChannelAvatar.js +1 -1
  19. package/dist/components/Channel/Channel.d.ts +1 -1
  20. package/dist/components/Channel/Channel.js +30 -14
  21. package/dist/components/Channel/channelState.d.ts +1 -3
  22. package/dist/components/Channel/channelState.js +10 -4
  23. package/dist/components/Channel/hooks/useCreateChannelStateContext.js +5 -3
  24. package/dist/components/Channel/hooks/useIsMounted.d.ts +1 -1
  25. package/dist/components/Channel/hooks/useMentionsHandlers.js +5 -2
  26. package/dist/components/Channel/utils.js +2 -1
  27. package/dist/components/ChannelHeader/ChannelHeader.js +1 -1
  28. package/dist/components/ChannelList/ChannelList.js +13 -8
  29. package/dist/components/ChannelList/hooks/useChannelListShape.d.ts +2 -2
  30. package/dist/components/ChannelList/hooks/useChannelListShape.js +46 -19
  31. package/dist/components/ChannelList/hooks/useChannelUpdatedListener.js +2 -1
  32. package/dist/components/ChannelList/hooks/useMessageNewListener.js +3 -1
  33. package/dist/components/ChannelList/hooks/useMobileNavigation.d.ts +1 -1
  34. package/dist/components/ChannelList/hooks/usePaginatedChannels.js +5 -3
  35. package/dist/components/ChannelList/hooks/useSelectedChannelState.js +1 -1
  36. package/dist/components/ChannelPreview/ChannelPreview.js +2 -2
  37. package/dist/components/ChannelPreview/ChannelPreviewMessenger.js +1 -1
  38. package/dist/components/ChannelPreview/icons.js +0 -1
  39. package/dist/components/ChannelPreview/utils.js +3 -3
  40. package/dist/components/ChannelSearch/ChannelSearch.js +5 -3
  41. package/dist/components/ChannelSearch/SearchBar.d.ts +1 -1
  42. package/dist/components/ChannelSearch/SearchInput.d.ts +1 -1
  43. package/dist/components/ChannelSearch/SearchResults.js +1 -1
  44. package/dist/components/ChannelSearch/hooks/useChannelSearch.d.ts +4 -2
  45. package/dist/components/ChannelSearch/hooks/useChannelSearch.js +61 -36
  46. package/dist/components/ChannelSearch/index.d.ts +1 -1
  47. package/dist/components/Chat/hooks/useChat.js +4 -2
  48. package/dist/components/Chat/hooks/useCreateChatClient.js +3 -1
  49. package/dist/components/ChatAutoComplete/ChatAutoComplete.js +1 -1
  50. package/dist/components/ChatView/ChatView.js +0 -1
  51. package/dist/components/Dialog/PromptDialog.d.ts +1 -1
  52. package/dist/components/Dialog/PromptDialog.js +1 -1
  53. package/dist/components/EventComponent/EventComponent.js +1 -1
  54. package/dist/components/Gallery/BaseImage.d.ts +1 -3
  55. package/dist/components/Gallery/Gallery.js +10 -2
  56. package/dist/components/Gallery/Image.js +1 -1
  57. package/dist/components/Gallery/ModalGallery.js +4 -4
  58. package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +9 -6
  59. package/dist/components/InfiniteScrollPaginator/InfiniteScrollPaginator.js +1 -1
  60. package/dist/components/LoadMore/LoadMorePaginator.js +1 -1
  61. package/dist/components/MML/MML.js +1 -0
  62. package/dist/components/MediaRecorder/transcode/wav.js +6 -3
  63. package/dist/components/Message/FixedHeightMessage.js +6 -8
  64. package/dist/components/Message/Message.js +2 -1
  65. package/dist/components/Message/MessageEditedTimestamp.js +1 -1
  66. package/dist/components/Message/MessageSimple.js +2 -5
  67. package/dist/components/Message/MessageStatus.js +1 -1
  68. package/dist/components/Message/MessageText.js +7 -7
  69. package/dist/components/Message/QuotedMessage.js +2 -2
  70. package/dist/components/Message/Timestamp.js +9 -1
  71. package/dist/components/Message/hooks/useActionHandler.js +1 -1
  72. package/dist/components/Message/hooks/useFlagHandler.js +2 -1
  73. package/dist/components/Message/hooks/useMarkUnreadHandler.js +2 -1
  74. package/dist/components/Message/hooks/useMessageTextStreaming.d.ts +1 -1
  75. package/dist/components/Message/hooks/useMessageTextStreaming.js +1 -1
  76. package/dist/components/Message/hooks/useMuteHandler.js +7 -4
  77. package/dist/components/Message/hooks/usePinHandler.js +1 -1
  78. package/dist/components/Message/hooks/useReactionHandler.js +10 -5
  79. package/dist/components/Message/hooks/useRetryHandler.js +1 -1
  80. package/dist/components/Message/hooks/useUserRole.js +1 -1
  81. package/dist/components/Message/renderText/renderText.js +2 -2
  82. package/dist/components/Message/utils.js +3 -3
  83. package/dist/components/MessageActions/MessageActionsBox.js +7 -3
  84. package/dist/components/MessageActions/hooks/useMessageActionsBoxPopper.d.ts +1 -1
  85. package/dist/components/MessageInput/AttachmentPreviewList/AttachmentPreviewList.js +1 -1
  86. package/dist/components/MessageInput/AttachmentPreviewList/FileAttachmentPreview.js +4 -2
  87. package/dist/components/MessageInput/AttachmentPreviewList/UnsupportedAttachmentPreview.js +4 -2
  88. package/dist/components/MessageInput/AttachmentSelector.js +1 -1
  89. package/dist/components/MessageInput/DefaultTriggerProvider.js +1 -1
  90. package/dist/components/MessageInput/DropzoneProvider.js +1 -1
  91. package/dist/components/MessageInput/MessageInput.js +1 -1
  92. package/dist/components/MessageInput/MessageInputFlat.js +4 -3
  93. package/dist/components/MessageInput/QuotedMessagePreview.js +1 -1
  94. package/dist/components/MessageInput/hooks/useAttachments.js +12 -4
  95. package/dist/components/MessageInput/hooks/useLinkPreviews.js +3 -1
  96. package/dist/components/MessageInput/hooks/useMessageInputState.js +4 -3
  97. package/dist/components/MessageInput/hooks/useMessageInputText.d.ts +1 -1
  98. package/dist/components/MessageInput/hooks/useMessageInputText.js +5 -3
  99. package/dist/components/MessageInput/hooks/useSubmitHandler.js +5 -3
  100. package/dist/components/MessageInput/hooks/useTimeElapsed.js +1 -1
  101. package/dist/components/MessageInput/hooks/useUserTrigger.js +2 -2
  102. package/dist/components/MessageInput/hooks/utils.js +6 -2
  103. package/dist/components/MessageList/ConnectionStatus.js +1 -1
  104. package/dist/components/MessageList/MessageList.js +5 -6
  105. package/dist/components/MessageList/MessageListNotifications.js +3 -1
  106. package/dist/components/MessageList/VirtualizedMessageList.d.ts +1 -1
  107. package/dist/components/MessageList/VirtualizedMessageList.js +19 -12
  108. package/dist/components/MessageList/VirtualizedMessageListComponents.js +2 -2
  109. package/dist/components/MessageList/hooks/MessageList/useMessageListElements.js +1 -3
  110. package/dist/components/MessageList/hooks/MessageList/useMessageListScrollManager.js +3 -2
  111. package/dist/components/MessageList/hooks/MessageList/useScrollLocationLogic.js +3 -2
  112. package/dist/components/MessageList/hooks/MessageList/useUnreadMessagesNotification.js +6 -2
  113. package/dist/components/MessageList/hooks/VirtualizedMessageList/useMessageSetKey.js +1 -1
  114. package/dist/components/MessageList/hooks/VirtualizedMessageList/useNewMessageNotification.d.ts +1 -1
  115. package/dist/components/MessageList/hooks/VirtualizedMessageList/usePrependMessagesCount.js +4 -3
  116. package/dist/components/MessageList/hooks/VirtualizedMessageList/useScrollToBottomOnNewMessage.js +1 -1
  117. package/dist/components/MessageList/hooks/VirtualizedMessageList/useUnreadMessagesNotificationVirtualized.js +7 -3
  118. package/dist/components/MessageList/hooks/useMarkRead.d.ts +2 -4
  119. package/dist/components/MessageList/hooks/useMarkRead.js +14 -16
  120. package/dist/components/MessageList/utils.js +28 -11
  121. package/dist/components/Modal/Modal.d.ts +1 -1
  122. package/dist/components/Modal/Modal.js +1 -1
  123. package/dist/components/Modal/ModalHeader.js +1 -1
  124. package/dist/components/Poll/Poll.js +1 -1
  125. package/dist/components/Poll/PollActions/PollActions.js +6 -4
  126. package/dist/components/Poll/PollActions/PollAnswerList.js +1 -1
  127. package/dist/components/Poll/PollActions/PollResults/PollOptionVotesList.js +1 -1
  128. package/dist/components/Poll/PollActions/PollResults/PollOptionWithLatestVotes.js +4 -2
  129. package/dist/components/Poll/PollActions/PollResults/PollResults.js +2 -1
  130. package/dist/components/Poll/PollContent.js +1 -1
  131. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.d.ts +1 -1
  132. package/dist/components/Poll/PollCreationDialog/OptionFieldSet.js +11 -4
  133. package/dist/components/Poll/PollCreationDialog/PollCreationDialog.js +13 -4
  134. package/dist/components/Poll/PollCreationDialog/PollCreationDialogControls.js +6 -3
  135. package/dist/components/Poll/PollOptionList.js +1 -1
  136. package/dist/components/Poll/PollOptionSelector.js +12 -5
  137. package/dist/components/Poll/hooks/useManagePollVotesRealtime.js +9 -4
  138. package/dist/components/Poll/hooks/usePollAnswerPagination.js +8 -2
  139. package/dist/components/Poll/hooks/usePollOptionVotesPagination.js +8 -2
  140. package/dist/components/ReactFileUtilities/FileIcon/mimeTypes.d.ts +1 -1
  141. package/dist/components/ReactFileUtilities/ImageDropzone.js +3 -1
  142. package/dist/components/ReactFileUtilities/UploadButton.js +1 -1
  143. package/dist/components/ReactFileUtilities/utils.js +3 -1
  144. package/dist/components/Reactions/ReactionSelector.js +3 -1
  145. package/dist/components/Reactions/ReactionSelectorWithButton.js +1 -1
  146. package/dist/components/Reactions/ReactionsList.d.ts +2 -2
  147. package/dist/components/Reactions/ReactionsList.js +7 -4
  148. package/dist/components/Reactions/ReactionsListModal.d.ts +1 -2
  149. package/dist/components/Reactions/ReactionsListModal.js +1 -1
  150. package/dist/components/Reactions/SpriteImage.js +6 -2
  151. package/dist/components/Reactions/hooks/useFetchReactions.js +1 -1
  152. package/dist/components/Reactions/hooks/useProcessReactions.js +1 -1
  153. package/dist/components/Reactions/index.d.ts +1 -0
  154. package/dist/components/Reactions/index.js +1 -0
  155. package/dist/components/Reactions/reactionOptions.js +20 -5
  156. package/dist/components/Thread/Thread.js +4 -3
  157. package/dist/components/Threads/ThreadContext.d.ts +1 -1
  158. package/dist/components/Threads/ThreadContext.js +1 -1
  159. package/dist/components/Threads/ThreadList/ThreadList.js +1 -1
  160. package/dist/components/Threads/ThreadList/ThreadListItem.d.ts +1 -1
  161. package/dist/components/Threads/ThreadList/ThreadListItem.js +1 -1
  162. package/dist/components/Threads/ThreadList/ThreadListItemUI.js +5 -3
  163. package/dist/components/Threads/icons.js +0 -1
  164. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  165. package/dist/components/Tooltip/Tooltip.js +1 -1
  166. package/dist/context/ComponentContext.d.ts +3 -1
  167. package/dist/context/ComponentContext.js +1 -1
  168. package/dist/context/DialogManagerContext.d.ts +1 -1
  169. package/dist/context/DialogManagerContext.js +1 -1
  170. package/dist/context/MessageBounceContext.js +2 -2
  171. package/dist/context/MessageContext.js +1 -1
  172. package/dist/context/VirtualizedMessageListContext.d.ts +13 -0
  173. package/dist/context/VirtualizedMessageListContext.js +7 -0
  174. package/dist/context/WithComponents.js +1 -1
  175. package/dist/css/v2/index.css +2 -2
  176. package/dist/css/v2/index.layout.css +2 -2
  177. package/dist/experimental/MessageActions/MessageActions.js +0 -1
  178. package/dist/experimental/MessageActions/defaults.js +31 -7
  179. package/dist/experimental/index.browser.cjs +103 -37
  180. package/dist/experimental/index.browser.cjs.map +2 -2
  181. package/dist/experimental/index.node.cjs +103 -37
  182. package/dist/experimental/index.node.cjs.map +2 -2
  183. package/dist/i18n/Streami18n.js +11 -2
  184. package/dist/i18n/utils.js +14 -1
  185. package/dist/index.browser.cjs +2329 -1145
  186. package/dist/index.browser.cjs.map +4 -4
  187. package/dist/index.node.cjs +2594 -1164
  188. package/dist/index.node.cjs.map +4 -4
  189. package/dist/plugins/Emojis/EmojiPicker.js +0 -1
  190. package/dist/plugins/Emojis/index.browser.cjs +3 -1
  191. package/dist/plugins/Emojis/index.browser.cjs.map +2 -2
  192. package/dist/plugins/Emojis/index.node.cjs +3 -1
  193. package/dist/plugins/Emojis/index.node.cjs.map +2 -2
  194. package/dist/plugins/encoders/mp3.browser.cjs +7 -4
  195. package/dist/plugins/encoders/mp3.browser.cjs.map +2 -2
  196. package/dist/plugins/encoders/mp3.node.cjs +7 -4
  197. package/dist/plugins/encoders/mp3.node.cjs.map +2 -2
  198. package/dist/scss/v2/ChannelSearch/ChannelSearch-layout.scss +1 -0
  199. package/dist/scss/v2/Message/Message-layout.scss +12 -5
  200. package/dist/scss/v2/Poll/Poll-layout.scss +1 -1
  201. package/dist/scss/v2/Search/Search-layout.scss +148 -0
  202. package/dist/scss/v2/Search/Search-theme.scss +222 -0
  203. package/dist/scss/v2/_icons.scss +2 -0
  204. package/dist/scss/v2/index.layout.scss +1 -0
  205. package/dist/scss/v2/index.scss +1 -0
  206. package/dist/store/hooks/useStateStore.js +35 -11
  207. package/package.json +32 -47
@@ -5,8 +5,8 @@ const STATUSES_EXCLUDED_FROM_PREPEND = {
5
5
  };
6
6
  export function usePrependedMessagesCount(messages, hasDateSeparator) {
7
7
  const firstRealMessageIndex = hasDateSeparator ? 1 : 0;
8
- const firstMessageOnFirstLoadedPage = useRef();
9
- const previousFirstMessageOnFirstLoadedPage = useRef();
8
+ const firstMessageOnFirstLoadedPage = useRef(undefined);
9
+ const previousFirstMessageOnFirstLoadedPage = useRef(undefined);
10
10
  const previousNumItemsPrepended = useRef(0);
11
11
  const numItemsPrepended = useMemo(() => {
12
12
  if (!messages || !messages.length) {
@@ -26,7 +26,8 @@ export function usePrependedMessagesCount(messages, hasDateSeparator) {
26
26
  // That in turn leads to incorrect index calculation in VirtualizedMessageList trying to access a message
27
27
  // at non-existent index. Therefore, we ignore messages of status "sending" / "failed" in order they are
28
28
  // not considered as prepended messages.
29
- const firstMsgMovedAfterMessagesInExcludedStatus = !!(currentFirstMessage?.status && STATUSES_EXCLUDED_FROM_PREPEND[currentFirstMessage.status]);
29
+ const firstMsgMovedAfterMessagesInExcludedStatus = !!(currentFirstMessage?.status &&
30
+ STATUSES_EXCLUDED_FROM_PREPEND[currentFirstMessage.status]);
30
31
  if (noNewMessages || firstMsgMovedAfterMessagesInExcludedStatus) {
31
32
  return previousNumItemsPrepended.current;
32
33
  }
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
2
  export const useScrollToBottomOnNewMessage = ({ messages, scrollToBottom, scrollToLatestMessageOnFocus, }) => {
3
3
  const [newMessagesReceivedInBackground, setNewMessagesReceivedInBackground] = useState(false);
4
- const scrollToBottomIfConfigured = useRef();
4
+ const scrollToBottomIfConfigured = useRef(undefined);
5
5
  scrollToBottomIfConfigured.current = (event) => {
6
6
  if (!scrollToLatestMessageOnFocus ||
7
7
  !newMessagesReceivedInBackground ||
@@ -21,10 +21,14 @@ export const useUnreadMessagesNotificationVirtualized = ({ lastRead, showAlways,
21
21
  if (!(firstRenderedMessage && lastRenderedMessage))
22
22
  return;
23
23
  const scrolledBelowSeparator = !!lastRead &&
24
- new Date(firstRenderedMessage.created_at).getTime() > lastRead.getTime();
24
+ new Date(firstRenderedMessage.created_at).getTime() >
25
+ lastRead.getTime();
25
26
  const scrolledAboveSeparator = !!lastRead &&
26
- new Date(lastRenderedMessage.created_at).getTime() < lastRead.getTime();
27
- setShow(showAlways ? scrolledBelowSeparator || scrolledAboveSeparator : scrolledBelowSeparator);
27
+ new Date(lastRenderedMessage.created_at).getTime() <
28
+ lastRead.getTime();
29
+ setShow(showAlways
30
+ ? scrolledBelowSeparator || scrolledAboveSeparator
31
+ : scrolledBelowSeparator);
28
32
  }, [lastRead, showAlways, unreadCount]);
29
33
  useEffect(() => {
30
34
  if (!unreadCount)
@@ -1,8 +1,7 @@
1
- import { DefaultStreamChatGenerics } from '../../../types';
1
+ import type { DefaultStreamChatGenerics } from '../../../types';
2
2
  type UseMarkReadParams = {
3
3
  isMessageListScrolledToBottom: boolean;
4
4
  messageListIsThread: boolean;
5
- unreadCount: number;
6
5
  wasMarkedUnread?: boolean;
7
6
  };
8
7
  /**
@@ -12,8 +11,7 @@ type UseMarkReadParams = {
12
11
  * 3. the channel was not marked unread by the user
13
12
  * @param isMessageListScrolledToBottom
14
13
  * @param messageListIsThread
15
- * @param unreadCount
16
14
  * @param wasChannelMarkedUnread
17
15
  */
18
- export declare const useMarkRead: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ isMessageListScrolledToBottom, messageListIsThread, unreadCount, wasMarkedUnread, }: UseMarkReadParams) => void;
16
+ export declare const useMarkRead: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>({ isMessageListScrolledToBottom, messageListIsThread, wasMarkedUnread, }: UseMarkReadParams) => void;
19
17
  export {};
@@ -1,5 +1,10 @@
1
- import { useEffect, useRef } from 'react';
1
+ import { useEffect } from 'react';
2
2
  import { useChannelActionContext, useChannelStateContext, useChatContext, } from '../../../context';
3
+ const hasReadLastMessage = (channel, userId) => {
4
+ const latestMessageIdInChannel = channel.state.latestMessages.slice(-1)[0]?.id;
5
+ const lastReadMessageIdServer = channel.state.read[userId]?.last_read_message_id;
6
+ return latestMessageIdInChannel === lastReadMessageIdServer;
7
+ };
3
8
  /**
4
9
  * Takes care of marking a channel read. The channel is read only if all the following applies:
5
10
  * 1. the message list is not rendered in a thread
@@ -7,29 +12,25 @@ import { useChannelActionContext, useChannelStateContext, useChatContext, } from
7
12
  * 3. the channel was not marked unread by the user
8
13
  * @param isMessageListScrolledToBottom
9
14
  * @param messageListIsThread
10
- * @param unreadCount
11
15
  * @param wasChannelMarkedUnread
12
16
  */
13
- export const useMarkRead = ({ isMessageListScrolledToBottom, messageListIsThread, unreadCount, wasMarkedUnread, }) => {
17
+ export const useMarkRead = ({ isMessageListScrolledToBottom, messageListIsThread, wasMarkedUnread, }) => {
14
18
  const { client } = useChatContext('useMarkRead');
15
19
  const { markRead, setChannelUnreadUiState } = useChannelActionContext('useMarkRead');
16
20
  const { channel } = useChannelStateContext('useMarkRead');
17
- const previousRenderMessageListScrolledToBottom = useRef(isMessageListScrolledToBottom);
18
21
  useEffect(() => {
19
- const shouldMarkRead = (unreadMessages) => !document.hidden &&
22
+ const shouldMarkRead = () => !document.hidden &&
20
23
  !wasMarkedUnread &&
21
24
  !messageListIsThread &&
22
25
  isMessageListScrolledToBottom &&
23
- unreadMessages > 0;
26
+ client.user?.id &&
27
+ !hasReadLastMessage(channel, client.user.id);
24
28
  const onVisibilityChange = () => {
25
- if (shouldMarkRead(channel.countUnread()))
29
+ if (shouldMarkRead())
26
30
  markRead();
27
31
  };
28
32
  const handleMessageNew = (event) => {
29
- const isOwnMessage = event.user?.id && event.user.id === client.user?.id;
30
33
  const mainChannelUpdated = !event.message?.parent_id || event.message?.show_in_channel;
31
- if (isOwnMessage)
32
- return;
33
34
  if (!isMessageListScrolledToBottom || wasMarkedUnread || document.hidden) {
34
35
  setChannelUnreadUiState((prev) => {
35
36
  const previousUnreadCount = prev?.unread_messages ?? 0;
@@ -44,17 +45,15 @@ export const useMarkRead = ({ isMessageListScrolledToBottom, messageListIsThread
44
45
  };
45
46
  });
46
47
  }
47
- else if (mainChannelUpdated && shouldMarkRead(channel.countUnread())) {
48
+ else if (mainChannelUpdated && shouldMarkRead()) {
48
49
  markRead();
49
50
  }
50
51
  };
51
52
  channel.on('message.new', handleMessageNew);
52
53
  document.addEventListener('visibilitychange', onVisibilityChange);
53
- const hasScrolledToBottom = previousRenderMessageListScrolledToBottom.current !== isMessageListScrolledToBottom &&
54
- isMessageListScrolledToBottom;
55
- if (hasScrolledToBottom && shouldMarkRead(channel.countUnread()))
54
+ if (shouldMarkRead()) {
56
55
  markRead();
57
- previousRenderMessageListScrolledToBottom.current = isMessageListScrolledToBottom;
56
+ }
58
57
  return () => {
59
58
  channel.off('message.new', handleMessageNew);
60
59
  document.removeEventListener('visibilitychange', onVisibilityChange);
@@ -66,7 +65,6 @@ export const useMarkRead = ({ isMessageListScrolledToBottom, messageListIsThread
66
65
  markRead,
67
66
  messageListIsThread,
68
67
  setChannelUnreadUiState,
69
- unreadCount,
70
68
  wasMarkedUnread,
71
69
  ]);
72
70
  };
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-continue */
2
1
  import { nanoid } from 'nanoid';
3
2
  import { CUSTOM_MESSAGE_TYPE } from '../../constants/messageTypes';
4
3
  import { isMessageEdited } from '../Message/utils';
@@ -31,20 +30,29 @@ export const processMessages = (params) => {
31
30
  if (hideDeletedMessages && message.type === 'deleted') {
32
31
  continue;
33
32
  }
34
- if (setGiphyPreviewMessage && message.type === 'ephemeral' && message.command === 'giphy') {
33
+ if (setGiphyPreviewMessage &&
34
+ message.type === 'ephemeral' &&
35
+ message.command === 'giphy') {
35
36
  ephemeralMessagePresent = true;
36
37
  setGiphyPreviewMessage(message);
37
38
  continue;
38
39
  }
39
40
  const changes = [];
40
- const messageDate = (message.created_at && isDate(message.created_at) && message.created_at.toDateString()) || '';
41
+ const messageDate = (message.created_at &&
42
+ isDate(message.created_at) &&
43
+ message.created_at.toDateString()) ||
44
+ '';
41
45
  const previousMessage = messages[i - 1];
42
46
  let prevMessageDate = messageDate;
43
- if (enableDateSeparator && previousMessage?.created_at && isDate(previousMessage.created_at)) {
47
+ if (enableDateSeparator &&
48
+ previousMessage?.created_at &&
49
+ isDate(previousMessage.created_at)) {
44
50
  prevMessageDate = previousMessage.created_at.toDateString();
45
51
  }
46
52
  if (!unread && !hideNewMessageSeparator) {
47
- unread = (lastRead && message.created_at && new Date(lastRead) < message.created_at) || false;
53
+ unread =
54
+ (lastRead && message.created_at && new Date(lastRead) < message.created_at) ||
55
+ false;
48
56
  // do not show date separator for current user's messages
49
57
  if (enableDateSeparator && unread && message.user?.id !== userId) {
50
58
  changes.push({
@@ -155,7 +163,9 @@ export const insertIntro = (messages, headerPosition) => {
155
163
  // else loop over the messages
156
164
  for (let i = 0; i < messages.length; i += 1) {
157
165
  const message = messages[i];
158
- const messageTime = message.created_at && isDate(message.created_at) ? message.created_at.getTime() : null;
166
+ const messageTime = message.created_at && isDate(message.created_at)
167
+ ? message.created_at.getTime()
168
+ : null;
159
169
  const nextMessage = messages[i + 1];
160
170
  const nextMessageTime = nextMessage.created_at && isDate(nextMessage.created_at)
161
171
  ? nextMessage.created_at.getTime()
@@ -199,7 +209,8 @@ export const getGroupStyles = (message, previousMessage, nextMessage, noGroupByU
199
209
  (maxTimeBetweenGroupedMessages !== undefined &&
200
210
  previousMessage.created_at &&
201
211
  message.created_at &&
202
- new Date(message.created_at).getTime() - new Date(previousMessage.created_at).getTime() >
212
+ new Date(message.created_at).getTime() -
213
+ new Date(previousMessage.created_at).getTime() >
203
214
  maxTimeBetweenGroupedMessages);
204
215
  const isBottomMessage = !nextMessage ||
205
216
  nextMessage.customType === CUSTOM_MESSAGE_TYPE.intro ||
@@ -209,12 +220,14 @@ export const getGroupStyles = (message, previousMessage, nextMessage, noGroupByU
209
220
  nextMessage.attachments?.length !== 0 ||
210
221
  message.user?.id !== nextMessage.user?.id ||
211
222
  nextMessage.deleted_at ||
212
- (nextMessage.reaction_groups && Object.keys(nextMessage.reaction_groups).length > 0) ||
223
+ (nextMessage.reaction_groups &&
224
+ Object.keys(nextMessage.reaction_groups).length > 0) ||
213
225
  isMessageEdited(message) ||
214
226
  (maxTimeBetweenGroupedMessages !== undefined &&
215
227
  nextMessage.created_at &&
216
228
  message.created_at &&
217
- new Date(nextMessage.created_at).getTime() - new Date(message.created_at).getTime() >
229
+ new Date(nextMessage.created_at).getTime() -
230
+ new Date(message.created_at).getTime() >
218
231
  maxTimeBetweenGroupedMessages);
219
232
  if (!isTopMessage && !isBottomMessage) {
220
233
  if (message.deleted_at || message.type === 'error')
@@ -239,7 +252,9 @@ export const hasMoreMessagesProbably = (returnedCountMessages, limit) => returne
239
252
  // @deprecated
240
253
  export const hasNotMoreMessages = (returnedCountMessages, limit) => returnedCountMessages < limit;
241
254
  export function isDateSeparatorMessage(message) {
242
- return message.customType === CUSTOM_MESSAGE_TYPE.date && !!message.date && isDate(message.date);
255
+ return (message.customType === CUSTOM_MESSAGE_TYPE.date &&
256
+ !!message.date &&
257
+ isDate(message.date));
243
258
  }
244
259
  export const getIsFirstUnreadMessage = ({ firstUnreadMessageId, isFirstMessage, lastReadDate, lastReadMessageId, message, previousMessage, unreadMessageCount = 0, }) => {
245
260
  const createdAtTimestamp = message.created_at && new Date(message.created_at).getTime();
@@ -247,5 +262,7 @@ export const getIsFirstUnreadMessage = ({ firstUnreadMessageId, isFirstMessage,
247
262
  const messageIsUnread = !!createdAtTimestamp && !!lastReadTimestamp && createdAtTimestamp > lastReadTimestamp;
248
263
  const previousMessageIsLastRead = !!lastReadMessageId && lastReadMessageId === previousMessage?.id;
249
264
  return (firstUnreadMessageId === message.id ||
250
- (!!unreadMessageCount && messageIsUnread && (isFirstMessage || previousMessageIsLastRead)));
265
+ (!!unreadMessageCount &&
266
+ messageIsUnread &&
267
+ (isFirstMessage || previousMessageIsLastRead)));
251
268
  };
@@ -7,4 +7,4 @@ export type ModalProps = {
7
7
  /** Callback handler for closing of modal. */
8
8
  onClose?: (event: React.KeyboardEvent | React.MouseEvent<HTMLButtonElement | HTMLDivElement>) => void;
9
9
  };
10
- export declare const Modal: ({ children, className, onClose, open }: PropsWithChildren<ModalProps>) => React.JSX.Element | null;
10
+ export declare const Modal: ({ children, className, onClose, open, }: PropsWithChildren<ModalProps>) => React.JSX.Element | null;
@@ -3,7 +3,7 @@ import React, { useEffect, useRef } from 'react';
3
3
  import { FocusScope } from '@react-aria/focus';
4
4
  import { CloseIconRound } from './icons';
5
5
  import { useTranslationContext } from '../../context';
6
- export const Modal = ({ children, className, onClose, open }) => {
6
+ export const Modal = ({ children, className, onClose, open, }) => {
7
7
  const { t } = useTranslationContext('Modal');
8
8
  const innerRef = useRef(null);
9
9
  const closeRef = useRef(null);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import clsx from 'clsx';
3
3
  export const ModalHeader = ({ className, close, goBack, title }) => (React.createElement("div", { className: clsx('str-chat__modal-header', className) },
4
- goBack && React.createElement("button", { className: 'str-chat__modal-header__go-back-button', onClick: goBack }),
4
+ goBack && (React.createElement("button", { className: 'str-chat__modal-header__go-back-button', onClick: goBack })),
5
5
  React.createElement("div", { className: 'str-chat__modal-header__title' }, title),
6
6
  close && React.createElement("button", { className: 'str-chat__modal-header__close-button', onClick: close })));
@@ -3,6 +3,6 @@ import { PollContent as DefaultPollContent } from './PollContent';
3
3
  import { QuotedPoll as DefaultQuotedPoll } from './QuotedPoll';
4
4
  import { PollProvider, useComponentContext } from '../../context';
5
5
  export const Poll = ({ isQuoted, poll, }) => {
6
- const { PollContent = DefaultPollContent, QuotedPoll = DefaultQuotedPoll, } = useComponentContext();
6
+ const { PollContent = DefaultPollContent, QuotedPoll = DefaultQuotedPoll } = useComponentContext();
7
7
  return poll ? (React.createElement(PollProvider, { poll: poll }, isQuoted ? React.createElement(QuotedPoll, null) : React.createElement(PollContent, null))) : null;
8
8
  };
@@ -1,9 +1,9 @@
1
1
  import React, { useCallback, useState } from 'react';
2
2
  import { PollAction } from './PollAction';
3
- import { AddCommentForm as DefaultAddCommentForm } from './AddCommentForm';
3
+ import { AddCommentForm as DefaultAddCommentForm, } from './AddCommentForm';
4
4
  import { SuggestPollOptionForm as DefaultSuggestPollOptionForm, } from './SuggestPollOptionForm';
5
- import { EndPollDialog as DefaultEndPollDialog } from './EndPollDialog';
6
- import { PollAnswerList as DefaultPollAnswerList } from './PollAnswerList';
5
+ import { EndPollDialog as DefaultEndPollDialog, } from './EndPollDialog';
6
+ import { PollAnswerList as DefaultPollAnswerList, } from './PollAnswerList';
7
7
  import { PollOptionsFullList as DefaultPollOptionsFullList, } from './PollOptionsFullList';
8
8
  import { PollResults as DefaultPollResults } from './PollResults';
9
9
  import { MAX_OPTIONS_DISPLAYED, MAX_POLL_OPTIONS } from '../constants';
@@ -33,7 +33,9 @@ export const PollActions = ({ AddCommentForm = DefaultAddCommentForm, EndPollDia
33
33
  count: options.length,
34
34
  }), closeModal: closeModal, modalIsOpen: modalOpen === 'view-all-options', openModal: () => setModalOpen('view-all-options') },
35
35
  React.createElement(PollOptionsFullList, { close: closeModal }))),
36
- !is_closed && allow_user_suggested_options && options.length < MAX_POLL_OPTIONS && (React.createElement(PollAction, { buttonText: t('Suggest an option'), closeModal: closeModal, modalClassName: 'str-chat__suggest-poll-option-modal', modalIsOpen: modalOpen === 'suggest-option', openModal: () => setModalOpen('suggest-option') },
36
+ !is_closed &&
37
+ allow_user_suggested_options &&
38
+ options.length < MAX_POLL_OPTIONS && (React.createElement(PollAction, { buttonText: t('Suggest an option'), closeModal: closeModal, modalClassName: 'str-chat__suggest-poll-option-modal', modalIsOpen: modalOpen === 'suggest-option', openModal: () => setModalOpen('suggest-option') },
37
39
  React.createElement(SuggestPollOptionForm, { close: closeModal, messageId: message.id }))),
38
40
  !is_closed && allow_answers && (React.createElement(PollAction, { buttonText: ownAnswer ? t('Update your comment') : t('Add a comment'), closeModal: closeModal, modalClassName: 'str-chat__add-poll-answer-modal', modalIsOpen: modalOpen === 'add-comment', openModal: () => setModalOpen('add-comment') },
39
41
  React.createElement(AddCommentForm, { close: closeModal, messageId: message.id }))),
@@ -14,7 +14,7 @@ export const PollAnswerList = ({ close, onUpdateOwnAnswerClick, }) => {
14
14
  const { t } = useTranslationContext();
15
15
  const { poll } = usePollContext();
16
16
  const { is_closed, ownAnswer } = useStateStore(poll.state, pollStateSelector);
17
- const { answers, error, hasNextPage, loading, loadMore, } = usePollAnswerPagination();
17
+ const { answers, error, hasNextPage, loading, loadMore } = usePollAnswerPagination();
18
18
  return (React.createElement("div", { className: 'str-chat__modal__poll-answer-list' },
19
19
  React.createElement(ModalHeader, { close: close, title: t('Poll comments') }),
20
20
  React.createElement("div", { className: 'str-chat__modal__poll-answer-list__body' },
@@ -6,7 +6,7 @@ import { InfiniteScrollPaginator } from '../../../InfiniteScrollPaginator/Infini
6
6
  import { PollOptionWithVotesHeader } from './PollOptionWithVotesHeader';
7
7
  export const PollOptionVotesList = ({ option, }) => {
8
8
  const paginationParams = useMemo(() => ({ filter: { option_id: option.id } }), [option.id]);
9
- const { error, hasNextPage, loading, loadMore, votes, } = usePollOptionVotesPagination({
9
+ const { error, hasNextPage, loading, loadMore, votes } = usePollOptionVotesPagination({
10
10
  paginationParams,
11
11
  });
12
12
  return (React.createElement("div", { className: 'str-chat__poll-option str-chat__poll-option--full-vote-list' },
@@ -2,8 +2,10 @@ import React from 'react';
2
2
  import { PollOptionWithVotesHeader } from './PollOptionWithVotesHeader';
3
3
  import { PollVoteListing } from '../../PollVote';
4
4
  import { useStateStore } from '../../../../store';
5
- import { useChannelStateContext, usePollContext, useTranslationContext } from '../../../../context';
6
- const pollStateSelector = (nextValue) => ({ latest_votes_by_option: nextValue.latest_votes_by_option });
5
+ import { useChannelStateContext, usePollContext, useTranslationContext, } from '../../../../context';
6
+ const pollStateSelector = (nextValue) => ({
7
+ latest_votes_by_option: nextValue.latest_votes_by_option,
8
+ });
7
9
  export const PollOptionWithLatestVotes = ({ countVotesPreview = 5, option, showAllVotes, }) => {
8
10
  const { t } = useTranslationContext();
9
11
  const { channelCapabilities = {} } = useChannelStateContext('PollOptionWithLatestVotes');
@@ -26,7 +26,8 @@ export const PollResults = ({ close, }) => {
26
26
  React.createElement("div", { className: 'str-chat__modal__poll-results__body' },
27
27
  React.createElement("div", { className: 'str-chat__modal__poll-results__title' }, name),
28
28
  React.createElement("div", { className: 'str-chat__modal__poll-results__option-list' }, options
29
- .sort((next, current) => (vote_counts_by_option[current.id] ?? 0) >= (vote_counts_by_option[next.id] ?? 0)
29
+ .sort((next, current) => (vote_counts_by_option[current.id] ?? 0) >=
30
+ (vote_counts_by_option[next.id] ?? 0)
30
31
  ? 1
31
32
  : -1)
32
33
  .map((option) => (React.createElement(PollOptionWithLatestVotes, { key: `poll-option-${option.id}`, option: option, showAllVotes: () => setOptionToView(option) })))))))));
@@ -8,7 +8,7 @@ import { useComponentContext, usePollContext } from '../../context';
8
8
  import { useStateStore } from '../../store';
9
9
  const pollStateSelectorPollContent = (nextValue) => ({ is_closed: nextValue.is_closed });
10
10
  export const PollContent = () => {
11
- const { PollHeader = DefaultPollHeader, PollActions = DefaultPollActions, } = useComponentContext();
11
+ const { PollActions = DefaultPollActions, PollHeader = DefaultPollHeader } = useComponentContext();
12
12
  const { poll } = usePollContext();
13
13
  const { is_closed } = useStateStore(poll.state, pollStateSelectorPollContent);
14
14
  return (React.createElement("div", { className: clsx('str-chat__poll', { 'str-chat__poll--closed': is_closed }) },
@@ -6,4 +6,4 @@ export type OptionFieldSetProps = {
6
6
  setErrors: (fn: (prev: OptionErrors) => OptionErrors) => void;
7
7
  setState: (fn: (prev: PollFormState) => PollFormState) => void;
8
8
  };
9
- export declare const OptionFieldSet: ({ errors, options, setErrors, setState }: OptionFieldSetProps) => React.JSX.Element;
9
+ export declare const OptionFieldSet: ({ errors, options, setErrors, setState, }: OptionFieldSetProps) => React.JSX.Element;
@@ -6,7 +6,7 @@ import { FieldError } from '../../Form/FieldError';
6
6
  import { DragAndDropContainer } from '../../DragAndDrop/DragAndDropContainer';
7
7
  import { useTranslationContext } from '../../../context';
8
8
  const VALIDATION_ERRORS = { 'Option already exists': true };
9
- export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
9
+ export const OptionFieldSet = ({ errors, options, setErrors, setState, }) => {
10
10
  const { t } = useTranslationContext('OptionFieldSet');
11
11
  const findOptionDuplicate = (sourceOption) => {
12
12
  const isDuplicateFilter = (option) => !!sourceOption.text.trim() && // do not include empty options into consideration
@@ -15,7 +15,10 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
15
15
  return options.find(isDuplicateFilter);
16
16
  };
17
17
  const onSetNewOrder = useCallback((newOrder) => {
18
- setState((prev) => ({ ...prev, options: newOrder.map((index) => prev.options[index]) }));
18
+ setState((prev) => ({
19
+ ...prev,
20
+ options: newOrder.map((index) => prev.options[index]),
21
+ }));
19
22
  }, [setState]);
20
23
  const draggable = options.length > 1;
21
24
  return (React.createElement("fieldset", { className: 'str-chat__form__field str-chat__form__input-fieldset' },
@@ -38,7 +41,9 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
38
41
  const shouldAddEmptyOption = prev.options.length < MAX_POLL_OPTIONS &&
39
42
  (!prev.options ||
40
43
  (prev.options.slice(i + 1).length === 0 && !!e.target.value));
41
- const shouldRemoveOption = prev.options && prev.options.slice(i + 1).length > 0 && !e.target.value;
44
+ const shouldRemoveOption = prev.options &&
45
+ prev.options.slice(i + 1).length > 0 &&
46
+ !e.target.value;
42
47
  const optionListHead = prev.options ? prev.options.slice(0, i) : [];
43
48
  const optionListTail = shouldAddEmptyOption
44
49
  ? [{ id: nanoid(), text: '' }]
@@ -55,7 +60,9 @@ export const OptionFieldSet = ({ errors, options, setErrors, setState }) => {
55
60
  ...prev,
56
61
  options: [
57
62
  ...optionListHead,
58
- ...(shouldRemoveOption ? [] : [{ ...option, text: e.target.value }]),
63
+ ...(shouldRemoveOption
64
+ ? []
65
+ : [{ ...option, text: e.target.value }]),
59
66
  ...optionListTail,
60
67
  ],
61
68
  };
@@ -64,20 +64,29 @@ export const PollCreationDialog = ({ close }) => {
64
64
  React.createElement("div", { className: clsx('str-chat__form__input-field__value') },
65
65
  React.createElement(FieldError, { className: 'str-chat__form__input-field__error', "data-testid": 'poll-max-votes-allowed-input-field-error', text: multipleAnswerCountError }),
66
66
  React.createElement("input", { id: 'max_votes_allowed', onChange: (e) => {
67
- const isValidValue = !e.target.value || e.target.value.match(VALID_MAX_VOTES_VALUE_REGEX);
67
+ const isValidValue = !e.target.value ||
68
+ e.target.value.match(VALID_MAX_VOTES_VALUE_REGEX);
68
69
  if (!isValidValue) {
69
70
  setMultipleAnswerCountError(t('Type a number from 2 to 10'));
70
71
  }
71
72
  else if (multipleAnswerCountError) {
72
73
  setMultipleAnswerCountError(undefined);
73
74
  }
74
- setState((prev) => ({ ...prev, max_votes_allowed: e.target.value }));
75
+ setState((prev) => ({
76
+ ...prev,
77
+ max_votes_allowed: e.target.value,
78
+ }));
75
79
  }, placeholder: t('Maximum number of votes (from 2 to 10)'), type: 'number', value: state.max_votes_allowed }))))),
76
80
  React.createElement(SimpleSwitchField, { checked: state.voting_visibility === 'anonymous', id: 'voting_visibility', labelText: t('Anonymous poll'), onChange: (e) => setState((prev) => ({
77
81
  ...prev,
78
- voting_visibility: (e.target.checked ? 'anonymous' : 'public'),
82
+ voting_visibility: (e.target.checked
83
+ ? 'anonymous'
84
+ : 'public'),
85
+ })) }),
86
+ React.createElement(SimpleSwitchField, { checked: state.allow_user_suggested_options, id: 'allow_user_suggested_options', labelText: t('Allow option suggestion'), onChange: (e) => setState((prev) => ({
87
+ ...prev,
88
+ allow_user_suggested_options: e.target.checked,
79
89
  })) }),
80
- React.createElement(SimpleSwitchField, { checked: state.allow_user_suggested_options, id: 'allow_user_suggested_options', labelText: t('Allow option suggestion'), onChange: (e) => setState((prev) => ({ ...prev, allow_user_suggested_options: e.target.checked })) }),
81
90
  React.createElement(SimpleSwitchField, { checked: state.allow_answers, id: 'allow_answers', labelText: t('Allow comments'), onChange: (e) => setState((prev) => ({ ...prev, allow_answers: e.target.checked })) }))),
82
91
  React.createElement(PollCreationDialogControls, { close: close, errors: [
83
92
  ...(nameError ?? []),
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { VALID_MAX_VOTES_VALUE_REGEX } from '../constants';
3
- import { useChatContext, useMessageInputContext, useTranslationContext } from '../../../context';
3
+ import { useChatContext, useMessageInputContext, useTranslationContext, } from '../../../context';
4
4
  export const PollCreationDialogControls = ({ close, errors, state, }) => {
5
5
  const { client } = useChatContext();
6
6
  const { t } = useTranslationContext('PollCreationDialogControls');
@@ -10,7 +10,8 @@ export const PollCreationDialogControls = ({ close, errors, state, }) => {
10
10
  const hasName = !!state.name;
11
11
  const maxVotesAllowedNumber = parseInt(state.max_votes_allowed?.match(VALID_MAX_VOTES_VALUE_REGEX)?.[0] || '');
12
12
  const validMaxVotesAllowed = state.max_votes_allowed === '' ||
13
- (!!maxVotesAllowedNumber && (2 <= maxVotesAllowedNumber || maxVotesAllowedNumber <= 10));
13
+ (!!maxVotesAllowedNumber &&
14
+ (2 <= maxVotesAllowedNumber || maxVotesAllowedNumber <= 10));
14
15
  const noErrors = errors.length === 0;
15
16
  return hasAtLeastOneOption && hasName && validMaxVotesAllowed && noErrors;
16
17
  };
@@ -24,7 +25,9 @@ export const PollCreationDialogControls = ({ close, errors, state, }) => {
24
25
  max_votes_allowed: state.max_votes_allowed
25
26
  ? parseInt(state.max_votes_allowed)
26
27
  : undefined,
27
- options: state.options?.filter((o) => o.text).map((o) => ({ text: o.text })),
28
+ options: state.options
29
+ ?.filter((o) => o.text)
30
+ .map((o) => ({ text: o.text })),
28
31
  });
29
32
  pollId = poll.id;
30
33
  }
@@ -5,7 +5,7 @@ import { useStateStore } from '../../store';
5
5
  import { useComponentContext, usePollContext } from '../../context';
6
6
  const pollStateSelector = (nextValue) => ({ options: nextValue.options });
7
7
  export const PollOptionList = ({ optionsDisplayCount, }) => {
8
- const { PollOptionSelector = DefaultPollOptionSelector, } = useComponentContext();
8
+ const { PollOptionSelector = DefaultPollOptionSelector } = useComponentContext();
9
9
  const { poll } = usePollContext();
10
10
  const { options } = useStateStore(poll.state, pollStateSelector);
11
11
  return (React.createElement("div", { className: clsx('str-chat__poll-option-list', {
@@ -24,7 +24,9 @@ export const PollOptionSelector = ({ displayAvatarCount, option, voteCountVerbos
24
24
  const { poll } = usePollContext();
25
25
  const { is_closed, latest_votes_by_option, maxVotedOptionIds, ownVotesByOptionId, vote_counts_by_option, voting_visibility, } = useStateStore(poll.state, pollStateSelector);
26
26
  const canCastVote = channelCapabilities['cast-poll-vote'] && !is_closed;
27
- const winningOptionCount = maxVotedOptionIds[0] ? vote_counts_by_option[maxVotedOptionIds[0]] : 0;
27
+ const winningOptionCount = maxVotedOptionIds[0]
28
+ ? vote_counts_by_option[maxVotedOptionIds[0]]
29
+ : 0;
28
30
  const toggleVote = useMemo(() => debounce(() => {
29
31
  if (!canCastVote)
30
32
  return;
@@ -45,9 +47,14 @@ export const PollOptionSelector = ({ displayAvatarCount, option, voteCountVerbos
45
47
  .slice(0, displayAvatarCount)
46
48
  .map(({ user }) => (React.createElement(Avatar, { image: user?.image, key: `poll-option-${option.id}-avatar-${user?.id}`, name: user?.name }))))),
47
49
  React.createElement("div", { className: 'str-chat__poll-option-vote-count' }, voteCountVerbose
48
- ? t('{{count}} votes', { count: vote_counts_by_option[option.id] ?? 0 })
49
- : vote_counts_by_option[option.id] ?? 0)),
50
- React.createElement(AmountBar, { amount: (winningOptionCount && (vote_counts_by_option[option.id] ?? 0) / winningOptionCount) * 100, className: clsx('str-chat__poll-option__votes-bar', {
51
- 'str-chat__poll-option__votes-bar--winner': is_closed && maxVotedOptionIds.length === 1 && maxVotedOptionIds[0] === option.id,
50
+ ? t('{{count}} votes', {
51
+ count: vote_counts_by_option[option.id] ?? 0,
52
+ })
53
+ : (vote_counts_by_option[option.id] ?? 0))),
54
+ React.createElement(AmountBar, { amount: (winningOptionCount &&
55
+ (vote_counts_by_option[option.id] ?? 0) / winningOptionCount) * 100, className: clsx('str-chat__poll-option__votes-bar', {
56
+ 'str-chat__poll-option__votes-bar--winner': is_closed &&
57
+ maxVotedOptionIds.length === 1 &&
58
+ maxVotedOptionIds[0] === option.id,
52
59
  }) })));
53
60
  };
@@ -11,16 +11,21 @@ export function useManagePollVotesRealtime(managedVoteType, cursorPaginatorState
11
11
  return;
12
12
  const isAnswer = isVoteAnswer(event.poll_vote);
13
13
  if ((managedVoteType === 'answer' && !isAnswer) ||
14
- (managedVoteType === 'vote' && (isAnswer || event.poll_vote.option_id !== optionId)))
14
+ (managedVoteType === 'vote' &&
15
+ (isAnswer || event.poll_vote.option_id !== optionId)))
15
16
  return;
16
17
  if (event.type === 'poll.vote_removed') {
17
- setVotesInRealtime((prev) => event.poll_vote ? prev.filter((vote) => vote.id !== event.poll_vote.id) : prev);
18
+ setVotesInRealtime((prev) => event.poll_vote
19
+ ? prev.filter((vote) => vote.id !== event.poll_vote.id)
20
+ : prev);
18
21
  }
19
22
  if (event.type === 'poll.vote_changed') {
20
- setVotesInRealtime((prev) => event.poll_vote ? prev.filter((vote) => vote.id !== event.poll_vote.id) : prev);
23
+ setVotesInRealtime((prev) => event.poll_vote
24
+ ? prev.filter((vote) => vote.id !== event.poll_vote.id)
25
+ : prev);
21
26
  }
22
27
  if (['poll.vote_casted', 'poll.vote_changed'].includes(event.type)) {
23
- setVotesInRealtime((prev) => (event.poll_vote ? [event.poll_vote, ...prev] : prev));
28
+ setVotesInRealtime((prev) => event.poll_vote ? [event.poll_vote, ...prev] : prev);
24
29
  }
25
30
  };
26
31
  const voteCastedSubscription = client.on('poll.vote_casted', handleVoteEvent);
@@ -3,13 +3,19 @@ import { useManagePollVotesRealtime } from './useManagePollVotesRealtime';
3
3
  import { useCursorPaginator, } from '../../InfiniteScrollPaginator/hooks/useCursorPaginator';
4
4
  import { usePollContext } from '../../../context';
5
5
  import { useStateStore } from '../../../store';
6
- const paginationStateSelector = (state) => [state.error, state.hasNextPage, state.loading];
6
+ const paginationStateSelector = (state) => [
7
+ state.error,
8
+ state.hasNextPage,
9
+ state.loading,
10
+ ];
7
11
  export const usePollAnswerPagination = ({ paginationParams } = {}) => {
8
12
  const { poll } = usePollContext();
9
13
  const paginationFn = useCallback(async (next) => {
10
14
  const { next: newNext, votes } = await poll.queryAnswers({
11
15
  filter: paginationParams?.filter,
12
- options: !next ? paginationParams?.options : { ...paginationParams?.options, next },
16
+ options: !next
17
+ ? paginationParams?.options
18
+ : { ...paginationParams?.options, next },
13
19
  sort: { created_at: -1, ...paginationParams?.sort },
14
20
  });
15
21
  return { items: votes, next: newNext };
@@ -3,13 +3,19 @@ import { useManagePollVotesRealtime } from './useManagePollVotesRealtime';
3
3
  import { useCursorPaginator, } from '../../InfiniteScrollPaginator/hooks/useCursorPaginator';
4
4
  import { useStateStore } from '../../../store';
5
5
  import { usePollContext } from '../../../context';
6
- const paginationStateSelector = (state) => [state.error, state.hasNextPage, state.loading];
6
+ const paginationStateSelector = (state) => [
7
+ state.error,
8
+ state.hasNextPage,
9
+ state.loading,
10
+ ];
7
11
  export const usePollOptionVotesPagination = ({ paginationParams, }) => {
8
12
  const { poll } = usePollContext();
9
13
  const paginationFn = useCallback(async (next) => {
10
14
  const { next: newNext, votes } = await poll.queryOptionVotes({
11
15
  filter: paginationParams.filter,
12
- options: !next ? paginationParams?.options : { ...paginationParams?.options, next },
16
+ options: !next
17
+ ? paginationParams?.options
18
+ : { ...paginationParams?.options, next },
13
19
  sort: { created_at: -1, ...paginationParams?.sort },
14
20
  });
15
21
  return { items: votes, next: newNext };
@@ -1,5 +1,5 @@
1
1
  export type GeneralType = 'audio/' | 'video/' | 'image/' | 'text/';
2
- export type SupportedMimeType = typeof wordMimeTypes[number] | typeof excelMimeTypes[number] | typeof powerpointMimeTypes[number] | typeof archiveFileTypes[number] | typeof codeFileTypes[number];
2
+ export type SupportedMimeType = (typeof wordMimeTypes)[number] | (typeof excelMimeTypes)[number] | (typeof powerpointMimeTypes)[number] | (typeof archiveFileTypes)[number] | (typeof codeFileTypes)[number];
3
3
  export declare const wordMimeTypes: string[];
4
4
  export declare const excelMimeTypes: string[];
5
5
  export declare const powerpointMimeTypes: string[];
@@ -12,7 +12,9 @@ export const ImageDropzone = ({ accept: acceptedFiles = [], children, disabled,
12
12
  handleFiles(accepted);
13
13
  }
14
14
  }, [handleFiles]);
15
- const accept = useMemo(() => (typeof acceptedFiles === 'string' ? acceptedFiles.split(',') : acceptedFiles).reduce((mediaTypeMap, mediaType) => {
15
+ const accept = useMemo(() => (typeof acceptedFiles === 'string'
16
+ ? acceptedFiles.split(',')
17
+ : acceptedFiles).reduce((mediaTypeMap, mediaType) => {
16
18
  mediaTypeMap[mediaType] ?? (mediaTypeMap[mediaType] = []);
17
19
  return mediaTypeMap;
18
20
  }, {}), [acceptedFiles]);