stream-chat-react 14.0.0-beta.1 → 14.0.0-beta.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.
- package/dist/{WithAudioPlayback-TERIQpZ6.js → cjs/WithAudioPlayback.4a84360f.js} +100 -12
- package/dist/cjs/WithAudioPlayback.4a84360f.js.map +1 -0
- package/dist/{audioProcessing-BbOs2wMd.js → cjs/audioProcessing.56e5db9d.js} +1 -1
- package/dist/cjs/audioProcessing.56e5db9d.js.map +1 -0
- package/dist/cjs/emojis.js +1 -1
- package/dist/cjs/index.js +1366 -1037
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mp3-encoder.js +1 -1
- package/dist/css/index.css +232 -62
- package/dist/css/index.css.map +1 -1
- package/dist/{WithAudioPlayback-BcKZ5Lbh.mjs → es/WithAudioPlayback.a3d5a2fc.mjs} +348 -260
- package/dist/es/WithAudioPlayback.a3d5a2fc.mjs.map +1 -0
- package/dist/{audioProcessing-ByEVSjGG.mjs → es/audioProcessing.21cb49e1.mjs} +1 -1
- package/dist/es/audioProcessing.21cb49e1.mjs.map +1 -0
- package/dist/es/emojis.mjs +1 -1
- package/dist/es/index.mjs +1500 -1171
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/mp3-encoder.mjs +1 -1
- package/dist/types/components/Attachment/Giphy.d.ts.map +1 -1
- package/dist/types/components/Attachment/VoiceRecording.d.ts.map +1 -1
- package/dist/types/components/AudioPlayback/AudioPlayer.d.ts.map +1 -1
- package/dist/types/components/Badge/Badge.d.ts +1 -0
- package/dist/types/components/Badge/Badge.d.ts.map +1 -1
- package/dist/types/components/BaseImage/toBaseImageDescriptors.d.ts +1 -1
- package/dist/types/components/BaseImage/toBaseImageDescriptors.d.ts.map +1 -1
- package/dist/types/components/Channel/Channel.d.ts.map +1 -1
- package/dist/types/components/Channel/utils.d.ts +7 -1
- package/dist/types/components/Channel/utils.d.ts.map +1 -1
- package/dist/types/components/ChannelList/hooks/useMobileNavigation.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.d.ts +3 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts +6 -3
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts.map +1 -1
- package/dist/types/components/Chat/hooks/useSplitActionSet.d.ts +5 -0
- package/dist/types/components/Chat/hooks/useSplitActionSet.d.ts.map +1 -1
- package/dist/types/components/ChatView/ChatView.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts +119 -3
- package/dist/types/components/Dialog/components/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/Dialog/hooks/useDialog.d.ts +1 -1
- package/dist/types/components/Dialog/hooks/useDialog.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogAnchor.d.ts +14 -1
- package/dist/types/components/Dialog/service/DialogAnchor.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogManager.d.ts +14 -3
- package/dist/types/components/Dialog/service/DialogManager.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogPortal.d.ts.map +1 -1
- package/dist/types/components/Gallery/Gallery.d.ts.map +1 -1
- package/dist/types/components/Gallery/GalleryContext.d.ts +1 -1
- package/dist/types/components/Gallery/GalleryContext.d.ts.map +1 -1
- package/dist/types/components/Icons/icons.d.ts +4 -0
- package/dist/types/components/Icons/icons.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecorderRecordingControls.d.ts.map +1 -1
- package/dist/types/components/Message/MessageErrorText.d.ts +0 -5
- package/dist/types/components/Message/MessageErrorText.d.ts.map +1 -1
- package/dist/types/components/Message/MessageText.d.ts.map +1 -1
- package/dist/types/components/Message/MessageUI.d.ts.map +1 -1
- package/dist/types/components/Message/hooks/useDeleteHandler.d.ts.map +1 -1
- package/dist/types/components/Message/index.d.ts +0 -1
- package/dist/types/components/Message/index.d.ts.map +1 -1
- package/dist/types/components/Message/utils.d.ts +1 -0
- package/dist/types/components/Message/utils.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.d.ts +14 -3
- package/dist/types/components/MessageActions/MessageActions.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.defaults.d.ts +1 -1
- package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
- package/dist/types/components/MessageActions/QuickMessageActionButton.d.ts.map +1 -1
- package/dist/types/components/MessageActions/hooks/useBaseMessageActionSetFilter.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/AttachmentPreviewList.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/ImageAttachmentPreview.d.ts +3 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/ImageAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/MediaAttachmentPreview.d.ts +4 -2
- package/dist/types/components/MessageComposer/AttachmentPreviewList/MediaAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/utils/AttachmentPreviewRoot.d.ts +6 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/utils/AttachmentPreviewRoot.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts +9 -2
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/CommandChip.d.ts +5 -1
- package/dist/types/components/MessageComposer/CommandChip.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/MessageComposerUI.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/MessageList/useScrollLocationLogic.d.ts +18 -0
- package/dist/types/components/MessageList/hooks/MessageList/useScrollLocationLogic.d.ts.map +1 -1
- package/dist/types/components/Notifications/Notification.d.ts.map +1 -1
- package/dist/types/components/Notifications/hooks/useNotificationTarget.d.ts +1 -1
- package/dist/types/components/Notifications/hooks/useNotificationTarget.d.ts.map +1 -1
- package/dist/types/components/Notifications/notificationTarget.d.ts +1 -1
- package/dist/types/components/Notifications/notificationTarget.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/PollResults/PollOptionWithVotes.d.ts.map +1 -1
- package/dist/types/components/Poll/PollOptionSelector.d.ts.map +1 -1
- package/dist/types/components/Reactions/MessageReactions.d.ts.map +1 -1
- package/dist/types/components/Reactions/MessageReactionsDetail.d.ts +1 -0
- package/dist/types/components/Reactions/MessageReactionsDetail.d.ts.map +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/SuggestionList/SuggestionList.d.ts.map +1 -1
- package/dist/types/components/TextareaComposer/TextareaComposer.d.ts +1 -2
- package/dist/types/components/TextareaComposer/TextareaComposer.d.ts.map +1 -1
- package/dist/types/context/ChannelListContext.d.ts +1 -1
- package/dist/types/context/ChannelListContext.d.ts.map +1 -1
- package/dist/types/context/ComponentContext.d.ts +10 -3
- package/dist/types/context/ComponentContext.d.ts.map +1 -1
- package/dist/types/context/DialogManagerContext.d.ts +11 -7
- package/dist/types/context/DialogManagerContext.d.ts.map +1 -1
- package/dist/types/i18n/Streami18n.d.ts +11 -6
- package/dist/types/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +13 -41
- package/dist/WithAudioPlayback-BcKZ5Lbh.mjs.map +0 -1
- package/dist/WithAudioPlayback-TERIQpZ6.js.map +0 -1
- package/dist/audioProcessing-BbOs2wMd.js.map +0 -1
- package/dist/audioProcessing-ByEVSjGG.mjs.map +0 -1
- package/dist/types/components/Message/icons.d.ts +0 -7
- package/dist/types/components/Message/icons.d.ts.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -4,8 +4,8 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const clsx = require("clsx");
|
|
5
5
|
const nanoid = require("nanoid");
|
|
6
6
|
const React = require("react");
|
|
7
|
-
const audioProcessing = require("
|
|
8
|
-
const WithAudioPlayback = require("
|
|
7
|
+
const audioProcessing = require("./audioProcessing.56e5db9d.js");
|
|
8
|
+
const WithAudioPlayback = require("./WithAudioPlayback.4a84360f.js");
|
|
9
9
|
const streamChat = require("stream-chat");
|
|
10
10
|
const throttle = require("lodash.throttle");
|
|
11
11
|
const linkify = require("linkifyjs");
|
|
@@ -19,7 +19,6 @@ const unistUtilVisit = require("unist-util-visit");
|
|
|
19
19
|
const i18n = require("i18next");
|
|
20
20
|
const Dayjs = require("dayjs");
|
|
21
21
|
const uniqBy = require("lodash.uniqby");
|
|
22
|
-
const tsPattern = require("ts-pattern");
|
|
23
22
|
const shim = require("use-sync-external-store/shim");
|
|
24
23
|
const debounce = require("lodash.debounce");
|
|
25
24
|
const fixWebmDuration = require("fix-webm-duration");
|
|
@@ -88,28 +87,12 @@ const useAIState = (channel) => {
|
|
|
88
87
|
}, [channel]);
|
|
89
88
|
return { aiState };
|
|
90
89
|
};
|
|
91
|
-
const ChannelListContext = React.createContext(
|
|
92
|
-
void 0
|
|
93
|
-
);
|
|
94
|
-
const ChannelListContextProvider = ({
|
|
95
|
-
children,
|
|
96
|
-
value
|
|
97
|
-
}) => /* @__PURE__ */ jsxRuntime.jsx(ChannelListContext.Provider, { value, children });
|
|
98
|
-
const useChannelListContext = (componentName) => {
|
|
99
|
-
const contextValue = React.useContext(ChannelListContext);
|
|
100
|
-
if (!contextValue) {
|
|
101
|
-
console.warn(
|
|
102
|
-
`The useChannelListContext hook was called outside of the ChannelListContext provider. Make sure this hook is called within the ChannelList component. The errored call is located in the ${componentName} component.`
|
|
103
|
-
);
|
|
104
|
-
return {};
|
|
105
|
-
}
|
|
106
|
-
return contextValue;
|
|
107
|
-
};
|
|
108
90
|
class DialogManager {
|
|
109
|
-
constructor({ id } = {}) {
|
|
91
|
+
constructor({ closeOnClickOutside = true, id } = {}) {
|
|
110
92
|
this.state = new streamChat.StateStore({
|
|
111
93
|
dialogsById: {}
|
|
112
94
|
});
|
|
95
|
+
this.closeOnClickOutside = closeOnClickOutside;
|
|
113
96
|
this.id = id ?? nanoid.nanoid();
|
|
114
97
|
}
|
|
115
98
|
get openDialogCount() {
|
|
@@ -124,13 +107,14 @@ class DialogManager {
|
|
|
124
107
|
get(id) {
|
|
125
108
|
return this.state.getLatestValue().dialogsById[id];
|
|
126
109
|
}
|
|
127
|
-
getOrCreate({ id }) {
|
|
110
|
+
getOrCreate({ closeOnClickOutside, id }) {
|
|
128
111
|
let dialog = this.state.getLatestValue().dialogsById[id];
|
|
129
112
|
if (!dialog) {
|
|
130
113
|
dialog = {
|
|
131
114
|
close: () => {
|
|
132
115
|
this.close(id);
|
|
133
116
|
},
|
|
117
|
+
closeOnClickOutside,
|
|
134
118
|
id,
|
|
135
119
|
isOpen: false,
|
|
136
120
|
open: () => {
|
|
@@ -146,21 +130,22 @@ class DialogManager {
|
|
|
146
130
|
};
|
|
147
131
|
this.state.next((current) => ({
|
|
148
132
|
...current,
|
|
149
|
-
|
|
133
|
+
dialogsById: { ...current.dialogsById, [id]: dialog }
|
|
150
134
|
}));
|
|
151
135
|
}
|
|
152
|
-
|
|
153
|
-
|
|
136
|
+
const shouldUpdateDialogSettings = dialog.closeOnClickOutside !== closeOnClickOutside || !!dialog.removalTimeout;
|
|
137
|
+
if (shouldUpdateDialogSettings) {
|
|
138
|
+
if (dialog.removalTimeout) clearTimeout(dialog.removalTimeout);
|
|
139
|
+
dialog = {
|
|
140
|
+
...dialog,
|
|
141
|
+
closeOnClickOutside,
|
|
142
|
+
removalTimeout: void 0
|
|
143
|
+
};
|
|
154
144
|
this.state.next((current) => ({
|
|
155
145
|
...current,
|
|
156
|
-
|
|
157
|
-
dialogsById
|
|
158
|
-
|
|
159
|
-
[id]: {
|
|
160
|
-
...dialog,
|
|
161
|
-
removalTimeout: void 0
|
|
162
|
-
}
|
|
163
|
-
}
|
|
146
|
+
dialogsById: {
|
|
147
|
+
...current.dialogsById,
|
|
148
|
+
[id]: dialog
|
|
164
149
|
}
|
|
165
150
|
}));
|
|
166
151
|
}
|
|
@@ -237,7 +222,11 @@ class DialogManager {
|
|
|
237
222
|
}));
|
|
238
223
|
}
|
|
239
224
|
}
|
|
240
|
-
const useDialog = ({
|
|
225
|
+
const useDialog = ({
|
|
226
|
+
closeOnClickOutside,
|
|
227
|
+
dialogManagerId,
|
|
228
|
+
id
|
|
229
|
+
}) => {
|
|
241
230
|
const { dialogManager } = useDialogManager({ dialogManagerId });
|
|
242
231
|
React.useEffect(
|
|
243
232
|
() => () => {
|
|
@@ -245,7 +234,7 @@ const useDialog = ({ dialogManagerId, id }) => {
|
|
|
245
234
|
},
|
|
246
235
|
[dialogManager, id]
|
|
247
236
|
);
|
|
248
|
-
return dialogManager.getOrCreate({ id });
|
|
237
|
+
return dialogManager.getOrCreate({ closeOnClickOutside, id });
|
|
249
238
|
};
|
|
250
239
|
const useDialogOnNearestManager = ({ id }) => {
|
|
251
240
|
const { dialogManager } = useNearestDialogManagerContext() ?? {};
|
|
@@ -292,9 +281,37 @@ const Portal = ({
|
|
|
292
281
|
if (!portalDestination) return null;
|
|
293
282
|
return reactDom.createPortal(children, portalDestination);
|
|
294
283
|
};
|
|
284
|
+
const shouldCloseOnOutsideClick = ({
|
|
285
|
+
dialog,
|
|
286
|
+
managerCloseOnClickOutside
|
|
287
|
+
}) => dialog.closeOnClickOutside ?? managerCloseOnClickOutside;
|
|
295
288
|
const DialogPortalDestination = () => {
|
|
296
289
|
const { dialogManager } = useNearestDialogManagerContext() ?? {};
|
|
297
290
|
const openedDialogCount = useOpenedDialogCount({ dialogManagerId: dialogManager?.id });
|
|
291
|
+
const [destinationRoot, setDestinationRoot] = React.useState(null);
|
|
292
|
+
React.useEffect(() => {
|
|
293
|
+
if (!destinationRoot || !dialogManager) return;
|
|
294
|
+
const handleDocumentClick = (event) => {
|
|
295
|
+
if (destinationRoot.contains(event.target)) return;
|
|
296
|
+
setTimeout(() => {
|
|
297
|
+
Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
|
|
298
|
+
(dialog) => {
|
|
299
|
+
if (!dialog.isOpen) return;
|
|
300
|
+
if (!shouldCloseOnOutsideClick({
|
|
301
|
+
dialog,
|
|
302
|
+
managerCloseOnClickOutside: dialogManager.closeOnClickOutside
|
|
303
|
+
}))
|
|
304
|
+
return;
|
|
305
|
+
dialogManager.close(dialog.id);
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
}, 0);
|
|
309
|
+
};
|
|
310
|
+
document.addEventListener("click", handleDocumentClick, { capture: true });
|
|
311
|
+
return () => {
|
|
312
|
+
document.removeEventListener("click", handleDocumentClick, { capture: true });
|
|
313
|
+
};
|
|
314
|
+
}, [destinationRoot, dialogManager]);
|
|
298
315
|
if (!openedDialogCount) return null;
|
|
299
316
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
300
317
|
"div",
|
|
@@ -302,7 +319,22 @@ const DialogPortalDestination = () => {
|
|
|
302
319
|
className: "str-chat__dialog-overlay",
|
|
303
320
|
"data-str-chat__portal-id": dialogManager?.id,
|
|
304
321
|
"data-testid": "str-chat__dialog-overlay",
|
|
305
|
-
onClick: () =>
|
|
322
|
+
onClick: (event) => {
|
|
323
|
+
if (!dialogManager) return;
|
|
324
|
+
if (event.target !== event.currentTarget) return;
|
|
325
|
+
Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
|
|
326
|
+
(dialog) => {
|
|
327
|
+
if (!dialog.isOpen) return;
|
|
328
|
+
if (!shouldCloseOnOutsideClick({
|
|
329
|
+
dialog,
|
|
330
|
+
managerCloseOnClickOutside: dialogManager.closeOnClickOutside
|
|
331
|
+
}))
|
|
332
|
+
return;
|
|
333
|
+
dialogManager.close(dialog.id);
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
},
|
|
337
|
+
ref: setDestinationRoot,
|
|
306
338
|
style: {
|
|
307
339
|
"--str-chat__dialog-overlay-height": openedDialogCount > 0 ? "100%" : "0"
|
|
308
340
|
}
|
|
@@ -324,11 +356,16 @@ const DialogPortalEntry = ({
|
|
|
324
356
|
};
|
|
325
357
|
const dialogManagersRegistry = new streamChat.StateStore({});
|
|
326
358
|
const getDialogManager = (id) => dialogManagersRegistry.getLatestValue()[id];
|
|
327
|
-
const getOrCreateDialogManager = (
|
|
359
|
+
const getOrCreateDialogManager = ({
|
|
360
|
+
closeOnClickOutside,
|
|
361
|
+
id
|
|
362
|
+
}) => {
|
|
328
363
|
let manager = getDialogManager(id);
|
|
329
364
|
if (!manager) {
|
|
330
|
-
manager = new DialogManager({ id });
|
|
365
|
+
manager = new DialogManager({ closeOnClickOutside, id });
|
|
331
366
|
dialogManagersRegistry.partialNext({ [id]: manager });
|
|
367
|
+
} else if (typeof closeOnClickOutside === "boolean") {
|
|
368
|
+
manager.closeOnClickOutside = closeOnClickOutside;
|
|
332
369
|
}
|
|
333
370
|
return manager;
|
|
334
371
|
};
|
|
@@ -339,20 +376,21 @@ const removeDialogManager = (id) => {
|
|
|
339
376
|
const DialogManagerProviderContext = React.createContext(void 0);
|
|
340
377
|
const DialogManagerProvider = ({
|
|
341
378
|
children,
|
|
379
|
+
closeOnClickOutside,
|
|
342
380
|
id
|
|
343
381
|
}) => {
|
|
344
382
|
const [dialogManager, setDialogManager] = React.useState(() => {
|
|
345
383
|
if (id) return getDialogManager(id) ?? null;
|
|
346
|
-
return new DialogManager();
|
|
384
|
+
return new DialogManager({ closeOnClickOutside });
|
|
347
385
|
});
|
|
348
386
|
React.useEffect(() => {
|
|
349
387
|
if (!id) return;
|
|
350
|
-
setDialogManager(getOrCreateDialogManager(id));
|
|
388
|
+
setDialogManager(getOrCreateDialogManager({ closeOnClickOutside, id }));
|
|
351
389
|
return () => {
|
|
352
390
|
removeDialogManager(id);
|
|
353
391
|
setDialogManager(null);
|
|
354
392
|
};
|
|
355
|
-
}, [id]);
|
|
393
|
+
}, [closeOnClickOutside, id]);
|
|
356
394
|
if (!dialogManager) return null;
|
|
357
395
|
return /* @__PURE__ */ jsxRuntime.jsxs(DialogManagerProviderContext.Provider, { value: { dialogManager }, children: [
|
|
358
396
|
children,
|
|
@@ -967,7 +1005,6 @@ const deTranslations = {
|
|
|
967
1005
|
"End vote": "Abstimmung beenden",
|
|
968
1006
|
"Enforce unique vote is enabled": "Eindeutige Abstimmung ist aktiviert",
|
|
969
1007
|
"Error": "Fehler",
|
|
970
|
-
"Error · Unsent": "Fehler · Nicht gesendet",
|
|
971
1008
|
"Error adding flag": "Fehler beim Hinzufügen des Flags",
|
|
972
1009
|
"Error connecting to chat, refresh the page to try again.": "Verbindungsfehler zum Chat, aktualisieren Sie die Seite, um es erneut zu versuchen.",
|
|
973
1010
|
"Error deleting message": "Fehler beim Löschen der Nachricht",
|
|
@@ -1089,8 +1126,6 @@ const deTranslations = {
|
|
|
1089
1126
|
"Maximum number of votes (from 2 to 10)": "Maximale Anzahl der Stimmen (von 2 bis 10)",
|
|
1090
1127
|
Menu: Menu$b,
|
|
1091
1128
|
"Message deleted": "Nachricht gelöscht",
|
|
1092
|
-
"Message Failed · Click to try again": "Nachricht fehlgeschlagen · Klicken, um es erneut zu versuchen",
|
|
1093
|
-
"Message Failed · Unauthorized": "Nachricht fehlgeschlagen · Nicht autorisiert",
|
|
1094
1129
|
"Message failed to send": "Nachricht konnte nicht gesendet werden",
|
|
1095
1130
|
"Message has been successfully flagged": "Nachricht wurde erfolgreich gemeldet",
|
|
1096
1131
|
"Message pinned": "Nachricht angeheftet",
|
|
@@ -1260,6 +1295,7 @@ const deTranslations = {
|
|
|
1260
1295
|
"View translation": "Übersetzung anzeigen",
|
|
1261
1296
|
"Voice message": "Sprachnachricht",
|
|
1262
1297
|
"Voice message {{ duration }}": "Sprachnachricht {{ duration }}",
|
|
1298
|
+
"Voice message deleted": "Sprachnachricht gelöscht",
|
|
1263
1299
|
voiceMessageCount_one: voiceMessageCount_one$9,
|
|
1264
1300
|
voiceMessageCount_other: voiceMessageCount_other$b,
|
|
1265
1301
|
"Vote ended": "Abstimmung beendet",
|
|
@@ -1490,7 +1526,6 @@ const enTranslations = {
|
|
|
1490
1526
|
"End vote": "End Vote",
|
|
1491
1527
|
"Enforce unique vote is enabled": "Enforce unique vote is enabled",
|
|
1492
1528
|
"Error": "Error",
|
|
1493
|
-
"Error · Unsent": "Error · Unsent",
|
|
1494
1529
|
"Error adding flag": "Error adding flag",
|
|
1495
1530
|
"Error connecting to chat, refresh the page to try again.": "Error connecting to chat, refresh the page to try again.",
|
|
1496
1531
|
"Error deleting message": "Error deleting message",
|
|
@@ -1612,8 +1647,6 @@ const enTranslations = {
|
|
|
1612
1647
|
"Maximum number of votes (from 2 to 10)": "Maximum number of votes (from 2 to 10)",
|
|
1613
1648
|
Menu: Menu$a,
|
|
1614
1649
|
"Message deleted": "Message deleted",
|
|
1615
|
-
"Message Failed · Click to try again": "Message Failed · Click to try again",
|
|
1616
|
-
"Message Failed · Unauthorized": "Message Failed · Unauthorized",
|
|
1617
1650
|
"Message failed to send": "Message failed to send",
|
|
1618
1651
|
"Message has been successfully flagged": "Message has been successfully flagged",
|
|
1619
1652
|
"Message pinned": "Message pinned",
|
|
@@ -1783,6 +1816,7 @@ const enTranslations = {
|
|
|
1783
1816
|
"View translation": "View translation",
|
|
1784
1817
|
"Voice message": "Voice message",
|
|
1785
1818
|
"Voice message {{ duration }}": "Voice message {{ duration }}",
|
|
1819
|
+
"Voice message deleted": "Voice message deleted",
|
|
1786
1820
|
voiceMessageCount_one: voiceMessageCount_one$8,
|
|
1787
1821
|
voiceMessageCount_other: voiceMessageCount_other$a,
|
|
1788
1822
|
"Vote ended": "Vote ended",
|
|
@@ -2029,7 +2063,6 @@ const esTranslations = {
|
|
|
2029
2063
|
"End vote": "Finalizar votación",
|
|
2030
2064
|
"Enforce unique vote is enabled": "El voto único está habilitado",
|
|
2031
2065
|
"Error": "Error",
|
|
2032
|
-
"Error · Unsent": "Error · No enviado",
|
|
2033
2066
|
"Error adding flag": "Error al agregar la bandera",
|
|
2034
2067
|
"Error connecting to chat, refresh the page to try again.": "Error al conectarse al chat, actualice la página para volver a intentarlo.",
|
|
2035
2068
|
"Error deleting message": "Error al eliminar el mensaje",
|
|
@@ -2154,8 +2187,6 @@ const esTranslations = {
|
|
|
2154
2187
|
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
|
|
2155
2188
|
Menu: Menu$9,
|
|
2156
2189
|
"Message deleted": "Mensaje eliminado",
|
|
2157
|
-
"Message Failed · Click to try again": "Mensaje fallido · Haga clic para volver a intentarlo",
|
|
2158
|
-
"Message Failed · Unauthorized": "Mensaje fallido · No autorizado",
|
|
2159
2190
|
"Message failed to send": "No se pudo enviar el mensaje",
|
|
2160
2191
|
"Message has been successfully flagged": "El mensaje se marcó correctamente",
|
|
2161
2192
|
"Message pinned": "Mensaje fijado",
|
|
@@ -2332,6 +2363,7 @@ const esTranslations = {
|
|
|
2332
2363
|
"View translation": "Ver traducción",
|
|
2333
2364
|
"Voice message": "Mensaje de voz",
|
|
2334
2365
|
"Voice message {{ duration }}": "Mensaje de voz {{ duration }}",
|
|
2366
|
+
"Voice message deleted": "Mensaje de voz eliminado",
|
|
2335
2367
|
voiceMessageCount_one: voiceMessageCount_one$7,
|
|
2336
2368
|
voiceMessageCount_many: voiceMessageCount_many$4,
|
|
2337
2369
|
voiceMessageCount_other: voiceMessageCount_other$9,
|
|
@@ -2579,7 +2611,6 @@ const frTranslations = {
|
|
|
2579
2611
|
"End vote": "Fin du vote",
|
|
2580
2612
|
"Enforce unique vote is enabled": "Le vote unique est activé",
|
|
2581
2613
|
"Error": "Erreur",
|
|
2582
|
-
"Error · Unsent": "Erreur - Non envoyé",
|
|
2583
2614
|
"Error adding flag": "Erreur lors de l'ajout du signalement",
|
|
2584
2615
|
"Error connecting to chat, refresh the page to try again.": "Erreur de connexion au chat, rafraîchissez la page pour réessayer.",
|
|
2585
2616
|
"Error deleting message": "Erreur lors de la suppression du message",
|
|
@@ -2704,8 +2735,6 @@ const frTranslations = {
|
|
|
2704
2735
|
"Maximum number of votes (from 2 to 10)": "Nombre maximum de votes (de 2 à 10)",
|
|
2705
2736
|
Menu: Menu$8,
|
|
2706
2737
|
"Message deleted": "Message supprimé",
|
|
2707
|
-
"Message Failed · Click to try again": "Échec de l'envoi du message - Cliquez pour réessayer",
|
|
2708
|
-
"Message Failed · Unauthorized": "Échec de l'envoi du message - Non autorisé",
|
|
2709
2738
|
"Message failed to send": "Échec de l'envoi du message",
|
|
2710
2739
|
"Message has been successfully flagged": "Le message a été signalé avec succès",
|
|
2711
2740
|
"Message pinned": "Message épinglé",
|
|
@@ -2882,6 +2911,7 @@ const frTranslations = {
|
|
|
2882
2911
|
"View translation": "Voir la traduction",
|
|
2883
2912
|
"Voice message": "Message vocal",
|
|
2884
2913
|
"Voice message {{ duration }}": "Message vocal {{ duration }}",
|
|
2914
|
+
"Voice message deleted": "Message vocal supprimé",
|
|
2885
2915
|
voiceMessageCount_one: voiceMessageCount_one$6,
|
|
2886
2916
|
voiceMessageCount_many: voiceMessageCount_many$3,
|
|
2887
2917
|
voiceMessageCount_other: voiceMessageCount_other$8,
|
|
@@ -3113,7 +3143,6 @@ const hiTranslations = {
|
|
|
3113
3143
|
"End vote": "मत समाप्त करें",
|
|
3114
3144
|
"Enforce unique vote is enabled": "अनोखा वोट सक्षम है",
|
|
3115
3145
|
"Error": "त्रुटि",
|
|
3116
|
-
"Error · Unsent": "फेल",
|
|
3117
3146
|
"Error adding flag": "ध्वज जोड़ने में त्रुटि",
|
|
3118
3147
|
"Error connecting to chat, refresh the page to try again.": "चैट से कनेक्ट करने में त्रुटि, पेज को रिफ्रेश करें",
|
|
3119
3148
|
"Error deleting message": "संदेश हटाने में त्रुटि",
|
|
@@ -3236,8 +3265,6 @@ const hiTranslations = {
|
|
|
3236
3265
|
"Maximum number of votes (from 2 to 10)": "अधिकतम वोटों की संख्या (2 से 10)",
|
|
3237
3266
|
Menu: Menu$7,
|
|
3238
3267
|
"Message deleted": "मैसेज हटा दिया गया",
|
|
3239
|
-
"Message Failed · Click to try again": "मैसेज फ़ैल - पुनः कोशिश करें",
|
|
3240
|
-
"Message Failed · Unauthorized": "मैसेज फ़ैल - अनधिकृत",
|
|
3241
3268
|
"Message failed to send": "संदेश भेजने में विफल",
|
|
3242
3269
|
"Message has been successfully flagged": "मैसेज को फ्लैग कर दिया गया है",
|
|
3243
3270
|
"Message pinned": "संदेश पिन किया गया",
|
|
@@ -3407,6 +3434,7 @@ const hiTranslations = {
|
|
|
3407
3434
|
"View translation": "अनुवाद देखें",
|
|
3408
3435
|
"Voice message": "आवाज संदेश",
|
|
3409
3436
|
"Voice message {{ duration }}": "वॉइस संदेश {{ duration }}",
|
|
3437
|
+
"Voice message deleted": "वॉइस संदेश हटा दिया गया",
|
|
3410
3438
|
voiceMessageCount_one: voiceMessageCount_one$5,
|
|
3411
3439
|
voiceMessageCount_other: voiceMessageCount_other$7,
|
|
3412
3440
|
"Vote ended": "मतदान समाप्त",
|
|
@@ -3653,7 +3681,6 @@ const itTranslations = {
|
|
|
3653
3681
|
"End vote": "Termina il voto",
|
|
3654
3682
|
"Enforce unique vote is enabled": "Il voto unico è abilitato",
|
|
3655
3683
|
"Error": "Errore",
|
|
3656
|
-
"Error · Unsent": "Errore · Non inviato",
|
|
3657
3684
|
"Error adding flag": "Errore durante l'aggiunta del flag",
|
|
3658
3685
|
"Error connecting to chat, refresh the page to try again.": "Errore di connessione alla chat, aggiorna la pagina per riprovare.",
|
|
3659
3686
|
"Error deleting message": "Errore durante l'eliminazione del messaggio",
|
|
@@ -3778,8 +3805,6 @@ const itTranslations = {
|
|
|
3778
3805
|
"Maximum number of votes (from 2 to 10)": "Numero massimo di voti (da 2 a 10)",
|
|
3779
3806
|
Menu: Menu$6,
|
|
3780
3807
|
"Message deleted": "Messaggio cancellato",
|
|
3781
|
-
"Message Failed · Click to try again": "Invio messaggio fallito · Clicca per riprovare",
|
|
3782
|
-
"Message Failed · Unauthorized": "Invio messaggio fallito · Non autorizzato",
|
|
3783
3808
|
"Message failed to send": "Invio del messaggio non riuscito",
|
|
3784
3809
|
"Message has been successfully flagged": "Il messaggio è stato segnalato con successo",
|
|
3785
3810
|
"Message pinned": "Messaggio bloccato",
|
|
@@ -3956,6 +3981,7 @@ const itTranslations = {
|
|
|
3956
3981
|
"View translation": "Visualizza traduzione",
|
|
3957
3982
|
"Voice message": "Messaggio vocale",
|
|
3958
3983
|
"Voice message {{ duration }}": "Messaggio vocale {{ duration }}",
|
|
3984
|
+
"Voice message deleted": "Messaggio vocale eliminato",
|
|
3959
3985
|
voiceMessageCount_one: voiceMessageCount_one$4,
|
|
3960
3986
|
voiceMessageCount_many: voiceMessageCount_many$2,
|
|
3961
3987
|
voiceMessageCount_other: voiceMessageCount_other$6,
|
|
@@ -4180,7 +4206,6 @@ const jaTranslations = {
|
|
|
4180
4206
|
"End vote": "投票を終了",
|
|
4181
4207
|
"Enforce unique vote is enabled": "一意の投票が有効になっています",
|
|
4182
4208
|
"Error": "エラー",
|
|
4183
|
-
"Error · Unsent": "エラー・未送信",
|
|
4184
4209
|
"Error adding flag": "フラグを追加のエラーが発生しました",
|
|
4185
4210
|
"Error connecting to chat, refresh the page to try again.": "チャットへの接続ができませんでした。ページを更新してください。",
|
|
4186
4211
|
"Error deleting message": "メッセージを削除するエラーが発生しました",
|
|
@@ -4299,8 +4324,6 @@ const jaTranslations = {
|
|
|
4299
4324
|
"Maximum number of votes (from 2 to 10)": "最大投票数(2から10まで)",
|
|
4300
4325
|
Menu: Menu$5,
|
|
4301
4326
|
"Message deleted": "メッセージが削除されました",
|
|
4302
|
-
"Message Failed · Click to try again": "メッセージが失敗しました · クリックして再試行してください",
|
|
4303
|
-
"Message Failed · Unauthorized": "メッセージが失敗しました · 許可されていません",
|
|
4304
4327
|
"Message failed to send": "メッセージの送信に失敗しました",
|
|
4305
4328
|
"Message has been successfully flagged": "メッセージに正常にフラグが付けられました",
|
|
4306
4329
|
"Message pinned": "メッセージにピンが付けられました",
|
|
@@ -4467,6 +4490,7 @@ const jaTranslations = {
|
|
|
4467
4490
|
"View translation": "翻訳を表示",
|
|
4468
4491
|
"Voice message": "ボイスメッセージ",
|
|
4469
4492
|
"Voice message {{ duration }}": "ボイスメッセージ {{ duration }}",
|
|
4493
|
+
"Voice message deleted": "ボイスメッセージが削除されました",
|
|
4470
4494
|
voiceMessageCount_other: voiceMessageCount_other$5,
|
|
4471
4495
|
"Vote ended": "投票が終了しました",
|
|
4472
4496
|
Votes: Votes$5,
|
|
@@ -4689,7 +4713,6 @@ const koTranslations = {
|
|
|
4689
4713
|
"End vote": "투표 종료",
|
|
4690
4714
|
"Enforce unique vote is enabled": "고유 투표가 활성화되었습니다",
|
|
4691
4715
|
"Error": "오류",
|
|
4692
|
-
"Error · Unsent": "오류 · 전송되지 않음",
|
|
4693
4716
|
"Error adding flag": "플래그를 추가하는 동안 오류가 발생했습니다.",
|
|
4694
4717
|
"Error connecting to chat, refresh the page to try again.": "채팅에 연결하는 동안 오류가 발생했습니다. 페이지를 새로고침하여 다시 시도하세요.",
|
|
4695
4718
|
"Error deleting message": "메시지를 삭제하는 중에 오류가 발생했습니다.",
|
|
@@ -4808,8 +4831,6 @@ const koTranslations = {
|
|
|
4808
4831
|
"Maximum number of votes (from 2 to 10)": "최대 투표 수 (2에서 10까지)",
|
|
4809
4832
|
Menu: Menu$4,
|
|
4810
4833
|
"Message deleted": "메시지가 삭제되었습니다.",
|
|
4811
|
-
"Message Failed · Click to try again": "메시지 실패 · 다시 시도하려면 클릭하세요.",
|
|
4812
|
-
"Message Failed · Unauthorized": "메시지 실패 · 승인되지 않음",
|
|
4813
4834
|
"Message failed to send": "메시지 전송 실패",
|
|
4814
4835
|
"Message has been successfully flagged": "메시지에 플래그가 지정되었습니다.",
|
|
4815
4836
|
"Message pinned": "메시지 핀했습니다",
|
|
@@ -4976,6 +4997,7 @@ const koTranslations = {
|
|
|
4976
4997
|
"View translation": "번역 보기",
|
|
4977
4998
|
"Voice message": "음성 메시지",
|
|
4978
4999
|
"Voice message {{ duration }}": "음성 메시지 {{ duration }}",
|
|
5000
|
+
"Voice message deleted": "음성 메시지가 삭제됨",
|
|
4979
5001
|
voiceMessageCount_other: voiceMessageCount_other$4,
|
|
4980
5002
|
"Vote ended": "투표 종료",
|
|
4981
5003
|
Votes: Votes$4,
|
|
@@ -5205,7 +5227,6 @@ const nlTranslations = {
|
|
|
5205
5227
|
"End vote": "Einde stem",
|
|
5206
5228
|
"Enforce unique vote is enabled": "Unieke stem is ingeschakeld",
|
|
5207
5229
|
"Error": "Fout",
|
|
5208
|
-
"Error · Unsent": "Fout · niet verzonden",
|
|
5209
5230
|
"Error adding flag": "Fout bij toevoegen van vlag",
|
|
5210
5231
|
"Error connecting to chat, refresh the page to try again.": "Fout bij het verbinden, ververs de pagina om nogmaals te proberen",
|
|
5211
5232
|
"Error deleting message": "Fout bij verwijderen van bericht",
|
|
@@ -5327,8 +5348,6 @@ const nlTranslations = {
|
|
|
5327
5348
|
"Maximum number of votes (from 2 to 10)": "Maximaal aantal stemmen (van 2 tot 10)",
|
|
5328
5349
|
Menu: Menu$3,
|
|
5329
5350
|
"Message deleted": "Bericht verwijderd",
|
|
5330
|
-
"Message Failed · Click to try again": "Bericht mislukt, klik om het nogmaals te proberen",
|
|
5331
|
-
"Message Failed · Unauthorized": "Bericht mislukt, ongeautoriseerd",
|
|
5332
5351
|
"Message failed to send": "Bericht kon niet worden verzonden",
|
|
5333
5352
|
"Message has been successfully flagged": "Bericht is succesvol gemarkeerd",
|
|
5334
5353
|
"Message pinned": "Bericht vastgezet",
|
|
@@ -5500,6 +5519,7 @@ const nlTranslations = {
|
|
|
5500
5519
|
"View translation": "Vertaling bekijken",
|
|
5501
5520
|
"Voice message": "Spraakbericht",
|
|
5502
5521
|
"Voice message {{ duration }}": "Spraakbericht {{ duration }}",
|
|
5522
|
+
"Voice message deleted": "Spraakbericht verwijderd",
|
|
5503
5523
|
voiceMessageCount_one: voiceMessageCount_one$3,
|
|
5504
5524
|
voiceMessageCount_other: voiceMessageCount_other$3,
|
|
5505
5525
|
"Vote ended": "Stemmen beëindigd",
|
|
@@ -5746,7 +5766,6 @@ const ptTranslations = {
|
|
|
5746
5766
|
"End vote": "Encerrar votação",
|
|
5747
5767
|
"Enforce unique vote is enabled": "Voto único está habilitado",
|
|
5748
5768
|
"Error": "Erro",
|
|
5749
|
-
"Error · Unsent": "Erro · Não enviado",
|
|
5750
5769
|
"Error adding flag": "Erro ao reportar",
|
|
5751
5770
|
"Error connecting to chat, refresh the page to try again.": "Erro ao conectar ao bate-papo, atualize a página para tentar novamente.",
|
|
5752
5771
|
"Error deleting message": "Erro ao deletar mensagem",
|
|
@@ -5871,8 +5890,6 @@ const ptTranslations = {
|
|
|
5871
5890
|
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
|
|
5872
5891
|
Menu: Menu$2,
|
|
5873
5892
|
"Message deleted": "Mensagem apagada",
|
|
5874
|
-
"Message Failed · Click to try again": "A mensagem falhou · Clique para tentar novamente",
|
|
5875
|
-
"Message Failed · Unauthorized": "A mensagem falhou · não autorizado",
|
|
5876
5893
|
"Message failed to send": "Falha ao enviar a mensagem",
|
|
5877
5894
|
"Message has been successfully flagged": "A mensagem foi reportada com sucesso",
|
|
5878
5895
|
"Message pinned": "Mensagem fixada",
|
|
@@ -6049,6 +6066,7 @@ const ptTranslations = {
|
|
|
6049
6066
|
"View translation": "Ver tradução",
|
|
6050
6067
|
"Voice message": "Mensagem de voz",
|
|
6051
6068
|
"Voice message {{ duration }}": "Mensagem de voz {{ duration }}",
|
|
6069
|
+
"Voice message deleted": "Mensagem de voz excluída",
|
|
6052
6070
|
voiceMessageCount_one: voiceMessageCount_one$2,
|
|
6053
6071
|
voiceMessageCount_many: voiceMessageCount_many$1,
|
|
6054
6072
|
voiceMessageCount_other: voiceMessageCount_other$2,
|
|
@@ -6316,7 +6334,6 @@ const ruTranslations = {
|
|
|
6316
6334
|
"End vote": "Закончить голосование",
|
|
6317
6335
|
"Enforce unique vote is enabled": "Уникальное голосование включено",
|
|
6318
6336
|
"Error": "Ошибка",
|
|
6319
|
-
"Error · Unsent": "Ошибка · Не отправлено",
|
|
6320
6337
|
"Error adding flag": "Ошибка добавления флага",
|
|
6321
6338
|
"Error connecting to chat, refresh the page to try again.": "Ошибка подключения к чату, обновите страницу чтобы попробовать снова.",
|
|
6322
6339
|
"Error deleting message": "Ошибка при удалении сообщения",
|
|
@@ -6447,8 +6464,6 @@ const ruTranslations = {
|
|
|
6447
6464
|
"Maximum number of votes (from 2 to 10)": "Максимальное количество голосов (от 2 до 10)",
|
|
6448
6465
|
Menu: Menu$1,
|
|
6449
6466
|
"Message deleted": "Сообщение удалено",
|
|
6450
|
-
"Message Failed · Click to try again": "Ошибка отправки сообщения · Нажмите чтобы повторить",
|
|
6451
|
-
"Message Failed · Unauthorized": "Ошибка отправки сообщения · Неавторизованный",
|
|
6452
6467
|
"Message failed to send": "Не удалось отправить сообщение",
|
|
6453
6468
|
"Message has been successfully flagged": "Жалоба на сообщение была принята",
|
|
6454
6469
|
"Message pinned": "Сообщение закреплено",
|
|
@@ -6632,6 +6647,7 @@ const ruTranslations = {
|
|
|
6632
6647
|
"View translation": "Показать перевод",
|
|
6633
6648
|
"Voice message": "Голосовое сообщение",
|
|
6634
6649
|
"Voice message {{ duration }}": "Голосовое сообщение {{ duration }}",
|
|
6650
|
+
"Voice message deleted": "Голосовое сообщение удалено",
|
|
6635
6651
|
voiceMessageCount_one: voiceMessageCount_one$1,
|
|
6636
6652
|
voiceMessageCount_few,
|
|
6637
6653
|
voiceMessageCount_many,
|
|
@@ -6864,7 +6880,6 @@ const trTranslations = {
|
|
|
6864
6880
|
"End vote": "Oyu bitir",
|
|
6865
6881
|
"Enforce unique vote is enabled": "Benzersiz oy etkinleştirildi",
|
|
6866
6882
|
"Error": "Hata",
|
|
6867
|
-
"Error · Unsent": "Hata · Gönderilemedi",
|
|
6868
6883
|
"Error adding flag": "Bayrak eklenirken hata oluştu",
|
|
6869
6884
|
"Error connecting to chat, refresh the page to try again.": "Bağlantı hatası, sayfayı yenileyip tekrar deneyin.",
|
|
6870
6885
|
"Error deleting message": "Mesaj silinirken hata oluştu",
|
|
@@ -6986,8 +7001,6 @@ const trTranslations = {
|
|
|
6986
7001
|
"Maximum number of votes (from 2 to 10)": "Maksimum oy sayısı (2 ile 10 arası)",
|
|
6987
7002
|
Menu,
|
|
6988
7003
|
"Message deleted": "Mesaj silindi",
|
|
6989
|
-
"Message Failed · Click to try again": "Mesaj Başarısız · Tekrar denemek için tıklayın",
|
|
6990
|
-
"Message Failed · Unauthorized": "Mesaj Başarısız · Yetkisiz",
|
|
6991
7004
|
"Message failed to send": "Mesaj gönderilemedi",
|
|
6992
7005
|
"Message has been successfully flagged": "Mesaj başarıyla bayraklandı",
|
|
6993
7006
|
"Message pinned": "Mesaj sabitlendi",
|
|
@@ -7157,6 +7170,7 @@ const trTranslations = {
|
|
|
7157
7170
|
"View translation": "Çeviriyi görüntüle",
|
|
7158
7171
|
"Voice message": "Sesli mesaj",
|
|
7159
7172
|
"Voice message {{ duration }}": "Sesli mesaj {{ duration }}",
|
|
7173
|
+
"Voice message deleted": "Sesli mesaj silindi",
|
|
7160
7174
|
voiceMessageCount_one,
|
|
7161
7175
|
voiceMessageCount_other,
|
|
7162
7176
|
"Vote ended": "Oylama sona erdi",
|
|
@@ -8586,11 +8600,18 @@ function useActionHandler(message) {
|
|
|
8586
8600
|
}
|
|
8587
8601
|
const useDeleteHandler = (message, notifications = {}) => {
|
|
8588
8602
|
const { getErrorNotification, notify } = notifications;
|
|
8589
|
-
const { deleteMessage, updateMessage } = WithAudioPlayback.useChannelActionContext("useDeleteHandler");
|
|
8603
|
+
const { deleteMessage, removeMessage, updateMessage } = WithAudioPlayback.useChannelActionContext("useDeleteHandler");
|
|
8590
8604
|
const { client } = WithAudioPlayback.useChatContext("useDeleteHandler");
|
|
8591
8605
|
const { t } = WithAudioPlayback.useTranslationContext("useDeleteHandler");
|
|
8592
8606
|
return async (options) => {
|
|
8593
|
-
if (!message
|
|
8607
|
+
if (!message) {
|
|
8608
|
+
return;
|
|
8609
|
+
}
|
|
8610
|
+
if (message.type === "error" || WithAudioPlayback.isNetworkSendFailure(message)) {
|
|
8611
|
+
removeMessage?.(message);
|
|
8612
|
+
return;
|
|
8613
|
+
}
|
|
8614
|
+
if (!message.id || !client || !updateMessage) {
|
|
8594
8615
|
return;
|
|
8595
8616
|
}
|
|
8596
8617
|
try {
|
|
@@ -8599,6 +8620,7 @@ const useDeleteHandler = (message, notifications = {}) => {
|
|
|
8599
8620
|
} catch (e) {
|
|
8600
8621
|
const errorMessage = getErrorNotification && WithAudioPlayback.validateAndGetMessage(getErrorNotification, [message]);
|
|
8601
8622
|
if (notify) notify(errorMessage || t("Error deleting message"), "error");
|
|
8623
|
+
throw e;
|
|
8602
8624
|
}
|
|
8603
8625
|
};
|
|
8604
8626
|
};
|
|
@@ -8910,7 +8932,7 @@ const useUserRole = (message, onlySenderCanEdit, disableQuotedMessages) => {
|
|
|
8910
8932
|
const canFlag = !isMyMessage && channelCapabilities["flag-message"];
|
|
8911
8933
|
const canMute = !isMyMessage && channelCapabilities["mute-channel"];
|
|
8912
8934
|
const canBlockUser = !isMyMessage;
|
|
8913
|
-
const canMarkUnread = channelCapabilities["read-events"];
|
|
8935
|
+
const canMarkUnread = !isMyMessage && channelCapabilities["read-events"];
|
|
8914
8936
|
const canQuote = !disableQuotedMessages && channelCapabilities["quote-message"];
|
|
8915
8937
|
const canReact = channelCapabilities["send-reaction"];
|
|
8916
8938
|
const canReply = channelCapabilities["send-reply"];
|
|
@@ -9007,73 +9029,6 @@ const useMessageReminder = (messageId) => {
|
|
|
9007
9029
|
const { reminder } = WithAudioPlayback.useStateStore(client.reminders.state, reminderSelector);
|
|
9008
9030
|
return reminder;
|
|
9009
9031
|
};
|
|
9010
|
-
const ActionsIcon = ({ className = "" }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9011
|
-
"svg",
|
|
9012
|
-
{
|
|
9013
|
-
className,
|
|
9014
|
-
height: "4",
|
|
9015
|
-
viewBox: "0 0 11 4",
|
|
9016
|
-
width: "11",
|
|
9017
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9018
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9019
|
-
"path",
|
|
9020
|
-
{
|
|
9021
|
-
d: "M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z",
|
|
9022
|
-
fillRule: "nonzero"
|
|
9023
|
-
}
|
|
9024
|
-
)
|
|
9025
|
-
}
|
|
9026
|
-
);
|
|
9027
|
-
const ReactionIcon = ({ className = "" }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
9028
|
-
"svg",
|
|
9029
|
-
{
|
|
9030
|
-
className,
|
|
9031
|
-
height: "12",
|
|
9032
|
-
viewBox: "0 0 12 12",
|
|
9033
|
-
width: "12",
|
|
9034
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9035
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("g", { clipRule: "evenodd", fillRule: "evenodd", children: [
|
|
9036
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z" }),
|
|
9037
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z" })
|
|
9038
|
-
] })
|
|
9039
|
-
}
|
|
9040
|
-
);
|
|
9041
|
-
const ThreadIcon = ({ className = "" }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, height: "10", width: "14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9042
|
-
"path",
|
|
9043
|
-
{
|
|
9044
|
-
d: "M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z",
|
|
9045
|
-
fillRule: "evenodd"
|
|
9046
|
-
}
|
|
9047
|
-
) });
|
|
9048
|
-
const PinIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { height: "13", viewBox: "0 0 14 13", width: "14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9049
|
-
"path",
|
|
9050
|
-
{
|
|
9051
|
-
d: "M13.3518 6.686L6.75251 0.0866699L5.80984 1.02867L6.75318 1.972V1.97334L3.45318 5.272L3.45251 5.27334L2.50984 4.32934L1.56718 5.27267L4.39584 8.10067L0.624512 11.8713L1.56718 12.814L5.33851 9.04334L8.16718 11.8713L9.10984 10.9293L8.16718 9.986L11.4672 6.686L12.4098 7.62867L13.3518 6.686ZM7.22451 9.04267L7.22385 9.04334L4.39584 6.21467L7.69518 2.91467L10.5232 5.74267L7.22451 9.04267Z",
|
|
9052
|
-
fillRule: "evenodd"
|
|
9053
|
-
}
|
|
9054
|
-
) });
|
|
9055
|
-
const MessageErrorIcon = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-error-icon", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9056
|
-
"svg",
|
|
9057
|
-
{
|
|
9058
|
-
"data-testid": "error",
|
|
9059
|
-
fill: "none",
|
|
9060
|
-
height: "24",
|
|
9061
|
-
viewBox: "0 0 24 24",
|
|
9062
|
-
width: "24",
|
|
9063
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9064
|
-
children: [
|
|
9065
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9066
|
-
"path",
|
|
9067
|
-
{
|
|
9068
|
-
d: "M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z",
|
|
9069
|
-
fill: "black",
|
|
9070
|
-
id: "background"
|
|
9071
|
-
}
|
|
9072
|
-
),
|
|
9073
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13 17H11V15H13V17ZM13 13H11V7H13V13Z", fill: "white" })
|
|
9074
|
-
]
|
|
9075
|
-
}
|
|
9076
|
-
) });
|
|
9077
9032
|
const Root = React.forwardRef(function AlertRoot({ children, className, ...props }, ref) {
|
|
9078
9033
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, className: clsx("str-chat__alert-root", className), ref, children });
|
|
9079
9034
|
});
|
|
@@ -9154,6 +9109,7 @@ function useDialogAnchor({
|
|
|
9154
9109
|
setPopperElement(null);
|
|
9155
9110
|
}
|
|
9156
9111
|
return {
|
|
9112
|
+
placement: stabilisedChosenPlacement ?? chosenPlacement,
|
|
9157
9113
|
setPopperElement,
|
|
9158
9114
|
styles: {
|
|
9159
9115
|
left: x ?? 0,
|
|
@@ -9166,6 +9122,8 @@ const DialogAnchor = ({
|
|
|
9166
9122
|
allowFlip = true,
|
|
9167
9123
|
children,
|
|
9168
9124
|
className,
|
|
9125
|
+
closeOnClickOutside,
|
|
9126
|
+
closeTransitionMs = 0,
|
|
9169
9127
|
dialogManagerId,
|
|
9170
9128
|
focus: focus$1 = true,
|
|
9171
9129
|
id,
|
|
@@ -9178,12 +9136,44 @@ const DialogAnchor = ({
|
|
|
9178
9136
|
updatePositionOnContentResize,
|
|
9179
9137
|
...restDivProps
|
|
9180
9138
|
}) => {
|
|
9181
|
-
const dialog = useDialog({ dialogManagerId, id });
|
|
9139
|
+
const dialog = useDialog({ closeOnClickOutside, dialogManagerId, id });
|
|
9182
9140
|
const open = useDialogIsOpen(id, dialogManagerId);
|
|
9183
|
-
const
|
|
9141
|
+
const [shouldRender, setShouldRender] = React.useState(open);
|
|
9142
|
+
const closeTimeoutRef = React.useRef(null);
|
|
9143
|
+
const isClosing = !open && shouldRender;
|
|
9144
|
+
React.useEffect(() => {
|
|
9145
|
+
if (open) {
|
|
9146
|
+
setShouldRender(true);
|
|
9147
|
+
if (closeTimeoutRef.current) {
|
|
9148
|
+
clearTimeout(closeTimeoutRef.current);
|
|
9149
|
+
closeTimeoutRef.current = null;
|
|
9150
|
+
}
|
|
9151
|
+
return;
|
|
9152
|
+
}
|
|
9153
|
+
if (!shouldRender) return;
|
|
9154
|
+
if (!closeTransitionMs) {
|
|
9155
|
+
setShouldRender(false);
|
|
9156
|
+
return;
|
|
9157
|
+
}
|
|
9158
|
+
closeTimeoutRef.current = setTimeout(() => {
|
|
9159
|
+
setShouldRender(false);
|
|
9160
|
+
closeTimeoutRef.current = null;
|
|
9161
|
+
}, closeTransitionMs);
|
|
9162
|
+
}, [closeTransitionMs, open, shouldRender]);
|
|
9163
|
+
React.useEffect(
|
|
9164
|
+
() => () => {
|
|
9165
|
+
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
|
|
9166
|
+
},
|
|
9167
|
+
[]
|
|
9168
|
+
);
|
|
9169
|
+
const {
|
|
9170
|
+
placement: chosenPlacement,
|
|
9171
|
+
setPopperElement,
|
|
9172
|
+
styles
|
|
9173
|
+
} = useDialogAnchor({
|
|
9184
9174
|
allowFlip,
|
|
9185
9175
|
offset,
|
|
9186
|
-
open,
|
|
9176
|
+
open: shouldRender,
|
|
9187
9177
|
placement,
|
|
9188
9178
|
referenceElement,
|
|
9189
9179
|
updateKey,
|
|
@@ -9200,7 +9190,7 @@ const DialogAnchor = ({
|
|
|
9200
9190
|
document.removeEventListener("keyup", hideOnEscape);
|
|
9201
9191
|
};
|
|
9202
9192
|
}, [dialog, open]);
|
|
9203
|
-
if (!
|
|
9193
|
+
if (!shouldRender) {
|
|
9204
9194
|
return null;
|
|
9205
9195
|
}
|
|
9206
9196
|
return /* @__PURE__ */ jsxRuntime.jsx(DialogPortalEntry, { dialogId: id, dialogManagerId, children: /* @__PURE__ */ jsxRuntime.jsx(focus.FocusScope, { autoFocus: focus$1, contain: trapFocus, restoreFocus: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9208,6 +9198,8 @@ const DialogAnchor = ({
|
|
|
9208
9198
|
{
|
|
9209
9199
|
...restDivProps,
|
|
9210
9200
|
className: clsx("str-chat__dialog-contents", className),
|
|
9201
|
+
"data-str-chat-dialog-state": isClosing ? "closing" : "open",
|
|
9202
|
+
"data-str-chat-placement": chosenPlacement,
|
|
9211
9203
|
"data-testid": "str-chat__dialog-contents",
|
|
9212
9204
|
ref: setPopperElement,
|
|
9213
9205
|
style: styles,
|
|
@@ -9334,6 +9326,11 @@ const Badge = ({
|
|
|
9334
9326
|
children
|
|
9335
9327
|
}
|
|
9336
9328
|
);
|
|
9329
|
+
const ErrorBadge = ({
|
|
9330
|
+
className,
|
|
9331
|
+
size = "sm",
|
|
9332
|
+
...rest
|
|
9333
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { ...rest, className, size, variant: "error", children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamation, {}) });
|
|
9337
9334
|
function AvatarStack({
|
|
9338
9335
|
badgeSize,
|
|
9339
9336
|
component: Component = "div",
|
|
@@ -9545,16 +9542,152 @@ const EmojiContextMenuButton = ({
|
|
|
9545
9542
|
]
|
|
9546
9543
|
}
|
|
9547
9544
|
);
|
|
9548
|
-
const
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9545
|
+
const ContextMenuButtonWithSubmenu = ({
|
|
9546
|
+
children,
|
|
9547
|
+
className,
|
|
9548
|
+
Submenu,
|
|
9549
|
+
submenuContainerProps,
|
|
9550
|
+
submenuPlacement = "right-start",
|
|
9551
|
+
submenuRollAxis = "x",
|
|
9552
|
+
...buttonProps
|
|
9552
9553
|
}) => {
|
|
9554
|
+
const { className: submenuClassName, ...submenuContainerRestProps } = submenuContainerProps ?? {};
|
|
9555
|
+
const buttonRef = React.useRef(null);
|
|
9556
|
+
const [dialogContainer, setDialogContainer] = React.useState(null);
|
|
9557
|
+
const keepSubmenuOpenFlag = React.useRef(false);
|
|
9558
|
+
const dialogCloseTimeout = React.useRef(null);
|
|
9559
|
+
const dialogId2 = React.useMemo(() => `submenu-${Math.random().toString(36).slice(2)}`, []);
|
|
9560
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
9561
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
9562
|
+
const {
|
|
9563
|
+
placement: chosenPlacement,
|
|
9564
|
+
setPopperElement,
|
|
9565
|
+
styles
|
|
9566
|
+
} = useDialogAnchor({
|
|
9567
|
+
open: dialogIsOpen,
|
|
9568
|
+
placement: submenuPlacement,
|
|
9569
|
+
referenceElement: buttonRef.current
|
|
9570
|
+
});
|
|
9571
|
+
const closeDialogLazily = React.useCallback(() => {
|
|
9572
|
+
if (dialogCloseTimeout.current) clearTimeout(dialogCloseTimeout.current);
|
|
9573
|
+
dialogCloseTimeout.current = setTimeout(() => {
|
|
9574
|
+
if (keepSubmenuOpenFlag.current) return;
|
|
9575
|
+
dialog.close();
|
|
9576
|
+
}, 100);
|
|
9577
|
+
}, [dialog]);
|
|
9578
|
+
const keepSubmenuOpen = React.useCallback(() => {
|
|
9579
|
+
keepSubmenuOpenFlag.current = true;
|
|
9580
|
+
}, []);
|
|
9581
|
+
const allowToCloseSubmenu = React.useCallback(() => {
|
|
9582
|
+
keepSubmenuOpenFlag.current = false;
|
|
9583
|
+
}, []);
|
|
9584
|
+
const closeSubmenu = React.useCallback(() => {
|
|
9585
|
+
allowToCloseSubmenu();
|
|
9586
|
+
closeDialogLazily();
|
|
9587
|
+
}, [allowToCloseSubmenu, closeDialogLazily]);
|
|
9588
|
+
const handleClose = React.useCallback(
|
|
9589
|
+
(event) => {
|
|
9590
|
+
const parentButton = buttonRef.current;
|
|
9591
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
9592
|
+
event.stopPropagation();
|
|
9593
|
+
closeDialogLazily();
|
|
9594
|
+
parentButton.focus();
|
|
9595
|
+
},
|
|
9596
|
+
[closeDialogLazily, dialogIsOpen, buttonRef]
|
|
9597
|
+
);
|
|
9598
|
+
const handleFocusParentButton = () => {
|
|
9599
|
+
if (dialogIsOpen) return;
|
|
9600
|
+
dialog.open();
|
|
9601
|
+
keepSubmenuOpen();
|
|
9602
|
+
};
|
|
9603
|
+
React.useEffect(() => {
|
|
9604
|
+
const parentButton = buttonRef.current;
|
|
9605
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
9606
|
+
const hideOnEscape = (event) => {
|
|
9607
|
+
if (event.key !== "Escape") return;
|
|
9608
|
+
handleClose(event);
|
|
9609
|
+
closeSubmenu();
|
|
9610
|
+
};
|
|
9611
|
+
document.addEventListener("keyup", hideOnEscape, { capture: true });
|
|
9612
|
+
return () => {
|
|
9613
|
+
document.removeEventListener("keyup", hideOnEscape, { capture: true });
|
|
9614
|
+
};
|
|
9615
|
+
}, [dialogIsOpen, handleClose, closeSubmenu]);
|
|
9616
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9617
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9618
|
+
BaseContextMenuButton,
|
|
9619
|
+
{
|
|
9620
|
+
"aria-selected": "false",
|
|
9621
|
+
className: clsx(className, "str_chat__button-with-submenu", {
|
|
9622
|
+
"str_chat__button-with-submenu--submenu-open": dialogIsOpen
|
|
9623
|
+
}),
|
|
9624
|
+
hasSubMenu: true,
|
|
9625
|
+
onBlur: closeSubmenu,
|
|
9626
|
+
onClick: (event) => {
|
|
9627
|
+
event.stopPropagation();
|
|
9628
|
+
dialog.toggle();
|
|
9629
|
+
},
|
|
9630
|
+
onFocus: handleFocusParentButton,
|
|
9631
|
+
onMouseEnter: handleFocusParentButton,
|
|
9632
|
+
onMouseLeave: closeSubmenu,
|
|
9633
|
+
role: "option",
|
|
9634
|
+
...buttonProps,
|
|
9635
|
+
ref: buttonRef,
|
|
9636
|
+
children
|
|
9637
|
+
}
|
|
9638
|
+
),
|
|
9639
|
+
dialogIsOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9640
|
+
"div",
|
|
9641
|
+
{
|
|
9642
|
+
className: clsx("str-chat__context-menu__submenu-container", submenuClassName),
|
|
9643
|
+
"data-str-chat-placement": chosenPlacement,
|
|
9644
|
+
"data-str-chat-roll-axis": submenuRollAxis,
|
|
9645
|
+
onBlur: (event) => {
|
|
9646
|
+
const isBlurredDescendant = event.relatedTarget instanceof Node && dialogContainer?.contains(event.relatedTarget);
|
|
9647
|
+
if (isBlurredDescendant) return;
|
|
9648
|
+
closeSubmenu();
|
|
9649
|
+
},
|
|
9650
|
+
onFocus: keepSubmenuOpen,
|
|
9651
|
+
onMouseEnter: keepSubmenuOpen,
|
|
9652
|
+
onMouseLeave: closeSubmenu,
|
|
9653
|
+
ref: (element) => {
|
|
9654
|
+
setPopperElement(element);
|
|
9655
|
+
setDialogContainer(element);
|
|
9656
|
+
},
|
|
9657
|
+
style: styles,
|
|
9658
|
+
tabIndex: -1,
|
|
9659
|
+
...submenuContainerRestProps,
|
|
9660
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Submenu, {})
|
|
9661
|
+
}
|
|
9662
|
+
)
|
|
9663
|
+
] });
|
|
9664
|
+
};
|
|
9665
|
+
const ContextMenuButton = (props) => {
|
|
9666
|
+
const {
|
|
9667
|
+
Submenu,
|
|
9668
|
+
submenuContainerProps,
|
|
9669
|
+
submenuPlacement,
|
|
9670
|
+
submenuRollAxis,
|
|
9671
|
+
...buttonProps
|
|
9672
|
+
} = props;
|
|
9553
9673
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
9674
|
+
if (Submenu) {
|
|
9675
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9676
|
+
ContextMenuButtonWithSubmenu,
|
|
9677
|
+
{
|
|
9678
|
+
...buttonProps,
|
|
9679
|
+
Submenu,
|
|
9680
|
+
submenuContainerProps,
|
|
9681
|
+
submenuPlacement,
|
|
9682
|
+
submenuRollAxis
|
|
9683
|
+
}
|
|
9684
|
+
);
|
|
9685
|
+
}
|
|
9686
|
+
const { onBlur, onFocus, ...baseButtonProps } = buttonProps;
|
|
9554
9687
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9555
9688
|
BaseContextMenuButton,
|
|
9556
9689
|
{
|
|
9557
|
-
...
|
|
9690
|
+
...baseButtonProps,
|
|
9558
9691
|
"aria-selected": isFocused ? "true" : "false",
|
|
9559
9692
|
onBlur: (e) => {
|
|
9560
9693
|
setIsFocused(false);
|
|
@@ -9603,12 +9736,14 @@ function ContextMenuContent({
|
|
|
9603
9736
|
backLabel = "Back",
|
|
9604
9737
|
children,
|
|
9605
9738
|
className,
|
|
9739
|
+
enableAnimations = true,
|
|
9606
9740
|
Header: Header2,
|
|
9607
9741
|
items,
|
|
9608
9742
|
ItemsWrapper,
|
|
9609
9743
|
menuClassName,
|
|
9610
9744
|
onClose,
|
|
9611
9745
|
onMenuLevelChange,
|
|
9746
|
+
transitionDirection,
|
|
9612
9747
|
...props
|
|
9613
9748
|
}) {
|
|
9614
9749
|
const rootLevel = React.useMemo(
|
|
@@ -9621,6 +9756,7 @@ function ContextMenuContent({
|
|
|
9621
9756
|
[Header2, items, ItemsWrapper, menuClassName]
|
|
9622
9757
|
);
|
|
9623
9758
|
const [menuStack, setMenuStack] = React.useState(() => [rootLevel]);
|
|
9759
|
+
const [menuBodyAnimationKey, setMenuBodyAnimationKey] = React.useState(0);
|
|
9624
9760
|
const activeMenu = menuStack[menuStack.length - 1];
|
|
9625
9761
|
const ActiveMenuItemsWrapper = activeMenu.ItemsWrapper ?? React.Fragment;
|
|
9626
9762
|
const closeMenu = React.useCallback(() => {
|
|
@@ -9644,10 +9780,9 @@ function ContextMenuContent({
|
|
|
9644
9780
|
[ItemsWrapper]
|
|
9645
9781
|
);
|
|
9646
9782
|
const returnToParentMenu = React.useCallback(() => {
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
}, []);
|
|
9783
|
+
if (menuStack.length <= 1) return;
|
|
9784
|
+
setMenuStack((current) => current.slice(0, current.length - 1));
|
|
9785
|
+
}, [menuStack.length]);
|
|
9651
9786
|
React.useEffect(() => {
|
|
9652
9787
|
setMenuStack((current) => {
|
|
9653
9788
|
if (current.length === 1 && current[0] === rootLevel) return current;
|
|
@@ -9657,42 +9792,116 @@ function ContextMenuContent({
|
|
|
9657
9792
|
React.useEffect(() => {
|
|
9658
9793
|
onMenuLevelChange?.(menuStack.length);
|
|
9659
9794
|
}, [menuStack.length, onMenuLevelChange]);
|
|
9660
|
-
|
|
9661
|
-
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9795
|
+
React.useEffect(() => {
|
|
9796
|
+
if (!transitionDirection) return;
|
|
9797
|
+
setMenuBodyAnimationKey((value) => value + 1);
|
|
9798
|
+
}, [transitionDirection, menuStack.length]);
|
|
9799
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContextMenuContext.Provider, { value: { closeMenu, openSubmenu, returnToParentMenu }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9800
|
+
ContextMenuRoot,
|
|
9801
|
+
{
|
|
9802
|
+
className: clsx(className, activeMenu.menuClassName),
|
|
9803
|
+
"data-str-chat-enable-animations": enableAnimations,
|
|
9804
|
+
...props,
|
|
9805
|
+
children: [
|
|
9806
|
+
activeMenu.Header ? /* @__PURE__ */ jsxRuntime.jsx(activeMenu.Header, {}) : menuStack.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuBackButton, { onClick: returnToParentMenu, children: [
|
|
9807
|
+
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {}),
|
|
9808
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: backLabel })
|
|
9809
|
+
] }) }) : null,
|
|
9810
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9811
|
+
ContextMenuBody,
|
|
9812
|
+
{
|
|
9813
|
+
className: clsx({
|
|
9814
|
+
"str-chat__context-menu__body--submenu-backward": transitionDirection === "backward",
|
|
9815
|
+
"str-chat__context-menu__body--submenu-forward": transitionDirection === "forward"
|
|
9816
|
+
}),
|
|
9817
|
+
children: activeMenu.Submenu ? /* @__PURE__ */ jsxRuntime.jsx(activeMenu.Submenu, {}) : /* @__PURE__ */ jsxRuntime.jsx(ActiveMenuItemsWrapper, { children: typeof children !== "undefined" ? children : activeMenu.items?.map((Item2, index) => /* @__PURE__ */ jsxRuntime.jsx(Item2, {}, `context-menu-item-${index}`)) })
|
|
9818
|
+
},
|
|
9819
|
+
`context-menu-body-${menuStack.length}-${menuBodyAnimationKey}`
|
|
9820
|
+
)
|
|
9821
|
+
]
|
|
9822
|
+
}
|
|
9823
|
+
) });
|
|
9667
9824
|
}
|
|
9668
9825
|
const ContextMenu = (props) => {
|
|
9826
|
+
const { ContextMenuContent: ContextMenuContentComponent = ContextMenuContent } = WithAudioPlayback.useComponentContext();
|
|
9669
9827
|
const {
|
|
9670
9828
|
allowFlip,
|
|
9829
|
+
closeOnClickOutside,
|
|
9830
|
+
closeTransitionMs = 130,
|
|
9671
9831
|
dialogManagerId,
|
|
9672
9832
|
focus: focus2,
|
|
9673
9833
|
id,
|
|
9674
9834
|
placement,
|
|
9675
9835
|
referenceElement,
|
|
9836
|
+
submenuTransitionDurationMs,
|
|
9676
9837
|
tabIndex,
|
|
9677
9838
|
trapFocus,
|
|
9678
9839
|
...menuProps
|
|
9679
9840
|
} = props;
|
|
9841
|
+
const resolvedSubmenuTransitionDurationMs = submenuTransitionDurationMs ?? 460;
|
|
9680
9842
|
const isAnchored = id != null;
|
|
9681
9843
|
const [menuLevel, setMenuLevel] = React.useState(1);
|
|
9844
|
+
const [transitionDirection, setTransitionDirection] = React.useState(void 0);
|
|
9845
|
+
const [contentResetToken, setContentResetToken] = React.useState(0);
|
|
9846
|
+
const transitionTimeoutRef = React.useRef(null);
|
|
9847
|
+
const previousMenuLevelRef = React.useRef(1);
|
|
9682
9848
|
const open = useDialogIsOpen(id ?? "", dialogManagerId);
|
|
9849
|
+
const previousOpenRef = React.useRef(open);
|
|
9683
9850
|
React.useEffect(() => {
|
|
9684
|
-
if (isAnchored
|
|
9851
|
+
if (!isAnchored) return;
|
|
9852
|
+
if (previousOpenRef.current && !open) {
|
|
9853
|
+
setMenuLevel(1);
|
|
9854
|
+
setTransitionDirection(void 0);
|
|
9855
|
+
setContentResetToken((value) => value + 1);
|
|
9856
|
+
previousMenuLevelRef.current = 1;
|
|
9857
|
+
if (transitionTimeoutRef.current) {
|
|
9858
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
9859
|
+
transitionTimeoutRef.current = null;
|
|
9860
|
+
}
|
|
9861
|
+
}
|
|
9862
|
+
previousOpenRef.current = open;
|
|
9685
9863
|
}, [isAnchored, open]);
|
|
9686
|
-
|
|
9687
|
-
|
|
9864
|
+
React.useEffect(
|
|
9865
|
+
() => () => {
|
|
9866
|
+
if (transitionTimeoutRef.current) {
|
|
9867
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
9868
|
+
}
|
|
9869
|
+
},
|
|
9870
|
+
[]
|
|
9871
|
+
);
|
|
9872
|
+
const handleMenuLevelChange = React.useCallback(
|
|
9873
|
+
(level) => {
|
|
9874
|
+
if (isAnchored) {
|
|
9875
|
+
const previousLevel = previousMenuLevelRef.current;
|
|
9876
|
+
if (level !== previousLevel) {
|
|
9877
|
+
setTransitionDirection(level > previousLevel ? "forward" : "backward");
|
|
9878
|
+
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
9879
|
+
transitionTimeoutRef.current = setTimeout(() => {
|
|
9880
|
+
setTransitionDirection(void 0);
|
|
9881
|
+
transitionTimeoutRef.current = null;
|
|
9882
|
+
}, resolvedSubmenuTransitionDurationMs);
|
|
9883
|
+
}
|
|
9884
|
+
previousMenuLevelRef.current = level;
|
|
9885
|
+
setMenuLevel(level);
|
|
9886
|
+
return;
|
|
9887
|
+
}
|
|
9888
|
+
menuProps.onMenuLevelChange?.(level);
|
|
9889
|
+
},
|
|
9890
|
+
[isAnchored, menuProps, resolvedSubmenuTransitionDurationMs]
|
|
9891
|
+
);
|
|
9892
|
+
const content = /* @__PURE__ */ React.createElement(
|
|
9893
|
+
ContextMenuContentComponent,
|
|
9688
9894
|
{
|
|
9689
9895
|
...menuProps,
|
|
9690
|
-
|
|
9896
|
+
key: `context-menu-content-${contentResetToken}`,
|
|
9897
|
+
onMenuLevelChange: handleMenuLevelChange,
|
|
9898
|
+
transitionDirection
|
|
9691
9899
|
}
|
|
9692
9900
|
);
|
|
9693
9901
|
if (isAnchored) {
|
|
9694
9902
|
const {
|
|
9695
9903
|
backLabel: _b,
|
|
9904
|
+
enableAnimations: _ea,
|
|
9696
9905
|
Header: _h,
|
|
9697
9906
|
items: _i,
|
|
9698
9907
|
ItemsWrapper: _w,
|
|
@@ -9705,6 +9914,8 @@ const ContextMenu = (props) => {
|
|
|
9705
9914
|
DialogAnchor,
|
|
9706
9915
|
{
|
|
9707
9916
|
allowFlip,
|
|
9917
|
+
closeOnClickOutside,
|
|
9918
|
+
closeTransitionMs,
|
|
9708
9919
|
dialogManagerId,
|
|
9709
9920
|
focus: focus2,
|
|
9710
9921
|
id,
|
|
@@ -9858,9 +10069,9 @@ const GlobalModal = ({
|
|
|
9858
10069
|
(source, event) => {
|
|
9859
10070
|
const allow = onCloseAttempt?.(source, event);
|
|
9860
10071
|
if (allow !== false) {
|
|
9861
|
-
onClose?.(event);
|
|
9862
10072
|
dialog.close();
|
|
9863
10073
|
closingRef.current = true;
|
|
10074
|
+
onClose?.(event);
|
|
9864
10075
|
}
|
|
9865
10076
|
},
|
|
9866
10077
|
[dialog, onClose, onCloseAttempt]
|
|
@@ -10036,16 +10247,19 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10036
10247
|
const isMessageThreadReply = typeof message.parent_id === "string";
|
|
10037
10248
|
const isBounced = WithAudioPlayback.isMessageBounced(message);
|
|
10038
10249
|
const allowRetry = WithAudioPlayback.isMessageErrorRetryable(message);
|
|
10250
|
+
const hasNetworkSendFailure = WithAudioPlayback.isNetworkSendFailure(message);
|
|
10039
10251
|
return React.useMemo(() => {
|
|
10040
10252
|
if (disable) return messageActionSet;
|
|
10041
10253
|
if (isBounced || isInitialMessage || // not sure whether this thing even works anymore
|
|
10042
10254
|
!message.type || message.type === "system" || message.type === "ephemeral" || message.status === "sending")
|
|
10043
10255
|
return [];
|
|
10044
|
-
return messageActionSet.filter((
|
|
10256
|
+
return messageActionSet.filter((action) => {
|
|
10257
|
+
if (action.placement === "quick-dropdown-toggle") return true;
|
|
10258
|
+
const type = action.type;
|
|
10045
10259
|
if (WithAudioPlayback.ACTIONS_NOT_WORKING_IN_THREAD.includes(type) && isMessageThreadReply)
|
|
10046
10260
|
return false;
|
|
10047
10261
|
if (message.error) {
|
|
10048
|
-
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" &&
|
|
10262
|
+
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" && (isBounced && canEdit || hasNetworkSendFailure) || type === "delete" && (isBounced && canDelete || hasNetworkSendFailure);
|
|
10049
10263
|
}
|
|
10050
10264
|
if (type === "resendMessage" || type === "blockUser" && !canBlockUser || type === "copyMessageText" && !message.text || type === "delete" && !canDelete || type === "edit" && !canEdit || type === "flag" && !canFlag || type === "markUnread" && !canMarkUnread || type === "mute" && !canMute || type === "quote" && !canQuote || type === "react" && !canReact || type === "reply" && !canReply || type === "remindMe" && !channelConfig?.["user_message_reminders"] || type === "saveForLater" && !channelConfig?.["user_message_reminders"])
|
|
10051
10265
|
return false;
|
|
@@ -10072,6 +10286,7 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10072
10286
|
message.text,
|
|
10073
10287
|
message.type,
|
|
10074
10288
|
disable,
|
|
10289
|
+
hasNetworkSendFailure,
|
|
10075
10290
|
messageActionSet
|
|
10076
10291
|
]);
|
|
10077
10292
|
};
|
|
@@ -10696,17 +10911,6 @@ const renderText = (text2, mentionedUsers, {
|
|
|
10696
10911
|
}
|
|
10697
10912
|
) });
|
|
10698
10913
|
};
|
|
10699
|
-
const ROOT_CLASS_NAME = "str-chat__message--error-message";
|
|
10700
|
-
function MessageErrorText({ message }) {
|
|
10701
|
-
const { t } = WithAudioPlayback.useTranslationContext("MessageText");
|
|
10702
|
-
if (message.type === "error" && !WithAudioPlayback.isMessageBounced(message)) {
|
|
10703
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ROOT_CLASS_NAME, children: t("Error · Unsent") });
|
|
10704
|
-
}
|
|
10705
|
-
if (message.status === "failed") {
|
|
10706
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ROOT_CLASS_NAME, children: message.error?.status !== 403 ? t("Message Failed · Click to try again") : t("Message Failed · Unauthorized") });
|
|
10707
|
-
}
|
|
10708
|
-
return null;
|
|
10709
|
-
}
|
|
10710
10914
|
const UnMemoizedMessageTextComponent = (props) => {
|
|
10711
10915
|
const {
|
|
10712
10916
|
customInnerClass,
|
|
@@ -10734,7 +10938,7 @@ const UnMemoizedMessageTextComponent = (props) => {
|
|
|
10734
10938
|
const wrapperClass = customWrapperClass || "str-chat__message-text";
|
|
10735
10939
|
const innerClass = customInnerClass;
|
|
10736
10940
|
if (!messageTextToRender) return null;
|
|
10737
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClass, tabIndex: 0, children: /* @__PURE__ */ jsxRuntime.
|
|
10941
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: wrapperClass, tabIndex: 0, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10738
10942
|
"div",
|
|
10739
10943
|
{
|
|
10740
10944
|
className: clsx(innerClass, {
|
|
@@ -10744,10 +10948,7 @@ const UnMemoizedMessageTextComponent = (props) => {
|
|
|
10744
10948
|
"data-testid": "message-text-inner-wrapper",
|
|
10745
10949
|
onClick: onMentionsClickMessage,
|
|
10746
10950
|
onMouseOver: onMentionsHoverMessage,
|
|
10747
|
-
children:
|
|
10748
|
-
/* @__PURE__ */ jsxRuntime.jsx(MessageErrorText, { message }),
|
|
10749
|
-
unsafeHTML && message.html ? /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: message.html } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: messageText })
|
|
10750
|
-
]
|
|
10951
|
+
children: unsafeHTML && message.html ? /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: message.html } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: messageText })
|
|
10751
10952
|
}
|
|
10752
10953
|
) });
|
|
10753
10954
|
};
|
|
@@ -11962,6 +12163,7 @@ const toBaseImageDescriptors = (attachment, options = {}) => {
|
|
|
11962
12163
|
title: attachment.title
|
|
11963
12164
|
};
|
|
11964
12165
|
}
|
|
12166
|
+
return void 0;
|
|
11965
12167
|
};
|
|
11966
12168
|
const BASE_FILE_ICON_CLASSNAME = "str-chat__file-icon";
|
|
11967
12169
|
const FILE_ICON_GRAPHIC_CLASSNAME = "str-chat__file-icon__graphic";
|
|
@@ -14799,7 +15001,8 @@ const PollOptionWithVotes = ({
|
|
|
14799
15001
|
"div",
|
|
14800
15002
|
{
|
|
14801
15003
|
className: clsx("str-chat__poll-option", {
|
|
14802
|
-
"str-chat__poll-option--has-more-votes": isVotesPreview && voteCount > countVotesPreview
|
|
15004
|
+
"str-chat__poll-option--has-more-votes": isVotesPreview && voteCount > countVotesPreview,
|
|
15005
|
+
"str-chat__poll-option--has-votes": voteCount
|
|
14803
15006
|
}),
|
|
14804
15007
|
children: [
|
|
14805
15008
|
/* @__PURE__ */ jsxRuntime.jsx(PollOptionWithVotesHeader, { option, optionOrderNumber: orderNumber }),
|
|
@@ -15093,10 +15296,12 @@ const PollOptionSelector = ({
|
|
|
15093
15296
|
canCastVote && /* @__PURE__ */ jsxRuntime.jsx(Checkmark, { checked: !!ownVotesByOptionId[option.id] }),
|
|
15094
15297
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__poll-option-data", children: [
|
|
15095
15298
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "str-chat__poll-option-text", children: option.text }),
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15299
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__poll-option-votes", children: [
|
|
15300
|
+
displayAvatarCount && voting_visibility === "public" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__poll-option-voters", children: /* @__PURE__ */ jsxRuntime.jsx(AvatarStack$1, { displayInfo: avatarDisplayInfo, size: "xs" }) }),
|
|
15301
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__poll-option-vote-count", children: voteCountVerbose ? t("{{count}} votes", {
|
|
15302
|
+
count: vote_counts_by_option[option.id] ?? 0
|
|
15303
|
+
}) : vote_counts_by_option[option.id] ?? 0 })
|
|
15304
|
+
] })
|
|
15100
15305
|
] }),
|
|
15101
15306
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15102
15307
|
AmountBar,
|
|
@@ -15611,31 +15816,34 @@ const CommandContextMenuItem = ({
|
|
|
15611
15816
|
}
|
|
15612
15817
|
);
|
|
15613
15818
|
};
|
|
15614
|
-
const AttachmentSelectorMenuInitButtonIcon = () => {
|
|
15819
|
+
const AttachmentSelectorMenuInitButtonIcon = ({ className }) => {
|
|
15615
15820
|
const { AttachmentSelectorInitiationButtonContents } = WithAudioPlayback.useComponentContext();
|
|
15616
15821
|
if (AttachmentSelectorInitiationButtonContents) {
|
|
15617
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AttachmentSelectorInitiationButtonContents, {});
|
|
15822
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { className, children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentSelectorInitiationButtonContents, {}) });
|
|
15618
15823
|
}
|
|
15619
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15824
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15825
|
+
WithAudioPlayback.IconPlusLarge,
|
|
15826
|
+
{
|
|
15827
|
+
className: clsx("str-chat__attachment-selector__menu-button__icon", className)
|
|
15828
|
+
}
|
|
15829
|
+
);
|
|
15620
15830
|
};
|
|
15621
|
-
const AttachmentSelectorButton = React.forwardRef(
|
|
15622
|
-
|
|
15623
|
-
|
|
15624
|
-
|
|
15625
|
-
|
|
15626
|
-
|
|
15627
|
-
|
|
15628
|
-
|
|
15629
|
-
|
|
15630
|
-
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
}
|
|
15638
|
-
);
|
|
15831
|
+
const AttachmentSelectorButton = React.forwardRef(function AttachmentSelectorButton2({ className, iconClassName, ...props }, ref) {
|
|
15832
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15833
|
+
WithAudioPlayback.Button,
|
|
15834
|
+
{
|
|
15835
|
+
appearance: "outline",
|
|
15836
|
+
circular: true,
|
|
15837
|
+
className: clsx("str-chat__attachment-selector__menu-button", className),
|
|
15838
|
+
"data-testid": "invoke-attachment-selector-button",
|
|
15839
|
+
size: "lg",
|
|
15840
|
+
variant: "secondary",
|
|
15841
|
+
...props,
|
|
15842
|
+
ref,
|
|
15843
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentSelectorMenuInitButtonIcon, { className: iconClassName })
|
|
15844
|
+
}
|
|
15845
|
+
);
|
|
15846
|
+
});
|
|
15639
15847
|
const SimpleAttachmentSelector = () => {
|
|
15640
15848
|
const { channelCapabilities } = WithAudioPlayback.useChannelStateContext();
|
|
15641
15849
|
const inputRef = React.useRef(null);
|
|
@@ -15807,7 +16015,7 @@ const AttachmentSelector = ({
|
|
|
15807
16015
|
getModalPortalDestination
|
|
15808
16016
|
}) => {
|
|
15809
16017
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
15810
|
-
const { Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
16018
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu, Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
15811
16019
|
const { channelCapabilities } = WithAudioPlayback.useChannelStateContext();
|
|
15812
16020
|
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
15813
16021
|
const isCooldownActive = WithAudioPlayback.useIsCooldownActive();
|
|
@@ -15858,16 +16066,16 @@ const AttachmentSelector = ({
|
|
|
15858
16066
|
"aria-expanded": menuDialogIsOpen,
|
|
15859
16067
|
"aria-haspopup": "true",
|
|
15860
16068
|
"aria-label": t("aria/Open Attachment Selector"),
|
|
15861
|
-
|
|
16069
|
+
disabled: isCooldownActive,
|
|
16070
|
+
iconClassName: clsx("str-chat__prepare-rotate45", {
|
|
15862
16071
|
"str-chat__rotate45": menuDialogIsOpen
|
|
15863
16072
|
}),
|
|
15864
|
-
disabled: isCooldownActive,
|
|
15865
16073
|
onClick: () => menuDialog?.toggle(),
|
|
15866
16074
|
ref: menuButtonRef
|
|
15867
16075
|
}
|
|
15868
16076
|
),
|
|
15869
16077
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
15870
|
-
|
|
16078
|
+
ContextMenuComponent,
|
|
15871
16079
|
{
|
|
15872
16080
|
allowFlip: true,
|
|
15873
16081
|
backLabel: t("Back"),
|
|
@@ -15986,562 +16194,175 @@ const PlayIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
|
15986
16194
|
}
|
|
15987
16195
|
);
|
|
15988
16196
|
const CheckSignIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { fill: "currentColor", viewBox: "0 0 18 14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.79457 10.875L2.32457 7.40502C1.93457 7.01502 1.30457 7.01502 0.91457 7.40502C0.52457 7.79502 0.52457 8.42502 0.91457 8.81502L5.09457 12.995C5.48457 13.385 6.11457 13.385 6.50457 12.995L17.0846 2.41502C17.4746 2.02502 17.4746 1.39502 17.0846 1.00502C16.6946 0.615024 16.0646 0.615024 15.6746 1.00502L5.79457 10.875Z" }) });
|
|
15989
|
-
const
|
|
15990
|
-
|
|
15991
|
-
|
|
15992
|
-
|
|
15993
|
-
|
|
15994
|
-
|
|
15995
|
-
|
|
15996
|
-
);
|
|
15997
|
-
return {};
|
|
16197
|
+
const INTERACTIVE_SELECTOR = 'button, a, input, textarea, select, [role="button"], [role="link"], [data-interactive="true"]';
|
|
16198
|
+
function hasInteractiveAncestorBeforeRoot(target, root) {
|
|
16199
|
+
if (!(target instanceof Element) || !root) return false;
|
|
16200
|
+
let el = target;
|
|
16201
|
+
while (el && el !== root) {
|
|
16202
|
+
if (el.matches(INTERACTIVE_SELECTOR)) return true;
|
|
16203
|
+
el = el.parentElement;
|
|
15998
16204
|
}
|
|
15999
|
-
return
|
|
16000
|
-
}
|
|
16001
|
-
const
|
|
16002
|
-
|
|
16003
|
-
|
|
16004
|
-
|
|
16005
|
-
|
|
16006
|
-
|
|
16007
|
-
onRequestClose
|
|
16205
|
+
return false;
|
|
16206
|
+
}
|
|
16207
|
+
const AttachmentPreviewRoot = ({
|
|
16208
|
+
attachment,
|
|
16209
|
+
onPressed,
|
|
16210
|
+
openPreview,
|
|
16211
|
+
tabIndex = 0,
|
|
16212
|
+
...props
|
|
16008
16213
|
}) => {
|
|
16009
|
-
const [currentIndex, setCurrentIndex] = React.useState(initialIndex);
|
|
16010
|
-
const itemCount = items.length;
|
|
16011
|
-
const goToIndex = React.useCallback(
|
|
16012
|
-
(index) => {
|
|
16013
|
-
if (index >= 0 && index < itemCount) {
|
|
16014
|
-
setCurrentIndex(index);
|
|
16015
|
-
}
|
|
16016
|
-
},
|
|
16017
|
-
[itemCount]
|
|
16018
|
-
);
|
|
16019
|
-
const goToNext = React.useCallback(() => {
|
|
16020
|
-
setCurrentIndex((prev) => prev < itemCount - 1 ? prev + 1 : prev);
|
|
16021
|
-
}, [itemCount]);
|
|
16022
|
-
const goToPrevious = React.useCallback(() => {
|
|
16023
|
-
setCurrentIndex((prev) => prev > 0 ? prev - 1 : prev);
|
|
16024
|
-
}, []);
|
|
16025
|
-
React.useEffect(() => {
|
|
16026
|
-
onIndexChange?.(currentIndex);
|
|
16027
|
-
}, [currentIndex, onIndexChange]);
|
|
16028
|
-
const hasNext = currentIndex < itemCount - 1;
|
|
16029
|
-
const hasPrevious = currentIndex > 0;
|
|
16030
|
-
const currentItem = items[currentIndex];
|
|
16031
|
-
const contextValue = React.useMemo(
|
|
16032
|
-
() => ({
|
|
16033
|
-
closeOnBackgroundClick,
|
|
16034
|
-
currentIndex,
|
|
16035
|
-
currentItem,
|
|
16036
|
-
goToIndex,
|
|
16037
|
-
goToNext,
|
|
16038
|
-
goToPrevious,
|
|
16039
|
-
hasNext,
|
|
16040
|
-
hasPrevious,
|
|
16041
|
-
itemCount,
|
|
16042
|
-
items,
|
|
16043
|
-
onRequestClose
|
|
16044
|
-
}),
|
|
16045
|
-
[
|
|
16046
|
-
closeOnBackgroundClick,
|
|
16047
|
-
currentIndex,
|
|
16048
|
-
currentItem,
|
|
16049
|
-
goToIndex,
|
|
16050
|
-
goToNext,
|
|
16051
|
-
goToPrevious,
|
|
16052
|
-
hasNext,
|
|
16053
|
-
hasPrevious,
|
|
16054
|
-
itemCount,
|
|
16055
|
-
items,
|
|
16056
|
-
onRequestClose
|
|
16057
|
-
]
|
|
16058
|
-
);
|
|
16059
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GalleryContext.Provider, { value: contextValue, children: GalleryUI2 ? /* @__PURE__ */ jsxRuntime.jsx(GalleryUI2, {}) : null });
|
|
16060
|
-
};
|
|
16061
|
-
const GalleryHeader = ({ currentItem }) => {
|
|
16062
16214
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
16063
|
-
const
|
|
16064
|
-
const
|
|
16065
|
-
const
|
|
16066
|
-
const
|
|
16067
|
-
const
|
|
16068
|
-
|
|
16069
|
-
if (
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
"a",
|
|
16083
|
-
{
|
|
16084
|
-
"aria-label": downloadLabel,
|
|
16085
|
-
className: "str-chat__gallery__action-button str-chat__gallery__action-button--download",
|
|
16086
|
-
download: true,
|
|
16087
|
-
href: downloadUrl,
|
|
16088
|
-
rel: "noreferrer",
|
|
16089
|
-
target: "_blank",
|
|
16090
|
-
title: downloadLabel,
|
|
16091
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconArrowDownCircle, {})
|
|
16092
|
-
}
|
|
16093
|
-
) : null,
|
|
16094
|
-
modalContext?.close ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
16095
|
-
WithAudioPlayback.Button,
|
|
16096
|
-
{
|
|
16097
|
-
"aria-label": t("Close"),
|
|
16098
|
-
className: "str-chat__gallery__action-button str-chat__gallery__action-button--close",
|
|
16099
|
-
onClick: modalContext.close,
|
|
16100
|
-
title: t("Close"),
|
|
16101
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconCrossMedium, {})
|
|
16102
|
-
}
|
|
16103
|
-
) : null
|
|
16104
|
-
] })
|
|
16105
|
-
] });
|
|
16106
|
-
};
|
|
16107
|
-
const VideoPlayer = ({ isPlaying, thumbnailUrl, videoUrl }) => {
|
|
16108
|
-
const { VideoPlayer: VideoPlayerContext } = WithAudioPlayback.useComponentContext();
|
|
16109
|
-
return VideoPlayerContext ? /* @__PURE__ */ jsxRuntime.jsx(VideoPlayerContext, { thumbnailUrl, videoUrl }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
16110
|
-
ReactPlayer,
|
|
16215
|
+
const [root, setRoot] = React.useState(null);
|
|
16216
|
+
const url = attachment.asset_url || attachment.image_url || attachment.localMetadata.previewUri;
|
|
16217
|
+
const canDownloadAttachment = false;
|
|
16218
|
+
const canPreviewAttachment = !!openPreview && (!!url && streamChat.isImageAttachment(attachment) || streamChat.isVideoAttachment(attachment));
|
|
16219
|
+
const handlePressed = (e) => {
|
|
16220
|
+
if (e.defaultPrevented) return;
|
|
16221
|
+
if (hasInteractiveAncestorBeforeRoot(e.target, root)) return;
|
|
16222
|
+
if (onPressed) {
|
|
16223
|
+
const shouldContinue = onPressed(e);
|
|
16224
|
+
if (!shouldContinue) return;
|
|
16225
|
+
}
|
|
16226
|
+
if (canPreviewAttachment) {
|
|
16227
|
+
openPreview();
|
|
16228
|
+
return;
|
|
16229
|
+
}
|
|
16230
|
+
};
|
|
16231
|
+
const isInteractive = canPreviewAttachment || canDownloadAttachment;
|
|
16232
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16233
|
+
"div",
|
|
16111
16234
|
{
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
|
|
16235
|
+
"aria-label": isInteractive ? t(canPreviewAttachment ? "aria/Show preview" : "aria/Download attachment") : void 0,
|
|
16236
|
+
...props,
|
|
16237
|
+
onClick: handlePressed,
|
|
16238
|
+
onKeyDown: isInteractive ? (e) => {
|
|
16239
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
16240
|
+
e.preventDefault();
|
|
16241
|
+
handlePressed(e);
|
|
16242
|
+
} : void 0,
|
|
16243
|
+
ref: setRoot,
|
|
16244
|
+
tabIndex: isInteractive ? tabIndex : -1,
|
|
16245
|
+
children: props.children
|
|
16119
16246
|
}
|
|
16120
16247
|
);
|
|
16121
16248
|
};
|
|
16122
|
-
const
|
|
16123
|
-
|
|
16124
|
-
|
|
16125
|
-
|
|
16249
|
+
const FileAttachmentPreview = ({
|
|
16250
|
+
attachment,
|
|
16251
|
+
handleRetry,
|
|
16252
|
+
removeAttachments
|
|
16126
16253
|
}) => {
|
|
16127
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16133
|
-
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
"
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
"str-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
}
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16254
|
+
const { t } = WithAudioPlayback.useTranslationContext("FilePreview");
|
|
16255
|
+
const { id, uploadPermissionCheck, uploadState } = attachment.localMetadata ?? {};
|
|
16256
|
+
const hasSizeLimitError = uploadPermissionCheck?.reason === "size_limit";
|
|
16257
|
+
const hasFatalError = uploadState === "blocked" || hasSizeLimitError;
|
|
16258
|
+
const hasRetriableError = uploadState === "failed" && !!handleRetry;
|
|
16259
|
+
const hasError = hasRetriableError || hasFatalError;
|
|
16260
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16261
|
+
AttachmentPreviewRoot,
|
|
16262
|
+
{
|
|
16263
|
+
attachment,
|
|
16264
|
+
className: "str-chat__attachment-preview-file",
|
|
16265
|
+
"data-testid": "attachment-preview-file",
|
|
16266
|
+
children: [
|
|
16267
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__attachment-preview-file__icon", children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { fileName: attachment.title, mimeType: attachment.mime_type }) }),
|
|
16268
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__info", children: [
|
|
16269
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__attachment-preview-file-name", title: attachment.title, children: attachment.title }),
|
|
16270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__data", children: [
|
|
16271
|
+
uploadState === "uploading" && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicatorIcon, {}),
|
|
16272
|
+
!hasError && /* @__PURE__ */ jsxRuntime.jsx(FileSizeIndicator, { fileSize: attachment.file_size }),
|
|
16273
|
+
hasFatalError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__fatal-error", children: [
|
|
16274
|
+
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationCircle, {}),
|
|
16275
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
|
|
16276
|
+
] }),
|
|
16277
|
+
hasRetriableError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
|
|
16278
|
+
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangle, {}),
|
|
16279
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Upload error") }),
|
|
16280
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16281
|
+
"button",
|
|
16282
|
+
{
|
|
16283
|
+
"aria-label": t("aria/Retry upload"),
|
|
16284
|
+
className: "str-chat__attachment-preview-file__retry-upload-button",
|
|
16285
|
+
"data-testid": "file-preview-item-retry-button",
|
|
16286
|
+
onClick: () => {
|
|
16287
|
+
handleRetry(attachment);
|
|
16288
|
+
},
|
|
16289
|
+
type: "button",
|
|
16290
|
+
children: t("Retry upload")
|
|
16291
|
+
}
|
|
16292
|
+
)
|
|
16293
|
+
] })
|
|
16294
|
+
] })
|
|
16295
|
+
] }),
|
|
16296
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16297
|
+
RemoveAttachmentPreviewButton,
|
|
16298
|
+
{
|
|
16299
|
+
"data-testid": "file-preview-item-delete-button",
|
|
16300
|
+
onClick: () => {
|
|
16301
|
+
if (id) removeAttachments([id]);
|
|
16302
|
+
},
|
|
16303
|
+
uploadState
|
|
16304
|
+
}
|
|
16305
|
+
)
|
|
16306
|
+
]
|
|
16307
|
+
}
|
|
16175
16308
|
);
|
|
16176
|
-
const ignoreNextClickRef = React.useRef(false);
|
|
16177
|
-
const touchStartRef = React.useRef(null);
|
|
16178
|
-
const isVerticalSwipeRef = React.useRef(false);
|
|
16179
|
-
const containerRef = React.useRef(null);
|
|
16180
|
-
React.useEffect(() => {
|
|
16181
|
-
setShowVideo(false);
|
|
16182
|
-
}, [currentIndex]);
|
|
16183
|
-
const prevIndexRef = React.useRef(currentIndex);
|
|
16184
|
-
React.useEffect(() => {
|
|
16185
|
-
if (prevIndexRef.current === currentIndex) return;
|
|
16186
|
-
const direction = currentIndex > prevIndexRef.current ? "forward" : "backward";
|
|
16187
|
-
setSlideDirection(direction);
|
|
16188
|
-
setSlideOffset(0);
|
|
16189
|
-
setIsDragging(false);
|
|
16190
|
-
isTransitioningRef.current = true;
|
|
16191
|
-
const timer = setTimeout(() => {
|
|
16192
|
-
setSlideDirection(null);
|
|
16193
|
-
isTransitioningRef.current = false;
|
|
16194
|
-
}, TRANSITION_DURATION);
|
|
16195
|
-
prevIndexRef.current = currentIndex;
|
|
16196
|
-
return () => clearTimeout(timer);
|
|
16197
|
-
}, [currentIndex]);
|
|
16198
|
-
const handleGoToNext = React.useCallback(() => {
|
|
16199
|
-
if (isTransitioningRef.current) return;
|
|
16200
|
-
goToNext();
|
|
16201
|
-
}, [goToNext]);
|
|
16202
|
-
const handleGoToPrevious = React.useCallback(() => {
|
|
16203
|
-
if (isTransitioningRef.current) return;
|
|
16204
|
-
goToPrevious();
|
|
16205
|
-
}, [goToPrevious]);
|
|
16206
|
-
const handleKeyDown = React.useCallback(
|
|
16207
|
-
(event) => {
|
|
16208
|
-
if (event.key === "ArrowLeft") {
|
|
16209
|
-
event.preventDefault();
|
|
16210
|
-
handleGoToPrevious();
|
|
16211
|
-
} else if (event.key === "ArrowRight") {
|
|
16212
|
-
event.preventDefault();
|
|
16213
|
-
handleGoToNext();
|
|
16214
|
-
}
|
|
16215
|
-
},
|
|
16216
|
-
[handleGoToNext, handleGoToPrevious]
|
|
16217
|
-
);
|
|
16218
|
-
React.useEffect(() => {
|
|
16219
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
16220
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
16221
|
-
}, [handleKeyDown]);
|
|
16222
|
-
const handleTouchStart = React.useCallback((event) => {
|
|
16223
|
-
if (isTransitioningRef.current) return;
|
|
16224
|
-
const touch = event.touches[0];
|
|
16225
|
-
ignoreNextClickRef.current = false;
|
|
16226
|
-
touchStartRef.current = { x: touch.clientX, y: touch.clientY };
|
|
16227
|
-
isVerticalSwipeRef.current = false;
|
|
16228
|
-
}, []);
|
|
16229
|
-
const handleTouchMove = React.useCallback(
|
|
16230
|
-
(event) => {
|
|
16231
|
-
if (!touchStartRef.current || isTransitioningRef.current) return;
|
|
16232
|
-
const touch = event.touches[0];
|
|
16233
|
-
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
16234
|
-
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
16235
|
-
if (!isDragging && !isVerticalSwipeRef.current) {
|
|
16236
|
-
if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 10) {
|
|
16237
|
-
ignoreNextClickRef.current = true;
|
|
16238
|
-
isVerticalSwipeRef.current = true;
|
|
16239
|
-
return;
|
|
16240
|
-
}
|
|
16241
|
-
if (Math.abs(deltaX) > 10) {
|
|
16242
|
-
ignoreNextClickRef.current = true;
|
|
16243
|
-
setIsDragging(true);
|
|
16244
|
-
}
|
|
16245
|
-
}
|
|
16246
|
-
if (isVerticalSwipeRef.current) return;
|
|
16247
|
-
if (!hasNext && deltaX < 0 || !hasPrevious && deltaX > 0) {
|
|
16248
|
-
setSlideOffset(deltaX * 0.3);
|
|
16249
|
-
} else {
|
|
16250
|
-
setSlideOffset(deltaX);
|
|
16251
|
-
}
|
|
16252
|
-
},
|
|
16253
|
-
[isDragging, hasNext, hasPrevious]
|
|
16254
|
-
);
|
|
16255
|
-
const handleTouchEnd = React.useCallback(() => {
|
|
16256
|
-
if (!touchStartRef.current || isVerticalSwipeRef.current) {
|
|
16257
|
-
if (isVerticalSwipeRef.current) ignoreNextClickRef.current = true;
|
|
16258
|
-
touchStartRef.current = null;
|
|
16259
|
-
return;
|
|
16260
|
-
}
|
|
16261
|
-
const offset = slideOffset;
|
|
16262
|
-
if (isDragging || Math.abs(offset) > 10) {
|
|
16263
|
-
ignoreNextClickRef.current = true;
|
|
16264
|
-
}
|
|
16265
|
-
touchStartRef.current = null;
|
|
16266
|
-
if (Math.abs(offset) >= SWIPE_THRESHOLD) {
|
|
16267
|
-
if (offset < 0 && hasNext) {
|
|
16268
|
-
goToNext();
|
|
16269
|
-
} else if (offset > 0 && hasPrevious) {
|
|
16270
|
-
goToPrevious();
|
|
16271
|
-
} else {
|
|
16272
|
-
setSlideOffset(0);
|
|
16273
|
-
}
|
|
16274
|
-
} else {
|
|
16275
|
-
setSlideOffset(0);
|
|
16276
|
-
}
|
|
16277
|
-
setIsDragging(false);
|
|
16278
|
-
}, [slideOffset, hasNext, hasPrevious, goToNext, goToPrevious, isDragging]);
|
|
16279
|
-
const requestClose = modalContext?.close ?? onRequestClose;
|
|
16280
|
-
const handleBackgroundClick = React.useCallback(
|
|
16281
|
-
(event) => {
|
|
16282
|
-
if (event.target !== event.currentTarget) return;
|
|
16283
|
-
if (ignoreNextClickRef.current) {
|
|
16284
|
-
ignoreNextClickRef.current = false;
|
|
16285
|
-
return;
|
|
16286
|
-
}
|
|
16287
|
-
if (!closeOnBackgroundClick) return;
|
|
16288
|
-
requestClose?.();
|
|
16289
|
-
},
|
|
16290
|
-
[closeOnBackgroundClick, requestClose]
|
|
16291
|
-
);
|
|
16292
|
-
const mediaStyle = isDragging || slideOffset !== 0 && slideDirection === null ? { transform: `translateX(${slideOffset}px)` } : {};
|
|
16293
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery", children: [
|
|
16294
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__main", children: [
|
|
16295
|
-
/* @__PURE__ */ jsxRuntime.jsx(GalleryHeader, { currentItem }),
|
|
16296
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16297
|
-
NavButton,
|
|
16298
|
-
{
|
|
16299
|
-
"aria-label": t("Previous image"),
|
|
16300
|
-
className: clsx(
|
|
16301
|
-
"str-chat__gallery__nav-button--prev",
|
|
16302
|
-
!hasPrevious && "str-chat__gallery__nav-button--hidden"
|
|
16303
|
-
),
|
|
16304
|
-
disabled: !hasPrevious,
|
|
16305
|
-
onClick: handleGoToPrevious,
|
|
16306
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {})
|
|
16307
|
-
}
|
|
16308
|
-
),
|
|
16309
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16310
|
-
"div",
|
|
16311
|
-
{
|
|
16312
|
-
className: "str-chat__gallery__slide-container",
|
|
16313
|
-
onClick: handleBackgroundClick,
|
|
16314
|
-
onTouchEnd: handleTouchEnd,
|
|
16315
|
-
onTouchMove: handleTouchMove,
|
|
16316
|
-
onTouchStart: handleTouchStart,
|
|
16317
|
-
ref: containerRef,
|
|
16318
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
16319
|
-
"div",
|
|
16320
|
-
{
|
|
16321
|
-
className: clsx({
|
|
16322
|
-
"str-chat__gallery__media--dragging": isDragging,
|
|
16323
|
-
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
16324
|
-
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
16325
|
-
}),
|
|
16326
|
-
style: mediaStyle,
|
|
16327
|
-
children: currentItem.videoUrl && currentItem.videoThumbnailUrl ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--video", children: showVideo ? /* @__PURE__ */ jsxRuntime.jsx(VideoPlayer, { isPlaying: true, videoUrl: currentItem.videoUrl }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
16328
|
-
VideoThumbnail,
|
|
16329
|
-
{
|
|
16330
|
-
alt: currentItem.title ?? "",
|
|
16331
|
-
onPlay: () => setShowVideo(true),
|
|
16332
|
-
src: currentItem.videoThumbnailUrl
|
|
16333
|
-
}
|
|
16334
|
-
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--image", children: /* @__PURE__ */ jsxRuntime.jsx(BaseImage, { alt: currentItem.alt, src: currentItem.imageUrl }) })
|
|
16335
|
-
}
|
|
16336
|
-
)
|
|
16337
|
-
}
|
|
16338
|
-
),
|
|
16339
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16340
|
-
NavButton,
|
|
16341
|
-
{
|
|
16342
|
-
"aria-label": t("Next image"),
|
|
16343
|
-
className: clsx(
|
|
16344
|
-
"str-chat__gallery__nav-button--next",
|
|
16345
|
-
!hasNext && "str-chat__gallery__nav-button--hidden"
|
|
16346
|
-
),
|
|
16347
|
-
disabled: !hasNext,
|
|
16348
|
-
onClick: handleGoToNext,
|
|
16349
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronRight, {})
|
|
16350
|
-
}
|
|
16351
|
-
)
|
|
16352
|
-
] }),
|
|
16353
|
-
itemCount > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__position-indicator", children: [
|
|
16354
|
-
currentIndex + 1,
|
|
16355
|
-
" of ",
|
|
16356
|
-
itemCount
|
|
16357
|
-
] })
|
|
16358
|
-
] });
|
|
16359
16309
|
};
|
|
16360
|
-
const
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
|
|
16364
|
-
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16310
|
+
const UnsupportedAttachmentPreview = ({
|
|
16311
|
+
attachment,
|
|
16312
|
+
handleRetry,
|
|
16313
|
+
removeAttachments
|
|
16314
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
16315
|
+
FileAttachmentPreview,
|
|
16316
|
+
{
|
|
16317
|
+
attachment,
|
|
16318
|
+
handleRetry,
|
|
16319
|
+
removeAttachments
|
|
16368
16320
|
}
|
|
16369
|
-
|
|
16321
|
+
);
|
|
16322
|
+
function formatTime(totalSeconds, rounding = "ceil") {
|
|
16323
|
+
if (totalSeconds == null || Number.isNaN(totalSeconds) || totalSeconds < 0) {
|
|
16324
|
+
return null;
|
|
16325
|
+
}
|
|
16326
|
+
const roundedSeconds = rounding === "floor" ? Math.floor(totalSeconds) : Math.ceil(totalSeconds);
|
|
16327
|
+
const hours = Math.floor(roundedSeconds / 3600);
|
|
16328
|
+
const minutes = Math.floor(roundedSeconds % 3600 / 60);
|
|
16329
|
+
const seconds = roundedSeconds % 60;
|
|
16330
|
+
const minSec = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
|
|
16331
|
+
2,
|
|
16332
|
+
"0"
|
|
16333
|
+
)}`;
|
|
16334
|
+
return hours ? `${String(hours).padStart(2, "0")}:${minSec}` : minSec;
|
|
16370
16335
|
}
|
|
16371
|
-
|
|
16372
|
-
|
|
16373
|
-
|
|
16374
|
-
|
|
16375
|
-
|
|
16376
|
-
|
|
16377
|
-
|
|
16378
|
-
const
|
|
16379
|
-
const
|
|
16380
|
-
const
|
|
16381
|
-
const
|
|
16382
|
-
const
|
|
16383
|
-
const
|
|
16384
|
-
const
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
if (onPressed) {
|
|
16388
|
-
const shouldContinue = onPressed(e);
|
|
16389
|
-
if (!shouldContinue) return;
|
|
16390
|
-
}
|
|
16391
|
-
if (canPreviewAttachment) {
|
|
16392
|
-
setShowPreview(true);
|
|
16393
|
-
return;
|
|
16394
|
-
}
|
|
16395
|
-
};
|
|
16336
|
+
function DurationDisplay({
|
|
16337
|
+
className,
|
|
16338
|
+
duration: duration2,
|
|
16339
|
+
isPlaying,
|
|
16340
|
+
secondsElapsed,
|
|
16341
|
+
showRemaining = false
|
|
16342
|
+
}) {
|
|
16343
|
+
const remainingSeconds = duration2 != null && secondsElapsed != null ? Math.max(0, duration2 - secondsElapsed) : void 0;
|
|
16344
|
+
const formattedDuration = formatTime(duration2);
|
|
16345
|
+
const formattedSecondsElapsed = formatTime(secondsElapsed);
|
|
16346
|
+
const formattedRemaining = formatTime(remainingSeconds);
|
|
16347
|
+
const shouldShowElapsed = !!secondsElapsed && secondsElapsed > 0 && secondsElapsed < (duration2 || 0);
|
|
16348
|
+
const canShowRemaining = showRemaining && duration2 != null && secondsElapsed != null;
|
|
16349
|
+
const primaryValue = showRemaining ? formattedRemaining : formattedSecondsElapsed;
|
|
16350
|
+
const showPrimary = (canShowRemaining || shouldShowElapsed) && !!primaryValue;
|
|
16351
|
+
const showDuration = !showPrimary && !!formattedDuration;
|
|
16396
16352
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16397
16353
|
"div",
|
|
16398
16354
|
{
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16405
|
-
|
|
16406
|
-
|
|
16407
|
-
ref: setRoot,
|
|
16408
|
-
role: showPreview ? "button" : props.role,
|
|
16409
|
-
tabIndex: showPreview || canDownloadAttachment ? tabIndex : -1,
|
|
16355
|
+
className: clsx(
|
|
16356
|
+
"str-chat__duration-display",
|
|
16357
|
+
{
|
|
16358
|
+
"str-chat__duration-display--hasProgress": !!secondsElapsed,
|
|
16359
|
+
"str-chat__duration-display--isPlaying": isPlaying
|
|
16360
|
+
},
|
|
16361
|
+
className
|
|
16362
|
+
),
|
|
16410
16363
|
children: [
|
|
16411
|
-
|
|
16412
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16413
|
-
Modal,
|
|
16414
|
-
{
|
|
16415
|
-
className: "str-chat__gallery-modal",
|
|
16416
|
-
onClose: (e) => {
|
|
16417
|
-
e.stopPropagation();
|
|
16418
|
-
setShowPreview(false);
|
|
16419
|
-
},
|
|
16420
|
-
open: showPreview && canPreviewAttachment,
|
|
16421
|
-
children: streamChat.isImageAttachment(attachment) || streamChat.isVideoAttachment(attachment) ? /* @__PURE__ */ jsxRuntime.jsx(Gallery, { items: [attachment] }) : null
|
|
16422
|
-
}
|
|
16423
|
-
)
|
|
16424
|
-
]
|
|
16425
|
-
}
|
|
16426
|
-
);
|
|
16427
|
-
};
|
|
16428
|
-
const FileAttachmentPreview = ({
|
|
16429
|
-
attachment,
|
|
16430
|
-
handleRetry,
|
|
16431
|
-
removeAttachments
|
|
16432
|
-
}) => {
|
|
16433
|
-
const { t } = WithAudioPlayback.useTranslationContext("FilePreview");
|
|
16434
|
-
const { id, uploadPermissionCheck, uploadState } = attachment.localMetadata ?? {};
|
|
16435
|
-
const hasSizeLimitError = uploadPermissionCheck?.reason === "size_limit";
|
|
16436
|
-
const hasFatalError = uploadState === "blocked" || hasSizeLimitError;
|
|
16437
|
-
const hasRetriableError = uploadState === "failed" && !!handleRetry;
|
|
16438
|
-
const hasError = hasRetriableError || hasFatalError;
|
|
16439
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16440
|
-
AttachmentPreviewRoot,
|
|
16441
|
-
{
|
|
16442
|
-
attachment,
|
|
16443
|
-
className: "str-chat__attachment-preview-file",
|
|
16444
|
-
"data-testid": "attachment-preview-file",
|
|
16445
|
-
children: [
|
|
16446
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__attachment-preview-file__icon", children: /* @__PURE__ */ jsxRuntime.jsx(FileIcon, { fileName: attachment.title, mimeType: attachment.mime_type }) }),
|
|
16447
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__info", children: [
|
|
16448
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__attachment-preview-file-name", title: attachment.title, children: attachment.title }),
|
|
16449
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__data", children: [
|
|
16450
|
-
uploadState === "uploading" && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicatorIcon, {}),
|
|
16451
|
-
!hasError && /* @__PURE__ */ jsxRuntime.jsx(FileSizeIndicator, { fileSize: attachment.file_size }),
|
|
16452
|
-
hasFatalError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__fatal-error", children: [
|
|
16453
|
-
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationCircle, {}),
|
|
16454
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
|
|
16455
|
-
] }),
|
|
16456
|
-
hasRetriableError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
|
|
16457
|
-
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationTriangle, {}),
|
|
16458
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Upload error") }),
|
|
16459
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16460
|
-
"button",
|
|
16461
|
-
{
|
|
16462
|
-
"aria-label": t("aria/Retry upload"),
|
|
16463
|
-
className: "str-chat__attachment-preview-file__retry-upload-button",
|
|
16464
|
-
"data-testid": "file-preview-item-retry-button",
|
|
16465
|
-
onClick: () => {
|
|
16466
|
-
handleRetry(attachment);
|
|
16467
|
-
},
|
|
16468
|
-
type: "button",
|
|
16469
|
-
children: t("Retry upload")
|
|
16470
|
-
}
|
|
16471
|
-
)
|
|
16472
|
-
] })
|
|
16473
|
-
] })
|
|
16474
|
-
] }),
|
|
16475
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16476
|
-
RemoveAttachmentPreviewButton,
|
|
16477
|
-
{
|
|
16478
|
-
"data-testid": "file-preview-item-delete-button",
|
|
16479
|
-
onClick: () => {
|
|
16480
|
-
if (id) removeAttachments([id]);
|
|
16481
|
-
},
|
|
16482
|
-
uploadState
|
|
16483
|
-
}
|
|
16484
|
-
)
|
|
16485
|
-
]
|
|
16486
|
-
}
|
|
16487
|
-
);
|
|
16488
|
-
};
|
|
16489
|
-
const UnsupportedAttachmentPreview = ({
|
|
16490
|
-
attachment,
|
|
16491
|
-
handleRetry,
|
|
16492
|
-
removeAttachments
|
|
16493
|
-
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
16494
|
-
FileAttachmentPreview,
|
|
16495
|
-
{
|
|
16496
|
-
attachment,
|
|
16497
|
-
handleRetry,
|
|
16498
|
-
removeAttachments
|
|
16499
|
-
}
|
|
16500
|
-
);
|
|
16501
|
-
function formatTime(totalSeconds, rounding = "ceil") {
|
|
16502
|
-
if (totalSeconds == null || Number.isNaN(totalSeconds) || totalSeconds < 0) {
|
|
16503
|
-
return null;
|
|
16504
|
-
}
|
|
16505
|
-
const roundedSeconds = rounding === "floor" ? Math.floor(totalSeconds) : Math.ceil(totalSeconds);
|
|
16506
|
-
const hours = Math.floor(roundedSeconds / 3600);
|
|
16507
|
-
const minutes = Math.floor(roundedSeconds % 3600 / 60);
|
|
16508
|
-
const seconds = roundedSeconds % 60;
|
|
16509
|
-
const minSec = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
|
|
16510
|
-
2,
|
|
16511
|
-
"0"
|
|
16512
|
-
)}`;
|
|
16513
|
-
return hours ? `${String(hours).padStart(2, "0")}:${minSec}` : minSec;
|
|
16514
|
-
}
|
|
16515
|
-
function DurationDisplay({
|
|
16516
|
-
className,
|
|
16517
|
-
duration: duration2,
|
|
16518
|
-
isPlaying,
|
|
16519
|
-
secondsElapsed,
|
|
16520
|
-
showRemaining = false
|
|
16521
|
-
}) {
|
|
16522
|
-
const remainingSeconds = duration2 != null && secondsElapsed != null ? Math.max(0, duration2 - secondsElapsed) : void 0;
|
|
16523
|
-
const formattedDuration = formatTime(duration2);
|
|
16524
|
-
const formattedSecondsElapsed = formatTime(secondsElapsed);
|
|
16525
|
-
const formattedRemaining = formatTime(remainingSeconds);
|
|
16526
|
-
const shouldShowElapsed = !!secondsElapsed && secondsElapsed > 0 && secondsElapsed < (duration2 || 0);
|
|
16527
|
-
const canShowRemaining = showRemaining && duration2 != null && secondsElapsed != null;
|
|
16528
|
-
const primaryValue = showRemaining ? formattedRemaining : formattedSecondsElapsed;
|
|
16529
|
-
const showPrimary = (canShowRemaining || shouldShowElapsed) && !!primaryValue;
|
|
16530
|
-
const showDuration = !showPrimary && !!formattedDuration;
|
|
16531
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16532
|
-
"div",
|
|
16533
|
-
{
|
|
16534
|
-
className: clsx(
|
|
16535
|
-
"str-chat__duration-display",
|
|
16536
|
-
{
|
|
16537
|
-
"str-chat__duration-display--hasProgress": !!secondsElapsed,
|
|
16538
|
-
"str-chat__duration-display--isPlaying": isPlaying
|
|
16539
|
-
},
|
|
16540
|
-
className
|
|
16541
|
-
),
|
|
16542
|
-
children: [
|
|
16543
|
-
showPrimary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__duration-display__time-elapsed", children: primaryValue }),
|
|
16544
|
-
showDuration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__duration-display__duration", children: formattedDuration })
|
|
16364
|
+
showPrimary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__duration-display__time-elapsed", children: primaryValue }),
|
|
16365
|
+
showDuration && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__duration-display__duration", children: formattedDuration })
|
|
16545
16366
|
]
|
|
16546
16367
|
}
|
|
16547
16368
|
);
|
|
@@ -17048,6 +16869,7 @@ const AudioAttachmentPreview = ({
|
|
|
17048
16869
|
const MediaAttachmentPreview = ({
|
|
17049
16870
|
attachment,
|
|
17050
16871
|
handleRetry,
|
|
16872
|
+
openPreview,
|
|
17051
16873
|
removeAttachments
|
|
17052
16874
|
}) => {
|
|
17053
16875
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
@@ -17088,6 +16910,7 @@ const MediaAttachmentPreview = ({
|
|
|
17088
16910
|
}),
|
|
17089
16911
|
"data-testid": "attachment-preview-media",
|
|
17090
16912
|
onPressed: hasRetriableError ? retry : void 0,
|
|
16913
|
+
openPreview: !isUploading && !hasUploadError ? openPreview : void 0,
|
|
17091
16914
|
children: [
|
|
17092
16915
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__attachment-preview-media__thumbnail-wrapper", children: [
|
|
17093
16916
|
thumbnail.url && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17137,6 +16960,380 @@ const MediaAttachmentPreview = ({
|
|
|
17137
16960
|
}
|
|
17138
16961
|
);
|
|
17139
16962
|
};
|
|
16963
|
+
const toGalleryItemDescriptors = (...args) => toBaseImageDescriptors(...args);
|
|
16964
|
+
const GalleryContext = React.createContext(void 0);
|
|
16965
|
+
const useGalleryContext = () => {
|
|
16966
|
+
const contextValue = React.useContext(GalleryContext);
|
|
16967
|
+
if (!contextValue) {
|
|
16968
|
+
console.warn(
|
|
16969
|
+
`The useGalleryContext hook was called outside of the GalleryContext provider. Make sure this hook is called within a child of the Gallery component.`
|
|
16970
|
+
);
|
|
16971
|
+
return {};
|
|
16972
|
+
}
|
|
16973
|
+
return contextValue;
|
|
16974
|
+
};
|
|
16975
|
+
const GalleryHeader = ({ currentItem }) => {
|
|
16976
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
16977
|
+
const { MessageTimestamp: MessageTimestamp$1 = MessageTimestamp } = WithAudioPlayback.useComponentContext();
|
|
16978
|
+
const { isMyMessage, message } = useMessageContext();
|
|
16979
|
+
const modalContext = React.useContext(ModalContext);
|
|
16980
|
+
const headerTitle = isMyMessage?.() && t("You") || message?.user?.name || message?.user?.id || currentItem.title || t("User uploaded content");
|
|
16981
|
+
const downloadUrl = React.useMemo(() => {
|
|
16982
|
+
const rawDownloadUrl = currentItem.videoUrl ?? currentItem.imageUrl;
|
|
16983
|
+
if (!rawDownloadUrl) return void 0;
|
|
16984
|
+
const sanitizedUrl = sanitizeUrl.sanitizeUrl(rawDownloadUrl);
|
|
16985
|
+
return sanitizedUrl === "about:blank" ? void 0 : sanitizedUrl;
|
|
16986
|
+
}, [currentItem.imageUrl, currentItem.videoUrl]);
|
|
16987
|
+
const downloadLabel = t("aria/Download attachment");
|
|
16988
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__header", children: [
|
|
16989
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "str-chat__gallery__header-spacer" }),
|
|
16990
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__header-meta", children: [
|
|
16991
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__gallery__title", children: headerTitle }),
|
|
16992
|
+
message?.created_at ? /* @__PURE__ */ jsxRuntime.jsx(MessageTimestamp$1, { customClass: "str-chat__gallery__timestamp" }) : null
|
|
16993
|
+
] }),
|
|
16994
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__header-actions", children: [
|
|
16995
|
+
downloadUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
16996
|
+
"a",
|
|
16997
|
+
{
|
|
16998
|
+
"aria-label": downloadLabel,
|
|
16999
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--download",
|
|
17000
|
+
download: true,
|
|
17001
|
+
href: downloadUrl,
|
|
17002
|
+
rel: "noreferrer",
|
|
17003
|
+
target: "_blank",
|
|
17004
|
+
title: downloadLabel,
|
|
17005
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconArrowDownCircle, {})
|
|
17006
|
+
}
|
|
17007
|
+
) : null,
|
|
17008
|
+
modalContext?.close ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17009
|
+
WithAudioPlayback.Button,
|
|
17010
|
+
{
|
|
17011
|
+
"aria-label": t("Close"),
|
|
17012
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--close",
|
|
17013
|
+
onClick: modalContext.close,
|
|
17014
|
+
title: t("Close"),
|
|
17015
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconCrossMedium, {})
|
|
17016
|
+
}
|
|
17017
|
+
) : null
|
|
17018
|
+
] })
|
|
17019
|
+
] });
|
|
17020
|
+
};
|
|
17021
|
+
const VideoPlayer = ({ isPlaying, thumbnailUrl, videoUrl }) => {
|
|
17022
|
+
const { VideoPlayer: VideoPlayerContext } = WithAudioPlayback.useComponentContext();
|
|
17023
|
+
return VideoPlayerContext ? /* @__PURE__ */ jsxRuntime.jsx(VideoPlayerContext, { thumbnailUrl, videoUrl }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17024
|
+
ReactPlayer,
|
|
17025
|
+
{
|
|
17026
|
+
className: "react-player",
|
|
17027
|
+
config: { file: { attributes: { poster: thumbnailUrl } } },
|
|
17028
|
+
controls: true,
|
|
17029
|
+
height: "100%",
|
|
17030
|
+
playing: isPlaying,
|
|
17031
|
+
url: videoUrl,
|
|
17032
|
+
width: "100%"
|
|
17033
|
+
}
|
|
17034
|
+
);
|
|
17035
|
+
};
|
|
17036
|
+
const VideoThumbnail = ({
|
|
17037
|
+
className,
|
|
17038
|
+
onPlay,
|
|
17039
|
+
...imageProps
|
|
17040
|
+
}) => {
|
|
17041
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
17042
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-attachment__video-thumbnail", children: [
|
|
17043
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17044
|
+
BaseImage,
|
|
17045
|
+
{
|
|
17046
|
+
className: clsx("str-chat__message-attachment__video-thumbnail-image", className),
|
|
17047
|
+
...imageProps
|
|
17048
|
+
}
|
|
17049
|
+
),
|
|
17050
|
+
onPlay ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17051
|
+
WithAudioPlayback.Button,
|
|
17052
|
+
{
|
|
17053
|
+
appearance: "solid",
|
|
17054
|
+
"aria-label": t("Play video"),
|
|
17055
|
+
circular: true,
|
|
17056
|
+
className: clsx(
|
|
17057
|
+
"str-chat__message-attachment__video-thumbnail__play-indicator"
|
|
17058
|
+
),
|
|
17059
|
+
onClick: onPlay,
|
|
17060
|
+
size: "lg",
|
|
17061
|
+
variant: "secondary",
|
|
17062
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconPlaySolid, {})
|
|
17063
|
+
}
|
|
17064
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-attachment__video-thumbnail__play-indicator", children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconPlaySolid, {}) })
|
|
17065
|
+
] });
|
|
17066
|
+
};
|
|
17067
|
+
const SWIPE_THRESHOLD = 50;
|
|
17068
|
+
const TRANSITION_DURATION = 300;
|
|
17069
|
+
const GalleryUI = () => {
|
|
17070
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
17071
|
+
const {
|
|
17072
|
+
closeOnBackgroundClick,
|
|
17073
|
+
currentIndex,
|
|
17074
|
+
currentItem,
|
|
17075
|
+
goToNext,
|
|
17076
|
+
goToPrevious,
|
|
17077
|
+
hasNext,
|
|
17078
|
+
hasPrevious,
|
|
17079
|
+
itemCount,
|
|
17080
|
+
onRequestClose
|
|
17081
|
+
} = useGalleryContext();
|
|
17082
|
+
const modalContext = React.useContext(ModalContext);
|
|
17083
|
+
const [showVideo, setShowVideo] = React.useState(false);
|
|
17084
|
+
const isTransitioningRef = React.useRef(false);
|
|
17085
|
+
const [slideOffset, setSlideOffset] = React.useState(0);
|
|
17086
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
17087
|
+
const [slideDirection, setSlideDirection] = React.useState(
|
|
17088
|
+
null
|
|
17089
|
+
);
|
|
17090
|
+
const ignoreNextClickRef = React.useRef(false);
|
|
17091
|
+
const touchStartRef = React.useRef(null);
|
|
17092
|
+
const isVerticalSwipeRef = React.useRef(false);
|
|
17093
|
+
const containerRef = React.useRef(null);
|
|
17094
|
+
React.useEffect(() => {
|
|
17095
|
+
setShowVideo(false);
|
|
17096
|
+
}, [currentIndex]);
|
|
17097
|
+
const prevIndexRef = React.useRef(currentIndex);
|
|
17098
|
+
React.useEffect(() => {
|
|
17099
|
+
if (prevIndexRef.current === currentIndex) return;
|
|
17100
|
+
const direction = currentIndex > prevIndexRef.current ? "forward" : "backward";
|
|
17101
|
+
setSlideDirection(direction);
|
|
17102
|
+
setSlideOffset(0);
|
|
17103
|
+
setIsDragging(false);
|
|
17104
|
+
isTransitioningRef.current = true;
|
|
17105
|
+
const timer = setTimeout(() => {
|
|
17106
|
+
setSlideDirection(null);
|
|
17107
|
+
isTransitioningRef.current = false;
|
|
17108
|
+
}, TRANSITION_DURATION);
|
|
17109
|
+
prevIndexRef.current = currentIndex;
|
|
17110
|
+
return () => clearTimeout(timer);
|
|
17111
|
+
}, [currentIndex]);
|
|
17112
|
+
const handleGoToNext = React.useCallback(() => {
|
|
17113
|
+
if (isTransitioningRef.current) return;
|
|
17114
|
+
goToNext();
|
|
17115
|
+
}, [goToNext]);
|
|
17116
|
+
const handleGoToPrevious = React.useCallback(() => {
|
|
17117
|
+
if (isTransitioningRef.current) return;
|
|
17118
|
+
goToPrevious();
|
|
17119
|
+
}, [goToPrevious]);
|
|
17120
|
+
const handleKeyDown = React.useCallback(
|
|
17121
|
+
(event) => {
|
|
17122
|
+
if (event.key === "ArrowLeft") {
|
|
17123
|
+
event.preventDefault();
|
|
17124
|
+
handleGoToPrevious();
|
|
17125
|
+
} else if (event.key === "ArrowRight") {
|
|
17126
|
+
event.preventDefault();
|
|
17127
|
+
handleGoToNext();
|
|
17128
|
+
}
|
|
17129
|
+
},
|
|
17130
|
+
[handleGoToNext, handleGoToPrevious]
|
|
17131
|
+
);
|
|
17132
|
+
React.useEffect(() => {
|
|
17133
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
17134
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
17135
|
+
}, [handleKeyDown]);
|
|
17136
|
+
const handleTouchStart = React.useCallback((event) => {
|
|
17137
|
+
if (isTransitioningRef.current) return;
|
|
17138
|
+
const touch = event.touches[0];
|
|
17139
|
+
ignoreNextClickRef.current = false;
|
|
17140
|
+
touchStartRef.current = { x: touch.clientX, y: touch.clientY };
|
|
17141
|
+
isVerticalSwipeRef.current = false;
|
|
17142
|
+
}, []);
|
|
17143
|
+
const handleTouchMove = React.useCallback(
|
|
17144
|
+
(event) => {
|
|
17145
|
+
if (!touchStartRef.current || isTransitioningRef.current) return;
|
|
17146
|
+
const touch = event.touches[0];
|
|
17147
|
+
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
17148
|
+
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
17149
|
+
if (!isDragging && !isVerticalSwipeRef.current) {
|
|
17150
|
+
if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 10) {
|
|
17151
|
+
ignoreNextClickRef.current = true;
|
|
17152
|
+
isVerticalSwipeRef.current = true;
|
|
17153
|
+
return;
|
|
17154
|
+
}
|
|
17155
|
+
if (Math.abs(deltaX) > 10) {
|
|
17156
|
+
ignoreNextClickRef.current = true;
|
|
17157
|
+
setIsDragging(true);
|
|
17158
|
+
}
|
|
17159
|
+
}
|
|
17160
|
+
if (isVerticalSwipeRef.current) return;
|
|
17161
|
+
if (!hasNext && deltaX < 0 || !hasPrevious && deltaX > 0) {
|
|
17162
|
+
setSlideOffset(deltaX * 0.3);
|
|
17163
|
+
} else {
|
|
17164
|
+
setSlideOffset(deltaX);
|
|
17165
|
+
}
|
|
17166
|
+
},
|
|
17167
|
+
[isDragging, hasNext, hasPrevious]
|
|
17168
|
+
);
|
|
17169
|
+
const handleTouchEnd = React.useCallback(() => {
|
|
17170
|
+
if (!touchStartRef.current || isVerticalSwipeRef.current) {
|
|
17171
|
+
if (isVerticalSwipeRef.current) ignoreNextClickRef.current = true;
|
|
17172
|
+
touchStartRef.current = null;
|
|
17173
|
+
return;
|
|
17174
|
+
}
|
|
17175
|
+
const offset = slideOffset;
|
|
17176
|
+
if (isDragging || Math.abs(offset) > 10) {
|
|
17177
|
+
ignoreNextClickRef.current = true;
|
|
17178
|
+
}
|
|
17179
|
+
touchStartRef.current = null;
|
|
17180
|
+
if (Math.abs(offset) >= SWIPE_THRESHOLD) {
|
|
17181
|
+
if (offset < 0 && hasNext) {
|
|
17182
|
+
goToNext();
|
|
17183
|
+
} else if (offset > 0 && hasPrevious) {
|
|
17184
|
+
goToPrevious();
|
|
17185
|
+
} else {
|
|
17186
|
+
setSlideOffset(0);
|
|
17187
|
+
}
|
|
17188
|
+
} else {
|
|
17189
|
+
setSlideOffset(0);
|
|
17190
|
+
}
|
|
17191
|
+
setIsDragging(false);
|
|
17192
|
+
}, [slideOffset, hasNext, hasPrevious, goToNext, goToPrevious, isDragging]);
|
|
17193
|
+
const requestClose = modalContext?.close ?? onRequestClose;
|
|
17194
|
+
const handleBackgroundClick = React.useCallback(
|
|
17195
|
+
(event) => {
|
|
17196
|
+
if (event.target !== event.currentTarget) return;
|
|
17197
|
+
if (ignoreNextClickRef.current) {
|
|
17198
|
+
ignoreNextClickRef.current = false;
|
|
17199
|
+
return;
|
|
17200
|
+
}
|
|
17201
|
+
if (!closeOnBackgroundClick) return;
|
|
17202
|
+
requestClose?.();
|
|
17203
|
+
},
|
|
17204
|
+
[closeOnBackgroundClick, requestClose]
|
|
17205
|
+
);
|
|
17206
|
+
const mediaStyle = isDragging || slideOffset !== 0 && slideDirection === null ? { transform: `translateX(${slideOffset}px)` } : {};
|
|
17207
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery", children: [
|
|
17208
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__main", children: [
|
|
17209
|
+
/* @__PURE__ */ jsxRuntime.jsx(GalleryHeader, { currentItem }),
|
|
17210
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17211
|
+
NavButton,
|
|
17212
|
+
{
|
|
17213
|
+
"aria-label": t("Previous image"),
|
|
17214
|
+
className: clsx(
|
|
17215
|
+
"str-chat__gallery__nav-button--prev",
|
|
17216
|
+
!hasPrevious && "str-chat__gallery__nav-button--hidden"
|
|
17217
|
+
),
|
|
17218
|
+
disabled: !hasPrevious,
|
|
17219
|
+
onClick: handleGoToPrevious,
|
|
17220
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {})
|
|
17221
|
+
}
|
|
17222
|
+
),
|
|
17223
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17224
|
+
"div",
|
|
17225
|
+
{
|
|
17226
|
+
className: "str-chat__gallery__slide-container",
|
|
17227
|
+
onClick: handleBackgroundClick,
|
|
17228
|
+
onTouchEnd: handleTouchEnd,
|
|
17229
|
+
onTouchMove: handleTouchMove,
|
|
17230
|
+
onTouchStart: handleTouchStart,
|
|
17231
|
+
ref: containerRef,
|
|
17232
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17233
|
+
"div",
|
|
17234
|
+
{
|
|
17235
|
+
className: clsx({
|
|
17236
|
+
"str-chat__gallery__media--dragging": isDragging,
|
|
17237
|
+
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
17238
|
+
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
17239
|
+
}),
|
|
17240
|
+
style: mediaStyle,
|
|
17241
|
+
children: currentItem.videoUrl && currentItem.videoThumbnailUrl ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--video", children: showVideo ? /* @__PURE__ */ jsxRuntime.jsx(VideoPlayer, { isPlaying: true, videoUrl: currentItem.videoUrl }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17242
|
+
VideoThumbnail,
|
|
17243
|
+
{
|
|
17244
|
+
alt: currentItem.title ?? "",
|
|
17245
|
+
onPlay: () => setShowVideo(true),
|
|
17246
|
+
src: currentItem.videoThumbnailUrl
|
|
17247
|
+
}
|
|
17248
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--image", children: /* @__PURE__ */ jsxRuntime.jsx(BaseImage, { alt: currentItem.alt, src: currentItem.imageUrl }) })
|
|
17249
|
+
}
|
|
17250
|
+
)
|
|
17251
|
+
}
|
|
17252
|
+
),
|
|
17253
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17254
|
+
NavButton,
|
|
17255
|
+
{
|
|
17256
|
+
"aria-label": t("Next image"),
|
|
17257
|
+
className: clsx(
|
|
17258
|
+
"str-chat__gallery__nav-button--next",
|
|
17259
|
+
!hasNext && "str-chat__gallery__nav-button--hidden"
|
|
17260
|
+
),
|
|
17261
|
+
disabled: !hasNext,
|
|
17262
|
+
onClick: handleGoToNext,
|
|
17263
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronRight, {})
|
|
17264
|
+
}
|
|
17265
|
+
)
|
|
17266
|
+
] }),
|
|
17267
|
+
itemCount > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__gallery__position-indicator", children: [
|
|
17268
|
+
currentIndex + 1,
|
|
17269
|
+
" of ",
|
|
17270
|
+
itemCount
|
|
17271
|
+
] })
|
|
17272
|
+
] });
|
|
17273
|
+
};
|
|
17274
|
+
const NavButton = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.Button, { ...props, className: clsx("str-chat__gallery__nav-button", className) });
|
|
17275
|
+
const Gallery = ({
|
|
17276
|
+
closeOnBackgroundClick = true,
|
|
17277
|
+
GalleryUI: GalleryUI$1,
|
|
17278
|
+
initialIndex = 0,
|
|
17279
|
+
items,
|
|
17280
|
+
onIndexChange,
|
|
17281
|
+
onRequestClose
|
|
17282
|
+
}) => {
|
|
17283
|
+
const { GalleryUI: ContextGalleryUI } = WithAudioPlayback.useComponentContext();
|
|
17284
|
+
const ResolvedGalleryUI = GalleryUI$1 ?? ContextGalleryUI ?? GalleryUI;
|
|
17285
|
+
const [currentIndex, setCurrentIndex] = React.useState(initialIndex);
|
|
17286
|
+
const itemCount = items.length;
|
|
17287
|
+
const goToIndex = React.useCallback(
|
|
17288
|
+
(index) => {
|
|
17289
|
+
if (index >= 0 && index < itemCount) {
|
|
17290
|
+
setCurrentIndex(index);
|
|
17291
|
+
}
|
|
17292
|
+
},
|
|
17293
|
+
[itemCount]
|
|
17294
|
+
);
|
|
17295
|
+
const goToNext = React.useCallback(() => {
|
|
17296
|
+
setCurrentIndex((prev) => prev < itemCount - 1 ? prev + 1 : prev);
|
|
17297
|
+
}, [itemCount]);
|
|
17298
|
+
const goToPrevious = React.useCallback(() => {
|
|
17299
|
+
setCurrentIndex((prev) => prev > 0 ? prev - 1 : prev);
|
|
17300
|
+
}, []);
|
|
17301
|
+
React.useEffect(() => {
|
|
17302
|
+
onIndexChange?.(currentIndex);
|
|
17303
|
+
}, [currentIndex, onIndexChange]);
|
|
17304
|
+
const hasNext = currentIndex < itemCount - 1;
|
|
17305
|
+
const hasPrevious = currentIndex > 0;
|
|
17306
|
+
const currentItem = items[currentIndex];
|
|
17307
|
+
const contextValue = React.useMemo(
|
|
17308
|
+
() => ({
|
|
17309
|
+
closeOnBackgroundClick,
|
|
17310
|
+
currentIndex,
|
|
17311
|
+
currentItem,
|
|
17312
|
+
goToIndex,
|
|
17313
|
+
goToNext,
|
|
17314
|
+
goToPrevious,
|
|
17315
|
+
hasNext,
|
|
17316
|
+
hasPrevious,
|
|
17317
|
+
itemCount,
|
|
17318
|
+
items,
|
|
17319
|
+
onRequestClose
|
|
17320
|
+
}),
|
|
17321
|
+
[
|
|
17322
|
+
closeOnBackgroundClick,
|
|
17323
|
+
currentIndex,
|
|
17324
|
+
currentItem,
|
|
17325
|
+
goToIndex,
|
|
17326
|
+
goToNext,
|
|
17327
|
+
goToPrevious,
|
|
17328
|
+
hasNext,
|
|
17329
|
+
hasPrevious,
|
|
17330
|
+
itemCount,
|
|
17331
|
+
items,
|
|
17332
|
+
onRequestClose
|
|
17333
|
+
]
|
|
17334
|
+
);
|
|
17335
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GalleryContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(ResolvedGalleryUI, {}) });
|
|
17336
|
+
};
|
|
17140
17337
|
const AttachmentPreviewList = ({
|
|
17141
17338
|
AudioAttachmentPreview: AudioAttachmentPreview2 = FileAttachmentPreview,
|
|
17142
17339
|
FileAttachmentPreview: FileAttachmentPreview$1 = FileAttachmentPreview,
|
|
@@ -17145,73 +17342,107 @@ const AttachmentPreviewList = ({
|
|
|
17145
17342
|
VideoAttachmentPreview = MediaAttachmentPreview
|
|
17146
17343
|
}) => {
|
|
17147
17344
|
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
17345
|
+
const { Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
17346
|
+
const [showPreview, setShowPreview] = React.useState(false);
|
|
17347
|
+
const initialIndexRef = React.useRef(0);
|
|
17148
17348
|
const { attachments } = useAttachmentsForPreview();
|
|
17149
17349
|
const filteredAttachments = React.useMemo(
|
|
17150
17350
|
() => attachments.filter((a) => !streamChat.isVoiceRecordingAttachment(a)),
|
|
17151
17351
|
[attachments]
|
|
17152
17352
|
);
|
|
17353
|
+
const { galleryItems, previewIndexById } = React.useMemo(() => {
|
|
17354
|
+
const items = [];
|
|
17355
|
+
const indexById = {};
|
|
17356
|
+
for (const a of attachments) {
|
|
17357
|
+
if (streamChat.isLocalImageAttachment(a) || streamChat.isLocalVideoAttachment(a)) {
|
|
17358
|
+
const descriptor = toBaseImageDescriptors(a);
|
|
17359
|
+
if (descriptor) {
|
|
17360
|
+
indexById[a.localMetadata.id] = items.length;
|
|
17361
|
+
items.push(descriptor);
|
|
17362
|
+
}
|
|
17363
|
+
}
|
|
17364
|
+
}
|
|
17365
|
+
return { galleryItems: items, previewIndexById: indexById };
|
|
17366
|
+
}, [attachments]);
|
|
17367
|
+
const openPreviewAtIndex = React.useCallback((index) => {
|
|
17368
|
+
initialIndexRef.current = index;
|
|
17369
|
+
setShowPreview(true);
|
|
17370
|
+
}, []);
|
|
17153
17371
|
if (!filteredAttachments.length) return null;
|
|
17154
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
17372
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17155
17373
|
"div",
|
|
17156
17374
|
{
|
|
17157
17375
|
className: "str-chat__attachment-preview-list",
|
|
17158
17376
|
"data-testid": "attachment-preview-list",
|
|
17159
|
-
children:
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
|
|
17202
|
-
|
|
17203
|
-
|
|
17204
|
-
|
|
17205
|
-
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17214
|
-
|
|
17377
|
+
children: [
|
|
17378
|
+
attachments.map((attachment) => {
|
|
17379
|
+
if (streamChat.isScrapedContent(attachment)) return null;
|
|
17380
|
+
if (streamChat.isLocalVoiceRecordingAttachment(attachment)) return null;
|
|
17381
|
+
if (streamChat.isLocalAudioAttachment(attachment)) {
|
|
17382
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17383
|
+
AudioAttachmentPreview2,
|
|
17384
|
+
{
|
|
17385
|
+
attachment,
|
|
17386
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17387
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17388
|
+
},
|
|
17389
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17390
|
+
);
|
|
17391
|
+
} else if (streamChat.isLocalVideoAttachment(attachment)) {
|
|
17392
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17393
|
+
VideoAttachmentPreview,
|
|
17394
|
+
{
|
|
17395
|
+
attachment,
|
|
17396
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17397
|
+
openPreview: () => openPreviewAtIndex(previewIndexById[attachment.localMetadata.id] ?? 0),
|
|
17398
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17399
|
+
},
|
|
17400
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17401
|
+
);
|
|
17402
|
+
} else if (streamChat.isLocalImageAttachment(attachment)) {
|
|
17403
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17404
|
+
ImageAttachmentPreview,
|
|
17405
|
+
{
|
|
17406
|
+
attachment,
|
|
17407
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17408
|
+
openPreview: () => openPreviewAtIndex(previewIndexById[attachment.localMetadata.id] ?? 0),
|
|
17409
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17410
|
+
},
|
|
17411
|
+
attachment.localMetadata.id || attachment.image_url
|
|
17412
|
+
);
|
|
17413
|
+
} else if (streamChat.isLocalFileAttachment(attachment)) {
|
|
17414
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17415
|
+
FileAttachmentPreview$1,
|
|
17416
|
+
{
|
|
17417
|
+
attachment,
|
|
17418
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17419
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17420
|
+
},
|
|
17421
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17422
|
+
);
|
|
17423
|
+
} else if (streamChat.isLocalAttachment(attachment)) {
|
|
17424
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17425
|
+
UnsupportedAttachmentPreview$1,
|
|
17426
|
+
{
|
|
17427
|
+
attachment,
|
|
17428
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17429
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17430
|
+
},
|
|
17431
|
+
attachment.localMetadata.id
|
|
17432
|
+
);
|
|
17433
|
+
}
|
|
17434
|
+
return null;
|
|
17435
|
+
}),
|
|
17436
|
+
galleryItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17437
|
+
Modal,
|
|
17438
|
+
{
|
|
17439
|
+
className: "str-chat__gallery-modal",
|
|
17440
|
+
onClose: () => setShowPreview(false),
|
|
17441
|
+
open: showPreview,
|
|
17442
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Gallery, { initialIndex: initialIndexRef.current, items: galleryItems })
|
|
17443
|
+
}
|
|
17444
|
+
)
|
|
17445
|
+
]
|
|
17215
17446
|
}
|
|
17216
17447
|
);
|
|
17217
17448
|
};
|
|
@@ -17239,11 +17470,9 @@ const VoiceRecordingPreviewSlot = ({
|
|
|
17239
17470
|
}
|
|
17240
17471
|
);
|
|
17241
17472
|
};
|
|
17242
|
-
const
|
|
17243
|
-
const CommandChip = () => {
|
|
17473
|
+
const CommandChip = ({ command }) => {
|
|
17244
17474
|
const { textComposer } = WithAudioPlayback.useMessageComposerController();
|
|
17245
17475
|
const { textareaRef } = WithAudioPlayback.useMessageComposerContext();
|
|
17246
|
-
const { command } = WithAudioPlayback.useStateStore(textComposer.state, textComposerStateSelector$4);
|
|
17247
17476
|
if (!command) return null;
|
|
17248
17477
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__command-chip", children: [
|
|
17249
17478
|
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconThunder, {}),
|
|
@@ -17542,9 +17771,12 @@ const ToggleRecordingButton = () => {
|
|
|
17542
17771
|
);
|
|
17543
17772
|
};
|
|
17544
17773
|
const AudioRecorderRecordingControls = () => {
|
|
17774
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
17775
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
17545
17776
|
const {
|
|
17546
17777
|
recordingController: { completeRecording, recorder, recording, recordingState }
|
|
17547
17778
|
} = WithAudioPlayback.useMessageComposerContext();
|
|
17779
|
+
const panel = WithAudioPlayback.useNotificationTarget();
|
|
17548
17780
|
const isUploadingFile = recording?.localMetadata?.uploadState === "uploading";
|
|
17549
17781
|
if (!recorder) return null;
|
|
17550
17782
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__audio_recorder__recording-controls", children: [
|
|
@@ -17556,7 +17788,17 @@ const AudioRecorderRecordingControls = () => {
|
|
|
17556
17788
|
className: "str-chat__audio_recorder__cancel-button",
|
|
17557
17789
|
"data-testid": "cancel-recording-audio-button",
|
|
17558
17790
|
disabled: isUploadingFile,
|
|
17559
|
-
onClick:
|
|
17791
|
+
onClick: () => {
|
|
17792
|
+
recorder.cancel();
|
|
17793
|
+
client.notifications.addInfo({
|
|
17794
|
+
message: t("Voice message deleted"),
|
|
17795
|
+
options: {
|
|
17796
|
+
tags: WithAudioPlayback.addNotificationTargetTag(panel),
|
|
17797
|
+
type: "audioRecording:cancel:success"
|
|
17798
|
+
},
|
|
17799
|
+
origin: { emitter: "AudioRecorder" }
|
|
17800
|
+
});
|
|
17801
|
+
},
|
|
17560
17802
|
size: "sm",
|
|
17561
17803
|
variant: "secondary",
|
|
17562
17804
|
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconTrashBin, {})
|
|
@@ -17863,7 +18105,10 @@ const SuggestionList = ({
|
|
|
17863
18105
|
setFocusedItemIndex,
|
|
17864
18106
|
suggestionItemComponents = defaultComponents
|
|
17865
18107
|
}) => {
|
|
17866
|
-
const {
|
|
18108
|
+
const {
|
|
18109
|
+
AutocompleteSuggestionItem = SuggestionListItem,
|
|
18110
|
+
ContextMenu: ContextMenuComponent = ContextMenu
|
|
18111
|
+
} = WithAudioPlayback.useComponentContext();
|
|
17867
18112
|
const { textareaRef } = WithAudioPlayback.useMessageComposerContext();
|
|
17868
18113
|
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
17869
18114
|
const { textComposer } = messageComposer;
|
|
@@ -17981,7 +18226,7 @@ const SuggestionList = ({
|
|
|
17981
18226
|
zIndex: 1e3
|
|
17982
18227
|
},
|
|
17983
18228
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17984
|
-
|
|
18229
|
+
ContextMenuComponent,
|
|
17985
18230
|
{
|
|
17986
18231
|
className: clsx("str-chat__suggestion-list", className),
|
|
17987
18232
|
Header: suggestions.searchSource.type === "commands" ? CommandsMenuHeader : void 0,
|
|
@@ -18080,6 +18325,12 @@ const TextareaComposer = ({
|
|
|
18080
18325
|
textComposer.state,
|
|
18081
18326
|
textComposerStateSelector$1
|
|
18082
18327
|
);
|
|
18328
|
+
const autosizeRows = !text2 && minRows == null ? 1 : void 0;
|
|
18329
|
+
const textareaStyle = text2 ? void 0 : {
|
|
18330
|
+
overflow: "hidden",
|
|
18331
|
+
textOverflow: "ellipsis",
|
|
18332
|
+
whiteSpace: "nowrap"
|
|
18333
|
+
};
|
|
18083
18334
|
const { enabled } = WithAudioPlayback.useStateStore(messageComposer.configState, configStateSelector);
|
|
18084
18335
|
const { quotedMessage } = WithAudioPlayback.useStateStore(
|
|
18085
18336
|
messageComposer.state,
|
|
@@ -18233,8 +18484,8 @@ const TextareaComposer = ({
|
|
|
18233
18484
|
),
|
|
18234
18485
|
"data-testid": "message-input",
|
|
18235
18486
|
disabled: !enabled || !!cooldownRemaining,
|
|
18236
|
-
maxRows,
|
|
18237
|
-
minRows,
|
|
18487
|
+
maxRows: autosizeRows ?? maxRows,
|
|
18488
|
+
minRows: autosizeRows ?? minRows,
|
|
18238
18489
|
onBlur,
|
|
18239
18490
|
onChange: changeHandler,
|
|
18240
18491
|
onCompositionEnd,
|
|
@@ -18246,7 +18497,8 @@ const TextareaComposer = ({
|
|
|
18246
18497
|
placeholder,
|
|
18247
18498
|
ref: (ref) => {
|
|
18248
18499
|
textareaRef.current = ref;
|
|
18249
|
-
}
|
|
18500
|
+
},
|
|
18501
|
+
style: textareaStyle
|
|
18250
18502
|
}
|
|
18251
18503
|
),
|
|
18252
18504
|
!isComposing && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -18578,7 +18830,7 @@ const MessageComposerUI = () => {
|
|
|
18578
18830
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-composer-controls", children: [
|
|
18579
18831
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-composer-controls__text-composition-controls", children: [
|
|
18580
18832
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-composer-controls__text-composition-controls__text", children: [
|
|
18581
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-composer-controls__text-composition-controls__command-chip-container", children: /* @__PURE__ */ jsxRuntime.jsx(CommandChip$1, {}) }),
|
|
18833
|
+
command && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-composer-controls__text-composition-controls__command-chip-container", children: /* @__PURE__ */ jsxRuntime.jsx(CommandChip$1, { command }) }),
|
|
18582
18834
|
/* @__PURE__ */ jsxRuntime.jsx(TextareaComposer$1, {})
|
|
18583
18835
|
] }),
|
|
18584
18836
|
/* @__PURE__ */ jsxRuntime.jsx(SendToChannelCheckbox$1, {})
|
|
@@ -18653,7 +18905,7 @@ const MessageComposerProvider = (props) => {
|
|
|
18653
18905
|
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
18654
18906
|
React.useEffect(
|
|
18655
18907
|
() => () => {
|
|
18656
|
-
messageComposer.createDraft();
|
|
18908
|
+
messageComposer.createDraft().finally(() => messageComposer.clear());
|
|
18657
18909
|
},
|
|
18658
18910
|
[messageComposer]
|
|
18659
18911
|
);
|
|
@@ -18971,7 +19223,7 @@ const useChat = ({
|
|
|
18971
19223
|
};
|
|
18972
19224
|
React.useEffect(() => {
|
|
18973
19225
|
if (!client) return;
|
|
18974
|
-
const version = "14.0.0-beta.
|
|
19226
|
+
const version = "14.0.0-beta.3";
|
|
18975
19227
|
const userAgent = client.getUserAgent();
|
|
18976
19228
|
if (!userAgent.includes("stream-chat-react")) {
|
|
18977
19229
|
client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
|
|
@@ -19472,13 +19724,13 @@ const ReactionSelector = (props) => {
|
|
|
19472
19724
|
) })
|
|
19473
19725
|
] });
|
|
19474
19726
|
};
|
|
19475
|
-
ReactionSelector.getDialogId = (
|
|
19727
|
+
ReactionSelector.getDialogId = ({ messageId, threadList }) => {
|
|
19476
19728
|
const dialogIdNamespace = threadList ? "-thread" : "";
|
|
19477
|
-
return `reaction-selector${dialogIdNamespace}
|
|
19478
|
-
}
|
|
19729
|
+
return `reaction-selector${dialogIdNamespace}-${messageId}`;
|
|
19730
|
+
};
|
|
19479
19731
|
ReactionSelector.displayName = "ReactionSelector";
|
|
19480
19732
|
const ReactionSelectorWithButton = ({
|
|
19481
|
-
ReactionIcon
|
|
19733
|
+
ReactionIcon
|
|
19482
19734
|
}) => {
|
|
19483
19735
|
const { t } = WithAudioPlayback.useTranslationContext("ReactionSelectorWithButton");
|
|
19484
19736
|
const { isMyMessage, message, threadList } = useMessageContext();
|
|
@@ -19512,7 +19764,7 @@ const ReactionSelectorWithButton = ({
|
|
|
19512
19764
|
"data-testid": "message-reaction-action",
|
|
19513
19765
|
onClick: () => dialog?.toggle(),
|
|
19514
19766
|
ref: buttonRef,
|
|
19515
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19767
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactionIcon, { className: "str-chat__message-action-icon" })
|
|
19516
19768
|
}
|
|
19517
19769
|
)
|
|
19518
19770
|
] });
|
|
@@ -19560,6 +19812,7 @@ const QuickMessageActionsButton = ({ className, ...props }) => /* @__PURE__ */ j
|
|
|
19560
19812
|
appearance: "ghost",
|
|
19561
19813
|
circular: true,
|
|
19562
19814
|
className: clsx("str-chat__message-actions-box-button", className),
|
|
19815
|
+
size: "sm",
|
|
19563
19816
|
variant: "secondary",
|
|
19564
19817
|
...props
|
|
19565
19818
|
}
|
|
@@ -19849,8 +20102,7 @@ const DefaultMessageActionComponents = {
|
|
|
19849
20102
|
const { closeMenu } = useContextMenuContext();
|
|
19850
20103
|
const { client } = WithAudioPlayback.useChatContext();
|
|
19851
20104
|
const { Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
19852
|
-
const {
|
|
19853
|
-
const { handleDelete, message } = useMessageContext();
|
|
20105
|
+
const { handleDelete } = useMessageContext();
|
|
19854
20106
|
const panel = WithAudioPlayback.useNotificationTarget();
|
|
19855
20107
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
19856
20108
|
const [openModal, setOpenModal] = React.useState(false);
|
|
@@ -19876,29 +20128,20 @@ const DefaultMessageActionComponents = {
|
|
|
19876
20128
|
closeMenu();
|
|
19877
20129
|
},
|
|
19878
20130
|
onDelete: async () => {
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
|
|
19892
|
-
message: t("Failed to delete the message"),
|
|
19893
|
-
options: {
|
|
19894
|
-
tags: WithAudioPlayback.addNotificationTargetTag(panel)
|
|
19895
|
-
},
|
|
19896
|
-
origin: { emitter: "MessageActions" }
|
|
19897
|
-
});
|
|
19898
|
-
}
|
|
20131
|
+
try {
|
|
20132
|
+
await handleDelete();
|
|
20133
|
+
client.notifications.addSuccess({
|
|
20134
|
+
message: t("Message deleted"),
|
|
20135
|
+
options: {
|
|
20136
|
+
tags: WithAudioPlayback.addNotificationTargetTag(panel)
|
|
20137
|
+
},
|
|
20138
|
+
origin: { emitter: "MessageActions" }
|
|
20139
|
+
});
|
|
20140
|
+
} catch {
|
|
20141
|
+
} finally {
|
|
20142
|
+
setOpenModal(false);
|
|
20143
|
+
closeMenu();
|
|
19899
20144
|
}
|
|
19900
|
-
setOpenModal(false);
|
|
19901
|
-
closeMenu();
|
|
19902
20145
|
}
|
|
19903
20146
|
}
|
|
19904
20147
|
) })
|
|
@@ -19930,8 +20173,34 @@ const DefaultMessageActionComponents = {
|
|
|
19930
20173
|
}
|
|
19931
20174
|
},
|
|
19932
20175
|
quick: {
|
|
20176
|
+
// eslint-disable-next-line react/display-name
|
|
20177
|
+
DropdownToggle: React.forwardRef((_, ref) => {
|
|
20178
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20179
|
+
const { message } = useMessageContext();
|
|
20180
|
+
const dropdownDialogIsOpen = useDialogIsOpen(
|
|
20181
|
+
MessageActions.getDialogId({ messageId: message.id })
|
|
20182
|
+
);
|
|
20183
|
+
const { dialog } = useDialogOnNearestManager({
|
|
20184
|
+
id: MessageActions.getDialogId({ messageId: message.id })
|
|
20185
|
+
});
|
|
20186
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20187
|
+
QuickMessageActionsButton,
|
|
20188
|
+
{
|
|
20189
|
+
"aria-expanded": dropdownDialogIsOpen,
|
|
20190
|
+
"aria-haspopup": "true",
|
|
20191
|
+
"aria-label": t("aria/Open Message Actions Menu"),
|
|
20192
|
+
className: "str-chat__message-actions-box-button",
|
|
20193
|
+
"data-testid": "message-actions-toggle-button",
|
|
20194
|
+
onClick: () => {
|
|
20195
|
+
dialog?.toggle();
|
|
20196
|
+
},
|
|
20197
|
+
ref,
|
|
20198
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconDotGrid1x3Horizontal, { className: "str-chat__message-action-icon" })
|
|
20199
|
+
}
|
|
20200
|
+
);
|
|
20201
|
+
}),
|
|
19933
20202
|
React() {
|
|
19934
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ReactionSelectorWithButton, { ReactionIcon });
|
|
20203
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReactionSelectorWithButton, { ReactionIcon: WithAudioPlayback.IconEmojiSmile });
|
|
19935
20204
|
},
|
|
19936
20205
|
Reply() {
|
|
19937
20206
|
const { handleOpenThread } = useMessageContext();
|
|
@@ -19943,14 +20212,17 @@ const DefaultMessageActionComponents = {
|
|
|
19943
20212
|
className: "str-chat__message-reply-in-thread-button",
|
|
19944
20213
|
"data-testid": "thread-action",
|
|
19945
20214
|
onClick: handleOpenThread,
|
|
19946
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20215
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconArrowShareLeft, { className: "str-chat__message-action-icon" })
|
|
19947
20216
|
}
|
|
19948
20217
|
);
|
|
19949
20218
|
}
|
|
19950
20219
|
}
|
|
19951
20220
|
};
|
|
19952
20221
|
const defaultMessageActionSet = [
|
|
19953
|
-
|
|
20222
|
+
{
|
|
20223
|
+
Component: DefaultMessageActionComponents.quick.DropdownToggle,
|
|
20224
|
+
placement: "quick-dropdown-toggle"
|
|
20225
|
+
},
|
|
19954
20226
|
{
|
|
19955
20227
|
Component: DefaultMessageActionComponents.quick.Reply,
|
|
19956
20228
|
placement: "quick",
|
|
@@ -20040,14 +20312,14 @@ function useFetchReactions(options) {
|
|
|
20040
20312
|
const handleFetchReactions = propHandleFetchReactions ?? contextHandleFetchReactions;
|
|
20041
20313
|
const [refetchNonce, setRefetchNonce] = React.useState(null);
|
|
20042
20314
|
React.useEffect(() => {
|
|
20043
|
-
if (!shouldFetch
|
|
20315
|
+
if (!shouldFetch) {
|
|
20044
20316
|
return;
|
|
20045
20317
|
}
|
|
20046
20318
|
let cancel = false;
|
|
20047
20319
|
(async () => {
|
|
20048
20320
|
try {
|
|
20049
20321
|
setIsLoading(true);
|
|
20050
|
-
const reactions2 = await handleFetchReactions(reactionType, sort);
|
|
20322
|
+
const reactions2 = await handleFetchReactions(reactionType ?? void 0, sort);
|
|
20051
20323
|
if (!cancel) {
|
|
20052
20324
|
setReactions(reactions2);
|
|
20053
20325
|
}
|
|
@@ -20071,6 +20343,16 @@ function useFetchReactions(options) {
|
|
|
20071
20343
|
return { isLoading, reactions, refetch };
|
|
20072
20344
|
}
|
|
20073
20345
|
const defaultReactionDetailsSort = { created_at: -1 };
|
|
20346
|
+
const MessageReactionsDetailLoadingIndicator = () => {
|
|
20347
|
+
const elements = React.useMemo(
|
|
20348
|
+
() => Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20349
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20350
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20351
|
+
] }, index)),
|
|
20352
|
+
[]
|
|
20353
|
+
);
|
|
20354
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: elements });
|
|
20355
|
+
};
|
|
20074
20356
|
function MessageReactionsDetail({
|
|
20075
20357
|
handleFetchReactions,
|
|
20076
20358
|
onSelectedReactionTypeChange,
|
|
@@ -20081,7 +20363,11 @@ function MessageReactionsDetail({
|
|
|
20081
20363
|
totalReactionCount
|
|
20082
20364
|
}) {
|
|
20083
20365
|
const { client } = WithAudioPlayback.useChatContext();
|
|
20084
|
-
const {
|
|
20366
|
+
const {
|
|
20367
|
+
Avatar: Avatar$1 = Avatar,
|
|
20368
|
+
LoadingIndicator: LoadingIndicator2 = MessageReactionsDetailLoadingIndicator,
|
|
20369
|
+
reactionOptions = defaultReactionOptions
|
|
20370
|
+
} = WithAudioPlayback.useComponentContext(MessageReactionsDetail.name);
|
|
20085
20371
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20086
20372
|
const {
|
|
20087
20373
|
handleReaction: contextHandleReaction,
|
|
@@ -20108,7 +20394,7 @@ function MessageReactionsDetail({
|
|
|
20108
20394
|
"div",
|
|
20109
20395
|
{
|
|
20110
20396
|
className: "str-chat__message-reactions-detail",
|
|
20111
|
-
"data-testid": "reactions-
|
|
20397
|
+
"data-testid": "message-reactions-detail",
|
|
20112
20398
|
children: [
|
|
20113
20399
|
typeof totalReactionCount === "number" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__total-count", children: t("{{ count }} reactions", { count: totalReactionCount }) }),
|
|
20114
20400
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__reaction-type-list-container", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "str-chat__message-reactions-detail__reaction-type-list", children: reactions.map(
|
|
@@ -20121,7 +20407,9 @@ function MessageReactionsDetail({
|
|
|
20121
20407
|
{
|
|
20122
20408
|
"aria-pressed": reactionType === selectedReactionType,
|
|
20123
20409
|
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20124
|
-
onClick: () => onSelectedReactionTypeChange?.(
|
|
20410
|
+
onClick: () => onSelectedReactionTypeChange?.(
|
|
20411
|
+
selectedReactionType === reactionType ? null : reactionType
|
|
20412
|
+
),
|
|
20125
20413
|
children: [
|
|
20126
20414
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) }),
|
|
20127
20415
|
reactionCount > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -20145,22 +20433,10 @@ function MessageReactionsDetail({
|
|
|
20145
20433
|
className: "str-chat__message-reactions-detail__user-list",
|
|
20146
20434
|
"data-testid": "all-reacting-users",
|
|
20147
20435
|
children: [
|
|
20148
|
-
areReactionsLoading && /* @__PURE__ */ jsxRuntime.
|
|
20149
|
-
|
|
20150
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20151
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20152
|
-
] }),
|
|
20153
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20154
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20155
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20156
|
-
] }),
|
|
20157
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20158
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20159
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20160
|
-
] })
|
|
20161
|
-
] }),
|
|
20162
|
-
!areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetailsWithLegacyFallback.map(({ user }) => {
|
|
20436
|
+
areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
|
|
20437
|
+
!areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetailsWithLegacyFallback.map(({ type, user }) => {
|
|
20163
20438
|
const belongsToCurrentUser = client.user?.id === user?.id;
|
|
20439
|
+
const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
|
|
20164
20440
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20165
20441
|
"div",
|
|
20166
20442
|
{
|
|
@@ -20185,23 +20461,23 @@ function MessageReactionsDetail({
|
|
|
20185
20461
|
children: belongsToCurrentUser ? t("You") : user?.name || user?.id
|
|
20186
20462
|
}
|
|
20187
20463
|
),
|
|
20188
|
-
belongsToCurrentUser &&
|
|
20464
|
+
belongsToCurrentUser && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20189
20465
|
"button",
|
|
20190
20466
|
{
|
|
20191
20467
|
className: "str-chat__message-reactions-detail__user-list-item-button",
|
|
20192
20468
|
"data-testid": "remove-reaction-button",
|
|
20193
|
-
onClick: (e) => {
|
|
20194
|
-
contextHandleReaction(
|
|
20195
|
-
|
|
20196
|
-
});
|
|
20469
|
+
onClick: async (e) => {
|
|
20470
|
+
await contextHandleReaction(type, e);
|
|
20471
|
+
refetch();
|
|
20197
20472
|
},
|
|
20198
20473
|
children: t("Tap to remove")
|
|
20199
20474
|
}
|
|
20200
20475
|
)
|
|
20201
|
-
] })
|
|
20476
|
+
] }),
|
|
20477
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__user-list-item-icon", children: EmojiComponent && !selectedReactionType && /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) })
|
|
20202
20478
|
]
|
|
20203
20479
|
},
|
|
20204
|
-
user?.id
|
|
20480
|
+
`${user?.id}-${type}`
|
|
20205
20481
|
);
|
|
20206
20482
|
}) })
|
|
20207
20483
|
]
|
|
@@ -20350,6 +20626,7 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20350
20626
|
const divRef = React.useRef(null);
|
|
20351
20627
|
const dialogId2 = `message-reactions-detail-${message.id}`;
|
|
20352
20628
|
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
20629
|
+
const isDialogOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20353
20630
|
const handleReactionButtonClick = (reactionType) => {
|
|
20354
20631
|
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
|
|
20355
20632
|
return;
|
|
@@ -20384,6 +20661,8 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20384
20661
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20385
20662
|
FragmentOrButton,
|
|
20386
20663
|
{
|
|
20664
|
+
"aria-expanded": isDialogOpen,
|
|
20665
|
+
"aria-pressed": isDialogOpen,
|
|
20387
20666
|
buttonIf: visualStyle === "clustered",
|
|
20388
20667
|
className: "str-chat__message-reactions__list-button",
|
|
20389
20668
|
onClick: () => handleReactionButtonClick(existingReactions[0]?.reactionType ?? null),
|
|
@@ -20421,9 +20700,7 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20421
20700
|
"button",
|
|
20422
20701
|
{
|
|
20423
20702
|
className: "str-chat__message-reactions__list-item-button",
|
|
20424
|
-
onClick: () => handleReactionButtonClick(
|
|
20425
|
-
existingReactions.at(-1)?.reactionType ?? null
|
|
20426
|
-
),
|
|
20703
|
+
onClick: () => handleReactionButtonClick(null),
|
|
20427
20704
|
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "str-chat__message-reactions__overflow-count", children: [
|
|
20428
20705
|
"+",
|
|
20429
20706
|
totalReactionCount - cappedExistingReactions.reactionCountToDisplay
|
|
@@ -20548,91 +20825,74 @@ const StreamEmoji = ({
|
|
|
20548
20825
|
const useSplitActionSet = (actionSet) => React.useMemo(() => {
|
|
20549
20826
|
const quickActionSet = [];
|
|
20550
20827
|
const dropdownActionSet = [];
|
|
20828
|
+
let quickDropdownToggleAction;
|
|
20551
20829
|
for (const action of actionSet) {
|
|
20552
20830
|
if (action.placement === "quick")
|
|
20553
20831
|
quickActionSet.push(action);
|
|
20554
20832
|
if (action.placement === "dropdown")
|
|
20555
20833
|
dropdownActionSet.push(action);
|
|
20834
|
+
if (action.placement === "quick-dropdown-toggle") {
|
|
20835
|
+
quickDropdownToggleAction ?? (quickDropdownToggleAction = action);
|
|
20836
|
+
}
|
|
20556
20837
|
}
|
|
20557
|
-
return { dropdownActionSet, quickActionSet };
|
|
20838
|
+
return { dropdownActionSet, quickActionSet, quickDropdownToggleAction };
|
|
20558
20839
|
}, [actionSet]);
|
|
20559
20840
|
const MessageActions = ({
|
|
20560
20841
|
disableBaseMessageActionSetFilter = false,
|
|
20561
20842
|
messageActionSet = defaultMessageActionSet
|
|
20562
20843
|
}) => {
|
|
20563
|
-
const { theme } = WithAudioPlayback.useChatContext();
|
|
20564
20844
|
const { isMyMessage, message, threadList } = useMessageContext();
|
|
20845
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu } = WithAudioPlayback.useComponentContext();
|
|
20565
20846
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20566
20847
|
const [actionsBoxButtonElement, setActionsBoxButtonElement] = React.useState(null);
|
|
20567
20848
|
const filteredMessageActionSet = useBaseMessageActionSetFilter(
|
|
20568
20849
|
messageActionSet,
|
|
20569
20850
|
disableBaseMessageActionSetFilter
|
|
20570
20851
|
);
|
|
20571
|
-
const { dropdownActionSet, quickActionSet } = useSplitActionSet(
|
|
20572
|
-
|
|
20573
|
-
);
|
|
20574
|
-
const dropdownDialogId = `message-actions--${message.id}`;
|
|
20852
|
+
const { dropdownActionSet, quickActionSet, quickDropdownToggleAction } = useSplitActionSet(filteredMessageActionSet);
|
|
20853
|
+
const messageActionsDialogId = MessageActions.getDialogId({ messageId: message.id });
|
|
20575
20854
|
const reactionSelectorDialogId = ReactionSelector.getDialogId({
|
|
20576
20855
|
messageId: message.id,
|
|
20577
20856
|
threadList
|
|
20578
20857
|
});
|
|
20579
|
-
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
20580
|
-
|
|
20858
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
20859
|
+
id: messageActionsDialogId
|
|
20860
|
+
});
|
|
20861
|
+
const messageActionsDialogIsOpen = useDialogIsOpen(
|
|
20862
|
+
messageActionsDialogId,
|
|
20863
|
+
dialogManager?.id
|
|
20864
|
+
);
|
|
20581
20865
|
const reactionSelectorDialogIsOpen = useDialogIsOpen(
|
|
20582
20866
|
reactionSelectorDialogId,
|
|
20583
20867
|
dialogManager?.id
|
|
20584
20868
|
);
|
|
20585
|
-
const contextMenuItems = React.useMemo(
|
|
20586
|
-
() => dropdownActionSet.map(({ Component }) => {
|
|
20587
|
-
const ActionItem = (menuProps) => /* @__PURE__ */ jsxRuntime.jsx(Component, { ...menuProps });
|
|
20588
|
-
return ActionItem;
|
|
20589
|
-
}),
|
|
20590
|
-
[dropdownActionSet]
|
|
20591
|
-
);
|
|
20592
20869
|
if (dropdownActionSet.length + quickActionSet.length === 0) {
|
|
20593
20870
|
return null;
|
|
20594
20871
|
}
|
|
20595
20872
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20596
20873
|
"div",
|
|
20597
20874
|
{
|
|
20598
|
-
className: clsx(
|
|
20599
|
-
"str-chat__message-options--active":
|
|
20875
|
+
className: clsx("str-chat__message-options", {
|
|
20876
|
+
"str-chat__message-options--active": messageActionsDialogIsOpen || reactionSelectorDialogIsOpen
|
|
20600
20877
|
}),
|
|
20601
20878
|
children: [
|
|
20602
|
-
dropdownActionSet.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20603
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20604
|
-
WithAudioPlayback.Button,
|
|
20605
|
-
{
|
|
20606
|
-
appearance: "ghost",
|
|
20607
|
-
"aria-expanded": dropdownDialogIsOpen,
|
|
20608
|
-
"aria-haspopup": "true",
|
|
20609
|
-
"aria-label": t("aria/Open Message Actions Menu"),
|
|
20610
|
-
circular: true,
|
|
20611
|
-
className: "str-chat__message-actions-box-button",
|
|
20612
|
-
"data-testid": "message-actions-toggle-button",
|
|
20613
|
-
onClick: () => {
|
|
20614
|
-
dialog?.toggle();
|
|
20615
|
-
},
|
|
20616
|
-
ref: setActionsBoxButtonElement,
|
|
20617
|
-
variant: "secondary",
|
|
20618
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ActionsIcon, { className: "str-chat__message-action-icon" })
|
|
20619
|
-
}
|
|
20620
|
-
),
|
|
20879
|
+
quickDropdownToggleAction && dropdownActionSet.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20880
|
+
/* @__PURE__ */ jsxRuntime.jsx(quickDropdownToggleAction.Component, { ref: setActionsBoxButtonElement }),
|
|
20621
20881
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20622
|
-
|
|
20882
|
+
ContextMenuComponent,
|
|
20623
20883
|
{
|
|
20624
20884
|
backLabel: t("Back"),
|
|
20625
20885
|
className: clsx("str-chat__message-actions-box", {
|
|
20626
|
-
"str-chat__message-actions-box--open":
|
|
20886
|
+
"str-chat__message-actions-box--open": messageActionsDialogIsOpen
|
|
20627
20887
|
}),
|
|
20628
20888
|
dialogManagerId: dialogManager?.id,
|
|
20629
|
-
id:
|
|
20630
|
-
items: contextMenuItems,
|
|
20889
|
+
id: messageActionsDialogId,
|
|
20631
20890
|
onClose: dialog?.close,
|
|
20632
20891
|
placement: isMyMessage() ? "top-end" : "top-start",
|
|
20633
20892
|
referenceElement: actionsBoxButtonElement,
|
|
20634
20893
|
tabIndex: -1,
|
|
20635
|
-
trapFocus: true
|
|
20894
|
+
trapFocus: true,
|
|
20895
|
+
children: dropdownActionSet.map(({ Component, type }) => /* @__PURE__ */ jsxRuntime.jsx(Component, {}, type))
|
|
20636
20896
|
}
|
|
20637
20897
|
)
|
|
20638
20898
|
] }),
|
|
@@ -20641,6 +20901,8 @@ const MessageActions = ({
|
|
|
20641
20901
|
}
|
|
20642
20902
|
);
|
|
20643
20903
|
};
|
|
20904
|
+
MessageActions.getDialogId = ({ messageId }) => `message-actions-${messageId}`;
|
|
20905
|
+
MessageActions.displayName = "MessageActions";
|
|
20644
20906
|
const MessageUIWithContext = ({
|
|
20645
20907
|
endOfGroup,
|
|
20646
20908
|
firstOfGroup,
|
|
@@ -20804,7 +21066,7 @@ const MessageUIWithContext = ({
|
|
|
20804
21066
|
isAIGenerated ? /* @__PURE__ */ jsxRuntime.jsx(StreamedMessageText$1, { message, renderText: renderText2 }) : /* @__PURE__ */ jsxRuntime.jsx(MessageText, { message, renderText: renderText2 })
|
|
20805
21067
|
] }),
|
|
20806
21068
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-host", children: hasReactions && /* @__PURE__ */ jsxRuntime.jsx(MessageReactions$1, { reverse: true }) }),
|
|
20807
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21069
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-error-indicator", children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBadge, {}) })
|
|
20808
21070
|
] })
|
|
20809
21071
|
]
|
|
20810
21072
|
}
|
|
@@ -21467,6 +21729,7 @@ const useScrollLocationLogic = (params) => {
|
|
|
21467
21729
|
const closeToBottom = React.useRef(false);
|
|
21468
21730
|
const closeToTop = React.useRef(false);
|
|
21469
21731
|
const previousScrollTopRef = React.useRef(0);
|
|
21732
|
+
const previousMessagesLengthRef = React.useRef(messages.length);
|
|
21470
21733
|
const anchorRestoreCleanupRef = React.useRef(null);
|
|
21471
21734
|
const captureAnchor = React.useCallback(() => {
|
|
21472
21735
|
if (!listElement) return null;
|
|
@@ -21618,6 +21881,60 @@ const useScrollLocationLogic = (params) => {
|
|
|
21618
21881
|
scrollToBottom();
|
|
21619
21882
|
}
|
|
21620
21883
|
}, [disableAutoScrollToBottom, justReachedLatestMessageSet, listElement, hasMoreNewer]);
|
|
21884
|
+
React.useLayoutEffect(() => {
|
|
21885
|
+
if (!listElement || disableAutoScrollToBottom || hasMoreNewer || suppressAutoscroll || justReachedLatestMessageSet || isRestoringOlderAnchorRef.current) {
|
|
21886
|
+
return;
|
|
21887
|
+
}
|
|
21888
|
+
const initialDistanceToBottom = listElement.scrollHeight - (listElement.scrollTop + listElement.clientHeight);
|
|
21889
|
+
const messagesHydrated = previousMessagesLengthRef.current === 0 && messages.length > 0;
|
|
21890
|
+
if (initialDistanceToBottom > scrolledUpThreshold && !messagesHydrated) {
|
|
21891
|
+
return;
|
|
21892
|
+
}
|
|
21893
|
+
let keepPinnedToBottom = true;
|
|
21894
|
+
const maybeScrollToBottom = () => {
|
|
21895
|
+
if (keepPinnedToBottom) {
|
|
21896
|
+
scrollToBottom();
|
|
21897
|
+
}
|
|
21898
|
+
};
|
|
21899
|
+
maybeScrollToBottom();
|
|
21900
|
+
const settleDelays = [80, messagesHydrated ? 260 : 420, 900, 1700];
|
|
21901
|
+
const settleTimeoutIds = settleDelays.map(
|
|
21902
|
+
(delay) => setTimeout(maybeScrollToBottom, delay)
|
|
21903
|
+
);
|
|
21904
|
+
const stopKeepingPinnedToBottom = () => {
|
|
21905
|
+
keepPinnedToBottom = false;
|
|
21906
|
+
};
|
|
21907
|
+
listElement.addEventListener("pointerdown", stopKeepingPinnedToBottom, {
|
|
21908
|
+
passive: true
|
|
21909
|
+
});
|
|
21910
|
+
listElement.addEventListener("touchstart", stopKeepingPinnedToBottom, {
|
|
21911
|
+
passive: true
|
|
21912
|
+
});
|
|
21913
|
+
listElement.addEventListener("wheel", stopKeepingPinnedToBottom, {
|
|
21914
|
+
passive: true
|
|
21915
|
+
});
|
|
21916
|
+
listElement.addEventListener("keydown", stopKeepingPinnedToBottom);
|
|
21917
|
+
const pinWindowTimeoutId = setTimeout(() => {
|
|
21918
|
+
stopKeepingPinnedToBottom();
|
|
21919
|
+
}, 2200);
|
|
21920
|
+
return () => {
|
|
21921
|
+
settleTimeoutIds.forEach(clearTimeout);
|
|
21922
|
+
clearTimeout(pinWindowTimeoutId);
|
|
21923
|
+
listElement.removeEventListener("pointerdown", stopKeepingPinnedToBottom);
|
|
21924
|
+
listElement.removeEventListener("touchstart", stopKeepingPinnedToBottom);
|
|
21925
|
+
listElement.removeEventListener("wheel", stopKeepingPinnedToBottom);
|
|
21926
|
+
listElement.removeEventListener("keydown", stopKeepingPinnedToBottom);
|
|
21927
|
+
};
|
|
21928
|
+
}, [
|
|
21929
|
+
disableAutoScrollToBottom,
|
|
21930
|
+
hasMoreNewer,
|
|
21931
|
+
justReachedLatestMessageSet,
|
|
21932
|
+
listElement,
|
|
21933
|
+
messages.length,
|
|
21934
|
+
scrollToBottom,
|
|
21935
|
+
scrolledUpThreshold,
|
|
21936
|
+
suppressAutoscroll
|
|
21937
|
+
]);
|
|
21621
21938
|
const updateScrollTop = useMessageListScrollManager({
|
|
21622
21939
|
captureAnchor,
|
|
21623
21940
|
disableScrollManagement: disableScrollManagement || isRestoringOlderAnchorRef.current,
|
|
@@ -21644,6 +21961,9 @@ const useScrollLocationLogic = (params) => {
|
|
|
21644
21961
|
React.useLayoutEffect(() => {
|
|
21645
21962
|
previousHasMoreNewerRef.current = hasMoreNewer;
|
|
21646
21963
|
}, [hasMoreNewer]);
|
|
21964
|
+
React.useLayoutEffect(() => {
|
|
21965
|
+
previousMessagesLengthRef.current = messages.length;
|
|
21966
|
+
}, [messages.length]);
|
|
21647
21967
|
const onScroll = React.useCallback(
|
|
21648
21968
|
(event) => {
|
|
21649
21969
|
const element = event.target;
|
|
@@ -21652,8 +21972,10 @@ const useScrollLocationLogic = (params) => {
|
|
|
21652
21972
|
updateScrollTop(scrollTop, captureAnchor);
|
|
21653
21973
|
const offsetHeight = element.offsetHeight;
|
|
21654
21974
|
const scrollHeight = element.scrollHeight;
|
|
21975
|
+
const distanceToBottom = scrollHeight - (scrollTop + offsetHeight);
|
|
21976
|
+
const bottomEnterThreshold = Math.max(Math.floor(scrolledUpThreshold * 0.6), 24);
|
|
21655
21977
|
const prevCloseToBottom = closeToBottom.current;
|
|
21656
|
-
closeToBottom.current =
|
|
21978
|
+
closeToBottom.current = prevCloseToBottom ? distanceToBottom < scrolledUpThreshold : distanceToBottom < bottomEnterThreshold;
|
|
21657
21979
|
closeToTop.current = scrollTop < scrolledUpThreshold;
|
|
21658
21980
|
if (closeToBottom.current) {
|
|
21659
21981
|
setHasNewMessages(false);
|
|
@@ -22488,7 +22810,7 @@ function defaultRenderMessages({
|
|
|
22488
22810
|
return renderedMessages;
|
|
22489
22811
|
}
|
|
22490
22812
|
const findReverse = (items, matches) => {
|
|
22491
|
-
for (let i = items.length - 1; i
|
|
22813
|
+
for (let i = items.length - 1; i >= 0; i -= 1) {
|
|
22492
22814
|
if (matches(items[i])) {
|
|
22493
22815
|
return items[i];
|
|
22494
22816
|
}
|
|
@@ -23588,11 +23910,17 @@ const useConnectionRecoveredListener = (forceUpdate) => {
|
|
|
23588
23910
|
const MOBILE_NAV_BREAKPOINT = 768;
|
|
23589
23911
|
const useMobileNavigation = (channelListRef, navOpen, closeMobileNav) => {
|
|
23590
23912
|
React.useEffect(() => {
|
|
23913
|
+
const isClickInsideChannelList = (event) => {
|
|
23914
|
+
const channelListElement = channelListRef.current;
|
|
23915
|
+
if (!channelListElement) return false;
|
|
23916
|
+
const eventPath = event.composedPath();
|
|
23917
|
+
return eventPath.includes(channelListElement);
|
|
23918
|
+
};
|
|
23591
23919
|
const handleClickOutside = (event) => {
|
|
23592
23920
|
if (typeof window !== "undefined" && window.innerWidth >= MOBILE_NAV_BREAKPOINT) {
|
|
23593
23921
|
return;
|
|
23594
23922
|
}
|
|
23595
|
-
if (closeMobileNav && channelListRef.current && !
|
|
23923
|
+
if (closeMobileNav && channelListRef.current && !isClickInsideChannelList(event) && navOpen) {
|
|
23596
23924
|
closeMobileNav();
|
|
23597
23925
|
}
|
|
23598
23926
|
};
|
|
@@ -24354,7 +24682,7 @@ const SearchBar = () => {
|
|
|
24354
24682
|
};
|
|
24355
24683
|
const ChannelSearchResultItem = ({ item }) => {
|
|
24356
24684
|
const { setActiveChannel } = WithAudioPlayback.useChatContext();
|
|
24357
|
-
const { setChannels } = useChannelListContext();
|
|
24685
|
+
const { setChannels } = WithAudioPlayback.useChannelListContext();
|
|
24358
24686
|
const onSelect = React.useCallback(() => {
|
|
24359
24687
|
setActiveChannel(item);
|
|
24360
24688
|
setChannels?.((channels) => uniqBy([item, ...channels], "cid"));
|
|
@@ -24377,7 +24705,7 @@ const MessageSearchResultItem = ({
|
|
|
24377
24705
|
searchController,
|
|
24378
24706
|
setActiveChannel
|
|
24379
24707
|
} = WithAudioPlayback.useChatContext();
|
|
24380
|
-
const { setChannels } = useChannelListContext();
|
|
24708
|
+
const { setChannels } = WithAudioPlayback.useChannelListContext();
|
|
24381
24709
|
const channel = React.useMemo(() => {
|
|
24382
24710
|
const { channel: channelData } = item;
|
|
24383
24711
|
const type = channelData?.type ?? "unknown";
|
|
@@ -24410,7 +24738,7 @@ const MessageSearchResultItem = ({
|
|
|
24410
24738
|
};
|
|
24411
24739
|
const UserSearchResultItem = ({ item }) => {
|
|
24412
24740
|
const { client, setActiveChannel } = WithAudioPlayback.useChatContext();
|
|
24413
|
-
const { setChannels } = useChannelListContext();
|
|
24741
|
+
const { setChannels } = WithAudioPlayback.useChannelListContext();
|
|
24414
24742
|
const { directMessagingChannelType } = useSearchContext();
|
|
24415
24743
|
const onClick = React.useCallback(() => {
|
|
24416
24744
|
const newChannel = client.channel(directMessagingChannelType, {
|
|
@@ -24722,7 +25050,7 @@ const UnMemoizedLoadMoreButton = ({
|
|
|
24722
25050
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__load-more-button", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
24723
25051
|
WithAudioPlayback.Button,
|
|
24724
25052
|
{
|
|
24725
|
-
appearance: "
|
|
25053
|
+
appearance: "ghost",
|
|
24726
25054
|
"aria-label": t("aria/Load More Channels"),
|
|
24727
25055
|
"data-testid": "load-more-button",
|
|
24728
25056
|
disabled: loading,
|
|
@@ -24936,7 +25264,7 @@ const UnMemoizedChannelList = (props) => {
|
|
|
24936
25264
|
);
|
|
24937
25265
|
const showChannelList = !searchIsActive;
|
|
24938
25266
|
return /* @__PURE__ */ jsxRuntime.jsx(DialogManagerProvider, { id: `channel-list-dialog-manager-${stableId}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
24939
|
-
ChannelListContextProvider,
|
|
25267
|
+
WithAudioPlayback.ChannelListContextProvider,
|
|
24940
25268
|
{
|
|
24941
25269
|
value: { channels, hasNextPage, loadNextPage, setChannels },
|
|
24942
25270
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ref: channelListRef, children: [
|
|
@@ -25330,6 +25658,36 @@ const useArchiveActionButtonBehavior = () => {
|
|
|
25330
25658
|
};
|
|
25331
25659
|
};
|
|
25332
25660
|
const defaultChannelActionSet = [
|
|
25661
|
+
{
|
|
25662
|
+
// eslint-disable-next-line react/display-name
|
|
25663
|
+
Component: React.forwardRef((_, ref) => {
|
|
25664
|
+
const { channel } = useChannelListItemContext();
|
|
25665
|
+
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
25666
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25667
|
+
channelId: channel.id
|
|
25668
|
+
});
|
|
25669
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25670
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
25671
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25672
|
+
WithAudioPlayback.Button,
|
|
25673
|
+
{
|
|
25674
|
+
appearance: "ghost",
|
|
25675
|
+
"aria-expanded": dialogIsOpen,
|
|
25676
|
+
"aria-pressed": dialogIsOpen,
|
|
25677
|
+
circular: true,
|
|
25678
|
+
onClick: (e) => {
|
|
25679
|
+
e.stopPropagation();
|
|
25680
|
+
dialog.toggle();
|
|
25681
|
+
},
|
|
25682
|
+
ref,
|
|
25683
|
+
size: "sm",
|
|
25684
|
+
variant: "secondary",
|
|
25685
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconDotGrid1x3Horizontal, {})
|
|
25686
|
+
}
|
|
25687
|
+
);
|
|
25688
|
+
}),
|
|
25689
|
+
placement: "quick-dropdown-toggle"
|
|
25690
|
+
},
|
|
25333
25691
|
{
|
|
25334
25692
|
Component() {
|
|
25335
25693
|
const behaviorProps = useArchiveActionButtonBehavior();
|
|
@@ -25462,7 +25820,7 @@ const defaultChannelActionSet = [
|
|
|
25462
25820
|
const membership = useChannelMembershipState(channel);
|
|
25463
25821
|
const dialogId2 = ChannelListItemActionButtons.getDialogId(
|
|
25464
25822
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25465
|
-
channel.id
|
|
25823
|
+
{ channelId: channel.id }
|
|
25466
25824
|
);
|
|
25467
25825
|
const { dialog } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25468
25826
|
const [inProgress, setInProgress] = React.useState(false);
|
|
@@ -25564,59 +25922,23 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25564
25922
|
const connectedUserIsMember = typeof membership.user !== "undefined";
|
|
25565
25923
|
const ownCapabilities = channel.data?.own_capabilities;
|
|
25566
25924
|
return React.useMemo(() => {
|
|
25567
|
-
const filtered = channelActionSet.filter(
|
|
25568
|
-
(action)
|
|
25569
|
-
|
|
25570
|
-
|
|
25571
|
-
|
|
25572
|
-
|
|
25573
|
-
|
|
25574
|
-
|
|
25575
|
-
|
|
25576
|
-
|
|
25577
|
-
|
|
25578
|
-
|
|
25579
|
-
|
|
25580
|
-
|
|
25581
|
-
|
|
25582
|
-
|
|
25583
|
-
|
|
25584
|
-
},
|
|
25585
|
-
isDirectMessageChannel: false
|
|
25586
|
-
},
|
|
25587
|
-
{
|
|
25588
|
-
action: { placement: "dropdown", type: "mute" },
|
|
25589
|
-
isDirectMessageChannel: true,
|
|
25590
|
-
ownCapabilities: tsPattern.P.when(
|
|
25591
|
-
(capabilities) => capabilities?.includes("mute-channel")
|
|
25592
|
-
)
|
|
25593
|
-
},
|
|
25594
|
-
{
|
|
25595
|
-
action: { placement: "quick", type: "mute" },
|
|
25596
|
-
isDirectMessageChannel: false,
|
|
25597
|
-
ownCapabilities: tsPattern.P.when(
|
|
25598
|
-
(capabilities) => capabilities?.includes("mute-channel")
|
|
25599
|
-
)
|
|
25600
|
-
},
|
|
25601
|
-
{
|
|
25602
|
-
action: { type: "ban" },
|
|
25603
|
-
memberCount: tsPattern.P.number.gt(0).and(tsPattern.P.number.lte(2)),
|
|
25604
|
-
ownCapabilities: tsPattern.P.when(
|
|
25605
|
-
(capabilities) => capabilities?.includes("ban-channel-members")
|
|
25606
|
-
)
|
|
25607
|
-
},
|
|
25608
|
-
{
|
|
25609
|
-
action: { type: "leave" },
|
|
25610
|
-
ownCapabilities: tsPattern.P.when(
|
|
25611
|
-
(capabilities) => capabilities?.includes("leave-channel")
|
|
25612
|
-
)
|
|
25613
|
-
},
|
|
25614
|
-
{
|
|
25615
|
-
action: { connectedUserIsMember: true, type: "pin" }
|
|
25616
|
-
},
|
|
25617
|
-
() => true
|
|
25618
|
-
).otherwise(() => false)
|
|
25619
|
-
);
|
|
25925
|
+
const filtered = channelActionSet.filter((action) => {
|
|
25926
|
+
if (action.placement === "quick-dropdown-toggle") return true;
|
|
25927
|
+
switch (action.type) {
|
|
25928
|
+
case "archive":
|
|
25929
|
+
return connectedUserIsMember && (action.placement === "quick" && isDirectMessageChannel || action.placement === "dropdown" && !isDirectMessageChannel);
|
|
25930
|
+
case "mute":
|
|
25931
|
+
return ownCapabilities?.includes("mute-channel") && (action.placement === "dropdown" && isDirectMessageChannel || action.placement === "quick" && !isDirectMessageChannel);
|
|
25932
|
+
case "ban":
|
|
25933
|
+
return memberCount > 0 && memberCount <= 2 && ownCapabilities?.includes("ban-channel-members");
|
|
25934
|
+
case "leave":
|
|
25935
|
+
return ownCapabilities?.includes("leave-channel");
|
|
25936
|
+
case "pin":
|
|
25937
|
+
return connectedUserIsMember;
|
|
25938
|
+
default:
|
|
25939
|
+
return true;
|
|
25940
|
+
}
|
|
25941
|
+
});
|
|
25620
25942
|
return filtered;
|
|
25621
25943
|
}, [
|
|
25622
25944
|
channelActionSet,
|
|
@@ -25627,17 +25949,18 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25627
25949
|
]);
|
|
25628
25950
|
};
|
|
25629
25951
|
const ChannelListItemActionButtons = () => {
|
|
25952
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu } = WithAudioPlayback.useComponentContext();
|
|
25630
25953
|
const { channel } = useChannelListItemContext();
|
|
25631
25954
|
const [referenceElement, setReferenceElement] = React.useState(null);
|
|
25632
|
-
const dialogId2 = ChannelListItemActionButtons.getDialogId(
|
|
25955
|
+
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
25633
25956
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25634
|
-
channel.id
|
|
25635
|
-
);
|
|
25957
|
+
channelId: channel.id
|
|
25958
|
+
});
|
|
25636
25959
|
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25637
25960
|
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
25638
25961
|
const filteredActionSet = useBaseChannelActionSetFilter(defaultChannelActionSet);
|
|
25639
|
-
const
|
|
25640
|
-
if (
|
|
25962
|
+
const { dropdownActionSet, quickActionSet, quickDropdownToggleAction } = useSplitActionSet(filteredActionSet);
|
|
25963
|
+
if (quickActionSet.length + dropdownActionSet.length === 0) {
|
|
25641
25964
|
return null;
|
|
25642
25965
|
}
|
|
25643
25966
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -25647,26 +25970,10 @@ const ChannelListItemActionButtons = () => {
|
|
|
25647
25970
|
"str-chat__channel-list-item__action-buttons--active": dialogIsOpen
|
|
25648
25971
|
}),
|
|
25649
25972
|
children: [
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
{
|
|
25653
|
-
appearance: "ghost",
|
|
25654
|
-
"aria-expanded": dialogIsOpen,
|
|
25655
|
-
"aria-pressed": dialogIsOpen,
|
|
25656
|
-
circular: true,
|
|
25657
|
-
onClick: (e) => {
|
|
25658
|
-
e.stopPropagation();
|
|
25659
|
-
dialog.toggle();
|
|
25660
|
-
},
|
|
25661
|
-
ref: setReferenceElement,
|
|
25662
|
-
size: "sm",
|
|
25663
|
-
variant: "secondary",
|
|
25664
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconDotGrid1x3Horizontal, {})
|
|
25665
|
-
}
|
|
25666
|
-
),
|
|
25667
|
-
splitActionSet.quickActionSet.map(({ Component, type }) => /* @__PURE__ */ jsxRuntime.jsx(Component, {}, type)),
|
|
25973
|
+
quickDropdownToggleAction && dropdownActionSet.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(quickDropdownToggleAction.Component, { ref: setReferenceElement }),
|
|
25974
|
+
quickActionSet.map(({ Component, type }) => /* @__PURE__ */ jsxRuntime.jsx(Component, {}, type)),
|
|
25668
25975
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25669
|
-
|
|
25976
|
+
ContextMenuComponent,
|
|
25670
25977
|
{
|
|
25671
25978
|
className: "str-chat__channel-list-item__action-buttons-context-menu",
|
|
25672
25979
|
dialogManagerId: dialogManager?.id,
|
|
@@ -25676,14 +25983,14 @@ const ChannelListItemActionButtons = () => {
|
|
|
25676
25983
|
referenceElement,
|
|
25677
25984
|
tabIndex: -1,
|
|
25678
25985
|
trapFocus: true,
|
|
25679
|
-
children:
|
|
25986
|
+
children: dropdownActionSet.map(({ Component, type }) => /* @__PURE__ */ jsxRuntime.jsx(Component, {}, type))
|
|
25680
25987
|
}
|
|
25681
25988
|
)
|
|
25682
25989
|
]
|
|
25683
25990
|
}
|
|
25684
25991
|
);
|
|
25685
25992
|
};
|
|
25686
|
-
ChannelListItemActionButtons.getDialogId = (channelId) => `channel-action-buttons-${channelId}`;
|
|
25993
|
+
ChannelListItemActionButtons.getDialogId = ({ channelId }) => `channel-action-buttons-${channelId}`;
|
|
25687
25994
|
ChannelListItemActionButtons.displayName = "ChannelListItemActionButtons";
|
|
25688
25995
|
function ChannelListItemTimestamp({ lastMessage }) {
|
|
25689
25996
|
const { t, tDateTimeParser } = WithAudioPlayback.useTranslationContext("ChannelListItemTimestamp");
|
|
@@ -26622,7 +26929,8 @@ const ThreadList = ({ virtuosoProps }) => {
|
|
|
26622
26929
|
};
|
|
26623
26930
|
const IconsBySeverity = {
|
|
26624
26931
|
error: WithAudioPlayback.IconExclamationCircle,
|
|
26625
|
-
info:
|
|
26932
|
+
info: null,
|
|
26933
|
+
// IconCircleInfoTooltip,
|
|
26626
26934
|
loading: WithAudioPlayback.IconArrowRotateRightLeftRepeatRefresh,
|
|
26627
26935
|
success: WithAudioPlayback.IconCheckmark2,
|
|
26628
26936
|
warning: WithAudioPlayback.IconExclamationTriangle
|
|
@@ -26630,7 +26938,7 @@ const IconsBySeverity = {
|
|
|
26630
26938
|
const DefaultNotificationIcon = ({ notification }) => {
|
|
26631
26939
|
if (!notification.severity) return null;
|
|
26632
26940
|
const Icon = IconsBySeverity[notification.severity] ?? null;
|
|
26633
|
-
return Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, {});
|
|
26941
|
+
return Icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__notification-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, {}) });
|
|
26634
26942
|
};
|
|
26635
26943
|
const Notification = React.forwardRef(
|
|
26636
26944
|
({
|
|
@@ -26674,7 +26982,7 @@ const Notification = React.forwardRef(
|
|
|
26674
26982
|
ref,
|
|
26675
26983
|
children: [
|
|
26676
26984
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__notification-content", children: [
|
|
26677
|
-
Icon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26985
|
+
Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { notification }),
|
|
26678
26986
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__notification-message", children: displayMessage })
|
|
26679
26987
|
] }),
|
|
26680
26988
|
notification.actions && notification.actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__notification-actions", children: notification.actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -27008,7 +27316,7 @@ const VoiceRecordingPlayerUI = ({ audioPlayer }) => {
|
|
|
27008
27316
|
secondsElapsed
|
|
27009
27317
|
} = WithAudioPlayback.useStateStore(audioPlayer?.state, audioPlayerStateSelector) ?? {};
|
|
27010
27318
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rootClassName, "data-testid": "voice-recording-widget", children: [
|
|
27011
|
-
/* @__PURE__ */ jsxRuntime.jsx(PlayButton, { isPlaying: !!isPlaying, onClick: audioPlayer.togglePlay }),
|
|
27319
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__play-button-container", children: /* @__PURE__ */ jsxRuntime.jsx(PlayButton, { isPlaying: !!isPlaying, onClick: audioPlayer.togglePlay }) }),
|
|
27012
27320
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__metadata", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-attachment__voice-recording-widget__audio-state", children: [
|
|
27013
27321
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__timer", children: durationSeconds ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
27014
27322
|
DurationDisplay,
|
|
@@ -27417,23 +27725,44 @@ const FileAttachment = ({ attachment }) => {
|
|
|
27417
27725
|
);
|
|
27418
27726
|
};
|
|
27419
27727
|
const Giphy = ({ attachment }) => {
|
|
27420
|
-
const { giphyVersion: giphyVersionName } = WithAudioPlayback.useChannelStateContext();
|
|
27728
|
+
const { giphyVersion: giphyVersionName, imageAttachmentSizeHandler } = WithAudioPlayback.useChannelStateContext();
|
|
27421
27729
|
const { BaseImage: BaseImage$1 = BaseImage } = WithAudioPlayback.useComponentContext();
|
|
27422
27730
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
27423
27731
|
const usesDefaultBaseImage = BaseImage$1 === BaseImage;
|
|
27732
|
+
const imageElement = React.useRef(null);
|
|
27733
|
+
const [attachmentConfiguration, setAttachmentConfiguration] = React.useState(void 0);
|
|
27424
27734
|
const imageDescriptors = React.useMemo(
|
|
27425
27735
|
() => toGalleryItemDescriptors(attachment, { giphyVersionName }),
|
|
27426
27736
|
[attachment, giphyVersionName]
|
|
27427
27737
|
);
|
|
27428
|
-
|
|
27429
|
-
const
|
|
27738
|
+
const alt = imageDescriptors && imageDescriptors.alt;
|
|
27739
|
+
const dimensions = imageDescriptors && imageDescriptors.dimensions;
|
|
27740
|
+
const imageUrl = imageDescriptors && imageDescriptors.imageUrl;
|
|
27741
|
+
const title = imageDescriptors && imageDescriptors.title;
|
|
27742
|
+
const resolvedImageUrl = attachmentConfiguration?.url || imageUrl;
|
|
27743
|
+
const imageStyleVariables = React.useMemo(() => {
|
|
27744
|
+
const originalHeight = Number(dimensions?.height);
|
|
27745
|
+
const originalWidth = Number(dimensions?.width);
|
|
27746
|
+
return {
|
|
27747
|
+
"--original-height": String(originalHeight > 1 ? originalHeight : 1e6),
|
|
27748
|
+
"--original-width": String(originalWidth > 1 ? originalWidth : 1e6)
|
|
27749
|
+
};
|
|
27750
|
+
}, [dimensions?.height, dimensions?.width]);
|
|
27751
|
+
React.useLayoutEffect(() => {
|
|
27752
|
+
if (!imageElement.current || !imageAttachmentSizeHandler) return;
|
|
27753
|
+
const config = imageAttachmentSizeHandler(attachment, imageElement.current);
|
|
27754
|
+
setAttachmentConfiguration(config);
|
|
27755
|
+
}, [attachment, imageAttachmentSizeHandler]);
|
|
27756
|
+
if (!imageUrl) return null;
|
|
27430
27757
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx(`str-chat__message-attachment-giphy`), children: [
|
|
27431
27758
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27432
27759
|
BaseImage$1,
|
|
27433
27760
|
{
|
|
27434
27761
|
alt: alt ?? title ?? t("User uploaded content"),
|
|
27435
27762
|
height: dimensions?.height,
|
|
27436
|
-
|
|
27763
|
+
ref: imageElement,
|
|
27764
|
+
src: resolvedImageUrl,
|
|
27765
|
+
style: imageStyleVariables,
|
|
27437
27766
|
width: dimensions?.width,
|
|
27438
27767
|
...usesDefaultBaseImage ? { showDownloadButtonOnError: false } : {}
|
|
27439
27768
|
}
|
|
@@ -28034,6 +28363,8 @@ exports.Button = WithAudioPlayback.Button;
|
|
|
28034
28363
|
exports.Channel = WithAudioPlayback.Channel;
|
|
28035
28364
|
exports.ChannelActionContext = WithAudioPlayback.ChannelActionContext;
|
|
28036
28365
|
exports.ChannelActionProvider = WithAudioPlayback.ChannelActionProvider;
|
|
28366
|
+
exports.ChannelListContext = WithAudioPlayback.ChannelListContext;
|
|
28367
|
+
exports.ChannelListContextProvider = WithAudioPlayback.ChannelListContextProvider;
|
|
28037
28368
|
exports.ChannelStateContext = WithAudioPlayback.ChannelStateContext;
|
|
28038
28369
|
exports.ChannelStateProvider = WithAudioPlayback.ChannelStateProvider;
|
|
28039
28370
|
exports.ChatContext = WithAudioPlayback.ChatContext;
|
|
@@ -28119,6 +28450,7 @@ exports.IconEditBigSolid = WithAudioPlayback.IconEditBigSolid;
|
|
|
28119
28450
|
exports.IconEmojiAddReaction = WithAudioPlayback.IconEmojiAddReaction;
|
|
28120
28451
|
exports.IconEmojiSad = WithAudioPlayback.IconEmojiSad;
|
|
28121
28452
|
exports.IconEmojiSmile = WithAudioPlayback.IconEmojiSmile;
|
|
28453
|
+
exports.IconExclamation = WithAudioPlayback.IconExclamation;
|
|
28122
28454
|
exports.IconExclamationCircle = WithAudioPlayback.IconExclamationCircle;
|
|
28123
28455
|
exports.IconExclamationCircle1 = WithAudioPlayback.IconExclamationCircle1;
|
|
28124
28456
|
exports.IconExclamationTriangle = WithAudioPlayback.IconExclamationTriangle;
|
|
@@ -28248,6 +28580,7 @@ exports.isMessageBlocked = WithAudioPlayback.isMessageBlocked;
|
|
|
28248
28580
|
exports.isMessageBounced = WithAudioPlayback.isMessageBounced;
|
|
28249
28581
|
exports.isMessageEdited = WithAudioPlayback.isMessageEdited;
|
|
28250
28582
|
exports.isMessageErrorRetryable = WithAudioPlayback.isMessageErrorRetryable;
|
|
28583
|
+
exports.isNetworkSendFailure = WithAudioPlayback.isNetworkSendFailure;
|
|
28251
28584
|
exports.isNotificationForPanel = WithAudioPlayback.isNotificationForPanel;
|
|
28252
28585
|
exports.isNotificationTargetPanel = WithAudioPlayback.isNotificationTargetPanel;
|
|
28253
28586
|
exports.isNumberOrString = WithAudioPlayback.isNumberOrString;
|
|
@@ -28266,6 +28599,7 @@ exports.useActiveThread = WithAudioPlayback.useActiveThread;
|
|
|
28266
28599
|
exports.useAudioPlayer = WithAudioPlayback.useAudioPlayer;
|
|
28267
28600
|
exports.useChannelActionContext = WithAudioPlayback.useChannelActionContext;
|
|
28268
28601
|
exports.useChannelEditMessageHandler = WithAudioPlayback.useEditMessageHandler;
|
|
28602
|
+
exports.useChannelListContext = WithAudioPlayback.useChannelListContext;
|
|
28269
28603
|
exports.useChannelMentionsHandler = WithAudioPlayback.useMentionsHandlers;
|
|
28270
28604
|
exports.useChannelStateContext = WithAudioPlayback.useChannelStateContext;
|
|
28271
28605
|
exports.useChatContext = WithAudioPlayback.useChatContext;
|
|
@@ -28284,7 +28618,6 @@ exports.validateAndGetMessage = WithAudioPlayback.validateAndGetMessage;
|
|
|
28284
28618
|
exports.AIStateIndicator = AIStateIndicator;
|
|
28285
28619
|
exports.AIStates = AIStates;
|
|
28286
28620
|
exports.ATTACHMENT_GROUPS_ORDER = ATTACHMENT_GROUPS_ORDER;
|
|
28287
|
-
exports.ActionsIcon = ActionsIcon;
|
|
28288
28621
|
exports.AddCommentPrompt = AddCommentPrompt;
|
|
28289
28622
|
exports.Alert = Alert;
|
|
28290
28623
|
exports.AmountBar = AmountBar;
|
|
@@ -28310,8 +28643,6 @@ exports.CardContainer = CardContainer;
|
|
|
28310
28643
|
exports.ChannelAvatar = ChannelAvatar;
|
|
28311
28644
|
exports.ChannelHeader = ChannelHeader;
|
|
28312
28645
|
exports.ChannelList = ChannelList;
|
|
28313
|
-
exports.ChannelListContext = ChannelListContext;
|
|
28314
|
-
exports.ChannelListContextProvider = ChannelListContextProvider;
|
|
28315
28646
|
exports.ChannelListItem = ChannelListItem;
|
|
28316
28647
|
exports.ChannelListItemActionButtons = ChannelListItemActionButtons;
|
|
28317
28648
|
exports.ChannelListItemTimestamp = ChannelListItemTimestamp;
|
|
@@ -28328,6 +28659,7 @@ exports.ContextMenu = ContextMenu;
|
|
|
28328
28659
|
exports.ContextMenuBackButton = ContextMenuBackButton;
|
|
28329
28660
|
exports.ContextMenuBody = ContextMenuBody;
|
|
28330
28661
|
exports.ContextMenuButton = ContextMenuButton;
|
|
28662
|
+
exports.ContextMenuContent = ContextMenuContent;
|
|
28331
28663
|
exports.ContextMenuHeader = ContextMenuHeader;
|
|
28332
28664
|
exports.ContextMenuRoot = ContextMenuRoot;
|
|
28333
28665
|
exports.CooldownTimer = CooldownTimer;
|
|
@@ -28345,6 +28677,7 @@ exports.DurationDisplay = DurationDisplay;
|
|
|
28345
28677
|
exports.EmojiContextMenuButton = EmojiContextMenuButton;
|
|
28346
28678
|
exports.EmoticonItem = EmoticonItem;
|
|
28347
28679
|
exports.EndPollAlert = EndPollAlert;
|
|
28680
|
+
exports.ErrorBadge = ErrorBadge;
|
|
28348
28681
|
exports.EventComponent = EventComponent;
|
|
28349
28682
|
exports.FILE_ICON_GRAPHIC_CLASSNAME = FILE_ICON_GRAPHIC_CLASSNAME;
|
|
28350
28683
|
exports.FILE_ICON_NO_LABEL_CLASSNAME = FILE_ICON_NO_LABEL_CLASSNAME;
|
|
@@ -28393,13 +28726,13 @@ exports.MessageContext = MessageContext;
|
|
|
28393
28726
|
exports.MessageDeletedBubble = MessageDeletedBubble;
|
|
28394
28727
|
exports.MessageDeliveryStatus = MessageDeliveryStatus;
|
|
28395
28728
|
exports.MessageEditedIndicator = MessageEditedIndicator;
|
|
28396
|
-
exports.MessageErrorIcon = MessageErrorIcon;
|
|
28397
28729
|
exports.MessageList = MessageList;
|
|
28398
28730
|
exports.MessageListContext = MessageListContext;
|
|
28399
28731
|
exports.MessageListContextProvider = MessageListContextProvider;
|
|
28400
28732
|
exports.MessageProvider = MessageProvider;
|
|
28401
28733
|
exports.MessageReactions = MessageReactions;
|
|
28402
28734
|
exports.MessageReactionsDetail = MessageReactionsDetail;
|
|
28735
|
+
exports.MessageReactionsDetailLoadingIndicator = MessageReactionsDetailLoadingIndicator;
|
|
28403
28736
|
exports.MessageRepliesCountButton = MessageRepliesCountButton;
|
|
28404
28737
|
exports.MessageSearchResultItem = MessageSearchResultItem;
|
|
28405
28738
|
exports.MessageStatus = MessageStatus;
|
|
@@ -28421,7 +28754,6 @@ exports.NotificationTranslationTopic = NotificationTranslationTopic;
|
|
|
28421
28754
|
exports.NumericInput = NumericInput;
|
|
28422
28755
|
exports.OtherFilesContainer = OtherFilesContainer;
|
|
28423
28756
|
exports.PauseIcon = PauseIcon;
|
|
28424
|
-
exports.PinIcon = PinIcon;
|
|
28425
28757
|
exports.PinIndicator = PinIndicator;
|
|
28426
28758
|
exports.PlayButton = PlayButton;
|
|
28427
28759
|
exports.PlayIcon = PlayIcon;
|
|
@@ -28448,7 +28780,6 @@ exports.QuotedMessage = QuotedMessage;
|
|
|
28448
28780
|
exports.QuotedMessagePreview = QuotedMessagePreview;
|
|
28449
28781
|
exports.QuotedMessagePreviewUI = QuotedMessagePreviewUI;
|
|
28450
28782
|
exports.QuotedVoiceRecording = QuotedVoiceRecording;
|
|
28451
|
-
exports.ReactionIcon = ReactionIcon;
|
|
28452
28783
|
exports.ReactionSelector = ReactionSelector;
|
|
28453
28784
|
exports.RecordingPermission = RecordingPermission;
|
|
28454
28785
|
exports.RecordingPermissionDeniedNotification = RecordingPermissionDeniedNotification;
|
|
@@ -28488,7 +28819,6 @@ exports.TextInputFieldSet = TextInputFieldSet;
|
|
|
28488
28819
|
exports.TextareaComposer = TextareaComposer;
|
|
28489
28820
|
exports.Thread = Thread;
|
|
28490
28821
|
exports.ThreadHeader = ThreadHeader;
|
|
28491
|
-
exports.ThreadIcon = ThreadIcon;
|
|
28492
28822
|
exports.ThreadList = ThreadList;
|
|
28493
28823
|
exports.ThreadListItem = ThreadListItem;
|
|
28494
28824
|
exports.ThreadListItemUI = ThreadListItemUI;
|
|
@@ -28596,7 +28926,6 @@ exports.useCanCreatePoll = useCanCreatePoll;
|
|
|
28596
28926
|
exports.useChannelDeletedListener = useChannelDeletedListener;
|
|
28597
28927
|
exports.useChannelDisplayName = useChannelDisplayName;
|
|
28598
28928
|
exports.useChannelHiddenListener = useChannelHiddenListener;
|
|
28599
|
-
exports.useChannelListContext = useChannelListContext;
|
|
28600
28929
|
exports.useChannelListItemContext = useChannelListItemContext;
|
|
28601
28930
|
exports.useChannelMembersState = useChannelMembersState;
|
|
28602
28931
|
exports.useChannelMembershipState = useChannelMembershipState;
|