stream-chat-react 14.0.1 → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/emojis.js +8 -8
- package/dist/cjs/emojis.js.map +1 -1
- package/dist/cjs/index.js +18599 -16466
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{WithAudioPlayback.ba05c770.js → useNotificationApi.f2c7704d.js} +1442 -1363
- package/dist/cjs/useNotificationApi.f2c7704d.js.map +1 -0
- package/dist/css/index.css +614 -557
- package/dist/css/index.css.map +1 -1
- package/dist/es/emojis.mjs +1 -1
- package/dist/es/index.mjs +18216 -16083
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/{WithAudioPlayback.610fdf2c.mjs → useNotificationApi.f91ae46b.mjs} +1576 -1497
- package/dist/es/useNotificationApi.f91ae46b.mjs.map +1 -0
- package/dist/types/a11y/a11yUtils.d.ts +23 -0
- package/dist/types/a11y/a11yUtils.d.ts.map +1 -0
- package/dist/types/a11y/hooks/useAriaIdentifiers.d.ts +15 -0
- package/dist/types/a11y/hooks/useAriaIdentifiers.d.ts.map +1 -0
- package/dist/types/a11y/hooks/useResolvedModalAriaProps.d.ts +22 -0
- package/dist/types/a11y/hooks/useResolvedModalAriaProps.d.ts.map +1 -0
- package/dist/types/components/Accessibility/AriaLiveRegion.d.ts +3 -0
- package/dist/types/components/Accessibility/AriaLiveRegion.d.ts.map +1 -0
- package/dist/types/components/Accessibility/NotificationAnnouncer.d.ts +14 -0
- package/dist/types/components/Accessibility/NotificationAnnouncer.d.ts.map +1 -0
- package/dist/types/components/Accessibility/hooks/useIncomingMessageAnnouncements.d.ts +9 -0
- package/dist/types/components/Accessibility/hooks/useIncomingMessageAnnouncements.d.ts.map +1 -0
- package/dist/types/components/Accessibility/index.d.ts +5 -0
- package/dist/types/components/Accessibility/index.d.ts.map +1 -0
- package/dist/types/components/Accessibility/useAriaLiveAnnouncer.d.ts +9 -0
- package/dist/types/components/Accessibility/useAriaLiveAnnouncer.d.ts.map +1 -0
- package/dist/types/components/Attachment/Audio.d.ts.map +1 -1
- package/dist/types/components/Attachment/LinkPreview/CardAudio.d.ts.map +1 -1
- package/dist/types/components/Attachment/ModalGallery.d.ts.map +1 -1
- package/dist/types/components/Attachment/VoiceRecording.d.ts.map +1 -1
- package/dist/types/components/AudioPlayback/components/DurationDisplay.d.ts.map +1 -1
- package/dist/types/components/AudioPlayback/components/ProgressBar.d.ts +5 -1
- package/dist/types/components/AudioPlayback/components/ProgressBar.d.ts.map +1 -1
- package/dist/types/components/AudioPlayback/components/WaveProgressBar.d.ts +5 -1
- package/dist/types/components/AudioPlayback/components/WaveProgressBar.d.ts.map +1 -1
- package/dist/types/components/AudioPlayback/components/formatTime.d.ts +2 -0
- package/dist/types/components/AudioPlayback/components/formatTime.d.ts.map +1 -0
- package/dist/types/components/AudioPlayback/components/keyboardSeek.d.ts +12 -0
- package/dist/types/components/AudioPlayback/components/keyboardSeek.d.ts.map +1 -0
- package/dist/types/components/AudioPlayback/components/progressBarA11y.d.ts +10 -0
- package/dist/types/components/AudioPlayback/components/progressBarA11y.d.ts.map +1 -0
- package/dist/types/components/Avatar/Avatar.d.ts +1 -1
- package/dist/types/components/Avatar/Avatar.d.ts.map +1 -1
- package/dist/types/components/BaseImage/BaseImage.d.ts.map +1 -1
- package/dist/types/components/Button/PlayButton.d.ts.map +1 -1
- package/dist/types/components/ChannelList/hooks/usePaginatedChannels.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItem.d.ts +2 -0
- package/dist/types/components/ChannelListItem/ChannelListItem.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemUI.d.ts.map +1 -1
- package/dist/types/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/components/ChatView/ChatView.a11y.utility.d.ts +26 -0
- package/dist/types/components/ChatView/ChatView.a11y.utility.d.ts.map +1 -0
- package/dist/types/components/ChatView/ChatView.d.ts +9 -0
- package/dist/types/components/ChatView/ChatView.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Alert.d.ts +3 -1
- package/dist/types/components/Dialog/components/Alert.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts +31 -6
- package/dist/types/components/Dialog/components/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Prompt.d.ts +3 -1
- package/dist/types/components/Dialog/components/Prompt.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/Viewer.d.ts +3 -1
- package/dist/types/components/Dialog/components/Viewer.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogAnchor.d.ts.map +1 -1
- package/dist/types/components/Form/Dropdown.d.ts +2 -1
- package/dist/types/components/Form/Dropdown.d.ts.map +1 -1
- package/dist/types/components/Form/NumericInput.d.ts.map +1 -1
- package/dist/types/components/Form/SwitchField.d.ts +5 -2
- package/dist/types/components/Form/SwitchField.d.ts.map +1 -1
- package/dist/types/components/Form/TextInput.d.ts.map +1 -1
- package/dist/types/components/Icons/BaseIcon.d.ts +4 -1
- package/dist/types/components/Icons/BaseIcon.d.ts.map +1 -1
- package/dist/types/components/Icons/createIcon.d.ts +6 -3
- package/dist/types/components/Icons/createIcon.d.ts.map +1 -1
- package/dist/types/components/Icons/icons.d.ts +81 -82
- package/dist/types/components/Icons/icons.d.ts.map +1 -1
- package/dist/types/components/InfiniteScrollPaginator/InfiniteScroll.d.ts.map +1 -1
- package/dist/types/components/Loading/LoadingIndicator.d.ts +2 -2
- package/dist/types/components/Loading/LoadingIndicator.d.ts.map +1 -1
- package/dist/types/components/Location/ShareLocationDialog.d.ts +1 -0
- package/dist/types/components/Location/ShareLocationDialog.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecorderRecordingControls.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecordingButtonWithNotification.d.ts.map +1 -1
- package/dist/types/components/MediaRecorder/AudioRecorder/AudioRecordingPlayback.d.ts.map +1 -1
- package/dist/types/components/Message/Message.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/types.d.ts +4 -2
- package/dist/types/components/Message/types.d.ts.map +1 -1
- package/dist/types/components/MessageActions/DeleteMessageAlert.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
- package/dist/types/components/MessageBounce/MessageBouncePrompt.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/AttachmentPreviewList.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/AudioAttachmentPreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentPreviewList/utils/AttachmentPreviewRoot.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/AttachmentSelector.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/CommandsMenu.d.ts +2 -1
- package/dist/types/components/MessageComposer/AttachmentSelector/CommandsMenu.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/CommandChip.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/EditedMessagePreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/QuotedMessagePreview.d.ts +4 -2
- package/dist/types/components/MessageComposer/QuotedMessagePreview.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/WithDragAndDropUpload.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/hooks/index.d.ts +1 -0
- package/dist/types/components/MessageComposer/hooks/index.d.ts.map +1 -1
- package/dist/types/components/MessageComposer/hooks/useMessageComposerCommands.d.ts +9 -0
- package/dist/types/components/MessageComposer/hooks/useMessageComposerCommands.d.ts.map +1 -0
- package/dist/types/components/MessageList/MessageList.d.ts.map +1 -1
- package/dist/types/components/MessageList/NewMessageNotification.d.ts.map +1 -1
- package/dist/types/components/MessageList/ScrollToLatestMessageButton.d.ts +1 -2
- package/dist/types/components/MessageList/ScrollToLatestMessageButton.d.ts.map +1 -1
- package/dist/types/components/MessageList/UnreadMessagesNotification.d.ts.map +1 -1
- package/dist/types/components/MessageList/UnreadMessagesSeparator.d.ts.map +1 -1
- package/dist/types/components/MessageList/VirtualizedMessageList.d.ts +1 -1
- package/dist/types/components/MessageList/VirtualizedMessageList.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/MessageList/useMessageListScrollManager.d.ts +1 -0
- package/dist/types/components/MessageList/hooks/MessageList/useMessageListScrollManager.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/MessageList/useScrollLocationLogic.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/useReducedMotionPreference.d.ts +2 -0
- package/dist/types/components/MessageList/hooks/useReducedMotionPreference.d.ts.map +1 -0
- package/dist/types/components/Modal/CloseButtonOnModalOverlay.d.ts.map +1 -1
- package/dist/types/components/Modal/GlobalModal.d.ts +9 -1
- package/dist/types/components/Modal/GlobalModal.d.ts.map +1 -1
- package/dist/types/components/Notifications/Notification.d.ts.map +1 -1
- package/dist/types/components/Notifications/NotificationList.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/AddCommentPrompt.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/PollAnswerList.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/PollOptionsFullList.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/PollResults/PollResults.d.ts.map +1 -1
- package/dist/types/components/Poll/PollActions/SuggestPollOptionPrompt.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/MultipleAnswersField.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/NameField.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/OptionFieldSet.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/PollCreationDialog.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.map +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts.map +1 -1
- package/dist/types/components/Search/SearchBar/SearchBar.d.ts.map +1 -1
- package/dist/types/components/Search/SearchResults/SearchResultItem.d.ts.map +1 -1
- package/dist/types/components/Search/SearchResults/SearchResultsHeader.d.ts.map +1 -1
- package/dist/types/components/SkipNavigation/SkipNavigation.d.ts +38 -0
- package/dist/types/components/SkipNavigation/SkipNavigation.d.ts.map +1 -0
- package/dist/types/components/SkipNavigation/index.d.ts +2 -0
- package/dist/types/components/SkipNavigation/index.d.ts.map +1 -0
- package/dist/types/components/TextareaComposer/SuggestionList/CommandItem.d.ts +1 -0
- package/dist/types/components/TextareaComposer/SuggestionList/CommandItem.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 -0
- package/dist/types/components/TextareaComposer/TextareaComposer.d.ts.map +1 -1
- package/dist/types/components/Threads/ThreadList/ThreadList.d.ts.map +1 -1
- package/dist/types/components/TypingIndicator/TypingIndicator.d.ts.map +1 -1
- package/dist/types/components/TypingIndicator/TypingIndicatorHeader.d.ts.map +1 -1
- package/dist/types/components/TypingIndicator/utils/getTypingStatusMessage.d.ts +8 -0
- package/dist/types/components/TypingIndicator/utils/getTypingStatusMessage.d.ts.map +1 -0
- package/dist/types/components/VisuallyHidden/VisuallyHidden.d.ts +7 -0
- package/dist/types/components/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/types/components/VisuallyHidden/index.d.ts +2 -0
- package/dist/types/components/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +3 -0
- package/dist/types/components/index.d.ts.map +1 -1
- package/dist/types/context/ComponentContext.d.ts +10 -1
- package/dist/types/context/ComponentContext.d.ts.map +1 -1
- package/dist/types/context/ModalContext.d.ts +1 -0
- package/dist/types/context/ModalContext.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +1 -0
- package/dist/types/context/index.d.ts.map +1 -1
- package/dist/types/i18n/Streami18n.d.ts +61 -2
- package/dist/types/i18n/Streami18n.d.ts.map +1 -1
- package/dist/types/i18n/TranslationBuilder/notifications/translators.d.ts +1 -0
- package/dist/types/i18n/TranslationBuilder/notifications/translators.d.ts.map +1 -1
- package/dist/types/i18n/TranslationBuilder/notifications/translatorsByNotificationType.d.ts.map +1 -1
- package/package.json +9 -5
- package/dist/cjs/WithAudioPlayback.ba05c770.js.map +0 -1
- package/dist/es/WithAudioPlayback.610fdf2c.mjs.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React, { useContext, createContext, useCallback, useMemo, forwardRef, useRef, useEffect,
|
|
2
|
+
import React, { useContext, createContext, useCallback, useMemo, forwardRef, useRef, useEffect, useState, createElement, useReducer, useLayoutEffect, useId } from "react";
|
|
3
3
|
import { flip, shift, size, useFloating, autoUpdate, autoPlacement, offset } from "@floating-ui/react";
|
|
4
4
|
import { StateStore, MessageComposer, FixedSizeQueueCache, ErrorFromResponse, localMessageToNewMessagePayload } from "stream-chat";
|
|
5
|
-
import throttle from "lodash.throttle";
|
|
6
|
-
import { useSyncExternalStore } from "use-sync-external-store/shim";
|
|
7
5
|
import clsx from "clsx";
|
|
8
6
|
import debounce from "lodash.debounce";
|
|
7
|
+
import throttle from "lodash.throttle";
|
|
9
8
|
import Dayjs from "dayjs";
|
|
10
9
|
import * as linkify from "linkifyjs";
|
|
10
|
+
import { useSyncExternalStore } from "use-sync-external-store/shim";
|
|
11
11
|
import { nanoid } from "nanoid";
|
|
12
12
|
import deepequal from "react-fast-compare";
|
|
13
13
|
import emojiRegex from "emoji-regex";
|
|
@@ -372,15 +372,96 @@ const useTypingContext = (componentName) => {
|
|
|
372
372
|
}
|
|
373
373
|
return contextValue;
|
|
374
374
|
};
|
|
375
|
-
const
|
|
376
|
-
"
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
375
|
+
const NOTIFICATION_TARGET_PANELS = [
|
|
376
|
+
"channel",
|
|
377
|
+
"thread",
|
|
378
|
+
"channel-list",
|
|
379
|
+
"thread-list"
|
|
380
|
+
];
|
|
381
|
+
const isNotificationTargetPanel = (value) => typeof value === "string" && NOTIFICATION_TARGET_PANELS.includes(value);
|
|
382
|
+
const getNotificationTargetPanel = (notification) => {
|
|
383
|
+
const targetTag = notification.tags?.find((tag) => tag.startsWith("target:"));
|
|
384
|
+
if (targetTag) {
|
|
385
|
+
const candidate = targetTag.slice("target:".length);
|
|
386
|
+
if (isNotificationTargetPanel(candidate)) return candidate;
|
|
382
387
|
}
|
|
383
|
-
|
|
388
|
+
const panel = notification.origin.context?.panel;
|
|
389
|
+
return isNotificationTargetPanel(panel) ? panel : void 0;
|
|
390
|
+
};
|
|
391
|
+
const getNotificationTargetPanels = (notification) => {
|
|
392
|
+
const targetPanels = (notification.tags ?? []).filter((tag) => tag.startsWith("target:")).map((tag) => tag.slice("target:".length)).filter(
|
|
393
|
+
(value) => isNotificationTargetPanel(value)
|
|
394
|
+
);
|
|
395
|
+
if (targetPanels.length > 0) {
|
|
396
|
+
return Array.from(new Set(targetPanels));
|
|
397
|
+
}
|
|
398
|
+
const panel = notification.origin.context?.panel;
|
|
399
|
+
return isNotificationTargetPanel(panel) ? [panel] : [];
|
|
400
|
+
};
|
|
401
|
+
const getNotificationTargetTag = (panel) => `target:${panel}`;
|
|
402
|
+
const addNotificationTargetTag = (panel, tags) => {
|
|
403
|
+
if (!panel) return tags ?? [];
|
|
404
|
+
return Array.from(/* @__PURE__ */ new Set([getNotificationTargetTag(panel), ...tags ?? []]));
|
|
405
|
+
};
|
|
406
|
+
const isNotificationForPanel = (notification, panel, options) => {
|
|
407
|
+
const explicitTargetPanels = getNotificationTargetPanels(notification);
|
|
408
|
+
if (explicitTargetPanels.length > 0) {
|
|
409
|
+
return explicitTargetPanels.includes(panel);
|
|
410
|
+
}
|
|
411
|
+
const resolvedPanel = options?.fallbackPanel ?? "channel";
|
|
412
|
+
return resolvedPanel === panel;
|
|
413
|
+
};
|
|
414
|
+
const variantToClass = {
|
|
415
|
+
danger: "str-chat__button--destructive",
|
|
416
|
+
primary: "str-chat__button--primary",
|
|
417
|
+
secondary: "str-chat__button--secondary"
|
|
418
|
+
};
|
|
419
|
+
const appearanceToClass = {
|
|
420
|
+
ghost: "str-chat__button--ghost",
|
|
421
|
+
outline: "str-chat__button--outline",
|
|
422
|
+
solid: "str-chat__button--solid"
|
|
423
|
+
};
|
|
424
|
+
const sizeToClass = {
|
|
425
|
+
lg: "str-chat__button--size-lg",
|
|
426
|
+
md: "str-chat__button--size-md",
|
|
427
|
+
sm: "str-chat__button--size-sm",
|
|
428
|
+
xs: "str-chat__button--size-xs"
|
|
429
|
+
};
|
|
430
|
+
const Button = forwardRef(function Button2({ appearance, children, circular, className, inverseTheme, size: size2, variant, ...props }, ref) {
|
|
431
|
+
return /* @__PURE__ */ jsx(
|
|
432
|
+
"button",
|
|
433
|
+
{
|
|
434
|
+
ref,
|
|
435
|
+
type: "button",
|
|
436
|
+
...props,
|
|
437
|
+
className: clsx(
|
|
438
|
+
"str-chat__button",
|
|
439
|
+
variant != null && variantToClass[variant],
|
|
440
|
+
appearance != null && appearanceToClass[appearance],
|
|
441
|
+
circular && "str-chat__button--circular",
|
|
442
|
+
inverseTheme && "str-chat__theme-inverse",
|
|
443
|
+
size2 != null && sizeToClass[size2],
|
|
444
|
+
className
|
|
445
|
+
),
|
|
446
|
+
children: /* @__PURE__ */ jsx("div", { className: "str-chat__button__content", children })
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
});
|
|
450
|
+
const BaseIcon = ({ className, decorative = true, ...props }) => {
|
|
451
|
+
const ariaHidden = props["aria-hidden"] ?? (decorative ? true : void 0);
|
|
452
|
+
const focusable = props.focusable ?? (decorative ? false : void 0);
|
|
453
|
+
return /* @__PURE__ */ jsx(
|
|
454
|
+
"svg",
|
|
455
|
+
{
|
|
456
|
+
viewBox: "0 0 20 20",
|
|
457
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
458
|
+
...props,
|
|
459
|
+
"aria-hidden": ariaHidden,
|
|
460
|
+
className: clsx("str-chat__icon", className),
|
|
461
|
+
focusable
|
|
462
|
+
}
|
|
463
|
+
);
|
|
464
|
+
};
|
|
384
465
|
function toIconClass(name) {
|
|
385
466
|
return "str-chat__icon--" + name.replace(/^Icon/, "").replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Za-z])(\d)/g, "$1-$2").replace(/(\d)([A-Za-z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
|
|
386
467
|
}
|
|
@@ -1495,977 +1576,259 @@ const IconGiphy = createIcon(
|
|
|
1495
1576
|
)
|
|
1496
1577
|
] })
|
|
1497
1578
|
);
|
|
1498
|
-
const
|
|
1499
|
-
const
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1579
|
+
const UnMemoizedEmptyStateIndicator = (props) => {
|
|
1580
|
+
const { listType, messageText } = props;
|
|
1581
|
+
const { t } = useTranslationContext("EmptyStateIndicator");
|
|
1582
|
+
if (listType === "thread") return null;
|
|
1583
|
+
if (listType === "channel") {
|
|
1584
|
+
const text = t("No conversations yet");
|
|
1585
|
+
return /* @__PURE__ */ jsxs("div", { className: "str-chat__channel-list-empty", children: [
|
|
1586
|
+
/* @__PURE__ */ jsx(IconMessageBubbles, {}),
|
|
1587
|
+
/* @__PURE__ */ jsx("p", { role: "listitem", children: text })
|
|
1588
|
+
] });
|
|
1589
|
+
}
|
|
1590
|
+
if (listType === "message") {
|
|
1591
|
+
const text = t(messageText || "Send a message to start the conversation");
|
|
1592
|
+
return /* @__PURE__ */ jsxs("div", { className: "str-chat__empty-channel", children: [
|
|
1593
|
+
/* @__PURE__ */ jsx(IconMessageBubble, {}),
|
|
1594
|
+
/* @__PURE__ */ jsx("p", { className: "str-chat__empty-channel-text", role: "listitem", children: text })
|
|
1595
|
+
] });
|
|
1596
|
+
}
|
|
1597
|
+
return /* @__PURE__ */ jsx("p", { children: t("No items exist") });
|
|
1505
1598
|
};
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
title,
|
|
1518
|
-
waveformData
|
|
1519
|
-
}) {
|
|
1520
|
-
this._plugins = /* @__PURE__ */ new Map();
|
|
1521
|
-
this.playTimeout = void 0;
|
|
1522
|
-
this.unsubscribeEventListeners = null;
|
|
1523
|
-
this._disposed = false;
|
|
1524
|
-
this._metadataProbe = null;
|
|
1525
|
-
this._restoringPosition = false;
|
|
1526
|
-
this._removalTimeout = void 0;
|
|
1527
|
-
this.setDurationSeconds = (durationSeconds2) => {
|
|
1528
|
-
this._data.durationSeconds = durationSeconds2;
|
|
1529
|
-
this.state.partialNext({ durationSeconds: durationSeconds2 });
|
|
1530
|
-
};
|
|
1531
|
-
this.setPlaybackStartSafetyTimeout = () => {
|
|
1532
|
-
clearTimeout(this.playTimeout);
|
|
1533
|
-
this.playTimeout = setTimeout(() => {
|
|
1534
|
-
if (!this.elementRef) return;
|
|
1535
|
-
try {
|
|
1536
|
-
this.elementRef.pause();
|
|
1537
|
-
this.state.partialNext({ isPlaying: false });
|
|
1538
|
-
} catch (e) {
|
|
1539
|
-
this.registerError({ errCode: "failed-to-start" });
|
|
1540
|
-
}
|
|
1541
|
-
}, 2e3);
|
|
1542
|
-
};
|
|
1543
|
-
this.updateDurationFromElement = (element) => {
|
|
1544
|
-
const duration = element.duration;
|
|
1545
|
-
if (typeof duration !== "number" || isNaN(duration) || !isFinite(duration) || duration <= 0) {
|
|
1546
|
-
return;
|
|
1547
|
-
}
|
|
1548
|
-
this.setDurationSeconds(duration);
|
|
1549
|
-
};
|
|
1550
|
-
this.clearMetadataProbe = () => {
|
|
1551
|
-
const probe = this._metadataProbe;
|
|
1552
|
-
this._metadataProbe = null;
|
|
1553
|
-
this._metadataProbePromise = void 0;
|
|
1554
|
-
if (!probe) return;
|
|
1555
|
-
try {
|
|
1556
|
-
probe.pause();
|
|
1557
|
-
} catch {
|
|
1558
|
-
}
|
|
1559
|
-
probe.removeAttribute("src");
|
|
1560
|
-
try {
|
|
1561
|
-
probe.load();
|
|
1562
|
-
} catch {
|
|
1563
|
-
}
|
|
1564
|
-
};
|
|
1565
|
-
this.preloadMetadata = () => {
|
|
1566
|
-
if (this._disposed || this.durationSeconds != null || !this.src || this._metadataProbePromise || typeof document === "undefined") {
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
const probe = document.createElement("audio");
|
|
1570
|
-
probe.preload = "metadata";
|
|
1571
|
-
this._metadataProbe = probe;
|
|
1572
|
-
this._metadataProbePromise = new Promise((resolve) => {
|
|
1573
|
-
const cleanup = () => {
|
|
1574
|
-
probe.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
1575
|
-
probe.removeEventListener("error", handleError);
|
|
1576
|
-
if (this._metadataProbe === probe) {
|
|
1577
|
-
this.clearMetadataProbe();
|
|
1578
|
-
} else {
|
|
1579
|
-
this._metadataProbePromise = void 0;
|
|
1580
|
-
}
|
|
1581
|
-
resolve();
|
|
1582
|
-
};
|
|
1583
|
-
const handleLoadedMetadata = () => {
|
|
1584
|
-
this.updateDurationFromElement(probe);
|
|
1585
|
-
cleanup();
|
|
1586
|
-
};
|
|
1587
|
-
const handleError = () => {
|
|
1588
|
-
cleanup();
|
|
1589
|
-
};
|
|
1590
|
-
probe.addEventListener("loadedmetadata", handleLoadedMetadata, { once: true });
|
|
1591
|
-
probe.addEventListener("error", handleError, { once: true });
|
|
1592
|
-
probe.src = this.src;
|
|
1593
|
-
try {
|
|
1594
|
-
probe.load();
|
|
1595
|
-
} catch {
|
|
1596
|
-
cleanup();
|
|
1597
|
-
}
|
|
1598
|
-
});
|
|
1599
|
-
};
|
|
1600
|
-
this.clearPlaybackStartSafetyTimeout = () => {
|
|
1601
|
-
if (!this.elementRef) return;
|
|
1602
|
-
clearTimeout(this.playTimeout);
|
|
1603
|
-
this.playTimeout = void 0;
|
|
1604
|
-
};
|
|
1605
|
-
this.clearPendingLoadedMeta = () => {
|
|
1606
|
-
const pending = this._pendingLoadedMeta;
|
|
1607
|
-
if (pending?.element && pending.onLoaded) {
|
|
1608
|
-
pending.element.removeEventListener("loadedmetadata", pending.onLoaded);
|
|
1609
|
-
}
|
|
1610
|
-
this._pendingLoadedMeta = void 0;
|
|
1611
|
-
};
|
|
1612
|
-
this.restoreSavedPosition = (elementRef) => {
|
|
1613
|
-
const saved = this.secondsElapsed;
|
|
1614
|
-
if (!saved || saved <= 0) return;
|
|
1615
|
-
const apply = () => {
|
|
1616
|
-
const duration = elementRef.duration;
|
|
1617
|
-
const clamped = typeof duration === "number" && !isNaN(duration) && isFinite(duration) ? Math.min(saved, duration) : saved;
|
|
1618
|
-
try {
|
|
1619
|
-
if (elementRef.currentTime === clamped) return;
|
|
1620
|
-
elementRef.currentTime = clamped;
|
|
1621
|
-
this.setSecondsElapsed(clamped);
|
|
1622
|
-
} catch {
|
|
1623
|
-
}
|
|
1599
|
+
const EmptyStateIndicator = React.memo(
|
|
1600
|
+
UnMemoizedEmptyStateIndicator
|
|
1601
|
+
);
|
|
1602
|
+
const makeChannelReducer = () => (state, action) => {
|
|
1603
|
+
switch (action.type) {
|
|
1604
|
+
case "closeThread": {
|
|
1605
|
+
return {
|
|
1606
|
+
...state,
|
|
1607
|
+
thread: null,
|
|
1608
|
+
threadLoadingMore: false,
|
|
1609
|
+
threadMessages: []
|
|
1624
1610
|
};
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
apply();
|
|
1636
|
-
this._restoringPosition = false;
|
|
1637
|
-
};
|
|
1638
|
-
elementRef.addEventListener("loadedmetadata", onLoaded, { once: true });
|
|
1639
|
-
this._pendingLoadedMeta = { element: elementRef, onLoaded };
|
|
1640
|
-
} else {
|
|
1641
|
-
this._restoringPosition = true;
|
|
1642
|
-
apply();
|
|
1643
|
-
this._restoringPosition = false;
|
|
1644
|
-
}
|
|
1645
|
-
};
|
|
1646
|
-
this.elementIsReady = () => {
|
|
1647
|
-
if (this._elementIsReadyPromise) return this._elementIsReadyPromise;
|
|
1648
|
-
this._elementIsReadyPromise = new Promise((resolve) => {
|
|
1649
|
-
if (!this.elementRef) return resolve(false);
|
|
1650
|
-
const element = this.elementRef;
|
|
1651
|
-
const handleLoaded = () => {
|
|
1652
|
-
element.removeEventListener("loadedmetadata", handleLoaded);
|
|
1653
|
-
resolve(element.readyState > 0);
|
|
1654
|
-
};
|
|
1655
|
-
element.addEventListener("loadedmetadata", handleLoaded);
|
|
1656
|
-
});
|
|
1657
|
-
return this._elementIsReadyPromise;
|
|
1658
|
-
};
|
|
1659
|
-
this.setRef = (elementRef) => {
|
|
1660
|
-
if (elementIsPlaying(this.elementRef)) {
|
|
1661
|
-
this.releaseElement({ resetState: false });
|
|
1662
|
-
}
|
|
1663
|
-
this.clearPendingLoadedMeta();
|
|
1664
|
-
this.clearMetadataProbe();
|
|
1665
|
-
this._restoringPosition = false;
|
|
1666
|
-
this._elementIsReadyPromise = void 0;
|
|
1667
|
-
this.state.partialNext({ elementRef });
|
|
1668
|
-
if (elementRef) {
|
|
1669
|
-
this.registerSubscriptions();
|
|
1670
|
-
}
|
|
1671
|
-
};
|
|
1672
|
-
this.setSecondsElapsed = (secondsElapsed) => {
|
|
1673
|
-
const duration = this.elementRef?.duration ?? this.durationSeconds;
|
|
1674
|
-
this.state.partialNext({
|
|
1675
|
-
progressPercent: duration && secondsElapsed ? secondsElapsed / duration * 100 : 0,
|
|
1676
|
-
secondsElapsed
|
|
1677
|
-
});
|
|
1678
|
-
};
|
|
1679
|
-
this.canPlayMimeType = (mimeType2) => {
|
|
1680
|
-
if (!mimeType2) return false;
|
|
1681
|
-
if (this.elementRef) return !!this.elementRef.canPlayType(mimeType2);
|
|
1682
|
-
return !!new Audio().canPlayType(mimeType2);
|
|
1683
|
-
};
|
|
1684
|
-
this.play = async (params) => {
|
|
1685
|
-
if (this._disposed) return;
|
|
1686
|
-
const elementRef = this.ensureElementRef();
|
|
1687
|
-
if (elementIsPlaying(this.elementRef)) {
|
|
1688
|
-
if (this.isPlaying) return;
|
|
1689
|
-
this.state.partialNext({ isPlaying: true });
|
|
1690
|
-
return;
|
|
1691
|
-
}
|
|
1692
|
-
const { currentPlaybackRate, playbackRates: playbackRates2 } = {
|
|
1693
|
-
currentPlaybackRate: this.currentPlaybackRate,
|
|
1694
|
-
playbackRates: this.playbackRates,
|
|
1695
|
-
...params
|
|
1611
|
+
}
|
|
1612
|
+
case "copyMessagesFromChannel": {
|
|
1613
|
+
const { channel, parentId } = action;
|
|
1614
|
+
return {
|
|
1615
|
+
...state,
|
|
1616
|
+
messages: [...channel.state.messages],
|
|
1617
|
+
pinnedMessages: [...channel.state.pinnedMessages],
|
|
1618
|
+
// copying messages from channel happens with new message - this resets the suppressAutoscroll
|
|
1619
|
+
suppressAutoscroll: false,
|
|
1620
|
+
threadMessages: parentId ? { ...channel.state.threads }[parentId] || [] : state.threadMessages
|
|
1696
1621
|
};
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
isPlaying: true,
|
|
1709
|
-
playbackRates: playbackRates2
|
|
1710
|
-
});
|
|
1711
|
-
this._pool.setActiveAudioPlayer(this);
|
|
1712
|
-
} catch (e) {
|
|
1713
|
-
this.registerError({ error: e });
|
|
1714
|
-
this.state.partialNext({ isPlaying: false });
|
|
1715
|
-
} finally {
|
|
1716
|
-
this.clearPlaybackStartSafetyTimeout();
|
|
1717
|
-
}
|
|
1718
|
-
};
|
|
1719
|
-
this.pause = () => {
|
|
1720
|
-
if (!elementIsPlaying(this.elementRef)) return;
|
|
1721
|
-
this.clearPlaybackStartSafetyTimeout();
|
|
1722
|
-
this.elementRef.pause();
|
|
1723
|
-
this.state.partialNext({ isPlaying: false });
|
|
1724
|
-
};
|
|
1725
|
-
this.stop = () => {
|
|
1726
|
-
this.pause();
|
|
1727
|
-
this.state.partialNext({ isPlaying: false });
|
|
1728
|
-
this.setSecondsElapsed(0);
|
|
1729
|
-
if (this.elementRef) this.elementRef.currentTime = 0;
|
|
1730
|
-
};
|
|
1731
|
-
this.togglePlay = async () => this.isPlaying ? this.pause() : await this.play();
|
|
1732
|
-
this.increasePlaybackRate = () => {
|
|
1733
|
-
let currentPlaybackRateIndex = this.state.getLatestValue().playbackRates.findIndex((rate) => rate === this.currentPlaybackRate);
|
|
1734
|
-
if (currentPlaybackRateIndex === -1) {
|
|
1735
|
-
currentPlaybackRateIndex = 0;
|
|
1736
|
-
}
|
|
1737
|
-
const nextIndex = currentPlaybackRateIndex === this.playbackRates.length - 1 ? 0 : currentPlaybackRateIndex + 1;
|
|
1738
|
-
const currentPlaybackRate = this.playbackRates[nextIndex];
|
|
1739
|
-
this.state.partialNext({ currentPlaybackRate });
|
|
1740
|
-
if (this.elementRef) {
|
|
1741
|
-
this.elementRef.playbackRate = currentPlaybackRate;
|
|
1742
|
-
}
|
|
1743
|
-
};
|
|
1744
|
-
this.seek = throttle(async ({ clientX, currentTarget }) => {
|
|
1745
|
-
let element = this.elementRef;
|
|
1746
|
-
if (!this.elementRef) {
|
|
1747
|
-
element = this.ensureElementRef();
|
|
1748
|
-
const isReady = await this.elementIsReady();
|
|
1749
|
-
if (!isReady) return;
|
|
1750
|
-
}
|
|
1751
|
-
if (!currentTarget || !element) return;
|
|
1752
|
-
if (!isSeekable(element)) {
|
|
1753
|
-
this.registerError({ errCode: "seek-not-supported" });
|
|
1754
|
-
return;
|
|
1755
|
-
}
|
|
1756
|
-
const { width, x } = currentTarget.getBoundingClientRect();
|
|
1757
|
-
const ratio = (clientX - x) / width;
|
|
1758
|
-
if (ratio > 1 || ratio < 0) return;
|
|
1759
|
-
const currentTime = ratio * element.duration;
|
|
1760
|
-
this.setSecondsElapsed(currentTime);
|
|
1761
|
-
element.currentTime = currentTime;
|
|
1762
|
-
}, 16);
|
|
1763
|
-
this.registerError = (params) => {
|
|
1764
|
-
defaultRegisterAudioPlayerError(params);
|
|
1765
|
-
this.plugins.forEach(({ onError }) => onError?.({ player: this, ...params }));
|
|
1766
|
-
};
|
|
1767
|
-
this.requestRemoval = () => {
|
|
1768
|
-
this._disposed = true;
|
|
1769
|
-
this.cancelScheduledRemoval();
|
|
1770
|
-
this.clearPendingLoadedMeta();
|
|
1771
|
-
this.clearMetadataProbe();
|
|
1772
|
-
this._restoringPosition = false;
|
|
1773
|
-
this.releaseElement({ resetState: true });
|
|
1774
|
-
this.unsubscribeEventListeners?.();
|
|
1775
|
-
this.unsubscribeEventListeners = null;
|
|
1776
|
-
this.plugins.forEach(({ onRemove }) => onRemove?.({ player: this }));
|
|
1777
|
-
this._pool.deregister(this.id);
|
|
1778
|
-
};
|
|
1779
|
-
this.cancelScheduledRemoval = () => {
|
|
1780
|
-
clearTimeout(this._removalTimeout);
|
|
1781
|
-
this._removalTimeout = void 0;
|
|
1782
|
-
};
|
|
1783
|
-
this.scheduleRemoval = (ms = 0) => {
|
|
1784
|
-
this.cancelScheduledRemoval();
|
|
1785
|
-
this._removalTimeout = setTimeout(() => {
|
|
1786
|
-
if (this.disposed) return;
|
|
1787
|
-
this.requestRemoval();
|
|
1788
|
-
}, ms);
|
|
1789
|
-
};
|
|
1790
|
-
this.releaseElementForHandoff = () => {
|
|
1791
|
-
if (!this.elementRef) return;
|
|
1792
|
-
this.releaseElement({ resetState: false });
|
|
1793
|
-
this.unsubscribeEventListeners?.();
|
|
1794
|
-
this.unsubscribeEventListeners = null;
|
|
1795
|
-
};
|
|
1796
|
-
this.registerSubscriptions = () => {
|
|
1797
|
-
this.unsubscribeEventListeners?.();
|
|
1798
|
-
const audioElement = this.elementRef;
|
|
1799
|
-
if (!audioElement) return;
|
|
1800
|
-
const handleEnded = () => {
|
|
1801
|
-
if (audioElement) {
|
|
1802
|
-
this.updateDurationFromElement(audioElement);
|
|
1803
|
-
}
|
|
1804
|
-
this.stop();
|
|
1622
|
+
}
|
|
1623
|
+
case "copyStateFromChannelOnEvent": {
|
|
1624
|
+
const { channel } = action;
|
|
1625
|
+
return {
|
|
1626
|
+
...state,
|
|
1627
|
+
members: { ...channel.state.members },
|
|
1628
|
+
messages: [...channel.state.messages],
|
|
1629
|
+
pinnedMessages: [...channel.state.pinnedMessages],
|
|
1630
|
+
read: { ...channel.state.read },
|
|
1631
|
+
watcherCount: channel.state.watcher_count,
|
|
1632
|
+
watchers: { ...channel.state.watchers }
|
|
1805
1633
|
};
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
"MEDIA_ERR_ABORTED: fetch aborted by user",
|
|
1820
|
-
"MEDIA_ERR_NETWORK: network failed while fetching",
|
|
1821
|
-
"MEDIA_ERR_DECODE: audio fetched but couldn’t decode",
|
|
1822
|
-
"MEDIA_ERR_SRC_NOT_SUPPORTED: source not supported"
|
|
1823
|
-
][audio?.error?.code];
|
|
1824
|
-
if (!errorMsg) return;
|
|
1825
|
-
defaultRegisterAudioPlayerError({ error: new Error(errorMsg + ` (${audio.src})`) });
|
|
1634
|
+
}
|
|
1635
|
+
case "initStateFromChannel": {
|
|
1636
|
+
const { channel, hasMore } = action;
|
|
1637
|
+
return {
|
|
1638
|
+
...state,
|
|
1639
|
+
hasMore,
|
|
1640
|
+
loading: false,
|
|
1641
|
+
members: { ...channel.state.members },
|
|
1642
|
+
messages: [...channel.state.messages],
|
|
1643
|
+
pinnedMessages: [...channel.state.pinnedMessages],
|
|
1644
|
+
read: { ...channel.state.read },
|
|
1645
|
+
watcherCount: channel.state.watcher_count,
|
|
1646
|
+
watchers: { ...channel.state.watchers }
|
|
1826
1647
|
};
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1648
|
+
}
|
|
1649
|
+
case "jumpToLatestMessageFinished": {
|
|
1650
|
+
const { hasMore, hasMoreNewer, messages } = action;
|
|
1651
|
+
return {
|
|
1652
|
+
...state,
|
|
1653
|
+
hasMore,
|
|
1654
|
+
hasMoreNewer,
|
|
1655
|
+
highlightedMessageId: void 0,
|
|
1656
|
+
loading: false,
|
|
1657
|
+
messages,
|
|
1658
|
+
suppressAutoscroll: false
|
|
1832
1659
|
};
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1660
|
+
}
|
|
1661
|
+
case "jumpToMessageFinished": {
|
|
1662
|
+
return {
|
|
1663
|
+
...state,
|
|
1664
|
+
hasMore: action.channel.state.messagePagination.hasPrev,
|
|
1665
|
+
hasMoreNewer: action.channel.state.messagePagination.hasNext,
|
|
1666
|
+
highlightedMessageId: action.highlightedMessageId,
|
|
1667
|
+
loadingMore: false,
|
|
1668
|
+
loadingMoreForJumpToChannelMessage: false,
|
|
1669
|
+
messages: action.channel.state.messages,
|
|
1670
|
+
suppressAutoscroll: false
|
|
1837
1671
|
};
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
audioElement.pause();
|
|
1844
|
-
audioElement.removeEventListener("ended", handleEnded);
|
|
1845
|
-
audioElement.removeEventListener("error", handleError);
|
|
1846
|
-
audioElement.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
1847
|
-
audioElement.removeEventListener("timeupdate", handleTimeupdate);
|
|
1672
|
+
}
|
|
1673
|
+
case "clearHighlightedMessage": {
|
|
1674
|
+
return {
|
|
1675
|
+
...state,
|
|
1676
|
+
highlightedMessageId: void 0
|
|
1848
1677
|
};
|
|
1849
|
-
};
|
|
1850
|
-
this._data = {
|
|
1851
|
-
durationSeconds,
|
|
1852
|
-
fileSize,
|
|
1853
|
-
id,
|
|
1854
|
-
mimeType,
|
|
1855
|
-
src,
|
|
1856
|
-
title,
|
|
1857
|
-
waveformData
|
|
1858
|
-
};
|
|
1859
|
-
this._pool = pool;
|
|
1860
|
-
this.setPlugins(() => plugins ?? []);
|
|
1861
|
-
const playbackRates = customPlaybackRates?.length ? customPlaybackRates : DEFAULT_PLAYBACK_RATES;
|
|
1862
|
-
const canPlayRecord = mimeType ? !!new Audio().canPlayType(mimeType) : true;
|
|
1863
|
-
this.state = new StateStore({
|
|
1864
|
-
canPlayRecord,
|
|
1865
|
-
currentPlaybackRate: playbackRates[0],
|
|
1866
|
-
durationSeconds,
|
|
1867
|
-
elementRef: null,
|
|
1868
|
-
isPlaying: false,
|
|
1869
|
-
playbackError: null,
|
|
1870
|
-
playbackRates,
|
|
1871
|
-
progressPercent: 0,
|
|
1872
|
-
secondsElapsed: 0
|
|
1873
|
-
});
|
|
1874
|
-
this.plugins.forEach((p) => p.onInit?.({ player: this }));
|
|
1875
|
-
this.preloadMetadata();
|
|
1876
|
-
}
|
|
1877
|
-
get plugins() {
|
|
1878
|
-
return Array.from(this._plugins.values());
|
|
1879
|
-
}
|
|
1880
|
-
get canPlayRecord() {
|
|
1881
|
-
return this.state.getLatestValue().canPlayRecord;
|
|
1882
|
-
}
|
|
1883
|
-
get elementRef() {
|
|
1884
|
-
return this.state.getLatestValue().elementRef;
|
|
1885
|
-
}
|
|
1886
|
-
get isPlaying() {
|
|
1887
|
-
return this.state.getLatestValue().isPlaying;
|
|
1888
|
-
}
|
|
1889
|
-
get currentPlaybackRate() {
|
|
1890
|
-
return this.state.getLatestValue().currentPlaybackRate;
|
|
1891
|
-
}
|
|
1892
|
-
get playbackRates() {
|
|
1893
|
-
return this.state.getLatestValue().playbackRates;
|
|
1894
|
-
}
|
|
1895
|
-
get durationSeconds() {
|
|
1896
|
-
return this.state.getLatestValue().durationSeconds;
|
|
1897
|
-
}
|
|
1898
|
-
get fileSize() {
|
|
1899
|
-
return this._data.fileSize;
|
|
1900
|
-
}
|
|
1901
|
-
get id() {
|
|
1902
|
-
return this._data.id;
|
|
1903
|
-
}
|
|
1904
|
-
get src() {
|
|
1905
|
-
return this._data.src;
|
|
1906
|
-
}
|
|
1907
|
-
get mimeType() {
|
|
1908
|
-
return this._data.mimeType;
|
|
1909
|
-
}
|
|
1910
|
-
get title() {
|
|
1911
|
-
return this._data.title;
|
|
1912
|
-
}
|
|
1913
|
-
get waveformData() {
|
|
1914
|
-
return this._data.waveformData;
|
|
1915
|
-
}
|
|
1916
|
-
get secondsElapsed() {
|
|
1917
|
-
return this.state.getLatestValue().secondsElapsed;
|
|
1918
|
-
}
|
|
1919
|
-
get progressPercent() {
|
|
1920
|
-
return this.state.getLatestValue().progressPercent;
|
|
1921
|
-
}
|
|
1922
|
-
get disposed() {
|
|
1923
|
-
return this._disposed;
|
|
1924
|
-
}
|
|
1925
|
-
ensureElementRef() {
|
|
1926
|
-
if (this._disposed) {
|
|
1927
|
-
throw new Error("AudioPlayer is disposed");
|
|
1928
1678
|
}
|
|
1929
|
-
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1679
|
+
case "loadMoreFinished": {
|
|
1680
|
+
const { hasMore, messages } = action;
|
|
1681
|
+
return {
|
|
1682
|
+
...state,
|
|
1683
|
+
hasMore,
|
|
1684
|
+
loadingMore: false,
|
|
1685
|
+
messages,
|
|
1686
|
+
suppressAutoscroll: false
|
|
1687
|
+
};
|
|
1935
1688
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1689
|
+
case "loadMoreNewerFinished": {
|
|
1690
|
+
const { hasMoreNewer, messages } = action;
|
|
1691
|
+
return {
|
|
1692
|
+
...state,
|
|
1693
|
+
hasMoreNewer,
|
|
1694
|
+
loadingMoreNewer: false,
|
|
1695
|
+
messages
|
|
1696
|
+
};
|
|
1943
1697
|
}
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
}
|
|
1952
|
-
return;
|
|
1698
|
+
case "loadMoreThreadFinished": {
|
|
1699
|
+
const { threadHasMore, threadMessages } = action;
|
|
1700
|
+
return {
|
|
1701
|
+
...state,
|
|
1702
|
+
threadHasMore,
|
|
1703
|
+
threadLoadingMore: false,
|
|
1704
|
+
threadMessages
|
|
1705
|
+
};
|
|
1953
1706
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1707
|
+
case "openThread": {
|
|
1708
|
+
const { channel, message } = action;
|
|
1709
|
+
return {
|
|
1710
|
+
...state,
|
|
1711
|
+
thread: message,
|
|
1712
|
+
threadHasMore: true,
|
|
1713
|
+
threadMessages: message.id ? { ...channel.state.threads }[message.id] || [] : [],
|
|
1714
|
+
threadSuppressAutoscroll: false
|
|
1715
|
+
};
|
|
1956
1716
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
this.clearMetadataProbe();
|
|
1961
|
-
this._restoringPosition = false;
|
|
1962
|
-
if (resetState) {
|
|
1963
|
-
this.stop();
|
|
1964
|
-
} else {
|
|
1965
|
-
this.state.partialNext({ isPlaying: false });
|
|
1966
|
-
if (this.elementRef) {
|
|
1967
|
-
try {
|
|
1968
|
-
this.elementRef.pause();
|
|
1969
|
-
} catch {
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1717
|
+
case "setError": {
|
|
1718
|
+
const { error } = action;
|
|
1719
|
+
return { ...state, error };
|
|
1972
1720
|
}
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1721
|
+
case "setLoadingMore": {
|
|
1722
|
+
const { loadingMore } = action;
|
|
1723
|
+
return { ...state, loadingMore, suppressAutoscroll: loadingMore };
|
|
1976
1724
|
}
|
|
1725
|
+
case "setLoadingMoreForJumpToChannelMessage": {
|
|
1726
|
+
const { loadingMoreForJumpToChannelMessage } = action;
|
|
1727
|
+
return {
|
|
1728
|
+
...state,
|
|
1729
|
+
loadingMoreForJumpToChannelMessage,
|
|
1730
|
+
suppressAutoscroll: loadingMoreForJumpToChannelMessage
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
case "setLoadingMoreNewer": {
|
|
1734
|
+
const { loadingMoreNewer } = action;
|
|
1735
|
+
return { ...state, loadingMoreNewer };
|
|
1736
|
+
}
|
|
1737
|
+
case "setThread": {
|
|
1738
|
+
const { message } = action;
|
|
1739
|
+
return { ...state, thread: message };
|
|
1740
|
+
}
|
|
1741
|
+
case "setTyping": {
|
|
1742
|
+
const { channel } = action;
|
|
1743
|
+
return {
|
|
1744
|
+
...state,
|
|
1745
|
+
typing: { ...channel.state.typing }
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
case "startLoadingThread": {
|
|
1749
|
+
return {
|
|
1750
|
+
...state,
|
|
1751
|
+
threadLoadingMore: true,
|
|
1752
|
+
threadSuppressAutoscroll: true
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
case "updateThreadOnEvent": {
|
|
1756
|
+
const { channel, message } = action;
|
|
1757
|
+
if (!state.thread) return state;
|
|
1758
|
+
return {
|
|
1759
|
+
...state,
|
|
1760
|
+
thread: message?.id === state.thread.id ? channel.state.formatMessage(message) : state.thread,
|
|
1761
|
+
threadMessages: state.thread?.id ? { ...channel.state.threads }[state.thread.id] || [] : []
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
default:
|
|
1765
|
+
return state;
|
|
1977
1766
|
}
|
|
1978
|
-
setPlugins(setter) {
|
|
1979
|
-
this._plugins = setter(this.plugins).reduce((acc, plugin) => {
|
|
1980
|
-
if (plugin.id) {
|
|
1981
|
-
acc.set(plugin.id, plugin);
|
|
1982
|
-
}
|
|
1983
|
-
return acc;
|
|
1984
|
-
}, /* @__PURE__ */ new Map());
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
class AudioPlayerPool {
|
|
1988
|
-
constructor(config) {
|
|
1989
|
-
this.state = new StateStore({
|
|
1990
|
-
activeAudioPlayer: null
|
|
1991
|
-
});
|
|
1992
|
-
this.pool = /* @__PURE__ */ new Map();
|
|
1993
|
-
this.audios = /* @__PURE__ */ new Map();
|
|
1994
|
-
this.sharedAudio = null;
|
|
1995
|
-
this.sharedOwnerId = null;
|
|
1996
|
-
this.getOrAdd = (params) => {
|
|
1997
|
-
const { playbackRates, plugins, ...descriptor } = params;
|
|
1998
|
-
let player = this.pool.get(params.id);
|
|
1999
|
-
if (player) {
|
|
2000
|
-
if (!player.disposed) {
|
|
2001
|
-
player.setDescriptor(descriptor);
|
|
2002
|
-
return player;
|
|
2003
|
-
}
|
|
2004
|
-
this.deregister(params.id);
|
|
2005
|
-
}
|
|
2006
|
-
player = new AudioPlayer({
|
|
2007
|
-
playbackRates,
|
|
2008
|
-
plugins,
|
|
2009
|
-
...descriptor,
|
|
2010
|
-
pool: this
|
|
2011
|
-
});
|
|
2012
|
-
this.pool.set(params.id, player);
|
|
2013
|
-
return player;
|
|
2014
|
-
};
|
|
2015
|
-
this.acquireElement = ({ ownerId, src }) => {
|
|
2016
|
-
if (!this.allowConcurrentPlayback) {
|
|
2017
|
-
if (!this.sharedAudio) {
|
|
2018
|
-
this.sharedAudio = new Audio();
|
|
2019
|
-
}
|
|
2020
|
-
if (this.sharedOwnerId && this.sharedOwnerId !== ownerId) {
|
|
2021
|
-
const previous = this.pool.get(this.sharedOwnerId);
|
|
2022
|
-
previous?.pause();
|
|
2023
|
-
previous?.releaseElementForHandoff();
|
|
2024
|
-
}
|
|
2025
|
-
this.sharedOwnerId = ownerId;
|
|
2026
|
-
if (this.sharedAudio.src !== src) {
|
|
2027
|
-
this.sharedAudio.src = src;
|
|
2028
|
-
}
|
|
2029
|
-
return this.sharedAudio;
|
|
2030
|
-
}
|
|
2031
|
-
let audio = this.audios.get(ownerId);
|
|
2032
|
-
if (!audio) {
|
|
2033
|
-
audio = new Audio();
|
|
2034
|
-
this.audios.set(ownerId, audio);
|
|
2035
|
-
}
|
|
2036
|
-
if (audio.src !== src) {
|
|
2037
|
-
audio.src = src;
|
|
2038
|
-
}
|
|
2039
|
-
return audio;
|
|
2040
|
-
};
|
|
2041
|
-
this.releaseElement = (ownerId) => {
|
|
2042
|
-
if (!this.allowConcurrentPlayback) {
|
|
2043
|
-
if (this.sharedOwnerId !== ownerId) return;
|
|
2044
|
-
const el2 = this.sharedAudio;
|
|
2045
|
-
if (el2) {
|
|
2046
|
-
try {
|
|
2047
|
-
el2.pause();
|
|
2048
|
-
} catch {
|
|
2049
|
-
}
|
|
2050
|
-
el2.removeAttribute("src");
|
|
2051
|
-
el2.load();
|
|
2052
|
-
}
|
|
2053
|
-
this.sharedOwnerId = null;
|
|
2054
|
-
return;
|
|
2055
|
-
}
|
|
2056
|
-
const el = this.audios.get(ownerId);
|
|
2057
|
-
if (!el) return;
|
|
2058
|
-
try {
|
|
2059
|
-
el.pause();
|
|
2060
|
-
} catch {
|
|
2061
|
-
}
|
|
2062
|
-
el.removeAttribute("src");
|
|
2063
|
-
el.load();
|
|
2064
|
-
this.audios.delete(ownerId);
|
|
2065
|
-
};
|
|
2066
|
-
this.setActiveAudioPlayer = (activeAudioPlayer) => {
|
|
2067
|
-
if (this.allowConcurrentPlayback) return;
|
|
2068
|
-
this.state.partialNext({ activeAudioPlayer });
|
|
2069
|
-
};
|
|
2070
|
-
this.remove = (id) => {
|
|
2071
|
-
const player = this.pool.get(id);
|
|
2072
|
-
if (!player) return;
|
|
2073
|
-
player.requestRemoval();
|
|
2074
|
-
};
|
|
2075
|
-
this.clear = () => {
|
|
2076
|
-
this.players.forEach((player) => {
|
|
2077
|
-
this.remove(player.id);
|
|
2078
|
-
});
|
|
2079
|
-
};
|
|
2080
|
-
this.registerSubscriptions = () => {
|
|
2081
|
-
this.players.forEach((p) => {
|
|
2082
|
-
if (p.elementRef) {
|
|
2083
|
-
p.registerSubscriptions();
|
|
2084
|
-
}
|
|
2085
|
-
});
|
|
2086
|
-
};
|
|
2087
|
-
this.allowConcurrentPlayback = !!config?.allowConcurrentPlayback;
|
|
2088
|
-
}
|
|
2089
|
-
get players() {
|
|
2090
|
-
return Array.from(this.pool.values());
|
|
2091
|
-
}
|
|
2092
|
-
get activeAudioPlayer() {
|
|
2093
|
-
return this.state.getLatestValue().activeAudioPlayer;
|
|
2094
|
-
}
|
|
2095
|
-
/** Removes the AudioPlayer instance from the pool of players */
|
|
2096
|
-
deregister(id) {
|
|
2097
|
-
if (this.pool.has(id)) {
|
|
2098
|
-
this.pool.delete(id);
|
|
2099
|
-
}
|
|
2100
|
-
if (this.activeAudioPlayer?.id === id) {
|
|
2101
|
-
this.setActiveAudioPlayer(null);
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
const SEEK_NOT_SUPPORTED_NOTIFICATION_DEBOUNCE_INTERVAL_MS = 1e3;
|
|
2106
|
-
const audioPlayerNotificationsPluginFactory = ({
|
|
2107
|
-
addNotification,
|
|
2108
|
-
panel = "channel",
|
|
2109
|
-
t
|
|
2110
|
-
}) => {
|
|
2111
|
-
const errors = {
|
|
2112
|
-
"failed-to-start": new Error(t("Failed to play the recording")),
|
|
2113
|
-
"not-playable": new Error(
|
|
2114
|
-
t("Recording format is not supported and cannot be reproduced")
|
|
2115
|
-
),
|
|
2116
|
-
"seek-not-supported": new Error(t("Cannot seek in the recording"))
|
|
2117
|
-
};
|
|
2118
|
-
let lastSeekNotSupportedNotificationAt;
|
|
2119
|
-
return {
|
|
2120
|
-
id: "AudioPlayerNotificationsPlugin",
|
|
2121
|
-
onError: ({ errCode, error: e }) => {
|
|
2122
|
-
if (errCode === "seek-not-supported") {
|
|
2123
|
-
const now = Date.now();
|
|
2124
|
-
if (typeof lastSeekNotSupportedNotificationAt === "number" && now - lastSeekNotSupportedNotificationAt < SEEK_NOT_SUPPORTED_NOTIFICATION_DEBOUNCE_INTERVAL_MS) {
|
|
2125
|
-
return;
|
|
2126
|
-
}
|
|
2127
|
-
lastSeekNotSupportedNotificationAt = now;
|
|
2128
|
-
}
|
|
2129
|
-
const error = (errCode && errors[errCode]) ?? e ?? new Error(t("Error reproducing the recording"));
|
|
2130
|
-
addNotification({
|
|
2131
|
-
emitter: "AudioPlayer",
|
|
2132
|
-
error,
|
|
2133
|
-
message: error.message,
|
|
2134
|
-
severity: "error",
|
|
2135
|
-
targetPanels: [panel],
|
|
2136
|
-
type: "browser:audio:playback:error"
|
|
2137
|
-
});
|
|
2138
|
-
}
|
|
2139
|
-
};
|
|
2140
|
-
};
|
|
2141
|
-
const NOTIFICATION_TARGET_PANELS = [
|
|
2142
|
-
"channel",
|
|
2143
|
-
"thread",
|
|
2144
|
-
"channel-list",
|
|
2145
|
-
"thread-list"
|
|
2146
|
-
];
|
|
2147
|
-
const isNotificationTargetPanel = (value) => typeof value === "string" && NOTIFICATION_TARGET_PANELS.includes(value);
|
|
2148
|
-
const getNotificationTargetPanel = (notification) => {
|
|
2149
|
-
const targetTag = notification.tags?.find((tag) => tag.startsWith("target:"));
|
|
2150
|
-
if (targetTag) {
|
|
2151
|
-
const candidate = targetTag.slice("target:".length);
|
|
2152
|
-
if (isNotificationTargetPanel(candidate)) return candidate;
|
|
2153
|
-
}
|
|
2154
|
-
const panel = notification.origin.context?.panel;
|
|
2155
|
-
return isNotificationTargetPanel(panel) ? panel : void 0;
|
|
2156
|
-
};
|
|
2157
|
-
const getNotificationTargetPanels = (notification) => {
|
|
2158
|
-
const targetPanels = (notification.tags ?? []).filter((tag) => tag.startsWith("target:")).map((tag) => tag.slice("target:".length)).filter(
|
|
2159
|
-
(value) => isNotificationTargetPanel(value)
|
|
2160
|
-
);
|
|
2161
|
-
if (targetPanels.length > 0) {
|
|
2162
|
-
return Array.from(new Set(targetPanels));
|
|
2163
|
-
}
|
|
2164
|
-
const panel = notification.origin.context?.panel;
|
|
2165
|
-
return isNotificationTargetPanel(panel) ? [panel] : [];
|
|
2166
1767
|
};
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
1768
|
+
const initialState = {
|
|
1769
|
+
error: null,
|
|
1770
|
+
hasMore: true,
|
|
1771
|
+
hasMoreNewer: false,
|
|
1772
|
+
loading: true,
|
|
1773
|
+
loadingMore: false,
|
|
1774
|
+
loadingMoreForJumpToChannelMessage: false,
|
|
1775
|
+
members: {},
|
|
1776
|
+
messages: [],
|
|
1777
|
+
pinnedMessages: [],
|
|
1778
|
+
read: {},
|
|
1779
|
+
suppressAutoscroll: false,
|
|
1780
|
+
thread: null,
|
|
1781
|
+
threadHasMore: true,
|
|
1782
|
+
threadLoadingMore: false,
|
|
1783
|
+
threadMessages: [],
|
|
1784
|
+
threadSuppressAutoscroll: false,
|
|
1785
|
+
typing: {},
|
|
1786
|
+
watcherCount: 0,
|
|
1787
|
+
watchers: {}
|
|
2171
1788
|
};
|
|
2172
|
-
const
|
|
2173
|
-
const
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
});
|
|
2216
|
-
const UnMemoizedEmptyStateIndicator = (props) => {
|
|
2217
|
-
const { listType, messageText } = props;
|
|
2218
|
-
const { t } = useTranslationContext("EmptyStateIndicator");
|
|
2219
|
-
if (listType === "thread") return null;
|
|
2220
|
-
if (listType === "channel") {
|
|
2221
|
-
const text = t("No conversations yet");
|
|
2222
|
-
return /* @__PURE__ */ jsxs("div", { className: "str-chat__channel-list-empty", children: [
|
|
2223
|
-
/* @__PURE__ */ jsx(IconMessageBubbles, {}),
|
|
2224
|
-
/* @__PURE__ */ jsx("p", { role: "listitem", children: text })
|
|
2225
|
-
] });
|
|
2226
|
-
}
|
|
2227
|
-
if (listType === "message") {
|
|
2228
|
-
const text = t(messageText || "Send a message to start the conversation");
|
|
2229
|
-
return /* @__PURE__ */ jsxs("div", { className: "str-chat__empty-channel", children: [
|
|
2230
|
-
/* @__PURE__ */ jsx(IconMessageBubble, {}),
|
|
2231
|
-
/* @__PURE__ */ jsx("p", { className: "str-chat__empty-channel-text", role: "listitem", children: text })
|
|
2232
|
-
] });
|
|
2233
|
-
}
|
|
2234
|
-
return /* @__PURE__ */ jsx("p", { children: t("No items exist") });
|
|
2235
|
-
};
|
|
2236
|
-
const EmptyStateIndicator = React.memo(
|
|
2237
|
-
UnMemoizedEmptyStateIndicator
|
|
2238
|
-
);
|
|
2239
|
-
const makeChannelReducer = () => (state, action) => {
|
|
2240
|
-
switch (action.type) {
|
|
2241
|
-
case "closeThread": {
|
|
2242
|
-
return {
|
|
2243
|
-
...state,
|
|
2244
|
-
thread: null,
|
|
2245
|
-
threadLoadingMore: false,
|
|
2246
|
-
threadMessages: []
|
|
2247
|
-
};
|
|
2248
|
-
}
|
|
2249
|
-
case "copyMessagesFromChannel": {
|
|
2250
|
-
const { channel, parentId } = action;
|
|
2251
|
-
return {
|
|
2252
|
-
...state,
|
|
2253
|
-
messages: [...channel.state.messages],
|
|
2254
|
-
pinnedMessages: [...channel.state.pinnedMessages],
|
|
2255
|
-
// copying messages from channel happens with new message - this resets the suppressAutoscroll
|
|
2256
|
-
suppressAutoscroll: false,
|
|
2257
|
-
threadMessages: parentId ? { ...channel.state.threads }[parentId] || [] : state.threadMessages
|
|
2258
|
-
};
|
|
2259
|
-
}
|
|
2260
|
-
case "copyStateFromChannelOnEvent": {
|
|
2261
|
-
const { channel } = action;
|
|
2262
|
-
return {
|
|
2263
|
-
...state,
|
|
2264
|
-
members: { ...channel.state.members },
|
|
2265
|
-
messages: [...channel.state.messages],
|
|
2266
|
-
pinnedMessages: [...channel.state.pinnedMessages],
|
|
2267
|
-
read: { ...channel.state.read },
|
|
2268
|
-
watcherCount: channel.state.watcher_count,
|
|
2269
|
-
watchers: { ...channel.state.watchers }
|
|
2270
|
-
};
|
|
2271
|
-
}
|
|
2272
|
-
case "initStateFromChannel": {
|
|
2273
|
-
const { channel, hasMore } = action;
|
|
2274
|
-
return {
|
|
2275
|
-
...state,
|
|
2276
|
-
hasMore,
|
|
2277
|
-
loading: false,
|
|
2278
|
-
members: { ...channel.state.members },
|
|
2279
|
-
messages: [...channel.state.messages],
|
|
2280
|
-
pinnedMessages: [...channel.state.pinnedMessages],
|
|
2281
|
-
read: { ...channel.state.read },
|
|
2282
|
-
watcherCount: channel.state.watcher_count,
|
|
2283
|
-
watchers: { ...channel.state.watchers }
|
|
2284
|
-
};
|
|
2285
|
-
}
|
|
2286
|
-
case "jumpToLatestMessageFinished": {
|
|
2287
|
-
const { hasMore, hasMoreNewer, messages } = action;
|
|
2288
|
-
return {
|
|
2289
|
-
...state,
|
|
2290
|
-
hasMore,
|
|
2291
|
-
hasMoreNewer,
|
|
2292
|
-
highlightedMessageId: void 0,
|
|
2293
|
-
loading: false,
|
|
2294
|
-
messages,
|
|
2295
|
-
suppressAutoscroll: false
|
|
2296
|
-
};
|
|
2297
|
-
}
|
|
2298
|
-
case "jumpToMessageFinished": {
|
|
2299
|
-
return {
|
|
2300
|
-
...state,
|
|
2301
|
-
hasMore: action.channel.state.messagePagination.hasPrev,
|
|
2302
|
-
hasMoreNewer: action.channel.state.messagePagination.hasNext,
|
|
2303
|
-
highlightedMessageId: action.highlightedMessageId,
|
|
2304
|
-
loadingMore: false,
|
|
2305
|
-
loadingMoreForJumpToChannelMessage: false,
|
|
2306
|
-
messages: action.channel.state.messages,
|
|
2307
|
-
suppressAutoscroll: false
|
|
2308
|
-
};
|
|
2309
|
-
}
|
|
2310
|
-
case "clearHighlightedMessage": {
|
|
2311
|
-
return {
|
|
2312
|
-
...state,
|
|
2313
|
-
highlightedMessageId: void 0
|
|
2314
|
-
};
|
|
2315
|
-
}
|
|
2316
|
-
case "loadMoreFinished": {
|
|
2317
|
-
const { hasMore, messages } = action;
|
|
2318
|
-
return {
|
|
2319
|
-
...state,
|
|
2320
|
-
hasMore,
|
|
2321
|
-
loadingMore: false,
|
|
2322
|
-
messages,
|
|
2323
|
-
suppressAutoscroll: false
|
|
2324
|
-
};
|
|
2325
|
-
}
|
|
2326
|
-
case "loadMoreNewerFinished": {
|
|
2327
|
-
const { hasMoreNewer, messages } = action;
|
|
2328
|
-
return {
|
|
2329
|
-
...state,
|
|
2330
|
-
hasMoreNewer,
|
|
2331
|
-
loadingMoreNewer: false,
|
|
2332
|
-
messages
|
|
2333
|
-
};
|
|
2334
|
-
}
|
|
2335
|
-
case "loadMoreThreadFinished": {
|
|
2336
|
-
const { threadHasMore, threadMessages } = action;
|
|
2337
|
-
return {
|
|
2338
|
-
...state,
|
|
2339
|
-
threadHasMore,
|
|
2340
|
-
threadLoadingMore: false,
|
|
2341
|
-
threadMessages
|
|
2342
|
-
};
|
|
2343
|
-
}
|
|
2344
|
-
case "openThread": {
|
|
2345
|
-
const { channel, message } = action;
|
|
2346
|
-
return {
|
|
2347
|
-
...state,
|
|
2348
|
-
thread: message,
|
|
2349
|
-
threadHasMore: true,
|
|
2350
|
-
threadMessages: message.id ? { ...channel.state.threads }[message.id] || [] : [],
|
|
2351
|
-
threadSuppressAutoscroll: false
|
|
2352
|
-
};
|
|
2353
|
-
}
|
|
2354
|
-
case "setError": {
|
|
2355
|
-
const { error } = action;
|
|
2356
|
-
return { ...state, error };
|
|
2357
|
-
}
|
|
2358
|
-
case "setLoadingMore": {
|
|
2359
|
-
const { loadingMore } = action;
|
|
2360
|
-
return { ...state, loadingMore, suppressAutoscroll: loadingMore };
|
|
2361
|
-
}
|
|
2362
|
-
case "setLoadingMoreForJumpToChannelMessage": {
|
|
2363
|
-
const { loadingMoreForJumpToChannelMessage } = action;
|
|
2364
|
-
return {
|
|
2365
|
-
...state,
|
|
2366
|
-
loadingMoreForJumpToChannelMessage,
|
|
2367
|
-
suppressAutoscroll: loadingMoreForJumpToChannelMessage
|
|
2368
|
-
};
|
|
2369
|
-
}
|
|
2370
|
-
case "setLoadingMoreNewer": {
|
|
2371
|
-
const { loadingMoreNewer } = action;
|
|
2372
|
-
return { ...state, loadingMoreNewer };
|
|
2373
|
-
}
|
|
2374
|
-
case "setThread": {
|
|
2375
|
-
const { message } = action;
|
|
2376
|
-
return { ...state, thread: message };
|
|
2377
|
-
}
|
|
2378
|
-
case "setTyping": {
|
|
2379
|
-
const { channel } = action;
|
|
2380
|
-
return {
|
|
2381
|
-
...state,
|
|
2382
|
-
typing: { ...channel.state.typing }
|
|
2383
|
-
};
|
|
2384
|
-
}
|
|
2385
|
-
case "startLoadingThread": {
|
|
2386
|
-
return {
|
|
2387
|
-
...state,
|
|
2388
|
-
threadLoadingMore: true,
|
|
2389
|
-
threadSuppressAutoscroll: true
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
case "updateThreadOnEvent": {
|
|
2393
|
-
const { channel, message } = action;
|
|
2394
|
-
if (!state.thread) return state;
|
|
2395
|
-
return {
|
|
2396
|
-
...state,
|
|
2397
|
-
thread: message?.id === state.thread.id ? channel.state.formatMessage(message) : state.thread,
|
|
2398
|
-
threadMessages: state.thread?.id ? { ...channel.state.threads }[state.thread.id] || [] : []
|
|
2399
|
-
};
|
|
2400
|
-
}
|
|
2401
|
-
default:
|
|
2402
|
-
return state;
|
|
2403
|
-
}
|
|
2404
|
-
};
|
|
2405
|
-
const initialState = {
|
|
2406
|
-
error: null,
|
|
2407
|
-
hasMore: true,
|
|
2408
|
-
hasMoreNewer: false,
|
|
2409
|
-
loading: true,
|
|
2410
|
-
loadingMore: false,
|
|
2411
|
-
loadingMoreForJumpToChannelMessage: false,
|
|
2412
|
-
members: {},
|
|
2413
|
-
messages: [],
|
|
2414
|
-
pinnedMessages: [],
|
|
2415
|
-
read: {},
|
|
2416
|
-
suppressAutoscroll: false,
|
|
2417
|
-
thread: null,
|
|
2418
|
-
threadHasMore: true,
|
|
2419
|
-
threadLoadingMore: false,
|
|
2420
|
-
threadMessages: [],
|
|
2421
|
-
threadSuppressAutoscroll: false,
|
|
2422
|
-
typing: {},
|
|
2423
|
-
watcherCount: 0,
|
|
2424
|
-
watchers: {}
|
|
2425
|
-
};
|
|
2426
|
-
const useCreateChannelStateContext = (value) => {
|
|
2427
|
-
const {
|
|
2428
|
-
channel,
|
|
2429
|
-
channelCapabilitiesArray = [],
|
|
2430
|
-
channelConfig,
|
|
2431
|
-
channelUnreadUiState,
|
|
2432
|
-
error,
|
|
2433
|
-
giphyVersion,
|
|
2434
|
-
hasMore,
|
|
2435
|
-
hasMoreNewer,
|
|
2436
|
-
highlightedMessageId,
|
|
2437
|
-
imageAttachmentSizeHandler,
|
|
2438
|
-
loading,
|
|
2439
|
-
loadingMore,
|
|
2440
|
-
loadingMoreForJumpToChannelMessage,
|
|
2441
|
-
members,
|
|
2442
|
-
messages = [],
|
|
2443
|
-
mutes,
|
|
2444
|
-
notifications,
|
|
2445
|
-
pinnedMessages,
|
|
2446
|
-
read = {},
|
|
2447
|
-
shouldGenerateVideoThumbnail,
|
|
2448
|
-
skipMessageDataMemoization,
|
|
2449
|
-
suppressAutoscroll,
|
|
2450
|
-
thread,
|
|
2451
|
-
threadHasMore,
|
|
2452
|
-
threadLoadingMore,
|
|
2453
|
-
threadMessages = [],
|
|
2454
|
-
videoAttachmentSizeHandler,
|
|
2455
|
-
watcher_count,
|
|
2456
|
-
watcherCount,
|
|
2457
|
-
watchers
|
|
2458
|
-
} = value;
|
|
2459
|
-
const channelId = channel.cid;
|
|
2460
|
-
const lastRead = channel.initialized && channel.lastRead()?.getTime();
|
|
2461
|
-
const membersLength = Object.keys(members || []).length;
|
|
2462
|
-
const notificationsLength = notifications.length;
|
|
2463
|
-
const readUsers = Object.values(read);
|
|
2464
|
-
const readUsersLength = readUsers.length;
|
|
2465
|
-
const readUsersLastReadDateStrings = [];
|
|
2466
|
-
for (const { last_read } of readUsers) {
|
|
2467
|
-
if (!lastRead) continue;
|
|
2468
|
-
readUsersLastReadDateStrings.push(last_read?.toISOString());
|
|
1789
|
+
const useCreateChannelStateContext = (value) => {
|
|
1790
|
+
const {
|
|
1791
|
+
channel,
|
|
1792
|
+
channelCapabilitiesArray = [],
|
|
1793
|
+
channelConfig,
|
|
1794
|
+
channelUnreadUiState,
|
|
1795
|
+
error,
|
|
1796
|
+
giphyVersion,
|
|
1797
|
+
hasMore,
|
|
1798
|
+
hasMoreNewer,
|
|
1799
|
+
highlightedMessageId,
|
|
1800
|
+
imageAttachmentSizeHandler,
|
|
1801
|
+
loading,
|
|
1802
|
+
loadingMore,
|
|
1803
|
+
loadingMoreForJumpToChannelMessage,
|
|
1804
|
+
members,
|
|
1805
|
+
messages = [],
|
|
1806
|
+
mutes,
|
|
1807
|
+
notifications,
|
|
1808
|
+
pinnedMessages,
|
|
1809
|
+
read = {},
|
|
1810
|
+
shouldGenerateVideoThumbnail,
|
|
1811
|
+
skipMessageDataMemoization,
|
|
1812
|
+
suppressAutoscroll,
|
|
1813
|
+
thread,
|
|
1814
|
+
threadHasMore,
|
|
1815
|
+
threadLoadingMore,
|
|
1816
|
+
threadMessages = [],
|
|
1817
|
+
videoAttachmentSizeHandler,
|
|
1818
|
+
watcher_count,
|
|
1819
|
+
watcherCount,
|
|
1820
|
+
watchers
|
|
1821
|
+
} = value;
|
|
1822
|
+
const channelId = channel.cid;
|
|
1823
|
+
const lastRead = channel.initialized && channel.lastRead()?.getTime();
|
|
1824
|
+
const membersLength = Object.keys(members || []).length;
|
|
1825
|
+
const notificationsLength = notifications.length;
|
|
1826
|
+
const readUsers = Object.values(read);
|
|
1827
|
+
const readUsersLength = readUsers.length;
|
|
1828
|
+
const readUsersLastReadDateStrings = [];
|
|
1829
|
+
for (const { last_read } of readUsers) {
|
|
1830
|
+
if (!lastRead) continue;
|
|
1831
|
+
readUsersLastReadDateStrings.push(last_read?.toISOString());
|
|
2469
1832
|
}
|
|
2470
1833
|
const readUsersLastReads = readUsersLastReadDateStrings.join();
|
|
2471
1834
|
const threadMessagesLength = threadMessages?.length;
|
|
@@ -2582,359 +1945,1067 @@ const useIsMounted = () => {
|
|
|
2582
1945
|
return () => {
|
|
2583
1946
|
isMounted.current = false;
|
|
2584
1947
|
};
|
|
2585
|
-
}, []);
|
|
2586
|
-
return isMounted;
|
|
2587
|
-
};
|
|
2588
|
-
const useMentionsHandlers = (onMentionsHover, onMentionsClick) => useCallback(
|
|
2589
|
-
(event, mentioned_users) => {
|
|
2590
|
-
if (!onMentionsHover && !onMentionsClick || !(event.target instanceof HTMLElement)) {
|
|
2591
|
-
return;
|
|
2592
|
-
}
|
|
2593
|
-
const target = event.target;
|
|
2594
|
-
const textContent = target.innerHTML.replace("*", "");
|
|
2595
|
-
if (textContent[0] === "@") {
|
|
2596
|
-
const userName = textContent.replace("@", "");
|
|
2597
|
-
const user = mentioned_users?.find(
|
|
2598
|
-
({ id, name }) => name === userName || id === userName
|
|
2599
|
-
);
|
|
2600
|
-
if (onMentionsHover && typeof onMentionsHover === "function" && event.type === "mouseover") {
|
|
2601
|
-
onMentionsHover(event, user);
|
|
2602
|
-
}
|
|
2603
|
-
if (onMentionsClick && event.type === "click" && typeof onMentionsClick === "function") {
|
|
2604
|
-
onMentionsClick(event, user);
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
},
|
|
2608
|
-
[onMentionsClick, onMentionsHover]
|
|
2609
|
-
);
|
|
2610
|
-
const LoadingMessage = ({
|
|
2611
|
-
bubbleSize,
|
|
2612
|
-
metadataSize,
|
|
2613
|
-
outgoing = false
|
|
2614
|
-
}) => /* @__PURE__ */ jsxs(
|
|
2615
|
-
"div",
|
|
2616
|
-
{
|
|
2617
|
-
className: `str-chat__loading-channel-message ${outgoing ? "str-chat__loading-channel-message--outgoing" : "str-chat__loading-channel-message--incoming"}`,
|
|
2618
|
-
children: [
|
|
2619
|
-
!outgoing ? /* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-avatar" }) : null,
|
|
2620
|
-
/* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel-message-content", children: [
|
|
2621
|
-
/* @__PURE__ */ jsx(
|
|
2622
|
-
"div",
|
|
2623
|
-
{
|
|
2624
|
-
className: `str-chat__loading-channel-message-bubble str-chat__loading-channel-message-bubble--${bubbleSize}`
|
|
2625
|
-
}
|
|
2626
|
-
),
|
|
2627
|
-
/* @__PURE__ */ jsx(
|
|
2628
|
-
"div",
|
|
2629
|
-
{
|
|
2630
|
-
className: `str-chat__loading-channel-message-metadata str-chat__loading-channel-message-metadata--${metadataSize}`
|
|
2631
|
-
}
|
|
2632
|
-
)
|
|
2633
|
-
] })
|
|
2634
|
-
]
|
|
2635
|
-
}
|
|
2636
|
-
);
|
|
2637
|
-
const LoadingMessageInput = () => /* @__PURE__ */ jsx("div", { className: "str-chat__message-composer-container str-chat__message-composer-container--loading", children: /* @__PURE__ */ jsxs("div", { className: "str-chat__message-composer", children: [
|
|
2638
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-input-button" }),
|
|
2639
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-input-pill" })
|
|
2640
|
-
] }) });
|
|
2641
|
-
const LoadingChannelHeader = () => /* @__PURE__ */ jsxs("div", { className: "str-chat__channel-header str-chat__channel-header--loading", children: [
|
|
2642
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__channel-header__data str-chat__channel-header__data--loading", children: /* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-header-name" }) }),
|
|
2643
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-header-avatar" })
|
|
2644
|
-
] });
|
|
2645
|
-
const LoadingChannel = () => /* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel", children: [
|
|
2646
|
-
/* @__PURE__ */ jsx(LoadingChannelHeader, {}),
|
|
2647
|
-
/* @__PURE__ */ jsx("div", { className: "str-chat__message-list str-chat__message-list--loading", children: /* @__PURE__ */ jsx("div", { className: "str-chat__message-list-scroll", children: /* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel-message-list", children: [
|
|
2648
|
-
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "lg", metadataSize: "md" }),
|
|
2649
|
-
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "md", metadataSize: "sm", outgoing: true }),
|
|
2650
|
-
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "lg", metadataSize: "md" })
|
|
2651
|
-
] }) }) }),
|
|
2652
|
-
/* @__PURE__ */ jsx(LoadingMessageInput, {})
|
|
2653
|
-
] });
|
|
2654
|
-
const UnMemoizedLoadingErrorIndicator = ({ error }) => {
|
|
2655
|
-
const { t } = useTranslationContext("LoadingErrorIndicator");
|
|
2656
|
-
if (!error) return null;
|
|
2657
|
-
return /* @__PURE__ */ jsx("div", { children: t("Error: {{ errorMessage }}", { errorMessage: error.message }) });
|
|
2658
|
-
};
|
|
2659
|
-
const LoadingErrorIndicator = React.memo(
|
|
2660
|
-
UnMemoizedLoadingErrorIndicator,
|
|
2661
|
-
(prevProps, nextProps) => prevProps.error?.message === nextProps.error?.message
|
|
2662
|
-
);
|
|
2663
|
-
const CHANNEL_CONTAINER_ID = "str-chat__channel";
|
|
2664
|
-
const DEFAULT_NEXT_CHANNEL_PAGE_SIZE = 25;
|
|
2665
|
-
const DEFAULT_JUMP_TO_PAGE_SIZE = 25;
|
|
2666
|
-
const DEFAULT_THREAD_PAGE_SIZE = 25;
|
|
2667
|
-
const DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD = 250;
|
|
2668
|
-
const DEFAULT_HIGHLIGHT_DURATION = 500;
|
|
2669
|
-
const validateAndGetMessage = (func, args) => {
|
|
2670
|
-
if (!func || typeof func !== "function") return null;
|
|
2671
|
-
if (!Array.isArray(args)) {
|
|
2672
|
-
args = [args];
|
|
2673
|
-
}
|
|
2674
|
-
const returnValue = func(...args);
|
|
2675
|
-
if (typeof returnValue !== "string") return null;
|
|
2676
|
-
return returnValue;
|
|
2677
|
-
};
|
|
2678
|
-
const isUserMuted = (message, mutes) => {
|
|
2679
|
-
if (!mutes || !message) return false;
|
|
2680
|
-
const userMuted = mutes.filter((el) => el.target.id === message.user?.id);
|
|
2681
|
-
return !!userMuted.length;
|
|
2682
|
-
};
|
|
2683
|
-
const OPTIONAL_MESSAGE_ACTIONS = {
|
|
2684
|
-
deleteForMe: "deleteForMe"
|
|
2685
|
-
};
|
|
2686
|
-
const MESSAGE_ACTIONS = {
|
|
2687
|
-
delete: "delete",
|
|
2688
|
-
download: "download",
|
|
2689
|
-
edit: "edit",
|
|
2690
|
-
flag: "flag",
|
|
2691
|
-
markUnread: "markUnread",
|
|
2692
|
-
mute: "mute",
|
|
2693
|
-
pin: "pin",
|
|
2694
|
-
quote: "quote",
|
|
2695
|
-
react: "react",
|
|
2696
|
-
remindMe: "remindMe",
|
|
2697
|
-
reply: "reply",
|
|
2698
|
-
saveForLater: "saveForLater"
|
|
2699
|
-
};
|
|
2700
|
-
const getMessageActions = (actions, {
|
|
2701
|
-
canDelete,
|
|
2702
|
-
canEdit,
|
|
2703
|
-
canFlag,
|
|
2704
|
-
canMarkUnread,
|
|
2705
|
-
canMute,
|
|
2706
|
-
canPin,
|
|
2707
|
-
canQuote,
|
|
2708
|
-
canReact,
|
|
2709
|
-
canReply
|
|
2710
|
-
}, channelConfig) => {
|
|
2711
|
-
const messageActionsAfterPermission = [];
|
|
2712
|
-
let messageActions = [];
|
|
2713
|
-
if (actions && typeof actions === "boolean") {
|
|
2714
|
-
messageActions = Object.keys(MESSAGE_ACTIONS);
|
|
2715
|
-
} else if (actions && Array.isArray(actions) && actions.length > 0) {
|
|
2716
|
-
messageActions = [...actions];
|
|
2717
|
-
} else {
|
|
2718
|
-
return [];
|
|
2719
|
-
}
|
|
2720
|
-
if (canDelete && messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1) {
|
|
2721
|
-
messageActionsAfterPermission.push(MESSAGE_ACTIONS.delete);
|
|
1948
|
+
}, []);
|
|
1949
|
+
return isMounted;
|
|
1950
|
+
};
|
|
1951
|
+
const useMentionsHandlers = (onMentionsHover, onMentionsClick) => useCallback(
|
|
1952
|
+
(event, mentioned_users) => {
|
|
1953
|
+
if (!onMentionsHover && !onMentionsClick || !(event.target instanceof HTMLElement)) {
|
|
1954
|
+
return;
|
|
1955
|
+
}
|
|
1956
|
+
const target = event.target;
|
|
1957
|
+
const textContent = target.innerHTML.replace("*", "");
|
|
1958
|
+
if (textContent[0] === "@") {
|
|
1959
|
+
const userName = textContent.replace("@", "");
|
|
1960
|
+
const user = mentioned_users?.find(
|
|
1961
|
+
({ id, name }) => name === userName || id === userName
|
|
1962
|
+
);
|
|
1963
|
+
if (onMentionsHover && typeof onMentionsHover === "function" && event.type === "mouseover") {
|
|
1964
|
+
onMentionsHover(event, user);
|
|
1965
|
+
}
|
|
1966
|
+
if (onMentionsClick && event.type === "click" && typeof onMentionsClick === "function") {
|
|
1967
|
+
onMentionsClick(event, user);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
},
|
|
1971
|
+
[onMentionsClick, onMentionsHover]
|
|
1972
|
+
);
|
|
1973
|
+
const LoadingMessage = ({
|
|
1974
|
+
bubbleSize,
|
|
1975
|
+
metadataSize,
|
|
1976
|
+
outgoing = false
|
|
1977
|
+
}) => /* @__PURE__ */ jsxs(
|
|
1978
|
+
"div",
|
|
1979
|
+
{
|
|
1980
|
+
className: `str-chat__loading-channel-message ${outgoing ? "str-chat__loading-channel-message--outgoing" : "str-chat__loading-channel-message--incoming"}`,
|
|
1981
|
+
children: [
|
|
1982
|
+
!outgoing ? /* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-avatar" }) : null,
|
|
1983
|
+
/* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel-message-content", children: [
|
|
1984
|
+
/* @__PURE__ */ jsx(
|
|
1985
|
+
"div",
|
|
1986
|
+
{
|
|
1987
|
+
className: `str-chat__loading-channel-message-bubble str-chat__loading-channel-message-bubble--${bubbleSize}`
|
|
1988
|
+
}
|
|
1989
|
+
),
|
|
1990
|
+
/* @__PURE__ */ jsx(
|
|
1991
|
+
"div",
|
|
1992
|
+
{
|
|
1993
|
+
className: `str-chat__loading-channel-message-metadata str-chat__loading-channel-message-metadata--${metadataSize}`
|
|
1994
|
+
}
|
|
1995
|
+
)
|
|
1996
|
+
] })
|
|
1997
|
+
]
|
|
1998
|
+
}
|
|
1999
|
+
);
|
|
2000
|
+
const LoadingMessageInput = () => /* @__PURE__ */ jsx("div", { className: "str-chat__message-composer-container str-chat__message-composer-container--loading", children: /* @__PURE__ */ jsxs("div", { className: "str-chat__message-composer", children: [
|
|
2001
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-input-button" }),
|
|
2002
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-message-input-pill" })
|
|
2003
|
+
] }) });
|
|
2004
|
+
const LoadingChannelHeader = () => /* @__PURE__ */ jsxs("div", { className: "str-chat__channel-header str-chat__channel-header--loading", children: [
|
|
2005
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__channel-header__data str-chat__channel-header__data--loading", children: /* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-header-name" }) }),
|
|
2006
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__loading-channel-header-avatar" })
|
|
2007
|
+
] });
|
|
2008
|
+
const LoadingChannel = () => /* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel", children: [
|
|
2009
|
+
/* @__PURE__ */ jsx(LoadingChannelHeader, {}),
|
|
2010
|
+
/* @__PURE__ */ jsx("div", { className: "str-chat__message-list str-chat__message-list--loading", children: /* @__PURE__ */ jsx("div", { className: "str-chat__message-list-scroll", children: /* @__PURE__ */ jsxs("div", { className: "str-chat__loading-channel-message-list", children: [
|
|
2011
|
+
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "lg", metadataSize: "md" }),
|
|
2012
|
+
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "md", metadataSize: "sm", outgoing: true }),
|
|
2013
|
+
/* @__PURE__ */ jsx(LoadingMessage, { bubbleSize: "lg", metadataSize: "md" })
|
|
2014
|
+
] }) }) }),
|
|
2015
|
+
/* @__PURE__ */ jsx(LoadingMessageInput, {})
|
|
2016
|
+
] });
|
|
2017
|
+
const UnMemoizedLoadingErrorIndicator = ({ error }) => {
|
|
2018
|
+
const { t } = useTranslationContext("LoadingErrorIndicator");
|
|
2019
|
+
if (!error) return null;
|
|
2020
|
+
return /* @__PURE__ */ jsx("div", { children: t("Error: {{ errorMessage }}", { errorMessage: error.message }) });
|
|
2021
|
+
};
|
|
2022
|
+
const LoadingErrorIndicator = React.memo(
|
|
2023
|
+
UnMemoizedLoadingErrorIndicator,
|
|
2024
|
+
(prevProps, nextProps) => prevProps.error?.message === nextProps.error?.message
|
|
2025
|
+
);
|
|
2026
|
+
const CHANNEL_CONTAINER_ID = "str-chat__channel";
|
|
2027
|
+
const DEFAULT_NEXT_CHANNEL_PAGE_SIZE = 25;
|
|
2028
|
+
const DEFAULT_JUMP_TO_PAGE_SIZE = 25;
|
|
2029
|
+
const DEFAULT_THREAD_PAGE_SIZE = 25;
|
|
2030
|
+
const DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD = 250;
|
|
2031
|
+
const DEFAULT_HIGHLIGHT_DURATION = 500;
|
|
2032
|
+
const validateAndGetMessage = (func, args) => {
|
|
2033
|
+
if (!func || typeof func !== "function") return null;
|
|
2034
|
+
if (!Array.isArray(args)) {
|
|
2035
|
+
args = [args];
|
|
2036
|
+
}
|
|
2037
|
+
const returnValue = func(...args);
|
|
2038
|
+
if (typeof returnValue !== "string") return null;
|
|
2039
|
+
return returnValue;
|
|
2040
|
+
};
|
|
2041
|
+
const isUserMuted = (message, mutes) => {
|
|
2042
|
+
if (!mutes || !message) return false;
|
|
2043
|
+
const userMuted = mutes.filter((el) => el.target.id === message.user?.id);
|
|
2044
|
+
return !!userMuted.length;
|
|
2045
|
+
};
|
|
2046
|
+
const OPTIONAL_MESSAGE_ACTIONS = {
|
|
2047
|
+
deleteForMe: "deleteForMe"
|
|
2048
|
+
};
|
|
2049
|
+
const MESSAGE_ACTIONS = {
|
|
2050
|
+
delete: "delete",
|
|
2051
|
+
download: "download",
|
|
2052
|
+
edit: "edit",
|
|
2053
|
+
flag: "flag",
|
|
2054
|
+
markUnread: "markUnread",
|
|
2055
|
+
mute: "mute",
|
|
2056
|
+
pin: "pin",
|
|
2057
|
+
quote: "quote",
|
|
2058
|
+
react: "react",
|
|
2059
|
+
remindMe: "remindMe",
|
|
2060
|
+
reply: "reply",
|
|
2061
|
+
saveForLater: "saveForLater"
|
|
2062
|
+
};
|
|
2063
|
+
const getMessageActions = (actions, {
|
|
2064
|
+
canDelete,
|
|
2065
|
+
canEdit,
|
|
2066
|
+
canFlag,
|
|
2067
|
+
canMarkUnread,
|
|
2068
|
+
canMute,
|
|
2069
|
+
canPin,
|
|
2070
|
+
canQuote,
|
|
2071
|
+
canReact,
|
|
2072
|
+
canReply
|
|
2073
|
+
}, channelConfig) => {
|
|
2074
|
+
const messageActionsAfterPermission = [];
|
|
2075
|
+
let messageActions = [];
|
|
2076
|
+
if (actions && typeof actions === "boolean") {
|
|
2077
|
+
messageActions = Object.keys(MESSAGE_ACTIONS);
|
|
2078
|
+
} else if (actions && Array.isArray(actions) && actions.length > 0) {
|
|
2079
|
+
messageActions = [...actions];
|
|
2080
|
+
} else {
|
|
2081
|
+
return [];
|
|
2082
|
+
}
|
|
2083
|
+
if (canDelete && messageActions.indexOf(MESSAGE_ACTIONS.delete) > -1) {
|
|
2084
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.delete);
|
|
2085
|
+
}
|
|
2086
|
+
if (messageActions.indexOf(MESSAGE_ACTIONS.download) > -1) {
|
|
2087
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.download);
|
|
2088
|
+
}
|
|
2089
|
+
if (canDelete && messageActions.indexOf(OPTIONAL_MESSAGE_ACTIONS.deleteForMe) > -1) {
|
|
2090
|
+
messageActionsAfterPermission.push(OPTIONAL_MESSAGE_ACTIONS.deleteForMe);
|
|
2091
|
+
}
|
|
2092
|
+
if (canEdit && messageActions.indexOf(MESSAGE_ACTIONS.edit) > -1) {
|
|
2093
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.edit);
|
|
2094
|
+
}
|
|
2095
|
+
if (canFlag && messageActions.indexOf(MESSAGE_ACTIONS.flag) > -1) {
|
|
2096
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.flag);
|
|
2097
|
+
}
|
|
2098
|
+
if (canMarkUnread && messageActions.indexOf(MESSAGE_ACTIONS.markUnread) > -1) {
|
|
2099
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.markUnread);
|
|
2100
|
+
}
|
|
2101
|
+
if (canMute && messageActions.indexOf(MESSAGE_ACTIONS.mute) > -1) {
|
|
2102
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.mute);
|
|
2103
|
+
}
|
|
2104
|
+
if (canPin && messageActions.indexOf(MESSAGE_ACTIONS.pin) > -1) {
|
|
2105
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.pin);
|
|
2106
|
+
}
|
|
2107
|
+
if (canQuote && messageActions.indexOf(MESSAGE_ACTIONS.quote) > -1) {
|
|
2108
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.quote);
|
|
2109
|
+
}
|
|
2110
|
+
if (canReact && messageActions.indexOf(MESSAGE_ACTIONS.react) > -1) {
|
|
2111
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.react);
|
|
2112
|
+
}
|
|
2113
|
+
if (channelConfig?.["user_message_reminders"] && messageActions.indexOf(MESSAGE_ACTIONS.remindMe) > -1) {
|
|
2114
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.remindMe);
|
|
2115
|
+
}
|
|
2116
|
+
if (canReply && messageActions.indexOf(MESSAGE_ACTIONS.reply) > -1) {
|
|
2117
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.reply);
|
|
2118
|
+
}
|
|
2119
|
+
if (channelConfig?.["user_message_reminders"] && messageActions.indexOf(MESSAGE_ACTIONS.saveForLater) > -1) {
|
|
2120
|
+
messageActionsAfterPermission.push(MESSAGE_ACTIONS.saveForLater);
|
|
2121
|
+
}
|
|
2122
|
+
return messageActionsAfterPermission;
|
|
2123
|
+
};
|
|
2124
|
+
const ACTIONS_NOT_WORKING_IN_THREAD = [
|
|
2125
|
+
MESSAGE_ACTIONS.pin,
|
|
2126
|
+
MESSAGE_ACTIONS.reply,
|
|
2127
|
+
MESSAGE_ACTIONS.markUnread
|
|
2128
|
+
];
|
|
2129
|
+
function areMessagesEqual(prevMessage, nextMessage) {
|
|
2130
|
+
const areBaseMessagesEqual = (prevMessage2, nextMessage2) => prevMessage2.deleted_at === nextMessage2.deleted_at && prevMessage2.latest_reactions?.length === nextMessage2.latest_reactions?.length && prevMessage2.own_reactions?.length === nextMessage2.own_reactions?.length && prevMessage2.pinned === nextMessage2.pinned && prevMessage2.reply_count === nextMessage2.reply_count && prevMessage2.show_in_channel === nextMessage2.show_in_channel && prevMessage2.status === nextMessage2.status && prevMessage2.text === nextMessage2.text && prevMessage2.type === nextMessage2.type && prevMessage2.updated_at === nextMessage2.updated_at && prevMessage2.user?.updated_at === nextMessage2.user?.updated_at;
|
|
2131
|
+
return areBaseMessagesEqual(prevMessage, nextMessage) && Boolean(prevMessage.quoted_message) === Boolean(nextMessage.quoted_message) && (!prevMessage.quoted_message && !nextMessage.quoted_message || areBaseMessagesEqual(
|
|
2132
|
+
prevMessage.quoted_message,
|
|
2133
|
+
nextMessage.quoted_message
|
|
2134
|
+
));
|
|
2135
|
+
}
|
|
2136
|
+
const areMessagePropsEqual = (prevProps, nextProps) => {
|
|
2137
|
+
const { message: prevMessage, Message: prevMessageUI } = prevProps;
|
|
2138
|
+
const { message: nextMessage, Message: nextMessageUI } = nextProps;
|
|
2139
|
+
if (prevMessageUI !== nextMessageUI) return false;
|
|
2140
|
+
if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {
|
|
2141
|
+
return false;
|
|
2142
|
+
}
|
|
2143
|
+
if (nextProps.closeReactionSelectorOnClick !== prevProps.closeReactionSelectorOnClick) {
|
|
2144
|
+
return false;
|
|
2145
|
+
}
|
|
2146
|
+
const messagesAreEqual = areMessagesEqual(prevMessage, nextMessage);
|
|
2147
|
+
if (!messagesAreEqual) return false;
|
|
2148
|
+
const deepEqualProps = deepequal(nextProps.messageActions, prevProps.messageActions) && deepequal(nextProps.readBy, prevProps.readBy) && deepequal(nextProps.deliveredTo, prevProps.deliveredTo) && deepequal(nextProps.highlighted, prevProps.highlighted) && deepequal(nextProps.groupStyles, prevProps.groupStyles) && // last 3 messages can have different group styles
|
|
2149
|
+
deepequal(nextProps.mutes, prevProps.mutes) && deepequal(nextProps.lastReceivedId, prevProps.lastReceivedId);
|
|
2150
|
+
if (!deepEqualProps) return false;
|
|
2151
|
+
return prevProps.messageListRect === nextProps.messageListRect;
|
|
2152
|
+
};
|
|
2153
|
+
const areMessageUIPropsEqual = (prevProps, nextProps) => {
|
|
2154
|
+
const { lastReceivedId: prevLastReceivedId, message: prevMessage } = prevProps;
|
|
2155
|
+
const { lastReceivedId: nextLastReceivedId, message: nextMessage } = nextProps;
|
|
2156
|
+
if (prevProps.highlighted !== nextProps.highlighted) return false;
|
|
2157
|
+
if (prevProps.threadList !== nextProps.threadList) return false;
|
|
2158
|
+
if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;
|
|
2159
|
+
if (prevProps.mutes?.length !== nextProps.mutes?.length) return false;
|
|
2160
|
+
if (prevProps.readBy?.length !== nextProps.readBy?.length) return false;
|
|
2161
|
+
if (prevProps.deliveredTo?.length !== nextProps.deliveredTo?.length) return false;
|
|
2162
|
+
if (prevProps.groupStyles !== nextProps.groupStyles) return false;
|
|
2163
|
+
if (prevProps.showDetailedReactions !== nextProps.showDetailedReactions) {
|
|
2164
|
+
return false;
|
|
2165
|
+
}
|
|
2166
|
+
if ((prevMessage.id === prevLastReceivedId || prevMessage.id === nextLastReceivedId) && prevLastReceivedId !== nextLastReceivedId) {
|
|
2167
|
+
return false;
|
|
2168
|
+
}
|
|
2169
|
+
return areMessagesEqual(prevMessage, nextMessage);
|
|
2170
|
+
};
|
|
2171
|
+
const messageHasReactions = (message) => Object.values(message?.reaction_groups ?? {}).some(({ count }) => count > 0);
|
|
2172
|
+
const messageHasQuotedMessage = (message) => !!message?.quoted_message;
|
|
2173
|
+
const messageHasAttachments = (message) => !!message?.attachments && !!message.attachments.length;
|
|
2174
|
+
const messageHasSingleAttachment = (message) => message?.attachments?.length === 1;
|
|
2175
|
+
const messageHasGiphyAttachment = (message) => !!message?.attachments?.some((att) => att.type === "giphy");
|
|
2176
|
+
const getImages = (message) => {
|
|
2177
|
+
if (!message?.attachments) {
|
|
2178
|
+
return [];
|
|
2179
|
+
}
|
|
2180
|
+
return message.attachments.filter((item) => item.type === "image");
|
|
2181
|
+
};
|
|
2182
|
+
const getNonImageAttachments = (message) => {
|
|
2183
|
+
if (!message?.attachments) {
|
|
2184
|
+
return [];
|
|
2185
|
+
}
|
|
2186
|
+
return message.attachments.filter((item) => item.type !== "image");
|
|
2187
|
+
};
|
|
2188
|
+
const mapToUserNameOrId = (user) => user.name || user.id;
|
|
2189
|
+
const getReadByTooltipText = (users, t, client, tooltipUserNameMapper) => {
|
|
2190
|
+
let outStr = "";
|
|
2191
|
+
if (!t) {
|
|
2192
|
+
throw new Error(
|
|
2193
|
+
"getReadByTooltipText was called, but translation function is not available"
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
if (!tooltipUserNameMapper) {
|
|
2197
|
+
throw new Error(
|
|
2198
|
+
"getReadByTooltipText was called, but tooltipUserNameMapper function is not available"
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
const otherUsers = users.filter((item) => item && client?.user && item.id !== client.user.id).map(tooltipUserNameMapper);
|
|
2202
|
+
const slicedArr = otherUsers.slice(0, 5);
|
|
2203
|
+
const restLength = otherUsers.length - slicedArr.length;
|
|
2204
|
+
if (slicedArr.length === 1) {
|
|
2205
|
+
outStr = `${slicedArr[0]} `;
|
|
2206
|
+
} else if (slicedArr.length === 2) {
|
|
2207
|
+
outStr = t("{{ firstUser }} and {{ secondUser }}", {
|
|
2208
|
+
firstUser: slicedArr[0],
|
|
2209
|
+
secondUser: slicedArr[1]
|
|
2210
|
+
});
|
|
2211
|
+
} else if (slicedArr.length > 2) {
|
|
2212
|
+
if (restLength === 0) {
|
|
2213
|
+
const lastUser = slicedArr.splice(slicedArr.length - 1, 1);
|
|
2214
|
+
outStr = t("{{ commaSeparatedUsers }}, and {{ lastUser }}", {
|
|
2215
|
+
commaSeparatedUsers: slicedArr.join(", "),
|
|
2216
|
+
lastUser
|
|
2217
|
+
});
|
|
2218
|
+
} else {
|
|
2219
|
+
outStr = t("{{ commaSeparatedUsers }} and {{ moreCount }} more", {
|
|
2220
|
+
commaSeparatedUsers: slicedArr.join(", "),
|
|
2221
|
+
moreCount: restLength
|
|
2222
|
+
});
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
return outStr;
|
|
2226
|
+
};
|
|
2227
|
+
const countEmojis = (text) => {
|
|
2228
|
+
const matches = text?.match(emojiRegex());
|
|
2229
|
+
return matches ? matches.length : 0;
|
|
2230
|
+
};
|
|
2231
|
+
const messageTextHasEmojisOnly = (message) => {
|
|
2232
|
+
if (!message.text) return false;
|
|
2233
|
+
const noEmojis = message.text.replace(emojiRegex(), "");
|
|
2234
|
+
const noSpace = noEmojis.replace(/[\s\n]/gm, "");
|
|
2235
|
+
return !noSpace;
|
|
2236
|
+
};
|
|
2237
|
+
const isMessageErrorRetryable = (message) => message.status === "failed" && message.error?.status !== 403;
|
|
2238
|
+
const isNetworkSendFailure = (message) => message.status === "failed" && message.error?.status === 0;
|
|
2239
|
+
const isMessageBounced = (message) => message.type === "error" && (message.moderation_details?.action === "MESSAGE_RESPONSE_ACTION_BOUNCE" || message.moderation?.action === "bounce");
|
|
2240
|
+
const isMessageBlocked = (message) => message.shadowed || message.type === "error" && (message.moderation_details?.action === "MESSAGE_RESPONSE_ACTION_REMOVE" || message.moderation?.action === "remove");
|
|
2241
|
+
const isMessageDeleted = (message) => Boolean(message.deleted_at || message.type === "deleted" || message.deleted_for_me);
|
|
2242
|
+
const isMessageEdited = (message) => !!message.message_text_updated_at;
|
|
2243
|
+
const hasResizeObserver = typeof window !== "undefined" && "ResizeObserver" in window;
|
|
2244
|
+
function autoMiddlewareFor(p) {
|
|
2245
|
+
if (!String(p).startsWith("auto")) return null;
|
|
2246
|
+
const alignment = p === "auto-start" ? "start" : p === "auto-end" ? "end" : void 0;
|
|
2247
|
+
return autoPlacement({ alignment });
|
|
2248
|
+
}
|
|
2249
|
+
function toOffsetMw(opt) {
|
|
2250
|
+
if (opt == null) return null;
|
|
2251
|
+
if (Array.isArray(opt)) {
|
|
2252
|
+
const [crossAxis, mainAxis] = opt;
|
|
2253
|
+
return offset({ crossAxis, mainAxis });
|
|
2254
|
+
}
|
|
2255
|
+
if (typeof opt === "number") return offset(opt);
|
|
2256
|
+
return offset(opt);
|
|
2257
|
+
}
|
|
2258
|
+
function usePopoverPosition({
|
|
2259
|
+
allowFlip = true,
|
|
2260
|
+
allowShift = true,
|
|
2261
|
+
autoUpdateOptions,
|
|
2262
|
+
fitAvailableSpace = false,
|
|
2263
|
+
freeze = false,
|
|
2264
|
+
offset: offset2,
|
|
2265
|
+
placement = "bottom-start",
|
|
2266
|
+
shiftOptions
|
|
2267
|
+
}) {
|
|
2268
|
+
const autoMw = autoMiddlewareFor(placement);
|
|
2269
|
+
const offsetMiddleware = toOffsetMw(offset2);
|
|
2270
|
+
const isSidePlacement = placement.startsWith("left") || placement.startsWith("right");
|
|
2271
|
+
const mergedShiftOptions = shiftOptions ? { padding: 8, ...shiftOptions } : { padding: 8 };
|
|
2272
|
+
const middleware = [
|
|
2273
|
+
// offset first (mirrors common Popper setups)
|
|
2274
|
+
...offsetMiddleware ? [offsetMiddleware] : [],
|
|
2275
|
+
// choose between autoPlacement (Popper's "auto*") OR flip()
|
|
2276
|
+
// only allow flip when not explicitly 'left*' or 'right*'
|
|
2277
|
+
...autoMw ? [autoMw] : allowFlip && !isSidePlacement ? [flip()] : [],
|
|
2278
|
+
// viewport collision adjustments
|
|
2279
|
+
...allowShift ? [shift(mergedShiftOptions)] : [],
|
|
2280
|
+
// optional size constraining
|
|
2281
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
2282
|
+
...fitAvailableSpace ? [size({ apply: () => {
|
|
2283
|
+
} })] : []
|
|
2284
|
+
];
|
|
2285
|
+
const seedPlacement = String(placement).startsWith("auto") ? "bottom" : placement;
|
|
2286
|
+
return useFloating({
|
|
2287
|
+
middleware,
|
|
2288
|
+
placement: seedPlacement,
|
|
2289
|
+
strategy: "fixed",
|
|
2290
|
+
whileElementsMounted: freeze ? void 0 : (reference, floating, update) => autoUpdate(reference, floating, update, {
|
|
2291
|
+
ancestorResize: true,
|
|
2292
|
+
ancestorScroll: true,
|
|
2293
|
+
animationFrame: false,
|
|
2294
|
+
elementResize: hasResizeObserver,
|
|
2295
|
+
...autoUpdateOptions
|
|
2296
|
+
})
|
|
2297
|
+
});
|
|
2298
|
+
}
|
|
2299
|
+
const LegacyThreadContext = React.createContext({ legacyThread: void 0 });
|
|
2300
|
+
const useLegacyThreadContext = () => useContext(LegacyThreadContext);
|
|
2301
|
+
const DEFAULT_PLAYBACK_RATES = [1, 1.5, 2];
|
|
2302
|
+
const isSeekable = (audioElement) => !(audioElement.duration === Infinity || isNaN(audioElement.duration));
|
|
2303
|
+
const defaultRegisterAudioPlayerError = ({
|
|
2304
|
+
error
|
|
2305
|
+
} = {}) => {
|
|
2306
|
+
if (!error) return;
|
|
2307
|
+
console.error("[AUDIO PLAYER]", error);
|
|
2308
|
+
};
|
|
2309
|
+
const elementIsPlaying = (audioElement) => audioElement && !(audioElement.paused || audioElement.ended);
|
|
2310
|
+
class AudioPlayer {
|
|
2311
|
+
constructor({
|
|
2312
|
+
durationSeconds,
|
|
2313
|
+
fileSize,
|
|
2314
|
+
id,
|
|
2315
|
+
mimeType,
|
|
2316
|
+
playbackRates: customPlaybackRates,
|
|
2317
|
+
plugins,
|
|
2318
|
+
pool,
|
|
2319
|
+
src,
|
|
2320
|
+
title,
|
|
2321
|
+
waveformData
|
|
2322
|
+
}) {
|
|
2323
|
+
this._plugins = /* @__PURE__ */ new Map();
|
|
2324
|
+
this.playTimeout = void 0;
|
|
2325
|
+
this.unsubscribeEventListeners = null;
|
|
2326
|
+
this._disposed = false;
|
|
2327
|
+
this._metadataProbe = null;
|
|
2328
|
+
this._restoringPosition = false;
|
|
2329
|
+
this._removalTimeout = void 0;
|
|
2330
|
+
this.setDurationSeconds = (durationSeconds2) => {
|
|
2331
|
+
this._data.durationSeconds = durationSeconds2;
|
|
2332
|
+
this.state.partialNext({ durationSeconds: durationSeconds2 });
|
|
2333
|
+
};
|
|
2334
|
+
this.setPlaybackStartSafetyTimeout = () => {
|
|
2335
|
+
clearTimeout(this.playTimeout);
|
|
2336
|
+
this.playTimeout = setTimeout(() => {
|
|
2337
|
+
if (!this.elementRef) return;
|
|
2338
|
+
try {
|
|
2339
|
+
this.elementRef.pause();
|
|
2340
|
+
this.state.partialNext({ isPlaying: false });
|
|
2341
|
+
} catch (e) {
|
|
2342
|
+
this.registerError({ errCode: "failed-to-start" });
|
|
2343
|
+
}
|
|
2344
|
+
}, 2e3);
|
|
2345
|
+
};
|
|
2346
|
+
this.updateDurationFromElement = (element) => {
|
|
2347
|
+
const duration = element.duration;
|
|
2348
|
+
if (typeof duration !== "number" || isNaN(duration) || !isFinite(duration) || duration <= 0) {
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2351
|
+
this.setDurationSeconds(duration);
|
|
2352
|
+
};
|
|
2353
|
+
this.clearMetadataProbe = () => {
|
|
2354
|
+
const probe = this._metadataProbe;
|
|
2355
|
+
this._metadataProbe = null;
|
|
2356
|
+
this._metadataProbePromise = void 0;
|
|
2357
|
+
if (!probe) return;
|
|
2358
|
+
try {
|
|
2359
|
+
probe.pause();
|
|
2360
|
+
} catch {
|
|
2361
|
+
}
|
|
2362
|
+
probe.removeAttribute("src");
|
|
2363
|
+
try {
|
|
2364
|
+
probe.load();
|
|
2365
|
+
} catch {
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
this.preloadMetadata = () => {
|
|
2369
|
+
if (this._disposed || this.durationSeconds != null || !this.src || this._metadataProbePromise || typeof document === "undefined") {
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
const probe = document.createElement("audio");
|
|
2373
|
+
probe.preload = "metadata";
|
|
2374
|
+
this._metadataProbe = probe;
|
|
2375
|
+
this._metadataProbePromise = new Promise((resolve) => {
|
|
2376
|
+
const cleanup = () => {
|
|
2377
|
+
probe.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
2378
|
+
probe.removeEventListener("error", handleError);
|
|
2379
|
+
if (this._metadataProbe === probe) {
|
|
2380
|
+
this.clearMetadataProbe();
|
|
2381
|
+
} else {
|
|
2382
|
+
this._metadataProbePromise = void 0;
|
|
2383
|
+
}
|
|
2384
|
+
resolve();
|
|
2385
|
+
};
|
|
2386
|
+
const handleLoadedMetadata = () => {
|
|
2387
|
+
this.updateDurationFromElement(probe);
|
|
2388
|
+
cleanup();
|
|
2389
|
+
};
|
|
2390
|
+
const handleError = () => {
|
|
2391
|
+
cleanup();
|
|
2392
|
+
};
|
|
2393
|
+
probe.addEventListener("loadedmetadata", handleLoadedMetadata, { once: true });
|
|
2394
|
+
probe.addEventListener("error", handleError, { once: true });
|
|
2395
|
+
probe.src = this.src;
|
|
2396
|
+
try {
|
|
2397
|
+
probe.load();
|
|
2398
|
+
} catch {
|
|
2399
|
+
cleanup();
|
|
2400
|
+
}
|
|
2401
|
+
});
|
|
2402
|
+
};
|
|
2403
|
+
this.clearPlaybackStartSafetyTimeout = () => {
|
|
2404
|
+
if (!this.elementRef) return;
|
|
2405
|
+
clearTimeout(this.playTimeout);
|
|
2406
|
+
this.playTimeout = void 0;
|
|
2407
|
+
};
|
|
2408
|
+
this.clearPendingLoadedMeta = () => {
|
|
2409
|
+
const pending = this._pendingLoadedMeta;
|
|
2410
|
+
if (pending?.element && pending.onLoaded) {
|
|
2411
|
+
pending.element.removeEventListener("loadedmetadata", pending.onLoaded);
|
|
2412
|
+
}
|
|
2413
|
+
this._pendingLoadedMeta = void 0;
|
|
2414
|
+
};
|
|
2415
|
+
this.restoreSavedPosition = (elementRef) => {
|
|
2416
|
+
const saved = this.secondsElapsed;
|
|
2417
|
+
if (!saved || saved <= 0) return;
|
|
2418
|
+
const apply = () => {
|
|
2419
|
+
const duration = elementRef.duration;
|
|
2420
|
+
const clamped = typeof duration === "number" && !isNaN(duration) && isFinite(duration) ? Math.min(saved, duration) : saved;
|
|
2421
|
+
try {
|
|
2422
|
+
if (elementRef.currentTime === clamped) return;
|
|
2423
|
+
elementRef.currentTime = clamped;
|
|
2424
|
+
this.setSecondsElapsed(clamped);
|
|
2425
|
+
} catch {
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
if (elementRef.readyState < 1) {
|
|
2429
|
+
this.clearPendingLoadedMeta();
|
|
2430
|
+
this._restoringPosition = true;
|
|
2431
|
+
const onLoaded = () => {
|
|
2432
|
+
if (this._pendingLoadedMeta?.onLoaded !== onLoaded) return;
|
|
2433
|
+
this._pendingLoadedMeta = void 0;
|
|
2434
|
+
if (this.elementRef !== elementRef) {
|
|
2435
|
+
this._restoringPosition = false;
|
|
2436
|
+
return;
|
|
2437
|
+
}
|
|
2438
|
+
apply();
|
|
2439
|
+
this._restoringPosition = false;
|
|
2440
|
+
};
|
|
2441
|
+
elementRef.addEventListener("loadedmetadata", onLoaded, { once: true });
|
|
2442
|
+
this._pendingLoadedMeta = { element: elementRef, onLoaded };
|
|
2443
|
+
} else {
|
|
2444
|
+
this._restoringPosition = true;
|
|
2445
|
+
apply();
|
|
2446
|
+
this._restoringPosition = false;
|
|
2447
|
+
}
|
|
2448
|
+
};
|
|
2449
|
+
this.elementIsReady = () => {
|
|
2450
|
+
if (this._elementIsReadyPromise) return this._elementIsReadyPromise;
|
|
2451
|
+
this._elementIsReadyPromise = new Promise((resolve) => {
|
|
2452
|
+
if (!this.elementRef) return resolve(false);
|
|
2453
|
+
const element = this.elementRef;
|
|
2454
|
+
const handleLoaded = () => {
|
|
2455
|
+
element.removeEventListener("loadedmetadata", handleLoaded);
|
|
2456
|
+
resolve(element.readyState > 0);
|
|
2457
|
+
};
|
|
2458
|
+
element.addEventListener("loadedmetadata", handleLoaded);
|
|
2459
|
+
});
|
|
2460
|
+
return this._elementIsReadyPromise;
|
|
2461
|
+
};
|
|
2462
|
+
this.setRef = (elementRef) => {
|
|
2463
|
+
if (elementIsPlaying(this.elementRef)) {
|
|
2464
|
+
this.releaseElement({ resetState: false });
|
|
2465
|
+
}
|
|
2466
|
+
this.clearPendingLoadedMeta();
|
|
2467
|
+
this.clearMetadataProbe();
|
|
2468
|
+
this._restoringPosition = false;
|
|
2469
|
+
this._elementIsReadyPromise = void 0;
|
|
2470
|
+
this.state.partialNext({ elementRef });
|
|
2471
|
+
if (elementRef) {
|
|
2472
|
+
this.registerSubscriptions();
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
this.setSecondsElapsed = (secondsElapsed) => {
|
|
2476
|
+
const duration = this.elementRef?.duration ?? this.durationSeconds;
|
|
2477
|
+
this.state.partialNext({
|
|
2478
|
+
progressPercent: duration && secondsElapsed ? secondsElapsed / duration * 100 : 0,
|
|
2479
|
+
secondsElapsed
|
|
2480
|
+
});
|
|
2481
|
+
};
|
|
2482
|
+
this.canPlayMimeType = (mimeType2) => {
|
|
2483
|
+
if (!mimeType2) return false;
|
|
2484
|
+
if (this.elementRef) return !!this.elementRef.canPlayType(mimeType2);
|
|
2485
|
+
return !!new Audio().canPlayType(mimeType2);
|
|
2486
|
+
};
|
|
2487
|
+
this.play = async (params) => {
|
|
2488
|
+
if (this._disposed) return;
|
|
2489
|
+
const elementRef = this.ensureElementRef();
|
|
2490
|
+
if (elementIsPlaying(this.elementRef)) {
|
|
2491
|
+
if (this.isPlaying) return;
|
|
2492
|
+
this.state.partialNext({ isPlaying: true });
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
const { currentPlaybackRate, playbackRates: playbackRates2 } = {
|
|
2496
|
+
currentPlaybackRate: this.currentPlaybackRate,
|
|
2497
|
+
playbackRates: this.playbackRates,
|
|
2498
|
+
...params
|
|
2499
|
+
};
|
|
2500
|
+
if (!this.canPlayRecord) {
|
|
2501
|
+
this.registerError({ errCode: "not-playable" });
|
|
2502
|
+
return;
|
|
2503
|
+
}
|
|
2504
|
+
this.restoreSavedPosition(elementRef);
|
|
2505
|
+
elementRef.playbackRate = currentPlaybackRate ?? this.currentPlaybackRate;
|
|
2506
|
+
this.setPlaybackStartSafetyTimeout();
|
|
2507
|
+
try {
|
|
2508
|
+
await elementRef.play();
|
|
2509
|
+
this.state.partialNext({
|
|
2510
|
+
currentPlaybackRate,
|
|
2511
|
+
isPlaying: true,
|
|
2512
|
+
playbackRates: playbackRates2
|
|
2513
|
+
});
|
|
2514
|
+
this._pool.setActiveAudioPlayer(this);
|
|
2515
|
+
} catch (e) {
|
|
2516
|
+
this.registerError({ error: e });
|
|
2517
|
+
this.state.partialNext({ isPlaying: false });
|
|
2518
|
+
} finally {
|
|
2519
|
+
this.clearPlaybackStartSafetyTimeout();
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
this.pause = () => {
|
|
2523
|
+
if (!elementIsPlaying(this.elementRef)) return;
|
|
2524
|
+
this.clearPlaybackStartSafetyTimeout();
|
|
2525
|
+
this.elementRef.pause();
|
|
2526
|
+
this.state.partialNext({ isPlaying: false });
|
|
2527
|
+
};
|
|
2528
|
+
this.stop = () => {
|
|
2529
|
+
this.pause();
|
|
2530
|
+
this.state.partialNext({ isPlaying: false });
|
|
2531
|
+
this.setSecondsElapsed(0);
|
|
2532
|
+
if (this.elementRef) this.elementRef.currentTime = 0;
|
|
2533
|
+
};
|
|
2534
|
+
this.togglePlay = async () => this.isPlaying ? this.pause() : await this.play();
|
|
2535
|
+
this.increasePlaybackRate = () => {
|
|
2536
|
+
let currentPlaybackRateIndex = this.state.getLatestValue().playbackRates.findIndex((rate) => rate === this.currentPlaybackRate);
|
|
2537
|
+
if (currentPlaybackRateIndex === -1) {
|
|
2538
|
+
currentPlaybackRateIndex = 0;
|
|
2539
|
+
}
|
|
2540
|
+
const nextIndex = currentPlaybackRateIndex === this.playbackRates.length - 1 ? 0 : currentPlaybackRateIndex + 1;
|
|
2541
|
+
const currentPlaybackRate = this.playbackRates[nextIndex];
|
|
2542
|
+
this.state.partialNext({ currentPlaybackRate });
|
|
2543
|
+
if (this.elementRef) {
|
|
2544
|
+
this.elementRef.playbackRate = currentPlaybackRate;
|
|
2545
|
+
}
|
|
2546
|
+
};
|
|
2547
|
+
this.seek = throttle(async ({ clientX, currentTarget }) => {
|
|
2548
|
+
let element = this.elementRef;
|
|
2549
|
+
if (!this.elementRef) {
|
|
2550
|
+
element = this.ensureElementRef();
|
|
2551
|
+
const isReady = await this.elementIsReady();
|
|
2552
|
+
if (!isReady) return;
|
|
2553
|
+
}
|
|
2554
|
+
if (!currentTarget || !element) return;
|
|
2555
|
+
if (!isSeekable(element)) {
|
|
2556
|
+
this.registerError({ errCode: "seek-not-supported" });
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
const { width, x } = currentTarget.getBoundingClientRect();
|
|
2560
|
+
const ratio = (clientX - x) / width;
|
|
2561
|
+
if (ratio > 1 || ratio < 0) return;
|
|
2562
|
+
const currentTime = ratio * element.duration;
|
|
2563
|
+
this.setSecondsElapsed(currentTime);
|
|
2564
|
+
element.currentTime = currentTime;
|
|
2565
|
+
}, 16);
|
|
2566
|
+
this.registerError = (params) => {
|
|
2567
|
+
defaultRegisterAudioPlayerError(params);
|
|
2568
|
+
this.plugins.forEach(({ onError }) => onError?.({ player: this, ...params }));
|
|
2569
|
+
};
|
|
2570
|
+
this.requestRemoval = () => {
|
|
2571
|
+
this._disposed = true;
|
|
2572
|
+
this.cancelScheduledRemoval();
|
|
2573
|
+
this.clearPendingLoadedMeta();
|
|
2574
|
+
this.clearMetadataProbe();
|
|
2575
|
+
this._restoringPosition = false;
|
|
2576
|
+
this.releaseElement({ resetState: true });
|
|
2577
|
+
this.unsubscribeEventListeners?.();
|
|
2578
|
+
this.unsubscribeEventListeners = null;
|
|
2579
|
+
this.plugins.forEach(({ onRemove }) => onRemove?.({ player: this }));
|
|
2580
|
+
this._pool.deregister(this.id);
|
|
2581
|
+
};
|
|
2582
|
+
this.cancelScheduledRemoval = () => {
|
|
2583
|
+
clearTimeout(this._removalTimeout);
|
|
2584
|
+
this._removalTimeout = void 0;
|
|
2585
|
+
};
|
|
2586
|
+
this.scheduleRemoval = (ms = 0) => {
|
|
2587
|
+
this.cancelScheduledRemoval();
|
|
2588
|
+
this._removalTimeout = setTimeout(() => {
|
|
2589
|
+
if (this.disposed) return;
|
|
2590
|
+
this.requestRemoval();
|
|
2591
|
+
}, ms);
|
|
2592
|
+
};
|
|
2593
|
+
this.releaseElementForHandoff = () => {
|
|
2594
|
+
if (!this.elementRef) return;
|
|
2595
|
+
this.releaseElement({ resetState: false });
|
|
2596
|
+
this.unsubscribeEventListeners?.();
|
|
2597
|
+
this.unsubscribeEventListeners = null;
|
|
2598
|
+
};
|
|
2599
|
+
this.registerSubscriptions = () => {
|
|
2600
|
+
this.unsubscribeEventListeners?.();
|
|
2601
|
+
const audioElement = this.elementRef;
|
|
2602
|
+
if (!audioElement) return;
|
|
2603
|
+
const handleEnded = () => {
|
|
2604
|
+
if (audioElement) {
|
|
2605
|
+
this.updateDurationFromElement(audioElement);
|
|
2606
|
+
}
|
|
2607
|
+
this.stop();
|
|
2608
|
+
};
|
|
2609
|
+
const handleError = (e) => {
|
|
2610
|
+
const audio = e.currentTarget;
|
|
2611
|
+
const state = { isPlaying: false };
|
|
2612
|
+
if (!audio?.error?.code) {
|
|
2613
|
+
this.state.partialNext(state);
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2616
|
+
if (audio.error.code === 4) {
|
|
2617
|
+
state.canPlayRecord = false;
|
|
2618
|
+
this.state.partialNext(state);
|
|
2619
|
+
}
|
|
2620
|
+
const errorMsg = [
|
|
2621
|
+
void 0,
|
|
2622
|
+
"MEDIA_ERR_ABORTED: fetch aborted by user",
|
|
2623
|
+
"MEDIA_ERR_NETWORK: network failed while fetching",
|
|
2624
|
+
"MEDIA_ERR_DECODE: audio fetched but couldn’t decode",
|
|
2625
|
+
"MEDIA_ERR_SRC_NOT_SUPPORTED: source not supported"
|
|
2626
|
+
][audio?.error?.code];
|
|
2627
|
+
if (!errorMsg) return;
|
|
2628
|
+
defaultRegisterAudioPlayerError({ error: new Error(errorMsg + ` (${audio.src})`) });
|
|
2629
|
+
};
|
|
2630
|
+
const handleTimeupdate = () => {
|
|
2631
|
+
const t = audioElement?.currentTime ?? 0;
|
|
2632
|
+
if (this._restoringPosition && t === 0) return;
|
|
2633
|
+
if (!this.isPlaying && t === 0 && this.secondsElapsed > 0) return;
|
|
2634
|
+
this.setSecondsElapsed(t);
|
|
2635
|
+
};
|
|
2636
|
+
const handleLoadedMetadata = () => {
|
|
2637
|
+
if (audioElement) {
|
|
2638
|
+
this.updateDurationFromElement(audioElement);
|
|
2639
|
+
}
|
|
2640
|
+
};
|
|
2641
|
+
audioElement.addEventListener("ended", handleEnded);
|
|
2642
|
+
audioElement.addEventListener("error", handleError);
|
|
2643
|
+
audioElement.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
2644
|
+
audioElement.addEventListener("timeupdate", handleTimeupdate);
|
|
2645
|
+
this.unsubscribeEventListeners = () => {
|
|
2646
|
+
audioElement.pause();
|
|
2647
|
+
audioElement.removeEventListener("ended", handleEnded);
|
|
2648
|
+
audioElement.removeEventListener("error", handleError);
|
|
2649
|
+
audioElement.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
2650
|
+
audioElement.removeEventListener("timeupdate", handleTimeupdate);
|
|
2651
|
+
};
|
|
2652
|
+
};
|
|
2653
|
+
this._data = {
|
|
2654
|
+
durationSeconds,
|
|
2655
|
+
fileSize,
|
|
2656
|
+
id,
|
|
2657
|
+
mimeType,
|
|
2658
|
+
src,
|
|
2659
|
+
title,
|
|
2660
|
+
waveformData
|
|
2661
|
+
};
|
|
2662
|
+
this._pool = pool;
|
|
2663
|
+
this.setPlugins(() => plugins ?? []);
|
|
2664
|
+
const playbackRates = customPlaybackRates?.length ? customPlaybackRates : DEFAULT_PLAYBACK_RATES;
|
|
2665
|
+
const canPlayRecord = mimeType ? !!new Audio().canPlayType(mimeType) : true;
|
|
2666
|
+
this.state = new StateStore({
|
|
2667
|
+
canPlayRecord,
|
|
2668
|
+
currentPlaybackRate: playbackRates[0],
|
|
2669
|
+
durationSeconds,
|
|
2670
|
+
elementRef: null,
|
|
2671
|
+
isPlaying: false,
|
|
2672
|
+
playbackError: null,
|
|
2673
|
+
playbackRates,
|
|
2674
|
+
progressPercent: 0,
|
|
2675
|
+
secondsElapsed: 0
|
|
2676
|
+
});
|
|
2677
|
+
this.plugins.forEach((p) => p.onInit?.({ player: this }));
|
|
2678
|
+
this.preloadMetadata();
|
|
2722
2679
|
}
|
|
2723
|
-
|
|
2724
|
-
|
|
2680
|
+
get plugins() {
|
|
2681
|
+
return Array.from(this._plugins.values());
|
|
2725
2682
|
}
|
|
2726
|
-
|
|
2727
|
-
|
|
2683
|
+
get canPlayRecord() {
|
|
2684
|
+
return this.state.getLatestValue().canPlayRecord;
|
|
2728
2685
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2686
|
+
get elementRef() {
|
|
2687
|
+
return this.state.getLatestValue().elementRef;
|
|
2731
2688
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2689
|
+
get isPlaying() {
|
|
2690
|
+
return this.state.getLatestValue().isPlaying;
|
|
2734
2691
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2692
|
+
get currentPlaybackRate() {
|
|
2693
|
+
return this.state.getLatestValue().currentPlaybackRate;
|
|
2737
2694
|
}
|
|
2738
|
-
|
|
2739
|
-
|
|
2695
|
+
get playbackRates() {
|
|
2696
|
+
return this.state.getLatestValue().playbackRates;
|
|
2740
2697
|
}
|
|
2741
|
-
|
|
2742
|
-
|
|
2698
|
+
get durationSeconds() {
|
|
2699
|
+
return this.state.getLatestValue().durationSeconds;
|
|
2743
2700
|
}
|
|
2744
|
-
|
|
2745
|
-
|
|
2701
|
+
get fileSize() {
|
|
2702
|
+
return this._data.fileSize;
|
|
2746
2703
|
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2704
|
+
get id() {
|
|
2705
|
+
return this._data.id;
|
|
2749
2706
|
}
|
|
2750
|
-
|
|
2751
|
-
|
|
2707
|
+
get src() {
|
|
2708
|
+
return this._data.src;
|
|
2752
2709
|
}
|
|
2753
|
-
|
|
2754
|
-
|
|
2710
|
+
get mimeType() {
|
|
2711
|
+
return this._data.mimeType;
|
|
2755
2712
|
}
|
|
2756
|
-
|
|
2757
|
-
|
|
2713
|
+
get title() {
|
|
2714
|
+
return this._data.title;
|
|
2758
2715
|
}
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
const ACTIONS_NOT_WORKING_IN_THREAD = [
|
|
2762
|
-
MESSAGE_ACTIONS.pin,
|
|
2763
|
-
MESSAGE_ACTIONS.reply,
|
|
2764
|
-
MESSAGE_ACTIONS.markUnread
|
|
2765
|
-
];
|
|
2766
|
-
function areMessagesEqual(prevMessage, nextMessage) {
|
|
2767
|
-
const areBaseMessagesEqual = (prevMessage2, nextMessage2) => prevMessage2.deleted_at === nextMessage2.deleted_at && prevMessage2.latest_reactions?.length === nextMessage2.latest_reactions?.length && prevMessage2.own_reactions?.length === nextMessage2.own_reactions?.length && prevMessage2.pinned === nextMessage2.pinned && prevMessage2.reply_count === nextMessage2.reply_count && prevMessage2.show_in_channel === nextMessage2.show_in_channel && prevMessage2.status === nextMessage2.status && prevMessage2.text === nextMessage2.text && prevMessage2.type === nextMessage2.type && prevMessage2.updated_at === nextMessage2.updated_at && prevMessage2.user?.updated_at === nextMessage2.user?.updated_at;
|
|
2768
|
-
return areBaseMessagesEqual(prevMessage, nextMessage) && Boolean(prevMessage.quoted_message) === Boolean(nextMessage.quoted_message) && (!prevMessage.quoted_message && !nextMessage.quoted_message || areBaseMessagesEqual(
|
|
2769
|
-
prevMessage.quoted_message,
|
|
2770
|
-
nextMessage.quoted_message
|
|
2771
|
-
));
|
|
2772
|
-
}
|
|
2773
|
-
const areMessagePropsEqual = (prevProps, nextProps) => {
|
|
2774
|
-
const { message: prevMessage, Message: prevMessageUI } = prevProps;
|
|
2775
|
-
const { message: nextMessage, Message: nextMessageUI } = nextProps;
|
|
2776
|
-
if (prevMessageUI !== nextMessageUI) return false;
|
|
2777
|
-
if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {
|
|
2778
|
-
return false;
|
|
2716
|
+
get waveformData() {
|
|
2717
|
+
return this._data.waveformData;
|
|
2779
2718
|
}
|
|
2780
|
-
|
|
2781
|
-
return
|
|
2719
|
+
get secondsElapsed() {
|
|
2720
|
+
return this.state.getLatestValue().secondsElapsed;
|
|
2782
2721
|
}
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
const deepEqualProps = deepequal(nextProps.messageActions, prevProps.messageActions) && deepequal(nextProps.readBy, prevProps.readBy) && deepequal(nextProps.deliveredTo, prevProps.deliveredTo) && deepequal(nextProps.highlighted, prevProps.highlighted) && deepequal(nextProps.groupStyles, prevProps.groupStyles) && // last 3 messages can have different group styles
|
|
2786
|
-
deepequal(nextProps.mutes, prevProps.mutes) && deepequal(nextProps.lastReceivedId, prevProps.lastReceivedId);
|
|
2787
|
-
if (!deepEqualProps) return false;
|
|
2788
|
-
return prevProps.messageListRect === nextProps.messageListRect;
|
|
2789
|
-
};
|
|
2790
|
-
const areMessageUIPropsEqual = (prevProps, nextProps) => {
|
|
2791
|
-
const { lastReceivedId: prevLastReceivedId, message: prevMessage } = prevProps;
|
|
2792
|
-
const { lastReceivedId: nextLastReceivedId, message: nextMessage } = nextProps;
|
|
2793
|
-
if (prevProps.highlighted !== nextProps.highlighted) return false;
|
|
2794
|
-
if (prevProps.threadList !== nextProps.threadList) return false;
|
|
2795
|
-
if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;
|
|
2796
|
-
if (prevProps.mutes?.length !== nextProps.mutes?.length) return false;
|
|
2797
|
-
if (prevProps.readBy?.length !== nextProps.readBy?.length) return false;
|
|
2798
|
-
if (prevProps.deliveredTo?.length !== nextProps.deliveredTo?.length) return false;
|
|
2799
|
-
if (prevProps.groupStyles !== nextProps.groupStyles) return false;
|
|
2800
|
-
if (prevProps.showDetailedReactions !== nextProps.showDetailedReactions) {
|
|
2801
|
-
return false;
|
|
2722
|
+
get progressPercent() {
|
|
2723
|
+
return this.state.getLatestValue().progressPercent;
|
|
2802
2724
|
}
|
|
2803
|
-
|
|
2804
|
-
return
|
|
2725
|
+
get disposed() {
|
|
2726
|
+
return this._disposed;
|
|
2805
2727
|
}
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
const
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2728
|
+
ensureElementRef() {
|
|
2729
|
+
if (this._disposed) {
|
|
2730
|
+
throw new Error("AudioPlayer is disposed");
|
|
2731
|
+
}
|
|
2732
|
+
if (!this.elementRef) {
|
|
2733
|
+
const el = this._pool.acquireElement({
|
|
2734
|
+
ownerId: this.id,
|
|
2735
|
+
src: this.src
|
|
2736
|
+
});
|
|
2737
|
+
this.setRef(el);
|
|
2738
|
+
}
|
|
2739
|
+
return this.elementRef;
|
|
2816
2740
|
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2741
|
+
setDescriptor(descriptor) {
|
|
2742
|
+
const previousSrc = this.src;
|
|
2743
|
+
this._data = { ...this._data, ...descriptor };
|
|
2744
|
+
if (descriptor.src !== previousSrc && this.elementRef) {
|
|
2745
|
+
this.elementRef.src = descriptor.src;
|
|
2746
|
+
}
|
|
2747
|
+
if (descriptor.src && descriptor.src !== previousSrc) {
|
|
2748
|
+
this.clearMetadataProbe();
|
|
2749
|
+
if (descriptor.durationSeconds == null) {
|
|
2750
|
+
this.setDurationSeconds(void 0);
|
|
2751
|
+
this.preloadMetadata();
|
|
2752
|
+
} else {
|
|
2753
|
+
this.setDurationSeconds(descriptor.durationSeconds);
|
|
2754
|
+
}
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
if (descriptor.durationSeconds != null) {
|
|
2758
|
+
this.setDurationSeconds(descriptor.durationSeconds);
|
|
2759
|
+
}
|
|
2822
2760
|
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2761
|
+
releaseElement({ resetState }) {
|
|
2762
|
+
this.clearPendingLoadedMeta();
|
|
2763
|
+
this.clearMetadataProbe();
|
|
2764
|
+
this._restoringPosition = false;
|
|
2765
|
+
if (resetState) {
|
|
2766
|
+
this.stop();
|
|
2767
|
+
} else {
|
|
2768
|
+
this.state.partialNext({ isPlaying: false });
|
|
2769
|
+
if (this.elementRef) {
|
|
2770
|
+
try {
|
|
2771
|
+
this.elementRef.pause();
|
|
2772
|
+
} catch {
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
if (this.elementRef) {
|
|
2777
|
+
this._pool.releaseElement(this.id);
|
|
2778
|
+
this.setRef(null);
|
|
2779
|
+
}
|
|
2832
2780
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2781
|
+
setPlugins(setter) {
|
|
2782
|
+
this._plugins = setter(this.plugins).reduce((acc, plugin) => {
|
|
2783
|
+
if (plugin.id) {
|
|
2784
|
+
acc.set(plugin.id, plugin);
|
|
2785
|
+
}
|
|
2786
|
+
return acc;
|
|
2787
|
+
}, /* @__PURE__ */ new Map());
|
|
2837
2788
|
}
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
} else if (slicedArr.length === 2) {
|
|
2844
|
-
outStr = t("{{ firstUser }} and {{ secondUser }}", {
|
|
2845
|
-
firstUser: slicedArr[0],
|
|
2846
|
-
secondUser: slicedArr[1]
|
|
2789
|
+
}
|
|
2790
|
+
class AudioPlayerPool {
|
|
2791
|
+
constructor(config) {
|
|
2792
|
+
this.state = new StateStore({
|
|
2793
|
+
activeAudioPlayer: null
|
|
2847
2794
|
});
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2795
|
+
this.pool = /* @__PURE__ */ new Map();
|
|
2796
|
+
this.audios = /* @__PURE__ */ new Map();
|
|
2797
|
+
this.sharedAudio = null;
|
|
2798
|
+
this.sharedOwnerId = null;
|
|
2799
|
+
this.getOrAdd = (params) => {
|
|
2800
|
+
const { playbackRates, plugins, ...descriptor } = params;
|
|
2801
|
+
let player = this.pool.get(params.id);
|
|
2802
|
+
if (player) {
|
|
2803
|
+
if (!player.disposed) {
|
|
2804
|
+
player.setDescriptor(descriptor);
|
|
2805
|
+
return player;
|
|
2806
|
+
}
|
|
2807
|
+
this.deregister(params.id);
|
|
2808
|
+
}
|
|
2809
|
+
player = new AudioPlayer({
|
|
2810
|
+
playbackRates,
|
|
2811
|
+
plugins,
|
|
2812
|
+
...descriptor,
|
|
2813
|
+
pool: this
|
|
2854
2814
|
});
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2815
|
+
this.pool.set(params.id, player);
|
|
2816
|
+
return player;
|
|
2817
|
+
};
|
|
2818
|
+
this.acquireElement = ({ ownerId, src }) => {
|
|
2819
|
+
if (!this.allowConcurrentPlayback) {
|
|
2820
|
+
if (!this.sharedAudio) {
|
|
2821
|
+
this.sharedAudio = new Audio();
|
|
2822
|
+
}
|
|
2823
|
+
if (this.sharedOwnerId && this.sharedOwnerId !== ownerId) {
|
|
2824
|
+
const previous = this.pool.get(this.sharedOwnerId);
|
|
2825
|
+
previous?.pause();
|
|
2826
|
+
previous?.releaseElementForHandoff();
|
|
2827
|
+
}
|
|
2828
|
+
this.sharedOwnerId = ownerId;
|
|
2829
|
+
if (this.sharedAudio.src !== src) {
|
|
2830
|
+
this.sharedAudio.src = src;
|
|
2831
|
+
}
|
|
2832
|
+
return this.sharedAudio;
|
|
2833
|
+
}
|
|
2834
|
+
let audio = this.audios.get(ownerId);
|
|
2835
|
+
if (!audio) {
|
|
2836
|
+
audio = new Audio();
|
|
2837
|
+
this.audios.set(ownerId, audio);
|
|
2838
|
+
}
|
|
2839
|
+
if (audio.src !== src) {
|
|
2840
|
+
audio.src = src;
|
|
2841
|
+
}
|
|
2842
|
+
return audio;
|
|
2843
|
+
};
|
|
2844
|
+
this.releaseElement = (ownerId) => {
|
|
2845
|
+
if (!this.allowConcurrentPlayback) {
|
|
2846
|
+
if (this.sharedOwnerId !== ownerId) return;
|
|
2847
|
+
const el2 = this.sharedAudio;
|
|
2848
|
+
if (el2) {
|
|
2849
|
+
try {
|
|
2850
|
+
el2.pause();
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2853
|
+
el2.removeAttribute("src");
|
|
2854
|
+
el2.load();
|
|
2855
|
+
}
|
|
2856
|
+
this.sharedOwnerId = null;
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2859
|
+
const el = this.audios.get(ownerId);
|
|
2860
|
+
if (!el) return;
|
|
2861
|
+
try {
|
|
2862
|
+
el.pause();
|
|
2863
|
+
} catch {
|
|
2864
|
+
}
|
|
2865
|
+
el.removeAttribute("src");
|
|
2866
|
+
el.load();
|
|
2867
|
+
this.audios.delete(ownerId);
|
|
2868
|
+
};
|
|
2869
|
+
this.setActiveAudioPlayer = (activeAudioPlayer) => {
|
|
2870
|
+
if (this.allowConcurrentPlayback) return;
|
|
2871
|
+
this.state.partialNext({ activeAudioPlayer });
|
|
2872
|
+
};
|
|
2873
|
+
this.remove = (id) => {
|
|
2874
|
+
const player = this.pool.get(id);
|
|
2875
|
+
if (!player) return;
|
|
2876
|
+
player.requestRemoval();
|
|
2877
|
+
};
|
|
2878
|
+
this.clear = () => {
|
|
2879
|
+
this.players.forEach((player) => {
|
|
2880
|
+
this.remove(player.id);
|
|
2881
|
+
});
|
|
2882
|
+
};
|
|
2883
|
+
this.registerSubscriptions = () => {
|
|
2884
|
+
this.players.forEach((p) => {
|
|
2885
|
+
if (p.elementRef) {
|
|
2886
|
+
p.registerSubscriptions();
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
};
|
|
2890
|
+
this.allowConcurrentPlayback = !!config?.allowConcurrentPlayback;
|
|
2891
|
+
}
|
|
2892
|
+
get players() {
|
|
2893
|
+
return Array.from(this.pool.values());
|
|
2894
|
+
}
|
|
2895
|
+
get activeAudioPlayer() {
|
|
2896
|
+
return this.state.getLatestValue().activeAudioPlayer;
|
|
2897
|
+
}
|
|
2898
|
+
/** Removes the AudioPlayer instance from the pool of players */
|
|
2899
|
+
deregister(id) {
|
|
2900
|
+
if (this.pool.has(id)) {
|
|
2901
|
+
this.pool.delete(id);
|
|
2902
|
+
}
|
|
2903
|
+
if (this.activeAudioPlayer?.id === id) {
|
|
2904
|
+
this.setActiveAudioPlayer(null);
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
const SEEK_NOT_SUPPORTED_NOTIFICATION_DEBOUNCE_INTERVAL_MS = 1e3;
|
|
2909
|
+
const audioPlayerNotificationsPluginFactory = ({
|
|
2910
|
+
addNotification,
|
|
2911
|
+
panel = "channel",
|
|
2912
|
+
t
|
|
2913
|
+
}) => {
|
|
2914
|
+
const errors = {
|
|
2915
|
+
"failed-to-start": new Error(t("Failed to play the recording")),
|
|
2916
|
+
"not-playable": new Error(
|
|
2917
|
+
t("Recording format is not supported and cannot be reproduced")
|
|
2918
|
+
),
|
|
2919
|
+
"seek-not-supported": new Error(t("Cannot seek in the recording"))
|
|
2920
|
+
};
|
|
2921
|
+
let lastSeekNotSupportedNotificationAt;
|
|
2922
|
+
return {
|
|
2923
|
+
id: "AudioPlayerNotificationsPlugin",
|
|
2924
|
+
onError: ({ errCode, error: e }) => {
|
|
2925
|
+
if (errCode === "seek-not-supported") {
|
|
2926
|
+
const now = Date.now();
|
|
2927
|
+
if (typeof lastSeekNotSupportedNotificationAt === "number" && now - lastSeekNotSupportedNotificationAt < SEEK_NOT_SUPPORTED_NOTIFICATION_DEBOUNCE_INTERVAL_MS) {
|
|
2928
|
+
return;
|
|
2929
|
+
}
|
|
2930
|
+
lastSeekNotSupportedNotificationAt = now;
|
|
2931
|
+
}
|
|
2932
|
+
const error = (errCode && errors[errCode]) ?? e ?? new Error(t("Error reproducing the recording"));
|
|
2933
|
+
addNotification({
|
|
2934
|
+
emitter: "AudioPlayer",
|
|
2935
|
+
error,
|
|
2936
|
+
message: error.message,
|
|
2937
|
+
severity: "error",
|
|
2938
|
+
targetPanels: [panel],
|
|
2939
|
+
type: "browser:audio:playback:error"
|
|
2859
2940
|
});
|
|
2860
2941
|
}
|
|
2861
|
-
}
|
|
2862
|
-
return outStr;
|
|
2942
|
+
};
|
|
2863
2943
|
};
|
|
2864
|
-
const
|
|
2865
|
-
|
|
2866
|
-
|
|
2944
|
+
const AudioPlayerContext = React.createContext({
|
|
2945
|
+
audioPlayers: null
|
|
2946
|
+
});
|
|
2947
|
+
const WithAudioPlayback = ({
|
|
2948
|
+
allowConcurrentPlayback,
|
|
2949
|
+
children
|
|
2950
|
+
}) => {
|
|
2951
|
+
const [audioPlayers] = useState(() => new AudioPlayerPool({ allowConcurrentPlayback }));
|
|
2952
|
+
useEffect(
|
|
2953
|
+
() => () => {
|
|
2954
|
+
audioPlayers.clear();
|
|
2955
|
+
},
|
|
2956
|
+
[audioPlayers]
|
|
2957
|
+
);
|
|
2958
|
+
return /* @__PURE__ */ jsx(AudioPlayerContext.Provider, { value: { audioPlayers }, children });
|
|
2867
2959
|
};
|
|
2868
|
-
const
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2960
|
+
const makeAudioPlayerId = ({ requester, src }) => `${requester ?? "requester-unknown"}:${src}`;
|
|
2961
|
+
const useAudioPlayer = ({
|
|
2962
|
+
durationSeconds,
|
|
2963
|
+
fileSize,
|
|
2964
|
+
mimeType,
|
|
2965
|
+
playbackRates,
|
|
2966
|
+
plugins,
|
|
2967
|
+
requester = "",
|
|
2968
|
+
src,
|
|
2969
|
+
title,
|
|
2970
|
+
waveformData
|
|
2971
|
+
}) => {
|
|
2972
|
+
const { addNotification } = useNotificationApi();
|
|
2973
|
+
const panel = useNotificationTarget();
|
|
2974
|
+
const { t } = useTranslationContext();
|
|
2975
|
+
const { audioPlayers } = useContext(AudioPlayerContext);
|
|
2976
|
+
const audioPlayer = src && audioPlayers ? audioPlayers.getOrAdd({
|
|
2977
|
+
durationSeconds,
|
|
2978
|
+
fileSize,
|
|
2979
|
+
id: makeAudioPlayerId({ requester, src }),
|
|
2980
|
+
mimeType,
|
|
2981
|
+
playbackRates,
|
|
2982
|
+
plugins,
|
|
2983
|
+
src,
|
|
2984
|
+
title,
|
|
2985
|
+
waveformData
|
|
2986
|
+
}) : void 0;
|
|
2987
|
+
useEffect(() => {
|
|
2988
|
+
if (!audioPlayer) return;
|
|
2989
|
+
const notificationsPlugin = audioPlayerNotificationsPluginFactory({
|
|
2990
|
+
addNotification,
|
|
2991
|
+
panel,
|
|
2992
|
+
t
|
|
2993
|
+
});
|
|
2994
|
+
audioPlayer.setPlugins((currentPlugins) => [
|
|
2995
|
+
...currentPlugins.filter((plugin) => plugin.id !== notificationsPlugin.id),
|
|
2996
|
+
notificationsPlugin
|
|
2997
|
+
]);
|
|
2998
|
+
}, [addNotification, audioPlayer, panel, t]);
|
|
2999
|
+
return audioPlayer;
|
|
3000
|
+
};
|
|
3001
|
+
const activeAudioPlayerSelector = ({ activeAudioPlayer }) => ({
|
|
3002
|
+
activeAudioPlayer
|
|
3003
|
+
});
|
|
3004
|
+
const useActiveAudioPlayer = () => {
|
|
3005
|
+
const { audioPlayers } = useContext(AudioPlayerContext);
|
|
3006
|
+
const { activeAudioPlayer } = useStateStore(audioPlayers?.state, activeAudioPlayerSelector) ?? {};
|
|
3007
|
+
return activeAudioPlayer;
|
|
2873
3008
|
};
|
|
2874
|
-
const isMessageErrorRetryable = (message) => message.status === "failed" && message.error?.status !== 403;
|
|
2875
|
-
const isNetworkSendFailure = (message) => message.status === "failed" && message.error?.status === 0;
|
|
2876
|
-
const isMessageBounced = (message) => message.type === "error" && (message.moderation_details?.action === "MESSAGE_RESPONSE_ACTION_BOUNCE" || message.moderation?.action === "bounce");
|
|
2877
|
-
const isMessageBlocked = (message) => message.shadowed || message.type === "error" && (message.moderation_details?.action === "MESSAGE_RESPONSE_ACTION_REMOVE" || message.moderation?.action === "remove");
|
|
2878
|
-
const isMessageDeleted = (message) => Boolean(message.deleted_at || message.type === "deleted" || message.deleted_for_me);
|
|
2879
|
-
const isMessageEdited = (message) => !!message.message_text_updated_at;
|
|
2880
|
-
const hasResizeObserver = typeof window !== "undefined" && "ResizeObserver" in window;
|
|
2881
|
-
function autoMiddlewareFor(p) {
|
|
2882
|
-
if (!String(p).startsWith("auto")) return null;
|
|
2883
|
-
const alignment = p === "auto-start" ? "start" : p === "auto-end" ? "end" : void 0;
|
|
2884
|
-
return autoPlacement({ alignment });
|
|
2885
|
-
}
|
|
2886
|
-
function toOffsetMw(opt) {
|
|
2887
|
-
if (opt == null) return null;
|
|
2888
|
-
if (Array.isArray(opt)) {
|
|
2889
|
-
const [crossAxis, mainAxis] = opt;
|
|
2890
|
-
return offset({ crossAxis, mainAxis });
|
|
2891
|
-
}
|
|
2892
|
-
if (typeof opt === "number") return offset(opt);
|
|
2893
|
-
return offset(opt);
|
|
2894
|
-
}
|
|
2895
|
-
function usePopoverPosition({
|
|
2896
|
-
allowFlip = true,
|
|
2897
|
-
allowShift = true,
|
|
2898
|
-
autoUpdateOptions,
|
|
2899
|
-
fitAvailableSpace = false,
|
|
2900
|
-
freeze = false,
|
|
2901
|
-
offset: offset2,
|
|
2902
|
-
placement = "bottom-start",
|
|
2903
|
-
shiftOptions
|
|
2904
|
-
}) {
|
|
2905
|
-
const autoMw = autoMiddlewareFor(placement);
|
|
2906
|
-
const offsetMiddleware = toOffsetMw(offset2);
|
|
2907
|
-
const isSidePlacement = placement.startsWith("left") || placement.startsWith("right");
|
|
2908
|
-
const mergedShiftOptions = shiftOptions ? { padding: 8, ...shiftOptions } : { padding: 8 };
|
|
2909
|
-
const middleware = [
|
|
2910
|
-
// offset first (mirrors common Popper setups)
|
|
2911
|
-
...offsetMiddleware ? [offsetMiddleware] : [],
|
|
2912
|
-
// choose between autoPlacement (Popper's "auto*") OR flip()
|
|
2913
|
-
// only allow flip when not explicitly 'left*' or 'right*'
|
|
2914
|
-
...autoMw ? [autoMw] : allowFlip && !isSidePlacement ? [flip()] : [],
|
|
2915
|
-
// viewport collision adjustments
|
|
2916
|
-
...allowShift ? [shift(mergedShiftOptions)] : [],
|
|
2917
|
-
// optional size constraining
|
|
2918
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
2919
|
-
...fitAvailableSpace ? [size({ apply: () => {
|
|
2920
|
-
} })] : []
|
|
2921
|
-
];
|
|
2922
|
-
const seedPlacement = String(placement).startsWith("auto") ? "bottom" : placement;
|
|
2923
|
-
return useFloating({
|
|
2924
|
-
middleware,
|
|
2925
|
-
placement: seedPlacement,
|
|
2926
|
-
strategy: "fixed",
|
|
2927
|
-
whileElementsMounted: freeze ? void 0 : (reference, floating, update) => autoUpdate(reference, floating, update, {
|
|
2928
|
-
ancestorResize: true,
|
|
2929
|
-
ancestorScroll: true,
|
|
2930
|
-
animationFrame: false,
|
|
2931
|
-
elementResize: hasResizeObserver,
|
|
2932
|
-
...autoUpdateOptions
|
|
2933
|
-
})
|
|
2934
|
-
});
|
|
2935
|
-
}
|
|
2936
|
-
const LegacyThreadContext = React.createContext({ legacyThread: void 0 });
|
|
2937
|
-
const useLegacyThreadContext = () => useContext(LegacyThreadContext);
|
|
2938
3009
|
const cooldownTimerStateSelector = (state) => ({
|
|
2939
3010
|
isCooldownActive: !!state.cooldownRemaining
|
|
2940
3011
|
});
|
|
@@ -3422,10 +3493,10 @@ const UnMemoizedChannel = (props) => {
|
|
|
3422
3493
|
if (channelsQueryState.queryInProgress === "reload" && LoadingIndicator) {
|
|
3423
3494
|
return /* @__PURE__ */ jsx(ChannelContainer, { children: /* @__PURE__ */ jsx(LoadingIndicator, {}) });
|
|
3424
3495
|
}
|
|
3425
|
-
if (channelsQueryState.error && LoadingErrorIndicator2) {
|
|
3496
|
+
if (channelsQueryState.error && !channel && LoadingErrorIndicator2) {
|
|
3426
3497
|
return /* @__PURE__ */ jsx(ChannelContainer, { children: /* @__PURE__ */ jsx(LoadingErrorIndicator2, { error: channelsQueryState.error }) });
|
|
3427
3498
|
}
|
|
3428
|
-
if (channelsQueryState.error) {
|
|
3499
|
+
if (channelsQueryState.error && !channel) {
|
|
3429
3500
|
return /* @__PURE__ */ jsx(ChannelContainer, {});
|
|
3430
3501
|
}
|
|
3431
3502
|
if (!channel?.cid) {
|
|
@@ -4104,7 +4175,7 @@ const ChannelInner = (props) => {
|
|
|
4104
4175
|
imageAttachmentSizeHandler: props.imageAttachmentSizeHandler || getImageAttachmentConfiguration,
|
|
4105
4176
|
mutes,
|
|
4106
4177
|
notifications: [],
|
|
4107
|
-
shouldGenerateVideoThumbnail: props.shouldGenerateVideoThumbnail
|
|
4178
|
+
shouldGenerateVideoThumbnail: props.shouldGenerateVideoThumbnail ?? true,
|
|
4108
4179
|
videoAttachmentSizeHandler: props.videoAttachmentSizeHandler || getVideoAttachmentConfiguration,
|
|
4109
4180
|
watcher_count: state.watcherCount
|
|
4110
4181
|
});
|
|
@@ -4182,7 +4253,31 @@ const UnreadCountBadge = ({
|
|
|
4182
4253
|
}
|
|
4183
4254
|
)
|
|
4184
4255
|
] });
|
|
4256
|
+
const DEFAULT_CHAT_VIEW_A11Y_CONTEXT_VALUE = {
|
|
4257
|
+
chatViewPanelIds: {
|
|
4258
|
+
channels: "str-chat__chat-view-panel-channels",
|
|
4259
|
+
threads: "str-chat__chat-view-panel-threads"
|
|
4260
|
+
},
|
|
4261
|
+
chatViewTabIds: {
|
|
4262
|
+
channels: "str-chat__chat-view-tab-channels",
|
|
4263
|
+
threads: "str-chat__chat-view-tab-threads"
|
|
4264
|
+
}
|
|
4265
|
+
};
|
|
4266
|
+
const createChatViewA11yContextValue = (chatViewId) => ({
|
|
4267
|
+
// Keep IDs unique per ChatView instance so ARIA references do not collide.
|
|
4268
|
+
chatViewPanelIds: {
|
|
4269
|
+
channels: `str-chat__chat-view-${chatViewId}-panel-channels`,
|
|
4270
|
+
threads: `str-chat__chat-view-${chatViewId}-panel-threads`
|
|
4271
|
+
},
|
|
4272
|
+
chatViewTabIds: {
|
|
4273
|
+
channels: `str-chat__chat-view-${chatViewId}-tab-channels`,
|
|
4274
|
+
threads: `str-chat__chat-view-${chatViewId}-tab-threads`
|
|
4275
|
+
}
|
|
4276
|
+
});
|
|
4185
4277
|
const ChatViewContext = createContext(void 0);
|
|
4278
|
+
const ChatViewA11yContext = createContext(
|
|
4279
|
+
DEFAULT_CHAT_VIEW_A11Y_CONTEXT_VALUE
|
|
4280
|
+
);
|
|
4186
4281
|
const useChatViewContext = () => {
|
|
4187
4282
|
const value = useContext(ChatViewContext);
|
|
4188
4283
|
if (!value) {
|
|
@@ -4193,16 +4288,33 @@ const useChatViewContext = () => {
|
|
|
4193
4288
|
}
|
|
4194
4289
|
return value;
|
|
4195
4290
|
};
|
|
4291
|
+
const useChatViewA11yContext = () => useContext(ChatViewA11yContext);
|
|
4196
4292
|
const ChatView = ({ children }) => {
|
|
4197
4293
|
const [activeChatView, setActiveChatView] = useState("channels");
|
|
4294
|
+
const chatViewId = useId().replace(/:/g, "");
|
|
4198
4295
|
const { theme } = useChatContext();
|
|
4296
|
+
const a11yValue = useMemo(
|
|
4297
|
+
() => createChatViewA11yContextValue(chatViewId),
|
|
4298
|
+
[chatViewId]
|
|
4299
|
+
);
|
|
4199
4300
|
const value = useMemo(() => ({ activeChatView, setActiveChatView }), [activeChatView]);
|
|
4200
|
-
return /* @__PURE__ */ jsx(ChatViewContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: clsx("str-chat", theme, "str-chat__chat-view"), children }) });
|
|
4301
|
+
return /* @__PURE__ */ jsx(ChatViewA11yContext.Provider, { value: a11yValue, children: /* @__PURE__ */ jsx(ChatViewContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: clsx("str-chat", theme, "str-chat__chat-view"), children }) }) });
|
|
4201
4302
|
};
|
|
4202
4303
|
const ChannelsView = ({ children }) => {
|
|
4203
4304
|
const { activeChatView } = useChatViewContext();
|
|
4204
|
-
|
|
4205
|
-
|
|
4305
|
+
const { chatViewPanelIds, chatViewTabIds } = useChatViewA11yContext();
|
|
4306
|
+
const isActive = activeChatView === "channels";
|
|
4307
|
+
if (!isActive) return null;
|
|
4308
|
+
return /* @__PURE__ */ jsx(
|
|
4309
|
+
"div",
|
|
4310
|
+
{
|
|
4311
|
+
"aria-labelledby": chatViewTabIds.channels,
|
|
4312
|
+
className: "str-chat__chat-view__channels",
|
|
4313
|
+
id: chatViewPanelIds.channels,
|
|
4314
|
+
role: "tabpanel",
|
|
4315
|
+
children
|
|
4316
|
+
}
|
|
4317
|
+
);
|
|
4206
4318
|
};
|
|
4207
4319
|
const ThreadsViewContext = createContext({
|
|
4208
4320
|
activeThread: void 0,
|
|
@@ -4211,10 +4323,21 @@ const ThreadsViewContext = createContext({
|
|
|
4211
4323
|
const useThreadsViewContext = () => useContext(ThreadsViewContext);
|
|
4212
4324
|
const ThreadsView = ({ children }) => {
|
|
4213
4325
|
const { activeChatView } = useChatViewContext();
|
|
4326
|
+
const { chatViewPanelIds, chatViewTabIds } = useChatViewA11yContext();
|
|
4214
4327
|
const [activeThread, setActiveThread] = useState(void 0);
|
|
4215
4328
|
const value = useMemo(() => ({ activeThread, setActiveThread }), [activeThread]);
|
|
4216
|
-
|
|
4217
|
-
|
|
4329
|
+
const isActive = activeChatView === "threads";
|
|
4330
|
+
if (!isActive) return null;
|
|
4331
|
+
return /* @__PURE__ */ jsx(ThreadsViewContext.Provider, { value, children: /* @__PURE__ */ jsx(
|
|
4332
|
+
"div",
|
|
4333
|
+
{
|
|
4334
|
+
"aria-labelledby": chatViewTabIds.threads,
|
|
4335
|
+
className: "str-chat__chat-view__threads",
|
|
4336
|
+
id: chatViewPanelIds.threads,
|
|
4337
|
+
role: "tabpanel",
|
|
4338
|
+
children
|
|
4339
|
+
}
|
|
4340
|
+
) });
|
|
4218
4341
|
};
|
|
4219
4342
|
const useActiveThread = ({ activeThread }) => {
|
|
4220
4343
|
useEffect(() => {
|
|
@@ -4310,17 +4433,22 @@ const ChatViewChannelsSelectorButton = ({
|
|
|
4310
4433
|
iconOnly = true
|
|
4311
4434
|
}) => {
|
|
4312
4435
|
const { activeChatView, setActiveChatView } = useChatViewContext();
|
|
4436
|
+
const { chatViewPanelIds, chatViewTabIds } = useChatViewA11yContext();
|
|
4313
4437
|
const { t } = useTranslationContext();
|
|
4314
4438
|
const isActive = activeChatView === "channels";
|
|
4315
4439
|
return /* @__PURE__ */ jsx(
|
|
4316
4440
|
ChatViewSelectorButton,
|
|
4317
4441
|
{
|
|
4318
4442
|
ActiveIcon: IconMessageBubbleFill,
|
|
4443
|
+
"aria-controls": chatViewPanelIds.channels,
|
|
4319
4444
|
"aria-selected": isActive,
|
|
4320
4445
|
Icon: IconMessageBubble,
|
|
4321
4446
|
iconOnly,
|
|
4447
|
+
id: chatViewTabIds.channels,
|
|
4322
4448
|
isActive,
|
|
4449
|
+
onClick: () => setActiveChatView("channels"),
|
|
4323
4450
|
onPointerDown: () => setActiveChatView("channels"),
|
|
4451
|
+
tabIndex: 0,
|
|
4324
4452
|
text: t("Channels")
|
|
4325
4453
|
}
|
|
4326
4454
|
);
|
|
@@ -4336,17 +4464,22 @@ const ChatViewThreadsSelectorButton = ({
|
|
|
4336
4464
|
unreadThreadCount: 0
|
|
4337
4465
|
};
|
|
4338
4466
|
const { activeChatView, setActiveChatView } = useChatViewContext();
|
|
4467
|
+
const { chatViewPanelIds, chatViewTabIds } = useChatViewA11yContext();
|
|
4339
4468
|
const { t } = useTranslationContext();
|
|
4340
4469
|
const isActive = activeChatView === "threads";
|
|
4341
4470
|
return /* @__PURE__ */ jsx(
|
|
4342
4471
|
ChatViewSelectorButton,
|
|
4343
4472
|
{
|
|
4344
4473
|
ActiveIcon: IconThreadFill,
|
|
4474
|
+
"aria-controls": chatViewPanelIds.threads,
|
|
4345
4475
|
"aria-selected": isActive,
|
|
4346
4476
|
Icon: IconThread,
|
|
4347
4477
|
iconOnly,
|
|
4478
|
+
id: chatViewTabIds.threads,
|
|
4348
4479
|
isActive,
|
|
4480
|
+
onClick: () => setActiveChatView("threads"),
|
|
4349
4481
|
onPointerDown: () => setActiveChatView("threads"),
|
|
4482
|
+
tabIndex: 0,
|
|
4350
4483
|
text: t("Threads"),
|
|
4351
4484
|
children: /* @__PURE__ */ jsx(UnreadCountBadge, { count: unreadThreadCount, position: "top-right", children: isActive ? /* @__PURE__ */ jsx(IconThreadFill, {}) : /* @__PURE__ */ jsx(IconThread, {}) })
|
|
4352
4485
|
}
|
|
@@ -4365,7 +4498,18 @@ const defaultChatViewSelectorItemSet = [
|
|
|
4365
4498
|
const ChatViewSelector = ({
|
|
4366
4499
|
iconOnly = true,
|
|
4367
4500
|
itemSet = defaultChatViewSelectorItemSet
|
|
4368
|
-
}) =>
|
|
4501
|
+
}) => {
|
|
4502
|
+
const { t } = useTranslationContext();
|
|
4503
|
+
return /* @__PURE__ */ jsx(
|
|
4504
|
+
"div",
|
|
4505
|
+
{
|
|
4506
|
+
"aria-label": t("aria/Chat view tabs"),
|
|
4507
|
+
className: "str-chat__chat-view__selector",
|
|
4508
|
+
role: "tablist",
|
|
4509
|
+
children: itemSet.map(({ Component, type }) => /* @__PURE__ */ jsx(Component, { iconOnly }, type))
|
|
4510
|
+
}
|
|
4511
|
+
);
|
|
4512
|
+
};
|
|
4369
4513
|
ChatView.Channels = ChannelsView;
|
|
4370
4514
|
ChatView.Threads = ThreadsView;
|
|
4371
4515
|
ChatView.ThreadAdapter = ThreadAdapter;
|
|
@@ -4491,177 +4635,112 @@ const useNotificationApi = () => {
|
|
|
4491
4635
|
startNotificationTimeout
|
|
4492
4636
|
};
|
|
4493
4637
|
};
|
|
4494
|
-
const AudioPlayerContext = React.createContext({
|
|
4495
|
-
audioPlayers: null
|
|
4496
|
-
});
|
|
4497
|
-
const WithAudioPlayback = ({
|
|
4498
|
-
allowConcurrentPlayback,
|
|
4499
|
-
children
|
|
4500
|
-
}) => {
|
|
4501
|
-
const [audioPlayers] = useState(() => new AudioPlayerPool({ allowConcurrentPlayback }));
|
|
4502
|
-
useEffect(
|
|
4503
|
-
() => () => {
|
|
4504
|
-
audioPlayers.clear();
|
|
4505
|
-
},
|
|
4506
|
-
[audioPlayers]
|
|
4507
|
-
);
|
|
4508
|
-
return /* @__PURE__ */ jsx(AudioPlayerContext.Provider, { value: { audioPlayers }, children });
|
|
4509
|
-
};
|
|
4510
|
-
const makeAudioPlayerId = ({ requester, src }) => `${requester ?? "requester-unknown"}:${src}`;
|
|
4511
|
-
const useAudioPlayer = ({
|
|
4512
|
-
durationSeconds,
|
|
4513
|
-
fileSize,
|
|
4514
|
-
mimeType,
|
|
4515
|
-
playbackRates,
|
|
4516
|
-
plugins,
|
|
4517
|
-
requester = "",
|
|
4518
|
-
src,
|
|
4519
|
-
title,
|
|
4520
|
-
waveformData
|
|
4521
|
-
}) => {
|
|
4522
|
-
const { addNotification } = useNotificationApi();
|
|
4523
|
-
const panel = useNotificationTarget();
|
|
4524
|
-
const { t } = useTranslationContext();
|
|
4525
|
-
const { audioPlayers } = useContext(AudioPlayerContext);
|
|
4526
|
-
const audioPlayer = src && audioPlayers ? audioPlayers.getOrAdd({
|
|
4527
|
-
durationSeconds,
|
|
4528
|
-
fileSize,
|
|
4529
|
-
id: makeAudioPlayerId({ requester, src }),
|
|
4530
|
-
mimeType,
|
|
4531
|
-
playbackRates,
|
|
4532
|
-
plugins,
|
|
4533
|
-
src,
|
|
4534
|
-
title,
|
|
4535
|
-
waveformData
|
|
4536
|
-
}) : void 0;
|
|
4537
|
-
useEffect(() => {
|
|
4538
|
-
if (!audioPlayer) return;
|
|
4539
|
-
const notificationsPlugin = audioPlayerNotificationsPluginFactory({
|
|
4540
|
-
addNotification,
|
|
4541
|
-
panel,
|
|
4542
|
-
t
|
|
4543
|
-
});
|
|
4544
|
-
audioPlayer.setPlugins((currentPlugins) => [
|
|
4545
|
-
...currentPlugins.filter((plugin) => plugin.id !== notificationsPlugin.id),
|
|
4546
|
-
notificationsPlugin
|
|
4547
|
-
]);
|
|
4548
|
-
}, [addNotification, audioPlayer, panel, t]);
|
|
4549
|
-
return audioPlayer;
|
|
4550
|
-
};
|
|
4551
|
-
const activeAudioPlayerSelector = ({ activeAudioPlayer }) => ({
|
|
4552
|
-
activeAudioPlayer
|
|
4553
|
-
});
|
|
4554
|
-
const useActiveAudioPlayer = () => {
|
|
4555
|
-
const { audioPlayers } = useContext(AudioPlayerContext);
|
|
4556
|
-
const { activeAudioPlayer } = useStateStore(audioPlayers?.state, activeAudioPlayerSelector) ?? {};
|
|
4557
|
-
return activeAudioPlayer;
|
|
4558
|
-
};
|
|
4559
4638
|
export {
|
|
4560
|
-
|
|
4561
|
-
|
|
4639
|
+
IconGiphy as $,
|
|
4640
|
+
IconNoSign as A,
|
|
4562
4641
|
Button as B,
|
|
4563
4642
|
ComponentContext as C,
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4643
|
+
isMessageDeleted as D,
|
|
4644
|
+
isMessageErrorRetryable as E,
|
|
4645
|
+
ACTIONS_NOT_WORKING_IN_THREAD as F,
|
|
4646
|
+
useNotificationApi as G,
|
|
4647
|
+
IconArrowUpRight as H,
|
|
4648
|
+
IconPauseFill as I,
|
|
4649
|
+
IconPin as J,
|
|
4650
|
+
mapToUserNameOrId as K,
|
|
4572
4651
|
LocalizedFormat as L,
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4652
|
+
IconClock as M,
|
|
4653
|
+
IconCheckmark1Small as N,
|
|
4654
|
+
IconChecks as O,
|
|
4655
|
+
getReadByTooltipText as P,
|
|
4656
|
+
messageHasAttachments as Q,
|
|
4657
|
+
messageTextHasEmojisOnly as R,
|
|
4658
|
+
isDate as S,
|
|
4659
|
+
getDateString as T,
|
|
4660
|
+
IconTranslate as U,
|
|
4661
|
+
IconDownload as V,
|
|
4662
|
+
useAudioPlayer as W,
|
|
4663
|
+
IconImage as X,
|
|
4664
|
+
IconArrowDownCircle as Y,
|
|
4665
|
+
IconRetry as Z,
|
|
4666
|
+
IconLink as _,
|
|
4588
4667
|
useMessageComposerController as a,
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4668
|
+
countEmojis as a$,
|
|
4669
|
+
IconLocation as a0,
|
|
4670
|
+
IconUnsupportedAttachment as a1,
|
|
4671
|
+
IconEyeFill as a2,
|
|
4672
|
+
useMessageComposerContext as a3,
|
|
4673
|
+
useIsCooldownActive as a4,
|
|
4674
|
+
IconXmarkSmall as a5,
|
|
4675
|
+
IconPoll as a6,
|
|
4676
|
+
IconFile as a7,
|
|
4677
|
+
IconVideo as a8,
|
|
4678
|
+
IconCamera as a9,
|
|
4679
|
+
IconUpload as aA,
|
|
4680
|
+
MessageComposerContextProvider as aB,
|
|
4681
|
+
useTypingContext as aC,
|
|
4682
|
+
useChatViewContext as aD,
|
|
4683
|
+
MESSAGE_ACTIONS as aE,
|
|
4684
|
+
LegacyThreadContext as aF,
|
|
4685
|
+
IconEmojiAdd as aG,
|
|
4686
|
+
IconReply as aH,
|
|
4687
|
+
IconEmoji as aI,
|
|
4688
|
+
IconMore as aJ,
|
|
4689
|
+
IconUserCheck as aK,
|
|
4690
|
+
IconBookmarkRemove as aL,
|
|
4691
|
+
IconBellOff as aM,
|
|
4692
|
+
IconNotification as aN,
|
|
4693
|
+
IconEdit as aO,
|
|
4694
|
+
IconCopy as aP,
|
|
4695
|
+
IconUnpin as aQ,
|
|
4696
|
+
IconQuote as aR,
|
|
4697
|
+
IconThread as aS,
|
|
4698
|
+
areMessageUIPropsEqual as aT,
|
|
4699
|
+
isDateSeparatorMessage as aU,
|
|
4700
|
+
isMessageBlocked as aV,
|
|
4701
|
+
messageHasSingleAttachment as aW,
|
|
4702
|
+
messageHasGiphyAttachment as aX,
|
|
4703
|
+
messageHasReactions as aY,
|
|
4704
|
+
messageHasQuotedMessage as aZ,
|
|
4705
|
+
isMessageEdited as a_,
|
|
4706
|
+
IconVoice as aa,
|
|
4707
|
+
IconBookmark as ab,
|
|
4708
|
+
IconBell as ac,
|
|
4709
|
+
IconChevronDown as ad,
|
|
4710
|
+
IconMinus as ae,
|
|
4711
|
+
IconPlusSmall as af,
|
|
4712
|
+
IconCheckmark as ag,
|
|
4713
|
+
DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD as ah,
|
|
4714
|
+
IconTrophy as ai,
|
|
4715
|
+
IconReorder as aj,
|
|
4716
|
+
IconMinusCircle as ak,
|
|
4717
|
+
IconSend as al,
|
|
4718
|
+
IconAudio as am,
|
|
4719
|
+
IconUserAdd as an,
|
|
4720
|
+
IconMute as ao,
|
|
4721
|
+
IconFlag as ap,
|
|
4722
|
+
IconUserRemove as aq,
|
|
4723
|
+
IconAttachment as ar,
|
|
4724
|
+
IconCommand as as,
|
|
4725
|
+
CHANNEL_CONTAINER_ID as at,
|
|
4726
|
+
IconPlus as au,
|
|
4727
|
+
IconExclamationTriangleFill as av,
|
|
4728
|
+
IconMicrophoneSolid as aw,
|
|
4729
|
+
IconVideoFill as ax,
|
|
4730
|
+
IconBolt as ay,
|
|
4731
|
+
IconDelete as az,
|
|
4653
4732
|
useChannelActionContext as b,
|
|
4654
4733
|
getNotificationTargetTag as b$,
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4734
|
+
areMessagePropsEqual as b0,
|
|
4735
|
+
getMessageActions as b1,
|
|
4736
|
+
processMessages as b2,
|
|
4737
|
+
insertIntro as b3,
|
|
4738
|
+
getGroupStyles as b4,
|
|
4739
|
+
getLastReceived as b5,
|
|
4740
|
+
IconArrowUp as b6,
|
|
4741
|
+
isIntroMessage as b7,
|
|
4742
|
+
isLocalMessage as b8,
|
|
4743
|
+
getIsFirstUnreadMessage as b9,
|
|
4665
4744
|
useEditMessageHandler as bA,
|
|
4666
4745
|
useMentionsHandlers as bB,
|
|
4667
4746
|
Channel as bC,
|
|
@@ -4689,23 +4768,23 @@ export {
|
|
|
4689
4768
|
isNotificationTargetPanel as bY,
|
|
4690
4769
|
getNotificationTargetPanel as bZ,
|
|
4691
4770
|
getNotificationTargetPanels as b_,
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4771
|
+
IconArrowDown as ba,
|
|
4772
|
+
DEFAULT_NEXT_CHANNEL_PAGE_SIZE as bb,
|
|
4773
|
+
EmptyStateIndicator as bc,
|
|
4774
|
+
useNotificationTarget as bd,
|
|
4775
|
+
getChannel as be,
|
|
4776
|
+
IconSearch as bf,
|
|
4777
|
+
IconXCircle as bg,
|
|
4778
|
+
useChannelListContext as bh,
|
|
4779
|
+
DEFAULT_JUMP_TO_PAGE_SIZE as bi,
|
|
4780
|
+
ChannelListContextProvider as bj,
|
|
4781
|
+
IconLeave as bk,
|
|
4782
|
+
IconArchive as bl,
|
|
4783
|
+
IconExclamationCircleFill as bm,
|
|
4784
|
+
useThreadsViewContext as bn,
|
|
4785
|
+
IconMessageBubbles as bo,
|
|
4786
|
+
IconRefresh as bp,
|
|
4787
|
+
hasSystemNotificationTag as bq,
|
|
4709
4788
|
defaultDateTimeParser as br,
|
|
4710
4789
|
isLanguageSupported as bs,
|
|
4711
4790
|
ChatProvider as bt,
|
|
@@ -4736,25 +4815,25 @@ export {
|
|
|
4736
4815
|
useChannelStateContext as d,
|
|
4737
4816
|
useChatContext as e,
|
|
4738
4817
|
isNotificationForPanel as f,
|
|
4739
|
-
|
|
4740
|
-
|
|
4818
|
+
IconPlayFill as g,
|
|
4819
|
+
getDefaultExportFromCjs as h,
|
|
4741
4820
|
isMessageBounced as i,
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4821
|
+
defaultTranslatorFunction as j,
|
|
4822
|
+
calendar as k,
|
|
4823
|
+
IconLoading as l,
|
|
4824
|
+
useComponentContext as m,
|
|
4825
|
+
isNetworkSendFailure as n,
|
|
4826
|
+
isUserMuted as o,
|
|
4748
4827
|
predefinedFormatters as p,
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4828
|
+
useThreadContext as q,
|
|
4829
|
+
usePopoverPosition as r,
|
|
4830
|
+
IconXmark as s,
|
|
4831
|
+
IconUser as t,
|
|
4753
4832
|
useStateStore as u,
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4833
|
+
IconExclamationMarkFill as v,
|
|
4834
|
+
IconChevronRight as w,
|
|
4835
|
+
IconChevronLeft as x,
|
|
4836
|
+
IconArrowLeft as y,
|
|
4837
|
+
IconExclamationMark as z
|
|
4759
4838
|
};
|
|
4760
|
-
//# sourceMappingURL=
|
|
4839
|
+
//# sourceMappingURL=useNotificationApi.f91ae46b.mjs.map
|