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/es/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import clsx from "clsx";
|
|
3
3
|
import { nanoid } from "nanoid";
|
|
4
|
-
import React, { useState, useEffect,
|
|
5
|
-
import { u as useHandleFileChangeWrapper, d as dataTransferItemsToFiles, r as renderAudio, t as toAudioBuffer, c as createFileFromBlobs, g as getExtensionFromMimeType, a as getRecordedMediaTypeFromMimeType } from "
|
|
6
|
-
import { u as useStateStore, a as useMessageComposerController, i as isMessageBounced, b as useChannelActionContext, C as ComponentContext, c as useTranslationContext, d as useChannelStateContext, e as useChatContext, f as isNotificationForPanel, B as BaseIcon, g as Button, I as IconPause, h as IconPlaySolid, j as getDefaultExportFromCjs, k as defaultTranslatorFunction, p as predefinedFormatters, L as LocalizedFormat, l as calendar, m as IconLoadingCircle,
|
|
7
|
-
import {
|
|
4
|
+
import React, { useState, useEffect, useCallback, useLayoutEffect, useMemo, useContext, createContext, useRef, forwardRef, createElement, Component, Fragment as Fragment$1 } from "react";
|
|
5
|
+
import { u as useHandleFileChangeWrapper, d as dataTransferItemsToFiles, r as renderAudio, t as toAudioBuffer, c as createFileFromBlobs, g as getExtensionFromMimeType, a as getRecordedMediaTypeFromMimeType } from "./audioProcessing.21cb49e1.mjs";
|
|
6
|
+
import { u as useStateStore, a as useMessageComposerController, i as isMessageBounced, b as useChannelActionContext, C as ComponentContext, c as useTranslationContext, d as useChannelStateContext, e as useChatContext, f as isNotificationForPanel, B as BaseIcon, g as Button, I as IconPause, h as IconPlaySolid, j as getDefaultExportFromCjs, k as defaultTranslatorFunction, p as predefinedFormatters, L as LocalizedFormat, l as calendar, m as IconLoadingCircle, n as isNetworkSendFailure, v as validateAndGetMessage, o as isUserMuted, q as defaultPinPermissions, r as useThreadContext, s as usePopoverPosition, t as useComponentContext, w as IconCrossMedium, x as IconPeople, y as IconExclamation, z as IconChevronRight, A as IconChevronLeft, D as IconArrowLeft, E as IconExclamationCircle, F as IconCircleBanSign, G as isMessageErrorRetryable, H as ACTIONS_NOT_WORKING_IN_THREAD, J as useNotificationTarget, K as IconArrowRightUp, M as addNotificationTargetTag, N as IconPin, O as mapToUserNameOrId, P as IconClock, Q as IconCheckmark1Small, R as IconDoubleCheckmark1Small, S as getReadByTooltipText, T as messageHasAttachments, U as messageTextHasEmojisOnly, V as isDate, W as getDateString, X as IconTranslate, Y as useMessageComposerContext, Z as useIsCooldownActive, _ as IconCrossSmall, $ as IconImages1Alt, a0 as IconChart5, a1 as IconMapPin, a2 as IconFileBend, a3 as IconChainLink, a4 as IconVideo, a5 as IconVideoSolid, a6 as IconMicrophone, a7 as IconBookmark, a8 as IconBellNotification, a9 as IconChevronDown, aa as IconPlusSmall, ab as IconCheckmark2, ac as DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ad as IconTrophy, ae as IconDotGrid2x3, af as IconCircleMinus, ag as IconPaperPlane, ah as IconVolumeFull, ai as IconPeopleAdd, aj as IconMute, ak as IconFlag2, al as IconPeopleRemove, am as IconPaperclip, an as IconRunShortcut, ao as CHANNEL_CONTAINER_ID, ap as IconPlusLarge, aq as IconExclamationTriangle, ar as useAudioPlayer, as as IconArrowRotateClockwise, at as IconArrowDownCircle, au as IconThunder, av as IconTrashBin, aw as IconFileArrowLeftIn, ax as MessageComposerContextProvider, ay as useTypingContext, az as defaultDateTimeParser, aA as isLanguageSupported, aB as IconLayoutAlignLeft, aC as useChatViewContext, aD as MESSAGE_ACTIONS, aE as LegacyThreadContext, aF as IconArrowShareLeft, aG as IconEmojiSmile, aH as IconDotGrid1x3Horizontal, aI as IconPeopleAdded, aJ as IconBookmarkRemove, aK as IconBellOff, aL as IconBubbleWideNotificationChatMessage, aM as IconEditBig, aN as IconSquareBehindSquare2_Copy, aO as IconUnpin, aP as IconCloseQuote2, aQ as IconBubbleText6ChatMessage, aR as areMessageUIPropsEqual, aS as isDateSeparatorMessage, aT as isMessageBlocked, aU as messageHasSingleAttachment, aV as messageHasGiphyAttachment, aW as messageHasReactions, aX as isMessageEdited, aY as countEmojis, aZ as areMessagePropsEqual, a_ as getMessageActions, a$ as processMessages, b0 as insertIntro, b1 as getGroupStyles, b2 as getLastReceived, b3 as IconArrowUp, b4 as isIntroMessage, b5 as isLocalMessage, b6 as getIsFirstUnreadMessage, b7 as IconArrowDown, b8 as DEFAULT_NEXT_CHANNEL_PAGE_SIZE, b9 as EmptyStateIndicator, ba as getChannel, bb as IconMagnifyingGlassSearch, bc as IconCircleX, bd as useChannelListContext, be as DEFAULT_JUMP_TO_PAGE_SIZE, bf as ChannelListContextProvider, bg as IconArchive, bh as IconArrowBoxLeft, bi as IconCamera1, bj as IconExclamationCircle1, bk as ChatProvider, bl as TranslationProvider, bm as useThreadsViewContext, bn as IconBubbles, bo as IconArrowRotateRightLeftRepeatRefresh, bp as IconEyeOpen } from "./WithAudioPlayback.a3d5a2fc.mjs";
|
|
7
|
+
import { bu, bx, dc, dd, de, df, dg, dh, bz, bC, by, bB, bD, di, bG, bH, bI, bJ, bK, bL, bM, bN, bO, bP, bQ, bR, bT, bS, bU, bV, bW, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, co, cp, cq, cr, cs, ct, cu, cv, cw, cx, cy, cz, cA, cB, cC, cD, cE, cF, cG, cH, cI, cJ, cK, cL, cM, cN, cO, cP, cQ, cR, cS, cT, cU, cV, cW, cX, cY, cZ, c_, dj, c$, da, db, dk, dl, dm, br, bF, bE, bs, bt, d0, d1, d7, d8, d4, d5, dn, d6, dp, d3, d2, bq, bA, bv, bw, d9 } from "./WithAudioPlayback.a3d5a2fc.mjs";
|
|
8
8
|
import { StateStore, formatMessage, MessageComposer as MessageComposer$1, isGiphyAttachment, isScrapedContent, isLocalVideoAttachment, isVideoAttachment, isLocalImageAttachment, isImageAttachment, isAudioAttachment, isVoiceRecordingAttachment, isFileAttachment, isVoteAnswer, VotingVisibility, isLocalVoiceRecordingAttachment, isLocalAudioAttachment, isLocalFileAttachment, isLocalAttachment, LinkPreviewsManager, SearchController, ChannelSearchSource, UserSearchSource, MessageSearchSource, StreamChat, isSharedLocationResponse, LiveLocationManager } from "stream-chat";
|
|
9
9
|
import throttle from "lodash.throttle";
|
|
10
10
|
import * as linkify from "linkifyjs";
|
|
@@ -19,7 +19,6 @@ import { visit, SKIP } from "unist-util-visit";
|
|
|
19
19
|
import i18n from "i18next";
|
|
20
20
|
import Dayjs from "dayjs";
|
|
21
21
|
import uniqBy from "lodash.uniqby";
|
|
22
|
-
import { match, P } from "ts-pattern";
|
|
23
22
|
import { useSyncExternalStore } from "use-sync-external-store/shim";
|
|
24
23
|
import debounce from "lodash.debounce";
|
|
25
24
|
import fixWebmDuration from "fix-webm-duration";
|
|
@@ -71,28 +70,12 @@ const useAIState = (channel) => {
|
|
|
71
70
|
}, [channel]);
|
|
72
71
|
return { aiState };
|
|
73
72
|
};
|
|
74
|
-
const ChannelListContext = createContext(
|
|
75
|
-
void 0
|
|
76
|
-
);
|
|
77
|
-
const ChannelListContextProvider = ({
|
|
78
|
-
children,
|
|
79
|
-
value
|
|
80
|
-
}) => /* @__PURE__ */ jsx(ChannelListContext.Provider, { value, children });
|
|
81
|
-
const useChannelListContext = (componentName) => {
|
|
82
|
-
const contextValue = useContext(ChannelListContext);
|
|
83
|
-
if (!contextValue) {
|
|
84
|
-
console.warn(
|
|
85
|
-
`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.`
|
|
86
|
-
);
|
|
87
|
-
return {};
|
|
88
|
-
}
|
|
89
|
-
return contextValue;
|
|
90
|
-
};
|
|
91
73
|
class DialogManager {
|
|
92
|
-
constructor({ id } = {}) {
|
|
74
|
+
constructor({ closeOnClickOutside = true, id } = {}) {
|
|
93
75
|
this.state = new StateStore({
|
|
94
76
|
dialogsById: {}
|
|
95
77
|
});
|
|
78
|
+
this.closeOnClickOutside = closeOnClickOutside;
|
|
96
79
|
this.id = id ?? nanoid();
|
|
97
80
|
}
|
|
98
81
|
get openDialogCount() {
|
|
@@ -107,13 +90,14 @@ class DialogManager {
|
|
|
107
90
|
get(id) {
|
|
108
91
|
return this.state.getLatestValue().dialogsById[id];
|
|
109
92
|
}
|
|
110
|
-
getOrCreate({ id }) {
|
|
93
|
+
getOrCreate({ closeOnClickOutside, id }) {
|
|
111
94
|
let dialog = this.state.getLatestValue().dialogsById[id];
|
|
112
95
|
if (!dialog) {
|
|
113
96
|
dialog = {
|
|
114
97
|
close: () => {
|
|
115
98
|
this.close(id);
|
|
116
99
|
},
|
|
100
|
+
closeOnClickOutside,
|
|
117
101
|
id,
|
|
118
102
|
isOpen: false,
|
|
119
103
|
open: () => {
|
|
@@ -129,21 +113,22 @@ class DialogManager {
|
|
|
129
113
|
};
|
|
130
114
|
this.state.next((current) => ({
|
|
131
115
|
...current,
|
|
132
|
-
|
|
116
|
+
dialogsById: { ...current.dialogsById, [id]: dialog }
|
|
133
117
|
}));
|
|
134
118
|
}
|
|
135
|
-
|
|
136
|
-
|
|
119
|
+
const shouldUpdateDialogSettings = dialog.closeOnClickOutside !== closeOnClickOutside || !!dialog.removalTimeout;
|
|
120
|
+
if (shouldUpdateDialogSettings) {
|
|
121
|
+
if (dialog.removalTimeout) clearTimeout(dialog.removalTimeout);
|
|
122
|
+
dialog = {
|
|
123
|
+
...dialog,
|
|
124
|
+
closeOnClickOutside,
|
|
125
|
+
removalTimeout: void 0
|
|
126
|
+
};
|
|
137
127
|
this.state.next((current) => ({
|
|
138
128
|
...current,
|
|
139
|
-
|
|
140
|
-
dialogsById
|
|
141
|
-
|
|
142
|
-
[id]: {
|
|
143
|
-
...dialog,
|
|
144
|
-
removalTimeout: void 0
|
|
145
|
-
}
|
|
146
|
-
}
|
|
129
|
+
dialogsById: {
|
|
130
|
+
...current.dialogsById,
|
|
131
|
+
[id]: dialog
|
|
147
132
|
}
|
|
148
133
|
}));
|
|
149
134
|
}
|
|
@@ -220,7 +205,11 @@ class DialogManager {
|
|
|
220
205
|
}));
|
|
221
206
|
}
|
|
222
207
|
}
|
|
223
|
-
const useDialog = ({
|
|
208
|
+
const useDialog = ({
|
|
209
|
+
closeOnClickOutside,
|
|
210
|
+
dialogManagerId,
|
|
211
|
+
id
|
|
212
|
+
}) => {
|
|
224
213
|
const { dialogManager } = useDialogManager({ dialogManagerId });
|
|
225
214
|
useEffect(
|
|
226
215
|
() => () => {
|
|
@@ -228,7 +217,7 @@ const useDialog = ({ dialogManagerId, id }) => {
|
|
|
228
217
|
},
|
|
229
218
|
[dialogManager, id]
|
|
230
219
|
);
|
|
231
|
-
return dialogManager.getOrCreate({ id });
|
|
220
|
+
return dialogManager.getOrCreate({ closeOnClickOutside, id });
|
|
232
221
|
};
|
|
233
222
|
const useDialogOnNearestManager = ({ id }) => {
|
|
234
223
|
const { dialogManager } = useNearestDialogManagerContext() ?? {};
|
|
@@ -275,9 +264,37 @@ const Portal = ({
|
|
|
275
264
|
if (!portalDestination) return null;
|
|
276
265
|
return createPortal(children, portalDestination);
|
|
277
266
|
};
|
|
267
|
+
const shouldCloseOnOutsideClick = ({
|
|
268
|
+
dialog,
|
|
269
|
+
managerCloseOnClickOutside
|
|
270
|
+
}) => dialog.closeOnClickOutside ?? managerCloseOnClickOutside;
|
|
278
271
|
const DialogPortalDestination = () => {
|
|
279
272
|
const { dialogManager } = useNearestDialogManagerContext() ?? {};
|
|
280
273
|
const openedDialogCount = useOpenedDialogCount({ dialogManagerId: dialogManager?.id });
|
|
274
|
+
const [destinationRoot, setDestinationRoot] = useState(null);
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
if (!destinationRoot || !dialogManager) return;
|
|
277
|
+
const handleDocumentClick = (event) => {
|
|
278
|
+
if (destinationRoot.contains(event.target)) return;
|
|
279
|
+
setTimeout(() => {
|
|
280
|
+
Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
|
|
281
|
+
(dialog) => {
|
|
282
|
+
if (!dialog.isOpen) return;
|
|
283
|
+
if (!shouldCloseOnOutsideClick({
|
|
284
|
+
dialog,
|
|
285
|
+
managerCloseOnClickOutside: dialogManager.closeOnClickOutside
|
|
286
|
+
}))
|
|
287
|
+
return;
|
|
288
|
+
dialogManager.close(dialog.id);
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
}, 0);
|
|
292
|
+
};
|
|
293
|
+
document.addEventListener("click", handleDocumentClick, { capture: true });
|
|
294
|
+
return () => {
|
|
295
|
+
document.removeEventListener("click", handleDocumentClick, { capture: true });
|
|
296
|
+
};
|
|
297
|
+
}, [destinationRoot, dialogManager]);
|
|
281
298
|
if (!openedDialogCount) return null;
|
|
282
299
|
return /* @__PURE__ */ jsx(
|
|
283
300
|
"div",
|
|
@@ -285,7 +302,22 @@ const DialogPortalDestination = () => {
|
|
|
285
302
|
className: "str-chat__dialog-overlay",
|
|
286
303
|
"data-str-chat__portal-id": dialogManager?.id,
|
|
287
304
|
"data-testid": "str-chat__dialog-overlay",
|
|
288
|
-
onClick: () =>
|
|
305
|
+
onClick: (event) => {
|
|
306
|
+
if (!dialogManager) return;
|
|
307
|
+
if (event.target !== event.currentTarget) return;
|
|
308
|
+
Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
|
|
309
|
+
(dialog) => {
|
|
310
|
+
if (!dialog.isOpen) return;
|
|
311
|
+
if (!shouldCloseOnOutsideClick({
|
|
312
|
+
dialog,
|
|
313
|
+
managerCloseOnClickOutside: dialogManager.closeOnClickOutside
|
|
314
|
+
}))
|
|
315
|
+
return;
|
|
316
|
+
dialogManager.close(dialog.id);
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
},
|
|
320
|
+
ref: setDestinationRoot,
|
|
289
321
|
style: {
|
|
290
322
|
"--str-chat__dialog-overlay-height": openedDialogCount > 0 ? "100%" : "0"
|
|
291
323
|
}
|
|
@@ -307,11 +339,16 @@ const DialogPortalEntry = ({
|
|
|
307
339
|
};
|
|
308
340
|
const dialogManagersRegistry = new StateStore({});
|
|
309
341
|
const getDialogManager = (id) => dialogManagersRegistry.getLatestValue()[id];
|
|
310
|
-
const getOrCreateDialogManager = (
|
|
342
|
+
const getOrCreateDialogManager = ({
|
|
343
|
+
closeOnClickOutside,
|
|
344
|
+
id
|
|
345
|
+
}) => {
|
|
311
346
|
let manager = getDialogManager(id);
|
|
312
347
|
if (!manager) {
|
|
313
|
-
manager = new DialogManager({ id });
|
|
348
|
+
manager = new DialogManager({ closeOnClickOutside, id });
|
|
314
349
|
dialogManagersRegistry.partialNext({ [id]: manager });
|
|
350
|
+
} else if (typeof closeOnClickOutside === "boolean") {
|
|
351
|
+
manager.closeOnClickOutside = closeOnClickOutside;
|
|
315
352
|
}
|
|
316
353
|
return manager;
|
|
317
354
|
};
|
|
@@ -322,20 +359,21 @@ const removeDialogManager = (id) => {
|
|
|
322
359
|
const DialogManagerProviderContext = React.createContext(void 0);
|
|
323
360
|
const DialogManagerProvider = ({
|
|
324
361
|
children,
|
|
362
|
+
closeOnClickOutside,
|
|
325
363
|
id
|
|
326
364
|
}) => {
|
|
327
365
|
const [dialogManager, setDialogManager] = useState(() => {
|
|
328
366
|
if (id) return getDialogManager(id) ?? null;
|
|
329
|
-
return new DialogManager();
|
|
367
|
+
return new DialogManager({ closeOnClickOutside });
|
|
330
368
|
});
|
|
331
369
|
useEffect(() => {
|
|
332
370
|
if (!id) return;
|
|
333
|
-
setDialogManager(getOrCreateDialogManager(id));
|
|
371
|
+
setDialogManager(getOrCreateDialogManager({ closeOnClickOutside, id }));
|
|
334
372
|
return () => {
|
|
335
373
|
removeDialogManager(id);
|
|
336
374
|
setDialogManager(null);
|
|
337
375
|
};
|
|
338
|
-
}, [id]);
|
|
376
|
+
}, [closeOnClickOutside, id]);
|
|
339
377
|
if (!dialogManager) return null;
|
|
340
378
|
return /* @__PURE__ */ jsxs(DialogManagerProviderContext.Provider, { value: { dialogManager }, children: [
|
|
341
379
|
children,
|
|
@@ -950,7 +988,6 @@ const deTranslations = {
|
|
|
950
988
|
"End vote": "Abstimmung beenden",
|
|
951
989
|
"Enforce unique vote is enabled": "Eindeutige Abstimmung ist aktiviert",
|
|
952
990
|
"Error": "Fehler",
|
|
953
|
-
"Error · Unsent": "Fehler · Nicht gesendet",
|
|
954
991
|
"Error adding flag": "Fehler beim Hinzufügen des Flags",
|
|
955
992
|
"Error connecting to chat, refresh the page to try again.": "Verbindungsfehler zum Chat, aktualisieren Sie die Seite, um es erneut zu versuchen.",
|
|
956
993
|
"Error deleting message": "Fehler beim Löschen der Nachricht",
|
|
@@ -1072,8 +1109,6 @@ const deTranslations = {
|
|
|
1072
1109
|
"Maximum number of votes (from 2 to 10)": "Maximale Anzahl der Stimmen (von 2 bis 10)",
|
|
1073
1110
|
Menu: Menu$b,
|
|
1074
1111
|
"Message deleted": "Nachricht gelöscht",
|
|
1075
|
-
"Message Failed · Click to try again": "Nachricht fehlgeschlagen · Klicken, um es erneut zu versuchen",
|
|
1076
|
-
"Message Failed · Unauthorized": "Nachricht fehlgeschlagen · Nicht autorisiert",
|
|
1077
1112
|
"Message failed to send": "Nachricht konnte nicht gesendet werden",
|
|
1078
1113
|
"Message has been successfully flagged": "Nachricht wurde erfolgreich gemeldet",
|
|
1079
1114
|
"Message pinned": "Nachricht angeheftet",
|
|
@@ -1243,6 +1278,7 @@ const deTranslations = {
|
|
|
1243
1278
|
"View translation": "Übersetzung anzeigen",
|
|
1244
1279
|
"Voice message": "Sprachnachricht",
|
|
1245
1280
|
"Voice message {{ duration }}": "Sprachnachricht {{ duration }}",
|
|
1281
|
+
"Voice message deleted": "Sprachnachricht gelöscht",
|
|
1246
1282
|
voiceMessageCount_one: voiceMessageCount_one$9,
|
|
1247
1283
|
voiceMessageCount_other: voiceMessageCount_other$b,
|
|
1248
1284
|
"Vote ended": "Abstimmung beendet",
|
|
@@ -1473,7 +1509,6 @@ const enTranslations = {
|
|
|
1473
1509
|
"End vote": "End Vote",
|
|
1474
1510
|
"Enforce unique vote is enabled": "Enforce unique vote is enabled",
|
|
1475
1511
|
"Error": "Error",
|
|
1476
|
-
"Error · Unsent": "Error · Unsent",
|
|
1477
1512
|
"Error adding flag": "Error adding flag",
|
|
1478
1513
|
"Error connecting to chat, refresh the page to try again.": "Error connecting to chat, refresh the page to try again.",
|
|
1479
1514
|
"Error deleting message": "Error deleting message",
|
|
@@ -1595,8 +1630,6 @@ const enTranslations = {
|
|
|
1595
1630
|
"Maximum number of votes (from 2 to 10)": "Maximum number of votes (from 2 to 10)",
|
|
1596
1631
|
Menu: Menu$a,
|
|
1597
1632
|
"Message deleted": "Message deleted",
|
|
1598
|
-
"Message Failed · Click to try again": "Message Failed · Click to try again",
|
|
1599
|
-
"Message Failed · Unauthorized": "Message Failed · Unauthorized",
|
|
1600
1633
|
"Message failed to send": "Message failed to send",
|
|
1601
1634
|
"Message has been successfully flagged": "Message has been successfully flagged",
|
|
1602
1635
|
"Message pinned": "Message pinned",
|
|
@@ -1766,6 +1799,7 @@ const enTranslations = {
|
|
|
1766
1799
|
"View translation": "View translation",
|
|
1767
1800
|
"Voice message": "Voice message",
|
|
1768
1801
|
"Voice message {{ duration }}": "Voice message {{ duration }}",
|
|
1802
|
+
"Voice message deleted": "Voice message deleted",
|
|
1769
1803
|
voiceMessageCount_one: voiceMessageCount_one$8,
|
|
1770
1804
|
voiceMessageCount_other: voiceMessageCount_other$a,
|
|
1771
1805
|
"Vote ended": "Vote ended",
|
|
@@ -2012,7 +2046,6 @@ const esTranslations = {
|
|
|
2012
2046
|
"End vote": "Finalizar votación",
|
|
2013
2047
|
"Enforce unique vote is enabled": "El voto único está habilitado",
|
|
2014
2048
|
"Error": "Error",
|
|
2015
|
-
"Error · Unsent": "Error · No enviado",
|
|
2016
2049
|
"Error adding flag": "Error al agregar la bandera",
|
|
2017
2050
|
"Error connecting to chat, refresh the page to try again.": "Error al conectarse al chat, actualice la página para volver a intentarlo.",
|
|
2018
2051
|
"Error deleting message": "Error al eliminar el mensaje",
|
|
@@ -2137,8 +2170,6 @@ const esTranslations = {
|
|
|
2137
2170
|
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
|
|
2138
2171
|
Menu: Menu$9,
|
|
2139
2172
|
"Message deleted": "Mensaje eliminado",
|
|
2140
|
-
"Message Failed · Click to try again": "Mensaje fallido · Haga clic para volver a intentarlo",
|
|
2141
|
-
"Message Failed · Unauthorized": "Mensaje fallido · No autorizado",
|
|
2142
2173
|
"Message failed to send": "No se pudo enviar el mensaje",
|
|
2143
2174
|
"Message has been successfully flagged": "El mensaje se marcó correctamente",
|
|
2144
2175
|
"Message pinned": "Mensaje fijado",
|
|
@@ -2315,6 +2346,7 @@ const esTranslations = {
|
|
|
2315
2346
|
"View translation": "Ver traducción",
|
|
2316
2347
|
"Voice message": "Mensaje de voz",
|
|
2317
2348
|
"Voice message {{ duration }}": "Mensaje de voz {{ duration }}",
|
|
2349
|
+
"Voice message deleted": "Mensaje de voz eliminado",
|
|
2318
2350
|
voiceMessageCount_one: voiceMessageCount_one$7,
|
|
2319
2351
|
voiceMessageCount_many: voiceMessageCount_many$4,
|
|
2320
2352
|
voiceMessageCount_other: voiceMessageCount_other$9,
|
|
@@ -2562,7 +2594,6 @@ const frTranslations = {
|
|
|
2562
2594
|
"End vote": "Fin du vote",
|
|
2563
2595
|
"Enforce unique vote is enabled": "Le vote unique est activé",
|
|
2564
2596
|
"Error": "Erreur",
|
|
2565
|
-
"Error · Unsent": "Erreur - Non envoyé",
|
|
2566
2597
|
"Error adding flag": "Erreur lors de l'ajout du signalement",
|
|
2567
2598
|
"Error connecting to chat, refresh the page to try again.": "Erreur de connexion au chat, rafraîchissez la page pour réessayer.",
|
|
2568
2599
|
"Error deleting message": "Erreur lors de la suppression du message",
|
|
@@ -2687,8 +2718,6 @@ const frTranslations = {
|
|
|
2687
2718
|
"Maximum number of votes (from 2 to 10)": "Nombre maximum de votes (de 2 à 10)",
|
|
2688
2719
|
Menu: Menu$8,
|
|
2689
2720
|
"Message deleted": "Message supprimé",
|
|
2690
|
-
"Message Failed · Click to try again": "Échec de l'envoi du message - Cliquez pour réessayer",
|
|
2691
|
-
"Message Failed · Unauthorized": "Échec de l'envoi du message - Non autorisé",
|
|
2692
2721
|
"Message failed to send": "Échec de l'envoi du message",
|
|
2693
2722
|
"Message has been successfully flagged": "Le message a été signalé avec succès",
|
|
2694
2723
|
"Message pinned": "Message épinglé",
|
|
@@ -2865,6 +2894,7 @@ const frTranslations = {
|
|
|
2865
2894
|
"View translation": "Voir la traduction",
|
|
2866
2895
|
"Voice message": "Message vocal",
|
|
2867
2896
|
"Voice message {{ duration }}": "Message vocal {{ duration }}",
|
|
2897
|
+
"Voice message deleted": "Message vocal supprimé",
|
|
2868
2898
|
voiceMessageCount_one: voiceMessageCount_one$6,
|
|
2869
2899
|
voiceMessageCount_many: voiceMessageCount_many$3,
|
|
2870
2900
|
voiceMessageCount_other: voiceMessageCount_other$8,
|
|
@@ -3096,7 +3126,6 @@ const hiTranslations = {
|
|
|
3096
3126
|
"End vote": "मत समाप्त करें",
|
|
3097
3127
|
"Enforce unique vote is enabled": "अनोखा वोट सक्षम है",
|
|
3098
3128
|
"Error": "त्रुटि",
|
|
3099
|
-
"Error · Unsent": "फेल",
|
|
3100
3129
|
"Error adding flag": "ध्वज जोड़ने में त्रुटि",
|
|
3101
3130
|
"Error connecting to chat, refresh the page to try again.": "चैट से कनेक्ट करने में त्रुटि, पेज को रिफ्रेश करें",
|
|
3102
3131
|
"Error deleting message": "संदेश हटाने में त्रुटि",
|
|
@@ -3219,8 +3248,6 @@ const hiTranslations = {
|
|
|
3219
3248
|
"Maximum number of votes (from 2 to 10)": "अधिकतम वोटों की संख्या (2 से 10)",
|
|
3220
3249
|
Menu: Menu$7,
|
|
3221
3250
|
"Message deleted": "मैसेज हटा दिया गया",
|
|
3222
|
-
"Message Failed · Click to try again": "मैसेज फ़ैल - पुनः कोशिश करें",
|
|
3223
|
-
"Message Failed · Unauthorized": "मैसेज फ़ैल - अनधिकृत",
|
|
3224
3251
|
"Message failed to send": "संदेश भेजने में विफल",
|
|
3225
3252
|
"Message has been successfully flagged": "मैसेज को फ्लैग कर दिया गया है",
|
|
3226
3253
|
"Message pinned": "संदेश पिन किया गया",
|
|
@@ -3390,6 +3417,7 @@ const hiTranslations = {
|
|
|
3390
3417
|
"View translation": "अनुवाद देखें",
|
|
3391
3418
|
"Voice message": "आवाज संदेश",
|
|
3392
3419
|
"Voice message {{ duration }}": "वॉइस संदेश {{ duration }}",
|
|
3420
|
+
"Voice message deleted": "वॉइस संदेश हटा दिया गया",
|
|
3393
3421
|
voiceMessageCount_one: voiceMessageCount_one$5,
|
|
3394
3422
|
voiceMessageCount_other: voiceMessageCount_other$7,
|
|
3395
3423
|
"Vote ended": "मतदान समाप्त",
|
|
@@ -3636,7 +3664,6 @@ const itTranslations = {
|
|
|
3636
3664
|
"End vote": "Termina il voto",
|
|
3637
3665
|
"Enforce unique vote is enabled": "Il voto unico è abilitato",
|
|
3638
3666
|
"Error": "Errore",
|
|
3639
|
-
"Error · Unsent": "Errore · Non inviato",
|
|
3640
3667
|
"Error adding flag": "Errore durante l'aggiunta del flag",
|
|
3641
3668
|
"Error connecting to chat, refresh the page to try again.": "Errore di connessione alla chat, aggiorna la pagina per riprovare.",
|
|
3642
3669
|
"Error deleting message": "Errore durante l'eliminazione del messaggio",
|
|
@@ -3761,8 +3788,6 @@ const itTranslations = {
|
|
|
3761
3788
|
"Maximum number of votes (from 2 to 10)": "Numero massimo di voti (da 2 a 10)",
|
|
3762
3789
|
Menu: Menu$6,
|
|
3763
3790
|
"Message deleted": "Messaggio cancellato",
|
|
3764
|
-
"Message Failed · Click to try again": "Invio messaggio fallito · Clicca per riprovare",
|
|
3765
|
-
"Message Failed · Unauthorized": "Invio messaggio fallito · Non autorizzato",
|
|
3766
3791
|
"Message failed to send": "Invio del messaggio non riuscito",
|
|
3767
3792
|
"Message has been successfully flagged": "Il messaggio è stato segnalato con successo",
|
|
3768
3793
|
"Message pinned": "Messaggio bloccato",
|
|
@@ -3939,6 +3964,7 @@ const itTranslations = {
|
|
|
3939
3964
|
"View translation": "Visualizza traduzione",
|
|
3940
3965
|
"Voice message": "Messaggio vocale",
|
|
3941
3966
|
"Voice message {{ duration }}": "Messaggio vocale {{ duration }}",
|
|
3967
|
+
"Voice message deleted": "Messaggio vocale eliminato",
|
|
3942
3968
|
voiceMessageCount_one: voiceMessageCount_one$4,
|
|
3943
3969
|
voiceMessageCount_many: voiceMessageCount_many$2,
|
|
3944
3970
|
voiceMessageCount_other: voiceMessageCount_other$6,
|
|
@@ -4163,7 +4189,6 @@ const jaTranslations = {
|
|
|
4163
4189
|
"End vote": "投票を終了",
|
|
4164
4190
|
"Enforce unique vote is enabled": "一意の投票が有効になっています",
|
|
4165
4191
|
"Error": "エラー",
|
|
4166
|
-
"Error · Unsent": "エラー・未送信",
|
|
4167
4192
|
"Error adding flag": "フラグを追加のエラーが発生しました",
|
|
4168
4193
|
"Error connecting to chat, refresh the page to try again.": "チャットへの接続ができませんでした。ページを更新してください。",
|
|
4169
4194
|
"Error deleting message": "メッセージを削除するエラーが発生しました",
|
|
@@ -4282,8 +4307,6 @@ const jaTranslations = {
|
|
|
4282
4307
|
"Maximum number of votes (from 2 to 10)": "最大投票数(2から10まで)",
|
|
4283
4308
|
Menu: Menu$5,
|
|
4284
4309
|
"Message deleted": "メッセージが削除されました",
|
|
4285
|
-
"Message Failed · Click to try again": "メッセージが失敗しました · クリックして再試行してください",
|
|
4286
|
-
"Message Failed · Unauthorized": "メッセージが失敗しました · 許可されていません",
|
|
4287
4310
|
"Message failed to send": "メッセージの送信に失敗しました",
|
|
4288
4311
|
"Message has been successfully flagged": "メッセージに正常にフラグが付けられました",
|
|
4289
4312
|
"Message pinned": "メッセージにピンが付けられました",
|
|
@@ -4450,6 +4473,7 @@ const jaTranslations = {
|
|
|
4450
4473
|
"View translation": "翻訳を表示",
|
|
4451
4474
|
"Voice message": "ボイスメッセージ",
|
|
4452
4475
|
"Voice message {{ duration }}": "ボイスメッセージ {{ duration }}",
|
|
4476
|
+
"Voice message deleted": "ボイスメッセージが削除されました",
|
|
4453
4477
|
voiceMessageCount_other: voiceMessageCount_other$5,
|
|
4454
4478
|
"Vote ended": "投票が終了しました",
|
|
4455
4479
|
Votes: Votes$5,
|
|
@@ -4672,7 +4696,6 @@ const koTranslations = {
|
|
|
4672
4696
|
"End vote": "투표 종료",
|
|
4673
4697
|
"Enforce unique vote is enabled": "고유 투표가 활성화되었습니다",
|
|
4674
4698
|
"Error": "오류",
|
|
4675
|
-
"Error · Unsent": "오류 · 전송되지 않음",
|
|
4676
4699
|
"Error adding flag": "플래그를 추가하는 동안 오류가 발생했습니다.",
|
|
4677
4700
|
"Error connecting to chat, refresh the page to try again.": "채팅에 연결하는 동안 오류가 발생했습니다. 페이지를 새로고침하여 다시 시도하세요.",
|
|
4678
4701
|
"Error deleting message": "메시지를 삭제하는 중에 오류가 발생했습니다.",
|
|
@@ -4791,8 +4814,6 @@ const koTranslations = {
|
|
|
4791
4814
|
"Maximum number of votes (from 2 to 10)": "최대 투표 수 (2에서 10까지)",
|
|
4792
4815
|
Menu: Menu$4,
|
|
4793
4816
|
"Message deleted": "메시지가 삭제되었습니다.",
|
|
4794
|
-
"Message Failed · Click to try again": "메시지 실패 · 다시 시도하려면 클릭하세요.",
|
|
4795
|
-
"Message Failed · Unauthorized": "메시지 실패 · 승인되지 않음",
|
|
4796
4817
|
"Message failed to send": "메시지 전송 실패",
|
|
4797
4818
|
"Message has been successfully flagged": "메시지에 플래그가 지정되었습니다.",
|
|
4798
4819
|
"Message pinned": "메시지 핀했습니다",
|
|
@@ -4959,6 +4980,7 @@ const koTranslations = {
|
|
|
4959
4980
|
"View translation": "번역 보기",
|
|
4960
4981
|
"Voice message": "음성 메시지",
|
|
4961
4982
|
"Voice message {{ duration }}": "음성 메시지 {{ duration }}",
|
|
4983
|
+
"Voice message deleted": "음성 메시지가 삭제됨",
|
|
4962
4984
|
voiceMessageCount_other: voiceMessageCount_other$4,
|
|
4963
4985
|
"Vote ended": "투표 종료",
|
|
4964
4986
|
Votes: Votes$4,
|
|
@@ -5188,7 +5210,6 @@ const nlTranslations = {
|
|
|
5188
5210
|
"End vote": "Einde stem",
|
|
5189
5211
|
"Enforce unique vote is enabled": "Unieke stem is ingeschakeld",
|
|
5190
5212
|
"Error": "Fout",
|
|
5191
|
-
"Error · Unsent": "Fout · niet verzonden",
|
|
5192
5213
|
"Error adding flag": "Fout bij toevoegen van vlag",
|
|
5193
5214
|
"Error connecting to chat, refresh the page to try again.": "Fout bij het verbinden, ververs de pagina om nogmaals te proberen",
|
|
5194
5215
|
"Error deleting message": "Fout bij verwijderen van bericht",
|
|
@@ -5310,8 +5331,6 @@ const nlTranslations = {
|
|
|
5310
5331
|
"Maximum number of votes (from 2 to 10)": "Maximaal aantal stemmen (van 2 tot 10)",
|
|
5311
5332
|
Menu: Menu$3,
|
|
5312
5333
|
"Message deleted": "Bericht verwijderd",
|
|
5313
|
-
"Message Failed · Click to try again": "Bericht mislukt, klik om het nogmaals te proberen",
|
|
5314
|
-
"Message Failed · Unauthorized": "Bericht mislukt, ongeautoriseerd",
|
|
5315
5334
|
"Message failed to send": "Bericht kon niet worden verzonden",
|
|
5316
5335
|
"Message has been successfully flagged": "Bericht is succesvol gemarkeerd",
|
|
5317
5336
|
"Message pinned": "Bericht vastgezet",
|
|
@@ -5483,6 +5502,7 @@ const nlTranslations = {
|
|
|
5483
5502
|
"View translation": "Vertaling bekijken",
|
|
5484
5503
|
"Voice message": "Spraakbericht",
|
|
5485
5504
|
"Voice message {{ duration }}": "Spraakbericht {{ duration }}",
|
|
5505
|
+
"Voice message deleted": "Spraakbericht verwijderd",
|
|
5486
5506
|
voiceMessageCount_one: voiceMessageCount_one$3,
|
|
5487
5507
|
voiceMessageCount_other: voiceMessageCount_other$3,
|
|
5488
5508
|
"Vote ended": "Stemmen beëindigd",
|
|
@@ -5729,7 +5749,6 @@ const ptTranslations = {
|
|
|
5729
5749
|
"End vote": "Encerrar votação",
|
|
5730
5750
|
"Enforce unique vote is enabled": "Voto único está habilitado",
|
|
5731
5751
|
"Error": "Erro",
|
|
5732
|
-
"Error · Unsent": "Erro · Não enviado",
|
|
5733
5752
|
"Error adding flag": "Erro ao reportar",
|
|
5734
5753
|
"Error connecting to chat, refresh the page to try again.": "Erro ao conectar ao bate-papo, atualize a página para tentar novamente.",
|
|
5735
5754
|
"Error deleting message": "Erro ao deletar mensagem",
|
|
@@ -5854,8 +5873,6 @@ const ptTranslations = {
|
|
|
5854
5873
|
"Maximum number of votes (from 2 to 10)": "Número máximo de votos (de 2 a 10)",
|
|
5855
5874
|
Menu: Menu$2,
|
|
5856
5875
|
"Message deleted": "Mensagem apagada",
|
|
5857
|
-
"Message Failed · Click to try again": "A mensagem falhou · Clique para tentar novamente",
|
|
5858
|
-
"Message Failed · Unauthorized": "A mensagem falhou · não autorizado",
|
|
5859
5876
|
"Message failed to send": "Falha ao enviar a mensagem",
|
|
5860
5877
|
"Message has been successfully flagged": "A mensagem foi reportada com sucesso",
|
|
5861
5878
|
"Message pinned": "Mensagem fixada",
|
|
@@ -6032,6 +6049,7 @@ const ptTranslations = {
|
|
|
6032
6049
|
"View translation": "Ver tradução",
|
|
6033
6050
|
"Voice message": "Mensagem de voz",
|
|
6034
6051
|
"Voice message {{ duration }}": "Mensagem de voz {{ duration }}",
|
|
6052
|
+
"Voice message deleted": "Mensagem de voz excluída",
|
|
6035
6053
|
voiceMessageCount_one: voiceMessageCount_one$2,
|
|
6036
6054
|
voiceMessageCount_many: voiceMessageCount_many$1,
|
|
6037
6055
|
voiceMessageCount_other: voiceMessageCount_other$2,
|
|
@@ -6299,7 +6317,6 @@ const ruTranslations = {
|
|
|
6299
6317
|
"End vote": "Закончить голосование",
|
|
6300
6318
|
"Enforce unique vote is enabled": "Уникальное голосование включено",
|
|
6301
6319
|
"Error": "Ошибка",
|
|
6302
|
-
"Error · Unsent": "Ошибка · Не отправлено",
|
|
6303
6320
|
"Error adding flag": "Ошибка добавления флага",
|
|
6304
6321
|
"Error connecting to chat, refresh the page to try again.": "Ошибка подключения к чату, обновите страницу чтобы попробовать снова.",
|
|
6305
6322
|
"Error deleting message": "Ошибка при удалении сообщения",
|
|
@@ -6430,8 +6447,6 @@ const ruTranslations = {
|
|
|
6430
6447
|
"Maximum number of votes (from 2 to 10)": "Максимальное количество голосов (от 2 до 10)",
|
|
6431
6448
|
Menu: Menu$1,
|
|
6432
6449
|
"Message deleted": "Сообщение удалено",
|
|
6433
|
-
"Message Failed · Click to try again": "Ошибка отправки сообщения · Нажмите чтобы повторить",
|
|
6434
|
-
"Message Failed · Unauthorized": "Ошибка отправки сообщения · Неавторизованный",
|
|
6435
6450
|
"Message failed to send": "Не удалось отправить сообщение",
|
|
6436
6451
|
"Message has been successfully flagged": "Жалоба на сообщение была принята",
|
|
6437
6452
|
"Message pinned": "Сообщение закреплено",
|
|
@@ -6615,6 +6630,7 @@ const ruTranslations = {
|
|
|
6615
6630
|
"View translation": "Показать перевод",
|
|
6616
6631
|
"Voice message": "Голосовое сообщение",
|
|
6617
6632
|
"Voice message {{ duration }}": "Голосовое сообщение {{ duration }}",
|
|
6633
|
+
"Voice message deleted": "Голосовое сообщение удалено",
|
|
6618
6634
|
voiceMessageCount_one: voiceMessageCount_one$1,
|
|
6619
6635
|
voiceMessageCount_few,
|
|
6620
6636
|
voiceMessageCount_many,
|
|
@@ -6847,7 +6863,6 @@ const trTranslations = {
|
|
|
6847
6863
|
"End vote": "Oyu bitir",
|
|
6848
6864
|
"Enforce unique vote is enabled": "Benzersiz oy etkinleştirildi",
|
|
6849
6865
|
"Error": "Hata",
|
|
6850
|
-
"Error · Unsent": "Hata · Gönderilemedi",
|
|
6851
6866
|
"Error adding flag": "Bayrak eklenirken hata oluştu",
|
|
6852
6867
|
"Error connecting to chat, refresh the page to try again.": "Bağlantı hatası, sayfayı yenileyip tekrar deneyin.",
|
|
6853
6868
|
"Error deleting message": "Mesaj silinirken hata oluştu",
|
|
@@ -6969,8 +6984,6 @@ const trTranslations = {
|
|
|
6969
6984
|
"Maximum number of votes (from 2 to 10)": "Maksimum oy sayısı (2 ile 10 arası)",
|
|
6970
6985
|
Menu,
|
|
6971
6986
|
"Message deleted": "Mesaj silindi",
|
|
6972
|
-
"Message Failed · Click to try again": "Mesaj Başarısız · Tekrar denemek için tıklayın",
|
|
6973
|
-
"Message Failed · Unauthorized": "Mesaj Başarısız · Yetkisiz",
|
|
6974
6987
|
"Message failed to send": "Mesaj gönderilemedi",
|
|
6975
6988
|
"Message has been successfully flagged": "Mesaj başarıyla bayraklandı",
|
|
6976
6989
|
"Message pinned": "Mesaj sabitlendi",
|
|
@@ -7140,6 +7153,7 @@ const trTranslations = {
|
|
|
7140
7153
|
"View translation": "Çeviriyi görüntüle",
|
|
7141
7154
|
"Voice message": "Sesli mesaj",
|
|
7142
7155
|
"Voice message {{ duration }}": "Sesli mesaj {{ duration }}",
|
|
7156
|
+
"Voice message deleted": "Sesli mesaj silindi",
|
|
7143
7157
|
voiceMessageCount_one,
|
|
7144
7158
|
voiceMessageCount_other,
|
|
7145
7159
|
"Vote ended": "Oylama sona erdi",
|
|
@@ -8569,11 +8583,18 @@ function useActionHandler(message) {
|
|
|
8569
8583
|
}
|
|
8570
8584
|
const useDeleteHandler = (message, notifications = {}) => {
|
|
8571
8585
|
const { getErrorNotification, notify } = notifications;
|
|
8572
|
-
const { deleteMessage, updateMessage } = useChannelActionContext("useDeleteHandler");
|
|
8586
|
+
const { deleteMessage, removeMessage, updateMessage } = useChannelActionContext("useDeleteHandler");
|
|
8573
8587
|
const { client } = useChatContext("useDeleteHandler");
|
|
8574
8588
|
const { t } = useTranslationContext("useDeleteHandler");
|
|
8575
8589
|
return async (options) => {
|
|
8576
|
-
if (!message
|
|
8590
|
+
if (!message) {
|
|
8591
|
+
return;
|
|
8592
|
+
}
|
|
8593
|
+
if (message.type === "error" || isNetworkSendFailure(message)) {
|
|
8594
|
+
removeMessage?.(message);
|
|
8595
|
+
return;
|
|
8596
|
+
}
|
|
8597
|
+
if (!message.id || !client || !updateMessage) {
|
|
8577
8598
|
return;
|
|
8578
8599
|
}
|
|
8579
8600
|
try {
|
|
@@ -8582,6 +8603,7 @@ const useDeleteHandler = (message, notifications = {}) => {
|
|
|
8582
8603
|
} catch (e) {
|
|
8583
8604
|
const errorMessage = getErrorNotification && validateAndGetMessage(getErrorNotification, [message]);
|
|
8584
8605
|
if (notify) notify(errorMessage || t("Error deleting message"), "error");
|
|
8606
|
+
throw e;
|
|
8585
8607
|
}
|
|
8586
8608
|
};
|
|
8587
8609
|
};
|
|
@@ -8893,7 +8915,7 @@ const useUserRole = (message, onlySenderCanEdit, disableQuotedMessages) => {
|
|
|
8893
8915
|
const canFlag = !isMyMessage && channelCapabilities["flag-message"];
|
|
8894
8916
|
const canMute = !isMyMessage && channelCapabilities["mute-channel"];
|
|
8895
8917
|
const canBlockUser = !isMyMessage;
|
|
8896
|
-
const canMarkUnread = channelCapabilities["read-events"];
|
|
8918
|
+
const canMarkUnread = !isMyMessage && channelCapabilities["read-events"];
|
|
8897
8919
|
const canQuote = !disableQuotedMessages && channelCapabilities["quote-message"];
|
|
8898
8920
|
const canReact = channelCapabilities["send-reaction"];
|
|
8899
8921
|
const canReply = channelCapabilities["send-reply"];
|
|
@@ -8990,73 +9012,6 @@ const useMessageReminder = (messageId) => {
|
|
|
8990
9012
|
const { reminder } = useStateStore(client.reminders.state, reminderSelector);
|
|
8991
9013
|
return reminder;
|
|
8992
9014
|
};
|
|
8993
|
-
const ActionsIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
8994
|
-
"svg",
|
|
8995
|
-
{
|
|
8996
|
-
className,
|
|
8997
|
-
height: "4",
|
|
8998
|
-
viewBox: "0 0 11 4",
|
|
8999
|
-
width: "11",
|
|
9000
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9001
|
-
children: /* @__PURE__ */ jsx(
|
|
9002
|
-
"path",
|
|
9003
|
-
{
|
|
9004
|
-
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",
|
|
9005
|
-
fillRule: "nonzero"
|
|
9006
|
-
}
|
|
9007
|
-
)
|
|
9008
|
-
}
|
|
9009
|
-
);
|
|
9010
|
-
const ReactionIcon = ({ className = "" }) => /* @__PURE__ */ jsx(
|
|
9011
|
-
"svg",
|
|
9012
|
-
{
|
|
9013
|
-
className,
|
|
9014
|
-
height: "12",
|
|
9015
|
-
viewBox: "0 0 12 12",
|
|
9016
|
-
width: "12",
|
|
9017
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9018
|
-
children: /* @__PURE__ */ jsxs("g", { clipRule: "evenodd", fillRule: "evenodd", children: [
|
|
9019
|
-
/* @__PURE__ */ 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" }),
|
|
9020
|
-
/* @__PURE__ */ 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" })
|
|
9021
|
-
] })
|
|
9022
|
-
}
|
|
9023
|
-
);
|
|
9024
|
-
const ThreadIcon = ({ className = "" }) => /* @__PURE__ */ jsx("svg", { className, height: "10", width: "14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx(
|
|
9025
|
-
"path",
|
|
9026
|
-
{
|
|
9027
|
-
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",
|
|
9028
|
-
fillRule: "evenodd"
|
|
9029
|
-
}
|
|
9030
|
-
) });
|
|
9031
|
-
const PinIcon = () => /* @__PURE__ */ jsx("svg", { height: "13", viewBox: "0 0 14 13", width: "14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx(
|
|
9032
|
-
"path",
|
|
9033
|
-
{
|
|
9034
|
-
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",
|
|
9035
|
-
fillRule: "evenodd"
|
|
9036
|
-
}
|
|
9037
|
-
) });
|
|
9038
|
-
const MessageErrorIcon = () => /* @__PURE__ */ jsx("div", { className: "str-chat__message-error-icon", children: /* @__PURE__ */ jsxs(
|
|
9039
|
-
"svg",
|
|
9040
|
-
{
|
|
9041
|
-
"data-testid": "error",
|
|
9042
|
-
fill: "none",
|
|
9043
|
-
height: "24",
|
|
9044
|
-
viewBox: "0 0 24 24",
|
|
9045
|
-
width: "24",
|
|
9046
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
9047
|
-
children: [
|
|
9048
|
-
/* @__PURE__ */ jsx(
|
|
9049
|
-
"path",
|
|
9050
|
-
{
|
|
9051
|
-
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",
|
|
9052
|
-
fill: "black",
|
|
9053
|
-
id: "background"
|
|
9054
|
-
}
|
|
9055
|
-
),
|
|
9056
|
-
/* @__PURE__ */ jsx("path", { d: "M13 17H11V15H13V17ZM13 13H11V7H13V13Z", fill: "white" })
|
|
9057
|
-
]
|
|
9058
|
-
}
|
|
9059
|
-
) });
|
|
9060
9015
|
const Root = forwardRef(function AlertRoot({ children, className, ...props }, ref) {
|
|
9061
9016
|
return /* @__PURE__ */ jsx("div", { ...props, className: clsx("str-chat__alert-root", className), ref, children });
|
|
9062
9017
|
});
|
|
@@ -9137,6 +9092,7 @@ function useDialogAnchor({
|
|
|
9137
9092
|
setPopperElement(null);
|
|
9138
9093
|
}
|
|
9139
9094
|
return {
|
|
9095
|
+
placement: stabilisedChosenPlacement ?? chosenPlacement,
|
|
9140
9096
|
setPopperElement,
|
|
9141
9097
|
styles: {
|
|
9142
9098
|
left: x ?? 0,
|
|
@@ -9149,6 +9105,8 @@ const DialogAnchor = ({
|
|
|
9149
9105
|
allowFlip = true,
|
|
9150
9106
|
children,
|
|
9151
9107
|
className,
|
|
9108
|
+
closeOnClickOutside,
|
|
9109
|
+
closeTransitionMs = 0,
|
|
9152
9110
|
dialogManagerId,
|
|
9153
9111
|
focus = true,
|
|
9154
9112
|
id,
|
|
@@ -9161,12 +9119,44 @@ const DialogAnchor = ({
|
|
|
9161
9119
|
updatePositionOnContentResize,
|
|
9162
9120
|
...restDivProps
|
|
9163
9121
|
}) => {
|
|
9164
|
-
const dialog = useDialog({ dialogManagerId, id });
|
|
9122
|
+
const dialog = useDialog({ closeOnClickOutside, dialogManagerId, id });
|
|
9165
9123
|
const open = useDialogIsOpen(id, dialogManagerId);
|
|
9166
|
-
const
|
|
9124
|
+
const [shouldRender, setShouldRender] = useState(open);
|
|
9125
|
+
const closeTimeoutRef = useRef(null);
|
|
9126
|
+
const isClosing = !open && shouldRender;
|
|
9127
|
+
useEffect(() => {
|
|
9128
|
+
if (open) {
|
|
9129
|
+
setShouldRender(true);
|
|
9130
|
+
if (closeTimeoutRef.current) {
|
|
9131
|
+
clearTimeout(closeTimeoutRef.current);
|
|
9132
|
+
closeTimeoutRef.current = null;
|
|
9133
|
+
}
|
|
9134
|
+
return;
|
|
9135
|
+
}
|
|
9136
|
+
if (!shouldRender) return;
|
|
9137
|
+
if (!closeTransitionMs) {
|
|
9138
|
+
setShouldRender(false);
|
|
9139
|
+
return;
|
|
9140
|
+
}
|
|
9141
|
+
closeTimeoutRef.current = setTimeout(() => {
|
|
9142
|
+
setShouldRender(false);
|
|
9143
|
+
closeTimeoutRef.current = null;
|
|
9144
|
+
}, closeTransitionMs);
|
|
9145
|
+
}, [closeTransitionMs, open, shouldRender]);
|
|
9146
|
+
useEffect(
|
|
9147
|
+
() => () => {
|
|
9148
|
+
if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current);
|
|
9149
|
+
},
|
|
9150
|
+
[]
|
|
9151
|
+
);
|
|
9152
|
+
const {
|
|
9153
|
+
placement: chosenPlacement,
|
|
9154
|
+
setPopperElement,
|
|
9155
|
+
styles
|
|
9156
|
+
} = useDialogAnchor({
|
|
9167
9157
|
allowFlip,
|
|
9168
9158
|
offset,
|
|
9169
|
-
open,
|
|
9159
|
+
open: shouldRender,
|
|
9170
9160
|
placement,
|
|
9171
9161
|
referenceElement,
|
|
9172
9162
|
updateKey,
|
|
@@ -9183,7 +9173,7 @@ const DialogAnchor = ({
|
|
|
9183
9173
|
document.removeEventListener("keyup", hideOnEscape);
|
|
9184
9174
|
};
|
|
9185
9175
|
}, [dialog, open]);
|
|
9186
|
-
if (!
|
|
9176
|
+
if (!shouldRender) {
|
|
9187
9177
|
return null;
|
|
9188
9178
|
}
|
|
9189
9179
|
return /* @__PURE__ */ jsx(DialogPortalEntry, { dialogId: id, dialogManagerId, children: /* @__PURE__ */ jsx(FocusScope, { autoFocus: focus, contain: trapFocus, restoreFocus: true, children: /* @__PURE__ */ jsx(
|
|
@@ -9191,6 +9181,8 @@ const DialogAnchor = ({
|
|
|
9191
9181
|
{
|
|
9192
9182
|
...restDivProps,
|
|
9193
9183
|
className: clsx("str-chat__dialog-contents", className),
|
|
9184
|
+
"data-str-chat-dialog-state": isClosing ? "closing" : "open",
|
|
9185
|
+
"data-str-chat-placement": chosenPlacement,
|
|
9194
9186
|
"data-testid": "str-chat__dialog-contents",
|
|
9195
9187
|
ref: setPopperElement,
|
|
9196
9188
|
style: styles,
|
|
@@ -9317,6 +9309,11 @@ const Badge = ({
|
|
|
9317
9309
|
children
|
|
9318
9310
|
}
|
|
9319
9311
|
);
|
|
9312
|
+
const ErrorBadge = ({
|
|
9313
|
+
className,
|
|
9314
|
+
size = "sm",
|
|
9315
|
+
...rest
|
|
9316
|
+
}) => /* @__PURE__ */ jsx(Badge, { ...rest, className, size, variant: "error", children: /* @__PURE__ */ jsx(IconExclamation, {}) });
|
|
9320
9317
|
function AvatarStack({
|
|
9321
9318
|
badgeSize,
|
|
9322
9319
|
component: Component2 = "div",
|
|
@@ -9528,16 +9525,152 @@ const EmojiContextMenuButton = ({
|
|
|
9528
9525
|
]
|
|
9529
9526
|
}
|
|
9530
9527
|
);
|
|
9531
|
-
const
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9528
|
+
const ContextMenuButtonWithSubmenu = ({
|
|
9529
|
+
children,
|
|
9530
|
+
className,
|
|
9531
|
+
Submenu,
|
|
9532
|
+
submenuContainerProps,
|
|
9533
|
+
submenuPlacement = "right-start",
|
|
9534
|
+
submenuRollAxis = "x",
|
|
9535
|
+
...buttonProps
|
|
9535
9536
|
}) => {
|
|
9537
|
+
const { className: submenuClassName, ...submenuContainerRestProps } = submenuContainerProps ?? {};
|
|
9538
|
+
const buttonRef = useRef(null);
|
|
9539
|
+
const [dialogContainer, setDialogContainer] = useState(null);
|
|
9540
|
+
const keepSubmenuOpenFlag = useRef(false);
|
|
9541
|
+
const dialogCloseTimeout = useRef(null);
|
|
9542
|
+
const dialogId2 = useMemo(() => `submenu-${Math.random().toString(36).slice(2)}`, []);
|
|
9543
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
9544
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
9545
|
+
const {
|
|
9546
|
+
placement: chosenPlacement,
|
|
9547
|
+
setPopperElement,
|
|
9548
|
+
styles
|
|
9549
|
+
} = useDialogAnchor({
|
|
9550
|
+
open: dialogIsOpen,
|
|
9551
|
+
placement: submenuPlacement,
|
|
9552
|
+
referenceElement: buttonRef.current
|
|
9553
|
+
});
|
|
9554
|
+
const closeDialogLazily = useCallback(() => {
|
|
9555
|
+
if (dialogCloseTimeout.current) clearTimeout(dialogCloseTimeout.current);
|
|
9556
|
+
dialogCloseTimeout.current = setTimeout(() => {
|
|
9557
|
+
if (keepSubmenuOpenFlag.current) return;
|
|
9558
|
+
dialog.close();
|
|
9559
|
+
}, 100);
|
|
9560
|
+
}, [dialog]);
|
|
9561
|
+
const keepSubmenuOpen = useCallback(() => {
|
|
9562
|
+
keepSubmenuOpenFlag.current = true;
|
|
9563
|
+
}, []);
|
|
9564
|
+
const allowToCloseSubmenu = useCallback(() => {
|
|
9565
|
+
keepSubmenuOpenFlag.current = false;
|
|
9566
|
+
}, []);
|
|
9567
|
+
const closeSubmenu = useCallback(() => {
|
|
9568
|
+
allowToCloseSubmenu();
|
|
9569
|
+
closeDialogLazily();
|
|
9570
|
+
}, [allowToCloseSubmenu, closeDialogLazily]);
|
|
9571
|
+
const handleClose = useCallback(
|
|
9572
|
+
(event) => {
|
|
9573
|
+
const parentButton = buttonRef.current;
|
|
9574
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
9575
|
+
event.stopPropagation();
|
|
9576
|
+
closeDialogLazily();
|
|
9577
|
+
parentButton.focus();
|
|
9578
|
+
},
|
|
9579
|
+
[closeDialogLazily, dialogIsOpen, buttonRef]
|
|
9580
|
+
);
|
|
9581
|
+
const handleFocusParentButton = () => {
|
|
9582
|
+
if (dialogIsOpen) return;
|
|
9583
|
+
dialog.open();
|
|
9584
|
+
keepSubmenuOpen();
|
|
9585
|
+
};
|
|
9586
|
+
useEffect(() => {
|
|
9587
|
+
const parentButton = buttonRef.current;
|
|
9588
|
+
if (!dialogIsOpen || !parentButton) return;
|
|
9589
|
+
const hideOnEscape = (event) => {
|
|
9590
|
+
if (event.key !== "Escape") return;
|
|
9591
|
+
handleClose(event);
|
|
9592
|
+
closeSubmenu();
|
|
9593
|
+
};
|
|
9594
|
+
document.addEventListener("keyup", hideOnEscape, { capture: true });
|
|
9595
|
+
return () => {
|
|
9596
|
+
document.removeEventListener("keyup", hideOnEscape, { capture: true });
|
|
9597
|
+
};
|
|
9598
|
+
}, [dialogIsOpen, handleClose, closeSubmenu]);
|
|
9599
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9600
|
+
/* @__PURE__ */ jsx(
|
|
9601
|
+
BaseContextMenuButton,
|
|
9602
|
+
{
|
|
9603
|
+
"aria-selected": "false",
|
|
9604
|
+
className: clsx(className, "str_chat__button-with-submenu", {
|
|
9605
|
+
"str_chat__button-with-submenu--submenu-open": dialogIsOpen
|
|
9606
|
+
}),
|
|
9607
|
+
hasSubMenu: true,
|
|
9608
|
+
onBlur: closeSubmenu,
|
|
9609
|
+
onClick: (event) => {
|
|
9610
|
+
event.stopPropagation();
|
|
9611
|
+
dialog.toggle();
|
|
9612
|
+
},
|
|
9613
|
+
onFocus: handleFocusParentButton,
|
|
9614
|
+
onMouseEnter: handleFocusParentButton,
|
|
9615
|
+
onMouseLeave: closeSubmenu,
|
|
9616
|
+
role: "option",
|
|
9617
|
+
...buttonProps,
|
|
9618
|
+
ref: buttonRef,
|
|
9619
|
+
children
|
|
9620
|
+
}
|
|
9621
|
+
),
|
|
9622
|
+
dialogIsOpen && /* @__PURE__ */ jsx(
|
|
9623
|
+
"div",
|
|
9624
|
+
{
|
|
9625
|
+
className: clsx("str-chat__context-menu__submenu-container", submenuClassName),
|
|
9626
|
+
"data-str-chat-placement": chosenPlacement,
|
|
9627
|
+
"data-str-chat-roll-axis": submenuRollAxis,
|
|
9628
|
+
onBlur: (event) => {
|
|
9629
|
+
const isBlurredDescendant = event.relatedTarget instanceof Node && dialogContainer?.contains(event.relatedTarget);
|
|
9630
|
+
if (isBlurredDescendant) return;
|
|
9631
|
+
closeSubmenu();
|
|
9632
|
+
},
|
|
9633
|
+
onFocus: keepSubmenuOpen,
|
|
9634
|
+
onMouseEnter: keepSubmenuOpen,
|
|
9635
|
+
onMouseLeave: closeSubmenu,
|
|
9636
|
+
ref: (element) => {
|
|
9637
|
+
setPopperElement(element);
|
|
9638
|
+
setDialogContainer(element);
|
|
9639
|
+
},
|
|
9640
|
+
style: styles,
|
|
9641
|
+
tabIndex: -1,
|
|
9642
|
+
...submenuContainerRestProps,
|
|
9643
|
+
children: /* @__PURE__ */ jsx(Submenu, {})
|
|
9644
|
+
}
|
|
9645
|
+
)
|
|
9646
|
+
] });
|
|
9647
|
+
};
|
|
9648
|
+
const ContextMenuButton = (props) => {
|
|
9649
|
+
const {
|
|
9650
|
+
Submenu,
|
|
9651
|
+
submenuContainerProps,
|
|
9652
|
+
submenuPlacement,
|
|
9653
|
+
submenuRollAxis,
|
|
9654
|
+
...buttonProps
|
|
9655
|
+
} = props;
|
|
9536
9656
|
const [isFocused, setIsFocused] = useState(false);
|
|
9657
|
+
if (Submenu) {
|
|
9658
|
+
return /* @__PURE__ */ jsx(
|
|
9659
|
+
ContextMenuButtonWithSubmenu,
|
|
9660
|
+
{
|
|
9661
|
+
...buttonProps,
|
|
9662
|
+
Submenu,
|
|
9663
|
+
submenuContainerProps,
|
|
9664
|
+
submenuPlacement,
|
|
9665
|
+
submenuRollAxis
|
|
9666
|
+
}
|
|
9667
|
+
);
|
|
9668
|
+
}
|
|
9669
|
+
const { onBlur, onFocus, ...baseButtonProps } = buttonProps;
|
|
9537
9670
|
return /* @__PURE__ */ jsx(
|
|
9538
9671
|
BaseContextMenuButton,
|
|
9539
9672
|
{
|
|
9540
|
-
...
|
|
9673
|
+
...baseButtonProps,
|
|
9541
9674
|
"aria-selected": isFocused ? "true" : "false",
|
|
9542
9675
|
onBlur: (e) => {
|
|
9543
9676
|
setIsFocused(false);
|
|
@@ -9586,12 +9719,14 @@ function ContextMenuContent({
|
|
|
9586
9719
|
backLabel = "Back",
|
|
9587
9720
|
children,
|
|
9588
9721
|
className,
|
|
9722
|
+
enableAnimations = true,
|
|
9589
9723
|
Header: Header2,
|
|
9590
9724
|
items,
|
|
9591
9725
|
ItemsWrapper,
|
|
9592
9726
|
menuClassName,
|
|
9593
9727
|
onClose,
|
|
9594
9728
|
onMenuLevelChange,
|
|
9729
|
+
transitionDirection,
|
|
9595
9730
|
...props
|
|
9596
9731
|
}) {
|
|
9597
9732
|
const rootLevel = useMemo(
|
|
@@ -9604,6 +9739,7 @@ function ContextMenuContent({
|
|
|
9604
9739
|
[Header2, items, ItemsWrapper, menuClassName]
|
|
9605
9740
|
);
|
|
9606
9741
|
const [menuStack, setMenuStack] = useState(() => [rootLevel]);
|
|
9742
|
+
const [menuBodyAnimationKey, setMenuBodyAnimationKey] = useState(0);
|
|
9607
9743
|
const activeMenu = menuStack[menuStack.length - 1];
|
|
9608
9744
|
const ActiveMenuItemsWrapper = activeMenu.ItemsWrapper ?? React.Fragment;
|
|
9609
9745
|
const closeMenu = useCallback(() => {
|
|
@@ -9627,10 +9763,9 @@ function ContextMenuContent({
|
|
|
9627
9763
|
[ItemsWrapper]
|
|
9628
9764
|
);
|
|
9629
9765
|
const returnToParentMenu = useCallback(() => {
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
}, []);
|
|
9766
|
+
if (menuStack.length <= 1) return;
|
|
9767
|
+
setMenuStack((current) => current.slice(0, current.length - 1));
|
|
9768
|
+
}, [menuStack.length]);
|
|
9634
9769
|
useEffect(() => {
|
|
9635
9770
|
setMenuStack((current) => {
|
|
9636
9771
|
if (current.length === 1 && current[0] === rootLevel) return current;
|
|
@@ -9640,42 +9775,116 @@ function ContextMenuContent({
|
|
|
9640
9775
|
useEffect(() => {
|
|
9641
9776
|
onMenuLevelChange?.(menuStack.length);
|
|
9642
9777
|
}, [menuStack.length, onMenuLevelChange]);
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9778
|
+
useEffect(() => {
|
|
9779
|
+
if (!transitionDirection) return;
|
|
9780
|
+
setMenuBodyAnimationKey((value) => value + 1);
|
|
9781
|
+
}, [transitionDirection, menuStack.length]);
|
|
9782
|
+
return /* @__PURE__ */ jsx(ContextMenuContext.Provider, { value: { closeMenu, openSubmenu, returnToParentMenu }, children: /* @__PURE__ */ jsxs(
|
|
9783
|
+
ContextMenuRoot,
|
|
9784
|
+
{
|
|
9785
|
+
className: clsx(className, activeMenu.menuClassName),
|
|
9786
|
+
"data-str-chat-enable-animations": enableAnimations,
|
|
9787
|
+
...props,
|
|
9788
|
+
children: [
|
|
9789
|
+
activeMenu.Header ? /* @__PURE__ */ jsx(activeMenu.Header, {}) : menuStack.length > 1 ? /* @__PURE__ */ jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxs(ContextMenuBackButton, { onClick: returnToParentMenu, children: [
|
|
9790
|
+
/* @__PURE__ */ jsx(IconChevronLeft, {}),
|
|
9791
|
+
/* @__PURE__ */ jsx("span", { children: backLabel })
|
|
9792
|
+
] }) }) : null,
|
|
9793
|
+
/* @__PURE__ */ jsx(
|
|
9794
|
+
ContextMenuBody,
|
|
9795
|
+
{
|
|
9796
|
+
className: clsx({
|
|
9797
|
+
"str-chat__context-menu__body--submenu-backward": transitionDirection === "backward",
|
|
9798
|
+
"str-chat__context-menu__body--submenu-forward": transitionDirection === "forward"
|
|
9799
|
+
}),
|
|
9800
|
+
children: activeMenu.Submenu ? /* @__PURE__ */ jsx(activeMenu.Submenu, {}) : /* @__PURE__ */ jsx(ActiveMenuItemsWrapper, { children: typeof children !== "undefined" ? children : activeMenu.items?.map((Item2, index) => /* @__PURE__ */ jsx(Item2, {}, `context-menu-item-${index}`)) })
|
|
9801
|
+
},
|
|
9802
|
+
`context-menu-body-${menuStack.length}-${menuBodyAnimationKey}`
|
|
9803
|
+
)
|
|
9804
|
+
]
|
|
9805
|
+
}
|
|
9806
|
+
) });
|
|
9650
9807
|
}
|
|
9651
9808
|
const ContextMenu = (props) => {
|
|
9809
|
+
const { ContextMenuContent: ContextMenuContentComponent = ContextMenuContent } = useComponentContext();
|
|
9652
9810
|
const {
|
|
9653
9811
|
allowFlip,
|
|
9812
|
+
closeOnClickOutside,
|
|
9813
|
+
closeTransitionMs = 130,
|
|
9654
9814
|
dialogManagerId,
|
|
9655
9815
|
focus,
|
|
9656
9816
|
id,
|
|
9657
9817
|
placement,
|
|
9658
9818
|
referenceElement,
|
|
9819
|
+
submenuTransitionDurationMs,
|
|
9659
9820
|
tabIndex,
|
|
9660
9821
|
trapFocus,
|
|
9661
9822
|
...menuProps
|
|
9662
9823
|
} = props;
|
|
9824
|
+
const resolvedSubmenuTransitionDurationMs = submenuTransitionDurationMs ?? 460;
|
|
9663
9825
|
const isAnchored = id != null;
|
|
9664
9826
|
const [menuLevel, setMenuLevel] = useState(1);
|
|
9827
|
+
const [transitionDirection, setTransitionDirection] = useState(void 0);
|
|
9828
|
+
const [contentResetToken, setContentResetToken] = useState(0);
|
|
9829
|
+
const transitionTimeoutRef = useRef(null);
|
|
9830
|
+
const previousMenuLevelRef = useRef(1);
|
|
9665
9831
|
const open = useDialogIsOpen(id ?? "", dialogManagerId);
|
|
9832
|
+
const previousOpenRef = useRef(open);
|
|
9666
9833
|
useEffect(() => {
|
|
9667
|
-
if (isAnchored
|
|
9834
|
+
if (!isAnchored) return;
|
|
9835
|
+
if (previousOpenRef.current && !open) {
|
|
9836
|
+
setMenuLevel(1);
|
|
9837
|
+
setTransitionDirection(void 0);
|
|
9838
|
+
setContentResetToken((value) => value + 1);
|
|
9839
|
+
previousMenuLevelRef.current = 1;
|
|
9840
|
+
if (transitionTimeoutRef.current) {
|
|
9841
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
9842
|
+
transitionTimeoutRef.current = null;
|
|
9843
|
+
}
|
|
9844
|
+
}
|
|
9845
|
+
previousOpenRef.current = open;
|
|
9668
9846
|
}, [isAnchored, open]);
|
|
9669
|
-
|
|
9670
|
-
|
|
9847
|
+
useEffect(
|
|
9848
|
+
() => () => {
|
|
9849
|
+
if (transitionTimeoutRef.current) {
|
|
9850
|
+
clearTimeout(transitionTimeoutRef.current);
|
|
9851
|
+
}
|
|
9852
|
+
},
|
|
9853
|
+
[]
|
|
9854
|
+
);
|
|
9855
|
+
const handleMenuLevelChange = useCallback(
|
|
9856
|
+
(level) => {
|
|
9857
|
+
if (isAnchored) {
|
|
9858
|
+
const previousLevel = previousMenuLevelRef.current;
|
|
9859
|
+
if (level !== previousLevel) {
|
|
9860
|
+
setTransitionDirection(level > previousLevel ? "forward" : "backward");
|
|
9861
|
+
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
9862
|
+
transitionTimeoutRef.current = setTimeout(() => {
|
|
9863
|
+
setTransitionDirection(void 0);
|
|
9864
|
+
transitionTimeoutRef.current = null;
|
|
9865
|
+
}, resolvedSubmenuTransitionDurationMs);
|
|
9866
|
+
}
|
|
9867
|
+
previousMenuLevelRef.current = level;
|
|
9868
|
+
setMenuLevel(level);
|
|
9869
|
+
return;
|
|
9870
|
+
}
|
|
9871
|
+
menuProps.onMenuLevelChange?.(level);
|
|
9872
|
+
},
|
|
9873
|
+
[isAnchored, menuProps, resolvedSubmenuTransitionDurationMs]
|
|
9874
|
+
);
|
|
9875
|
+
const content = /* @__PURE__ */ createElement(
|
|
9876
|
+
ContextMenuContentComponent,
|
|
9671
9877
|
{
|
|
9672
9878
|
...menuProps,
|
|
9673
|
-
|
|
9879
|
+
key: `context-menu-content-${contentResetToken}`,
|
|
9880
|
+
onMenuLevelChange: handleMenuLevelChange,
|
|
9881
|
+
transitionDirection
|
|
9674
9882
|
}
|
|
9675
9883
|
);
|
|
9676
9884
|
if (isAnchored) {
|
|
9677
9885
|
const {
|
|
9678
9886
|
backLabel: _b,
|
|
9887
|
+
enableAnimations: _ea,
|
|
9679
9888
|
Header: _h,
|
|
9680
9889
|
items: _i,
|
|
9681
9890
|
ItemsWrapper: _w,
|
|
@@ -9688,6 +9897,8 @@ const ContextMenu = (props) => {
|
|
|
9688
9897
|
DialogAnchor,
|
|
9689
9898
|
{
|
|
9690
9899
|
allowFlip,
|
|
9900
|
+
closeOnClickOutside,
|
|
9901
|
+
closeTransitionMs,
|
|
9691
9902
|
dialogManagerId,
|
|
9692
9903
|
focus,
|
|
9693
9904
|
id,
|
|
@@ -9841,9 +10052,9 @@ const GlobalModal = ({
|
|
|
9841
10052
|
(source, event) => {
|
|
9842
10053
|
const allow = onCloseAttempt?.(source, event);
|
|
9843
10054
|
if (allow !== false) {
|
|
9844
|
-
onClose?.(event);
|
|
9845
10055
|
dialog.close();
|
|
9846
10056
|
closingRef.current = true;
|
|
10057
|
+
onClose?.(event);
|
|
9847
10058
|
}
|
|
9848
10059
|
},
|
|
9849
10060
|
[dialog, onClose, onCloseAttempt]
|
|
@@ -10019,16 +10230,19 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10019
10230
|
const isMessageThreadReply = typeof message.parent_id === "string";
|
|
10020
10231
|
const isBounced = isMessageBounced(message);
|
|
10021
10232
|
const allowRetry = isMessageErrorRetryable(message);
|
|
10233
|
+
const hasNetworkSendFailure = isNetworkSendFailure(message);
|
|
10022
10234
|
return useMemo(() => {
|
|
10023
10235
|
if (disable) return messageActionSet;
|
|
10024
10236
|
if (isBounced || isInitialMessage || // not sure whether this thing even works anymore
|
|
10025
10237
|
!message.type || message.type === "system" || message.type === "ephemeral" || message.status === "sending")
|
|
10026
10238
|
return [];
|
|
10027
|
-
return messageActionSet.filter((
|
|
10239
|
+
return messageActionSet.filter((action) => {
|
|
10240
|
+
if (action.placement === "quick-dropdown-toggle") return true;
|
|
10241
|
+
const type = action.type;
|
|
10028
10242
|
if (ACTIONS_NOT_WORKING_IN_THREAD.includes(type) && isMessageThreadReply)
|
|
10029
10243
|
return false;
|
|
10030
10244
|
if (message.error) {
|
|
10031
|
-
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" &&
|
|
10245
|
+
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" && (isBounced && canEdit || hasNetworkSendFailure) || type === "delete" && (isBounced && canDelete || hasNetworkSendFailure);
|
|
10032
10246
|
}
|
|
10033
10247
|
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"])
|
|
10034
10248
|
return false;
|
|
@@ -10055,6 +10269,7 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10055
10269
|
message.text,
|
|
10056
10270
|
message.type,
|
|
10057
10271
|
disable,
|
|
10272
|
+
hasNetworkSendFailure,
|
|
10058
10273
|
messageActionSet
|
|
10059
10274
|
]);
|
|
10060
10275
|
};
|
|
@@ -10370,14 +10585,14 @@ const matchMarkdownLinks = (message) => {
|
|
|
10370
10585
|
const regexMdLinks = /\[([^[]+)\](\(.*\))/gm;
|
|
10371
10586
|
const matches = message.match(regexMdLinks);
|
|
10372
10587
|
const singleMatch = /\[([^[]+)\]\((.*)\)/;
|
|
10373
|
-
const links = matches ? matches.map((
|
|
10374
|
-
const i = singleMatch.exec(
|
|
10588
|
+
const links = matches ? matches.map((match) => {
|
|
10589
|
+
const i = singleMatch.exec(match);
|
|
10375
10590
|
return i && [i[1], i[2]];
|
|
10376
10591
|
}) : [];
|
|
10377
10592
|
return links.flat();
|
|
10378
10593
|
};
|
|
10379
10594
|
const emojiMarkdownPlugin = () => {
|
|
10380
|
-
const replace = (
|
|
10595
|
+
const replace = (match) => u("element", { properties: {}, tagName: "emoji" }, [u("text", match)]);
|
|
10381
10596
|
const transform2 = (node) => findAndReplace(node, [emojiRegex(), replace]);
|
|
10382
10597
|
return transform2;
|
|
10383
10598
|
};
|
|
@@ -10387,13 +10602,13 @@ const mentionsMarkdownPlugin = (mentioned_users) => () => {
|
|
|
10387
10602
|
mentioned_usernames.map((username) => `@${username}`).join("|"),
|
|
10388
10603
|
"g"
|
|
10389
10604
|
);
|
|
10390
|
-
const replace = (
|
|
10391
|
-
const usernameOrId =
|
|
10605
|
+
const replace = (match) => {
|
|
10606
|
+
const usernameOrId = match.replace("@", "");
|
|
10392
10607
|
const user = mentioned_users.find(
|
|
10393
10608
|
({ id, name }) => name === usernameOrId || id === usernameOrId
|
|
10394
10609
|
);
|
|
10395
10610
|
return u("element", { mentionedUser: user, properties: {}, tagName: "mention" }, [
|
|
10396
|
-
u("text",
|
|
10611
|
+
u("text", match)
|
|
10397
10612
|
]);
|
|
10398
10613
|
};
|
|
10399
10614
|
const transform2 = (tree) => {
|
|
@@ -10498,12 +10713,12 @@ const plusPlusToEmphasis = () => {
|
|
|
10498
10713
|
if (node.type !== "text" || parent == null || typeof index !== "number") return;
|
|
10499
10714
|
const value = node.value;
|
|
10500
10715
|
INS_REGEX.lastIndex = 0;
|
|
10501
|
-
let
|
|
10716
|
+
let match;
|
|
10502
10717
|
let last = 0;
|
|
10503
10718
|
const out = [];
|
|
10504
|
-
while (
|
|
10505
|
-
const [full, inner] =
|
|
10506
|
-
const start =
|
|
10719
|
+
while (match = INS_REGEX.exec(value)) {
|
|
10720
|
+
const [full, inner] = match;
|
|
10721
|
+
const start = match.index;
|
|
10507
10722
|
if (start > last) out.push({ type: "text", value: value.slice(last, start) });
|
|
10508
10723
|
out.push({
|
|
10509
10724
|
children: [{ type: "text", value: inner }],
|
|
@@ -10679,17 +10894,6 @@ const renderText = (text2, mentionedUsers, {
|
|
|
10679
10894
|
}
|
|
10680
10895
|
) });
|
|
10681
10896
|
};
|
|
10682
|
-
const ROOT_CLASS_NAME = "str-chat__message--error-message";
|
|
10683
|
-
function MessageErrorText({ message }) {
|
|
10684
|
-
const { t } = useTranslationContext("MessageText");
|
|
10685
|
-
if (message.type === "error" && !isMessageBounced(message)) {
|
|
10686
|
-
return /* @__PURE__ */ jsx("div", { className: ROOT_CLASS_NAME, children: t("Error · Unsent") });
|
|
10687
|
-
}
|
|
10688
|
-
if (message.status === "failed") {
|
|
10689
|
-
return /* @__PURE__ */ jsx("div", { className: ROOT_CLASS_NAME, children: message.error?.status !== 403 ? t("Message Failed · Click to try again") : t("Message Failed · Unauthorized") });
|
|
10690
|
-
}
|
|
10691
|
-
return null;
|
|
10692
|
-
}
|
|
10693
10897
|
const UnMemoizedMessageTextComponent = (props) => {
|
|
10694
10898
|
const {
|
|
10695
10899
|
customInnerClass,
|
|
@@ -10717,7 +10921,7 @@ const UnMemoizedMessageTextComponent = (props) => {
|
|
|
10717
10921
|
const wrapperClass = customWrapperClass || "str-chat__message-text";
|
|
10718
10922
|
const innerClass = customInnerClass;
|
|
10719
10923
|
if (!messageTextToRender) return null;
|
|
10720
|
-
return /* @__PURE__ */ jsx("div", { className: wrapperClass, tabIndex: 0, children: /* @__PURE__ */
|
|
10924
|
+
return /* @__PURE__ */ jsx("div", { className: wrapperClass, tabIndex: 0, children: /* @__PURE__ */ jsx(
|
|
10721
10925
|
"div",
|
|
10722
10926
|
{
|
|
10723
10927
|
className: clsx(innerClass, {
|
|
@@ -10727,10 +10931,7 @@ const UnMemoizedMessageTextComponent = (props) => {
|
|
|
10727
10931
|
"data-testid": "message-text-inner-wrapper",
|
|
10728
10932
|
onClick: onMentionsClickMessage,
|
|
10729
10933
|
onMouseOver: onMentionsHoverMessage,
|
|
10730
|
-
children:
|
|
10731
|
-
/* @__PURE__ */ jsx(MessageErrorText, { message }),
|
|
10732
|
-
unsafeHTML && message.html ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: message.html } }) : /* @__PURE__ */ jsx("div", { children: messageText })
|
|
10733
|
-
]
|
|
10934
|
+
children: unsafeHTML && message.html ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: message.html } }) : /* @__PURE__ */ jsx("div", { children: messageText })
|
|
10734
10935
|
}
|
|
10735
10936
|
) });
|
|
10736
10937
|
};
|
|
@@ -11945,6 +12146,7 @@ const toBaseImageDescriptors = (attachment, options = {}) => {
|
|
|
11945
12146
|
title: attachment.title
|
|
11946
12147
|
};
|
|
11947
12148
|
}
|
|
12149
|
+
return void 0;
|
|
11948
12150
|
};
|
|
11949
12151
|
const BASE_FILE_ICON_CLASSNAME = "str-chat__file-icon";
|
|
11950
12152
|
const FILE_ICON_GRAPHIC_CLASSNAME = "str-chat__file-icon__graphic";
|
|
@@ -14782,7 +14984,8 @@ const PollOptionWithVotes = ({
|
|
|
14782
14984
|
"div",
|
|
14783
14985
|
{
|
|
14784
14986
|
className: clsx("str-chat__poll-option", {
|
|
14785
|
-
"str-chat__poll-option--has-more-votes": isVotesPreview && voteCount > countVotesPreview
|
|
14987
|
+
"str-chat__poll-option--has-more-votes": isVotesPreview && voteCount > countVotesPreview,
|
|
14988
|
+
"str-chat__poll-option--has-votes": voteCount
|
|
14786
14989
|
}),
|
|
14787
14990
|
children: [
|
|
14788
14991
|
/* @__PURE__ */ jsx(PollOptionWithVotesHeader, { option, optionOrderNumber: orderNumber }),
|
|
@@ -15076,10 +15279,12 @@ const PollOptionSelector = ({
|
|
|
15076
15279
|
canCastVote && /* @__PURE__ */ jsx(Checkmark, { checked: !!ownVotesByOptionId[option.id] }),
|
|
15077
15280
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__poll-option-data", children: [
|
|
15078
15281
|
/* @__PURE__ */ jsx("p", { className: "str-chat__poll-option-text", children: option.text }),
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15282
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__poll-option-votes", children: [
|
|
15283
|
+
displayAvatarCount && voting_visibility === "public" && /* @__PURE__ */ jsx("div", { className: "str-chat__poll-option-voters", children: /* @__PURE__ */ jsx(AvatarStack$1, { displayInfo: avatarDisplayInfo, size: "xs" }) }),
|
|
15284
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__poll-option-vote-count", children: voteCountVerbose ? t("{{count}} votes", {
|
|
15285
|
+
count: vote_counts_by_option[option.id] ?? 0
|
|
15286
|
+
}) : vote_counts_by_option[option.id] ?? 0 })
|
|
15287
|
+
] })
|
|
15083
15288
|
] }),
|
|
15084
15289
|
/* @__PURE__ */ jsx(
|
|
15085
15290
|
AmountBar,
|
|
@@ -15594,31 +15799,34 @@ const CommandContextMenuItem = ({
|
|
|
15594
15799
|
}
|
|
15595
15800
|
);
|
|
15596
15801
|
};
|
|
15597
|
-
const AttachmentSelectorMenuInitButtonIcon = () => {
|
|
15802
|
+
const AttachmentSelectorMenuInitButtonIcon = ({ className }) => {
|
|
15598
15803
|
const { AttachmentSelectorInitiationButtonContents } = useComponentContext();
|
|
15599
15804
|
if (AttachmentSelectorInitiationButtonContents) {
|
|
15600
|
-
return /* @__PURE__ */ jsx(AttachmentSelectorInitiationButtonContents, {});
|
|
15805
|
+
return /* @__PURE__ */ jsx("span", { className, children: /* @__PURE__ */ jsx(AttachmentSelectorInitiationButtonContents, {}) });
|
|
15601
15806
|
}
|
|
15602
|
-
return /* @__PURE__ */ jsx(
|
|
15807
|
+
return /* @__PURE__ */ jsx(
|
|
15808
|
+
IconPlusLarge,
|
|
15809
|
+
{
|
|
15810
|
+
className: clsx("str-chat__attachment-selector__menu-button__icon", className)
|
|
15811
|
+
}
|
|
15812
|
+
);
|
|
15603
15813
|
};
|
|
15604
|
-
const AttachmentSelectorButton = forwardRef(
|
|
15605
|
-
|
|
15606
|
-
|
|
15607
|
-
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
|
|
15615
|
-
|
|
15616
|
-
|
|
15617
|
-
|
|
15618
|
-
|
|
15619
|
-
|
|
15620
|
-
}
|
|
15621
|
-
);
|
|
15814
|
+
const AttachmentSelectorButton = forwardRef(function AttachmentSelectorButton2({ className, iconClassName, ...props }, ref) {
|
|
15815
|
+
return /* @__PURE__ */ jsx(
|
|
15816
|
+
Button,
|
|
15817
|
+
{
|
|
15818
|
+
appearance: "outline",
|
|
15819
|
+
circular: true,
|
|
15820
|
+
className: clsx("str-chat__attachment-selector__menu-button", className),
|
|
15821
|
+
"data-testid": "invoke-attachment-selector-button",
|
|
15822
|
+
size: "lg",
|
|
15823
|
+
variant: "secondary",
|
|
15824
|
+
...props,
|
|
15825
|
+
ref,
|
|
15826
|
+
children: /* @__PURE__ */ jsx(AttachmentSelectorMenuInitButtonIcon, { className: iconClassName })
|
|
15827
|
+
}
|
|
15828
|
+
);
|
|
15829
|
+
});
|
|
15622
15830
|
const SimpleAttachmentSelector = () => {
|
|
15623
15831
|
const { channelCapabilities } = useChannelStateContext();
|
|
15624
15832
|
const inputRef = useRef(null);
|
|
@@ -15790,7 +15998,7 @@ const AttachmentSelector = ({
|
|
|
15790
15998
|
getModalPortalDestination
|
|
15791
15999
|
}) => {
|
|
15792
16000
|
const { t } = useTranslationContext();
|
|
15793
|
-
const { Modal = GlobalModal } = useComponentContext();
|
|
16001
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu, Modal = GlobalModal } = useComponentContext();
|
|
15794
16002
|
const { channelCapabilities } = useChannelStateContext();
|
|
15795
16003
|
const messageComposer = useMessageComposerController();
|
|
15796
16004
|
const isCooldownActive = useIsCooldownActive();
|
|
@@ -15841,16 +16049,16 @@ const AttachmentSelector = ({
|
|
|
15841
16049
|
"aria-expanded": menuDialogIsOpen,
|
|
15842
16050
|
"aria-haspopup": "true",
|
|
15843
16051
|
"aria-label": t("aria/Open Attachment Selector"),
|
|
15844
|
-
|
|
16052
|
+
disabled: isCooldownActive,
|
|
16053
|
+
iconClassName: clsx("str-chat__prepare-rotate45", {
|
|
15845
16054
|
"str-chat__rotate45": menuDialogIsOpen
|
|
15846
16055
|
}),
|
|
15847
|
-
disabled: isCooldownActive,
|
|
15848
16056
|
onClick: () => menuDialog?.toggle(),
|
|
15849
16057
|
ref: menuButtonRef
|
|
15850
16058
|
}
|
|
15851
16059
|
),
|
|
15852
16060
|
/* @__PURE__ */ jsx(
|
|
15853
|
-
|
|
16061
|
+
ContextMenuComponent,
|
|
15854
16062
|
{
|
|
15855
16063
|
allowFlip: true,
|
|
15856
16064
|
backLabel: t("Back"),
|
|
@@ -15969,562 +16177,175 @@ const PlayIcon = () => /* @__PURE__ */ jsx(
|
|
|
15969
16177
|
}
|
|
15970
16178
|
);
|
|
15971
16179
|
const CheckSignIcon = () => /* @__PURE__ */ jsx("svg", { fill: "currentColor", viewBox: "0 0 18 14", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ 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" }) });
|
|
15972
|
-
const
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
);
|
|
15980
|
-
return {};
|
|
16180
|
+
const INTERACTIVE_SELECTOR = 'button, a, input, textarea, select, [role="button"], [role="link"], [data-interactive="true"]';
|
|
16181
|
+
function hasInteractiveAncestorBeforeRoot(target, root) {
|
|
16182
|
+
if (!(target instanceof Element) || !root) return false;
|
|
16183
|
+
let el = target;
|
|
16184
|
+
while (el && el !== root) {
|
|
16185
|
+
if (el.matches(INTERACTIVE_SELECTOR)) return true;
|
|
16186
|
+
el = el.parentElement;
|
|
15981
16187
|
}
|
|
15982
|
-
return
|
|
15983
|
-
}
|
|
15984
|
-
const
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
|
|
15988
|
-
|
|
15989
|
-
|
|
15990
|
-
onRequestClose
|
|
16188
|
+
return false;
|
|
16189
|
+
}
|
|
16190
|
+
const AttachmentPreviewRoot = ({
|
|
16191
|
+
attachment,
|
|
16192
|
+
onPressed,
|
|
16193
|
+
openPreview,
|
|
16194
|
+
tabIndex = 0,
|
|
16195
|
+
...props
|
|
15991
16196
|
}) => {
|
|
15992
|
-
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
15993
|
-
const itemCount = items.length;
|
|
15994
|
-
const goToIndex = useCallback(
|
|
15995
|
-
(index) => {
|
|
15996
|
-
if (index >= 0 && index < itemCount) {
|
|
15997
|
-
setCurrentIndex(index);
|
|
15998
|
-
}
|
|
15999
|
-
},
|
|
16000
|
-
[itemCount]
|
|
16001
|
-
);
|
|
16002
|
-
const goToNext = useCallback(() => {
|
|
16003
|
-
setCurrentIndex((prev) => prev < itemCount - 1 ? prev + 1 : prev);
|
|
16004
|
-
}, [itemCount]);
|
|
16005
|
-
const goToPrevious = useCallback(() => {
|
|
16006
|
-
setCurrentIndex((prev) => prev > 0 ? prev - 1 : prev);
|
|
16007
|
-
}, []);
|
|
16008
|
-
useEffect(() => {
|
|
16009
|
-
onIndexChange?.(currentIndex);
|
|
16010
|
-
}, [currentIndex, onIndexChange]);
|
|
16011
|
-
const hasNext = currentIndex < itemCount - 1;
|
|
16012
|
-
const hasPrevious = currentIndex > 0;
|
|
16013
|
-
const currentItem = items[currentIndex];
|
|
16014
|
-
const contextValue = useMemo(
|
|
16015
|
-
() => ({
|
|
16016
|
-
closeOnBackgroundClick,
|
|
16017
|
-
currentIndex,
|
|
16018
|
-
currentItem,
|
|
16019
|
-
goToIndex,
|
|
16020
|
-
goToNext,
|
|
16021
|
-
goToPrevious,
|
|
16022
|
-
hasNext,
|
|
16023
|
-
hasPrevious,
|
|
16024
|
-
itemCount,
|
|
16025
|
-
items,
|
|
16026
|
-
onRequestClose
|
|
16027
|
-
}),
|
|
16028
|
-
[
|
|
16029
|
-
closeOnBackgroundClick,
|
|
16030
|
-
currentIndex,
|
|
16031
|
-
currentItem,
|
|
16032
|
-
goToIndex,
|
|
16033
|
-
goToNext,
|
|
16034
|
-
goToPrevious,
|
|
16035
|
-
hasNext,
|
|
16036
|
-
hasPrevious,
|
|
16037
|
-
itemCount,
|
|
16038
|
-
items,
|
|
16039
|
-
onRequestClose
|
|
16040
|
-
]
|
|
16041
|
-
);
|
|
16042
|
-
return /* @__PURE__ */ jsx(GalleryContext.Provider, { value: contextValue, children: GalleryUI2 ? /* @__PURE__ */ jsx(GalleryUI2, {}) : null });
|
|
16043
|
-
};
|
|
16044
|
-
const GalleryHeader = ({ currentItem }) => {
|
|
16045
16197
|
const { t } = useTranslationContext();
|
|
16046
|
-
const
|
|
16047
|
-
const
|
|
16048
|
-
const
|
|
16049
|
-
const
|
|
16050
|
-
const
|
|
16051
|
-
|
|
16052
|
-
if (
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
"a",
|
|
16066
|
-
{
|
|
16067
|
-
"aria-label": downloadLabel,
|
|
16068
|
-
className: "str-chat__gallery__action-button str-chat__gallery__action-button--download",
|
|
16069
|
-
download: true,
|
|
16070
|
-
href: downloadUrl,
|
|
16071
|
-
rel: "noreferrer",
|
|
16072
|
-
target: "_blank",
|
|
16073
|
-
title: downloadLabel,
|
|
16074
|
-
children: /* @__PURE__ */ jsx(IconArrowDownCircle, {})
|
|
16075
|
-
}
|
|
16076
|
-
) : null,
|
|
16077
|
-
modalContext?.close ? /* @__PURE__ */ jsx(
|
|
16078
|
-
Button,
|
|
16079
|
-
{
|
|
16080
|
-
"aria-label": t("Close"),
|
|
16081
|
-
className: "str-chat__gallery__action-button str-chat__gallery__action-button--close",
|
|
16082
|
-
onClick: modalContext.close,
|
|
16083
|
-
title: t("Close"),
|
|
16084
|
-
children: /* @__PURE__ */ jsx(IconCrossMedium, {})
|
|
16085
|
-
}
|
|
16086
|
-
) : null
|
|
16087
|
-
] })
|
|
16088
|
-
] });
|
|
16089
|
-
};
|
|
16090
|
-
const VideoPlayer = ({ isPlaying, thumbnailUrl, videoUrl }) => {
|
|
16091
|
-
const { VideoPlayer: VideoPlayerContext } = useComponentContext();
|
|
16092
|
-
return VideoPlayerContext ? /* @__PURE__ */ jsx(VideoPlayerContext, { thumbnailUrl, videoUrl }) : /* @__PURE__ */ jsx(
|
|
16093
|
-
ReactPlayer,
|
|
16198
|
+
const [root, setRoot] = useState(null);
|
|
16199
|
+
const url = attachment.asset_url || attachment.image_url || attachment.localMetadata.previewUri;
|
|
16200
|
+
const canDownloadAttachment = false;
|
|
16201
|
+
const canPreviewAttachment = !!openPreview && (!!url && isImageAttachment(attachment) || isVideoAttachment(attachment));
|
|
16202
|
+
const handlePressed = (e) => {
|
|
16203
|
+
if (e.defaultPrevented) return;
|
|
16204
|
+
if (hasInteractiveAncestorBeforeRoot(e.target, root)) return;
|
|
16205
|
+
if (onPressed) {
|
|
16206
|
+
const shouldContinue = onPressed(e);
|
|
16207
|
+
if (!shouldContinue) return;
|
|
16208
|
+
}
|
|
16209
|
+
if (canPreviewAttachment) {
|
|
16210
|
+
openPreview();
|
|
16211
|
+
return;
|
|
16212
|
+
}
|
|
16213
|
+
};
|
|
16214
|
+
const isInteractive = canPreviewAttachment || canDownloadAttachment;
|
|
16215
|
+
return /* @__PURE__ */ jsx(
|
|
16216
|
+
"div",
|
|
16094
16217
|
{
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16218
|
+
"aria-label": isInteractive ? t(canPreviewAttachment ? "aria/Show preview" : "aria/Download attachment") : void 0,
|
|
16219
|
+
...props,
|
|
16220
|
+
onClick: handlePressed,
|
|
16221
|
+
onKeyDown: isInteractive ? (e) => {
|
|
16222
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
16223
|
+
e.preventDefault();
|
|
16224
|
+
handlePressed(e);
|
|
16225
|
+
} : void 0,
|
|
16226
|
+
ref: setRoot,
|
|
16227
|
+
tabIndex: isInteractive ? tabIndex : -1,
|
|
16228
|
+
children: props.children
|
|
16102
16229
|
}
|
|
16103
16230
|
);
|
|
16104
16231
|
};
|
|
16105
|
-
const
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16232
|
+
const FileAttachmentPreview = ({
|
|
16233
|
+
attachment,
|
|
16234
|
+
handleRetry,
|
|
16235
|
+
removeAttachments
|
|
16109
16236
|
}) => {
|
|
16110
|
-
const { t } = useTranslationContext();
|
|
16111
|
-
|
|
16112
|
-
|
|
16113
|
-
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
"
|
|
16124
|
-
|
|
16125
|
-
|
|
16126
|
-
"str-
|
|
16127
|
-
|
|
16128
|
-
|
|
16129
|
-
|
|
16130
|
-
|
|
16131
|
-
|
|
16132
|
-
|
|
16133
|
-
|
|
16134
|
-
|
|
16135
|
-
}
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16237
|
+
const { t } = useTranslationContext("FilePreview");
|
|
16238
|
+
const { id, uploadPermissionCheck, uploadState } = attachment.localMetadata ?? {};
|
|
16239
|
+
const hasSizeLimitError = uploadPermissionCheck?.reason === "size_limit";
|
|
16240
|
+
const hasFatalError = uploadState === "blocked" || hasSizeLimitError;
|
|
16241
|
+
const hasRetriableError = uploadState === "failed" && !!handleRetry;
|
|
16242
|
+
const hasError = hasRetriableError || hasFatalError;
|
|
16243
|
+
return /* @__PURE__ */ jsxs(
|
|
16244
|
+
AttachmentPreviewRoot,
|
|
16245
|
+
{
|
|
16246
|
+
attachment,
|
|
16247
|
+
className: "str-chat__attachment-preview-file",
|
|
16248
|
+
"data-testid": "attachment-preview-file",
|
|
16249
|
+
children: [
|
|
16250
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__attachment-preview-file__icon", children: /* @__PURE__ */ jsx(FileIcon, { fileName: attachment.title, mimeType: attachment.mime_type }) }),
|
|
16251
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__info", children: [
|
|
16252
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__attachment-preview-file-name", title: attachment.title, children: attachment.title }),
|
|
16253
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__data", children: [
|
|
16254
|
+
uploadState === "uploading" && /* @__PURE__ */ jsx(LoadingIndicatorIcon, {}),
|
|
16255
|
+
!hasError && /* @__PURE__ */ jsx(FileSizeIndicator, { fileSize: attachment.file_size }),
|
|
16256
|
+
hasFatalError && /* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__fatal-error", children: [
|
|
16257
|
+
/* @__PURE__ */ jsx(IconExclamationCircle, {}),
|
|
16258
|
+
/* @__PURE__ */ jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
|
|
16259
|
+
] }),
|
|
16260
|
+
hasRetriableError && /* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
|
|
16261
|
+
/* @__PURE__ */ jsx(IconExclamationTriangle, {}),
|
|
16262
|
+
/* @__PURE__ */ jsx("span", { children: t("Upload error") }),
|
|
16263
|
+
/* @__PURE__ */ jsx(
|
|
16264
|
+
"button",
|
|
16265
|
+
{
|
|
16266
|
+
"aria-label": t("aria/Retry upload"),
|
|
16267
|
+
className: "str-chat__attachment-preview-file__retry-upload-button",
|
|
16268
|
+
"data-testid": "file-preview-item-retry-button",
|
|
16269
|
+
onClick: () => {
|
|
16270
|
+
handleRetry(attachment);
|
|
16271
|
+
},
|
|
16272
|
+
type: "button",
|
|
16273
|
+
children: t("Retry upload")
|
|
16274
|
+
}
|
|
16275
|
+
)
|
|
16276
|
+
] })
|
|
16277
|
+
] })
|
|
16278
|
+
] }),
|
|
16279
|
+
/* @__PURE__ */ jsx(
|
|
16280
|
+
RemoveAttachmentPreviewButton,
|
|
16281
|
+
{
|
|
16282
|
+
"data-testid": "file-preview-item-delete-button",
|
|
16283
|
+
onClick: () => {
|
|
16284
|
+
if (id) removeAttachments([id]);
|
|
16285
|
+
},
|
|
16286
|
+
uploadState
|
|
16287
|
+
}
|
|
16288
|
+
)
|
|
16289
|
+
]
|
|
16290
|
+
}
|
|
16158
16291
|
);
|
|
16159
|
-
const ignoreNextClickRef = useRef(false);
|
|
16160
|
-
const touchStartRef = useRef(null);
|
|
16161
|
-
const isVerticalSwipeRef = useRef(false);
|
|
16162
|
-
const containerRef = useRef(null);
|
|
16163
|
-
useEffect(() => {
|
|
16164
|
-
setShowVideo(false);
|
|
16165
|
-
}, [currentIndex]);
|
|
16166
|
-
const prevIndexRef = useRef(currentIndex);
|
|
16167
|
-
useEffect(() => {
|
|
16168
|
-
if (prevIndexRef.current === currentIndex) return;
|
|
16169
|
-
const direction = currentIndex > prevIndexRef.current ? "forward" : "backward";
|
|
16170
|
-
setSlideDirection(direction);
|
|
16171
|
-
setSlideOffset(0);
|
|
16172
|
-
setIsDragging(false);
|
|
16173
|
-
isTransitioningRef.current = true;
|
|
16174
|
-
const timer = setTimeout(() => {
|
|
16175
|
-
setSlideDirection(null);
|
|
16176
|
-
isTransitioningRef.current = false;
|
|
16177
|
-
}, TRANSITION_DURATION);
|
|
16178
|
-
prevIndexRef.current = currentIndex;
|
|
16179
|
-
return () => clearTimeout(timer);
|
|
16180
|
-
}, [currentIndex]);
|
|
16181
|
-
const handleGoToNext = useCallback(() => {
|
|
16182
|
-
if (isTransitioningRef.current) return;
|
|
16183
|
-
goToNext();
|
|
16184
|
-
}, [goToNext]);
|
|
16185
|
-
const handleGoToPrevious = useCallback(() => {
|
|
16186
|
-
if (isTransitioningRef.current) return;
|
|
16187
|
-
goToPrevious();
|
|
16188
|
-
}, [goToPrevious]);
|
|
16189
|
-
const handleKeyDown = useCallback(
|
|
16190
|
-
(event) => {
|
|
16191
|
-
if (event.key === "ArrowLeft") {
|
|
16192
|
-
event.preventDefault();
|
|
16193
|
-
handleGoToPrevious();
|
|
16194
|
-
} else if (event.key === "ArrowRight") {
|
|
16195
|
-
event.preventDefault();
|
|
16196
|
-
handleGoToNext();
|
|
16197
|
-
}
|
|
16198
|
-
},
|
|
16199
|
-
[handleGoToNext, handleGoToPrevious]
|
|
16200
|
-
);
|
|
16201
|
-
useEffect(() => {
|
|
16202
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
16203
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
16204
|
-
}, [handleKeyDown]);
|
|
16205
|
-
const handleTouchStart = useCallback((event) => {
|
|
16206
|
-
if (isTransitioningRef.current) return;
|
|
16207
|
-
const touch = event.touches[0];
|
|
16208
|
-
ignoreNextClickRef.current = false;
|
|
16209
|
-
touchStartRef.current = { x: touch.clientX, y: touch.clientY };
|
|
16210
|
-
isVerticalSwipeRef.current = false;
|
|
16211
|
-
}, []);
|
|
16212
|
-
const handleTouchMove = useCallback(
|
|
16213
|
-
(event) => {
|
|
16214
|
-
if (!touchStartRef.current || isTransitioningRef.current) return;
|
|
16215
|
-
const touch = event.touches[0];
|
|
16216
|
-
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
16217
|
-
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
16218
|
-
if (!isDragging && !isVerticalSwipeRef.current) {
|
|
16219
|
-
if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 10) {
|
|
16220
|
-
ignoreNextClickRef.current = true;
|
|
16221
|
-
isVerticalSwipeRef.current = true;
|
|
16222
|
-
return;
|
|
16223
|
-
}
|
|
16224
|
-
if (Math.abs(deltaX) > 10) {
|
|
16225
|
-
ignoreNextClickRef.current = true;
|
|
16226
|
-
setIsDragging(true);
|
|
16227
|
-
}
|
|
16228
|
-
}
|
|
16229
|
-
if (isVerticalSwipeRef.current) return;
|
|
16230
|
-
if (!hasNext && deltaX < 0 || !hasPrevious && deltaX > 0) {
|
|
16231
|
-
setSlideOffset(deltaX * 0.3);
|
|
16232
|
-
} else {
|
|
16233
|
-
setSlideOffset(deltaX);
|
|
16234
|
-
}
|
|
16235
|
-
},
|
|
16236
|
-
[isDragging, hasNext, hasPrevious]
|
|
16237
|
-
);
|
|
16238
|
-
const handleTouchEnd = useCallback(() => {
|
|
16239
|
-
if (!touchStartRef.current || isVerticalSwipeRef.current) {
|
|
16240
|
-
if (isVerticalSwipeRef.current) ignoreNextClickRef.current = true;
|
|
16241
|
-
touchStartRef.current = null;
|
|
16242
|
-
return;
|
|
16243
|
-
}
|
|
16244
|
-
const offset = slideOffset;
|
|
16245
|
-
if (isDragging || Math.abs(offset) > 10) {
|
|
16246
|
-
ignoreNextClickRef.current = true;
|
|
16247
|
-
}
|
|
16248
|
-
touchStartRef.current = null;
|
|
16249
|
-
if (Math.abs(offset) >= SWIPE_THRESHOLD) {
|
|
16250
|
-
if (offset < 0 && hasNext) {
|
|
16251
|
-
goToNext();
|
|
16252
|
-
} else if (offset > 0 && hasPrevious) {
|
|
16253
|
-
goToPrevious();
|
|
16254
|
-
} else {
|
|
16255
|
-
setSlideOffset(0);
|
|
16256
|
-
}
|
|
16257
|
-
} else {
|
|
16258
|
-
setSlideOffset(0);
|
|
16259
|
-
}
|
|
16260
|
-
setIsDragging(false);
|
|
16261
|
-
}, [slideOffset, hasNext, hasPrevious, goToNext, goToPrevious, isDragging]);
|
|
16262
|
-
const requestClose = modalContext?.close ?? onRequestClose;
|
|
16263
|
-
const handleBackgroundClick = useCallback(
|
|
16264
|
-
(event) => {
|
|
16265
|
-
if (event.target !== event.currentTarget) return;
|
|
16266
|
-
if (ignoreNextClickRef.current) {
|
|
16267
|
-
ignoreNextClickRef.current = false;
|
|
16268
|
-
return;
|
|
16269
|
-
}
|
|
16270
|
-
if (!closeOnBackgroundClick) return;
|
|
16271
|
-
requestClose?.();
|
|
16272
|
-
},
|
|
16273
|
-
[closeOnBackgroundClick, requestClose]
|
|
16274
|
-
);
|
|
16275
|
-
const mediaStyle = isDragging || slideOffset !== 0 && slideDirection === null ? { transform: `translateX(${slideOffset}px)` } : {};
|
|
16276
|
-
return /* @__PURE__ */ jsxs("div", { className: "str-chat__gallery", children: [
|
|
16277
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__main", children: [
|
|
16278
|
-
/* @__PURE__ */ jsx(GalleryHeader, { currentItem }),
|
|
16279
|
-
/* @__PURE__ */ jsx(
|
|
16280
|
-
NavButton,
|
|
16281
|
-
{
|
|
16282
|
-
"aria-label": t("Previous image"),
|
|
16283
|
-
className: clsx(
|
|
16284
|
-
"str-chat__gallery__nav-button--prev",
|
|
16285
|
-
!hasPrevious && "str-chat__gallery__nav-button--hidden"
|
|
16286
|
-
),
|
|
16287
|
-
disabled: !hasPrevious,
|
|
16288
|
-
onClick: handleGoToPrevious,
|
|
16289
|
-
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
16290
|
-
}
|
|
16291
|
-
),
|
|
16292
|
-
/* @__PURE__ */ jsx(
|
|
16293
|
-
"div",
|
|
16294
|
-
{
|
|
16295
|
-
className: "str-chat__gallery__slide-container",
|
|
16296
|
-
onClick: handleBackgroundClick,
|
|
16297
|
-
onTouchEnd: handleTouchEnd,
|
|
16298
|
-
onTouchMove: handleTouchMove,
|
|
16299
|
-
onTouchStart: handleTouchStart,
|
|
16300
|
-
ref: containerRef,
|
|
16301
|
-
children: /* @__PURE__ */ jsx(
|
|
16302
|
-
"div",
|
|
16303
|
-
{
|
|
16304
|
-
className: clsx({
|
|
16305
|
-
"str-chat__gallery__media--dragging": isDragging,
|
|
16306
|
-
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
16307
|
-
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
16308
|
-
}),
|
|
16309
|
-
style: mediaStyle,
|
|
16310
|
-
children: currentItem.videoUrl && currentItem.videoThumbnailUrl ? /* @__PURE__ */ jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--video", children: showVideo ? /* @__PURE__ */ jsx(VideoPlayer, { isPlaying: true, videoUrl: currentItem.videoUrl }) : /* @__PURE__ */ jsx(
|
|
16311
|
-
VideoThumbnail,
|
|
16312
|
-
{
|
|
16313
|
-
alt: currentItem.title ?? "",
|
|
16314
|
-
onPlay: () => setShowVideo(true),
|
|
16315
|
-
src: currentItem.videoThumbnailUrl
|
|
16316
|
-
}
|
|
16317
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--image", children: /* @__PURE__ */ jsx(BaseImage, { alt: currentItem.alt, src: currentItem.imageUrl }) })
|
|
16318
|
-
}
|
|
16319
|
-
)
|
|
16320
|
-
}
|
|
16321
|
-
),
|
|
16322
|
-
/* @__PURE__ */ jsx(
|
|
16323
|
-
NavButton,
|
|
16324
|
-
{
|
|
16325
|
-
"aria-label": t("Next image"),
|
|
16326
|
-
className: clsx(
|
|
16327
|
-
"str-chat__gallery__nav-button--next",
|
|
16328
|
-
!hasNext && "str-chat__gallery__nav-button--hidden"
|
|
16329
|
-
),
|
|
16330
|
-
disabled: !hasNext,
|
|
16331
|
-
onClick: handleGoToNext,
|
|
16332
|
-
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
16333
|
-
}
|
|
16334
|
-
)
|
|
16335
|
-
] }),
|
|
16336
|
-
itemCount > 1 && /* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__position-indicator", children: [
|
|
16337
|
-
currentIndex + 1,
|
|
16338
|
-
" of ",
|
|
16339
|
-
itemCount
|
|
16340
|
-
] })
|
|
16341
|
-
] });
|
|
16342
16292
|
};
|
|
16343
|
-
const
|
|
16344
|
-
|
|
16345
|
-
|
|
16346
|
-
|
|
16347
|
-
|
|
16348
|
-
|
|
16349
|
-
|
|
16350
|
-
|
|
16293
|
+
const UnsupportedAttachmentPreview = ({
|
|
16294
|
+
attachment,
|
|
16295
|
+
handleRetry,
|
|
16296
|
+
removeAttachments
|
|
16297
|
+
}) => /* @__PURE__ */ jsx(
|
|
16298
|
+
FileAttachmentPreview,
|
|
16299
|
+
{
|
|
16300
|
+
attachment,
|
|
16301
|
+
handleRetry,
|
|
16302
|
+
removeAttachments
|
|
16351
16303
|
}
|
|
16352
|
-
|
|
16304
|
+
);
|
|
16305
|
+
function formatTime(totalSeconds, rounding = "ceil") {
|
|
16306
|
+
if (totalSeconds == null || Number.isNaN(totalSeconds) || totalSeconds < 0) {
|
|
16307
|
+
return null;
|
|
16308
|
+
}
|
|
16309
|
+
const roundedSeconds = rounding === "floor" ? Math.floor(totalSeconds) : Math.ceil(totalSeconds);
|
|
16310
|
+
const hours = Math.floor(roundedSeconds / 3600);
|
|
16311
|
+
const minutes = Math.floor(roundedSeconds % 3600 / 60);
|
|
16312
|
+
const seconds = roundedSeconds % 60;
|
|
16313
|
+
const minSec = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
|
|
16314
|
+
2,
|
|
16315
|
+
"0"
|
|
16316
|
+
)}`;
|
|
16317
|
+
return hours ? `${String(hours).padStart(2, "0")}:${minSec}` : minSec;
|
|
16353
16318
|
}
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
|
|
16361
|
-
const
|
|
16362
|
-
const
|
|
16363
|
-
const
|
|
16364
|
-
const
|
|
16365
|
-
const
|
|
16366
|
-
const
|
|
16367
|
-
const
|
|
16368
|
-
|
|
16369
|
-
|
|
16370
|
-
if (onPressed) {
|
|
16371
|
-
const shouldContinue = onPressed(e);
|
|
16372
|
-
if (!shouldContinue) return;
|
|
16373
|
-
}
|
|
16374
|
-
if (canPreviewAttachment) {
|
|
16375
|
-
setShowPreview(true);
|
|
16376
|
-
return;
|
|
16377
|
-
}
|
|
16378
|
-
};
|
|
16319
|
+
function DurationDisplay({
|
|
16320
|
+
className,
|
|
16321
|
+
duration: duration2,
|
|
16322
|
+
isPlaying,
|
|
16323
|
+
secondsElapsed,
|
|
16324
|
+
showRemaining = false
|
|
16325
|
+
}) {
|
|
16326
|
+
const remainingSeconds = duration2 != null && secondsElapsed != null ? Math.max(0, duration2 - secondsElapsed) : void 0;
|
|
16327
|
+
const formattedDuration = formatTime(duration2);
|
|
16328
|
+
const formattedSecondsElapsed = formatTime(secondsElapsed);
|
|
16329
|
+
const formattedRemaining = formatTime(remainingSeconds);
|
|
16330
|
+
const shouldShowElapsed = !!secondsElapsed && secondsElapsed > 0 && secondsElapsed < (duration2 || 0);
|
|
16331
|
+
const canShowRemaining = showRemaining && duration2 != null && secondsElapsed != null;
|
|
16332
|
+
const primaryValue = showRemaining ? formattedRemaining : formattedSecondsElapsed;
|
|
16333
|
+
const showPrimary = (canShowRemaining || shouldShowElapsed) && !!primaryValue;
|
|
16334
|
+
const showDuration = !showPrimary && !!formattedDuration;
|
|
16379
16335
|
return /* @__PURE__ */ jsxs(
|
|
16380
16336
|
"div",
|
|
16381
16337
|
{
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
ref: setRoot,
|
|
16391
|
-
role: showPreview ? "button" : props.role,
|
|
16392
|
-
tabIndex: showPreview || canDownloadAttachment ? tabIndex : -1,
|
|
16338
|
+
className: clsx(
|
|
16339
|
+
"str-chat__duration-display",
|
|
16340
|
+
{
|
|
16341
|
+
"str-chat__duration-display--hasProgress": !!secondsElapsed,
|
|
16342
|
+
"str-chat__duration-display--isPlaying": isPlaying
|
|
16343
|
+
},
|
|
16344
|
+
className
|
|
16345
|
+
),
|
|
16393
16346
|
children: [
|
|
16394
|
-
|
|
16395
|
-
/* @__PURE__ */ jsx(
|
|
16396
|
-
Modal,
|
|
16397
|
-
{
|
|
16398
|
-
className: "str-chat__gallery-modal",
|
|
16399
|
-
onClose: (e) => {
|
|
16400
|
-
e.stopPropagation();
|
|
16401
|
-
setShowPreview(false);
|
|
16402
|
-
},
|
|
16403
|
-
open: showPreview && canPreviewAttachment,
|
|
16404
|
-
children: isImageAttachment(attachment) || isVideoAttachment(attachment) ? /* @__PURE__ */ jsx(Gallery, { items: [attachment] }) : null
|
|
16405
|
-
}
|
|
16406
|
-
)
|
|
16407
|
-
]
|
|
16408
|
-
}
|
|
16409
|
-
);
|
|
16410
|
-
};
|
|
16411
|
-
const FileAttachmentPreview = ({
|
|
16412
|
-
attachment,
|
|
16413
|
-
handleRetry,
|
|
16414
|
-
removeAttachments
|
|
16415
|
-
}) => {
|
|
16416
|
-
const { t } = useTranslationContext("FilePreview");
|
|
16417
|
-
const { id, uploadPermissionCheck, uploadState } = attachment.localMetadata ?? {};
|
|
16418
|
-
const hasSizeLimitError = uploadPermissionCheck?.reason === "size_limit";
|
|
16419
|
-
const hasFatalError = uploadState === "blocked" || hasSizeLimitError;
|
|
16420
|
-
const hasRetriableError = uploadState === "failed" && !!handleRetry;
|
|
16421
|
-
const hasError = hasRetriableError || hasFatalError;
|
|
16422
|
-
return /* @__PURE__ */ jsxs(
|
|
16423
|
-
AttachmentPreviewRoot,
|
|
16424
|
-
{
|
|
16425
|
-
attachment,
|
|
16426
|
-
className: "str-chat__attachment-preview-file",
|
|
16427
|
-
"data-testid": "attachment-preview-file",
|
|
16428
|
-
children: [
|
|
16429
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__attachment-preview-file__icon", children: /* @__PURE__ */ jsx(FileIcon, { fileName: attachment.title, mimeType: attachment.mime_type }) }),
|
|
16430
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__info", children: [
|
|
16431
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__attachment-preview-file-name", title: attachment.title, children: attachment.title }),
|
|
16432
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__data", children: [
|
|
16433
|
-
uploadState === "uploading" && /* @__PURE__ */ jsx(LoadingIndicatorIcon, {}),
|
|
16434
|
-
!hasError && /* @__PURE__ */ jsx(FileSizeIndicator, { fileSize: attachment.file_size }),
|
|
16435
|
-
hasFatalError && /* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__fatal-error", children: [
|
|
16436
|
-
/* @__PURE__ */ jsx(IconExclamationCircle, {}),
|
|
16437
|
-
/* @__PURE__ */ jsx("span", { children: hasSizeLimitError ? t("File too large") : uploadState === "blocked" ? t("Upload blocked") : t("Upload failed") })
|
|
16438
|
-
] }),
|
|
16439
|
-
hasRetriableError && /* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-file__retriable-error", children: [
|
|
16440
|
-
/* @__PURE__ */ jsx(IconExclamationTriangle, {}),
|
|
16441
|
-
/* @__PURE__ */ jsx("span", { children: t("Upload error") }),
|
|
16442
|
-
/* @__PURE__ */ jsx(
|
|
16443
|
-
"button",
|
|
16444
|
-
{
|
|
16445
|
-
"aria-label": t("aria/Retry upload"),
|
|
16446
|
-
className: "str-chat__attachment-preview-file__retry-upload-button",
|
|
16447
|
-
"data-testid": "file-preview-item-retry-button",
|
|
16448
|
-
onClick: () => {
|
|
16449
|
-
handleRetry(attachment);
|
|
16450
|
-
},
|
|
16451
|
-
type: "button",
|
|
16452
|
-
children: t("Retry upload")
|
|
16453
|
-
}
|
|
16454
|
-
)
|
|
16455
|
-
] })
|
|
16456
|
-
] })
|
|
16457
|
-
] }),
|
|
16458
|
-
/* @__PURE__ */ jsx(
|
|
16459
|
-
RemoveAttachmentPreviewButton,
|
|
16460
|
-
{
|
|
16461
|
-
"data-testid": "file-preview-item-delete-button",
|
|
16462
|
-
onClick: () => {
|
|
16463
|
-
if (id) removeAttachments([id]);
|
|
16464
|
-
},
|
|
16465
|
-
uploadState
|
|
16466
|
-
}
|
|
16467
|
-
)
|
|
16468
|
-
]
|
|
16469
|
-
}
|
|
16470
|
-
);
|
|
16471
|
-
};
|
|
16472
|
-
const UnsupportedAttachmentPreview = ({
|
|
16473
|
-
attachment,
|
|
16474
|
-
handleRetry,
|
|
16475
|
-
removeAttachments
|
|
16476
|
-
}) => /* @__PURE__ */ jsx(
|
|
16477
|
-
FileAttachmentPreview,
|
|
16478
|
-
{
|
|
16479
|
-
attachment,
|
|
16480
|
-
handleRetry,
|
|
16481
|
-
removeAttachments
|
|
16482
|
-
}
|
|
16483
|
-
);
|
|
16484
|
-
function formatTime(totalSeconds, rounding = "ceil") {
|
|
16485
|
-
if (totalSeconds == null || Number.isNaN(totalSeconds) || totalSeconds < 0) {
|
|
16486
|
-
return null;
|
|
16487
|
-
}
|
|
16488
|
-
const roundedSeconds = rounding === "floor" ? Math.floor(totalSeconds) : Math.ceil(totalSeconds);
|
|
16489
|
-
const hours = Math.floor(roundedSeconds / 3600);
|
|
16490
|
-
const minutes = Math.floor(roundedSeconds % 3600 / 60);
|
|
16491
|
-
const seconds = roundedSeconds % 60;
|
|
16492
|
-
const minSec = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(
|
|
16493
|
-
2,
|
|
16494
|
-
"0"
|
|
16495
|
-
)}`;
|
|
16496
|
-
return hours ? `${String(hours).padStart(2, "0")}:${minSec}` : minSec;
|
|
16497
|
-
}
|
|
16498
|
-
function DurationDisplay({
|
|
16499
|
-
className,
|
|
16500
|
-
duration: duration2,
|
|
16501
|
-
isPlaying,
|
|
16502
|
-
secondsElapsed,
|
|
16503
|
-
showRemaining = false
|
|
16504
|
-
}) {
|
|
16505
|
-
const remainingSeconds = duration2 != null && secondsElapsed != null ? Math.max(0, duration2 - secondsElapsed) : void 0;
|
|
16506
|
-
const formattedDuration = formatTime(duration2);
|
|
16507
|
-
const formattedSecondsElapsed = formatTime(secondsElapsed);
|
|
16508
|
-
const formattedRemaining = formatTime(remainingSeconds);
|
|
16509
|
-
const shouldShowElapsed = !!secondsElapsed && secondsElapsed > 0 && secondsElapsed < (duration2 || 0);
|
|
16510
|
-
const canShowRemaining = showRemaining && duration2 != null && secondsElapsed != null;
|
|
16511
|
-
const primaryValue = showRemaining ? formattedRemaining : formattedSecondsElapsed;
|
|
16512
|
-
const showPrimary = (canShowRemaining || shouldShowElapsed) && !!primaryValue;
|
|
16513
|
-
const showDuration = !showPrimary && !!formattedDuration;
|
|
16514
|
-
return /* @__PURE__ */ jsxs(
|
|
16515
|
-
"div",
|
|
16516
|
-
{
|
|
16517
|
-
className: clsx(
|
|
16518
|
-
"str-chat__duration-display",
|
|
16519
|
-
{
|
|
16520
|
-
"str-chat__duration-display--hasProgress": !!secondsElapsed,
|
|
16521
|
-
"str-chat__duration-display--isPlaying": isPlaying
|
|
16522
|
-
},
|
|
16523
|
-
className
|
|
16524
|
-
),
|
|
16525
|
-
children: [
|
|
16526
|
-
showPrimary && /* @__PURE__ */ jsx("span", { className: "str-chat__duration-display__time-elapsed", children: primaryValue }),
|
|
16527
|
-
showDuration && /* @__PURE__ */ jsx("span", { className: "str-chat__duration-display__duration", children: formattedDuration })
|
|
16347
|
+
showPrimary && /* @__PURE__ */ jsx("span", { className: "str-chat__duration-display__time-elapsed", children: primaryValue }),
|
|
16348
|
+
showDuration && /* @__PURE__ */ jsx("span", { className: "str-chat__duration-display__duration", children: formattedDuration })
|
|
16528
16349
|
]
|
|
16529
16350
|
}
|
|
16530
16351
|
);
|
|
@@ -17031,6 +16852,7 @@ const AudioAttachmentPreview = ({
|
|
|
17031
16852
|
const MediaAttachmentPreview = ({
|
|
17032
16853
|
attachment,
|
|
17033
16854
|
handleRetry,
|
|
16855
|
+
openPreview,
|
|
17034
16856
|
removeAttachments
|
|
17035
16857
|
}) => {
|
|
17036
16858
|
const { t } = useTranslationContext();
|
|
@@ -17071,6 +16893,7 @@ const MediaAttachmentPreview = ({
|
|
|
17071
16893
|
}),
|
|
17072
16894
|
"data-testid": "attachment-preview-media",
|
|
17073
16895
|
onPressed: hasRetriableError ? retry : void 0,
|
|
16896
|
+
openPreview: !isUploading && !hasUploadError ? openPreview : void 0,
|
|
17074
16897
|
children: [
|
|
17075
16898
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__attachment-preview-media__thumbnail-wrapper", children: [
|
|
17076
16899
|
thumbnail.url && /* @__PURE__ */ jsx(
|
|
@@ -17120,6 +16943,380 @@ const MediaAttachmentPreview = ({
|
|
|
17120
16943
|
}
|
|
17121
16944
|
);
|
|
17122
16945
|
};
|
|
16946
|
+
const toGalleryItemDescriptors = (...args) => toBaseImageDescriptors(...args);
|
|
16947
|
+
const GalleryContext = createContext(void 0);
|
|
16948
|
+
const useGalleryContext = () => {
|
|
16949
|
+
const contextValue = useContext(GalleryContext);
|
|
16950
|
+
if (!contextValue) {
|
|
16951
|
+
console.warn(
|
|
16952
|
+
`The useGalleryContext hook was called outside of the GalleryContext provider. Make sure this hook is called within a child of the Gallery component.`
|
|
16953
|
+
);
|
|
16954
|
+
return {};
|
|
16955
|
+
}
|
|
16956
|
+
return contextValue;
|
|
16957
|
+
};
|
|
16958
|
+
const GalleryHeader = ({ currentItem }) => {
|
|
16959
|
+
const { t } = useTranslationContext();
|
|
16960
|
+
const { MessageTimestamp: MessageTimestamp$1 = MessageTimestamp } = useComponentContext();
|
|
16961
|
+
const { isMyMessage, message } = useMessageContext();
|
|
16962
|
+
const modalContext = useContext(ModalContext);
|
|
16963
|
+
const headerTitle = isMyMessage?.() && t("You") || message?.user?.name || message?.user?.id || currentItem.title || t("User uploaded content");
|
|
16964
|
+
const downloadUrl = useMemo(() => {
|
|
16965
|
+
const rawDownloadUrl = currentItem.videoUrl ?? currentItem.imageUrl;
|
|
16966
|
+
if (!rawDownloadUrl) return void 0;
|
|
16967
|
+
const sanitizedUrl = sanitizeUrl(rawDownloadUrl);
|
|
16968
|
+
return sanitizedUrl === "about:blank" ? void 0 : sanitizedUrl;
|
|
16969
|
+
}, [currentItem.imageUrl, currentItem.videoUrl]);
|
|
16970
|
+
const downloadLabel = t("aria/Download attachment");
|
|
16971
|
+
return /* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__header", children: [
|
|
16972
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "str-chat__gallery__header-spacer" }),
|
|
16973
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__header-meta", children: [
|
|
16974
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__gallery__title", children: headerTitle }),
|
|
16975
|
+
message?.created_at ? /* @__PURE__ */ jsx(MessageTimestamp$1, { customClass: "str-chat__gallery__timestamp" }) : null
|
|
16976
|
+
] }),
|
|
16977
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__header-actions", children: [
|
|
16978
|
+
downloadUrl ? /* @__PURE__ */ jsx(
|
|
16979
|
+
"a",
|
|
16980
|
+
{
|
|
16981
|
+
"aria-label": downloadLabel,
|
|
16982
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--download",
|
|
16983
|
+
download: true,
|
|
16984
|
+
href: downloadUrl,
|
|
16985
|
+
rel: "noreferrer",
|
|
16986
|
+
target: "_blank",
|
|
16987
|
+
title: downloadLabel,
|
|
16988
|
+
children: /* @__PURE__ */ jsx(IconArrowDownCircle, {})
|
|
16989
|
+
}
|
|
16990
|
+
) : null,
|
|
16991
|
+
modalContext?.close ? /* @__PURE__ */ jsx(
|
|
16992
|
+
Button,
|
|
16993
|
+
{
|
|
16994
|
+
"aria-label": t("Close"),
|
|
16995
|
+
className: "str-chat__gallery__action-button str-chat__gallery__action-button--close",
|
|
16996
|
+
onClick: modalContext.close,
|
|
16997
|
+
title: t("Close"),
|
|
16998
|
+
children: /* @__PURE__ */ jsx(IconCrossMedium, {})
|
|
16999
|
+
}
|
|
17000
|
+
) : null
|
|
17001
|
+
] })
|
|
17002
|
+
] });
|
|
17003
|
+
};
|
|
17004
|
+
const VideoPlayer = ({ isPlaying, thumbnailUrl, videoUrl }) => {
|
|
17005
|
+
const { VideoPlayer: VideoPlayerContext } = useComponentContext();
|
|
17006
|
+
return VideoPlayerContext ? /* @__PURE__ */ jsx(VideoPlayerContext, { thumbnailUrl, videoUrl }) : /* @__PURE__ */ jsx(
|
|
17007
|
+
ReactPlayer,
|
|
17008
|
+
{
|
|
17009
|
+
className: "react-player",
|
|
17010
|
+
config: { file: { attributes: { poster: thumbnailUrl } } },
|
|
17011
|
+
controls: true,
|
|
17012
|
+
height: "100%",
|
|
17013
|
+
playing: isPlaying,
|
|
17014
|
+
url: videoUrl,
|
|
17015
|
+
width: "100%"
|
|
17016
|
+
}
|
|
17017
|
+
);
|
|
17018
|
+
};
|
|
17019
|
+
const VideoThumbnail = ({
|
|
17020
|
+
className,
|
|
17021
|
+
onPlay,
|
|
17022
|
+
...imageProps
|
|
17023
|
+
}) => {
|
|
17024
|
+
const { t } = useTranslationContext();
|
|
17025
|
+
return /* @__PURE__ */ jsxs("div", { className: "str-chat__message-attachment__video-thumbnail", children: [
|
|
17026
|
+
/* @__PURE__ */ jsx(
|
|
17027
|
+
BaseImage,
|
|
17028
|
+
{
|
|
17029
|
+
className: clsx("str-chat__message-attachment__video-thumbnail-image", className),
|
|
17030
|
+
...imageProps
|
|
17031
|
+
}
|
|
17032
|
+
),
|
|
17033
|
+
onPlay ? /* @__PURE__ */ jsx(
|
|
17034
|
+
Button,
|
|
17035
|
+
{
|
|
17036
|
+
appearance: "solid",
|
|
17037
|
+
"aria-label": t("Play video"),
|
|
17038
|
+
circular: true,
|
|
17039
|
+
className: clsx(
|
|
17040
|
+
"str-chat__message-attachment__video-thumbnail__play-indicator"
|
|
17041
|
+
),
|
|
17042
|
+
onClick: onPlay,
|
|
17043
|
+
size: "lg",
|
|
17044
|
+
variant: "secondary",
|
|
17045
|
+
children: /* @__PURE__ */ jsx(IconPlaySolid, {})
|
|
17046
|
+
}
|
|
17047
|
+
) : /* @__PURE__ */ jsx("div", { className: "str-chat__message-attachment__video-thumbnail__play-indicator", children: /* @__PURE__ */ jsx(IconPlaySolid, {}) })
|
|
17048
|
+
] });
|
|
17049
|
+
};
|
|
17050
|
+
const SWIPE_THRESHOLD = 50;
|
|
17051
|
+
const TRANSITION_DURATION = 300;
|
|
17052
|
+
const GalleryUI = () => {
|
|
17053
|
+
const { t } = useTranslationContext();
|
|
17054
|
+
const {
|
|
17055
|
+
closeOnBackgroundClick,
|
|
17056
|
+
currentIndex,
|
|
17057
|
+
currentItem,
|
|
17058
|
+
goToNext,
|
|
17059
|
+
goToPrevious,
|
|
17060
|
+
hasNext,
|
|
17061
|
+
hasPrevious,
|
|
17062
|
+
itemCount,
|
|
17063
|
+
onRequestClose
|
|
17064
|
+
} = useGalleryContext();
|
|
17065
|
+
const modalContext = useContext(ModalContext);
|
|
17066
|
+
const [showVideo, setShowVideo] = useState(false);
|
|
17067
|
+
const isTransitioningRef = useRef(false);
|
|
17068
|
+
const [slideOffset, setSlideOffset] = useState(0);
|
|
17069
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
17070
|
+
const [slideDirection, setSlideDirection] = useState(
|
|
17071
|
+
null
|
|
17072
|
+
);
|
|
17073
|
+
const ignoreNextClickRef = useRef(false);
|
|
17074
|
+
const touchStartRef = useRef(null);
|
|
17075
|
+
const isVerticalSwipeRef = useRef(false);
|
|
17076
|
+
const containerRef = useRef(null);
|
|
17077
|
+
useEffect(() => {
|
|
17078
|
+
setShowVideo(false);
|
|
17079
|
+
}, [currentIndex]);
|
|
17080
|
+
const prevIndexRef = useRef(currentIndex);
|
|
17081
|
+
useEffect(() => {
|
|
17082
|
+
if (prevIndexRef.current === currentIndex) return;
|
|
17083
|
+
const direction = currentIndex > prevIndexRef.current ? "forward" : "backward";
|
|
17084
|
+
setSlideDirection(direction);
|
|
17085
|
+
setSlideOffset(0);
|
|
17086
|
+
setIsDragging(false);
|
|
17087
|
+
isTransitioningRef.current = true;
|
|
17088
|
+
const timer = setTimeout(() => {
|
|
17089
|
+
setSlideDirection(null);
|
|
17090
|
+
isTransitioningRef.current = false;
|
|
17091
|
+
}, TRANSITION_DURATION);
|
|
17092
|
+
prevIndexRef.current = currentIndex;
|
|
17093
|
+
return () => clearTimeout(timer);
|
|
17094
|
+
}, [currentIndex]);
|
|
17095
|
+
const handleGoToNext = useCallback(() => {
|
|
17096
|
+
if (isTransitioningRef.current) return;
|
|
17097
|
+
goToNext();
|
|
17098
|
+
}, [goToNext]);
|
|
17099
|
+
const handleGoToPrevious = useCallback(() => {
|
|
17100
|
+
if (isTransitioningRef.current) return;
|
|
17101
|
+
goToPrevious();
|
|
17102
|
+
}, [goToPrevious]);
|
|
17103
|
+
const handleKeyDown = useCallback(
|
|
17104
|
+
(event) => {
|
|
17105
|
+
if (event.key === "ArrowLeft") {
|
|
17106
|
+
event.preventDefault();
|
|
17107
|
+
handleGoToPrevious();
|
|
17108
|
+
} else if (event.key === "ArrowRight") {
|
|
17109
|
+
event.preventDefault();
|
|
17110
|
+
handleGoToNext();
|
|
17111
|
+
}
|
|
17112
|
+
},
|
|
17113
|
+
[handleGoToNext, handleGoToPrevious]
|
|
17114
|
+
);
|
|
17115
|
+
useEffect(() => {
|
|
17116
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
17117
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
17118
|
+
}, [handleKeyDown]);
|
|
17119
|
+
const handleTouchStart = useCallback((event) => {
|
|
17120
|
+
if (isTransitioningRef.current) return;
|
|
17121
|
+
const touch = event.touches[0];
|
|
17122
|
+
ignoreNextClickRef.current = false;
|
|
17123
|
+
touchStartRef.current = { x: touch.clientX, y: touch.clientY };
|
|
17124
|
+
isVerticalSwipeRef.current = false;
|
|
17125
|
+
}, []);
|
|
17126
|
+
const handleTouchMove = useCallback(
|
|
17127
|
+
(event) => {
|
|
17128
|
+
if (!touchStartRef.current || isTransitioningRef.current) return;
|
|
17129
|
+
const touch = event.touches[0];
|
|
17130
|
+
const deltaX = touch.clientX - touchStartRef.current.x;
|
|
17131
|
+
const deltaY = touch.clientY - touchStartRef.current.y;
|
|
17132
|
+
if (!isDragging && !isVerticalSwipeRef.current) {
|
|
17133
|
+
if (Math.abs(deltaY) > Math.abs(deltaX) && Math.abs(deltaY) > 10) {
|
|
17134
|
+
ignoreNextClickRef.current = true;
|
|
17135
|
+
isVerticalSwipeRef.current = true;
|
|
17136
|
+
return;
|
|
17137
|
+
}
|
|
17138
|
+
if (Math.abs(deltaX) > 10) {
|
|
17139
|
+
ignoreNextClickRef.current = true;
|
|
17140
|
+
setIsDragging(true);
|
|
17141
|
+
}
|
|
17142
|
+
}
|
|
17143
|
+
if (isVerticalSwipeRef.current) return;
|
|
17144
|
+
if (!hasNext && deltaX < 0 || !hasPrevious && deltaX > 0) {
|
|
17145
|
+
setSlideOffset(deltaX * 0.3);
|
|
17146
|
+
} else {
|
|
17147
|
+
setSlideOffset(deltaX);
|
|
17148
|
+
}
|
|
17149
|
+
},
|
|
17150
|
+
[isDragging, hasNext, hasPrevious]
|
|
17151
|
+
);
|
|
17152
|
+
const handleTouchEnd = useCallback(() => {
|
|
17153
|
+
if (!touchStartRef.current || isVerticalSwipeRef.current) {
|
|
17154
|
+
if (isVerticalSwipeRef.current) ignoreNextClickRef.current = true;
|
|
17155
|
+
touchStartRef.current = null;
|
|
17156
|
+
return;
|
|
17157
|
+
}
|
|
17158
|
+
const offset = slideOffset;
|
|
17159
|
+
if (isDragging || Math.abs(offset) > 10) {
|
|
17160
|
+
ignoreNextClickRef.current = true;
|
|
17161
|
+
}
|
|
17162
|
+
touchStartRef.current = null;
|
|
17163
|
+
if (Math.abs(offset) >= SWIPE_THRESHOLD) {
|
|
17164
|
+
if (offset < 0 && hasNext) {
|
|
17165
|
+
goToNext();
|
|
17166
|
+
} else if (offset > 0 && hasPrevious) {
|
|
17167
|
+
goToPrevious();
|
|
17168
|
+
} else {
|
|
17169
|
+
setSlideOffset(0);
|
|
17170
|
+
}
|
|
17171
|
+
} else {
|
|
17172
|
+
setSlideOffset(0);
|
|
17173
|
+
}
|
|
17174
|
+
setIsDragging(false);
|
|
17175
|
+
}, [slideOffset, hasNext, hasPrevious, goToNext, goToPrevious, isDragging]);
|
|
17176
|
+
const requestClose = modalContext?.close ?? onRequestClose;
|
|
17177
|
+
const handleBackgroundClick = useCallback(
|
|
17178
|
+
(event) => {
|
|
17179
|
+
if (event.target !== event.currentTarget) return;
|
|
17180
|
+
if (ignoreNextClickRef.current) {
|
|
17181
|
+
ignoreNextClickRef.current = false;
|
|
17182
|
+
return;
|
|
17183
|
+
}
|
|
17184
|
+
if (!closeOnBackgroundClick) return;
|
|
17185
|
+
requestClose?.();
|
|
17186
|
+
},
|
|
17187
|
+
[closeOnBackgroundClick, requestClose]
|
|
17188
|
+
);
|
|
17189
|
+
const mediaStyle = isDragging || slideOffset !== 0 && slideDirection === null ? { transform: `translateX(${slideOffset}px)` } : {};
|
|
17190
|
+
return /* @__PURE__ */ jsxs("div", { className: "str-chat__gallery", children: [
|
|
17191
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__main", children: [
|
|
17192
|
+
/* @__PURE__ */ jsx(GalleryHeader, { currentItem }),
|
|
17193
|
+
/* @__PURE__ */ jsx(
|
|
17194
|
+
NavButton,
|
|
17195
|
+
{
|
|
17196
|
+
"aria-label": t("Previous image"),
|
|
17197
|
+
className: clsx(
|
|
17198
|
+
"str-chat__gallery__nav-button--prev",
|
|
17199
|
+
!hasPrevious && "str-chat__gallery__nav-button--hidden"
|
|
17200
|
+
),
|
|
17201
|
+
disabled: !hasPrevious,
|
|
17202
|
+
onClick: handleGoToPrevious,
|
|
17203
|
+
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
17204
|
+
}
|
|
17205
|
+
),
|
|
17206
|
+
/* @__PURE__ */ jsx(
|
|
17207
|
+
"div",
|
|
17208
|
+
{
|
|
17209
|
+
className: "str-chat__gallery__slide-container",
|
|
17210
|
+
onClick: handleBackgroundClick,
|
|
17211
|
+
onTouchEnd: handleTouchEnd,
|
|
17212
|
+
onTouchMove: handleTouchMove,
|
|
17213
|
+
onTouchStart: handleTouchStart,
|
|
17214
|
+
ref: containerRef,
|
|
17215
|
+
children: /* @__PURE__ */ jsx(
|
|
17216
|
+
"div",
|
|
17217
|
+
{
|
|
17218
|
+
className: clsx({
|
|
17219
|
+
"str-chat__gallery__media--dragging": isDragging,
|
|
17220
|
+
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
17221
|
+
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
17222
|
+
}),
|
|
17223
|
+
style: mediaStyle,
|
|
17224
|
+
children: currentItem.videoUrl && currentItem.videoThumbnailUrl ? /* @__PURE__ */ jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--video", children: showVideo ? /* @__PURE__ */ jsx(VideoPlayer, { isPlaying: true, videoUrl: currentItem.videoUrl }) : /* @__PURE__ */ jsx(
|
|
17225
|
+
VideoThumbnail,
|
|
17226
|
+
{
|
|
17227
|
+
alt: currentItem.title ?? "",
|
|
17228
|
+
onPlay: () => setShowVideo(true),
|
|
17229
|
+
src: currentItem.videoThumbnailUrl
|
|
17230
|
+
}
|
|
17231
|
+
) }) : /* @__PURE__ */ jsx("div", { className: "str-chat__gallery__media str-chat__gallery__media--image", children: /* @__PURE__ */ jsx(BaseImage, { alt: currentItem.alt, src: currentItem.imageUrl }) })
|
|
17232
|
+
}
|
|
17233
|
+
)
|
|
17234
|
+
}
|
|
17235
|
+
),
|
|
17236
|
+
/* @__PURE__ */ jsx(
|
|
17237
|
+
NavButton,
|
|
17238
|
+
{
|
|
17239
|
+
"aria-label": t("Next image"),
|
|
17240
|
+
className: clsx(
|
|
17241
|
+
"str-chat__gallery__nav-button--next",
|
|
17242
|
+
!hasNext && "str-chat__gallery__nav-button--hidden"
|
|
17243
|
+
),
|
|
17244
|
+
disabled: !hasNext,
|
|
17245
|
+
onClick: handleGoToNext,
|
|
17246
|
+
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
17247
|
+
}
|
|
17248
|
+
)
|
|
17249
|
+
] }),
|
|
17250
|
+
itemCount > 1 && /* @__PURE__ */ jsxs("div", { className: "str-chat__gallery__position-indicator", children: [
|
|
17251
|
+
currentIndex + 1,
|
|
17252
|
+
" of ",
|
|
17253
|
+
itemCount
|
|
17254
|
+
] })
|
|
17255
|
+
] });
|
|
17256
|
+
};
|
|
17257
|
+
const NavButton = ({ className, ...props }) => /* @__PURE__ */ jsx(Button, { ...props, className: clsx("str-chat__gallery__nav-button", className) });
|
|
17258
|
+
const Gallery = ({
|
|
17259
|
+
closeOnBackgroundClick = true,
|
|
17260
|
+
GalleryUI: GalleryUI$1,
|
|
17261
|
+
initialIndex = 0,
|
|
17262
|
+
items,
|
|
17263
|
+
onIndexChange,
|
|
17264
|
+
onRequestClose
|
|
17265
|
+
}) => {
|
|
17266
|
+
const { GalleryUI: ContextGalleryUI } = useComponentContext();
|
|
17267
|
+
const ResolvedGalleryUI = GalleryUI$1 ?? ContextGalleryUI ?? GalleryUI;
|
|
17268
|
+
const [currentIndex, setCurrentIndex] = useState(initialIndex);
|
|
17269
|
+
const itemCount = items.length;
|
|
17270
|
+
const goToIndex = useCallback(
|
|
17271
|
+
(index) => {
|
|
17272
|
+
if (index >= 0 && index < itemCount) {
|
|
17273
|
+
setCurrentIndex(index);
|
|
17274
|
+
}
|
|
17275
|
+
},
|
|
17276
|
+
[itemCount]
|
|
17277
|
+
);
|
|
17278
|
+
const goToNext = useCallback(() => {
|
|
17279
|
+
setCurrentIndex((prev) => prev < itemCount - 1 ? prev + 1 : prev);
|
|
17280
|
+
}, [itemCount]);
|
|
17281
|
+
const goToPrevious = useCallback(() => {
|
|
17282
|
+
setCurrentIndex((prev) => prev > 0 ? prev - 1 : prev);
|
|
17283
|
+
}, []);
|
|
17284
|
+
useEffect(() => {
|
|
17285
|
+
onIndexChange?.(currentIndex);
|
|
17286
|
+
}, [currentIndex, onIndexChange]);
|
|
17287
|
+
const hasNext = currentIndex < itemCount - 1;
|
|
17288
|
+
const hasPrevious = currentIndex > 0;
|
|
17289
|
+
const currentItem = items[currentIndex];
|
|
17290
|
+
const contextValue = useMemo(
|
|
17291
|
+
() => ({
|
|
17292
|
+
closeOnBackgroundClick,
|
|
17293
|
+
currentIndex,
|
|
17294
|
+
currentItem,
|
|
17295
|
+
goToIndex,
|
|
17296
|
+
goToNext,
|
|
17297
|
+
goToPrevious,
|
|
17298
|
+
hasNext,
|
|
17299
|
+
hasPrevious,
|
|
17300
|
+
itemCount,
|
|
17301
|
+
items,
|
|
17302
|
+
onRequestClose
|
|
17303
|
+
}),
|
|
17304
|
+
[
|
|
17305
|
+
closeOnBackgroundClick,
|
|
17306
|
+
currentIndex,
|
|
17307
|
+
currentItem,
|
|
17308
|
+
goToIndex,
|
|
17309
|
+
goToNext,
|
|
17310
|
+
goToPrevious,
|
|
17311
|
+
hasNext,
|
|
17312
|
+
hasPrevious,
|
|
17313
|
+
itemCount,
|
|
17314
|
+
items,
|
|
17315
|
+
onRequestClose
|
|
17316
|
+
]
|
|
17317
|
+
);
|
|
17318
|
+
return /* @__PURE__ */ jsx(GalleryContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ResolvedGalleryUI, {}) });
|
|
17319
|
+
};
|
|
17123
17320
|
const AttachmentPreviewList = ({
|
|
17124
17321
|
AudioAttachmentPreview: AudioAttachmentPreview2 = FileAttachmentPreview,
|
|
17125
17322
|
FileAttachmentPreview: FileAttachmentPreview$1 = FileAttachmentPreview,
|
|
@@ -17128,73 +17325,107 @@ const AttachmentPreviewList = ({
|
|
|
17128
17325
|
VideoAttachmentPreview = MediaAttachmentPreview
|
|
17129
17326
|
}) => {
|
|
17130
17327
|
const messageComposer = useMessageComposerController();
|
|
17328
|
+
const { Modal = GlobalModal } = useComponentContext();
|
|
17329
|
+
const [showPreview, setShowPreview] = useState(false);
|
|
17330
|
+
const initialIndexRef = useRef(0);
|
|
17131
17331
|
const { attachments } = useAttachmentsForPreview();
|
|
17132
17332
|
const filteredAttachments = useMemo(
|
|
17133
17333
|
() => attachments.filter((a) => !isVoiceRecordingAttachment(a)),
|
|
17134
17334
|
[attachments]
|
|
17135
17335
|
);
|
|
17336
|
+
const { galleryItems, previewIndexById } = useMemo(() => {
|
|
17337
|
+
const items = [];
|
|
17338
|
+
const indexById = {};
|
|
17339
|
+
for (const a of attachments) {
|
|
17340
|
+
if (isLocalImageAttachment(a) || isLocalVideoAttachment(a)) {
|
|
17341
|
+
const descriptor = toBaseImageDescriptors(a);
|
|
17342
|
+
if (descriptor) {
|
|
17343
|
+
indexById[a.localMetadata.id] = items.length;
|
|
17344
|
+
items.push(descriptor);
|
|
17345
|
+
}
|
|
17346
|
+
}
|
|
17347
|
+
}
|
|
17348
|
+
return { galleryItems: items, previewIndexById: indexById };
|
|
17349
|
+
}, [attachments]);
|
|
17350
|
+
const openPreviewAtIndex = useCallback((index) => {
|
|
17351
|
+
initialIndexRef.current = index;
|
|
17352
|
+
setShowPreview(true);
|
|
17353
|
+
}, []);
|
|
17136
17354
|
if (!filteredAttachments.length) return null;
|
|
17137
|
-
return /* @__PURE__ */
|
|
17355
|
+
return /* @__PURE__ */ jsxs(
|
|
17138
17356
|
"div",
|
|
17139
17357
|
{
|
|
17140
17358
|
className: "str-chat__attachment-preview-list",
|
|
17141
17359
|
"data-testid": "attachment-preview-list",
|
|
17142
|
-
children:
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
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
|
-
|
|
17360
|
+
children: [
|
|
17361
|
+
attachments.map((attachment) => {
|
|
17362
|
+
if (isScrapedContent(attachment)) return null;
|
|
17363
|
+
if (isLocalVoiceRecordingAttachment(attachment)) return null;
|
|
17364
|
+
if (isLocalAudioAttachment(attachment)) {
|
|
17365
|
+
return /* @__PURE__ */ jsx(
|
|
17366
|
+
AudioAttachmentPreview2,
|
|
17367
|
+
{
|
|
17368
|
+
attachment,
|
|
17369
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17370
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17371
|
+
},
|
|
17372
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17373
|
+
);
|
|
17374
|
+
} else if (isLocalVideoAttachment(attachment)) {
|
|
17375
|
+
return /* @__PURE__ */ jsx(
|
|
17376
|
+
VideoAttachmentPreview,
|
|
17377
|
+
{
|
|
17378
|
+
attachment,
|
|
17379
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17380
|
+
openPreview: () => openPreviewAtIndex(previewIndexById[attachment.localMetadata.id] ?? 0),
|
|
17381
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17382
|
+
},
|
|
17383
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17384
|
+
);
|
|
17385
|
+
} else if (isLocalImageAttachment(attachment)) {
|
|
17386
|
+
return /* @__PURE__ */ jsx(
|
|
17387
|
+
ImageAttachmentPreview,
|
|
17388
|
+
{
|
|
17389
|
+
attachment,
|
|
17390
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17391
|
+
openPreview: () => openPreviewAtIndex(previewIndexById[attachment.localMetadata.id] ?? 0),
|
|
17392
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17393
|
+
},
|
|
17394
|
+
attachment.localMetadata.id || attachment.image_url
|
|
17395
|
+
);
|
|
17396
|
+
} else if (isLocalFileAttachment(attachment)) {
|
|
17397
|
+
return /* @__PURE__ */ jsx(
|
|
17398
|
+
FileAttachmentPreview$1,
|
|
17399
|
+
{
|
|
17400
|
+
attachment,
|
|
17401
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17402
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17403
|
+
},
|
|
17404
|
+
attachment.localMetadata.id || attachment.asset_url
|
|
17405
|
+
);
|
|
17406
|
+
} else if (isLocalAttachment(attachment)) {
|
|
17407
|
+
return /* @__PURE__ */ jsx(
|
|
17408
|
+
UnsupportedAttachmentPreview$1,
|
|
17409
|
+
{
|
|
17410
|
+
attachment,
|
|
17411
|
+
handleRetry: messageComposer.attachmentManager.uploadAttachment,
|
|
17412
|
+
removeAttachments: messageComposer.attachmentManager.removeAttachments
|
|
17413
|
+
},
|
|
17414
|
+
attachment.localMetadata.id
|
|
17415
|
+
);
|
|
17416
|
+
}
|
|
17417
|
+
return null;
|
|
17418
|
+
}),
|
|
17419
|
+
galleryItems.length > 0 && /* @__PURE__ */ jsx(
|
|
17420
|
+
Modal,
|
|
17421
|
+
{
|
|
17422
|
+
className: "str-chat__gallery-modal",
|
|
17423
|
+
onClose: () => setShowPreview(false),
|
|
17424
|
+
open: showPreview,
|
|
17425
|
+
children: /* @__PURE__ */ jsx(Gallery, { initialIndex: initialIndexRef.current, items: galleryItems })
|
|
17426
|
+
}
|
|
17427
|
+
)
|
|
17428
|
+
]
|
|
17198
17429
|
}
|
|
17199
17430
|
);
|
|
17200
17431
|
};
|
|
@@ -17222,11 +17453,9 @@ const VoiceRecordingPreviewSlot = ({
|
|
|
17222
17453
|
}
|
|
17223
17454
|
);
|
|
17224
17455
|
};
|
|
17225
|
-
const
|
|
17226
|
-
const CommandChip = () => {
|
|
17456
|
+
const CommandChip = ({ command }) => {
|
|
17227
17457
|
const { textComposer } = useMessageComposerController();
|
|
17228
17458
|
const { textareaRef } = useMessageComposerContext();
|
|
17229
|
-
const { command } = useStateStore(textComposer.state, textComposerStateSelector$4);
|
|
17230
17459
|
if (!command) return null;
|
|
17231
17460
|
return /* @__PURE__ */ jsxs("div", { className: "str-chat__command-chip", children: [
|
|
17232
17461
|
/* @__PURE__ */ jsx(IconThunder, {}),
|
|
@@ -17525,9 +17754,12 @@ const ToggleRecordingButton = () => {
|
|
|
17525
17754
|
);
|
|
17526
17755
|
};
|
|
17527
17756
|
const AudioRecorderRecordingControls = () => {
|
|
17757
|
+
const { client } = useChatContext();
|
|
17758
|
+
const { t } = useTranslationContext();
|
|
17528
17759
|
const {
|
|
17529
17760
|
recordingController: { completeRecording, recorder, recording, recordingState }
|
|
17530
17761
|
} = useMessageComposerContext();
|
|
17762
|
+
const panel = useNotificationTarget();
|
|
17531
17763
|
const isUploadingFile = recording?.localMetadata?.uploadState === "uploading";
|
|
17532
17764
|
if (!recorder) return null;
|
|
17533
17765
|
return /* @__PURE__ */ jsxs("div", { className: "str-chat__audio_recorder__recording-controls", children: [
|
|
@@ -17539,7 +17771,17 @@ const AudioRecorderRecordingControls = () => {
|
|
|
17539
17771
|
className: "str-chat__audio_recorder__cancel-button",
|
|
17540
17772
|
"data-testid": "cancel-recording-audio-button",
|
|
17541
17773
|
disabled: isUploadingFile,
|
|
17542
|
-
onClick:
|
|
17774
|
+
onClick: () => {
|
|
17775
|
+
recorder.cancel();
|
|
17776
|
+
client.notifications.addInfo({
|
|
17777
|
+
message: t("Voice message deleted"),
|
|
17778
|
+
options: {
|
|
17779
|
+
tags: addNotificationTargetTag(panel),
|
|
17780
|
+
type: "audioRecording:cancel:success"
|
|
17781
|
+
},
|
|
17782
|
+
origin: { emitter: "AudioRecorder" }
|
|
17783
|
+
});
|
|
17784
|
+
},
|
|
17543
17785
|
size: "sm",
|
|
17544
17786
|
variant: "secondary",
|
|
17545
17787
|
children: /* @__PURE__ */ jsx(IconTrashBin, {})
|
|
@@ -17846,7 +18088,10 @@ const SuggestionList = ({
|
|
|
17846
18088
|
setFocusedItemIndex,
|
|
17847
18089
|
suggestionItemComponents = defaultComponents
|
|
17848
18090
|
}) => {
|
|
17849
|
-
const {
|
|
18091
|
+
const {
|
|
18092
|
+
AutocompleteSuggestionItem = SuggestionListItem,
|
|
18093
|
+
ContextMenu: ContextMenuComponent = ContextMenu
|
|
18094
|
+
} = useComponentContext();
|
|
17850
18095
|
const { textareaRef } = useMessageComposerContext();
|
|
17851
18096
|
const messageComposer = useMessageComposerController();
|
|
17852
18097
|
const { textComposer } = messageComposer;
|
|
@@ -17964,7 +18209,7 @@ const SuggestionList = ({
|
|
|
17964
18209
|
zIndex: 1e3
|
|
17965
18210
|
},
|
|
17966
18211
|
children: /* @__PURE__ */ jsx(
|
|
17967
|
-
|
|
18212
|
+
ContextMenuComponent,
|
|
17968
18213
|
{
|
|
17969
18214
|
className: clsx("str-chat__suggestion-list", className),
|
|
17970
18215
|
Header: suggestions.searchSource.type === "commands" ? CommandsMenuHeader : void 0,
|
|
@@ -18063,6 +18308,12 @@ const TextareaComposer = ({
|
|
|
18063
18308
|
textComposer.state,
|
|
18064
18309
|
textComposerStateSelector$1
|
|
18065
18310
|
);
|
|
18311
|
+
const autosizeRows = !text2 && minRows == null ? 1 : void 0;
|
|
18312
|
+
const textareaStyle = text2 ? void 0 : {
|
|
18313
|
+
overflow: "hidden",
|
|
18314
|
+
textOverflow: "ellipsis",
|
|
18315
|
+
whiteSpace: "nowrap"
|
|
18316
|
+
};
|
|
18066
18317
|
const { enabled } = useStateStore(messageComposer.configState, configStateSelector);
|
|
18067
18318
|
const { quotedMessage } = useStateStore(
|
|
18068
18319
|
messageComposer.state,
|
|
@@ -18216,8 +18467,8 @@ const TextareaComposer = ({
|
|
|
18216
18467
|
),
|
|
18217
18468
|
"data-testid": "message-input",
|
|
18218
18469
|
disabled: !enabled || !!cooldownRemaining,
|
|
18219
|
-
maxRows,
|
|
18220
|
-
minRows,
|
|
18470
|
+
maxRows: autosizeRows ?? maxRows,
|
|
18471
|
+
minRows: autosizeRows ?? minRows,
|
|
18221
18472
|
onBlur,
|
|
18222
18473
|
onChange: changeHandler,
|
|
18223
18474
|
onCompositionEnd,
|
|
@@ -18229,7 +18480,8 @@ const TextareaComposer = ({
|
|
|
18229
18480
|
placeholder,
|
|
18230
18481
|
ref: (ref) => {
|
|
18231
18482
|
textareaRef.current = ref;
|
|
18232
|
-
}
|
|
18483
|
+
},
|
|
18484
|
+
style: textareaStyle
|
|
18233
18485
|
}
|
|
18234
18486
|
),
|
|
18235
18487
|
!isComposing && /* @__PURE__ */ jsx(
|
|
@@ -18561,7 +18813,7 @@ const MessageComposerUI = () => {
|
|
|
18561
18813
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__message-composer-controls", children: [
|
|
18562
18814
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__message-composer-controls__text-composition-controls", children: [
|
|
18563
18815
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__message-composer-controls__text-composition-controls__text", children: [
|
|
18564
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-composer-controls__text-composition-controls__command-chip-container", children: /* @__PURE__ */ jsx(CommandChip$1, {}) }),
|
|
18816
|
+
command && /* @__PURE__ */ jsx("div", { className: "str-chat__message-composer-controls__text-composition-controls__command-chip-container", children: /* @__PURE__ */ jsx(CommandChip$1, { command }) }),
|
|
18565
18817
|
/* @__PURE__ */ jsx(TextareaComposer$1, {})
|
|
18566
18818
|
] }),
|
|
18567
18819
|
/* @__PURE__ */ jsx(SendToChannelCheckbox$1, {})
|
|
@@ -18636,7 +18888,7 @@ const MessageComposerProvider = (props) => {
|
|
|
18636
18888
|
const messageComposer = useMessageComposerController();
|
|
18637
18889
|
useEffect(
|
|
18638
18890
|
() => () => {
|
|
18639
|
-
messageComposer.createDraft();
|
|
18891
|
+
messageComposer.createDraft().finally(() => messageComposer.clear());
|
|
18640
18892
|
},
|
|
18641
18893
|
[messageComposer]
|
|
18642
18894
|
);
|
|
@@ -18954,7 +19206,7 @@ const useChat = ({
|
|
|
18954
19206
|
};
|
|
18955
19207
|
useEffect(() => {
|
|
18956
19208
|
if (!client) return;
|
|
18957
|
-
const version = "14.0.0-beta.
|
|
19209
|
+
const version = "14.0.0-beta.3";
|
|
18958
19210
|
const userAgent = client.getUserAgent();
|
|
18959
19211
|
if (!userAgent.includes("stream-chat-react")) {
|
|
18960
19212
|
client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
|
|
@@ -19455,13 +19707,13 @@ const ReactionSelector = (props) => {
|
|
|
19455
19707
|
) })
|
|
19456
19708
|
] });
|
|
19457
19709
|
};
|
|
19458
|
-
ReactionSelector.getDialogId = (
|
|
19710
|
+
ReactionSelector.getDialogId = ({ messageId, threadList }) => {
|
|
19459
19711
|
const dialogIdNamespace = threadList ? "-thread" : "";
|
|
19460
|
-
return `reaction-selector${dialogIdNamespace}
|
|
19461
|
-
}
|
|
19712
|
+
return `reaction-selector${dialogIdNamespace}-${messageId}`;
|
|
19713
|
+
};
|
|
19462
19714
|
ReactionSelector.displayName = "ReactionSelector";
|
|
19463
19715
|
const ReactionSelectorWithButton = ({
|
|
19464
|
-
ReactionIcon
|
|
19716
|
+
ReactionIcon
|
|
19465
19717
|
}) => {
|
|
19466
19718
|
const { t } = useTranslationContext("ReactionSelectorWithButton");
|
|
19467
19719
|
const { isMyMessage, message, threadList } = useMessageContext();
|
|
@@ -19495,7 +19747,7 @@ const ReactionSelectorWithButton = ({
|
|
|
19495
19747
|
"data-testid": "message-reaction-action",
|
|
19496
19748
|
onClick: () => dialog?.toggle(),
|
|
19497
19749
|
ref: buttonRef,
|
|
19498
|
-
children: /* @__PURE__ */ jsx(
|
|
19750
|
+
children: /* @__PURE__ */ jsx(ReactionIcon, { className: "str-chat__message-action-icon" })
|
|
19499
19751
|
}
|
|
19500
19752
|
)
|
|
19501
19753
|
] });
|
|
@@ -19543,6 +19795,7 @@ const QuickMessageActionsButton = ({ className, ...props }) => /* @__PURE__ */ j
|
|
|
19543
19795
|
appearance: "ghost",
|
|
19544
19796
|
circular: true,
|
|
19545
19797
|
className: clsx("str-chat__message-actions-box-button", className),
|
|
19798
|
+
size: "sm",
|
|
19546
19799
|
variant: "secondary",
|
|
19547
19800
|
...props
|
|
19548
19801
|
}
|
|
@@ -19832,8 +20085,7 @@ const DefaultMessageActionComponents = {
|
|
|
19832
20085
|
const { closeMenu } = useContextMenuContext();
|
|
19833
20086
|
const { client } = useChatContext();
|
|
19834
20087
|
const { Modal = GlobalModal } = useComponentContext();
|
|
19835
|
-
const {
|
|
19836
|
-
const { handleDelete, message } = useMessageContext();
|
|
20088
|
+
const { handleDelete } = useMessageContext();
|
|
19837
20089
|
const panel = useNotificationTarget();
|
|
19838
20090
|
const { t } = useTranslationContext();
|
|
19839
20091
|
const [openModal, setOpenModal] = useState(false);
|
|
@@ -19859,29 +20111,20 @@ const DefaultMessageActionComponents = {
|
|
|
19859
20111
|
closeMenu();
|
|
19860
20112
|
},
|
|
19861
20113
|
onDelete: async () => {
|
|
19862
|
-
|
|
19863
|
-
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19871
|
-
|
|
19872
|
-
|
|
19873
|
-
|
|
19874
|
-
|
|
19875
|
-
message: t("Failed to delete the message"),
|
|
19876
|
-
options: {
|
|
19877
|
-
tags: addNotificationTargetTag(panel)
|
|
19878
|
-
},
|
|
19879
|
-
origin: { emitter: "MessageActions" }
|
|
19880
|
-
});
|
|
19881
|
-
}
|
|
20114
|
+
try {
|
|
20115
|
+
await handleDelete();
|
|
20116
|
+
client.notifications.addSuccess({
|
|
20117
|
+
message: t("Message deleted"),
|
|
20118
|
+
options: {
|
|
20119
|
+
tags: addNotificationTargetTag(panel)
|
|
20120
|
+
},
|
|
20121
|
+
origin: { emitter: "MessageActions" }
|
|
20122
|
+
});
|
|
20123
|
+
} catch {
|
|
20124
|
+
} finally {
|
|
20125
|
+
setOpenModal(false);
|
|
20126
|
+
closeMenu();
|
|
19882
20127
|
}
|
|
19883
|
-
setOpenModal(false);
|
|
19884
|
-
closeMenu();
|
|
19885
20128
|
}
|
|
19886
20129
|
}
|
|
19887
20130
|
) })
|
|
@@ -19913,8 +20156,34 @@ const DefaultMessageActionComponents = {
|
|
|
19913
20156
|
}
|
|
19914
20157
|
},
|
|
19915
20158
|
quick: {
|
|
20159
|
+
// eslint-disable-next-line react/display-name
|
|
20160
|
+
DropdownToggle: forwardRef((_, ref) => {
|
|
20161
|
+
const { t } = useTranslationContext();
|
|
20162
|
+
const { message } = useMessageContext();
|
|
20163
|
+
const dropdownDialogIsOpen = useDialogIsOpen(
|
|
20164
|
+
MessageActions.getDialogId({ messageId: message.id })
|
|
20165
|
+
);
|
|
20166
|
+
const { dialog } = useDialogOnNearestManager({
|
|
20167
|
+
id: MessageActions.getDialogId({ messageId: message.id })
|
|
20168
|
+
});
|
|
20169
|
+
return /* @__PURE__ */ jsx(
|
|
20170
|
+
QuickMessageActionsButton,
|
|
20171
|
+
{
|
|
20172
|
+
"aria-expanded": dropdownDialogIsOpen,
|
|
20173
|
+
"aria-haspopup": "true",
|
|
20174
|
+
"aria-label": t("aria/Open Message Actions Menu"),
|
|
20175
|
+
className: "str-chat__message-actions-box-button",
|
|
20176
|
+
"data-testid": "message-actions-toggle-button",
|
|
20177
|
+
onClick: () => {
|
|
20178
|
+
dialog?.toggle();
|
|
20179
|
+
},
|
|
20180
|
+
ref,
|
|
20181
|
+
children: /* @__PURE__ */ jsx(IconDotGrid1x3Horizontal, { className: "str-chat__message-action-icon" })
|
|
20182
|
+
}
|
|
20183
|
+
);
|
|
20184
|
+
}),
|
|
19916
20185
|
React() {
|
|
19917
|
-
return /* @__PURE__ */ jsx(ReactionSelectorWithButton, { ReactionIcon });
|
|
20186
|
+
return /* @__PURE__ */ jsx(ReactionSelectorWithButton, { ReactionIcon: IconEmojiSmile });
|
|
19918
20187
|
},
|
|
19919
20188
|
Reply() {
|
|
19920
20189
|
const { handleOpenThread } = useMessageContext();
|
|
@@ -19926,14 +20195,17 @@ const DefaultMessageActionComponents = {
|
|
|
19926
20195
|
className: "str-chat__message-reply-in-thread-button",
|
|
19927
20196
|
"data-testid": "thread-action",
|
|
19928
20197
|
onClick: handleOpenThread,
|
|
19929
|
-
children: /* @__PURE__ */ jsx(
|
|
20198
|
+
children: /* @__PURE__ */ jsx(IconArrowShareLeft, { className: "str-chat__message-action-icon" })
|
|
19930
20199
|
}
|
|
19931
20200
|
);
|
|
19932
20201
|
}
|
|
19933
20202
|
}
|
|
19934
20203
|
};
|
|
19935
20204
|
const defaultMessageActionSet = [
|
|
19936
|
-
|
|
20205
|
+
{
|
|
20206
|
+
Component: DefaultMessageActionComponents.quick.DropdownToggle,
|
|
20207
|
+
placement: "quick-dropdown-toggle"
|
|
20208
|
+
},
|
|
19937
20209
|
{
|
|
19938
20210
|
Component: DefaultMessageActionComponents.quick.Reply,
|
|
19939
20211
|
placement: "quick",
|
|
@@ -20023,14 +20295,14 @@ function useFetchReactions(options) {
|
|
|
20023
20295
|
const handleFetchReactions = propHandleFetchReactions ?? contextHandleFetchReactions;
|
|
20024
20296
|
const [refetchNonce, setRefetchNonce] = useState(null);
|
|
20025
20297
|
useEffect(() => {
|
|
20026
|
-
if (!shouldFetch
|
|
20298
|
+
if (!shouldFetch) {
|
|
20027
20299
|
return;
|
|
20028
20300
|
}
|
|
20029
20301
|
let cancel = false;
|
|
20030
20302
|
(async () => {
|
|
20031
20303
|
try {
|
|
20032
20304
|
setIsLoading(true);
|
|
20033
|
-
const reactions2 = await handleFetchReactions(reactionType, sort);
|
|
20305
|
+
const reactions2 = await handleFetchReactions(reactionType ?? void 0, sort);
|
|
20034
20306
|
if (!cancel) {
|
|
20035
20307
|
setReactions(reactions2);
|
|
20036
20308
|
}
|
|
@@ -20054,6 +20326,16 @@ function useFetchReactions(options) {
|
|
|
20054
20326
|
return { isLoading, reactions, refetch };
|
|
20055
20327
|
}
|
|
20056
20328
|
const defaultReactionDetailsSort = { created_at: -1 };
|
|
20329
|
+
const MessageReactionsDetailLoadingIndicator = () => {
|
|
20330
|
+
const elements = useMemo(
|
|
20331
|
+
() => Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20332
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20333
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20334
|
+
] }, index)),
|
|
20335
|
+
[]
|
|
20336
|
+
);
|
|
20337
|
+
return /* @__PURE__ */ jsx(Fragment, { children: elements });
|
|
20338
|
+
};
|
|
20057
20339
|
function MessageReactionsDetail({
|
|
20058
20340
|
handleFetchReactions,
|
|
20059
20341
|
onSelectedReactionTypeChange,
|
|
@@ -20064,7 +20346,11 @@ function MessageReactionsDetail({
|
|
|
20064
20346
|
totalReactionCount
|
|
20065
20347
|
}) {
|
|
20066
20348
|
const { client } = useChatContext();
|
|
20067
|
-
const {
|
|
20349
|
+
const {
|
|
20350
|
+
Avatar: Avatar$1 = Avatar,
|
|
20351
|
+
LoadingIndicator: LoadingIndicator2 = MessageReactionsDetailLoadingIndicator,
|
|
20352
|
+
reactionOptions = defaultReactionOptions
|
|
20353
|
+
} = useComponentContext(MessageReactionsDetail.name);
|
|
20068
20354
|
const { t } = useTranslationContext();
|
|
20069
20355
|
const {
|
|
20070
20356
|
handleReaction: contextHandleReaction,
|
|
@@ -20091,7 +20377,7 @@ function MessageReactionsDetail({
|
|
|
20091
20377
|
"div",
|
|
20092
20378
|
{
|
|
20093
20379
|
className: "str-chat__message-reactions-detail",
|
|
20094
|
-
"data-testid": "reactions-
|
|
20380
|
+
"data-testid": "message-reactions-detail",
|
|
20095
20381
|
children: [
|
|
20096
20382
|
typeof totalReactionCount === "number" && /* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__total-count", children: t("{{ count }} reactions", { count: totalReactionCount }) }),
|
|
20097
20383
|
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__reaction-type-list-container", children: /* @__PURE__ */ jsx("ul", { className: "str-chat__message-reactions-detail__reaction-type-list", children: reactions.map(
|
|
@@ -20104,7 +20390,9 @@ function MessageReactionsDetail({
|
|
|
20104
20390
|
{
|
|
20105
20391
|
"aria-pressed": reactionType === selectedReactionType,
|
|
20106
20392
|
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20107
|
-
onClick: () => onSelectedReactionTypeChange?.(
|
|
20393
|
+
onClick: () => onSelectedReactionTypeChange?.(
|
|
20394
|
+
selectedReactionType === reactionType ? null : reactionType
|
|
20395
|
+
),
|
|
20108
20396
|
children: [
|
|
20109
20397
|
/* @__PURE__ */ jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsx(EmojiComponent, {}) }),
|
|
20110
20398
|
reactionCount > 1 && /* @__PURE__ */ jsx(
|
|
@@ -20128,22 +20416,10 @@ function MessageReactionsDetail({
|
|
|
20128
20416
|
className: "str-chat__message-reactions-detail__user-list",
|
|
20129
20417
|
"data-testid": "all-reacting-users",
|
|
20130
20418
|
children: [
|
|
20131
|
-
areReactionsLoading && /* @__PURE__ */
|
|
20132
|
-
|
|
20133
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20134
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20135
|
-
] }),
|
|
20136
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20137
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20138
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20139
|
-
] }),
|
|
20140
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
20141
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
20142
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
20143
|
-
] })
|
|
20144
|
-
] }),
|
|
20145
|
-
!areReactionsLoading && /* @__PURE__ */ jsx(Fragment, { children: reactionDetailsWithLegacyFallback.map(({ user }) => {
|
|
20419
|
+
areReactionsLoading && /* @__PURE__ */ jsx(LoadingIndicator2, {}),
|
|
20420
|
+
!areReactionsLoading && /* @__PURE__ */ jsx(Fragment, { children: reactionDetailsWithLegacyFallback.map(({ type, user }) => {
|
|
20146
20421
|
const belongsToCurrentUser = client.user?.id === user?.id;
|
|
20422
|
+
const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
|
|
20147
20423
|
return /* @__PURE__ */ jsxs(
|
|
20148
20424
|
"div",
|
|
20149
20425
|
{
|
|
@@ -20168,23 +20444,23 @@ function MessageReactionsDetail({
|
|
|
20168
20444
|
children: belongsToCurrentUser ? t("You") : user?.name || user?.id
|
|
20169
20445
|
}
|
|
20170
20446
|
),
|
|
20171
|
-
belongsToCurrentUser &&
|
|
20447
|
+
belongsToCurrentUser && /* @__PURE__ */ jsx(
|
|
20172
20448
|
"button",
|
|
20173
20449
|
{
|
|
20174
20450
|
className: "str-chat__message-reactions-detail__user-list-item-button",
|
|
20175
20451
|
"data-testid": "remove-reaction-button",
|
|
20176
|
-
onClick: (e) => {
|
|
20177
|
-
contextHandleReaction(
|
|
20178
|
-
|
|
20179
|
-
});
|
|
20452
|
+
onClick: async (e) => {
|
|
20453
|
+
await contextHandleReaction(type, e);
|
|
20454
|
+
refetch();
|
|
20180
20455
|
},
|
|
20181
20456
|
children: t("Tap to remove")
|
|
20182
20457
|
}
|
|
20183
20458
|
)
|
|
20184
|
-
] })
|
|
20459
|
+
] }),
|
|
20460
|
+
/* @__PURE__ */ jsx("span", { className: "str-chat__message-reactions-detail__user-list-item-icon", children: EmojiComponent && !selectedReactionType && /* @__PURE__ */ jsx(EmojiComponent, {}) })
|
|
20185
20461
|
]
|
|
20186
20462
|
},
|
|
20187
|
-
user?.id
|
|
20463
|
+
`${user?.id}-${type}`
|
|
20188
20464
|
);
|
|
20189
20465
|
}) })
|
|
20190
20466
|
]
|
|
@@ -20333,6 +20609,7 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20333
20609
|
const divRef = useRef(null);
|
|
20334
20610
|
const dialogId2 = `message-reactions-detail-${message.id}`;
|
|
20335
20611
|
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
20612
|
+
const isDialogOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20336
20613
|
const handleReactionButtonClick = (reactionType) => {
|
|
20337
20614
|
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
|
|
20338
20615
|
return;
|
|
@@ -20367,6 +20644,8 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20367
20644
|
children: /* @__PURE__ */ jsxs(
|
|
20368
20645
|
FragmentOrButton,
|
|
20369
20646
|
{
|
|
20647
|
+
"aria-expanded": isDialogOpen,
|
|
20648
|
+
"aria-pressed": isDialogOpen,
|
|
20370
20649
|
buttonIf: visualStyle === "clustered",
|
|
20371
20650
|
className: "str-chat__message-reactions__list-button",
|
|
20372
20651
|
onClick: () => handleReactionButtonClick(existingReactions[0]?.reactionType ?? null),
|
|
@@ -20404,9 +20683,7 @@ const UnMemoizedMessageReactions = (props) => {
|
|
|
20404
20683
|
"button",
|
|
20405
20684
|
{
|
|
20406
20685
|
className: "str-chat__message-reactions__list-item-button",
|
|
20407
|
-
onClick: () => handleReactionButtonClick(
|
|
20408
|
-
existingReactions.at(-1)?.reactionType ?? null
|
|
20409
|
-
),
|
|
20686
|
+
onClick: () => handleReactionButtonClick(null),
|
|
20410
20687
|
children: /* @__PURE__ */ jsxs("span", { className: "str-chat__message-reactions__overflow-count", children: [
|
|
20411
20688
|
"+",
|
|
20412
20689
|
totalReactionCount - cappedExistingReactions.reactionCountToDisplay
|
|
@@ -20531,91 +20808,74 @@ const StreamEmoji = ({
|
|
|
20531
20808
|
const useSplitActionSet = (actionSet) => useMemo(() => {
|
|
20532
20809
|
const quickActionSet = [];
|
|
20533
20810
|
const dropdownActionSet = [];
|
|
20811
|
+
let quickDropdownToggleAction;
|
|
20534
20812
|
for (const action of actionSet) {
|
|
20535
20813
|
if (action.placement === "quick")
|
|
20536
20814
|
quickActionSet.push(action);
|
|
20537
20815
|
if (action.placement === "dropdown")
|
|
20538
20816
|
dropdownActionSet.push(action);
|
|
20817
|
+
if (action.placement === "quick-dropdown-toggle") {
|
|
20818
|
+
quickDropdownToggleAction ?? (quickDropdownToggleAction = action);
|
|
20819
|
+
}
|
|
20539
20820
|
}
|
|
20540
|
-
return { dropdownActionSet, quickActionSet };
|
|
20821
|
+
return { dropdownActionSet, quickActionSet, quickDropdownToggleAction };
|
|
20541
20822
|
}, [actionSet]);
|
|
20542
20823
|
const MessageActions = ({
|
|
20543
20824
|
disableBaseMessageActionSetFilter = false,
|
|
20544
20825
|
messageActionSet = defaultMessageActionSet
|
|
20545
20826
|
}) => {
|
|
20546
|
-
const { theme } = useChatContext();
|
|
20547
20827
|
const { isMyMessage, message, threadList } = useMessageContext();
|
|
20828
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu } = useComponentContext();
|
|
20548
20829
|
const { t } = useTranslationContext();
|
|
20549
20830
|
const [actionsBoxButtonElement, setActionsBoxButtonElement] = useState(null);
|
|
20550
20831
|
const filteredMessageActionSet = useBaseMessageActionSetFilter(
|
|
20551
20832
|
messageActionSet,
|
|
20552
20833
|
disableBaseMessageActionSetFilter
|
|
20553
20834
|
);
|
|
20554
|
-
const { dropdownActionSet, quickActionSet } = useSplitActionSet(
|
|
20555
|
-
|
|
20556
|
-
);
|
|
20557
|
-
const dropdownDialogId = `message-actions--${message.id}`;
|
|
20835
|
+
const { dropdownActionSet, quickActionSet, quickDropdownToggleAction } = useSplitActionSet(filteredMessageActionSet);
|
|
20836
|
+
const messageActionsDialogId = MessageActions.getDialogId({ messageId: message.id });
|
|
20558
20837
|
const reactionSelectorDialogId = ReactionSelector.getDialogId({
|
|
20559
20838
|
messageId: message.id,
|
|
20560
20839
|
threadList
|
|
20561
20840
|
});
|
|
20562
|
-
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
20563
|
-
|
|
20841
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
20842
|
+
id: messageActionsDialogId
|
|
20843
|
+
});
|
|
20844
|
+
const messageActionsDialogIsOpen = useDialogIsOpen(
|
|
20845
|
+
messageActionsDialogId,
|
|
20846
|
+
dialogManager?.id
|
|
20847
|
+
);
|
|
20564
20848
|
const reactionSelectorDialogIsOpen = useDialogIsOpen(
|
|
20565
20849
|
reactionSelectorDialogId,
|
|
20566
20850
|
dialogManager?.id
|
|
20567
20851
|
);
|
|
20568
|
-
const contextMenuItems = useMemo(
|
|
20569
|
-
() => dropdownActionSet.map(({ Component: Component2 }) => {
|
|
20570
|
-
const ActionItem = (menuProps) => /* @__PURE__ */ jsx(Component2, { ...menuProps });
|
|
20571
|
-
return ActionItem;
|
|
20572
|
-
}),
|
|
20573
|
-
[dropdownActionSet]
|
|
20574
|
-
);
|
|
20575
20852
|
if (dropdownActionSet.length + quickActionSet.length === 0) {
|
|
20576
20853
|
return null;
|
|
20577
20854
|
}
|
|
20578
20855
|
return /* @__PURE__ */ jsxs(
|
|
20579
20856
|
"div",
|
|
20580
20857
|
{
|
|
20581
|
-
className: clsx(
|
|
20582
|
-
"str-chat__message-options--active":
|
|
20858
|
+
className: clsx("str-chat__message-options", {
|
|
20859
|
+
"str-chat__message-options--active": messageActionsDialogIsOpen || reactionSelectorDialogIsOpen
|
|
20583
20860
|
}),
|
|
20584
20861
|
children: [
|
|
20585
|
-
dropdownActionSet.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20586
|
-
/* @__PURE__ */ jsx(
|
|
20587
|
-
Button,
|
|
20588
|
-
{
|
|
20589
|
-
appearance: "ghost",
|
|
20590
|
-
"aria-expanded": dropdownDialogIsOpen,
|
|
20591
|
-
"aria-haspopup": "true",
|
|
20592
|
-
"aria-label": t("aria/Open Message Actions Menu"),
|
|
20593
|
-
circular: true,
|
|
20594
|
-
className: "str-chat__message-actions-box-button",
|
|
20595
|
-
"data-testid": "message-actions-toggle-button",
|
|
20596
|
-
onClick: () => {
|
|
20597
|
-
dialog?.toggle();
|
|
20598
|
-
},
|
|
20599
|
-
ref: setActionsBoxButtonElement,
|
|
20600
|
-
variant: "secondary",
|
|
20601
|
-
children: /* @__PURE__ */ jsx(ActionsIcon, { className: "str-chat__message-action-icon" })
|
|
20602
|
-
}
|
|
20603
|
-
),
|
|
20862
|
+
quickDropdownToggleAction && dropdownActionSet.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20863
|
+
/* @__PURE__ */ jsx(quickDropdownToggleAction.Component, { ref: setActionsBoxButtonElement }),
|
|
20604
20864
|
/* @__PURE__ */ jsx(
|
|
20605
|
-
|
|
20865
|
+
ContextMenuComponent,
|
|
20606
20866
|
{
|
|
20607
20867
|
backLabel: t("Back"),
|
|
20608
20868
|
className: clsx("str-chat__message-actions-box", {
|
|
20609
|
-
"str-chat__message-actions-box--open":
|
|
20869
|
+
"str-chat__message-actions-box--open": messageActionsDialogIsOpen
|
|
20610
20870
|
}),
|
|
20611
20871
|
dialogManagerId: dialogManager?.id,
|
|
20612
|
-
id:
|
|
20613
|
-
items: contextMenuItems,
|
|
20872
|
+
id: messageActionsDialogId,
|
|
20614
20873
|
onClose: dialog?.close,
|
|
20615
20874
|
placement: isMyMessage() ? "top-end" : "top-start",
|
|
20616
20875
|
referenceElement: actionsBoxButtonElement,
|
|
20617
20876
|
tabIndex: -1,
|
|
20618
|
-
trapFocus: true
|
|
20877
|
+
trapFocus: true,
|
|
20878
|
+
children: dropdownActionSet.map(({ Component: Component2, type }) => /* @__PURE__ */ jsx(Component2, {}, type))
|
|
20619
20879
|
}
|
|
20620
20880
|
)
|
|
20621
20881
|
] }),
|
|
@@ -20624,6 +20884,8 @@ const MessageActions = ({
|
|
|
20624
20884
|
}
|
|
20625
20885
|
);
|
|
20626
20886
|
};
|
|
20887
|
+
MessageActions.getDialogId = ({ messageId }) => `message-actions-${messageId}`;
|
|
20888
|
+
MessageActions.displayName = "MessageActions";
|
|
20627
20889
|
const MessageUIWithContext = ({
|
|
20628
20890
|
endOfGroup,
|
|
20629
20891
|
firstOfGroup,
|
|
@@ -20787,7 +21049,7 @@ const MessageUIWithContext = ({
|
|
|
20787
21049
|
isAIGenerated ? /* @__PURE__ */ jsx(StreamedMessageText$1, { message, renderText: renderText2 }) : /* @__PURE__ */ jsx(MessageText, { message, renderText: renderText2 })
|
|
20788
21050
|
] }),
|
|
20789
21051
|
/* @__PURE__ */ jsx("div", { className: "str-chat__message-reactions-host", children: hasReactions && /* @__PURE__ */ jsx(MessageReactions$1, { reverse: true }) }),
|
|
20790
|
-
/* @__PURE__ */ jsx(
|
|
21052
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__message-error-indicator", children: /* @__PURE__ */ jsx(ErrorBadge, {}) })
|
|
20791
21053
|
] })
|
|
20792
21054
|
]
|
|
20793
21055
|
}
|
|
@@ -21450,6 +21712,7 @@ const useScrollLocationLogic = (params) => {
|
|
|
21450
21712
|
const closeToBottom = useRef(false);
|
|
21451
21713
|
const closeToTop = useRef(false);
|
|
21452
21714
|
const previousScrollTopRef = useRef(0);
|
|
21715
|
+
const previousMessagesLengthRef = useRef(messages.length);
|
|
21453
21716
|
const anchorRestoreCleanupRef = useRef(null);
|
|
21454
21717
|
const captureAnchor = useCallback(() => {
|
|
21455
21718
|
if (!listElement) return null;
|
|
@@ -21601,6 +21864,60 @@ const useScrollLocationLogic = (params) => {
|
|
|
21601
21864
|
scrollToBottom();
|
|
21602
21865
|
}
|
|
21603
21866
|
}, [disableAutoScrollToBottom, justReachedLatestMessageSet, listElement, hasMoreNewer]);
|
|
21867
|
+
useLayoutEffect(() => {
|
|
21868
|
+
if (!listElement || disableAutoScrollToBottom || hasMoreNewer || suppressAutoscroll || justReachedLatestMessageSet || isRestoringOlderAnchorRef.current) {
|
|
21869
|
+
return;
|
|
21870
|
+
}
|
|
21871
|
+
const initialDistanceToBottom = listElement.scrollHeight - (listElement.scrollTop + listElement.clientHeight);
|
|
21872
|
+
const messagesHydrated = previousMessagesLengthRef.current === 0 && messages.length > 0;
|
|
21873
|
+
if (initialDistanceToBottom > scrolledUpThreshold && !messagesHydrated) {
|
|
21874
|
+
return;
|
|
21875
|
+
}
|
|
21876
|
+
let keepPinnedToBottom = true;
|
|
21877
|
+
const maybeScrollToBottom = () => {
|
|
21878
|
+
if (keepPinnedToBottom) {
|
|
21879
|
+
scrollToBottom();
|
|
21880
|
+
}
|
|
21881
|
+
};
|
|
21882
|
+
maybeScrollToBottom();
|
|
21883
|
+
const settleDelays = [80, messagesHydrated ? 260 : 420, 900, 1700];
|
|
21884
|
+
const settleTimeoutIds = settleDelays.map(
|
|
21885
|
+
(delay) => setTimeout(maybeScrollToBottom, delay)
|
|
21886
|
+
);
|
|
21887
|
+
const stopKeepingPinnedToBottom = () => {
|
|
21888
|
+
keepPinnedToBottom = false;
|
|
21889
|
+
};
|
|
21890
|
+
listElement.addEventListener("pointerdown", stopKeepingPinnedToBottom, {
|
|
21891
|
+
passive: true
|
|
21892
|
+
});
|
|
21893
|
+
listElement.addEventListener("touchstart", stopKeepingPinnedToBottom, {
|
|
21894
|
+
passive: true
|
|
21895
|
+
});
|
|
21896
|
+
listElement.addEventListener("wheel", stopKeepingPinnedToBottom, {
|
|
21897
|
+
passive: true
|
|
21898
|
+
});
|
|
21899
|
+
listElement.addEventListener("keydown", stopKeepingPinnedToBottom);
|
|
21900
|
+
const pinWindowTimeoutId = setTimeout(() => {
|
|
21901
|
+
stopKeepingPinnedToBottom();
|
|
21902
|
+
}, 2200);
|
|
21903
|
+
return () => {
|
|
21904
|
+
settleTimeoutIds.forEach(clearTimeout);
|
|
21905
|
+
clearTimeout(pinWindowTimeoutId);
|
|
21906
|
+
listElement.removeEventListener("pointerdown", stopKeepingPinnedToBottom);
|
|
21907
|
+
listElement.removeEventListener("touchstart", stopKeepingPinnedToBottom);
|
|
21908
|
+
listElement.removeEventListener("wheel", stopKeepingPinnedToBottom);
|
|
21909
|
+
listElement.removeEventListener("keydown", stopKeepingPinnedToBottom);
|
|
21910
|
+
};
|
|
21911
|
+
}, [
|
|
21912
|
+
disableAutoScrollToBottom,
|
|
21913
|
+
hasMoreNewer,
|
|
21914
|
+
justReachedLatestMessageSet,
|
|
21915
|
+
listElement,
|
|
21916
|
+
messages.length,
|
|
21917
|
+
scrollToBottom,
|
|
21918
|
+
scrolledUpThreshold,
|
|
21919
|
+
suppressAutoscroll
|
|
21920
|
+
]);
|
|
21604
21921
|
const updateScrollTop = useMessageListScrollManager({
|
|
21605
21922
|
captureAnchor,
|
|
21606
21923
|
disableScrollManagement: disableScrollManagement || isRestoringOlderAnchorRef.current,
|
|
@@ -21627,6 +21944,9 @@ const useScrollLocationLogic = (params) => {
|
|
|
21627
21944
|
useLayoutEffect(() => {
|
|
21628
21945
|
previousHasMoreNewerRef.current = hasMoreNewer;
|
|
21629
21946
|
}, [hasMoreNewer]);
|
|
21947
|
+
useLayoutEffect(() => {
|
|
21948
|
+
previousMessagesLengthRef.current = messages.length;
|
|
21949
|
+
}, [messages.length]);
|
|
21630
21950
|
const onScroll = useCallback(
|
|
21631
21951
|
(event) => {
|
|
21632
21952
|
const element = event.target;
|
|
@@ -21635,8 +21955,10 @@ const useScrollLocationLogic = (params) => {
|
|
|
21635
21955
|
updateScrollTop(scrollTop, captureAnchor);
|
|
21636
21956
|
const offsetHeight = element.offsetHeight;
|
|
21637
21957
|
const scrollHeight = element.scrollHeight;
|
|
21958
|
+
const distanceToBottom = scrollHeight - (scrollTop + offsetHeight);
|
|
21959
|
+
const bottomEnterThreshold = Math.max(Math.floor(scrolledUpThreshold * 0.6), 24);
|
|
21638
21960
|
const prevCloseToBottom = closeToBottom.current;
|
|
21639
|
-
closeToBottom.current =
|
|
21961
|
+
closeToBottom.current = prevCloseToBottom ? distanceToBottom < scrolledUpThreshold : distanceToBottom < bottomEnterThreshold;
|
|
21640
21962
|
closeToTop.current = scrollTop < scrolledUpThreshold;
|
|
21641
21963
|
if (closeToBottom.current) {
|
|
21642
21964
|
setHasNewMessages(false);
|
|
@@ -22471,7 +22793,7 @@ function defaultRenderMessages({
|
|
|
22471
22793
|
return renderedMessages;
|
|
22472
22794
|
}
|
|
22473
22795
|
const findReverse = (items, matches) => {
|
|
22474
|
-
for (let i = items.length - 1; i
|
|
22796
|
+
for (let i = items.length - 1; i >= 0; i -= 1) {
|
|
22475
22797
|
if (matches(items[i])) {
|
|
22476
22798
|
return items[i];
|
|
22477
22799
|
}
|
|
@@ -23571,11 +23893,17 @@ const useConnectionRecoveredListener = (forceUpdate) => {
|
|
|
23571
23893
|
const MOBILE_NAV_BREAKPOINT = 768;
|
|
23572
23894
|
const useMobileNavigation = (channelListRef, navOpen, closeMobileNav) => {
|
|
23573
23895
|
useEffect(() => {
|
|
23896
|
+
const isClickInsideChannelList = (event) => {
|
|
23897
|
+
const channelListElement = channelListRef.current;
|
|
23898
|
+
if (!channelListElement) return false;
|
|
23899
|
+
const eventPath = event.composedPath();
|
|
23900
|
+
return eventPath.includes(channelListElement);
|
|
23901
|
+
};
|
|
23574
23902
|
const handleClickOutside = (event) => {
|
|
23575
23903
|
if (typeof window !== "undefined" && window.innerWidth >= MOBILE_NAV_BREAKPOINT) {
|
|
23576
23904
|
return;
|
|
23577
23905
|
}
|
|
23578
|
-
if (closeMobileNav && channelListRef.current && !
|
|
23906
|
+
if (closeMobileNav && channelListRef.current && !isClickInsideChannelList(event) && navOpen) {
|
|
23579
23907
|
closeMobileNav();
|
|
23580
23908
|
}
|
|
23581
23909
|
};
|
|
@@ -24705,7 +25033,7 @@ const UnMemoizedLoadMoreButton = ({
|
|
|
24705
25033
|
return /* @__PURE__ */ jsx("div", { className: "str-chat__load-more-button", children: /* @__PURE__ */ jsx(
|
|
24706
25034
|
Button,
|
|
24707
25035
|
{
|
|
24708
|
-
appearance: "
|
|
25036
|
+
appearance: "ghost",
|
|
24709
25037
|
"aria-label": t("aria/Load More Channels"),
|
|
24710
25038
|
"data-testid": "load-more-button",
|
|
24711
25039
|
disabled: loading,
|
|
@@ -25313,6 +25641,36 @@ const useArchiveActionButtonBehavior = () => {
|
|
|
25313
25641
|
};
|
|
25314
25642
|
};
|
|
25315
25643
|
const defaultChannelActionSet = [
|
|
25644
|
+
{
|
|
25645
|
+
// eslint-disable-next-line react/display-name
|
|
25646
|
+
Component: forwardRef((_, ref) => {
|
|
25647
|
+
const { channel } = useChannelListItemContext();
|
|
25648
|
+
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
25649
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25650
|
+
channelId: channel.id
|
|
25651
|
+
});
|
|
25652
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25653
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
25654
|
+
return /* @__PURE__ */ jsx(
|
|
25655
|
+
Button,
|
|
25656
|
+
{
|
|
25657
|
+
appearance: "ghost",
|
|
25658
|
+
"aria-expanded": dialogIsOpen,
|
|
25659
|
+
"aria-pressed": dialogIsOpen,
|
|
25660
|
+
circular: true,
|
|
25661
|
+
onClick: (e) => {
|
|
25662
|
+
e.stopPropagation();
|
|
25663
|
+
dialog.toggle();
|
|
25664
|
+
},
|
|
25665
|
+
ref,
|
|
25666
|
+
size: "sm",
|
|
25667
|
+
variant: "secondary",
|
|
25668
|
+
children: /* @__PURE__ */ jsx(IconDotGrid1x3Horizontal, {})
|
|
25669
|
+
}
|
|
25670
|
+
);
|
|
25671
|
+
}),
|
|
25672
|
+
placement: "quick-dropdown-toggle"
|
|
25673
|
+
},
|
|
25316
25674
|
{
|
|
25317
25675
|
Component() {
|
|
25318
25676
|
const behaviorProps = useArchiveActionButtonBehavior();
|
|
@@ -25445,7 +25803,7 @@ const defaultChannelActionSet = [
|
|
|
25445
25803
|
const membership = useChannelMembershipState(channel);
|
|
25446
25804
|
const dialogId2 = ChannelListItemActionButtons.getDialogId(
|
|
25447
25805
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25448
|
-
channel.id
|
|
25806
|
+
{ channelId: channel.id }
|
|
25449
25807
|
);
|
|
25450
25808
|
const { dialog } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25451
25809
|
const [inProgress, setInProgress] = useState(false);
|
|
@@ -25547,59 +25905,23 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25547
25905
|
const connectedUserIsMember = typeof membership.user !== "undefined";
|
|
25548
25906
|
const ownCapabilities = channel.data?.own_capabilities;
|
|
25549
25907
|
return useMemo(() => {
|
|
25550
|
-
const filtered = channelActionSet.filter(
|
|
25551
|
-
(action)
|
|
25552
|
-
|
|
25553
|
-
|
|
25554
|
-
|
|
25555
|
-
|
|
25556
|
-
|
|
25557
|
-
|
|
25558
|
-
|
|
25559
|
-
|
|
25560
|
-
|
|
25561
|
-
|
|
25562
|
-
|
|
25563
|
-
|
|
25564
|
-
|
|
25565
|
-
|
|
25566
|
-
|
|
25567
|
-
},
|
|
25568
|
-
isDirectMessageChannel: false
|
|
25569
|
-
},
|
|
25570
|
-
{
|
|
25571
|
-
action: { placement: "dropdown", type: "mute" },
|
|
25572
|
-
isDirectMessageChannel: true,
|
|
25573
|
-
ownCapabilities: P.when(
|
|
25574
|
-
(capabilities) => capabilities?.includes("mute-channel")
|
|
25575
|
-
)
|
|
25576
|
-
},
|
|
25577
|
-
{
|
|
25578
|
-
action: { placement: "quick", type: "mute" },
|
|
25579
|
-
isDirectMessageChannel: false,
|
|
25580
|
-
ownCapabilities: P.when(
|
|
25581
|
-
(capabilities) => capabilities?.includes("mute-channel")
|
|
25582
|
-
)
|
|
25583
|
-
},
|
|
25584
|
-
{
|
|
25585
|
-
action: { type: "ban" },
|
|
25586
|
-
memberCount: P.number.gt(0).and(P.number.lte(2)),
|
|
25587
|
-
ownCapabilities: P.when(
|
|
25588
|
-
(capabilities) => capabilities?.includes("ban-channel-members")
|
|
25589
|
-
)
|
|
25590
|
-
},
|
|
25591
|
-
{
|
|
25592
|
-
action: { type: "leave" },
|
|
25593
|
-
ownCapabilities: P.when(
|
|
25594
|
-
(capabilities) => capabilities?.includes("leave-channel")
|
|
25595
|
-
)
|
|
25596
|
-
},
|
|
25597
|
-
{
|
|
25598
|
-
action: { connectedUserIsMember: true, type: "pin" }
|
|
25599
|
-
},
|
|
25600
|
-
() => true
|
|
25601
|
-
).otherwise(() => false)
|
|
25602
|
-
);
|
|
25908
|
+
const filtered = channelActionSet.filter((action) => {
|
|
25909
|
+
if (action.placement === "quick-dropdown-toggle") return true;
|
|
25910
|
+
switch (action.type) {
|
|
25911
|
+
case "archive":
|
|
25912
|
+
return connectedUserIsMember && (action.placement === "quick" && isDirectMessageChannel || action.placement === "dropdown" && !isDirectMessageChannel);
|
|
25913
|
+
case "mute":
|
|
25914
|
+
return ownCapabilities?.includes("mute-channel") && (action.placement === "dropdown" && isDirectMessageChannel || action.placement === "quick" && !isDirectMessageChannel);
|
|
25915
|
+
case "ban":
|
|
25916
|
+
return memberCount > 0 && memberCount <= 2 && ownCapabilities?.includes("ban-channel-members");
|
|
25917
|
+
case "leave":
|
|
25918
|
+
return ownCapabilities?.includes("leave-channel");
|
|
25919
|
+
case "pin":
|
|
25920
|
+
return connectedUserIsMember;
|
|
25921
|
+
default:
|
|
25922
|
+
return true;
|
|
25923
|
+
}
|
|
25924
|
+
});
|
|
25603
25925
|
return filtered;
|
|
25604
25926
|
}, [
|
|
25605
25927
|
channelActionSet,
|
|
@@ -25610,17 +25932,18 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25610
25932
|
]);
|
|
25611
25933
|
};
|
|
25612
25934
|
const ChannelListItemActionButtons = () => {
|
|
25935
|
+
const { ContextMenu: ContextMenuComponent = ContextMenu } = useComponentContext();
|
|
25613
25936
|
const { channel } = useChannelListItemContext();
|
|
25614
25937
|
const [referenceElement, setReferenceElement] = React.useState(null);
|
|
25615
|
-
const dialogId2 = ChannelListItemActionButtons.getDialogId(
|
|
25938
|
+
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
25616
25939
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25617
|
-
channel.id
|
|
25618
|
-
);
|
|
25940
|
+
channelId: channel.id
|
|
25941
|
+
});
|
|
25619
25942
|
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25620
25943
|
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
25621
25944
|
const filteredActionSet = useBaseChannelActionSetFilter(defaultChannelActionSet);
|
|
25622
|
-
const
|
|
25623
|
-
if (
|
|
25945
|
+
const { dropdownActionSet, quickActionSet, quickDropdownToggleAction } = useSplitActionSet(filteredActionSet);
|
|
25946
|
+
if (quickActionSet.length + dropdownActionSet.length === 0) {
|
|
25624
25947
|
return null;
|
|
25625
25948
|
}
|
|
25626
25949
|
return /* @__PURE__ */ jsxs(
|
|
@@ -25630,26 +25953,10 @@ const ChannelListItemActionButtons = () => {
|
|
|
25630
25953
|
"str-chat__channel-list-item__action-buttons--active": dialogIsOpen
|
|
25631
25954
|
}),
|
|
25632
25955
|
children: [
|
|
25633
|
-
|
|
25634
|
-
|
|
25635
|
-
{
|
|
25636
|
-
appearance: "ghost",
|
|
25637
|
-
"aria-expanded": dialogIsOpen,
|
|
25638
|
-
"aria-pressed": dialogIsOpen,
|
|
25639
|
-
circular: true,
|
|
25640
|
-
onClick: (e) => {
|
|
25641
|
-
e.stopPropagation();
|
|
25642
|
-
dialog.toggle();
|
|
25643
|
-
},
|
|
25644
|
-
ref: setReferenceElement,
|
|
25645
|
-
size: "sm",
|
|
25646
|
-
variant: "secondary",
|
|
25647
|
-
children: /* @__PURE__ */ jsx(IconDotGrid1x3Horizontal, {})
|
|
25648
|
-
}
|
|
25649
|
-
),
|
|
25650
|
-
splitActionSet.quickActionSet.map(({ Component: Component2, type }) => /* @__PURE__ */ jsx(Component2, {}, type)),
|
|
25956
|
+
quickDropdownToggleAction && dropdownActionSet.length > 0 && /* @__PURE__ */ jsx(quickDropdownToggleAction.Component, { ref: setReferenceElement }),
|
|
25957
|
+
quickActionSet.map(({ Component: Component2, type }) => /* @__PURE__ */ jsx(Component2, {}, type)),
|
|
25651
25958
|
/* @__PURE__ */ jsx(
|
|
25652
|
-
|
|
25959
|
+
ContextMenuComponent,
|
|
25653
25960
|
{
|
|
25654
25961
|
className: "str-chat__channel-list-item__action-buttons-context-menu",
|
|
25655
25962
|
dialogManagerId: dialogManager?.id,
|
|
@@ -25659,14 +25966,14 @@ const ChannelListItemActionButtons = () => {
|
|
|
25659
25966
|
referenceElement,
|
|
25660
25967
|
tabIndex: -1,
|
|
25661
25968
|
trapFocus: true,
|
|
25662
|
-
children:
|
|
25969
|
+
children: dropdownActionSet.map(({ Component: Component2, type }) => /* @__PURE__ */ jsx(Component2, {}, type))
|
|
25663
25970
|
}
|
|
25664
25971
|
)
|
|
25665
25972
|
]
|
|
25666
25973
|
}
|
|
25667
25974
|
);
|
|
25668
25975
|
};
|
|
25669
|
-
ChannelListItemActionButtons.getDialogId = (channelId) => `channel-action-buttons-${channelId}`;
|
|
25976
|
+
ChannelListItemActionButtons.getDialogId = ({ channelId }) => `channel-action-buttons-${channelId}`;
|
|
25670
25977
|
ChannelListItemActionButtons.displayName = "ChannelListItemActionButtons";
|
|
25671
25978
|
function ChannelListItemTimestamp({ lastMessage }) {
|
|
25672
25979
|
const { t, tDateTimeParser } = useTranslationContext("ChannelListItemTimestamp");
|
|
@@ -26605,7 +26912,8 @@ const ThreadList = ({ virtuosoProps }) => {
|
|
|
26605
26912
|
};
|
|
26606
26913
|
const IconsBySeverity = {
|
|
26607
26914
|
error: IconExclamationCircle,
|
|
26608
|
-
info:
|
|
26915
|
+
info: null,
|
|
26916
|
+
// IconCircleInfoTooltip,
|
|
26609
26917
|
loading: IconArrowRotateRightLeftRepeatRefresh,
|
|
26610
26918
|
success: IconCheckmark2,
|
|
26611
26919
|
warning: IconExclamationTriangle
|
|
@@ -26613,7 +26921,7 @@ const IconsBySeverity = {
|
|
|
26613
26921
|
const DefaultNotificationIcon = ({ notification }) => {
|
|
26614
26922
|
if (!notification.severity) return null;
|
|
26615
26923
|
const Icon = IconsBySeverity[notification.severity] ?? null;
|
|
26616
|
-
return Icon && /* @__PURE__ */ jsx(Icon, {});
|
|
26924
|
+
return Icon && /* @__PURE__ */ jsx("div", { className: "str-chat__notification-icon", children: /* @__PURE__ */ jsx(Icon, {}) });
|
|
26617
26925
|
};
|
|
26618
26926
|
const Notification = forwardRef(
|
|
26619
26927
|
({
|
|
@@ -26657,7 +26965,7 @@ const Notification = forwardRef(
|
|
|
26657
26965
|
ref,
|
|
26658
26966
|
children: [
|
|
26659
26967
|
/* @__PURE__ */ jsxs("div", { className: "str-chat__notification-content", children: [
|
|
26660
|
-
Icon && /* @__PURE__ */ jsx(
|
|
26968
|
+
Icon && /* @__PURE__ */ jsx(Icon, { notification }),
|
|
26661
26969
|
/* @__PURE__ */ jsx("div", { className: "str-chat__notification-message", children: displayMessage })
|
|
26662
26970
|
] }),
|
|
26663
26971
|
notification.actions && notification.actions.length > 0 && /* @__PURE__ */ jsx("div", { className: "str-chat__notification-actions", children: notification.actions.map((action, index) => /* @__PURE__ */ jsx(
|
|
@@ -26991,7 +27299,7 @@ const VoiceRecordingPlayerUI = ({ audioPlayer }) => {
|
|
|
26991
27299
|
secondsElapsed
|
|
26992
27300
|
} = useStateStore(audioPlayer?.state, audioPlayerStateSelector) ?? {};
|
|
26993
27301
|
return /* @__PURE__ */ jsxs("div", { className: rootClassName, "data-testid": "voice-recording-widget", children: [
|
|
26994
|
-
/* @__PURE__ */ jsx(PlayButton, { isPlaying: !!isPlaying, onClick: audioPlayer.togglePlay }),
|
|
27302
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__play-button-container", children: /* @__PURE__ */ jsx(PlayButton, { isPlaying: !!isPlaying, onClick: audioPlayer.togglePlay }) }),
|
|
26995
27303
|
/* @__PURE__ */ jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__metadata", children: /* @__PURE__ */ jsxs("div", { className: "str-chat__message-attachment__voice-recording-widget__audio-state", children: [
|
|
26996
27304
|
/* @__PURE__ */ jsx("div", { className: "str-chat__message-attachment__voice-recording-widget__timer", children: durationSeconds ? /* @__PURE__ */ jsx(
|
|
26997
27305
|
DurationDisplay,
|
|
@@ -27400,23 +27708,44 @@ const FileAttachment = ({ attachment }) => {
|
|
|
27400
27708
|
);
|
|
27401
27709
|
};
|
|
27402
27710
|
const Giphy = ({ attachment }) => {
|
|
27403
|
-
const { giphyVersion: giphyVersionName } = useChannelStateContext();
|
|
27711
|
+
const { giphyVersion: giphyVersionName, imageAttachmentSizeHandler } = useChannelStateContext();
|
|
27404
27712
|
const { BaseImage: BaseImage$1 = BaseImage } = useComponentContext();
|
|
27405
27713
|
const { t } = useTranslationContext();
|
|
27406
27714
|
const usesDefaultBaseImage = BaseImage$1 === BaseImage;
|
|
27715
|
+
const imageElement = useRef(null);
|
|
27716
|
+
const [attachmentConfiguration, setAttachmentConfiguration] = useState(void 0);
|
|
27407
27717
|
const imageDescriptors = useMemo(
|
|
27408
27718
|
() => toGalleryItemDescriptors(attachment, { giphyVersionName }),
|
|
27409
27719
|
[attachment, giphyVersionName]
|
|
27410
27720
|
);
|
|
27411
|
-
|
|
27412
|
-
const
|
|
27721
|
+
const alt = imageDescriptors && imageDescriptors.alt;
|
|
27722
|
+
const dimensions = imageDescriptors && imageDescriptors.dimensions;
|
|
27723
|
+
const imageUrl = imageDescriptors && imageDescriptors.imageUrl;
|
|
27724
|
+
const title = imageDescriptors && imageDescriptors.title;
|
|
27725
|
+
const resolvedImageUrl = attachmentConfiguration?.url || imageUrl;
|
|
27726
|
+
const imageStyleVariables = useMemo(() => {
|
|
27727
|
+
const originalHeight = Number(dimensions?.height);
|
|
27728
|
+
const originalWidth = Number(dimensions?.width);
|
|
27729
|
+
return {
|
|
27730
|
+
"--original-height": String(originalHeight > 1 ? originalHeight : 1e6),
|
|
27731
|
+
"--original-width": String(originalWidth > 1 ? originalWidth : 1e6)
|
|
27732
|
+
};
|
|
27733
|
+
}, [dimensions?.height, dimensions?.width]);
|
|
27734
|
+
useLayoutEffect(() => {
|
|
27735
|
+
if (!imageElement.current || !imageAttachmentSizeHandler) return;
|
|
27736
|
+
const config = imageAttachmentSizeHandler(attachment, imageElement.current);
|
|
27737
|
+
setAttachmentConfiguration(config);
|
|
27738
|
+
}, [attachment, imageAttachmentSizeHandler]);
|
|
27739
|
+
if (!imageUrl) return null;
|
|
27413
27740
|
return /* @__PURE__ */ jsxs("div", { className: clsx(`str-chat__message-attachment-giphy`), children: [
|
|
27414
27741
|
/* @__PURE__ */ jsx(
|
|
27415
27742
|
BaseImage$1,
|
|
27416
27743
|
{
|
|
27417
27744
|
alt: alt ?? title ?? t("User uploaded content"),
|
|
27418
27745
|
height: dimensions?.height,
|
|
27419
|
-
|
|
27746
|
+
ref: imageElement,
|
|
27747
|
+
src: resolvedImageUrl,
|
|
27748
|
+
style: imageStyleVariables,
|
|
27420
27749
|
width: dimensions?.width,
|
|
27421
27750
|
...usesDefaultBaseImage ? { showDownloadButtonOnError: false } : {}
|
|
27422
27751
|
}
|
|
@@ -28016,7 +28345,6 @@ export {
|
|
|
28016
28345
|
AIStateIndicator,
|
|
28017
28346
|
AIStates,
|
|
28018
28347
|
ATTACHMENT_GROUPS_ORDER,
|
|
28019
|
-
ActionsIcon,
|
|
28020
28348
|
AddCommentPrompt,
|
|
28021
28349
|
Alert,
|
|
28022
28350
|
AmountBar,
|
|
@@ -28029,7 +28357,7 @@ export {
|
|
|
28029
28357
|
AttachmentWithinContainer,
|
|
28030
28358
|
Audio,
|
|
28031
28359
|
AudioContainer,
|
|
28032
|
-
|
|
28360
|
+
bu as AudioPlayer,
|
|
28033
28361
|
AudioRecorder,
|
|
28034
28362
|
Avatar,
|
|
28035
28363
|
AvatarStack,
|
|
@@ -28041,13 +28369,13 @@ export {
|
|
|
28041
28369
|
Callout,
|
|
28042
28370
|
Card,
|
|
28043
28371
|
CardContainer,
|
|
28044
|
-
|
|
28045
|
-
|
|
28046
|
-
|
|
28372
|
+
bx as Channel,
|
|
28373
|
+
dc as ChannelActionContext,
|
|
28374
|
+
dd as ChannelActionProvider,
|
|
28047
28375
|
ChannelAvatar,
|
|
28048
28376
|
ChannelHeader,
|
|
28049
28377
|
ChannelList,
|
|
28050
|
-
ChannelListContext,
|
|
28378
|
+
de as ChannelListContext,
|
|
28051
28379
|
ChannelListContextProvider,
|
|
28052
28380
|
ChannelListItem,
|
|
28053
28381
|
ChannelListItemActionButtons,
|
|
@@ -28055,27 +28383,28 @@ export {
|
|
|
28055
28383
|
ChannelListItemUI,
|
|
28056
28384
|
ChannelListUI,
|
|
28057
28385
|
ChannelSearchResultItem,
|
|
28058
|
-
|
|
28059
|
-
|
|
28386
|
+
df as ChannelStateContext,
|
|
28387
|
+
dg as ChannelStateProvider,
|
|
28060
28388
|
Chat,
|
|
28061
|
-
|
|
28389
|
+
dh as ChatContext,
|
|
28062
28390
|
ChatProvider,
|
|
28063
|
-
|
|
28064
|
-
|
|
28065
|
-
|
|
28066
|
-
|
|
28067
|
-
|
|
28391
|
+
bz as ChatView,
|
|
28392
|
+
bC as ChatViewChannelsSelectorButton,
|
|
28393
|
+
by as ChatViewContext,
|
|
28394
|
+
bB as ChatViewSelectorButton,
|
|
28395
|
+
bD as ChatViewThreadsSelectorButton,
|
|
28068
28396
|
CheckSignIcon,
|
|
28069
28397
|
Checkmark,
|
|
28070
28398
|
CommandChip,
|
|
28071
28399
|
CommandItem,
|
|
28072
28400
|
ComponentContext,
|
|
28073
|
-
|
|
28401
|
+
di as ComponentProvider,
|
|
28074
28402
|
ConnectionStatus,
|
|
28075
28403
|
ContextMenu,
|
|
28076
28404
|
ContextMenuBackButton,
|
|
28077
28405
|
ContextMenuBody,
|
|
28078
28406
|
ContextMenuButton,
|
|
28407
|
+
ContextMenuContent,
|
|
28079
28408
|
ContextMenuHeader,
|
|
28080
28409
|
ContextMenuRoot,
|
|
28081
28410
|
CooldownTimer,
|
|
@@ -28094,6 +28423,7 @@ export {
|
|
|
28094
28423
|
EmoticonItem,
|
|
28095
28424
|
EmptyStateIndicator,
|
|
28096
28425
|
EndPollAlert,
|
|
28426
|
+
ErrorBadge,
|
|
28097
28427
|
EventComponent,
|
|
28098
28428
|
FILE_ICON_GRAPHIC_CLASSNAME,
|
|
28099
28429
|
FILE_ICON_NO_LABEL_CLASSNAME,
|
|
@@ -28114,162 +28444,163 @@ export {
|
|
|
28114
28444
|
GlobalModal,
|
|
28115
28445
|
GroupAvatar,
|
|
28116
28446
|
Header$1 as Header,
|
|
28117
|
-
|
|
28118
|
-
|
|
28447
|
+
bG as IconApiAggregate,
|
|
28448
|
+
bH as IconApples,
|
|
28119
28449
|
IconArchive,
|
|
28120
28450
|
IconArrowBoxLeft,
|
|
28121
28451
|
IconArrowDown,
|
|
28122
28452
|
IconArrowDownCircle,
|
|
28123
28453
|
IconArrowLeft,
|
|
28124
|
-
|
|
28454
|
+
bI as IconArrowRight,
|
|
28125
28455
|
IconArrowRightUp,
|
|
28126
28456
|
IconArrowRotateClockwise,
|
|
28127
28457
|
IconArrowRotateRightLeftRepeatRefresh,
|
|
28128
|
-
|
|
28458
|
+
IconArrowShareLeft,
|
|
28129
28459
|
IconArrowUp,
|
|
28130
|
-
|
|
28131
|
-
|
|
28132
|
-
|
|
28460
|
+
bJ as IconArrowsRepeatLeftRight,
|
|
28461
|
+
bK as IconAt,
|
|
28462
|
+
bL as IconAtSolid,
|
|
28133
28463
|
IconBellNotification,
|
|
28134
28464
|
IconBellOff,
|
|
28135
28465
|
IconBookmark,
|
|
28136
28466
|
IconBookmarkRemove,
|
|
28137
|
-
|
|
28138
|
-
|
|
28139
|
-
|
|
28140
|
-
|
|
28141
|
-
|
|
28142
|
-
|
|
28467
|
+
bM as IconBrowserAISparkle,
|
|
28468
|
+
bN as IconBubble2ChatMessage,
|
|
28469
|
+
bO as IconBubble2Solid,
|
|
28470
|
+
bP as IconBubble3ChatMessage,
|
|
28471
|
+
bQ as IconBubble3Solid,
|
|
28472
|
+
bR as IconBubbleAnnotation2ChatMessage,
|
|
28143
28473
|
IconBubbleText6ChatMessage,
|
|
28144
|
-
|
|
28145
|
-
|
|
28474
|
+
bT as IconBubbleText6Solid,
|
|
28475
|
+
bS as IconBubbleText6SolidChatMessage,
|
|
28146
28476
|
IconBubbleWideNotificationChatMessage,
|
|
28147
|
-
|
|
28477
|
+
bU as IconBubbleWideSparkleChatMessage,
|
|
28148
28478
|
IconBubbles,
|
|
28149
|
-
|
|
28150
|
-
|
|
28479
|
+
bV as IconCalendar1,
|
|
28480
|
+
bW as IconCallCancel,
|
|
28151
28481
|
IconCamera1,
|
|
28152
|
-
|
|
28153
|
-
|
|
28482
|
+
bX as IconCar1,
|
|
28483
|
+
bY as IconCat,
|
|
28154
28484
|
IconChainLink,
|
|
28155
28485
|
IconChart5,
|
|
28156
28486
|
IconCheckmark1Small,
|
|
28157
28487
|
IconCheckmark2,
|
|
28158
|
-
|
|
28488
|
+
bZ as IconCheckmark2Small,
|
|
28159
28489
|
IconChevronDown,
|
|
28160
|
-
|
|
28490
|
+
b_ as IconChevronGrabberVerticalSelector,
|
|
28161
28491
|
IconChevronLeft,
|
|
28162
28492
|
IconChevronRight,
|
|
28163
|
-
|
|
28493
|
+
b$ as IconChevronTop,
|
|
28164
28494
|
IconCircleBanSign,
|
|
28165
|
-
|
|
28166
|
-
IconCircleInfoTooltip,
|
|
28495
|
+
c0 as IconCircleCheck,
|
|
28496
|
+
c1 as IconCircleInfoTooltip,
|
|
28167
28497
|
IconCircleMinus,
|
|
28168
|
-
|
|
28169
|
-
|
|
28498
|
+
c2 as IconCircleQuestionmark,
|
|
28499
|
+
c3 as IconCircleQuestionmarkFilled,
|
|
28170
28500
|
IconCircleX,
|
|
28171
28501
|
IconClock,
|
|
28172
|
-
|
|
28502
|
+
c4 as IconClockSolid,
|
|
28173
28503
|
IconCloseQuote2,
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
|
|
28177
|
-
|
|
28178
|
-
|
|
28504
|
+
c5 as IconCode,
|
|
28505
|
+
c6 as IconCodeBrackets,
|
|
28506
|
+
c7 as IconCodeEditorInsert,
|
|
28507
|
+
c8 as IconCompass,
|
|
28508
|
+
c9 as IconCreditCard2Billing,
|
|
28179
28509
|
IconCrossMedium,
|
|
28180
28510
|
IconCrossSmall,
|
|
28181
28511
|
IconDotGrid1x3Horizontal,
|
|
28182
28512
|
IconDotGrid2x3,
|
|
28183
|
-
|
|
28513
|
+
ca as IconDotsGrid1x3Vertical,
|
|
28184
28514
|
IconDoubleCheckmark1Small,
|
|
28185
28515
|
IconEditBig,
|
|
28186
|
-
|
|
28187
|
-
|
|
28188
|
-
|
|
28189
|
-
|
|
28516
|
+
cb as IconEditBigSolid,
|
|
28517
|
+
cc as IconEmojiAddReaction,
|
|
28518
|
+
cd as IconEmojiSad,
|
|
28519
|
+
IconEmojiSmile,
|
|
28520
|
+
IconExclamation,
|
|
28190
28521
|
IconExclamationCircle,
|
|
28191
28522
|
IconExclamationCircle1,
|
|
28192
28523
|
IconExclamationTriangle,
|
|
28193
|
-
|
|
28524
|
+
ce as IconExclamationTriangle1,
|
|
28194
28525
|
IconEyeOpen,
|
|
28195
28526
|
IconFileArrowLeftIn,
|
|
28196
28527
|
IconFileBend,
|
|
28197
|
-
|
|
28198
|
-
|
|
28528
|
+
cf as IconFilledCircleInfoTooltip,
|
|
28529
|
+
cg as IconFilter1,
|
|
28199
28530
|
IconFlag2,
|
|
28200
|
-
|
|
28531
|
+
ch as IconGauge,
|
|
28201
28532
|
IconGiphy,
|
|
28202
|
-
|
|
28203
|
-
|
|
28204
|
-
|
|
28205
|
-
|
|
28533
|
+
ci as IconGoogle,
|
|
28534
|
+
cj as IconHashtagChannel,
|
|
28535
|
+
ck as IconHeart2,
|
|
28536
|
+
cl as IconHistory,
|
|
28206
28537
|
IconImages1Alt,
|
|
28207
|
-
|
|
28208
|
-
|
|
28538
|
+
cm as IconInvite,
|
|
28539
|
+
cn as IconLayersBehind,
|
|
28209
28540
|
IconLayoutAlignLeft,
|
|
28210
|
-
|
|
28211
|
-
|
|
28212
|
-
|
|
28213
|
-
|
|
28541
|
+
co as IconLayoutGrid1,
|
|
28542
|
+
cp as IconLightBulbSimple,
|
|
28543
|
+
cq as IconLimits,
|
|
28544
|
+
cr as IconLineChart3,
|
|
28214
28545
|
IconLoadingCircle,
|
|
28215
|
-
|
|
28546
|
+
cs as IconLock,
|
|
28216
28547
|
IconMagnifyingGlassSearch,
|
|
28217
28548
|
IconMapPin,
|
|
28218
28549
|
IconMicrophone,
|
|
28219
|
-
|
|
28220
|
-
|
|
28221
|
-
|
|
28550
|
+
ct as IconMicrophoneSolid,
|
|
28551
|
+
cu as IconMinusLarge,
|
|
28552
|
+
cv as IconMinusSmall,
|
|
28222
28553
|
IconMute,
|
|
28223
|
-
|
|
28224
|
-
|
|
28554
|
+
cw as IconNewspaper2,
|
|
28555
|
+
cx as IconOrganization,
|
|
28225
28556
|
IconPaperPlane,
|
|
28226
|
-
|
|
28557
|
+
cy as IconPaperPlaneTopRight,
|
|
28227
28558
|
IconPaperclip,
|
|
28228
|
-
|
|
28559
|
+
cz as IconParagraphsText,
|
|
28229
28560
|
IconPause,
|
|
28230
|
-
|
|
28561
|
+
cA as IconPencil,
|
|
28231
28562
|
IconPeople,
|
|
28232
|
-
|
|
28563
|
+
cB as IconPeople2,
|
|
28233
28564
|
IconPeopleAdd,
|
|
28234
28565
|
IconPeopleAdded,
|
|
28235
|
-
|
|
28236
|
-
|
|
28237
|
-
|
|
28566
|
+
cC as IconPeopleCircle,
|
|
28567
|
+
cD as IconPeopleCopy,
|
|
28568
|
+
cE as IconPeopleEditUserRights,
|
|
28238
28569
|
IconPeopleRemove,
|
|
28239
|
-
|
|
28570
|
+
cF as IconPersona,
|
|
28240
28571
|
IconPin,
|
|
28241
28572
|
IconPlaySolid,
|
|
28242
28573
|
IconPlusLarge,
|
|
28243
28574
|
IconPlusSmall,
|
|
28244
28575
|
IconRunShortcut,
|
|
28245
|
-
|
|
28246
|
-
|
|
28247
|
-
|
|
28248
|
-
|
|
28249
|
-
|
|
28250
|
-
|
|
28251
|
-
|
|
28576
|
+
cG as IconSearchText,
|
|
28577
|
+
cH as IconSettingsGear2,
|
|
28578
|
+
cI as IconSettingsSliderVer,
|
|
28579
|
+
cJ as IconShapesPlusCloseSquareCircle,
|
|
28580
|
+
cK as IconShapesTriangleSquareCircle,
|
|
28581
|
+
cL as IconShareRedirectLink,
|
|
28582
|
+
cM as IconShield,
|
|
28252
28583
|
IconSquareBehindSquare2_Copy,
|
|
28253
|
-
|
|
28254
|
-
|
|
28255
|
-
|
|
28256
|
-
|
|
28257
|
-
|
|
28258
|
-
|
|
28584
|
+
cN as IconSquareCircleTopRightFeeds,
|
|
28585
|
+
cO as IconStop,
|
|
28586
|
+
cP as IconTable,
|
|
28587
|
+
cQ as IconTeam,
|
|
28588
|
+
cR as IconTennis,
|
|
28589
|
+
cS as IconTextToImageURLEnrichment,
|
|
28259
28590
|
IconThunder,
|
|
28260
28591
|
IconTranslate,
|
|
28261
28592
|
IconTrashBin,
|
|
28262
|
-
|
|
28593
|
+
cT as IconTrending4,
|
|
28263
28594
|
IconTrophy,
|
|
28264
|
-
|
|
28595
|
+
cU as IconUnlocked,
|
|
28265
28596
|
IconUnpin,
|
|
28266
|
-
|
|
28597
|
+
cV as IconUsers,
|
|
28267
28598
|
IconVideo,
|
|
28268
28599
|
IconVideoSolid,
|
|
28269
|
-
|
|
28270
|
-
|
|
28600
|
+
cW as IconVoiceAndVideo,
|
|
28601
|
+
cX as IconVoiceHigh,
|
|
28271
28602
|
IconVolumeFull,
|
|
28272
|
-
|
|
28603
|
+
cY as IconWebhook,
|
|
28273
28604
|
ImageComponent,
|
|
28274
28605
|
ImageContainer,
|
|
28275
28606
|
ImagePlaceholder,
|
|
@@ -28278,9 +28609,9 @@ export {
|
|
|
28278
28609
|
LinkPreviewList,
|
|
28279
28610
|
LoadMoreButton,
|
|
28280
28611
|
LoadMorePaginator,
|
|
28281
|
-
|
|
28612
|
+
cZ as LoadingChannel,
|
|
28282
28613
|
LoadingChannels,
|
|
28283
|
-
|
|
28614
|
+
c_ as LoadingErrorIndicator,
|
|
28284
28615
|
LoadingIndicator,
|
|
28285
28616
|
LoadingIndicatorIcon,
|
|
28286
28617
|
MAX_MESSAGE_REACTIONS_TO_FETCH,
|
|
@@ -28295,20 +28626,20 @@ export {
|
|
|
28295
28626
|
MessageBouncePrompt,
|
|
28296
28627
|
MessageBounceProvider,
|
|
28297
28628
|
MessageComposer,
|
|
28298
|
-
|
|
28629
|
+
dj as MessageComposerContext,
|
|
28299
28630
|
MessageComposerContextProvider,
|
|
28300
28631
|
MessageComposerUI,
|
|
28301
28632
|
MessageContext,
|
|
28302
28633
|
MessageDeletedBubble,
|
|
28303
28634
|
MessageDeliveryStatus,
|
|
28304
28635
|
MessageEditedIndicator,
|
|
28305
|
-
MessageErrorIcon,
|
|
28306
28636
|
MessageList,
|
|
28307
28637
|
MessageListContext,
|
|
28308
28638
|
MessageListContextProvider,
|
|
28309
28639
|
MessageProvider,
|
|
28310
28640
|
MessageReactions,
|
|
28311
28641
|
MessageReactionsDetail,
|
|
28642
|
+
MessageReactionsDetailLoadingIndicator,
|
|
28312
28643
|
MessageRepliesCountButton,
|
|
28313
28644
|
MessageSearchResultItem,
|
|
28314
28645
|
MessageStatus,
|
|
@@ -28328,10 +28659,9 @@ export {
|
|
|
28328
28659
|
NotificationList,
|
|
28329
28660
|
NotificationTranslationTopic,
|
|
28330
28661
|
NumericInput,
|
|
28331
|
-
|
|
28662
|
+
c$ as OPTIONAL_MESSAGE_ACTIONS,
|
|
28332
28663
|
OtherFilesContainer,
|
|
28333
28664
|
PauseIcon,
|
|
28334
|
-
PinIcon,
|
|
28335
28665
|
PinIndicator,
|
|
28336
28666
|
PlayButton,
|
|
28337
28667
|
PlayIcon,
|
|
@@ -28358,7 +28688,6 @@ export {
|
|
|
28358
28688
|
QuotedMessagePreview,
|
|
28359
28689
|
QuotedMessagePreviewUI,
|
|
28360
28690
|
QuotedVoiceRecording,
|
|
28361
|
-
ReactionIcon,
|
|
28362
28691
|
ReactionSelector,
|
|
28363
28692
|
RecordingPermission,
|
|
28364
28693
|
RecordingPermissionDeniedNotification,
|
|
@@ -28397,23 +28726,22 @@ export {
|
|
|
28397
28726
|
TextInputFieldSet,
|
|
28398
28727
|
TextareaComposer,
|
|
28399
28728
|
Thread,
|
|
28400
|
-
|
|
28729
|
+
da as ThreadContext,
|
|
28401
28730
|
ThreadHeader,
|
|
28402
|
-
ThreadIcon,
|
|
28403
28731
|
ThreadList,
|
|
28404
28732
|
ThreadListItem,
|
|
28405
28733
|
ThreadListItemUI,
|
|
28406
|
-
|
|
28734
|
+
db as ThreadProvider,
|
|
28407
28735
|
ThreadStart,
|
|
28408
28736
|
Tooltip,
|
|
28409
28737
|
TranslationBuilder,
|
|
28410
|
-
|
|
28738
|
+
dk as TranslationContext,
|
|
28411
28739
|
TranslationProvider,
|
|
28412
28740
|
TranslationTopic,
|
|
28413
|
-
|
|
28741
|
+
dl as TypingContext,
|
|
28414
28742
|
TypingIndicator,
|
|
28415
28743
|
TypingIndicatorHeader,
|
|
28416
|
-
|
|
28744
|
+
dm as TypingProvider,
|
|
28417
28745
|
UNREAD_MESSAGE_SEPARATOR_CLASS,
|
|
28418
28746
|
UnMemoizedLoadMorePaginator,
|
|
28419
28747
|
UnreadMessagesNotification,
|
|
@@ -28433,31 +28761,31 @@ export {
|
|
|
28433
28761
|
VoiceRecordingPlayer,
|
|
28434
28762
|
WaveProgressBar,
|
|
28435
28763
|
Window,
|
|
28436
|
-
|
|
28764
|
+
br as WithAudioPlayback,
|
|
28437
28765
|
WithComponents,
|
|
28438
28766
|
WithDragAndDropUpload,
|
|
28439
28767
|
addNotificationTargetTag,
|
|
28440
28768
|
areMessagePropsEqual,
|
|
28441
28769
|
areMessageUIPropsEqual,
|
|
28442
28770
|
countEmojis,
|
|
28443
|
-
|
|
28771
|
+
bF as createIcon,
|
|
28444
28772
|
deTranslations,
|
|
28445
28773
|
defaultAllowedTagNames,
|
|
28446
28774
|
defaultAttachmentActionsDefaultFocus,
|
|
28447
28775
|
defaultAttachmentSelectorActionSet,
|
|
28448
|
-
|
|
28776
|
+
bE as defaultChatViewSelectorItemSet,
|
|
28449
28777
|
defaultComponents,
|
|
28450
28778
|
defaultDateTimeParser,
|
|
28451
28779
|
defaultMessageActionSet,
|
|
28452
28780
|
defaultPinPermissions,
|
|
28453
28781
|
defaultReactionOptions,
|
|
28454
|
-
|
|
28782
|
+
bs as defaultRegisterAudioPlayerError,
|
|
28455
28783
|
defaultRenderMessages,
|
|
28456
28784
|
defaultTranslatorFunction,
|
|
28457
28785
|
displayDuration,
|
|
28458
28786
|
divMod,
|
|
28459
28787
|
downSample,
|
|
28460
|
-
|
|
28788
|
+
bt as elementIsPlaying,
|
|
28461
28789
|
emojiMarkdownPlugin,
|
|
28462
28790
|
emojiToUnicode,
|
|
28463
28791
|
enTranslations,
|
|
@@ -28471,21 +28799,21 @@ export {
|
|
|
28471
28799
|
getCssDimensionsVariables,
|
|
28472
28800
|
getGroupChannelDisplayInfo,
|
|
28473
28801
|
getGroupStyles,
|
|
28474
|
-
|
|
28802
|
+
d0 as getImages,
|
|
28475
28803
|
getIsFirstUnreadMessage,
|
|
28476
28804
|
getLastReceived,
|
|
28477
28805
|
getLatestMessagePreview,
|
|
28478
28806
|
getMessageActions,
|
|
28479
|
-
|
|
28480
|
-
|
|
28481
|
-
|
|
28807
|
+
d1 as getNonImageAttachments,
|
|
28808
|
+
d7 as getNotificationTargetPanel,
|
|
28809
|
+
d8 as getNotificationTargetTag,
|
|
28482
28810
|
getReadByTooltipText,
|
|
28483
28811
|
getTextareaCaretRect,
|
|
28484
28812
|
getTranslatedMessageText,
|
|
28485
28813
|
getWholeChar,
|
|
28486
28814
|
handleActionWarning,
|
|
28487
|
-
|
|
28488
|
-
|
|
28815
|
+
d4 as hasMoreMessagesProbably,
|
|
28816
|
+
d5 as hasNotMoreMessages,
|
|
28489
28817
|
hiTranslations,
|
|
28490
28818
|
htmlToTextPlugin,
|
|
28491
28819
|
imageToLink,
|
|
@@ -28495,7 +28823,7 @@ export {
|
|
|
28495
28823
|
isChrome,
|
|
28496
28824
|
isDate,
|
|
28497
28825
|
isDateSeparatorMessage,
|
|
28498
|
-
|
|
28826
|
+
dn as isDayOrMoment,
|
|
28499
28827
|
isFirefox,
|
|
28500
28828
|
isGalleryAttachmentType,
|
|
28501
28829
|
isIntroMessage,
|
|
@@ -28505,9 +28833,10 @@ export {
|
|
|
28505
28833
|
isMessageBounced,
|
|
28506
28834
|
isMessageEdited,
|
|
28507
28835
|
isMessageErrorRetryable,
|
|
28836
|
+
isNetworkSendFailure,
|
|
28508
28837
|
isNotificationForPanel,
|
|
28509
|
-
|
|
28510
|
-
|
|
28838
|
+
d6 as isNotificationTargetPanel,
|
|
28839
|
+
dp as isNumberOrString,
|
|
28511
28840
|
isSafari,
|
|
28512
28841
|
isSvgAttachment,
|
|
28513
28842
|
isUserMuted,
|
|
@@ -28515,8 +28844,8 @@ export {
|
|
|
28515
28844
|
jaTranslations,
|
|
28516
28845
|
keepLineBreaksPlugin,
|
|
28517
28846
|
koTranslations,
|
|
28518
|
-
|
|
28519
|
-
|
|
28847
|
+
d3 as makeDateMessageId,
|
|
28848
|
+
d2 as makeIntroMessage,
|
|
28520
28849
|
mapEmojiMartData,
|
|
28521
28850
|
mapToUserNameOrId,
|
|
28522
28851
|
markDownRenderers,
|
|
@@ -28553,8 +28882,8 @@ export {
|
|
|
28553
28882
|
upSample,
|
|
28554
28883
|
useAIState,
|
|
28555
28884
|
useActionHandler,
|
|
28556
|
-
|
|
28557
|
-
|
|
28885
|
+
bq as useActiveAudioPlayer,
|
|
28886
|
+
bA as useActiveThread,
|
|
28558
28887
|
useAttachmentManagerState,
|
|
28559
28888
|
useAttachmentsForPreview,
|
|
28560
28889
|
useAudioPlayer,
|
|
@@ -28563,13 +28892,13 @@ export {
|
|
|
28563
28892
|
useChannelActionContext,
|
|
28564
28893
|
useChannelDeletedListener,
|
|
28565
28894
|
useChannelDisplayName,
|
|
28566
|
-
|
|
28895
|
+
bv as useChannelEditMessageHandler,
|
|
28567
28896
|
useChannelHiddenListener,
|
|
28568
28897
|
useChannelListContext,
|
|
28569
28898
|
useChannelListItemContext,
|
|
28570
28899
|
useChannelMembersState,
|
|
28571
28900
|
useChannelMembershipState,
|
|
28572
|
-
|
|
28901
|
+
bw as useChannelMentionsHandler,
|
|
28573
28902
|
useChannelPreviewInfo,
|
|
28574
28903
|
useChannelStateContext,
|
|
28575
28904
|
useChannelTruncatedListener,
|
|
@@ -28594,7 +28923,7 @@ export {
|
|
|
28594
28923
|
useFlagHandler,
|
|
28595
28924
|
useGalleryContext,
|
|
28596
28925
|
useLastReadData,
|
|
28597
|
-
|
|
28926
|
+
d9 as useLegacyThreadContext,
|
|
28598
28927
|
useLiveLocationSharingManager,
|
|
28599
28928
|
useMarkUnreadHandler,
|
|
28600
28929
|
useMentionsHandler,
|