stream-chat-react 12.0.0-rc.2 → 12.0.0-rc.3

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 (91) hide show
  1. package/README.md +10 -0
  2. package/dist/components/Attachment/components/WaveProgressBar.d.ts +3 -1
  3. package/dist/components/Attachment/components/WaveProgressBar.js +44 -9
  4. package/dist/components/Channel/channelState.js +1 -0
  5. package/dist/components/DateSeparator/DateSeparator.js +1 -1
  6. package/dist/components/EventComponent/EventComponent.js +1 -1
  7. package/dist/components/InfiniteScrollPaginator/InfiniteScroll.js +9 -3
  8. package/dist/components/MediaRecorder/classes/MediaRecorderController.d.ts +6 -7
  9. package/dist/components/MediaRecorder/classes/MediaRecorderController.js +0 -5
  10. package/dist/components/MediaRecorder/hooks/index.d.ts +1 -1
  11. package/dist/components/MediaRecorder/hooks/useMediaRecorder.d.ts +1 -2
  12. package/dist/components/MediaRecorder/hooks/useMediaRecorder.js +1 -1
  13. package/dist/components/MediaRecorder/index.d.ts +1 -0
  14. package/dist/components/MediaRecorder/transcode/index.d.ts +6 -5
  15. package/dist/components/MediaRecorder/transcode/index.js +5 -15
  16. package/dist/components/Message/MessageSimple.js +1 -1
  17. package/dist/components/Message/MessageTimestamp.d.ts +0 -1
  18. package/dist/components/Message/MessageTimestamp.js +0 -1
  19. package/dist/components/Message/Timestamp.d.ts +0 -1
  20. package/dist/components/Message/Timestamp.js +2 -3
  21. package/dist/components/Message/renderText/remarkPlugins/keepLineBreaksPlugin.js +1 -1
  22. package/dist/components/Message/utils.js +2 -0
  23. package/dist/components/MessageInput/AttachmentPreviewList/AttachmentPreviewList.js +23 -27
  24. package/dist/components/MessageInput/AttachmentPreviewList/FileAttachmentPreview.d.ts +1 -0
  25. package/dist/components/MessageInput/AttachmentPreviewList/FileAttachmentPreview.js +1 -1
  26. package/dist/components/MessageInput/AttachmentPreviewList/ImageAttachmentPreview.js +2 -1
  27. package/dist/components/MessageInput/MessageInput.d.ts +4 -6
  28. package/dist/components/MessageInput/MessageInputFlat.js +4 -7
  29. package/dist/components/MessageInput/hooks/useAttachments.d.ts +1 -5
  30. package/dist/components/MessageInput/hooks/useAttachments.js +65 -52
  31. package/dist/components/MessageInput/hooks/useCreateMessageInputContext.js +2 -19
  32. package/dist/components/MessageInput/hooks/useMessageInputState.d.ts +2 -35
  33. package/dist/components/MessageInput/hooks/useMessageInputState.js +2 -107
  34. package/dist/components/MessageInput/hooks/usePasteHandler.js +1 -3
  35. package/dist/components/MessageInput/hooks/useSubmitHandler.js +19 -71
  36. package/dist/components/MessageInput/hooks/utils.d.ts +1 -2
  37. package/dist/components/MessageInput/icons.d.ts +0 -1
  38. package/dist/components/MessageInput/icons.js +0 -3
  39. package/dist/components/MessageInput/types.d.ts +3 -30
  40. package/dist/components/MessageList/MessageList.d.ts +3 -1
  41. package/dist/components/MessageList/MessageList.js +2 -1
  42. package/dist/components/MessageList/VirtualizedMessageList.d.ts +3 -1
  43. package/dist/components/MessageList/VirtualizedMessageList.js +3 -3
  44. package/dist/components/MessageList/VirtualizedMessageListComponents.js +3 -2
  45. package/dist/components/MessageList/hooks/MessageList/useEnrichedMessages.d.ts +2 -1
  46. package/dist/components/MessageList/hooks/MessageList/useEnrichedMessages.js +3 -3
  47. package/dist/components/MessageList/utils.d.ts +1 -1
  48. package/dist/components/MessageList/utils.js +16 -6
  49. package/dist/components/ReactFileUtilities/types.d.ts +0 -29
  50. package/dist/components/ReactFileUtilities/utils.d.ts +2 -0
  51. package/dist/components/ReactFileUtilities/utils.js +2 -0
  52. package/dist/context/ChannelActionContext.d.ts +2 -2
  53. package/dist/context/MessageInputContext.d.ts +1 -5
  54. package/dist/i18n/Streami18n.d.ts +2 -0
  55. package/dist/i18n/de.json +3 -1
  56. package/dist/i18n/en.json +3 -1
  57. package/dist/i18n/es.json +3 -1
  58. package/dist/i18n/fr.json +3 -1
  59. package/dist/i18n/hi.json +3 -1
  60. package/dist/i18n/it.json +3 -1
  61. package/dist/i18n/ja.json +3 -1
  62. package/dist/i18n/ko.json +3 -1
  63. package/dist/i18n/nl.json +3 -1
  64. package/dist/i18n/pt.json +3 -1
  65. package/dist/i18n/ru.json +3 -1
  66. package/dist/i18n/tr.json +3 -1
  67. package/dist/i18n/utils.d.ts +3 -3
  68. package/dist/index.cjs.js +1987 -12143
  69. package/dist/index.cjs.js.map +4 -4
  70. package/dist/{components → plugins}/Emojis/EmojiPicker.js +1 -1
  71. package/dist/plugins/Emojis/icons.d.ts +2 -0
  72. package/dist/plugins/Emojis/icons.js +4 -0
  73. package/dist/{components → plugins}/Emojis/index.cjs.js +23 -22
  74. package/dist/plugins/Emojis/index.cjs.js.map +7 -0
  75. package/dist/plugins/Emojis/index.d.ts +2 -0
  76. package/dist/plugins/Emojis/index.js +2 -0
  77. package/dist/plugins/encoders/mp3.cjs.js +111 -0
  78. package/dist/plugins/encoders/mp3.cjs.js.map +7 -0
  79. package/dist/{components/MediaRecorder/transcode → plugins/encoders}/mp3.js +3 -3
  80. package/package.json +16 -6
  81. package/dist/components/Emojis/index.cjs.js.map +0 -7
  82. package/dist/components/Emojis/index.d.ts +0 -1
  83. package/dist/components/Emojis/index.js +0 -1
  84. package/dist/components/MessageInput/AttachmentPreviewList/UploadPreviewItem.d.ts +0 -11
  85. package/dist/components/MessageInput/AttachmentPreviewList/UploadPreviewItem.js +0 -51
  86. package/dist/components/MessageInput/hooks/useFileUploads.d.ts +0 -7
  87. package/dist/components/MessageInput/hooks/useFileUploads.js +0 -85
  88. package/dist/components/MessageInput/hooks/useImageUploads.d.ts +0 -8
  89. package/dist/components/MessageInput/hooks/useImageUploads.js +0 -94
  90. /package/dist/{components → plugins}/Emojis/EmojiPicker.d.ts +0 -0
  91. /package/dist/{components/MediaRecorder/transcode → plugins/encoders}/mp3.d.ts +0 -0
@@ -1,4 +1,3 @@
1
- import type { ImageUpload } from '../../ReactFileUtilities';
2
1
  import type { UserResponse } from 'stream-chat';
3
2
  import type { ChannelActionContextValue } from '../../../context/ChannelActionContext';
4
3
  import type { ChatContextValue } from '../../../context/ChatContext';
@@ -19,7 +18,7 @@ export type SearchLocalUserParams<StreamChatGenerics extends DefaultStreamChatGe
19
18
  export declare const searchLocalUsers: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(params: SearchLocalUserParams<StreamChatGenerics>) => UserResponse<StreamChatGenerics>[];
20
19
  type CheckUploadPermissionsParams<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = {
21
20
  addNotification: ChannelActionContextValue<StreamChatGenerics>['addNotification'];
22
- file: ImageUpload['file'];
21
+ file: File;
23
22
  getAppSettings: ChatContextValue<StreamChatGenerics>['getAppSettings'];
24
23
  t: TranslationContextValue['t'];
25
24
  uploadType: 'image' | 'file';
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- export declare const EmojiPickerIcon: () => React.JSX.Element;
3
2
  export declare const LoadingIndicatorIcon: ({ size }: {
4
3
  size?: number;
5
4
  }) => React.JSX.Element;
@@ -1,9 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { nanoid } from 'nanoid';
3
3
  import { useTranslationContext } from '../../context/TranslationContext';
4
- export const EmojiPickerIcon = () => (React.createElement("svg", { preserveAspectRatio: 'xMinYMin', viewBox: '0 0 28 28', width: '100%', xmlns: 'http://www.w3.org/2000/svg' },
5
- React.createElement("g", { clipRule: 'evenodd', fillRule: 'evenodd' },
6
- React.createElement("path", { d: 'M14 4.4C8.6 4.4 4.4 8.6 4.4 14c0 5.4 4.2 9.6 9.6 9.6c5.4 0 9.6-4.2 9.6-9.6c0-5.4-4.2-9.6-9.6-9.6zM2 14c0-6.6 5.4-12 12-12s12 5.4 12 12s-5.4 12-12 12s-12-5.4-12-12zM12.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM18.8 11c0 1-.8 1.8-1.8 1.8s-1.8-.8-1.8-1.8s.8-1.8 1.8-1.8s1.8.8 1.8 1.8zM8.6 15.4c.6-.4 1.2-.2 1.6.2c.6.8 1.6 1.8 3 2c1.2.4 2.8.2 4.8-2c.4-.4 1.2-.6 1.6 0c.4.4.6 1.2 0 1.6c-2.2 2.6-4.8 3.4-7 3c-2-.4-3.6-1.8-4.4-3c-.4-.6-.2-1.2.4-1.8z' }))));
7
4
  export const LoadingIndicatorIcon = ({ size = 20 }) => {
8
5
  const id = useMemo(() => nanoid(), []);
9
6
  return (React.createElement("div", { className: 'str-chat__loading-indicator' },
@@ -1,36 +1,6 @@
1
1
  import type { Attachment, DefaultGenerics, ExtendableGenerics, OGAttachment } from 'stream-chat';
2
2
  import type { DefaultStreamChatGenerics } from '../../types/types';
3
3
  export type AttachmentLoadingState = 'uploading' | 'finished' | 'failed';
4
- export type FileUpload = {
5
- file: {
6
- name: string;
7
- lastModified?: number;
8
- lastModifiedDate?: Date;
9
- size?: number;
10
- type?: string;
11
- uri?: string;
12
- };
13
- id: string;
14
- state: AttachmentLoadingState;
15
- thumb_url?: string;
16
- url?: string;
17
- };
18
- export type ImageUpload<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = {
19
- file: {
20
- name: string;
21
- height?: number;
22
- lastModified?: number;
23
- lastModifiedDate?: Date;
24
- size?: number;
25
- type?: string;
26
- uri?: string;
27
- width?: number;
28
- };
29
- id: string;
30
- state: AttachmentLoadingState;
31
- previewUri?: string;
32
- url?: string;
33
- } & Pick<Attachment<StreamChatGenerics>, 'og_scrape_url' | 'title' | 'title_link' | 'author_name' | 'text'>;
34
4
  export declare enum LinkPreviewState {
35
5
  /** Link preview has been dismissed using MessageInputContextValue.dismissLinkPreview **/
36
6
  DISMISSED = "dismissed",
@@ -111,4 +81,7 @@ export type LocalImageAttachment<StreamChatGenerics extends DefaultStreamChatGen
111
81
  export type LocalFileAttachment<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, CustomLocalMetadata = Record<string, unknown>> = LocalAttachmentCast<FileAttachment<StreamChatGenerics>, LocalAttachmentUploadMetadata & CustomLocalMetadata>;
112
82
  export type AnyLocalAttachment<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, CustomLocalMetadata = Record<string, unknown>> = LocalAttachmentCast<Attachment<StreamChatGenerics>, LocalAttachmentMetadata<CustomLocalMetadata>>;
113
83
  export type LocalAttachment<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics> = AnyLocalAttachment<StreamChatGenerics> | LocalFileAttachment<StreamChatGenerics> | LocalImageAttachment<StreamChatGenerics> | LocalAudioAttachment<StreamChatGenerics> | LocalVideoAttachment<StreamChatGenerics> | LocalVoiceRecordingAttachment<StreamChatGenerics>;
84
+ export type LocalAttachmentToUpload<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, CustomLocalMetadata = Record<string, unknown>> = Partial<Attachment<StreamChatGenerics>> & {
85
+ localMetadata: Partial<BaseLocalAttachmentMetadata> & LocalAttachmentUploadMetadata & CustomLocalMetadata;
86
+ };
114
87
  export {};
@@ -11,7 +11,7 @@ export type MessageListProps<StreamChatGenerics extends DefaultStreamChatGeneric
11
11
  /** Disables the injection of date separator components in MessageList, defaults to `false` */
12
12
  disableDateSeparator?: boolean;
13
13
  /** Callback function to set group styles for each message */
14
- groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean) => GroupStyle;
14
+ groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean, maxTimeBetweenGroupedMessages?: number) => GroupStyle;
15
15
  /** Whether the list has more items to load */
16
16
  hasMore?: boolean;
17
17
  /** Element to be rendered at the top of the thread message list. By default, these are the Message and ThreadStart components */
@@ -34,6 +34,8 @@ export type MessageListProps<StreamChatGenerics extends DefaultStreamChatGeneric
34
34
  loadMore?: ChannelActionContextValue['loadMore'] | (() => Promise<void>);
35
35
  /** Function called when newer messages are to be loaded, defaults to function stored in [ChannelActionContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_action_context/) */
36
36
  loadMoreNewer?: ChannelActionContextValue['loadMoreNewer'] | (() => Promise<void>);
37
+ /** Maximum time in milliseconds that should occur between messages to still consider them grouped together */
38
+ maxTimeBetweenGroupedMessages?: number;
37
39
  /** The limit to use when paginating messages */
38
40
  messageLimit?: number;
39
41
  /** The messages to render in the list, defaults to messages stored in [ChannelStateContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_state_context/) */
@@ -19,7 +19,7 @@ import { MessageListMainPanel } from './MessageListMainPanel';
19
19
  import { defaultRenderMessages } from './renderMessages';
20
20
  import { DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, } from '../../constants/limits';
21
21
  const MessageListWithContext = (props) => {
22
- const { channel, channelUnreadUiState, disableDateSeparator = false, groupStyles, hideDeletedMessages = false, hideNewMessageSeparator = false, internalInfiniteScrollProps: { threshold: loadMoreScrollThreshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ...restInternalInfiniteScrollProps } = {}, messageActions = Object.keys(MESSAGE_ACTIONS), messages = [], notifications, noGroupByUser = false, pinPermissions = defaultPinPermissions, // @deprecated in favor of `channelCapabilities` - TODO: remove in next major release
22
+ const { channel, channelUnreadUiState, disableDateSeparator = false, groupStyles, hideDeletedMessages = false, hideNewMessageSeparator = false, internalInfiniteScrollProps: { threshold: loadMoreScrollThreshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ...restInternalInfiniteScrollProps } = {}, maxTimeBetweenGroupedMessages, messageActions = Object.keys(MESSAGE_ACTIONS), messages = [], notifications, noGroupByUser = false, pinPermissions = defaultPinPermissions, // @deprecated in favor of `channelCapabilities` - TODO: remove in next major release
23
23
  returnAllReadData = false, threadList = false, unsafeHTML = false, headerPosition, read, renderMessages = defaultRenderMessages, reviewProcessedMessage, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, loadMore: loadMoreCallback, loadMoreNewer: loadMoreNewerCallback, hasMoreNewer = false, reactionDetailsSort, showUnreadNotificationAlways, sortReactionDetails, sortReactions, suppressAutoscroll, highlightedMessageId, jumpToLatestMessage = () => Promise.resolve(), } = props;
24
24
  const [listElement, setListElement] = React.useState(null);
25
25
  const [ulElement, setUlElement] = React.useState(null);
@@ -51,6 +51,7 @@ const MessageListWithContext = (props) => {
51
51
  headerPosition,
52
52
  hideDeletedMessages,
53
53
  hideNewMessageSeparator,
54
+ maxTimeBetweenGroupedMessages,
54
55
  messages,
55
56
  noGroupByUser,
56
57
  reviewProcessedMessage,
@@ -51,7 +51,7 @@ export type VirtualizedMessageListProps<StreamChatGenerics extends DefaultStream
51
51
  /** Disables the injection of date separator components in MessageList, defaults to `true` */
52
52
  disableDateSeparator?: boolean;
53
53
  /** Callback function to set group styles for each message */
54
- groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean) => GroupStyle;
54
+ groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean, maxTimeBetweenGroupedMessages?: number) => GroupStyle;
55
55
  /** Whether or not the list has more items to load */
56
56
  hasMore?: boolean;
57
57
  /** Whether or not the list has newer items to load */
@@ -75,6 +75,8 @@ export type VirtualizedMessageListProps<StreamChatGenerics extends DefaultStream
75
75
  loadMore?: ChannelActionContextValue['loadMore'] | (() => Promise<void>);
76
76
  /** Function called when new messages are to be loaded, defaults to function stored in [ChannelActionContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_action_context/) */
77
77
  loadMoreNewer?: ChannelActionContextValue['loadMore'] | (() => Promise<void>);
78
+ /** Maximum time in milliseconds that should occur between messages to still consider them grouped together */
79
+ maxTimeBetweenGroupedMessages?: number;
78
80
  /** Custom UI component to display a message, defaults to and accepts same props as [MessageSimple](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Message/MessageSimple.tsx) */
79
81
  Message?: React.ComponentType<MessageUIComponentProps<StreamChatGenerics>>;
80
82
  /** The limit to use when paginating messages */
@@ -46,7 +46,7 @@ function calculateInitialTopMostItemIndex(messages, highlightedMessageId) {
46
46
  return messages.length - 1;
47
47
  }
48
48
  const VirtualizedMessageListWithContext = (props) => {
49
- const { additionalMessageInputProps, additionalVirtuosoProps = {}, channel, channelUnreadUiState, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, defaultItemHeight, disableDateSeparator = true, formatDate, groupStyles, hasMoreNewer, head, hideDeletedMessages = false, hideNewMessageSeparator = false, highlightedMessageId, jumpToLatestMessage, loadingMore, loadMore, loadMoreNewer, Message: MessageUIComponentFromProps, messageActions, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, messages, notifications,
49
+ const { additionalMessageInputProps, additionalVirtuosoProps = {}, channel, channelUnreadUiState, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, defaultItemHeight, disableDateSeparator = true, formatDate, groupStyles, hasMoreNewer, head, hideDeletedMessages = false, hideNewMessageSeparator = false, highlightedMessageId, jumpToLatestMessage, loadingMore, loadMore, loadMoreNewer, maxTimeBetweenGroupedMessages, Message: MessageUIComponentFromProps, messageActions, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, messages, notifications,
50
50
  // TODO: refactor to scrollSeekPlaceHolderConfiguration and components.ScrollSeekPlaceholder, like the Virtuoso Component
51
51
  overscan = 0, read, returnAllReadData = false, reviewProcessedMessage, scrollSeekPlaceHolder, scrollToLatestMessageOnFocus = false, separateGiphyPreview = false, shouldGroupByUser = false, showUnreadNotificationAlways, reactionDetailsSort, sortReactionDetails, sortReactions, stickToBottomScrollBehavior = 'smooth', suppressAutoscroll, threadList, } = props;
52
52
  const { components: virtuosoComponentsFromProps, ...overridingVirtuosoProps } = additionalVirtuosoProps;
@@ -106,14 +106,14 @@ const VirtualizedMessageListWithContext = (props) => {
106
106
  ]);
107
107
  const groupStylesFn = groupStyles || getGroupStyles;
108
108
  const messageGroupStyles = useMemo(() => processedMessages.reduce((acc, message, i) => {
109
- const style = groupStylesFn(message, processedMessages[i - 1], processedMessages[i + 1], !shouldGroupByUser);
109
+ const style = groupStylesFn(message, processedMessages[i - 1], processedMessages[i + 1], !shouldGroupByUser, maxTimeBetweenGroupedMessages);
110
110
  if (style)
111
111
  acc[message.id] = style;
112
112
  return acc;
113
113
  }, {}),
114
114
  // processedMessages were incorrectly rebuilt with a new object identity at some point, hence the .length usage
115
115
  // eslint-disable-next-line react-hooks/exhaustive-deps
116
- [processedMessages.length, shouldGroupByUser, groupStylesFn]);
116
+ [maxTimeBetweenGroupedMessages, processedMessages.length, shouldGroupByUser, groupStylesFn]);
117
117
  const { atBottom, isMessageListScrolledToBottom, newMessagesNotification, setIsMessageListScrolledToBottom, setNewMessagesNotification, } = useNewMessageNotification(processedMessages, client.userID, hasMoreNewer);
118
118
  useMarkRead({
119
119
  isMessageListScrolledToBottom,
@@ -47,7 +47,7 @@ export const EmptyPlaceholder = ({ context, }) => {
47
47
  return (React.createElement(React.Fragment, null, EmptyStateIndicator && (React.createElement(EmptyStateIndicator, { listType: context?.threadList ? 'thread' : 'message' }))));
48
48
  };
49
49
  export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
50
- const { additionalMessageInputProps, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, DateSeparator, firstUnreadMessageId, formatDate, lastReadDate, lastReadMessageId, lastReceivedMessageId, Message: MessageUIComponent, messageActions, MessageSystem, numItemsPrepended, ownMessagesReadByOthers, processedMessages: messageList, reactionDetailsSort, shouldGroupByUser, sortReactionDetails, sortReactions, unreadMessageCount = 0, UnreadMessagesSeparator, virtuosoRef, } = virtuosoContext;
50
+ const { additionalMessageInputProps, closeReactionSelectorOnClick, customMessageActions, customMessageRenderer, DateSeparator, firstUnreadMessageId, formatDate, lastReadDate, lastReadMessageId, lastReceivedMessageId, Message: MessageUIComponent, messageActions, messageGroupStyles, MessageSystem, numItemsPrepended, ownMessagesReadByOthers, processedMessages: messageList, reactionDetailsSort, shouldGroupByUser, sortReactionDetails, sortReactions, unreadMessageCount = 0, UnreadMessagesSeparator, virtuosoRef, } = virtuosoContext;
51
51
  const streamMessageIndex = calculateItemIndex(virtuosoIndex, numItemsPrepended);
52
52
  if (customMessageRenderer) {
53
53
  return customMessageRenderer(messageList, streamMessageIndex);
@@ -66,6 +66,7 @@ export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
66
66
  message.user?.id === messageList[streamMessageIndex - 1].user?.id;
67
67
  const maybePrevMessage = messageList[streamMessageIndex - 1];
68
68
  const maybeNextMessage = messageList[streamMessageIndex + 1];
69
+ // FIXME: firstOfGroup & endOfGroup should be derived from groupStyles which apply a more complex logic
69
70
  const firstOfGroup = shouldGroupByUser &&
70
71
  (message.user?.id !== maybePrevMessage?.user?.id ||
71
72
  (maybePrevMessage && isMessageEdited(maybePrevMessage)));
@@ -88,7 +89,7 @@ export const messageRenderer = (virtuosoIndex, _data, virtuosoContext) => {
88
89
  return (React.createElement(React.Fragment, null,
89
90
  showUnreadSeparatorAbove && (React.createElement("div", { className: 'str-chat__unread-messages-separator-wrapper' },
90
91
  React.createElement(UnreadMessagesSeparator, { unreadCount: unreadMessageCount }))),
91
- React.createElement(Message, { additionalMessageInputProps: additionalMessageInputProps, autoscrollToBottom: virtuosoRef.current?.autoscrollToBottom, closeReactionSelectorOnClick: closeReactionSelectorOnClick, customMessageActions: customMessageActions, endOfGroup: endOfGroup, firstOfGroup: firstOfGroup, formatDate: formatDate, groupedByUser: groupedByUser, lastReceivedId: lastReceivedMessageId, message: message, Message: MessageUIComponent, messageActions: messageActions, reactionDetailsSort: reactionDetailsSort, readBy: ownMessagesReadByOthers[message.id] || [], sortReactionDetails: sortReactionDetails, sortReactions: sortReactions }),
92
+ React.createElement(Message, { additionalMessageInputProps: additionalMessageInputProps, autoscrollToBottom: virtuosoRef.current?.autoscrollToBottom, closeReactionSelectorOnClick: closeReactionSelectorOnClick, customMessageActions: customMessageActions, endOfGroup: endOfGroup, firstOfGroup: firstOfGroup, formatDate: formatDate, groupedByUser: groupedByUser, groupStyles: [messageGroupStyles[message.id] ?? ''], lastReceivedId: lastReceivedMessageId, message: message, Message: MessageUIComponent, messageActions: messageActions, reactionDetailsSort: reactionDetailsSort, readBy: ownMessagesReadByOthers[message.id] || [], sortReactionDetails: sortReactionDetails, sortReactions: sortReactions }),
92
93
  showUnreadSeparatorBelow && (React.createElement("div", { className: 'str-chat__unread-messages-separator-wrapper' },
93
94
  React.createElement(UnreadMessagesSeparator, { unreadCount: unreadMessageCount })))));
94
95
  };
@@ -9,8 +9,9 @@ export declare const useEnrichedMessages: <StreamChatGenerics extends DefaultStr
9
9
  hideNewMessageSeparator: boolean;
10
10
  messages: StreamMessage<StreamChatGenerics>[];
11
11
  noGroupByUser: boolean;
12
- groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean) => GroupStyle;
12
+ groupStyles?: (message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean, maxTimeBetweenGroupedMessages?: number) => GroupStyle;
13
13
  headerPosition?: number;
14
+ maxTimeBetweenGroupedMessages?: number;
14
15
  reviewProcessedMessage?: ProcessMessagesParams<StreamChatGenerics>['reviewProcessedMessage'];
15
16
  }) => {
16
17
  messageGroupStyles: Record<string, GroupStyle>;
@@ -3,7 +3,7 @@ import { getGroupStyles, insertIntro, processMessages, } from '../../utils';
3
3
  import { useChatContext } from '../../../../context/ChatContext';
4
4
  import { useComponentContext } from '../../../../context/ComponentContext';
5
5
  export const useEnrichedMessages = (args) => {
6
- const { channel, disableDateSeparator, groupStyles, headerPosition, hideDeletedMessages, hideNewMessageSeparator, messages, noGroupByUser, reviewProcessedMessage, } = args;
6
+ const { channel, disableDateSeparator, groupStyles, headerPosition, hideDeletedMessages, hideNewMessageSeparator, maxTimeBetweenGroupedMessages, messages, noGroupByUser, reviewProcessedMessage, } = args;
7
7
  const { client } = useChatContext('useEnrichedMessages');
8
8
  const { HeaderComponent } = useComponentContext('useEnrichedMessages');
9
9
  const lastRead = useMemo(() => channel.lastRead?.(), [channel]);
@@ -24,12 +24,12 @@ export const useEnrichedMessages = (args) => {
24
24
  }
25
25
  const groupStylesFn = groupStyles || getGroupStyles;
26
26
  const messageGroupStyles = useMemo(() => messagesWithDates.reduce((acc, message, i) => {
27
- const style = groupStylesFn(message, messagesWithDates[i - 1], messagesWithDates[i + 1], noGroupByUser);
27
+ const style = groupStylesFn(message, messagesWithDates[i - 1], messagesWithDates[i + 1], noGroupByUser, maxTimeBetweenGroupedMessages);
28
28
  if (style)
29
29
  acc[message.id] = style;
30
30
  return acc;
31
31
  }, {}),
32
32
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
- [messagesWithDates, noGroupByUser]);
33
+ [maxTimeBetweenGroupedMessages, messagesWithDates, noGroupByUser]);
34
34
  return { messageGroupStyles, messages: messagesWithDates };
35
35
  };
@@ -57,7 +57,7 @@ export declare const getReadStates: <StreamChatGenerics extends DefaultStreamCha
57
57
  }> | undefined, returnAllReadData: boolean) => Record<string, UserResponse<StreamChatGenerics>[]>;
58
58
  export declare const insertIntro: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(messages: StreamMessage<StreamChatGenerics>[], headerPosition?: number) => StreamMessage<StreamChatGenerics>[];
59
59
  export type GroupStyle = '' | 'middle' | 'top' | 'bottom' | 'single';
60
- export declare const getGroupStyles: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean) => GroupStyle;
60
+ export declare const getGroupStyles: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(message: StreamMessage<StreamChatGenerics>, previousMessage: StreamMessage<StreamChatGenerics>, nextMessage: StreamMessage<StreamChatGenerics>, noGroupByUser: boolean, maxTimeBetweenGroupedMessages?: number) => GroupStyle;
61
61
  export declare const hasMoreMessagesProbably: (returnedCountMessages: number, limit: number) => boolean;
62
62
  export declare const hasNotMoreMessages: (returnedCountMessages: number, limit: number) => boolean;
63
63
  type DateSeparatorMessage = {
@@ -179,7 +179,7 @@ export const insertIntro = (messages, headerPosition) => {
179
179
  }
180
180
  return newMessages;
181
181
  };
182
- export const getGroupStyles = (message, previousMessage, nextMessage, noGroupByUser) => {
182
+ export const getGroupStyles = (message, previousMessage, nextMessage, noGroupByUser, maxTimeBetweenGroupedMessages) => {
183
183
  if (message.customType === CUSTOM_MESSAGE_TYPE.date)
184
184
  return '';
185
185
  if (message.customType === CUSTOM_MESSAGE_TYPE.intro)
@@ -190,22 +190,32 @@ export const getGroupStyles = (message, previousMessage, nextMessage, noGroupByU
190
190
  previousMessage.customType === CUSTOM_MESSAGE_TYPE.intro ||
191
191
  previousMessage.customType === CUSTOM_MESSAGE_TYPE.date ||
192
192
  previousMessage.type === 'system' ||
193
+ previousMessage.type === 'error' ||
193
194
  previousMessage.attachments?.length !== 0 ||
194
195
  message.user?.id !== previousMessage.user?.id ||
195
- previousMessage.type === 'error' ||
196
196
  previousMessage.deleted_at ||
197
197
  (message.reaction_groups && Object.keys(message.reaction_groups).length > 0) ||
198
- isMessageEdited(previousMessage);
198
+ isMessageEdited(previousMessage) ||
199
+ (maxTimeBetweenGroupedMessages !== undefined &&
200
+ previousMessage.created_at &&
201
+ message.created_at &&
202
+ new Date(message.created_at).getTime() - new Date(previousMessage.created_at).getTime() >
203
+ maxTimeBetweenGroupedMessages);
199
204
  const isBottomMessage = !nextMessage ||
205
+ nextMessage.customType === CUSTOM_MESSAGE_TYPE.intro ||
200
206
  nextMessage.customType === CUSTOM_MESSAGE_TYPE.date ||
201
207
  nextMessage.type === 'system' ||
202
- nextMessage.customType === CUSTOM_MESSAGE_TYPE.intro ||
208
+ nextMessage.type === 'error' ||
203
209
  nextMessage.attachments?.length !== 0 ||
204
210
  message.user?.id !== nextMessage.user?.id ||
205
- nextMessage.type === 'error' ||
206
211
  nextMessage.deleted_at ||
207
212
  (nextMessage.reaction_groups && Object.keys(nextMessage.reaction_groups).length > 0) ||
208
- isMessageEdited(message);
213
+ isMessageEdited(message) ||
214
+ (maxTimeBetweenGroupedMessages !== undefined &&
215
+ nextMessage.created_at &&
216
+ message.created_at &&
217
+ new Date(nextMessage.created_at).getTime() - new Date(message.created_at).getTime() >
218
+ maxTimeBetweenGroupedMessages);
209
219
  if (!isTopMessage && !isBottomMessage) {
210
220
  if (message.deleted_at || message.type === 'error')
211
221
  return 'single';
@@ -1,31 +1,2 @@
1
1
  export type RecordedMediaType = 'audio' | 'video';
2
- export type UploadState = 'uploading' | 'finished' | 'failed';
3
2
  export type FileLike = Blob | File;
4
- export type UploadInfo = {
5
- id: string;
6
- state: UploadState;
7
- url?: string;
8
- };
9
- export type FileUpload = {
10
- file: {
11
- name: string;
12
- lastModified?: number;
13
- lastModifiedDate?: Date;
14
- size?: number;
15
- type?: string;
16
- uri?: string;
17
- };
18
- } & UploadInfo;
19
- export type ImageUpload = {
20
- file: {
21
- name: string;
22
- height?: number;
23
- lastModified?: number;
24
- lastModifiedDate?: Date;
25
- size?: number;
26
- type?: string;
27
- uri?: string;
28
- width?: number;
29
- };
30
- previewUri?: string;
31
- } & UploadInfo;
@@ -3,6 +3,7 @@ import { ChangeEvent } from 'react';
3
3
  export declare const useHandleFileChangeWrapper: (resetOnChange?: boolean, handler?: (files: Array<File>) => void) => ({ currentTarget }: ChangeEvent<HTMLInputElement>) => void;
4
4
  export declare function dataTransferItemsHaveFiles(items?: DataTransferItem[]): boolean;
5
5
  export declare function dataTransferItemsToFiles(items?: DataTransferItem[]): Promise<FileLike[]>;
6
+ export declare const isBlobButNotFile: (obj: unknown) => obj is Blob;
6
7
  export declare const createFileFromBlobs: ({ blobsArray, fileName, mimeType, }: {
7
8
  blobsArray: Blob[];
8
9
  fileName: string;
@@ -11,3 +12,4 @@ export declare const createFileFromBlobs: ({ blobsArray, fileName, mimeType, }:
11
12
  export declare const getExtensionFromMimeType: (mimeType: string) => string | null;
12
13
  export declare const getRecordedMediaTypeFromMimeType: (mimeType: string) => RecordedMediaType | null;
13
14
  export declare const readFileAsArrayBuffer: (file: File) => Promise<ArrayBuffer>;
15
+ export declare const generateFileName: (mimeType: string) => string;
@@ -77,6 +77,7 @@ const extractImageSources = (s) => {
77
77
  const imageTags = new DOMParser().parseFromString(s, 'text/html').getElementsByTagName('img');
78
78
  return Array.from(imageTags, (tag) => tag.src).filter((tag) => tag);
79
79
  };
80
+ export const isBlobButNotFile = (obj) => obj instanceof Blob && !(obj instanceof File);
80
81
  export const createFileFromBlobs = ({ blobsArray, fileName, mimeType, }) => {
81
82
  const concatenatedBlob = new Blob(blobsArray, { type: mimeType });
82
83
  return new File([concatenatedBlob], fileName, { type: concatenatedBlob.type });
@@ -99,3 +100,4 @@ export const readFileAsArrayBuffer = (file) => new Promise((resolve, reject) =>
99
100
  };
100
101
  fileReader.readAsArrayBuffer(file);
101
102
  });
103
+ export const generateFileName = (mimeType) => `file_${new Date().toISOString()}.${getExtensionFromMimeType(mimeType)}`;
@@ -31,9 +31,9 @@ export type ChannelActionContextValue<StreamChatGenerics extends DefaultStreamCh
31
31
  deleteMessage: (message: StreamMessage<StreamChatGenerics>) => Promise<MessageResponse<StreamChatGenerics>>;
32
32
  dispatch: React.Dispatch<ChannelStateReducerAction<StreamChatGenerics>>;
33
33
  editMessage: (message: UpdatedMessage<StreamChatGenerics>, options?: UpdateMessageOptions) => Promise<UpdateMessageAPIResponse<StreamChatGenerics> | void>;
34
- jumpToFirstUnreadMessage: (queryMessageLimit?: number) => Promise<void>;
34
+ jumpToFirstUnreadMessage: (queryMessageLimit?: number, highlightDuration?: number) => Promise<void>;
35
35
  jumpToLatestMessage: () => Promise<void>;
36
- jumpToMessage: (messageId: string, limit?: number) => Promise<void>;
36
+ jumpToMessage: (messageId: string, limit?: number, highlightDuration?: number) => Promise<void>;
37
37
  loadMore: (limit?: number) => Promise<number>;
38
38
  loadMoreNewer: (limit?: number) => Promise<number>;
39
39
  loadMoreThread: () => Promise<void>;
@@ -17,14 +17,10 @@ export declare const MessageInputContext: React.Context<(MessageInputState & imp
17
17
  onSelectUser: (item: import("stream-chat").UserResponse<DefaultStreamChatGenerics>) => void;
18
18
  recordingController: import("..").RecordingController<DefaultStreamChatGenerics>;
19
19
  removeAttachments: (ids: string[]) => void;
20
- removeFile: (id: string) => void;
21
- removeImage: (id: string) => void;
22
20
  textareaRef: React.MutableRefObject<HTMLTextAreaElement | null | undefined>;
23
21
  uploadAttachment: (attachment: import("../components/MessageInput").LocalAttachment<DefaultStreamChatGenerics>) => Promise<import("../components/MessageInput").LocalAttachment<DefaultStreamChatGenerics> | undefined>;
24
- uploadFile: (id: string) => void;
25
- uploadImage: (id: string) => void;
26
22
  uploadNewFiles: (files: FileList | File[]) => void;
27
- upsertAttachments: (attachments: (import("stream-chat").Attachment<DefaultStreamChatGenerics> | import("../components/MessageInput").LocalAttachment<DefaultStreamChatGenerics>)[]) => void;
23
+ upsertAttachments: (attachments: (import("../components/MessageInput").LocalAttachment<DefaultStreamChatGenerics> | import("stream-chat").Attachment<DefaultStreamChatGenerics>)[]) => void;
28
24
  }) | undefined>;
29
25
  export declare const MessageInputContextProvider: <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, V extends CustomTrigger = CustomTrigger>({ children, value, }: PropsWithChildren<{
30
26
  value: MessageInputContextValue<StreamChatGenerics, V>;
@@ -145,6 +145,7 @@ export declare class Streami18n {
145
145
  "Connection failure, reconnecting now...": string;
146
146
  Delete: string;
147
147
  Delivered: string;
148
+ "Download attachment {{ name }}": string;
148
149
  "Drag your files here": string;
149
150
  "Drag your files here to add to your post": string;
150
151
  "Edit Message": string;
@@ -229,6 +230,7 @@ export declare class Streami18n {
229
230
  "aria/Channel list": string;
230
231
  "aria/Channel search results": string;
231
232
  "aria/Close thread": string;
233
+ "aria/Download attachment": string;
232
234
  "aria/Emoji picker": string;
233
235
  "aria/File input": string;
234
236
  "aria/File upload": string;
package/dist/i18n/de.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "Verbindungsfehler, Wiederherstellung der Verbindung...",
14
14
  "Delete": "Löschen",
15
15
  "Delivered": "Zugestellt",
16
+ "Download attachment {{ name }}": "Anhang {{ name }} herunterladen",
16
17
  "Drag your files here": "Ziehen Sie Ihre Dateien hierher",
17
18
  "Drag your files here to add to your post": "Ziehen Sie Ihre Dateien hierher, um sie Ihrem Beitrag hinzuzufügen",
18
19
  "Edit Message": "Nachricht bearbeiten",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "Kanalliste",
98
99
  "aria/Channel search results": "Kanalsuchergebnisse",
99
100
  "aria/Close thread": "Thread schließen",
101
+ "aria/Download attachment": "Anhang herunterladen",
100
102
  "aria/Emoji picker": "Emoji-Auswahl",
101
103
  "aria/File input": "Dateieingabe",
102
104
  "aria/File upload": "Datei hochladen",
@@ -124,7 +126,7 @@
124
126
  "searchResultsCount_other": "{{ count }} Ergebnisse",
125
127
  "this content could not be displayed": "Dieser Inhalt konnte nicht angezeigt werden",
126
128
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
127
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
129
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
128
130
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
129
131
  "unban-command-args": "[@Benutzername]",
130
132
  "unban-command-description": "Einen Benutzer entbannen",
package/dist/i18n/en.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "Connection failure, reconnecting now...",
14
14
  "Delete": "Delete",
15
15
  "Delivered": "Delivered",
16
+ "Download attachment {{ name }}": "Download attachment {{ name }}",
16
17
  "Drag your files here": "Drag your files here",
17
18
  "Drag your files here to add to your post": "Drag your files here to add to your post",
18
19
  "Edit Message": "Edit Message",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "Channel list",
98
99
  "aria/Channel search results": "Channel search results",
99
100
  "aria/Close thread": "Close thread",
101
+ "aria/Download attachment": "aria/Download attachment",
100
102
  "aria/Emoji picker": "Emoji picker",
101
103
  "aria/File input": "File input",
102
104
  "aria/File upload": "File upload",
@@ -118,7 +120,7 @@
118
120
  "searchResultsCount_other": "{{ count }} results",
119
121
  "this content could not be displayed": "this content could not be displayed",
120
122
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
121
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
123
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
122
124
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
123
125
  "unreadMessagesSeparatorText_one": "1 unread message",
124
126
  "unreadMessagesSeparatorText_other": "{{count}} unread messages",
package/dist/i18n/es.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "Fallo de conexión, reconectando ahora ...",
14
14
  "Delete": "Borrar",
15
15
  "Delivered": "Entregado",
16
+ "Download attachment {{ name }}": "Descargar adjunto {{ name }}",
16
17
  "Drag your files here": "Arrastra tus archivos aquí",
17
18
  "Drag your files here to add to your post": "Arrastra tus archivos aquí para agregarlos a tu publicación",
18
19
  "Edit Message": "Editar mensaje",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "Lista de canales",
98
99
  "aria/Channel search results": "Resultados de búsqueda de canales",
99
100
  "aria/Close thread": "Cerrar hilo",
101
+ "aria/Download attachment": "Descargar adjunto",
100
102
  "aria/Emoji picker": "Selector de emojis",
101
103
  "aria/File input": "Entrada de archivo",
102
104
  "aria/File upload": "Carga de archivo",
@@ -126,7 +128,7 @@
126
128
  "searchResultsCount_other": "{{ count }} resultados",
127
129
  "this content could not be displayed": "este contenido no se pudo mostrar",
128
130
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
129
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
131
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
130
132
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
131
133
  "unban-command-args": "[@usuario]",
132
134
  "unban-command-description": "Quitar la prohibición a un usuario",
package/dist/i18n/fr.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "Échec de la connexion, reconnexion en cours...",
14
14
  "Delete": "Supprimer",
15
15
  "Delivered": "Publié",
16
+ "Download attachment {{ name }}": "Télécharger la pièce jointe {{ name }}",
16
17
  "Drag your files here": "Glissez vos fichiers ici",
17
18
  "Drag your files here to add to your post": "Glissez vos fichiers ici pour les ajouter à votre publication",
18
19
  "Edit Message": "Éditer un message",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "Liste des canaux",
98
99
  "aria/Channel search results": "Résultats de la recherche de canaux",
99
100
  "aria/Close thread": "Fermer le fil",
101
+ "aria/Download attachment": "Télécharger la pièce jointe",
100
102
  "aria/Emoji picker": "Sélecteur d'émojis",
101
103
  "aria/File input": "Entrée de fichier",
102
104
  "aria/File upload": "Téléchargement de fichier",
@@ -126,7 +128,7 @@
126
128
  "searchResultsCount_other": "{{ count }} résultats",
127
129
  "this content could not be displayed": "ce contenu n'a pu être affiché",
128
130
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
129
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
131
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
130
132
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
131
133
  "unban-command-args": "[@nomdutilisateur]",
132
134
  "unban-command-description": "Débannir un utilisateur",
package/dist/i18n/hi.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "कनेक्शन विफल रहा, अब पुनः कनेक्ट हो रहा है ...",
14
14
  "Delete": "डिलीट",
15
15
  "Delivered": "पहुंच गया",
16
+ "Download attachment {{ name }}": "अनुलग्नक {{ name }} डाउनलोड करें",
16
17
  "Drag your files here": "अपनी फ़ाइलें यहाँ खींचें",
17
18
  "Drag your files here to add to your post": "अपनी फ़ाइलें यहाँ खींचें और अपने पोस्ट में जोड़ने के लिए",
18
19
  "Edit Message": "मैसेज में बदलाव करे",
@@ -98,6 +99,7 @@
98
99
  "aria/Channel list": "चैनल सूची",
99
100
  "aria/Channel search results": "चैनल खोज परिणाम",
100
101
  "aria/Close thread": "थ्रेड बंद करें",
102
+ "aria/Download attachment": "अनुलग्नक डाउनलोड करें",
101
103
  "aria/Emoji picker": "इमोजी चुनने वाला",
102
104
  "aria/File input": "फ़ाइल इनपुट",
103
105
  "aria/File upload": "फ़ाइल अपलोड",
@@ -125,7 +127,7 @@
125
127
  "searchResultsCount_other": "{{ count }} परिणाम",
126
128
  "this content could not be displayed": "यह कॉन्टेंट लोड नहीं हो पाया",
127
129
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
128
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
130
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
129
131
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
130
132
  "unban-command-args": "[@उपयोगकर्तनाम]",
131
133
  "unban-command-description": "एक उपयोगकर्ता को प्रतिषेध से मुक्त करें",
package/dist/i18n/it.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "Connessione fallitta, riconnessione in corso...",
14
14
  "Delete": "Cancella",
15
15
  "Delivered": "Consegnato",
16
+ "Download attachment {{ name }}": "Scarica l'allegato {{ name }}",
16
17
  "Drag your files here": "Trascina i tuoi file qui",
17
18
  "Drag your files here to add to your post": "Trascina i tuoi file qui per aggiungerli al tuo post",
18
19
  "Edit Message": "Modifica messaggio",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "Elenco dei canali",
98
99
  "aria/Channel search results": "Risultati della ricerca dei canali",
99
100
  "aria/Close thread": "Chiudi discussione",
101
+ "aria/Download attachment": "Scarica l'allegato",
100
102
  "aria/Emoji picker": "Selettore di emoji",
101
103
  "aria/File input": "Input di file",
102
104
  "aria/File upload": "Caricamento di file",
@@ -126,7 +128,7 @@
126
128
  "searchResultsCount_other": "{{ count }} risultati",
127
129
  "this content could not be displayed": "questo contenuto non puó essere mostrato",
128
130
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
129
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
131
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
130
132
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
131
133
  "unban-command-args": "[@nomeutente]",
132
134
  "unban-command-description": "Togliere il divieto a un utente",
package/dist/i18n/ja.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "接続が失敗しました。再接続中...",
14
14
  "Delete": "消去",
15
15
  "Delivered": "配信しました",
16
+ "Download attachment {{ name }}": "添付ファイル {{ name }} をダウンロード",
16
17
  "Drag your files here": "ここにファイルをドラッグ",
17
18
  "Drag your files here to add to your post": "投稿に追加するためにここにファイルをドラッグ",
18
19
  "Edit Message": "メッセージを編集",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "チャンネル一覧",
98
99
  "aria/Channel search results": "チャンネル検索結果",
99
100
  "aria/Close thread": "スレッドを閉じる",
101
+ "aria/Download attachment": "添付ファイルをダウンロード",
100
102
  "aria/Emoji picker": "絵文字ピッカー",
101
103
  "aria/File input": "ファイル入力",
102
104
  "aria/File upload": "ファイルアップロード",
@@ -124,7 +126,7 @@
124
126
  "searchResultsCount_other": "{{ count }}件の結果",
125
127
  "this content could not be displayed": "このコンテンツは表示できませんでした",
126
128
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
127
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
129
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
128
130
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
129
131
  "unban-command-args": "[@ユーザ名]",
130
132
  "unban-command-description": "ユーザーの禁止を解除する",
package/dist/i18n/ko.json CHANGED
@@ -13,6 +13,7 @@
13
13
  "Connection failure, reconnecting now...": "연결 실패, 지금 다시 연결 중...",
14
14
  "Delete": "삭제",
15
15
  "Delivered": "배달됨",
16
+ "Download attachment {{ name }}": "첨부 파일 {{ name }} 다운로드",
16
17
  "Drag your files here": "여기로 파일을 끌어다 놓으세요",
17
18
  "Drag your files here to add to your post": "게시물에 추가하려면 파일을 여기로 끌어다 놓으세요",
18
19
  "Edit Message": "메시지 수정",
@@ -97,6 +98,7 @@
97
98
  "aria/Channel list": "채널 목록",
98
99
  "aria/Channel search results": "채널 검색 결과",
99
100
  "aria/Close thread": "스레드 닫기",
101
+ "aria/Download attachment": "첨부 파일 다운로드",
100
102
  "aria/Emoji picker": "이모지 선택기",
101
103
  "aria/File input": "파일 입력",
102
104
  "aria/File upload": "파일 업로드",
@@ -124,7 +126,7 @@
124
126
  "searchResultsCount_other": "{{ count }}개 결과",
125
127
  "this content could not be displayed": "이 콘텐츠를 표시할 수 없습니다",
126
128
  "timestamp/DateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}",
127
- "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true; format: h:mmA) }}",
129
+ "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}",
128
130
  "timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: dddd L) }}",
129
131
  "unban-command-args": "[@사용자이름]",
130
132
  "unban-command-description": "사용자 차단 해제",