stream-chat-react 14.0.0-beta.7 → 14.0.0-beta.8
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/{WithAudioPlayback.83ba0e35.js → WithAudioPlayback.58b0b39b.js} +4 -2
- package/dist/cjs/WithAudioPlayback.58b0b39b.js.map +1 -0
- package/dist/cjs/emojis.js +1 -1
- package/dist/cjs/index.js +1732 -1588
- package/dist/cjs/index.js.map +1 -1
- package/dist/css/index.css +1346 -1115
- package/dist/css/index.css.map +1 -1
- package/dist/es/{WithAudioPlayback.21b7f35a.mjs → WithAudioPlayback.2ffdc4c5.mjs} +169 -167
- package/dist/es/WithAudioPlayback.2ffdc4c5.mjs.map +1 -0
- package/dist/es/emojis.mjs +1 -1
- package/dist/es/index.mjs +1783 -1639
- package/dist/es/index.mjs.map +1 -1
- package/dist/types/components/ChannelListItem/ChannelListItemActionButtons.defaults.d.ts.map +1 -1
- package/dist/types/components/ChannelListItem/utils.d.ts.map +1 -1
- package/dist/types/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts +3 -1
- package/dist/types/components/Dialog/components/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/Dialog/service/DialogPortal.d.ts.map +1 -1
- package/dist/types/components/Form/NumericInput.d.ts.map +1 -1
- package/dist/types/components/Form/TextInput.d.ts +15 -8
- package/dist/types/components/Form/TextInput.d.ts.map +1 -1
- package/dist/types/components/Form/index.d.ts +1 -0
- package/dist/types/components/Form/index.d.ts.map +1 -1
- package/dist/types/components/Message/MessageUI.d.ts.map +1 -1
- package/dist/types/components/Message/utils.d.ts +1 -0
- package/dist/types/components/Message/utils.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.d.ts.map +1 -1
- package/dist/types/components/MessageActions/MessageActions.defaults.d.ts.map +1 -1
- package/dist/types/components/MessageActions/hooks/useBaseMessageActionSetFilter.d.ts +1 -1
- package/dist/types/components/MessageActions/hooks/useBaseMessageActionSetFilter.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/MessageList/useFloatingDateSeparatorMessageList.d.ts +2 -2
- package/dist/types/components/MessageList/hooks/MessageList/useFloatingDateSeparatorMessageList.d.ts.map +1 -1
- package/dist/types/components/MessageList/hooks/VirtualizedMessageList/useFloatingDateSeparator.d.ts.map +1 -1
- package/dist/types/components/Poll/PollCreationDialog/OptionFieldSet.d.ts.map +1 -1
- package/dist/types/components/Reactions/ReactionSelector.d.ts +2 -0
- package/dist/types/components/Reactions/ReactionSelector.d.ts.map +1 -1
- package/dist/types/components/SummarizedMessagePreview/hooks/useLatestMessagePreview.d.ts.map +1 -1
- package/dist/types/components/Tooltip/Tooltip.d.ts +4 -2
- package/dist/types/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/WithAudioPlayback.83ba0e35.js.map +0 -1
- package/dist/es/WithAudioPlayback.21b7f35a.mjs.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const clsx = require("clsx");
|
|
|
5
5
|
const nanoid = require("nanoid");
|
|
6
6
|
const React = require("react");
|
|
7
7
|
const audioProcessing = require("./audioProcessing.56e5db9d.js");
|
|
8
|
-
const WithAudioPlayback = require("./WithAudioPlayback.
|
|
8
|
+
const WithAudioPlayback = require("./WithAudioPlayback.58b0b39b.js");
|
|
9
9
|
const streamChat = require("stream-chat");
|
|
10
10
|
const throttle = require("lodash.throttle");
|
|
11
11
|
const linkify = require("linkifyjs");
|
|
@@ -308,6 +308,10 @@ const DialogPortalDestination = () => {
|
|
|
308
308
|
if (!destinationRoot || !dialogManager) return;
|
|
309
309
|
const handleDocumentClick = (event) => {
|
|
310
310
|
const target = event.target;
|
|
311
|
+
const clickedOverlay = target.closest?.(
|
|
312
|
+
"[data-str-chat__portal-id]"
|
|
313
|
+
);
|
|
314
|
+
if (clickedOverlay && clickedOverlay !== destinationRoot) return;
|
|
311
315
|
if (target !== destinationRoot && destinationRoot.contains(target)) return;
|
|
312
316
|
setTimeout(() => {
|
|
313
317
|
Object.values(dialogManager.state.getLatestValue().dialogsById).forEach(
|
|
@@ -9859,6 +9863,7 @@ const ContextMenuContext = React.createContext(
|
|
|
9859
9863
|
);
|
|
9860
9864
|
const useContextMenuContext = () => React.useContext(ContextMenuContext);
|
|
9861
9865
|
function ContextMenuContent({
|
|
9866
|
+
anchorReferenceElement,
|
|
9862
9867
|
backLabel = "Back",
|
|
9863
9868
|
children,
|
|
9864
9869
|
className,
|
|
@@ -9922,31 +9927,37 @@ function ContextMenuContent({
|
|
|
9922
9927
|
if (!transitionDirection) return;
|
|
9923
9928
|
setMenuBodyAnimationKey((value) => value + 1);
|
|
9924
9929
|
}, [transitionDirection, menuStack.length]);
|
|
9925
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9926
|
-
|
|
9930
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9931
|
+
ContextMenuContext.Provider,
|
|
9927
9932
|
{
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9933
|
+
value: { anchorReferenceElement, closeMenu, openSubmenu, returnToParentMenu },
|
|
9934
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9935
|
+
ContextMenuRoot,
|
|
9936
|
+
{
|
|
9937
|
+
className: clsx(className, activeMenu.menuClassName),
|
|
9938
|
+
"data-str-chat-enable-animations": enableAnimations,
|
|
9939
|
+
...props,
|
|
9940
|
+
children: [
|
|
9941
|
+
activeMenu.Header ? /* @__PURE__ */ jsxRuntime.jsx(activeMenu.Header, {}) : menuStack.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuBackButton, { onClick: returnToParentMenu, children: [
|
|
9942
|
+
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {}),
|
|
9943
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: backLabel })
|
|
9944
|
+
] }) }) : null,
|
|
9945
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9946
|
+
ContextMenuBody,
|
|
9947
|
+
{
|
|
9948
|
+
className: clsx({
|
|
9949
|
+
"str-chat__context-menu__body--submenu-backward": transitionDirection === "backward",
|
|
9950
|
+
"str-chat__context-menu__body--submenu-forward": transitionDirection === "forward"
|
|
9951
|
+
}),
|
|
9952
|
+
children: activeMenu.Submenu ? /* @__PURE__ */ jsxRuntime.jsx(activeMenu.Submenu, {}) : /* @__PURE__ */ jsxRuntime.jsx(ActiveMenuItemsWrapper, { children: typeof children !== "undefined" ? children : activeMenu.items?.map((Item2, index) => /* @__PURE__ */ jsxRuntime.jsx(Item2, {}, `context-menu-item-${index}`)) })
|
|
9953
|
+
},
|
|
9954
|
+
`context-menu-body-${menuStack.length}-${menuBodyAnimationKey}`
|
|
9955
|
+
)
|
|
9956
|
+
]
|
|
9957
|
+
}
|
|
9958
|
+
)
|
|
9948
9959
|
}
|
|
9949
|
-
)
|
|
9960
|
+
);
|
|
9950
9961
|
}
|
|
9951
9962
|
const ContextMenu = (props) => {
|
|
9952
9963
|
const { ContextMenuContent: ContextMenuContentComponent = ContextMenuContent } = WithAudioPlayback.useComponentContext();
|
|
@@ -10019,6 +10030,7 @@ const ContextMenu = (props) => {
|
|
|
10019
10030
|
const content = /* @__PURE__ */ React.createElement(
|
|
10020
10031
|
ContextMenuContentComponent,
|
|
10021
10032
|
{
|
|
10033
|
+
anchorReferenceElement: isAnchored ? referenceElement : void 0,
|
|
10022
10034
|
...menuProps,
|
|
10023
10035
|
key: `context-menu-content-${contentResetToken}`,
|
|
10024
10036
|
onMenuLevelChange: handleMenuLevelChange,
|
|
@@ -10360,6 +10372,7 @@ const MessageBlocked = () => {
|
|
|
10360
10372
|
const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
10361
10373
|
const { initialMessage: isInitialMessage, message } = useMessageContext();
|
|
10362
10374
|
const { channelConfig } = WithAudioPlayback.useChannelStateContext();
|
|
10375
|
+
const messageIsDeleted = WithAudioPlayback.isMessageDeleted(message);
|
|
10363
10376
|
const {
|
|
10364
10377
|
canBlockUser,
|
|
10365
10378
|
canDelete,
|
|
@@ -10387,9 +10400,9 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10387
10400
|
if (WithAudioPlayback.ACTIONS_NOT_WORKING_IN_THREAD.includes(type) && isMessageThreadReply)
|
|
10388
10401
|
return false;
|
|
10389
10402
|
if (message.error) {
|
|
10390
|
-
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" && (isBounced && canEdit || hasNetworkSendFailure) || type === "delete" && (isBounced && canDelete || hasNetworkSendFailure);
|
|
10403
|
+
return type === "resendMessage" && canSendMessage && (allowRetry || isBounced) || type === "edit" && (isBounced && canEdit || hasNetworkSendFailure) || type === "delete" && !messageIsDeleted && (isBounced && canDelete || hasNetworkSendFailure);
|
|
10391
10404
|
}
|
|
10392
|
-
if (type === "resendMessage" || type === "blockUser" && !canBlockUser || type === "copyMessageText" && !message.text || type === "delete" && !canDelete || type === "edit" && !canEdit || type === "flag" && !canFlag || type === "markUnread" && !canMarkUnread || type === "mute" && !canMute || type === "quote" && !canQuote || type === "react" && !canReact || type === "reply" && !canReply || type === "remindMe" && !channelConfig?.["user_message_reminders"] || type === "saveForLater" && !channelConfig?.["user_message_reminders"])
|
|
10405
|
+
if (type === "resendMessage" || type === "blockUser" && !canBlockUser || type === "copyMessageText" && !message.text || type === "delete" && (!canDelete || messageIsDeleted) || type === "edit" && !canEdit || type === "flag" && !canFlag || type === "markUnread" && !canMarkUnread || type === "mute" && !canMute || type === "quote" && !canQuote || type === "react" && !canReact || type === "reply" && !canReply || type === "remindMe" && !channelConfig?.["user_message_reminders"] || type === "saveForLater" && !channelConfig?.["user_message_reminders"])
|
|
10393
10406
|
return false;
|
|
10394
10407
|
return true;
|
|
10395
10408
|
});
|
|
@@ -10408,6 +10421,7 @@ const useBaseMessageActionSetFilter = (messageActionSet, disable = false) => {
|
|
|
10408
10421
|
channelConfig,
|
|
10409
10422
|
isBounced,
|
|
10410
10423
|
isInitialMessage,
|
|
10424
|
+
messageIsDeleted,
|
|
10411
10425
|
isMessageThreadReply,
|
|
10412
10426
|
message.error,
|
|
10413
10427
|
message.status,
|
|
@@ -10539,9 +10553,10 @@ const PinIndicator = ({ message }) => {
|
|
|
10539
10553
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
|
|
10540
10554
|
] }) });
|
|
10541
10555
|
};
|
|
10542
|
-
const Tooltip = ({ children, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__tooltip", ...rest, children });
|
|
10556
|
+
const Tooltip = ({ children, className, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("str-chat__tooltip", className), ...rest, children });
|
|
10543
10557
|
const PopperTooltip = ({
|
|
10544
10558
|
children,
|
|
10559
|
+
className,
|
|
10545
10560
|
offset = [0, 10],
|
|
10546
10561
|
placement = "top",
|
|
10547
10562
|
referenceElement,
|
|
@@ -10568,7 +10583,7 @@ const PopperTooltip = ({
|
|
|
10568
10583
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10569
10584
|
"div",
|
|
10570
10585
|
{
|
|
10571
|
-
className: "str-chat__tooltip",
|
|
10586
|
+
className: clsx("str-chat__tooltip", className),
|
|
10572
10587
|
"data-placement": resolvedPlacement,
|
|
10573
10588
|
ref: setPopperElement,
|
|
10574
10589
|
style: { left: x ?? 0, position: strategy, top: y ?? 0 },
|
|
@@ -14181,8 +14196,9 @@ const NumericInput = React.forwardRef(
|
|
|
14181
14196
|
),
|
|
14182
14197
|
disabled: disabled || atMin,
|
|
14183
14198
|
onClick: handleDecrement,
|
|
14199
|
+
size: "xs",
|
|
14184
14200
|
variant: "secondary",
|
|
14185
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14201
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMinus, { className: "str-chat__form-numeric-input__stepper-icon" })
|
|
14186
14202
|
}
|
|
14187
14203
|
),
|
|
14188
14204
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -14211,7 +14227,7 @@ const NumericInput = React.forwardRef(
|
|
|
14211
14227
|
),
|
|
14212
14228
|
disabled: disabled || atMax,
|
|
14213
14229
|
onClick: handleIncrement,
|
|
14214
|
-
size: "
|
|
14230
|
+
size: "xs",
|
|
14215
14231
|
variant: "secondary",
|
|
14216
14232
|
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconPlusSmall, { className: "str-chat__form-numeric-input__stepper-icon" })
|
|
14217
14233
|
}
|
|
@@ -14222,12 +14238,72 @@ const NumericInput = React.forwardRef(
|
|
|
14222
14238
|
);
|
|
14223
14239
|
}
|
|
14224
14240
|
);
|
|
14241
|
+
const TextInputIconMessageLine = ({ icon, text: text2 }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
14242
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "str-chat__form-text-input__message-icon", children: icon }),
|
|
14243
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__form-text-input__message-text", children: text2 })
|
|
14244
|
+
] });
|
|
14245
|
+
const TextInputFieldMessage = (props) => {
|
|
14246
|
+
if (props.kind === "neutral") {
|
|
14247
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14248
|
+
"div",
|
|
14249
|
+
{
|
|
14250
|
+
className: clsx(
|
|
14251
|
+
"str-chat__form-text-input__message",
|
|
14252
|
+
props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"
|
|
14253
|
+
),
|
|
14254
|
+
id: props.id,
|
|
14255
|
+
children: props.text
|
|
14256
|
+
}
|
|
14257
|
+
);
|
|
14258
|
+
} else if (props.kind === "success") {
|
|
14259
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14260
|
+
"div",
|
|
14261
|
+
{
|
|
14262
|
+
className: clsx(
|
|
14263
|
+
"str-chat__form-text-input__message",
|
|
14264
|
+
"str-chat__form-text-input__message--success",
|
|
14265
|
+
props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"
|
|
14266
|
+
),
|
|
14267
|
+
id: props.id,
|
|
14268
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14269
|
+
TextInputIconMessageLine,
|
|
14270
|
+
{
|
|
14271
|
+
icon: props.successMessageIcon ?? /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconCheckmark, {}),
|
|
14272
|
+
text: props.text
|
|
14273
|
+
}
|
|
14274
|
+
)
|
|
14275
|
+
}
|
|
14276
|
+
);
|
|
14277
|
+
} else if (props.kind === "error") {
|
|
14278
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14279
|
+
"div",
|
|
14280
|
+
{
|
|
14281
|
+
className: clsx(
|
|
14282
|
+
"str-chat__form-text-input__message",
|
|
14283
|
+
"str-chat__form-field-error",
|
|
14284
|
+
props.insidePlacement && "str-chat__form-text-input__message--field-message-inside"
|
|
14285
|
+
),
|
|
14286
|
+
id: props.id,
|
|
14287
|
+
role: "alert",
|
|
14288
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14289
|
+
TextInputIconMessageLine,
|
|
14290
|
+
{
|
|
14291
|
+
icon: props.errorMessageIcon ?? /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconExclamationMark, {}),
|
|
14292
|
+
text: props.text
|
|
14293
|
+
}
|
|
14294
|
+
)
|
|
14295
|
+
}
|
|
14296
|
+
);
|
|
14297
|
+
}
|
|
14298
|
+
return null;
|
|
14299
|
+
};
|
|
14225
14300
|
const TextInput = React.forwardRef(function TextInput2({
|
|
14226
14301
|
className,
|
|
14227
14302
|
disabled,
|
|
14228
14303
|
error = false,
|
|
14229
14304
|
errorMessage,
|
|
14230
14305
|
errorMessageIcon,
|
|
14306
|
+
fieldMessagePlacement = "outside",
|
|
14231
14307
|
id: idProp,
|
|
14232
14308
|
label,
|
|
14233
14309
|
leading,
|
|
@@ -14239,71 +14315,86 @@ const TextInput = React.forwardRef(function TextInput2({
|
|
|
14239
14315
|
variant = "outline",
|
|
14240
14316
|
...inputProps
|
|
14241
14317
|
}, ref) {
|
|
14242
|
-
const
|
|
14243
|
-
const id = idProp ??
|
|
14244
|
-
const
|
|
14245
|
-
const
|
|
14246
|
-
const
|
|
14247
|
-
const
|
|
14248
|
-
const
|
|
14249
|
-
const
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14255
|
-
|
|
14318
|
+
const autoId = useStableId();
|
|
14319
|
+
const id = idProp ?? autoId;
|
|
14320
|
+
const hasError = error && (errorMessage != null || message != null);
|
|
14321
|
+
const showSuccess = !hasError && successMessage != null;
|
|
14322
|
+
const showNeutral = !hasError && !showSuccess && message != null;
|
|
14323
|
+
const hasFeedback = hasError || showSuccess || showNeutral;
|
|
14324
|
+
const messageInside = fieldMessagePlacement === "inside" && hasFeedback;
|
|
14325
|
+
const messageId = hasError ? `${id}-field-error` : showSuccess || showNeutral ? `${id}-message` : void 0;
|
|
14326
|
+
const describedBy = messageId;
|
|
14327
|
+
const fieldMessage = hasError ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14328
|
+
TextInputFieldMessage,
|
|
14329
|
+
{
|
|
14330
|
+
errorMessageIcon,
|
|
14331
|
+
id: messageId,
|
|
14332
|
+
insidePlacement: messageInside,
|
|
14333
|
+
kind: "error",
|
|
14334
|
+
text: errorMessage ?? message
|
|
14335
|
+
}
|
|
14336
|
+
) : showSuccess ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14337
|
+
TextInputFieldMessage,
|
|
14338
|
+
{
|
|
14339
|
+
id: messageId,
|
|
14340
|
+
insidePlacement: messageInside,
|
|
14341
|
+
kind: "success",
|
|
14342
|
+
successMessageIcon,
|
|
14343
|
+
text: successMessage
|
|
14344
|
+
}
|
|
14345
|
+
) : showNeutral ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
14346
|
+
TextInputFieldMessage,
|
|
14347
|
+
{
|
|
14348
|
+
id: messageId,
|
|
14349
|
+
insidePlacement: messageInside,
|
|
14350
|
+
kind: "neutral",
|
|
14351
|
+
text: message
|
|
14352
|
+
}
|
|
14353
|
+
) : null;
|
|
14256
14354
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14257
14355
|
"div",
|
|
14258
14356
|
{
|
|
14259
14357
|
className: clsx(
|
|
14260
14358
|
"str-chat__form-text-input",
|
|
14261
14359
|
error && "str-chat__form-text-input--error",
|
|
14262
|
-
|
|
14360
|
+
showSuccess && "str-chat__form-text-input--success",
|
|
14263
14361
|
disabled && "str-chat__form-text-input--disabled",
|
|
14362
|
+
messageInside && "str-chat__form-text-input--field-message-inside",
|
|
14264
14363
|
className
|
|
14265
14364
|
),
|
|
14266
14365
|
children: [
|
|
14267
|
-
|
|
14366
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx("label", { className: "str-chat__form-text-input__label", htmlFor: id, children: label }) : null,
|
|
14268
14367
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
14269
14368
|
"div",
|
|
14270
14369
|
{
|
|
14271
14370
|
className: clsx(
|
|
14272
14371
|
"str-chat__form-text-input__wrapper",
|
|
14273
|
-
`str-chat__form-text-input__wrapper--${variant}
|
|
14372
|
+
`str-chat__form-text-input__wrapper--${variant}`,
|
|
14373
|
+
messageInside && "str-chat__form-text-input__wrapper--field-message-inside"
|
|
14274
14374
|
),
|
|
14275
14375
|
children: [
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14376
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__form-text-input__control-row", children: [
|
|
14377
|
+
leading ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "str-chat__form-text-input__leading", children: leading }) : null,
|
|
14378
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
14379
|
+
"input",
|
|
14380
|
+
{
|
|
14381
|
+
"aria-describedby": describedBy,
|
|
14382
|
+
"aria-invalid": error,
|
|
14383
|
+
className: "str-chat__form-text-input__input",
|
|
14384
|
+
disabled,
|
|
14385
|
+
id,
|
|
14386
|
+
ref,
|
|
14387
|
+
...inputProps
|
|
14388
|
+
}
|
|
14389
|
+
),
|
|
14390
|
+
trailingText != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "str-chat__form-text-input__suffix", children: trailingText }) : null,
|
|
14391
|
+
trailing ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "str-chat__form-text-input__trailing", children: trailing }) : null
|
|
14392
|
+
] }),
|
|
14393
|
+
messageInside ? fieldMessage : null
|
|
14291
14394
|
]
|
|
14292
14395
|
}
|
|
14293
14396
|
),
|
|
14294
|
-
|
|
14295
|
-
"div",
|
|
14296
|
-
{
|
|
14297
|
-
className: clsx(
|
|
14298
|
-
"str-chat__form-text-input__message",
|
|
14299
|
-
displayError && "str-chat__form-field-error",
|
|
14300
|
-
displaySuccess && "str-chat__form-text-input__message--success"
|
|
14301
|
-
),
|
|
14302
|
-
id: messageId,
|
|
14303
|
-
role: error ? "alert" : void 0,
|
|
14304
|
-
children: messageContent
|
|
14305
|
-
}
|
|
14306
|
-
)
|
|
14397
|
+
messageInside ? null : fieldMessage
|
|
14307
14398
|
]
|
|
14308
14399
|
}
|
|
14309
14400
|
);
|
|
@@ -15688,6 +15779,7 @@ const OptionFieldSet = () => {
|
|
|
15688
15779
|
{
|
|
15689
15780
|
className: "str-chat__form__input-field__value",
|
|
15690
15781
|
error: !!error,
|
|
15782
|
+
fieldMessagePlacement: "inside",
|
|
15691
15783
|
id: option.id,
|
|
15692
15784
|
leading: draggable ? /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconReorder, { className: "str-chat__drag-handle" }) : void 0,
|
|
15693
15785
|
message: error ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "poll-option-input-field-error", children: knownValidationErrors[error] ?? t("Error") }) : void 0,
|
|
@@ -15725,7 +15817,7 @@ const RemoveOptionButton = ({ className, ...props }) => /* @__PURE__ */ jsxRunti
|
|
|
15725
15817
|
appearance: "ghost",
|
|
15726
15818
|
circular: true,
|
|
15727
15819
|
className: clsx("str-chat__form__remove-option-button", className),
|
|
15728
|
-
size: "
|
|
15820
|
+
size: "xs",
|
|
15729
15821
|
variant: "secondary",
|
|
15730
15822
|
...props,
|
|
15731
15823
|
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMinusCircle, {})
|
|
@@ -17341,7 +17433,7 @@ const GalleryUI = () => {
|
|
|
17341
17433
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17342
17434
|
"div",
|
|
17343
17435
|
{
|
|
17344
|
-
className: clsx({
|
|
17436
|
+
className: clsx("str-chat__gallery__media-container", {
|
|
17345
17437
|
"str-chat__gallery__media--dragging": isDragging,
|
|
17346
17438
|
"str-chat__gallery__media--slide-backward": !isDragging && slideDirection === "backward",
|
|
17347
17439
|
"str-chat__gallery__media--slide-forward": !isDragging && slideDirection === "forward"
|
|
@@ -18246,7 +18338,7 @@ const textComposerStateSelector$3 = ({ selection, suggestions }) => ({
|
|
|
18246
18338
|
const searchSourceStateSelector$5 = (nextValue) => ({
|
|
18247
18339
|
items: nextValue.items ?? []
|
|
18248
18340
|
});
|
|
18249
|
-
const defaultComponents = {
|
|
18341
|
+
const defaultComponents$1 = {
|
|
18250
18342
|
"/": (props) => /* @__PURE__ */ jsxRuntime.jsx(CommandItem, { ...props, entity: props.entity }),
|
|
18251
18343
|
":": (props) => /* @__PURE__ */ jsxRuntime.jsx(EmoticonItem, { ...props, entity: props.entity }),
|
|
18252
18344
|
"@": (props) => /* @__PURE__ */ jsxRuntime.jsx(UserItem, { ...props, entity: props.entity })
|
|
@@ -18257,7 +18349,7 @@ const SuggestionList = ({
|
|
|
18257
18349
|
containerClassName,
|
|
18258
18350
|
focusedItemIndex,
|
|
18259
18351
|
setFocusedItemIndex,
|
|
18260
|
-
suggestionItemComponents = defaultComponents
|
|
18352
|
+
suggestionItemComponents = defaultComponents$1
|
|
18261
18353
|
}) => {
|
|
18262
18354
|
const {
|
|
18263
18355
|
AutocompleteSuggestionItem = SuggestionListItem,
|
|
@@ -19111,7 +19203,7 @@ const getLatestMessagePreview = (channel, t, userLanguage = "en", isMessageAIGen
|
|
|
19111
19203
|
if (!latestMessage) {
|
|
19112
19204
|
return t("Nothing yet...");
|
|
19113
19205
|
}
|
|
19114
|
-
if (latestMessage
|
|
19206
|
+
if (WithAudioPlayback.isMessageDeleted(latestMessage)) {
|
|
19115
19207
|
return t("Message deleted");
|
|
19116
19208
|
}
|
|
19117
19209
|
if (poll) {
|
|
@@ -19649,7 +19741,11 @@ const defaultReactionOptions = {
|
|
|
19649
19741
|
};
|
|
19650
19742
|
const stableOwnReactions = [];
|
|
19651
19743
|
const ReactionSelector = (props) => {
|
|
19652
|
-
const {
|
|
19744
|
+
const {
|
|
19745
|
+
dialogId: propDialogId,
|
|
19746
|
+
handleReaction: propHandleReaction,
|
|
19747
|
+
own_reactions: propOwnReactions
|
|
19748
|
+
} = props;
|
|
19653
19749
|
const [extendedListOpen, setExtendedListOpen] = React.useState(false);
|
|
19654
19750
|
const {
|
|
19655
19751
|
reactionOptions = defaultReactionOptions,
|
|
@@ -19661,7 +19757,7 @@ const ReactionSelector = (props) => {
|
|
|
19661
19757
|
message,
|
|
19662
19758
|
threadList
|
|
19663
19759
|
} = useMessageContext();
|
|
19664
|
-
const dialogId2 = ReactionSelector.getDialogId({
|
|
19760
|
+
const dialogId2 = propDialogId ?? ReactionSelector.getDialogId({
|
|
19665
19761
|
messageId: message.id,
|
|
19666
19762
|
threadList
|
|
19667
19763
|
});
|
|
@@ -19687,50 +19783,61 @@ const ReactionSelector = (props) => {
|
|
|
19687
19783
|
})
|
|
19688
19784
|
);
|
|
19689
19785
|
}, [reactionOptions]);
|
|
19690
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
19691
|
-
|
|
19692
|
-
|
|
19693
|
-
|
|
19694
|
-
|
|
19695
|
-
|
|
19696
|
-
|
|
19697
|
-
children:
|
|
19698
|
-
|
|
19699
|
-
|
|
19700
|
-
{
|
|
19701
|
-
|
|
19702
|
-
|
|
19703
|
-
|
|
19704
|
-
|
|
19705
|
-
|
|
19706
|
-
|
|
19707
|
-
|
|
19708
|
-
|
|
19709
|
-
|
|
19710
|
-
|
|
19711
|
-
|
|
19712
|
-
|
|
19713
|
-
|
|
19714
|
-
|
|
19715
|
-
|
|
19716
|
-
|
|
19717
|
-
|
|
19718
|
-
|
|
19719
|
-
|
|
19720
|
-
|
|
19721
|
-
|
|
19722
|
-
|
|
19723
|
-
|
|
19724
|
-
|
|
19725
|
-
|
|
19726
|
-
|
|
19727
|
-
|
|
19728
|
-
|
|
19786
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__reaction-selector", "data-testid": "reaction-selector", children: !extendedListOpen ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19787
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19788
|
+
"ul",
|
|
19789
|
+
{
|
|
19790
|
+
className: "str-chat__reaction-selector-list",
|
|
19791
|
+
"data-testid": "reaction-selector-list",
|
|
19792
|
+
children: adjustedQuickReactionOptions.map(
|
|
19793
|
+
({ Component, name: reactionName, type: reactionType }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__reaction-list-selector__item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19794
|
+
"button",
|
|
19795
|
+
{
|
|
19796
|
+
"aria-label": `Select Reaction: ${reactionName || reactionType}`,
|
|
19797
|
+
"aria-pressed": typeof ownReactionByType[reactionType] !== "undefined",
|
|
19798
|
+
className: clsx("str-chat__reaction-selector-list__item-button"),
|
|
19799
|
+
"data-testid": "select-reaction-button",
|
|
19800
|
+
"data-text": reactionType,
|
|
19801
|
+
onClick: (event) => {
|
|
19802
|
+
handleReaction(reactionType, event);
|
|
19803
|
+
if (closeReactionSelectorOnClick) {
|
|
19804
|
+
dialog.close();
|
|
19805
|
+
}
|
|
19806
|
+
},
|
|
19807
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__reaction-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Component, {}) })
|
|
19808
|
+
}
|
|
19809
|
+
) }, reactionType)
|
|
19810
|
+
)
|
|
19811
|
+
}
|
|
19812
|
+
),
|
|
19813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19814
|
+
WithAudioPlayback.Button,
|
|
19815
|
+
{
|
|
19816
|
+
appearance: "outline",
|
|
19817
|
+
circular: true,
|
|
19818
|
+
className: "str-chat__reaction-selector__add-button",
|
|
19819
|
+
"data-testid": "reaction-selector-add-button",
|
|
19820
|
+
onClick: () => {
|
|
19821
|
+
setExtendedListOpen(true);
|
|
19822
|
+
},
|
|
19823
|
+
size: "sm",
|
|
19824
|
+
variant: "secondary",
|
|
19825
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconPlus, {})
|
|
19826
|
+
}
|
|
19827
|
+
)
|
|
19828
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
19829
|
+
ReactionSelectorExtendedList2,
|
|
19830
|
+
{
|
|
19831
|
+
...props,
|
|
19832
|
+
dialogId: dialogId2,
|
|
19833
|
+
handleReaction: async (reactionType, event) => {
|
|
19834
|
+
await handleReaction(reactionType, event);
|
|
19835
|
+
if (closeReactionSelectorOnClick) {
|
|
19836
|
+
dialog.close();
|
|
19729
19837
|
}
|
|
19730
|
-
|
|
19731
|
-
|
|
19732
|
-
|
|
19733
|
-
] });
|
|
19838
|
+
}
|
|
19839
|
+
}
|
|
19840
|
+
) });
|
|
19734
19841
|
};
|
|
19735
19842
|
ReactionSelector.getDialogId = ({ messageId, threadList }) => {
|
|
19736
19843
|
const dialogIdNamespace = threadList ? "-thread" : "";
|
|
@@ -19790,521 +19897,682 @@ ReactionSelector.ExtendedList = function ReactionSelectorExtendedList({
|
|
|
19790
19897
|
}
|
|
19791
19898
|
);
|
|
19792
19899
|
};
|
|
19793
|
-
|
|
19794
|
-
|
|
19900
|
+
function useFetchReactions(options) {
|
|
19901
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
19902
|
+
const { handleFetchReactions: contextHandleFetchReactions } = useMessageContext();
|
|
19903
|
+
const { t } = WithAudioPlayback.useTranslationContext("useFetchReactions");
|
|
19904
|
+
const [reactions, setReactions] = React.useState([]);
|
|
19905
|
+
const {
|
|
19906
|
+
handleFetchReactions: propHandleFetchReactions,
|
|
19907
|
+
reactionType,
|
|
19908
|
+
shouldFetch,
|
|
19909
|
+
sort
|
|
19910
|
+
} = options;
|
|
19911
|
+
const [isLoading, setIsLoading] = React.useState(shouldFetch);
|
|
19912
|
+
const handleFetchReactions = propHandleFetchReactions ?? contextHandleFetchReactions;
|
|
19913
|
+
const [refetchNonce, setRefetchNonce] = React.useState(null);
|
|
19914
|
+
React.useEffect(() => {
|
|
19915
|
+
if (!shouldFetch) {
|
|
19916
|
+
return;
|
|
19917
|
+
}
|
|
19918
|
+
let cancel = false;
|
|
19919
|
+
(async () => {
|
|
19920
|
+
try {
|
|
19921
|
+
setIsLoading(true);
|
|
19922
|
+
const reactions2 = await handleFetchReactions(reactionType ?? void 0, sort);
|
|
19923
|
+
if (!cancel) {
|
|
19924
|
+
setReactions(reactions2);
|
|
19925
|
+
}
|
|
19926
|
+
} catch (e) {
|
|
19927
|
+
if (!cancel) {
|
|
19928
|
+
setReactions([]);
|
|
19929
|
+
addNotification({
|
|
19930
|
+
emitter: "Reactions",
|
|
19931
|
+
error: e instanceof Error ? e : void 0,
|
|
19932
|
+
message: t("Error fetching reactions"),
|
|
19933
|
+
severity: "error",
|
|
19934
|
+
type: "api:message:reactions:fetch:failed"
|
|
19935
|
+
});
|
|
19936
|
+
}
|
|
19937
|
+
} finally {
|
|
19938
|
+
if (!cancel) {
|
|
19939
|
+
setIsLoading(false);
|
|
19940
|
+
}
|
|
19941
|
+
}
|
|
19942
|
+
})();
|
|
19943
|
+
return () => {
|
|
19944
|
+
cancel = true;
|
|
19945
|
+
};
|
|
19946
|
+
}, [
|
|
19947
|
+
addNotification,
|
|
19948
|
+
handleFetchReactions,
|
|
19949
|
+
reactionType,
|
|
19950
|
+
refetchNonce,
|
|
19951
|
+
shouldFetch,
|
|
19952
|
+
sort,
|
|
19953
|
+
t
|
|
19954
|
+
]);
|
|
19955
|
+
const refetch = React.useCallback(() => {
|
|
19956
|
+
setRefetchNonce(Math.random());
|
|
19957
|
+
}, []);
|
|
19958
|
+
return { isLoading, reactions, refetch };
|
|
19959
|
+
}
|
|
19960
|
+
const defaultReactionDetailsSort = { created_at: -1 };
|
|
19961
|
+
const MessageReactionsDetailLoadingIndicator = () => {
|
|
19962
|
+
const elements = React.useMemo(
|
|
19963
|
+
() => Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__skeleton-item", children: [
|
|
19964
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-avatar" }),
|
|
19965
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__skeleton-line" })
|
|
19966
|
+
] }, index)),
|
|
19967
|
+
[]
|
|
19968
|
+
);
|
|
19969
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: elements });
|
|
19970
|
+
};
|
|
19971
|
+
const MessageReactionsDetail = ({
|
|
19972
|
+
handleFetchReactions,
|
|
19973
|
+
handleReaction,
|
|
19974
|
+
onSelectedReactionTypeChange,
|
|
19975
|
+
own_reactions,
|
|
19976
|
+
reactionDetailsSort: propReactionDetailsSort,
|
|
19977
|
+
reactionGroups,
|
|
19978
|
+
reactions,
|
|
19979
|
+
selectedReactionType,
|
|
19980
|
+
totalReactionCount
|
|
19795
19981
|
}) => {
|
|
19796
|
-
const
|
|
19797
|
-
const {
|
|
19798
|
-
const {
|
|
19799
|
-
|
|
19800
|
-
|
|
19801
|
-
|
|
19802
|
-
|
|
19982
|
+
const [extendedReactionListOpen, setExtendedReactionListOpen] = React.useState(false);
|
|
19983
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
19984
|
+
const {
|
|
19985
|
+
Avatar: Avatar$1 = Avatar,
|
|
19986
|
+
LoadingIndicator: LoadingIndicator2 = MessageReactionsDetailLoadingIndicator,
|
|
19987
|
+
reactionOptions = defaultReactionOptions,
|
|
19988
|
+
ReactionSelectorExtendedList: ReactionSelectorExtendedList2 = ReactionSelector.ExtendedList
|
|
19989
|
+
} = WithAudioPlayback.useComponentContext(MessageReactionsDetail.name);
|
|
19990
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
19991
|
+
const {
|
|
19992
|
+
handleReaction: contextHandleReaction,
|
|
19993
|
+
message,
|
|
19994
|
+
reactionDetailsSort: contextReactionDetailsSort
|
|
19995
|
+
} = useMessageContext(MessageReactionsDetail.name);
|
|
19996
|
+
const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
|
|
19997
|
+
const {
|
|
19998
|
+
isLoading: areReactionsLoading,
|
|
19999
|
+
reactions: reactionDetails,
|
|
20000
|
+
refetch
|
|
20001
|
+
} = useFetchReactions({
|
|
20002
|
+
handleFetchReactions,
|
|
20003
|
+
reactionType: selectedReactionType,
|
|
20004
|
+
shouldFetch: true,
|
|
20005
|
+
sort: reactionDetailsSort
|
|
19803
20006
|
});
|
|
19804
|
-
|
|
19805
|
-
|
|
19806
|
-
|
|
19807
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19808
|
-
DialogAnchor,
|
|
20007
|
+
if (extendedReactionListOpen) {
|
|
20008
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20009
|
+
"div",
|
|
19809
20010
|
{
|
|
19810
|
-
|
|
19811
|
-
|
|
19812
|
-
|
|
19813
|
-
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
|
|
19818
|
-
|
|
19819
|
-
|
|
19820
|
-
QuickMessageActionsButton,
|
|
19821
|
-
{
|
|
19822
|
-
"aria-expanded": dialogIsOpen,
|
|
19823
|
-
"aria-label": t("aria/Open Reaction Selector"),
|
|
19824
|
-
className: "str-chat__message-reactions-button",
|
|
19825
|
-
"data-testid": "message-reaction-action",
|
|
19826
|
-
onClick: () => dialog?.toggle(),
|
|
19827
|
-
ref: buttonRef,
|
|
19828
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ReactionIcon, { className: "str-chat__message-action-icon" })
|
|
20011
|
+
className: "str-chat__message-reactions-detail",
|
|
20012
|
+
"data-testid": "message-reactions-detail",
|
|
20013
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20014
|
+
ReactionSelectorExtendedList2,
|
|
20015
|
+
{
|
|
20016
|
+
dialogId: MessageReactionsDetail.getDialogId({ messageId: message.id }),
|
|
20017
|
+
handleReaction,
|
|
20018
|
+
own_reactions
|
|
20019
|
+
}
|
|
20020
|
+
)
|
|
19829
20021
|
}
|
|
19830
|
-
)
|
|
19831
|
-
] });
|
|
19832
|
-
};
|
|
19833
|
-
const getErrorMessage$1 = (error, fallback) => error instanceof Error && error.message ? error.message : fallback;
|
|
19834
|
-
const getNotificationError$1 = (error) => {
|
|
19835
|
-
if (error instanceof Error) return error;
|
|
19836
|
-
if (typeof error === "string") return new Error(error);
|
|
19837
|
-
if (error && typeof error === "object" && "message" in error) {
|
|
19838
|
-
const message = error.message;
|
|
19839
|
-
if (typeof message === "string") return new Error(message);
|
|
20022
|
+
);
|
|
19840
20023
|
}
|
|
19841
|
-
return
|
|
19842
|
-
};
|
|
19843
|
-
const RemindMeSubmenuHeader = () => {
|
|
19844
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
19845
|
-
const { returnToParentMenu } = useContextMenuContext();
|
|
19846
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuBackButton, { onClick: returnToParentMenu, children: [
|
|
19847
|
-
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {}),
|
|
19848
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Remind Me") })
|
|
19849
|
-
] }) });
|
|
19850
|
-
};
|
|
19851
|
-
const RemindMeSubmenu = () => {
|
|
19852
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
19853
|
-
const { client } = WithAudioPlayback.useChatContext();
|
|
19854
|
-
const { message } = useMessageContext();
|
|
19855
|
-
const { closeMenu } = useContextMenuContext();
|
|
19856
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
19857
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20024
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19858
20025
|
"div",
|
|
19859
20026
|
{
|
|
19860
|
-
|
|
19861
|
-
|
|
19862
|
-
|
|
19863
|
-
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
|
|
19869
|
-
|
|
19870
|
-
|
|
19871
|
-
|
|
19872
|
-
|
|
19873
|
-
|
|
19874
|
-
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
|
|
19878
|
-
|
|
19879
|
-
|
|
19880
|
-
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
|
|
19892
|
-
|
|
19893
|
-
|
|
19894
|
-
|
|
19895
|
-
|
|
19896
|
-
|
|
19897
|
-
|
|
19898
|
-
|
|
19899
|
-
|
|
19900
|
-
|
|
20027
|
+
className: "str-chat__message-reactions-detail",
|
|
20028
|
+
"data-testid": "message-reactions-detail",
|
|
20029
|
+
children: [
|
|
20030
|
+
typeof totalReactionCount === "number" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__total-count", children: t("{{ count }} reactions", { count: totalReactionCount }) }),
|
|
20031
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__reaction-type-list-container", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20032
|
+
"ul",
|
|
20033
|
+
{
|
|
20034
|
+
className: "str-chat__message-reactions-detail__reaction-type-list",
|
|
20035
|
+
"data-testid": "reaction-type-list",
|
|
20036
|
+
children: [
|
|
20037
|
+
/* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions-detail__reaction-type-list-item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20038
|
+
"button",
|
|
20039
|
+
{
|
|
20040
|
+
"aria-label": t("Add reaction"),
|
|
20041
|
+
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20042
|
+
"data-testid": "add-reaction-button",
|
|
20043
|
+
onClick: () => setExtendedReactionListOpen(true),
|
|
20044
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconEmojiAdd, {}) })
|
|
20045
|
+
}
|
|
20046
|
+
) }),
|
|
20047
|
+
reactions.map(
|
|
20048
|
+
({ EmojiComponent, reactionCount, reactionType }) => EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20049
|
+
"li",
|
|
20050
|
+
{
|
|
20051
|
+
className: "str-chat__message-reactions-detail__reaction-type-list-item",
|
|
20052
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20053
|
+
"button",
|
|
20054
|
+
{
|
|
20055
|
+
"aria-pressed": reactionType === selectedReactionType,
|
|
20056
|
+
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20057
|
+
onClick: () => onSelectedReactionTypeChange?.(
|
|
20058
|
+
selectedReactionType === reactionType ? null : reactionType
|
|
20059
|
+
),
|
|
20060
|
+
children: [
|
|
20061
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) }),
|
|
20062
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20063
|
+
"span",
|
|
20064
|
+
{
|
|
20065
|
+
className: "str-chat__message-reactions-detail__reaction-type-list-item-count",
|
|
20066
|
+
"data-testid": "reaction-type-count",
|
|
20067
|
+
children: reactionCount
|
|
20068
|
+
}
|
|
20069
|
+
)
|
|
20070
|
+
]
|
|
20071
|
+
}
|
|
20072
|
+
)
|
|
20073
|
+
},
|
|
20074
|
+
reactionType
|
|
20075
|
+
)
|
|
20076
|
+
)
|
|
20077
|
+
]
|
|
20078
|
+
}
|
|
20079
|
+
) }),
|
|
20080
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__user-list-container", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20081
|
+
"div",
|
|
20082
|
+
{
|
|
20083
|
+
className: "str-chat__message-reactions-detail__user-list",
|
|
20084
|
+
"data-testid": "all-reacting-users",
|
|
20085
|
+
children: [
|
|
20086
|
+
areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
|
|
20087
|
+
!areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetails.map(({ type, user }) => {
|
|
20088
|
+
const belongsToCurrentUser = client.user?.id === user?.id;
|
|
20089
|
+
const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
|
|
20090
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20091
|
+
"div",
|
|
20092
|
+
{
|
|
20093
|
+
className: "str-chat__message-reactions-detail__user-list-item",
|
|
20094
|
+
children: [
|
|
20095
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20096
|
+
Avatar$1,
|
|
20097
|
+
{
|
|
20098
|
+
className: "str-chat__avatar--with-border",
|
|
20099
|
+
"data-testid": "avatar",
|
|
20100
|
+
imageUrl: user?.image,
|
|
20101
|
+
size: "md",
|
|
20102
|
+
userName: user?.name || user?.id
|
|
20103
|
+
}
|
|
20104
|
+
),
|
|
20105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__user-list-item-info", children: [
|
|
20106
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20107
|
+
"span",
|
|
20108
|
+
{
|
|
20109
|
+
className: "str-chat__message-reactions-detail__user-list-item-username",
|
|
20110
|
+
"data-testid": "reaction-user-username",
|
|
20111
|
+
children: belongsToCurrentUser ? t("You") : user?.name || user?.id
|
|
20112
|
+
}
|
|
20113
|
+
),
|
|
20114
|
+
belongsToCurrentUser && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20115
|
+
"button",
|
|
20116
|
+
{
|
|
20117
|
+
className: "str-chat__message-reactions-detail__user-list-item-button",
|
|
20118
|
+
"data-testid": "remove-reaction-button",
|
|
20119
|
+
onClick: async (e) => {
|
|
20120
|
+
const reactionCountBeforeRemoval = reactionGroups?.[type]?.count ?? 0;
|
|
20121
|
+
await contextHandleReaction(type, e);
|
|
20122
|
+
if (selectedReactionType !== null && reactionCountBeforeRemoval <= 1) {
|
|
20123
|
+
onSelectedReactionTypeChange?.(null);
|
|
20124
|
+
} else {
|
|
20125
|
+
refetch();
|
|
20126
|
+
}
|
|
20127
|
+
},
|
|
20128
|
+
children: t("Tap to remove")
|
|
20129
|
+
}
|
|
20130
|
+
)
|
|
20131
|
+
] }),
|
|
20132
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__user-list-item-icon", children: !selectedReactionType && EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) })
|
|
20133
|
+
]
|
|
20134
|
+
},
|
|
20135
|
+
`${user?.id}-${type}`
|
|
20136
|
+
);
|
|
20137
|
+
}) })
|
|
20138
|
+
]
|
|
20139
|
+
}
|
|
20140
|
+
) })
|
|
20141
|
+
]
|
|
19901
20142
|
}
|
|
19902
20143
|
);
|
|
19903
20144
|
};
|
|
19904
|
-
|
|
19905
|
-
|
|
19906
|
-
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
className: clsx("str-chat__message-actions-box-button", className),
|
|
19910
|
-
size: "sm",
|
|
19911
|
-
variant: "secondary",
|
|
19912
|
-
...props
|
|
20145
|
+
MessageReactionsDetail.displayName = "MessageReactionsDetail";
|
|
20146
|
+
MessageReactionsDetail.getDialogId = ({ messageId }) => `message-reactions-detail-${messageId}`;
|
|
20147
|
+
const defaultReactionsSort = (a, b) => {
|
|
20148
|
+
if (a.firstReactionAt && b.firstReactionAt) {
|
|
20149
|
+
return +a.firstReactionAt - +b.firstReactionAt;
|
|
19913
20150
|
}
|
|
19914
|
-
);
|
|
19915
|
-
|
|
19916
|
-
|
|
19917
|
-
const {
|
|
19918
|
-
|
|
19919
|
-
|
|
19920
|
-
|
|
19921
|
-
|
|
19922
|
-
|
|
19923
|
-
|
|
19924
|
-
|
|
19925
|
-
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19929
|
-
|
|
19930
|
-
|
|
19931
|
-
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
|
|
19946
|
-
|
|
19947
|
-
|
|
19948
|
-
|
|
19949
|
-
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
|
|
19959
|
-
|
|
19960
|
-
|
|
20151
|
+
return a.reactionType.localeCompare(b.reactionType, "en");
|
|
20152
|
+
};
|
|
20153
|
+
const useProcessReactions = (params) => {
|
|
20154
|
+
const {
|
|
20155
|
+
own_reactions: propOwnReactions,
|
|
20156
|
+
reaction_groups: propReactionGroups,
|
|
20157
|
+
reactions: propReactions,
|
|
20158
|
+
sortReactions: propSortReactions
|
|
20159
|
+
} = params;
|
|
20160
|
+
const { message, sortReactions: contextSortReactions } = useMessageContext();
|
|
20161
|
+
const { reactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
|
|
20162
|
+
const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort;
|
|
20163
|
+
const latestReactions = propReactions ?? message.latest_reactions;
|
|
20164
|
+
const ownReactions = propOwnReactions ?? message?.own_reactions;
|
|
20165
|
+
const reactionGroups = propReactionGroups ?? message?.reaction_groups ?? void 0;
|
|
20166
|
+
const isOwnReaction = React.useCallback(
|
|
20167
|
+
(reactionType) => ownReactions?.some((reaction) => reaction.type === reactionType) ?? false,
|
|
20168
|
+
[ownReactions]
|
|
20169
|
+
);
|
|
20170
|
+
const getEmojiByReactionType = React.useCallback(
|
|
20171
|
+
(reactionType) => {
|
|
20172
|
+
if (Array.isArray(reactionOptions)) {
|
|
20173
|
+
return reactionOptions.find(({ type }) => type === reactionType)?.Component ?? null;
|
|
20174
|
+
}
|
|
20175
|
+
return reactionOptions.quick[reactionType]?.Component ?? reactionOptions.extended?.[reactionType]?.Component ?? null;
|
|
20176
|
+
},
|
|
20177
|
+
[reactionOptions]
|
|
20178
|
+
);
|
|
20179
|
+
const isSupportedReaction = React.useCallback(
|
|
20180
|
+
(reactionType) => {
|
|
20181
|
+
if (Array.isArray(reactionOptions)) {
|
|
20182
|
+
return reactionOptions.some(
|
|
20183
|
+
(reactionOption) => reactionOption.type === reactionType
|
|
20184
|
+
);
|
|
20185
|
+
}
|
|
20186
|
+
return typeof reactionOptions.quick[reactionType] !== "undefined" || typeof reactionOptions.extended?.[reactionType] !== "undefined";
|
|
20187
|
+
},
|
|
20188
|
+
[reactionOptions]
|
|
20189
|
+
);
|
|
20190
|
+
const uniqueReactionTypeCount = React.useMemo(() => {
|
|
20191
|
+
if (!reactionGroups) {
|
|
20192
|
+
return 0;
|
|
20193
|
+
}
|
|
20194
|
+
return Object.keys(reactionGroups).filter(
|
|
20195
|
+
(reactionType) => isSupportedReaction(reactionType)
|
|
20196
|
+
).length;
|
|
20197
|
+
}, [isSupportedReaction, reactionGroups]);
|
|
20198
|
+
const getLatestReactedUserNames = React.useCallback(
|
|
20199
|
+
(reactionType) => latestReactions?.flatMap((reaction) => {
|
|
20200
|
+
if (reactionType && reactionType === reaction.type) {
|
|
20201
|
+
const username = reaction.user?.name || reaction.user?.id;
|
|
20202
|
+
return username ? [username] : [];
|
|
20203
|
+
}
|
|
20204
|
+
return [];
|
|
20205
|
+
}) ?? [],
|
|
20206
|
+
[latestReactions]
|
|
20207
|
+
);
|
|
20208
|
+
const existingReactions = React.useMemo(() => {
|
|
20209
|
+
if (!reactionGroups) {
|
|
20210
|
+
return [];
|
|
19961
20211
|
}
|
|
20212
|
+
const unsortedReactions = Object.entries(reactionGroups).flatMap(
|
|
20213
|
+
([reactionType, { count, first_reaction_at, last_reaction_at }]) => {
|
|
20214
|
+
if (count === 0 || !isSupportedReaction(reactionType)) {
|
|
20215
|
+
return [];
|
|
20216
|
+
}
|
|
20217
|
+
const latestReactedUserNames = getLatestReactedUserNames(reactionType);
|
|
20218
|
+
return [
|
|
20219
|
+
{
|
|
20220
|
+
EmojiComponent: getEmojiByReactionType(reactionType),
|
|
20221
|
+
firstReactionAt: first_reaction_at ? new Date(first_reaction_at) : null,
|
|
20222
|
+
isOwnReaction: isOwnReaction(reactionType),
|
|
20223
|
+
lastReactionAt: last_reaction_at ? new Date(last_reaction_at) : null,
|
|
20224
|
+
latestReactedUserNames,
|
|
20225
|
+
reactionCount: count,
|
|
20226
|
+
reactionType,
|
|
20227
|
+
unlistedReactedUserCount: count - latestReactedUserNames.length
|
|
20228
|
+
}
|
|
20229
|
+
];
|
|
20230
|
+
}
|
|
20231
|
+
);
|
|
20232
|
+
return unsortedReactions.sort(sortReactions);
|
|
20233
|
+
}, [
|
|
20234
|
+
getEmojiByReactionType,
|
|
20235
|
+
getLatestReactedUserNames,
|
|
20236
|
+
isOwnReaction,
|
|
20237
|
+
isSupportedReaction,
|
|
20238
|
+
reactionGroups,
|
|
20239
|
+
sortReactions
|
|
20240
|
+
]);
|
|
20241
|
+
const hasReactions = existingReactions.length > 0;
|
|
20242
|
+
const totalReactionCount = React.useMemo(
|
|
20243
|
+
() => Object.values(reactionGroups ?? {}).reduce((total, { count }) => total + count, 0),
|
|
20244
|
+
[reactionGroups]
|
|
19962
20245
|
);
|
|
20246
|
+
return {
|
|
20247
|
+
existingReactions,
|
|
20248
|
+
hasReactions,
|
|
20249
|
+
reactionGroups,
|
|
20250
|
+
totalReactionCount,
|
|
20251
|
+
uniqueReactionTypeCount
|
|
20252
|
+
};
|
|
19963
20253
|
};
|
|
19964
|
-
const
|
|
19965
|
-
|
|
19966
|
-
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
if (
|
|
19970
|
-
|
|
19971
|
-
if (typeof message === "string") return new Error(message);
|
|
20254
|
+
const FragmentOrButton = ({
|
|
20255
|
+
buttonIf: renderButton = false,
|
|
20256
|
+
children,
|
|
20257
|
+
...props
|
|
20258
|
+
}) => {
|
|
20259
|
+
if (renderButton) {
|
|
20260
|
+
return /* @__PURE__ */ jsxRuntime.jsx("button", { ...props, children });
|
|
19972
20261
|
}
|
|
19973
|
-
return
|
|
20262
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
19974
20263
|
};
|
|
19975
|
-
const
|
|
19976
|
-
|
|
19977
|
-
|
|
19978
|
-
|
|
19979
|
-
|
|
19980
|
-
|
|
19981
|
-
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
|
|
19998
|
-
|
|
19999
|
-
|
|
20000
|
-
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
|
|
20015
|
-
|
|
20016
|
-
|
|
20017
|
-
|
|
20018
|
-
|
|
20019
|
-
|
|
20020
|
-
|
|
20021
|
-
|
|
20022
|
-
|
|
20023
|
-
|
|
20024
|
-
|
|
20025
|
-
|
|
20026
|
-
|
|
20027
|
-
|
|
20028
|
-
|
|
20029
|
-
|
|
20030
|
-
|
|
20031
|
-
|
|
20032
|
-
|
|
20033
|
-
|
|
20034
|
-
|
|
20035
|
-
|
|
20036
|
-
|
|
20037
|
-
|
|
20038
|
-
|
|
20039
|
-
|
|
20040
|
-
|
|
20041
|
-
|
|
20042
|
-
|
|
20043
|
-
|
|
20044
|
-
|
|
20045
|
-
|
|
20046
|
-
|
|
20047
|
-
|
|
20048
|
-
|
|
20049
|
-
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
|
|
20055
|
-
|
|
20056
|
-
|
|
20057
|
-
)
|
|
20058
|
-
|
|
20059
|
-
|
|
20060
|
-
|
|
20061
|
-
|
|
20062
|
-
|
|
20063
|
-
|
|
20064
|
-
|
|
20065
|
-
|
|
20066
|
-
|
|
20067
|
-
|
|
20068
|
-
|
|
20069
|
-
|
|
20070
|
-
|
|
20071
|
-
|
|
20072
|
-
|
|
20073
|
-
|
|
20074
|
-
|
|
20075
|
-
|
|
20076
|
-
|
|
20077
|
-
|
|
20078
|
-
|
|
20079
|
-
|
|
20080
|
-
|
|
20081
|
-
|
|
20082
|
-
|
|
20083
|
-
|
|
20084
|
-
|
|
20085
|
-
|
|
20086
|
-
|
|
20087
|
-
|
|
20088
|
-
|
|
20089
|
-
|
|
20090
|
-
|
|
20091
|
-
ContextMenuButton,
|
|
20092
|
-
{
|
|
20093
|
-
"aria-label": t("aria/Resend Message"),
|
|
20094
|
-
className: msgActionsBoxButtonClassName,
|
|
20095
|
-
Icon: WithAudioPlayback.IconRetry,
|
|
20096
|
-
onClick: () => {
|
|
20097
|
-
handleRetry(message);
|
|
20098
|
-
closeMenu();
|
|
20099
|
-
},
|
|
20100
|
-
children: t("Resend")
|
|
20101
|
-
}
|
|
20102
|
-
);
|
|
20103
|
-
},
|
|
20104
|
-
Edit() {
|
|
20105
|
-
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
20106
|
-
const { message } = useMessageContext();
|
|
20107
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20108
|
-
const { closeMenu } = useContextMenuContext();
|
|
20109
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20110
|
-
ContextMenuButton,
|
|
20111
|
-
{
|
|
20112
|
-
"aria-label": t("aria/Edit Message"),
|
|
20113
|
-
className: msgActionsBoxButtonClassName,
|
|
20114
|
-
Icon: WithAudioPlayback.IconEdit,
|
|
20115
|
-
onClick: () => {
|
|
20116
|
-
savePreEditSnapshot(messageComposer);
|
|
20117
|
-
messageComposer.initState({ composition: message });
|
|
20118
|
-
closeMenu();
|
|
20119
|
-
},
|
|
20120
|
-
children: t("Edit Message")
|
|
20121
|
-
}
|
|
20122
|
-
);
|
|
20123
|
-
},
|
|
20124
|
-
MarkUnread() {
|
|
20125
|
-
const { closeMenu } = useContextMenuContext();
|
|
20126
|
-
const { handleMarkUnread, message } = useMessageContext();
|
|
20127
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20128
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20129
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20130
|
-
ContextMenuButton,
|
|
20131
|
-
{
|
|
20132
|
-
"aria-label": t("aria/Mark Message Unread"),
|
|
20133
|
-
className: msgActionsBoxButtonClassName,
|
|
20134
|
-
Icon: WithAudioPlayback.IconNotification,
|
|
20135
|
-
onClick: async (event) => {
|
|
20136
|
-
try {
|
|
20137
|
-
await handleMarkUnread(event);
|
|
20138
|
-
addNotification({
|
|
20139
|
-
context: {
|
|
20140
|
-
message
|
|
20141
|
-
},
|
|
20142
|
-
emitter: "MessageActions",
|
|
20143
|
-
message: t("Message marked as unread"),
|
|
20144
|
-
severity: "success",
|
|
20145
|
-
type: "api:message:markUnread:success"
|
|
20146
|
-
});
|
|
20147
|
-
} catch (error) {
|
|
20148
|
-
addNotification({
|
|
20149
|
-
context: {
|
|
20150
|
-
message
|
|
20151
|
-
},
|
|
20152
|
-
emitter: "MessageActions",
|
|
20153
|
-
error: getNotificationError(error),
|
|
20154
|
-
message: getErrorMessage(
|
|
20155
|
-
error,
|
|
20156
|
-
t(
|
|
20157
|
-
"Error marking message unread. Cannot mark unread messages older than the newest 100 channel messages."
|
|
20264
|
+
const UnMemoizedMessageReactions = (props) => {
|
|
20265
|
+
const {
|
|
20266
|
+
capLimit: { clustered: capLimitClustered = 5, segmented: capLimitSegmented = 4 } = {},
|
|
20267
|
+
flipHorizontalPosition = false,
|
|
20268
|
+
handleFetchReactions,
|
|
20269
|
+
reactionDetailsSort,
|
|
20270
|
+
verticalPosition = "top",
|
|
20271
|
+
visualStyle = "clustered",
|
|
20272
|
+
...rest
|
|
20273
|
+
} = props;
|
|
20274
|
+
const {
|
|
20275
|
+
existingReactions,
|
|
20276
|
+
hasReactions,
|
|
20277
|
+
reactionGroups,
|
|
20278
|
+
totalReactionCount,
|
|
20279
|
+
uniqueReactionTypeCount
|
|
20280
|
+
} = useProcessReactions(rest);
|
|
20281
|
+
const [selectedReactionType, setSelectedReactionType] = React.useState(
|
|
20282
|
+
null
|
|
20283
|
+
);
|
|
20284
|
+
const { t } = WithAudioPlayback.useTranslationContext("MessageReactions");
|
|
20285
|
+
const { MessageReactionsDetail: MessageReactionsDetail$1 = MessageReactionsDetail } = WithAudioPlayback.useComponentContext();
|
|
20286
|
+
const { isMyMessage, message } = useMessageContext();
|
|
20287
|
+
const divRef = React.useRef(null);
|
|
20288
|
+
const dialogId2 = MessageReactionsDetail.getDialogId({
|
|
20289
|
+
messageId: message.id
|
|
20290
|
+
});
|
|
20291
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
20292
|
+
const isDialogOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20293
|
+
const handleReactionButtonClick = (reactionType) => {
|
|
20294
|
+
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
|
|
20295
|
+
return;
|
|
20296
|
+
}
|
|
20297
|
+
setSelectedReactionType(reactionType);
|
|
20298
|
+
dialog.open();
|
|
20299
|
+
};
|
|
20300
|
+
const cappedExistingReactions = React.useMemo(() => {
|
|
20301
|
+
if (visualStyle === "segmented" && verticalPosition !== "top") return null;
|
|
20302
|
+
const capLimit = visualStyle === "segmented" ? capLimitSegmented : capLimitClustered;
|
|
20303
|
+
const sliced = existingReactions.slice(0, capLimit);
|
|
20304
|
+
return {
|
|
20305
|
+
/**
|
|
20306
|
+
* Accumulated reaction count of capped reaction types, first four in case of
|
|
20307
|
+
* segmented(top) and first five in case of clustered(top/bottom) variations.
|
|
20308
|
+
*/
|
|
20309
|
+
reactionCountToDisplay: sliced.reduce(
|
|
20310
|
+
(accumulatedCount, { reactionCount }) => accumulatedCount + reactionCount,
|
|
20311
|
+
0
|
|
20312
|
+
),
|
|
20313
|
+
reactionsToDisplay: sliced
|
|
20314
|
+
};
|
|
20315
|
+
}, [
|
|
20316
|
+
capLimitClustered,
|
|
20317
|
+
capLimitSegmented,
|
|
20318
|
+
existingReactions,
|
|
20319
|
+
verticalPosition,
|
|
20320
|
+
visualStyle
|
|
20321
|
+
]);
|
|
20322
|
+
if (!hasReactions) return null;
|
|
20323
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20324
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20325
|
+
"div",
|
|
20326
|
+
{
|
|
20327
|
+
"aria-label": t("aria/Reaction list"),
|
|
20328
|
+
className: clsx("str-chat__message-reactions", {
|
|
20329
|
+
[`str-chat__message-reactions--flipped-horizontally`]: flipHorizontalPosition,
|
|
20330
|
+
[`str-chat__message-reactions--${verticalPosition}`]: typeof verticalPosition === "string",
|
|
20331
|
+
[`str-chat__message-reactions--${visualStyle}`]: typeof visualStyle === "string"
|
|
20332
|
+
}),
|
|
20333
|
+
ref: divRef,
|
|
20334
|
+
role: "figure",
|
|
20335
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20336
|
+
FragmentOrButton,
|
|
20337
|
+
{
|
|
20338
|
+
"aria-expanded": isDialogOpen,
|
|
20339
|
+
"aria-pressed": isDialogOpen,
|
|
20340
|
+
buttonIf: visualStyle === "clustered",
|
|
20341
|
+
className: "str-chat__message-reactions__list-button",
|
|
20342
|
+
"data-testid": "message-reactions-list-button",
|
|
20343
|
+
onClick: () => handleReactionButtonClick(null),
|
|
20344
|
+
children: [
|
|
20345
|
+
/* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "str-chat__message-reactions__list", children: [
|
|
20346
|
+
(cappedExistingReactions?.reactionsToDisplay ?? existingReactions).map(
|
|
20347
|
+
({ EmojiComponent, reactionCount, reactionType }) => EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20348
|
+
"li",
|
|
20349
|
+
{
|
|
20350
|
+
className: "str-chat__message-reactions__list-item",
|
|
20351
|
+
"data-testid": "message-reactions-list-item",
|
|
20352
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20353
|
+
FragmentOrButton,
|
|
20354
|
+
{
|
|
20355
|
+
buttonIf: visualStyle === "segmented",
|
|
20356
|
+
className: "str-chat__message-reactions__list-item-button",
|
|
20357
|
+
onClick: () => handleReactionButtonClick(reactionType),
|
|
20358
|
+
children: [
|
|
20359
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20360
|
+
"span",
|
|
20361
|
+
{
|
|
20362
|
+
className: "str-chat__message-reactions__list-item-icon",
|
|
20363
|
+
"data-testid": "message-reactions-list-item-icon",
|
|
20364
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {})
|
|
20365
|
+
}
|
|
20366
|
+
),
|
|
20367
|
+
visualStyle === "segmented" && reactionCount > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20368
|
+
"span",
|
|
20369
|
+
{
|
|
20370
|
+
className: "str-chat__message-reactions__list-item-count",
|
|
20371
|
+
"data-testclass": "message-reactions-item-count",
|
|
20372
|
+
children: reactionCount
|
|
20373
|
+
}
|
|
20374
|
+
)
|
|
20375
|
+
]
|
|
20376
|
+
}
|
|
20377
|
+
)
|
|
20378
|
+
},
|
|
20379
|
+
reactionType
|
|
20158
20380
|
)
|
|
20159
20381
|
),
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
|
|
20382
|
+
uniqueReactionTypeCount > 4 && cappedExistingReactions && visualStyle === "segmented" && /* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions__list-item str-chat__message-reactions__list-item--more", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20383
|
+
"button",
|
|
20384
|
+
{
|
|
20385
|
+
className: "str-chat__message-reactions__list-item-button",
|
|
20386
|
+
onClick: () => handleReactionButtonClick(null),
|
|
20387
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "str-chat__message-reactions__overflow-count", children: [
|
|
20388
|
+
"+",
|
|
20389
|
+
totalReactionCount - cappedExistingReactions.reactionCountToDisplay
|
|
20390
|
+
] })
|
|
20391
|
+
}
|
|
20392
|
+
) })
|
|
20393
|
+
] }),
|
|
20394
|
+
visualStyle === "clustered" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20395
|
+
"span",
|
|
20396
|
+
{
|
|
20397
|
+
className: "str-chat__message-reactions__total-count",
|
|
20398
|
+
"data-testid": "message-reactions-total-count",
|
|
20399
|
+
children: totalReactionCount
|
|
20400
|
+
}
|
|
20401
|
+
)
|
|
20402
|
+
]
|
|
20403
|
+
}
|
|
20404
|
+
)
|
|
20405
|
+
}
|
|
20406
|
+
),
|
|
20407
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20408
|
+
DialogAnchor,
|
|
20409
|
+
{
|
|
20410
|
+
dialogManagerId: dialogManager?.id,
|
|
20411
|
+
id: dialogId2,
|
|
20412
|
+
offset: 8,
|
|
20413
|
+
placement: isMyMessage() ? "bottom-end" : "bottom-start",
|
|
20414
|
+
referenceElement: divRef.current,
|
|
20415
|
+
trapFocus: true,
|
|
20416
|
+
updatePositionOnContentResize: true,
|
|
20417
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20418
|
+
MessageReactionsDetail$1,
|
|
20419
|
+
{
|
|
20420
|
+
handleFetchReactions,
|
|
20421
|
+
onSelectedReactionTypeChange: setSelectedReactionType,
|
|
20422
|
+
reactionDetailsSort,
|
|
20423
|
+
reactionGroups,
|
|
20424
|
+
reactions: existingReactions,
|
|
20425
|
+
selectedReactionType,
|
|
20426
|
+
totalReactionCount
|
|
20427
|
+
}
|
|
20428
|
+
)
|
|
20429
|
+
}
|
|
20430
|
+
)
|
|
20431
|
+
] });
|
|
20432
|
+
};
|
|
20433
|
+
const MessageReactions = React.memo(
|
|
20434
|
+
UnMemoizedMessageReactions
|
|
20435
|
+
);
|
|
20436
|
+
const getImageDimensions = (source) => new Promise((resolve, reject) => {
|
|
20437
|
+
const image = new Image();
|
|
20438
|
+
image.addEventListener(
|
|
20439
|
+
"load",
|
|
20440
|
+
() => {
|
|
20441
|
+
resolve([image.width, image.height]);
|
|
20169
20442
|
},
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20176
|
-
|
|
20177
|
-
|
|
20178
|
-
|
|
20179
|
-
|
|
20180
|
-
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
|
|
20184
|
-
|
|
20185
|
-
|
|
20186
|
-
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
|
|
20190
|
-
|
|
20191
|
-
|
|
20192
|
-
|
|
20193
|
-
|
|
20194
|
-
|
|
20195
|
-
|
|
20196
|
-
|
|
20197
|
-
|
|
20198
|
-
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
|
|
20203
|
-
|
|
20204
|
-
|
|
20205
|
-
|
|
20206
|
-
|
|
20207
|
-
|
|
20208
|
-
|
|
20209
|
-
|
|
20210
|
-
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
20218
|
-
|
|
20219
|
-
|
|
20220
|
-
|
|
20221
|
-
|
|
20222
|
-
|
|
20223
|
-
|
|
20224
|
-
|
|
20225
|
-
|
|
20226
|
-
|
|
20227
|
-
|
|
20228
|
-
|
|
20229
|
-
|
|
20230
|
-
|
|
20231
|
-
|
|
20232
|
-
|
|
20233
|
-
|
|
20443
|
+
{ once: true }
|
|
20444
|
+
);
|
|
20445
|
+
image.addEventListener("error", () => reject(`Couldn't load image from ${source}`), {
|
|
20446
|
+
once: true
|
|
20447
|
+
});
|
|
20448
|
+
image.src = source;
|
|
20449
|
+
});
|
|
20450
|
+
const SpriteImage = ({
|
|
20451
|
+
columns,
|
|
20452
|
+
fallback,
|
|
20453
|
+
height,
|
|
20454
|
+
position,
|
|
20455
|
+
rows,
|
|
20456
|
+
spriteUrl,
|
|
20457
|
+
style,
|
|
20458
|
+
width
|
|
20459
|
+
}) => {
|
|
20460
|
+
const [[spriteWidth, spriteHeight], setSpriteDimensions] = React.useState([0, 0]);
|
|
20461
|
+
React.useEffect(() => {
|
|
20462
|
+
getImageDimensions(spriteUrl).then(setSpriteDimensions).catch(console.error);
|
|
20463
|
+
}, [spriteUrl]);
|
|
20464
|
+
const [x, y] = position;
|
|
20465
|
+
if (!spriteHeight || !spriteWidth) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
|
|
20466
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20467
|
+
"div",
|
|
20468
|
+
{
|
|
20469
|
+
"data-testid": "sprite-image",
|
|
20470
|
+
style: {
|
|
20471
|
+
...style,
|
|
20472
|
+
"--str-chat__sprite-image-resize-ratio": "var(--str-chat__sprite-image-resize-ratio-x, var(--str-chat__sprite-image-resize-ratio-y, 1))",
|
|
20473
|
+
"--str-chat__sprite-image-resize-ratio-x": "calc(var(--str-chat__sprite-image-width) / var(--str-chat__sprite-item-width))",
|
|
20474
|
+
"--str-chat__sprite-image-resize-ratio-y": "calc(var(--str-chat__sprite-image-height) / var(--str-chat__sprite-item-height))",
|
|
20475
|
+
"--str-chat__sprite-item-height": `${spriteHeight / rows}`,
|
|
20476
|
+
"--str-chat__sprite-item-width": `${spriteWidth / columns}`,
|
|
20477
|
+
...Number.isFinite(height) ? { "--str-chat__sprite-image-height": `${height}px` } : {},
|
|
20478
|
+
...Number.isFinite(width) ? { "--str-chat__sprite-image-width": `${width}px` } : {},
|
|
20479
|
+
backgroundImage: `url('${spriteUrl}')`,
|
|
20480
|
+
backgroundPosition: `${x * (100 / (columns - 1))}% ${y * (100 / (rows - 1))}%`,
|
|
20481
|
+
backgroundSize: `${columns * 100}% ${rows * 100}%`,
|
|
20482
|
+
height: "var(--str-chat__sprite-image-height, calc(var(--str-chat__sprite-item-height) * var(--str-chat__sprite-image-resize-ratio)))",
|
|
20483
|
+
width: "var(--str-chat__sprite-image-width, calc(var(--str-chat__sprite-item-width) * var(--str-chat__sprite-image-resize-ratio)))"
|
|
20484
|
+
}
|
|
20485
|
+
}
|
|
20486
|
+
);
|
|
20487
|
+
};
|
|
20488
|
+
const ReactionSelectorWithButton = ({
|
|
20489
|
+
ReactionIcon
|
|
20490
|
+
}) => {
|
|
20491
|
+
const { t } = WithAudioPlayback.useTranslationContext("ReactionSelectorWithButton");
|
|
20492
|
+
const { isMyMessage, message, threadList } = useMessageContext();
|
|
20493
|
+
const { ReactionSelector: ReactionSelector$1 = ReactionSelector } = WithAudioPlayback.useComponentContext();
|
|
20494
|
+
const buttonRef = React.useRef(null);
|
|
20495
|
+
const dialogId2 = ReactionSelector.getDialogId({
|
|
20496
|
+
messageId: message.id,
|
|
20497
|
+
threadList
|
|
20498
|
+
});
|
|
20499
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
20500
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20501
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20503
|
+
DialogAnchor,
|
|
20504
|
+
{
|
|
20505
|
+
dialogManagerId: dialogManager?.id,
|
|
20506
|
+
id: dialogId2,
|
|
20507
|
+
placement: isMyMessage() ? "top-end" : "top-start",
|
|
20508
|
+
referenceElement: buttonRef.current,
|
|
20509
|
+
trapFocus: true,
|
|
20510
|
+
updatePositionOnContentResize: true,
|
|
20511
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactionSelector$1, {})
|
|
20512
|
+
}
|
|
20513
|
+
),
|
|
20514
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20515
|
+
QuickMessageActionsButton,
|
|
20516
|
+
{
|
|
20517
|
+
"aria-expanded": dialogIsOpen,
|
|
20518
|
+
"aria-label": t("aria/Open Reaction Selector"),
|
|
20519
|
+
className: "str-chat__message-reactions-button",
|
|
20520
|
+
"data-testid": "message-reaction-action",
|
|
20521
|
+
onClick: () => dialog?.toggle(),
|
|
20522
|
+
ref: buttonRef,
|
|
20523
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactionIcon, { className: "str-chat__message-action-icon" })
|
|
20524
|
+
}
|
|
20525
|
+
)
|
|
20526
|
+
] });
|
|
20527
|
+
};
|
|
20528
|
+
const getErrorMessage$1 = (error, fallback) => error instanceof Error && error.message ? error.message : fallback;
|
|
20529
|
+
const getNotificationError$1 = (error) => {
|
|
20530
|
+
if (error instanceof Error) return error;
|
|
20531
|
+
if (typeof error === "string") return new Error(error);
|
|
20532
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
20533
|
+
const message = error.message;
|
|
20534
|
+
if (typeof message === "string") return new Error(message);
|
|
20535
|
+
}
|
|
20536
|
+
return void 0;
|
|
20537
|
+
};
|
|
20538
|
+
const RemindMeSubmenuHeader = () => {
|
|
20539
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20540
|
+
const { returnToParentMenu } = useContextMenuContext();
|
|
20541
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContextMenuHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuBackButton, { onClick: returnToParentMenu, children: [
|
|
20542
|
+
/* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconChevronLeft, {}),
|
|
20543
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t("Remind Me") })
|
|
20544
|
+
] }) });
|
|
20545
|
+
};
|
|
20546
|
+
const RemindMeSubmenu = () => {
|
|
20547
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20548
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
20549
|
+
const { message } = useMessageContext();
|
|
20550
|
+
const { closeMenu } = useContextMenuContext();
|
|
20551
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20552
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20553
|
+
"div",
|
|
20554
|
+
{
|
|
20555
|
+
"aria-label": t("aria/Remind Me Options"),
|
|
20556
|
+
className: "str-chat__message-actions-box__submenu",
|
|
20557
|
+
role: "listbox",
|
|
20558
|
+
children: client.reminders.scheduledOffsetsMs.map((offsetMs) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20234
20559
|
ContextMenuButton,
|
|
20235
20560
|
{
|
|
20236
|
-
|
|
20237
|
-
className: msgActionsBoxButtonClassName,
|
|
20238
|
-
Icon: reminder ? WithAudioPlayback.IconBookmarkRemove : WithAudioPlayback.IconBookmark,
|
|
20561
|
+
className: "str-chat__message-actions-list-item-button",
|
|
20239
20562
|
onClick: async () => {
|
|
20240
20563
|
try {
|
|
20241
|
-
|
|
20242
|
-
|
|
20243
|
-
|
|
20244
|
-
context: {
|
|
20245
|
-
message
|
|
20246
|
-
},
|
|
20247
|
-
emitter: "MessageActions",
|
|
20248
|
-
message: t("Remove save for later"),
|
|
20249
|
-
severity: "success",
|
|
20250
|
-
type: "api:message:saveForLater:delete:success"
|
|
20251
|
-
});
|
|
20252
|
-
} else {
|
|
20253
|
-
await client.reminders.createReminder({ messageId: message.id });
|
|
20254
|
-
addNotification({
|
|
20255
|
-
context: {
|
|
20256
|
-
message
|
|
20257
|
-
},
|
|
20258
|
-
emitter: "MessageActions",
|
|
20259
|
-
message: t("Saved for later"),
|
|
20260
|
-
severity: "success",
|
|
20261
|
-
type: "api:message:saveForLater:create:success"
|
|
20262
|
-
});
|
|
20263
|
-
}
|
|
20264
|
-
} catch (error) {
|
|
20265
|
-
addNotification({
|
|
20266
|
-
context: {
|
|
20267
|
-
message
|
|
20268
|
-
},
|
|
20269
|
-
emitter: "MessageActions",
|
|
20270
|
-
error: getNotificationError(error),
|
|
20271
|
-
message: getErrorMessage(
|
|
20272
|
-
error,
|
|
20273
|
-
reminder ? "Error removing message from saved for later" : "Error saving message for later"
|
|
20274
|
-
),
|
|
20275
|
-
severity: "error",
|
|
20276
|
-
type: reminder ? "api:message:saveForLater:delete:failed" : "api:message:saveForLater:create:failed"
|
|
20564
|
+
await client.reminders.upsertReminder({
|
|
20565
|
+
messageId: message.id,
|
|
20566
|
+
remind_at: new Date((/* @__PURE__ */ new Date()).getTime() + offsetMs).toISOString()
|
|
20277
20567
|
});
|
|
20278
|
-
} finally {
|
|
20279
|
-
closeMenu();
|
|
20280
|
-
}
|
|
20281
|
-
},
|
|
20282
|
-
children: reminder ? t("Remove save for later") : t("Save for later")
|
|
20283
|
-
}
|
|
20284
|
-
);
|
|
20285
|
-
},
|
|
20286
|
-
Flag() {
|
|
20287
|
-
const { closeMenu } = useContextMenuContext();
|
|
20288
|
-
const { handleFlag, message } = useMessageContext();
|
|
20289
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20290
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20291
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20292
|
-
ContextMenuButton,
|
|
20293
|
-
{
|
|
20294
|
-
"aria-label": t("aria/Flag Message"),
|
|
20295
|
-
className: msgActionsBoxButtonClassName,
|
|
20296
|
-
Icon: WithAudioPlayback.IconFlag,
|
|
20297
|
-
onClick: async (event) => {
|
|
20298
|
-
try {
|
|
20299
|
-
await handleFlag(event);
|
|
20300
20568
|
addNotification({
|
|
20301
20569
|
context: {
|
|
20302
20570
|
message
|
|
20303
20571
|
},
|
|
20304
20572
|
emitter: "MessageActions",
|
|
20305
|
-
message: t("
|
|
20573
|
+
message: t("Reminder set"),
|
|
20306
20574
|
severity: "success",
|
|
20307
|
-
type: "api:message:
|
|
20575
|
+
type: "api:message:reminder:set:success"
|
|
20308
20576
|
});
|
|
20309
20577
|
} catch (error) {
|
|
20310
20578
|
addNotification({
|
|
@@ -20312,46 +20580,218 @@ const DefaultMessageActionComponents = {
|
|
|
20312
20580
|
message
|
|
20313
20581
|
},
|
|
20314
20582
|
emitter: "MessageActions",
|
|
20315
|
-
error: getNotificationError(error),
|
|
20316
|
-
message: getErrorMessage(error,
|
|
20583
|
+
error: getNotificationError$1(error),
|
|
20584
|
+
message: getErrorMessage$1(error, "Error setting reminder"),
|
|
20317
20585
|
severity: "error",
|
|
20318
|
-
type: "api:message:
|
|
20586
|
+
type: "api:message:reminder:set:failed"
|
|
20319
20587
|
});
|
|
20588
|
+
} finally {
|
|
20589
|
+
closeMenu();
|
|
20320
20590
|
}
|
|
20321
|
-
closeMenu();
|
|
20322
20591
|
},
|
|
20323
|
-
children: t("
|
|
20324
|
-
}
|
|
20325
|
-
|
|
20326
|
-
|
|
20327
|
-
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
|
|
20592
|
+
children: t("duration/Remind Me", { milliseconds: offsetMs })
|
|
20593
|
+
},
|
|
20594
|
+
`reminder-offset-option--${offsetMs}`
|
|
20595
|
+
))
|
|
20596
|
+
}
|
|
20597
|
+
);
|
|
20598
|
+
};
|
|
20599
|
+
const QuickMessageActionsButton = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20600
|
+
WithAudioPlayback.Button,
|
|
20601
|
+
{
|
|
20602
|
+
appearance: "ghost",
|
|
20603
|
+
circular: true,
|
|
20604
|
+
className: clsx("str-chat__message-actions-box-button", className),
|
|
20605
|
+
size: "sm",
|
|
20606
|
+
variant: "secondary",
|
|
20607
|
+
...props
|
|
20608
|
+
}
|
|
20609
|
+
);
|
|
20610
|
+
const DeleteMessageAlert = ({ onCancel, onDelete }) => {
|
|
20611
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20612
|
+
const { close } = useModalContext();
|
|
20613
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20614
|
+
Alert.Root,
|
|
20615
|
+
{
|
|
20616
|
+
className: "str-chat__delete-message-alert",
|
|
20617
|
+
"data-testid": "message-delete-alert",
|
|
20618
|
+
children: [
|
|
20619
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20620
|
+
Alert.Header,
|
|
20621
|
+
{
|
|
20622
|
+
description: t("Are you sure you want to delete this message?"),
|
|
20623
|
+
title: t("Delete message")
|
|
20624
|
+
}
|
|
20625
|
+
),
|
|
20626
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Alert.Actions, { children: [
|
|
20627
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20628
|
+
WithAudioPlayback.Button,
|
|
20629
|
+
{
|
|
20630
|
+
appearance: "outline",
|
|
20631
|
+
className: "str-chat__delete-message-alert__delete-button",
|
|
20632
|
+
"data-testid": "delete-message-alert-delete-button",
|
|
20633
|
+
onClick: onDelete,
|
|
20634
|
+
size: "md",
|
|
20635
|
+
variant: "danger",
|
|
20636
|
+
children: t("Delete message")
|
|
20637
|
+
}
|
|
20638
|
+
),
|
|
20639
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20640
|
+
WithAudioPlayback.Button,
|
|
20641
|
+
{
|
|
20642
|
+
appearance: "outline",
|
|
20643
|
+
className: "str-chat__delete-message-alert__cancel-button",
|
|
20644
|
+
"data-testid": "delete-message-alert-cancel-button",
|
|
20645
|
+
onClick: () => {
|
|
20646
|
+
onCancel();
|
|
20647
|
+
close();
|
|
20648
|
+
},
|
|
20649
|
+
size: "md",
|
|
20650
|
+
variant: "secondary",
|
|
20651
|
+
children: t("Cancel")
|
|
20652
|
+
}
|
|
20653
|
+
)
|
|
20654
|
+
] })
|
|
20655
|
+
]
|
|
20656
|
+
}
|
|
20657
|
+
);
|
|
20658
|
+
};
|
|
20659
|
+
const msgActionsBoxButtonClassName = "str-chat__message-actions-list-item-button";
|
|
20660
|
+
const getErrorMessage = (error, fallback) => error instanceof Error && error.message ? error.message : fallback;
|
|
20661
|
+
const getNotificationError = (error) => {
|
|
20662
|
+
if (error instanceof Error) return error;
|
|
20663
|
+
if (typeof error === "string") return new Error(error);
|
|
20664
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
20665
|
+
const message = error.message;
|
|
20666
|
+
if (typeof message === "string") return new Error(message);
|
|
20667
|
+
}
|
|
20668
|
+
return void 0;
|
|
20669
|
+
};
|
|
20670
|
+
const DefaultMessageActionComponents = {
|
|
20671
|
+
dropdown: {
|
|
20672
|
+
React() {
|
|
20673
|
+
const { ReactionSelector: ReactionSelector$1 = ReactionSelector } = WithAudioPlayback.useComponentContext();
|
|
20674
|
+
const { anchorReferenceElement } = useContextMenuContext();
|
|
20675
|
+
const { isMyMessage, message, threadList } = useMessageContext();
|
|
20676
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20677
|
+
const [referenceElement, setReferenceElement] = React.useState(null);
|
|
20678
|
+
const dialogId2 = `${ReactionSelector.getDialogId({
|
|
20679
|
+
messageId: message.id,
|
|
20680
|
+
threadList
|
|
20681
|
+
})}-dropdown`;
|
|
20682
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
20683
|
+
id: dialogId2
|
|
20684
|
+
});
|
|
20685
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20686
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20687
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20688
|
+
DialogAnchor,
|
|
20689
|
+
{
|
|
20690
|
+
dialogManagerId: dialogManager?.id,
|
|
20691
|
+
id: dialogId2,
|
|
20692
|
+
offset: 8,
|
|
20693
|
+
placement: isMyMessage() ? "top-end" : "top-start",
|
|
20694
|
+
referenceElement,
|
|
20695
|
+
trapFocus: true,
|
|
20696
|
+
updatePositionOnContentResize: true,
|
|
20697
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ReactionSelector$1, { dialogId: dialogId2 })
|
|
20698
|
+
}
|
|
20699
|
+
),
|
|
20700
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20701
|
+
ContextMenuButton,
|
|
20702
|
+
{
|
|
20703
|
+
"aria-expanded": dialogIsOpen,
|
|
20704
|
+
"aria-label": t("aria/Open Reaction Selector"),
|
|
20705
|
+
className: clsx(
|
|
20706
|
+
msgActionsBoxButtonClassName,
|
|
20707
|
+
"str-chat__message-actions-list-item-button--react"
|
|
20708
|
+
),
|
|
20709
|
+
"data-testid": "dropdown-react-action",
|
|
20710
|
+
Icon: WithAudioPlayback.IconEmoji,
|
|
20711
|
+
onClick: (event) => {
|
|
20712
|
+
if (dialogIsOpen) {
|
|
20713
|
+
dialog.close();
|
|
20714
|
+
return;
|
|
20715
|
+
}
|
|
20716
|
+
setReferenceElement(
|
|
20717
|
+
anchorReferenceElement instanceof HTMLElement ? anchorReferenceElement : event.currentTarget
|
|
20718
|
+
);
|
|
20719
|
+
dialog.open();
|
|
20720
|
+
},
|
|
20721
|
+
children: t("Add reaction")
|
|
20722
|
+
}
|
|
20723
|
+
)
|
|
20724
|
+
] });
|
|
20725
|
+
},
|
|
20726
|
+
ThreadReply() {
|
|
20727
|
+
const { closeMenu } = useContextMenuContext();
|
|
20728
|
+
const { handleOpenThread } = useMessageContext();
|
|
20729
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20334
20730
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20335
20731
|
ContextMenuButton,
|
|
20336
20732
|
{
|
|
20337
|
-
"aria-label":
|
|
20733
|
+
"aria-label": t("aria/Open Thread"),
|
|
20338
20734
|
className: msgActionsBoxButtonClassName,
|
|
20339
|
-
|
|
20735
|
+
"data-testid": "thread-action",
|
|
20736
|
+
Icon: WithAudioPlayback.IconThread,
|
|
20737
|
+
onClick: (e) => {
|
|
20738
|
+
handleOpenThread(e);
|
|
20739
|
+
closeMenu();
|
|
20740
|
+
},
|
|
20741
|
+
children: t("Thread Reply")
|
|
20742
|
+
}
|
|
20743
|
+
);
|
|
20744
|
+
},
|
|
20745
|
+
Quote() {
|
|
20746
|
+
const { closeMenu } = useContextMenuContext();
|
|
20747
|
+
const { message } = useMessageContext();
|
|
20748
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20749
|
+
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
20750
|
+
const handleQuote = () => {
|
|
20751
|
+
messageComposer.setQuotedMessage(message);
|
|
20752
|
+
const elements = message.parent_id ? document.querySelectorAll(".str-chat__thread .str-chat__textarea__textarea") : document.getElementsByClassName("str-chat__textarea__textarea");
|
|
20753
|
+
const textarea = elements.item(0);
|
|
20754
|
+
if (textarea instanceof HTMLTextAreaElement) {
|
|
20755
|
+
textarea.focus();
|
|
20756
|
+
}
|
|
20757
|
+
};
|
|
20758
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20759
|
+
ContextMenuButton,
|
|
20760
|
+
{
|
|
20761
|
+
"aria-label": t("aria/Quote Message"),
|
|
20762
|
+
className: msgActionsBoxButtonClassName,
|
|
20763
|
+
Icon: WithAudioPlayback.IconQuote,
|
|
20764
|
+
onClick: () => {
|
|
20765
|
+
handleQuote();
|
|
20766
|
+
closeMenu();
|
|
20767
|
+
},
|
|
20768
|
+
children: t("Quote Reply")
|
|
20769
|
+
}
|
|
20770
|
+
);
|
|
20771
|
+
},
|
|
20772
|
+
Pin() {
|
|
20773
|
+
const { closeMenu } = useContextMenuContext();
|
|
20774
|
+
const { handlePin, message } = useMessageContext();
|
|
20775
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20776
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20777
|
+
const isPinned = !!message.pinned;
|
|
20778
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20779
|
+
ContextMenuButton,
|
|
20780
|
+
{
|
|
20781
|
+
"aria-label": isPinned ? t("aria/Unpin Message") : t("aria/Pin Message"),
|
|
20782
|
+
className: msgActionsBoxButtonClassName,
|
|
20783
|
+
Icon: isPinned ? WithAudioPlayback.IconUnpin : WithAudioPlayback.IconPin,
|
|
20340
20784
|
onClick: async (event) => {
|
|
20341
20785
|
try {
|
|
20342
|
-
await
|
|
20786
|
+
await handlePin(event);
|
|
20343
20787
|
addNotification({
|
|
20344
20788
|
context: {
|
|
20345
20789
|
message
|
|
20346
20790
|
},
|
|
20347
20791
|
emitter: "MessageActions",
|
|
20348
|
-
message:
|
|
20349
|
-
user: message.user?.name || message.user?.id
|
|
20350
|
-
}) : t("{{ user }} has been muted", {
|
|
20351
|
-
user: message.user?.name || message.user?.id
|
|
20352
|
-
}),
|
|
20792
|
+
message: isPinned ? t("Message unpinned") : t("Message pinned"),
|
|
20353
20793
|
severity: "success",
|
|
20354
|
-
type:
|
|
20794
|
+
type: isPinned ? "api:message:unpin:success" : "api:message:pin:success"
|
|
20355
20795
|
});
|
|
20356
20796
|
} catch (error) {
|
|
20357
20797
|
addNotification({
|
|
@@ -20362,818 +20802,553 @@ const DefaultMessageActionComponents = {
|
|
|
20362
20802
|
error: getNotificationError(error),
|
|
20363
20803
|
message: getErrorMessage(
|
|
20364
20804
|
error,
|
|
20365
|
-
|
|
20805
|
+
isPinned ? t("Error removing message pin") : t("Error pinning message")
|
|
20366
20806
|
),
|
|
20367
20807
|
severity: "error",
|
|
20368
|
-
type:
|
|
20808
|
+
type: isPinned ? "api:message:unpin:failed" : "api:message:pin:failed"
|
|
20369
20809
|
});
|
|
20370
20810
|
}
|
|
20371
20811
|
closeMenu();
|
|
20372
20812
|
},
|
|
20373
|
-
children:
|
|
20813
|
+
children: isPinned ? t("Unpin") : t("Pin")
|
|
20374
20814
|
}
|
|
20375
20815
|
);
|
|
20376
20816
|
},
|
|
20377
|
-
|
|
20378
|
-
const { closeMenu } = useContextMenuContext();
|
|
20379
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20380
|
-
const { Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
20381
|
-
const { handleDelete, message } = useMessageContext();
|
|
20382
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20383
|
-
const [openModal, setOpenModal] = React.useState(false);
|
|
20384
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20385
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20386
|
-
ContextMenuButton,
|
|
20387
|
-
{
|
|
20388
|
-
"aria-label": t("aria/Delete Message"),
|
|
20389
|
-
className: msgActionsBoxButtonClassName,
|
|
20390
|
-
Icon: WithAudioPlayback.IconDelete,
|
|
20391
|
-
onClick: () => {
|
|
20392
|
-
setOpenModal(true);
|
|
20393
|
-
},
|
|
20394
|
-
variant: "destructive",
|
|
20395
|
-
children: t("Delete message")
|
|
20396
|
-
}
|
|
20397
|
-
),
|
|
20398
|
-
/* @__PURE__ */ jsxRuntime.jsx(Modal, { open: openModal, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20399
|
-
DeleteMessageAlert,
|
|
20400
|
-
{
|
|
20401
|
-
onCancel: () => {
|
|
20402
|
-
setOpenModal(false);
|
|
20403
|
-
closeMenu();
|
|
20404
|
-
},
|
|
20405
|
-
onDelete: async () => {
|
|
20406
|
-
try {
|
|
20407
|
-
await handleDelete();
|
|
20408
|
-
addNotification({
|
|
20409
|
-
context: {
|
|
20410
|
-
message
|
|
20411
|
-
},
|
|
20412
|
-
emitter: "MessageActions",
|
|
20413
|
-
message: t("Message deleted"),
|
|
20414
|
-
severity: "success",
|
|
20415
|
-
type: "api:message:delete:success"
|
|
20416
|
-
});
|
|
20417
|
-
} catch (error) {
|
|
20418
|
-
addNotification({
|
|
20419
|
-
context: {
|
|
20420
|
-
message
|
|
20421
|
-
},
|
|
20422
|
-
emitter: "MessageActions",
|
|
20423
|
-
error: getNotificationError(error),
|
|
20424
|
-
message: getErrorMessage(error, t("Error deleting message")),
|
|
20425
|
-
severity: "error",
|
|
20426
|
-
type: "api:message:delete:failed"
|
|
20427
|
-
});
|
|
20428
|
-
} finally {
|
|
20429
|
-
setOpenModal(false);
|
|
20430
|
-
closeMenu();
|
|
20431
|
-
}
|
|
20432
|
-
}
|
|
20433
|
-
}
|
|
20434
|
-
) })
|
|
20435
|
-
] });
|
|
20436
|
-
},
|
|
20437
|
-
BlockUser() {
|
|
20817
|
+
CopyMessageText() {
|
|
20438
20818
|
const { closeMenu } = useContextMenuContext();
|
|
20439
|
-
const { client } = WithAudioPlayback.useChatContext();
|
|
20440
20819
|
const { message } = useMessageContext();
|
|
20441
20820
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20442
|
-
const isBlocked = !message.user?.id || new Set(client.blockedUsers.getLatestValue().userIds).has(message.user?.id);
|
|
20443
20821
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20444
20822
|
ContextMenuButton,
|
|
20445
20823
|
{
|
|
20446
|
-
"aria-label":
|
|
20447
|
-
className:
|
|
20448
|
-
Icon:
|
|
20824
|
+
"aria-label": t("aria/Copy Message Text"),
|
|
20825
|
+
className: msgActionsBoxButtonClassName,
|
|
20826
|
+
Icon: WithAudioPlayback.IconCopy,
|
|
20449
20827
|
onClick: () => {
|
|
20450
|
-
|
|
20451
|
-
if (targetId) {
|
|
20452
|
-
if (isBlocked) client.unBlockUser(targetId);
|
|
20453
|
-
else client.blockUser(targetId);
|
|
20454
|
-
}
|
|
20828
|
+
if (message.text) navigator.clipboard.writeText(message.text);
|
|
20455
20829
|
closeMenu();
|
|
20456
20830
|
},
|
|
20457
|
-
children:
|
|
20831
|
+
children: t("Copy Message")
|
|
20458
20832
|
}
|
|
20459
20833
|
);
|
|
20460
|
-
}
|
|
20461
|
-
|
|
20462
|
-
|
|
20463
|
-
|
|
20464
|
-
DropdownToggle: React.forwardRef((_, ref) => {
|
|
20834
|
+
},
|
|
20835
|
+
Resend() {
|
|
20836
|
+
const { closeMenu } = useContextMenuContext();
|
|
20837
|
+
const { handleRetry, message } = useMessageContext();
|
|
20465
20838
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20466
|
-
const { message } = useMessageContext();
|
|
20467
|
-
const dropdownDialogIsOpen = useDialogIsOpen(
|
|
20468
|
-
MessageActions.getDialogId({ messageId: message.id })
|
|
20469
|
-
);
|
|
20470
|
-
const { dialog } = useDialogOnNearestManager({
|
|
20471
|
-
id: MessageActions.getDialogId({ messageId: message.id })
|
|
20472
|
-
});
|
|
20473
20839
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20474
|
-
|
|
20840
|
+
ContextMenuButton,
|
|
20475
20841
|
{
|
|
20476
|
-
"aria-
|
|
20477
|
-
|
|
20478
|
-
|
|
20479
|
-
className: "str-chat__message-actions-box-button",
|
|
20480
|
-
"data-testid": "message-actions-toggle-button",
|
|
20842
|
+
"aria-label": t("aria/Resend Message"),
|
|
20843
|
+
className: msgActionsBoxButtonClassName,
|
|
20844
|
+
Icon: WithAudioPlayback.IconRetry,
|
|
20481
20845
|
onClick: () => {
|
|
20482
|
-
|
|
20846
|
+
handleRetry(message);
|
|
20847
|
+
closeMenu();
|
|
20483
20848
|
},
|
|
20484
|
-
|
|
20485
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMore, { className: "str-chat__message-action-icon" })
|
|
20849
|
+
children: t("Resend")
|
|
20486
20850
|
}
|
|
20487
20851
|
);
|
|
20488
|
-
}),
|
|
20489
|
-
React() {
|
|
20490
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ReactionSelectorWithButton, { ReactionIcon: WithAudioPlayback.IconEmoji });
|
|
20491
20852
|
},
|
|
20492
|
-
|
|
20493
|
-
const
|
|
20853
|
+
Edit() {
|
|
20854
|
+
const messageComposer = WithAudioPlayback.useMessageComposerController();
|
|
20855
|
+
const { message } = useMessageContext();
|
|
20494
20856
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20857
|
+
const { closeMenu } = useContextMenuContext();
|
|
20495
20858
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20496
|
-
|
|
20859
|
+
ContextMenuButton,
|
|
20497
20860
|
{
|
|
20498
|
-
"aria-label": t("aria/
|
|
20499
|
-
className:
|
|
20500
|
-
|
|
20501
|
-
onClick:
|
|
20502
|
-
|
|
20861
|
+
"aria-label": t("aria/Edit Message"),
|
|
20862
|
+
className: msgActionsBoxButtonClassName,
|
|
20863
|
+
Icon: WithAudioPlayback.IconEdit,
|
|
20864
|
+
onClick: () => {
|
|
20865
|
+
savePreEditSnapshot(messageComposer);
|
|
20866
|
+
messageComposer.initState({ composition: message });
|
|
20867
|
+
closeMenu();
|
|
20868
|
+
},
|
|
20869
|
+
children: t("Edit Message")
|
|
20503
20870
|
}
|
|
20504
20871
|
);
|
|
20505
|
-
}
|
|
20506
|
-
|
|
20507
|
-
};
|
|
20508
|
-
const
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
|
|
20512
|
-
|
|
20513
|
-
|
|
20514
|
-
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
|
|
20543
|
-
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
Component: DefaultMessageActionComponents.dropdown.Edit,
|
|
20550
|
-
placement: "dropdown",
|
|
20551
|
-
type: "edit"
|
|
20552
|
-
},
|
|
20553
|
-
{
|
|
20554
|
-
Component: DefaultMessageActionComponents.dropdown.MarkUnread,
|
|
20555
|
-
placement: "dropdown",
|
|
20556
|
-
type: "markUnread"
|
|
20557
|
-
},
|
|
20558
|
-
{
|
|
20559
|
-
Component: DefaultMessageActionComponents.dropdown.RemindMe,
|
|
20560
|
-
placement: "dropdown",
|
|
20561
|
-
type: "remindMe"
|
|
20562
|
-
},
|
|
20563
|
-
{
|
|
20564
|
-
Component: DefaultMessageActionComponents.dropdown.SaveForLater,
|
|
20565
|
-
placement: "dropdown",
|
|
20566
|
-
type: "saveForLater"
|
|
20567
|
-
},
|
|
20568
|
-
{
|
|
20569
|
-
Component: DefaultMessageActionComponents.dropdown.Flag,
|
|
20570
|
-
placement: "dropdown",
|
|
20571
|
-
type: "flag"
|
|
20572
|
-
},
|
|
20573
|
-
{
|
|
20574
|
-
Component: DefaultMessageActionComponents.dropdown.Mute,
|
|
20575
|
-
placement: "dropdown",
|
|
20576
|
-
type: "mute"
|
|
20577
|
-
},
|
|
20578
|
-
{
|
|
20579
|
-
Component: DefaultMessageActionComponents.dropdown.Delete,
|
|
20580
|
-
placement: "dropdown",
|
|
20581
|
-
type: "delete"
|
|
20582
|
-
},
|
|
20583
|
-
{
|
|
20584
|
-
Component: DefaultMessageActionComponents.dropdown.BlockUser,
|
|
20585
|
-
placement: "dropdown",
|
|
20586
|
-
type: "blockUser"
|
|
20587
|
-
}
|
|
20588
|
-
];
|
|
20589
|
-
function useFetchReactions(options) {
|
|
20590
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20591
|
-
const { handleFetchReactions: contextHandleFetchReactions } = useMessageContext();
|
|
20592
|
-
const { t } = WithAudioPlayback.useTranslationContext("useFetchReactions");
|
|
20593
|
-
const [reactions, setReactions] = React.useState([]);
|
|
20594
|
-
const {
|
|
20595
|
-
handleFetchReactions: propHandleFetchReactions,
|
|
20596
|
-
reactionType,
|
|
20597
|
-
shouldFetch,
|
|
20598
|
-
sort
|
|
20599
|
-
} = options;
|
|
20600
|
-
const [isLoading, setIsLoading] = React.useState(shouldFetch);
|
|
20601
|
-
const handleFetchReactions = propHandleFetchReactions ?? contextHandleFetchReactions;
|
|
20602
|
-
const [refetchNonce, setRefetchNonce] = React.useState(null);
|
|
20603
|
-
React.useEffect(() => {
|
|
20604
|
-
if (!shouldFetch) {
|
|
20605
|
-
return;
|
|
20606
|
-
}
|
|
20607
|
-
let cancel = false;
|
|
20608
|
-
(async () => {
|
|
20609
|
-
try {
|
|
20610
|
-
setIsLoading(true);
|
|
20611
|
-
const reactions2 = await handleFetchReactions(reactionType ?? void 0, sort);
|
|
20612
|
-
if (!cancel) {
|
|
20613
|
-
setReactions(reactions2);
|
|
20614
|
-
}
|
|
20615
|
-
} catch (e) {
|
|
20616
|
-
if (!cancel) {
|
|
20617
|
-
setReactions([]);
|
|
20618
|
-
addNotification({
|
|
20619
|
-
emitter: "Reactions",
|
|
20620
|
-
error: e instanceof Error ? e : void 0,
|
|
20621
|
-
message: t("Error fetching reactions"),
|
|
20622
|
-
severity: "error",
|
|
20623
|
-
type: "api:message:reactions:fetch:failed"
|
|
20624
|
-
});
|
|
20625
|
-
}
|
|
20626
|
-
} finally {
|
|
20627
|
-
if (!cancel) {
|
|
20628
|
-
setIsLoading(false);
|
|
20872
|
+
},
|
|
20873
|
+
MarkUnread() {
|
|
20874
|
+
const { closeMenu } = useContextMenuContext();
|
|
20875
|
+
const { handleMarkUnread, message } = useMessageContext();
|
|
20876
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20877
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20878
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20879
|
+
ContextMenuButton,
|
|
20880
|
+
{
|
|
20881
|
+
"aria-label": t("aria/Mark Message Unread"),
|
|
20882
|
+
className: msgActionsBoxButtonClassName,
|
|
20883
|
+
Icon: WithAudioPlayback.IconNotification,
|
|
20884
|
+
onClick: async (event) => {
|
|
20885
|
+
try {
|
|
20886
|
+
await handleMarkUnread(event);
|
|
20887
|
+
addNotification({
|
|
20888
|
+
context: {
|
|
20889
|
+
message
|
|
20890
|
+
},
|
|
20891
|
+
emitter: "MessageActions",
|
|
20892
|
+
message: t("Message marked as unread"),
|
|
20893
|
+
severity: "success",
|
|
20894
|
+
type: "api:message:markUnread:success"
|
|
20895
|
+
});
|
|
20896
|
+
} catch (error) {
|
|
20897
|
+
addNotification({
|
|
20898
|
+
context: {
|
|
20899
|
+
message
|
|
20900
|
+
},
|
|
20901
|
+
emitter: "MessageActions",
|
|
20902
|
+
error: getNotificationError(error),
|
|
20903
|
+
message: getErrorMessage(
|
|
20904
|
+
error,
|
|
20905
|
+
t(
|
|
20906
|
+
"Error marking message unread. Cannot mark unread messages older than the newest 100 channel messages."
|
|
20907
|
+
)
|
|
20908
|
+
),
|
|
20909
|
+
severity: "error",
|
|
20910
|
+
type: "api:message:markUnread:failed"
|
|
20911
|
+
});
|
|
20912
|
+
}
|
|
20913
|
+
closeMenu();
|
|
20914
|
+
},
|
|
20915
|
+
children: t("Mark as unread")
|
|
20629
20916
|
}
|
|
20630
|
-
|
|
20631
|
-
}
|
|
20632
|
-
|
|
20633
|
-
|
|
20634
|
-
|
|
20635
|
-
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20640
|
-
|
|
20641
|
-
|
|
20642
|
-
|
|
20643
|
-
|
|
20644
|
-
|
|
20645
|
-
|
|
20646
|
-
|
|
20647
|
-
|
|
20648
|
-
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
|
|
20652
|
-
|
|
20653
|
-
|
|
20654
|
-
|
|
20655
|
-
] }, index)),
|
|
20656
|
-
[]
|
|
20657
|
-
);
|
|
20658
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: elements });
|
|
20659
|
-
};
|
|
20660
|
-
const MessageReactionsDetail = ({
|
|
20661
|
-
handleFetchReactions,
|
|
20662
|
-
handleReaction,
|
|
20663
|
-
onSelectedReactionTypeChange,
|
|
20664
|
-
own_reactions,
|
|
20665
|
-
reactionDetailsSort: propReactionDetailsSort,
|
|
20666
|
-
reactionGroups,
|
|
20667
|
-
reactions,
|
|
20668
|
-
selectedReactionType,
|
|
20669
|
-
totalReactionCount
|
|
20670
|
-
}) => {
|
|
20671
|
-
const [extendedReactionListOpen, setExtendedReactionListOpen] = React.useState(false);
|
|
20672
|
-
const { client } = WithAudioPlayback.useChatContext();
|
|
20673
|
-
const {
|
|
20674
|
-
Avatar: Avatar$1 = Avatar,
|
|
20675
|
-
LoadingIndicator: LoadingIndicator2 = MessageReactionsDetailLoadingIndicator,
|
|
20676
|
-
reactionOptions = defaultReactionOptions,
|
|
20677
|
-
ReactionSelectorExtendedList: ReactionSelectorExtendedList2 = ReactionSelector.ExtendedList
|
|
20678
|
-
} = WithAudioPlayback.useComponentContext(MessageReactionsDetail.name);
|
|
20679
|
-
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20680
|
-
const {
|
|
20681
|
-
handleReaction: contextHandleReaction,
|
|
20682
|
-
message,
|
|
20683
|
-
reactionDetailsSort: contextReactionDetailsSort
|
|
20684
|
-
} = useMessageContext(MessageReactionsDetail.name);
|
|
20685
|
-
const reactionDetailsSort = propReactionDetailsSort ?? contextReactionDetailsSort ?? defaultReactionDetailsSort;
|
|
20686
|
-
const {
|
|
20687
|
-
isLoading: areReactionsLoading,
|
|
20688
|
-
reactions: reactionDetails,
|
|
20689
|
-
refetch
|
|
20690
|
-
} = useFetchReactions({
|
|
20691
|
-
handleFetchReactions,
|
|
20692
|
-
reactionType: selectedReactionType,
|
|
20693
|
-
shouldFetch: true,
|
|
20694
|
-
sort: reactionDetailsSort
|
|
20695
|
-
});
|
|
20696
|
-
if (extendedReactionListOpen) {
|
|
20697
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20698
|
-
"div",
|
|
20699
|
-
{
|
|
20700
|
-
className: "str-chat__message-reactions-detail",
|
|
20701
|
-
"data-testid": "message-reactions-detail",
|
|
20702
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20703
|
-
ReactionSelectorExtendedList2,
|
|
20704
|
-
{
|
|
20705
|
-
dialogId: MessageReactionsDetail.getDialogId({ messageId: message.id }),
|
|
20706
|
-
handleReaction,
|
|
20707
|
-
own_reactions
|
|
20708
|
-
}
|
|
20709
|
-
)
|
|
20710
|
-
}
|
|
20711
|
-
);
|
|
20712
|
-
}
|
|
20713
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20714
|
-
"div",
|
|
20715
|
-
{
|
|
20716
|
-
className: "str-chat__message-reactions-detail",
|
|
20717
|
-
"data-testid": "message-reactions-detail",
|
|
20718
|
-
children: [
|
|
20719
|
-
typeof totalReactionCount === "number" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__total-count", children: t("{{ count }} reactions", { count: totalReactionCount }) }),
|
|
20720
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "str-chat__message-reactions-detail__reaction-type-list-container", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20721
|
-
"ul",
|
|
20722
|
-
{
|
|
20723
|
-
className: "str-chat__message-reactions-detail__reaction-type-list",
|
|
20724
|
-
"data-testid": "reaction-type-list",
|
|
20725
|
-
children: [
|
|
20726
|
-
/* @__PURE__ */ jsxRuntime.jsx("li", { className: "str-chat__message-reactions-detail__reaction-type-list-item", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20727
|
-
"button",
|
|
20728
|
-
{
|
|
20729
|
-
"aria-label": t("Add reaction"),
|
|
20730
|
-
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20731
|
-
"data-testid": "add-reaction-button",
|
|
20732
|
-
onClick: () => setExtendedReactionListOpen(true),
|
|
20733
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconEmojiAdd, {}) })
|
|
20734
|
-
}
|
|
20735
|
-
) }),
|
|
20736
|
-
reactions.map(
|
|
20737
|
-
({ EmojiComponent, reactionCount, reactionType }) => EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20738
|
-
"li",
|
|
20739
|
-
{
|
|
20740
|
-
className: "str-chat__message-reactions-detail__reaction-type-list-item",
|
|
20741
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20742
|
-
"button",
|
|
20743
|
-
{
|
|
20744
|
-
"aria-pressed": reactionType === selectedReactionType,
|
|
20745
|
-
className: "str-chat__message-reactions-detail__reaction-type-list-item-button",
|
|
20746
|
-
onClick: () => onSelectedReactionTypeChange?.(
|
|
20747
|
-
selectedReactionType === reactionType ? null : reactionType
|
|
20748
|
-
),
|
|
20749
|
-
children: [
|
|
20750
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__reaction-type-list-item-icon", children: /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) }),
|
|
20751
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20752
|
-
"span",
|
|
20753
|
-
{
|
|
20754
|
-
className: "str-chat__message-reactions-detail__reaction-type-list-item-count",
|
|
20755
|
-
"data-testid": "reaction-type-count",
|
|
20756
|
-
children: reactionCount
|
|
20757
|
-
}
|
|
20758
|
-
)
|
|
20759
|
-
]
|
|
20760
|
-
}
|
|
20761
|
-
)
|
|
20917
|
+
);
|
|
20918
|
+
},
|
|
20919
|
+
RemindMe() {
|
|
20920
|
+
const { closeMenu, openSubmenu } = useContextMenuContext();
|
|
20921
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
20922
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20923
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20924
|
+
const { message } = useMessageContext();
|
|
20925
|
+
const reminder = useMessageReminder(message.id);
|
|
20926
|
+
const messageAlreadyBookmarked = reminder && !reminder?.remindAt;
|
|
20927
|
+
if (messageAlreadyBookmarked) return null;
|
|
20928
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20929
|
+
ContextMenuButton,
|
|
20930
|
+
{
|
|
20931
|
+
"aria-label": reminder ? t("aria/Remind Me Message") : t("aria/Remove Reminder"),
|
|
20932
|
+
className: msgActionsBoxButtonClassName,
|
|
20933
|
+
hasSubMenu: !reminder,
|
|
20934
|
+
Icon: reminder ? WithAudioPlayback.IconBellOff : WithAudioPlayback.IconBell,
|
|
20935
|
+
onClick: async () => {
|
|
20936
|
+
if (reminder) {
|
|
20937
|
+
try {
|
|
20938
|
+
await client.reminders.deleteReminder(reminder.id);
|
|
20939
|
+
addNotification({
|
|
20940
|
+
context: {
|
|
20941
|
+
message
|
|
20762
20942
|
},
|
|
20763
|
-
|
|
20764
|
-
|
|
20765
|
-
|
|
20766
|
-
|
|
20767
|
-
|
|
20768
|
-
|
|
20769
|
-
|
|
20770
|
-
|
|
20771
|
-
|
|
20772
|
-
className: "str-chat__message-reactions-detail__user-list",
|
|
20773
|
-
"data-testid": "all-reacting-users",
|
|
20774
|
-
children: [
|
|
20775
|
-
areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(LoadingIndicator2, {}),
|
|
20776
|
-
!areReactionsLoading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: reactionDetails.map(({ type, user }) => {
|
|
20777
|
-
const belongsToCurrentUser = client.user?.id === user?.id;
|
|
20778
|
-
const EmojiComponent = Array.isArray(reactionOptions) ? void 0 : reactionOptions.quick[type]?.Component ?? reactionOptions.extended?.[type]?.Component;
|
|
20779
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20780
|
-
"div",
|
|
20781
|
-
{
|
|
20782
|
-
className: "str-chat__message-reactions-detail__user-list-item",
|
|
20783
|
-
children: [
|
|
20784
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20785
|
-
Avatar$1,
|
|
20786
|
-
{
|
|
20787
|
-
className: "str-chat__avatar--with-border",
|
|
20788
|
-
"data-testid": "avatar",
|
|
20789
|
-
imageUrl: user?.image,
|
|
20790
|
-
size: "md",
|
|
20791
|
-
userName: user?.name || user?.id
|
|
20792
|
-
}
|
|
20793
|
-
),
|
|
20794
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "str-chat__message-reactions-detail__user-list-item-info", children: [
|
|
20795
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20796
|
-
"span",
|
|
20797
|
-
{
|
|
20798
|
-
className: "str-chat__message-reactions-detail__user-list-item-username",
|
|
20799
|
-
"data-testid": "reaction-user-username",
|
|
20800
|
-
children: belongsToCurrentUser ? t("You") : user?.name || user?.id
|
|
20801
|
-
}
|
|
20802
|
-
),
|
|
20803
|
-
belongsToCurrentUser && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20804
|
-
"button",
|
|
20805
|
-
{
|
|
20806
|
-
className: "str-chat__message-reactions-detail__user-list-item-button",
|
|
20807
|
-
"data-testid": "remove-reaction-button",
|
|
20808
|
-
onClick: async (e) => {
|
|
20809
|
-
const reactionCountBeforeRemoval = reactionGroups?.[type]?.count ?? 0;
|
|
20810
|
-
await contextHandleReaction(type, e);
|
|
20811
|
-
if (selectedReactionType !== null && reactionCountBeforeRemoval <= 1) {
|
|
20812
|
-
onSelectedReactionTypeChange?.(null);
|
|
20813
|
-
} else {
|
|
20814
|
-
refetch();
|
|
20815
|
-
}
|
|
20816
|
-
},
|
|
20817
|
-
children: t("Tap to remove")
|
|
20818
|
-
}
|
|
20819
|
-
)
|
|
20820
|
-
] }),
|
|
20821
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "str-chat__message-reactions-detail__user-list-item-icon", children: !selectedReactionType && EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {}) })
|
|
20822
|
-
]
|
|
20943
|
+
emitter: "MessageActions",
|
|
20944
|
+
message: t("Remove reminder"),
|
|
20945
|
+
severity: "success",
|
|
20946
|
+
type: "api:message:reminder:delete:success"
|
|
20947
|
+
});
|
|
20948
|
+
} catch (error) {
|
|
20949
|
+
addNotification({
|
|
20950
|
+
context: {
|
|
20951
|
+
message
|
|
20823
20952
|
},
|
|
20824
|
-
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
|
|
20829
|
-
|
|
20830
|
-
|
|
20831
|
-
|
|
20832
|
-
|
|
20833
|
-
}
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
20838
|
-
|
|
20839
|
-
|
|
20840
|
-
|
|
20841
|
-
};
|
|
20842
|
-
const useProcessReactions = (params) => {
|
|
20843
|
-
const {
|
|
20844
|
-
own_reactions: propOwnReactions,
|
|
20845
|
-
reaction_groups: propReactionGroups,
|
|
20846
|
-
reactions: propReactions,
|
|
20847
|
-
sortReactions: propSortReactions
|
|
20848
|
-
} = params;
|
|
20849
|
-
const { message, sortReactions: contextSortReactions } = useMessageContext();
|
|
20850
|
-
const { reactionOptions = defaultReactionOptions } = WithAudioPlayback.useComponentContext();
|
|
20851
|
-
const sortReactions = propSortReactions ?? contextSortReactions ?? defaultReactionsSort;
|
|
20852
|
-
const latestReactions = propReactions ?? message.latest_reactions;
|
|
20853
|
-
const ownReactions = propOwnReactions ?? message?.own_reactions;
|
|
20854
|
-
const reactionGroups = propReactionGroups ?? message?.reaction_groups ?? void 0;
|
|
20855
|
-
const isOwnReaction = React.useCallback(
|
|
20856
|
-
(reactionType) => ownReactions?.some((reaction) => reaction.type === reactionType) ?? false,
|
|
20857
|
-
[ownReactions]
|
|
20858
|
-
);
|
|
20859
|
-
const getEmojiByReactionType = React.useCallback(
|
|
20860
|
-
(reactionType) => {
|
|
20861
|
-
if (Array.isArray(reactionOptions)) {
|
|
20862
|
-
return reactionOptions.find(({ type }) => type === reactionType)?.Component ?? null;
|
|
20863
|
-
}
|
|
20864
|
-
return reactionOptions.quick[reactionType]?.Component ?? reactionOptions.extended?.[reactionType]?.Component ?? null;
|
|
20865
|
-
},
|
|
20866
|
-
[reactionOptions]
|
|
20867
|
-
);
|
|
20868
|
-
const isSupportedReaction = React.useCallback(
|
|
20869
|
-
(reactionType) => {
|
|
20870
|
-
if (Array.isArray(reactionOptions)) {
|
|
20871
|
-
return reactionOptions.some(
|
|
20872
|
-
(reactionOption) => reactionOption.type === reactionType
|
|
20873
|
-
);
|
|
20874
|
-
}
|
|
20875
|
-
return typeof reactionOptions.quick[reactionType] !== "undefined" || typeof reactionOptions.extended?.[reactionType] !== "undefined";
|
|
20876
|
-
},
|
|
20877
|
-
[reactionOptions]
|
|
20878
|
-
);
|
|
20879
|
-
const uniqueReactionTypeCount = React.useMemo(() => {
|
|
20880
|
-
if (!reactionGroups) {
|
|
20881
|
-
return 0;
|
|
20882
|
-
}
|
|
20883
|
-
return Object.keys(reactionGroups).filter(
|
|
20884
|
-
(reactionType) => isSupportedReaction(reactionType)
|
|
20885
|
-
).length;
|
|
20886
|
-
}, [isSupportedReaction, reactionGroups]);
|
|
20887
|
-
const getLatestReactedUserNames = React.useCallback(
|
|
20888
|
-
(reactionType) => latestReactions?.flatMap((reaction) => {
|
|
20889
|
-
if (reactionType && reactionType === reaction.type) {
|
|
20890
|
-
const username = reaction.user?.name || reaction.user?.id;
|
|
20891
|
-
return username ? [username] : [];
|
|
20892
|
-
}
|
|
20893
|
-
return [];
|
|
20894
|
-
}) ?? [],
|
|
20895
|
-
[latestReactions]
|
|
20896
|
-
);
|
|
20897
|
-
const existingReactions = React.useMemo(() => {
|
|
20898
|
-
if (!reactionGroups) {
|
|
20899
|
-
return [];
|
|
20900
|
-
}
|
|
20901
|
-
const unsortedReactions = Object.entries(reactionGroups).flatMap(
|
|
20902
|
-
([reactionType, { count, first_reaction_at, last_reaction_at }]) => {
|
|
20903
|
-
if (count === 0 || !isSupportedReaction(reactionType)) {
|
|
20904
|
-
return [];
|
|
20953
|
+
emitter: "MessageActions",
|
|
20954
|
+
error: getNotificationError(error),
|
|
20955
|
+
message: getErrorMessage(error, "Error removing reminder"),
|
|
20956
|
+
severity: "error",
|
|
20957
|
+
type: "api:message:reminder:delete:failed"
|
|
20958
|
+
});
|
|
20959
|
+
} finally {
|
|
20960
|
+
closeMenu();
|
|
20961
|
+
}
|
|
20962
|
+
} else {
|
|
20963
|
+
openSubmenu({
|
|
20964
|
+
Header: RemindMeSubmenuHeader,
|
|
20965
|
+
Submenu: RemindMeSubmenu
|
|
20966
|
+
});
|
|
20967
|
+
}
|
|
20968
|
+
},
|
|
20969
|
+
children: reminder ? t("Remove reminder") : t("Remind me")
|
|
20905
20970
|
}
|
|
20906
|
-
|
|
20907
|
-
|
|
20908
|
-
|
|
20909
|
-
|
|
20910
|
-
|
|
20911
|
-
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
|
|
20925
|
-
|
|
20926
|
-
|
|
20927
|
-
|
|
20928
|
-
|
|
20929
|
-
|
|
20930
|
-
|
|
20931
|
-
|
|
20932
|
-
|
|
20933
|
-
|
|
20934
|
-
|
|
20935
|
-
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
|
|
20939
|
-
|
|
20940
|
-
|
|
20941
|
-
|
|
20942
|
-
|
|
20943
|
-
|
|
20944
|
-
|
|
20945
|
-
|
|
20946
|
-
|
|
20947
|
-
}
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
}
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
reactionDetailsSort,
|
|
20959
|
-
verticalPosition = "top",
|
|
20960
|
-
visualStyle = "clustered",
|
|
20961
|
-
...rest
|
|
20962
|
-
} = props;
|
|
20963
|
-
const {
|
|
20964
|
-
existingReactions,
|
|
20965
|
-
hasReactions,
|
|
20966
|
-
reactionGroups,
|
|
20967
|
-
totalReactionCount,
|
|
20968
|
-
uniqueReactionTypeCount
|
|
20969
|
-
} = useProcessReactions(rest);
|
|
20970
|
-
const [selectedReactionType, setSelectedReactionType] = React.useState(
|
|
20971
|
-
null
|
|
20972
|
-
);
|
|
20973
|
-
const { t } = WithAudioPlayback.useTranslationContext("MessageReactions");
|
|
20974
|
-
const { MessageReactionsDetail: MessageReactionsDetail$1 = MessageReactionsDetail } = WithAudioPlayback.useComponentContext();
|
|
20975
|
-
const { isMyMessage, message } = useMessageContext();
|
|
20976
|
-
const divRef = React.useRef(null);
|
|
20977
|
-
const dialogId2 = MessageReactionsDetail.getDialogId({
|
|
20978
|
-
messageId: message.id
|
|
20979
|
-
});
|
|
20980
|
-
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
20981
|
-
const isDialogOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
20982
|
-
const handleReactionButtonClick = (reactionType) => {
|
|
20983
|
-
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
|
|
20984
|
-
return;
|
|
20985
|
-
}
|
|
20986
|
-
setSelectedReactionType(reactionType);
|
|
20987
|
-
dialog.open();
|
|
20988
|
-
};
|
|
20989
|
-
const cappedExistingReactions = React.useMemo(() => {
|
|
20990
|
-
if (visualStyle === "segmented" && verticalPosition !== "top") return null;
|
|
20991
|
-
const capLimit = visualStyle === "segmented" ? capLimitSegmented : capLimitClustered;
|
|
20992
|
-
const sliced = existingReactions.slice(0, capLimit);
|
|
20993
|
-
return {
|
|
20994
|
-
/**
|
|
20995
|
-
* Accumulated reaction count of capped reaction types, first four in case of
|
|
20996
|
-
* segmented(top) and first five in case of clustered(top/bottom) variations.
|
|
20997
|
-
*/
|
|
20998
|
-
reactionCountToDisplay: sliced.reduce(
|
|
20999
|
-
(accumulatedCount, { reactionCount }) => accumulatedCount + reactionCount,
|
|
21000
|
-
0
|
|
21001
|
-
),
|
|
21002
|
-
reactionsToDisplay: sliced
|
|
21003
|
-
};
|
|
21004
|
-
}, [
|
|
21005
|
-
capLimitClustered,
|
|
21006
|
-
capLimitSegmented,
|
|
21007
|
-
existingReactions,
|
|
21008
|
-
verticalPosition,
|
|
21009
|
-
visualStyle
|
|
21010
|
-
]);
|
|
21011
|
-
if (!hasReactions) return null;
|
|
21012
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21013
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21014
|
-
"div",
|
|
21015
|
-
{
|
|
21016
|
-
"aria-label": t("aria/Reaction list"),
|
|
21017
|
-
className: clsx("str-chat__message-reactions", {
|
|
21018
|
-
[`str-chat__message-reactions--flipped-horizontally`]: flipHorizontalPosition,
|
|
21019
|
-
[`str-chat__message-reactions--${verticalPosition}`]: typeof verticalPosition === "string",
|
|
21020
|
-
[`str-chat__message-reactions--${visualStyle}`]: typeof visualStyle === "string"
|
|
21021
|
-
}),
|
|
21022
|
-
ref: divRef,
|
|
21023
|
-
role: "figure",
|
|
21024
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21025
|
-
FragmentOrButton,
|
|
21026
|
-
{
|
|
21027
|
-
"aria-expanded": isDialogOpen,
|
|
21028
|
-
"aria-pressed": isDialogOpen,
|
|
21029
|
-
buttonIf: visualStyle === "clustered",
|
|
21030
|
-
className: "str-chat__message-reactions__list-button",
|
|
21031
|
-
"data-testid": "message-reactions-list-button",
|
|
21032
|
-
onClick: () => handleReactionButtonClick(null),
|
|
21033
|
-
children: [
|
|
21034
|
-
/* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "str-chat__message-reactions__list", children: [
|
|
21035
|
-
(cappedExistingReactions?.reactionsToDisplay ?? existingReactions).map(
|
|
21036
|
-
({ EmojiComponent, reactionCount, reactionType }) => EmojiComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21037
|
-
"li",
|
|
21038
|
-
{
|
|
21039
|
-
className: "str-chat__message-reactions__list-item",
|
|
21040
|
-
"data-testid": "message-reactions-list-item",
|
|
21041
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21042
|
-
FragmentOrButton,
|
|
21043
|
-
{
|
|
21044
|
-
buttonIf: visualStyle === "segmented",
|
|
21045
|
-
className: "str-chat__message-reactions__list-item-button",
|
|
21046
|
-
onClick: () => handleReactionButtonClick(reactionType),
|
|
21047
|
-
children: [
|
|
21048
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21049
|
-
"span",
|
|
21050
|
-
{
|
|
21051
|
-
className: "str-chat__message-reactions__list-item-icon",
|
|
21052
|
-
"data-testid": "message-reactions-list-item-icon",
|
|
21053
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(EmojiComponent, {})
|
|
21054
|
-
}
|
|
21055
|
-
),
|
|
21056
|
-
visualStyle === "segmented" && reactionCount > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21057
|
-
"span",
|
|
21058
|
-
{
|
|
21059
|
-
className: "str-chat__message-reactions__list-item-count",
|
|
21060
|
-
"data-testclass": "message-reactions-item-count",
|
|
21061
|
-
children: reactionCount
|
|
21062
|
-
}
|
|
21063
|
-
)
|
|
21064
|
-
]
|
|
21065
|
-
}
|
|
21066
|
-
)
|
|
21067
|
-
},
|
|
21068
|
-
reactionType
|
|
21069
|
-
)
|
|
20971
|
+
);
|
|
20972
|
+
},
|
|
20973
|
+
SaveForLater() {
|
|
20974
|
+
const { closeMenu } = useContextMenuContext();
|
|
20975
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
20976
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
20977
|
+
const { message } = useMessageContext();
|
|
20978
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
20979
|
+
const reminder = useMessageReminder(message.id);
|
|
20980
|
+
const messageAlreadyHasReminderScheduled = Boolean(reminder && reminder?.remindAt);
|
|
20981
|
+
if (messageAlreadyHasReminderScheduled) return null;
|
|
20982
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20983
|
+
ContextMenuButton,
|
|
20984
|
+
{
|
|
20985
|
+
"aria-label": reminder ? t("aria/Remove Save For Later") : t("aria/Bookmark Message"),
|
|
20986
|
+
className: msgActionsBoxButtonClassName,
|
|
20987
|
+
Icon: reminder ? WithAudioPlayback.IconBookmarkRemove : WithAudioPlayback.IconBookmark,
|
|
20988
|
+
onClick: async () => {
|
|
20989
|
+
try {
|
|
20990
|
+
if (reminder) {
|
|
20991
|
+
await client.reminders.deleteReminder(reminder.id);
|
|
20992
|
+
addNotification({
|
|
20993
|
+
context: {
|
|
20994
|
+
message
|
|
20995
|
+
},
|
|
20996
|
+
emitter: "MessageActions",
|
|
20997
|
+
message: t("Remove save for later"),
|
|
20998
|
+
severity: "success",
|
|
20999
|
+
type: "api:message:saveForLater:delete:success"
|
|
21000
|
+
});
|
|
21001
|
+
} else {
|
|
21002
|
+
await client.reminders.createReminder({ messageId: message.id });
|
|
21003
|
+
addNotification({
|
|
21004
|
+
context: {
|
|
21005
|
+
message
|
|
21006
|
+
},
|
|
21007
|
+
emitter: "MessageActions",
|
|
21008
|
+
message: t("Saved for later"),
|
|
21009
|
+
severity: "success",
|
|
21010
|
+
type: "api:message:saveForLater:create:success"
|
|
21011
|
+
});
|
|
21012
|
+
}
|
|
21013
|
+
} catch (error) {
|
|
21014
|
+
addNotification({
|
|
21015
|
+
context: {
|
|
21016
|
+
message
|
|
21017
|
+
},
|
|
21018
|
+
emitter: "MessageActions",
|
|
21019
|
+
error: getNotificationError(error),
|
|
21020
|
+
message: getErrorMessage(
|
|
21021
|
+
error,
|
|
21022
|
+
reminder ? "Error removing message from saved for later" : "Error saving message for later"
|
|
21070
21023
|
),
|
|
21071
|
-
|
|
21072
|
-
|
|
21073
|
-
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21090
|
-
|
|
21091
|
-
|
|
21092
|
-
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
|
|
21101
|
-
|
|
21102
|
-
|
|
21103
|
-
|
|
21104
|
-
|
|
21105
|
-
|
|
21106
|
-
|
|
21107
|
-
|
|
21024
|
+
severity: "error",
|
|
21025
|
+
type: reminder ? "api:message:saveForLater:delete:failed" : "api:message:saveForLater:create:failed"
|
|
21026
|
+
});
|
|
21027
|
+
} finally {
|
|
21028
|
+
closeMenu();
|
|
21029
|
+
}
|
|
21030
|
+
},
|
|
21031
|
+
children: reminder ? t("Remove save for later") : t("Save for later")
|
|
21032
|
+
}
|
|
21033
|
+
);
|
|
21034
|
+
},
|
|
21035
|
+
Flag() {
|
|
21036
|
+
const { closeMenu } = useContextMenuContext();
|
|
21037
|
+
const { handleFlag, message } = useMessageContext();
|
|
21038
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
21039
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21040
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21041
|
+
ContextMenuButton,
|
|
21042
|
+
{
|
|
21043
|
+
"aria-label": t("aria/Flag Message"),
|
|
21044
|
+
className: msgActionsBoxButtonClassName,
|
|
21045
|
+
Icon: WithAudioPlayback.IconFlag,
|
|
21046
|
+
onClick: async (event) => {
|
|
21047
|
+
try {
|
|
21048
|
+
await handleFlag(event);
|
|
21049
|
+
addNotification({
|
|
21050
|
+
context: {
|
|
21051
|
+
message
|
|
21052
|
+
},
|
|
21053
|
+
emitter: "MessageActions",
|
|
21054
|
+
message: t("Message has been successfully flagged"),
|
|
21055
|
+
severity: "success",
|
|
21056
|
+
type: "api:message:flag:success"
|
|
21057
|
+
});
|
|
21058
|
+
} catch (error) {
|
|
21059
|
+
addNotification({
|
|
21060
|
+
context: {
|
|
21061
|
+
message
|
|
21062
|
+
},
|
|
21063
|
+
emitter: "MessageActions",
|
|
21064
|
+
error: getNotificationError(error),
|
|
21065
|
+
message: getErrorMessage(error, t("Error adding flag")),
|
|
21066
|
+
severity: "error",
|
|
21067
|
+
type: "api:message:flag:failed"
|
|
21068
|
+
});
|
|
21069
|
+
}
|
|
21070
|
+
closeMenu();
|
|
21071
|
+
},
|
|
21072
|
+
children: t("Flag")
|
|
21073
|
+
}
|
|
21074
|
+
);
|
|
21075
|
+
},
|
|
21076
|
+
Mute() {
|
|
21077
|
+
const { closeMenu } = useContextMenuContext();
|
|
21078
|
+
const { handleMute, message } = useMessageContext();
|
|
21079
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
21080
|
+
const { mutes } = WithAudioPlayback.useChatContext();
|
|
21081
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21082
|
+
const isMuted = WithAudioPlayback.isUserMuted(message, mutes);
|
|
21083
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21084
|
+
ContextMenuButton,
|
|
21085
|
+
{
|
|
21086
|
+
"aria-label": isMuted ? t("aria/Unmute User") : t("aria/Mute User"),
|
|
21087
|
+
className: msgActionsBoxButtonClassName,
|
|
21088
|
+
Icon: isMuted ? WithAudioPlayback.IconAudio : WithAudioPlayback.IconMute,
|
|
21089
|
+
onClick: async (event) => {
|
|
21090
|
+
try {
|
|
21091
|
+
await handleMute(event);
|
|
21092
|
+
addNotification({
|
|
21093
|
+
context: {
|
|
21094
|
+
message
|
|
21095
|
+
},
|
|
21096
|
+
emitter: "MessageActions",
|
|
21097
|
+
message: isMuted ? t("{{ user }} has been unmuted", {
|
|
21098
|
+
user: message.user?.name || message.user?.id
|
|
21099
|
+
}) : t("{{ user }} has been muted", {
|
|
21100
|
+
user: message.user?.name || message.user?.id
|
|
21101
|
+
}),
|
|
21102
|
+
severity: "success",
|
|
21103
|
+
type: isMuted ? "api:user:unmute:success" : "api:user:mute:success"
|
|
21104
|
+
});
|
|
21105
|
+
} catch (error) {
|
|
21106
|
+
addNotification({
|
|
21107
|
+
context: {
|
|
21108
|
+
message
|
|
21109
|
+
},
|
|
21110
|
+
emitter: "MessageActions",
|
|
21111
|
+
error: getNotificationError(error),
|
|
21112
|
+
message: getErrorMessage(
|
|
21113
|
+
error,
|
|
21114
|
+
isMuted ? t("Error unmuting a user ...") : t("Error muting a user ...")
|
|
21115
|
+
),
|
|
21116
|
+
severity: "error",
|
|
21117
|
+
type: isMuted ? "api:user:unmute:failed" : "api:user:mute:failed"
|
|
21118
|
+
});
|
|
21119
|
+
}
|
|
21120
|
+
closeMenu();
|
|
21121
|
+
},
|
|
21122
|
+
children: isMuted ? t("Unmute") : t("Mute")
|
|
21123
|
+
}
|
|
21124
|
+
);
|
|
21125
|
+
},
|
|
21126
|
+
Delete() {
|
|
21127
|
+
const { closeMenu } = useContextMenuContext();
|
|
21128
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
21129
|
+
const { Modal = GlobalModal } = WithAudioPlayback.useComponentContext();
|
|
21130
|
+
const { handleDelete, message } = useMessageContext();
|
|
21131
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21132
|
+
const [openModal, setOpenModal] = React.useState(false);
|
|
21133
|
+
if (WithAudioPlayback.isMessageDeleted(message)) return null;
|
|
21134
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21135
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21136
|
+
ContextMenuButton,
|
|
21108
21137
|
{
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21138
|
+
"aria-label": t("aria/Delete Message"),
|
|
21139
|
+
className: msgActionsBoxButtonClassName,
|
|
21140
|
+
Icon: WithAudioPlayback.IconDelete,
|
|
21141
|
+
onClick: () => {
|
|
21142
|
+
setOpenModal(true);
|
|
21143
|
+
},
|
|
21144
|
+
variant: "destructive",
|
|
21145
|
+
children: t("Delete message")
|
|
21116
21146
|
}
|
|
21117
|
-
)
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21147
|
+
),
|
|
21148
|
+
/* @__PURE__ */ jsxRuntime.jsx(Modal, { open: openModal, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21149
|
+
DeleteMessageAlert,
|
|
21150
|
+
{
|
|
21151
|
+
onCancel: () => {
|
|
21152
|
+
setOpenModal(false);
|
|
21153
|
+
closeMenu();
|
|
21154
|
+
},
|
|
21155
|
+
onDelete: async () => {
|
|
21156
|
+
try {
|
|
21157
|
+
await handleDelete();
|
|
21158
|
+
addNotification({
|
|
21159
|
+
context: {
|
|
21160
|
+
message
|
|
21161
|
+
},
|
|
21162
|
+
emitter: "MessageActions",
|
|
21163
|
+
message: t("Message deleted"),
|
|
21164
|
+
severity: "success",
|
|
21165
|
+
type: "api:message:delete:success"
|
|
21166
|
+
});
|
|
21167
|
+
} catch (error) {
|
|
21168
|
+
addNotification({
|
|
21169
|
+
context: {
|
|
21170
|
+
message
|
|
21171
|
+
},
|
|
21172
|
+
emitter: "MessageActions",
|
|
21173
|
+
error: getNotificationError(error),
|
|
21174
|
+
message: getErrorMessage(error, t("Error deleting message")),
|
|
21175
|
+
severity: "error",
|
|
21176
|
+
type: "api:message:delete:failed"
|
|
21177
|
+
});
|
|
21178
|
+
} finally {
|
|
21179
|
+
setOpenModal(false);
|
|
21180
|
+
closeMenu();
|
|
21181
|
+
}
|
|
21182
|
+
}
|
|
21183
|
+
}
|
|
21184
|
+
) })
|
|
21185
|
+
] });
|
|
21131
21186
|
},
|
|
21132
|
-
{
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
|
|
21138
|
-
|
|
21139
|
-
|
|
21140
|
-
|
|
21141
|
-
|
|
21142
|
-
|
|
21143
|
-
|
|
21144
|
-
|
|
21145
|
-
|
|
21146
|
-
|
|
21147
|
-
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
|
|
21155
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21156
|
-
"div",
|
|
21157
|
-
{
|
|
21158
|
-
"data-testid": "sprite-image",
|
|
21159
|
-
style: {
|
|
21160
|
-
...style,
|
|
21161
|
-
"--str-chat__sprite-image-resize-ratio": "var(--str-chat__sprite-image-resize-ratio-x, var(--str-chat__sprite-image-resize-ratio-y, 1))",
|
|
21162
|
-
"--str-chat__sprite-image-resize-ratio-x": "calc(var(--str-chat__sprite-image-width) / var(--str-chat__sprite-item-width))",
|
|
21163
|
-
"--str-chat__sprite-image-resize-ratio-y": "calc(var(--str-chat__sprite-image-height) / var(--str-chat__sprite-item-height))",
|
|
21164
|
-
"--str-chat__sprite-item-height": `${spriteHeight / rows}`,
|
|
21165
|
-
"--str-chat__sprite-item-width": `${spriteWidth / columns}`,
|
|
21166
|
-
...Number.isFinite(height) ? { "--str-chat__sprite-image-height": `${height}px` } : {},
|
|
21167
|
-
...Number.isFinite(width) ? { "--str-chat__sprite-image-width": `${width}px` } : {},
|
|
21168
|
-
backgroundImage: `url('${spriteUrl}')`,
|
|
21169
|
-
backgroundPosition: `${x * (100 / (columns - 1))}% ${y * (100 / (rows - 1))}%`,
|
|
21170
|
-
backgroundSize: `${columns * 100}% ${rows * 100}%`,
|
|
21171
|
-
height: "var(--str-chat__sprite-image-height, calc(var(--str-chat__sprite-item-height) * var(--str-chat__sprite-image-resize-ratio)))",
|
|
21172
|
-
width: "var(--str-chat__sprite-image-width, calc(var(--str-chat__sprite-item-width) * var(--str-chat__sprite-image-resize-ratio)))"
|
|
21173
|
-
}
|
|
21187
|
+
BlockUser() {
|
|
21188
|
+
const { closeMenu } = useContextMenuContext();
|
|
21189
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
21190
|
+
const { message } = useMessageContext();
|
|
21191
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21192
|
+
const isBlocked = !message.user?.id || new Set(client.blockedUsers.getLatestValue().userIds).has(message.user?.id);
|
|
21193
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21194
|
+
ContextMenuButton,
|
|
21195
|
+
{
|
|
21196
|
+
"aria-label": isBlocked ? t("aria/Unblock User") : t("aria/Block User"),
|
|
21197
|
+
className: clsx(msgActionsBoxButtonClassName),
|
|
21198
|
+
Icon: isBlocked ? WithAudioPlayback.IconUserCheck : WithAudioPlayback.IconNoSign,
|
|
21199
|
+
onClick: () => {
|
|
21200
|
+
const targetId = message.user?.id;
|
|
21201
|
+
if (targetId) {
|
|
21202
|
+
if (isBlocked) client.unBlockUser(targetId);
|
|
21203
|
+
else client.blockUser(targetId);
|
|
21204
|
+
}
|
|
21205
|
+
closeMenu();
|
|
21206
|
+
},
|
|
21207
|
+
children: isBlocked ? t("Unblock User") : t("Block User")
|
|
21208
|
+
}
|
|
21209
|
+
);
|
|
21174
21210
|
}
|
|
21175
|
-
|
|
21211
|
+
},
|
|
21212
|
+
quick: {
|
|
21213
|
+
// eslint-disable-next-line react/display-name
|
|
21214
|
+
DropdownToggle: React.forwardRef((_, ref) => {
|
|
21215
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21216
|
+
const { message, threadList } = useMessageContext();
|
|
21217
|
+
const dropdownDialogIsOpen = useDialogIsOpen(
|
|
21218
|
+
MessageActions.getDialogId({ messageId: message.id })
|
|
21219
|
+
);
|
|
21220
|
+
const { dialog } = useDialogOnNearestManager({
|
|
21221
|
+
id: MessageActions.getDialogId({ messageId: message.id })
|
|
21222
|
+
});
|
|
21223
|
+
const reactionSelectorDialogId = ReactionSelector.getDialogId({
|
|
21224
|
+
messageId: message.id,
|
|
21225
|
+
threadList
|
|
21226
|
+
});
|
|
21227
|
+
const { dialog: dropdownReactionSelectorDialog } = useDialogOnNearestManager({
|
|
21228
|
+
id: `${reactionSelectorDialogId}-dropdown`
|
|
21229
|
+
});
|
|
21230
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21231
|
+
QuickMessageActionsButton,
|
|
21232
|
+
{
|
|
21233
|
+
"aria-expanded": dropdownDialogIsOpen,
|
|
21234
|
+
"aria-haspopup": "true",
|
|
21235
|
+
"aria-label": t("aria/Open Message Actions Menu"),
|
|
21236
|
+
className: "str-chat__message-actions-box-button",
|
|
21237
|
+
"data-testid": "message-actions-toggle-button",
|
|
21238
|
+
onClick: () => {
|
|
21239
|
+
dropdownReactionSelectorDialog?.close();
|
|
21240
|
+
dialog?.toggle();
|
|
21241
|
+
},
|
|
21242
|
+
ref,
|
|
21243
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMore, { className: "str-chat__message-action-icon" })
|
|
21244
|
+
}
|
|
21245
|
+
);
|
|
21246
|
+
}),
|
|
21247
|
+
React() {
|
|
21248
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ReactionSelectorWithButton, { ReactionIcon: WithAudioPlayback.IconEmoji });
|
|
21249
|
+
},
|
|
21250
|
+
Reply() {
|
|
21251
|
+
const { handleOpenThread } = useMessageContext();
|
|
21252
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
21253
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21254
|
+
QuickMessageActionsButton,
|
|
21255
|
+
{
|
|
21256
|
+
"aria-label": t("aria/Open Thread"),
|
|
21257
|
+
className: "str-chat__message-reply-in-thread-button",
|
|
21258
|
+
"data-testid": "thread-action",
|
|
21259
|
+
onClick: handleOpenThread,
|
|
21260
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconReply, { className: "str-chat__message-action-icon" })
|
|
21261
|
+
}
|
|
21262
|
+
);
|
|
21263
|
+
}
|
|
21264
|
+
}
|
|
21176
21265
|
};
|
|
21266
|
+
const defaultMessageActionSet = [
|
|
21267
|
+
{
|
|
21268
|
+
Component: DefaultMessageActionComponents.quick.DropdownToggle,
|
|
21269
|
+
placement: "quick-dropdown-toggle"
|
|
21270
|
+
},
|
|
21271
|
+
{
|
|
21272
|
+
Component: DefaultMessageActionComponents.quick.Reply,
|
|
21273
|
+
placement: "quick",
|
|
21274
|
+
type: "reply"
|
|
21275
|
+
},
|
|
21276
|
+
{
|
|
21277
|
+
Component: DefaultMessageActionComponents.quick.React,
|
|
21278
|
+
placement: "quick",
|
|
21279
|
+
type: "react"
|
|
21280
|
+
},
|
|
21281
|
+
{
|
|
21282
|
+
Component: DefaultMessageActionComponents.dropdown.React,
|
|
21283
|
+
placement: "dropdown",
|
|
21284
|
+
type: "react"
|
|
21285
|
+
},
|
|
21286
|
+
{
|
|
21287
|
+
Component: DefaultMessageActionComponents.dropdown.ThreadReply,
|
|
21288
|
+
placement: "dropdown",
|
|
21289
|
+
type: "reply"
|
|
21290
|
+
},
|
|
21291
|
+
{
|
|
21292
|
+
Component: DefaultMessageActionComponents.dropdown.Quote,
|
|
21293
|
+
placement: "dropdown",
|
|
21294
|
+
type: "quote"
|
|
21295
|
+
},
|
|
21296
|
+
{
|
|
21297
|
+
Component: DefaultMessageActionComponents.dropdown.Pin,
|
|
21298
|
+
placement: "dropdown",
|
|
21299
|
+
type: "pin"
|
|
21300
|
+
},
|
|
21301
|
+
{
|
|
21302
|
+
Component: DefaultMessageActionComponents.dropdown.CopyMessageText,
|
|
21303
|
+
placement: "dropdown",
|
|
21304
|
+
type: "copyMessageText"
|
|
21305
|
+
},
|
|
21306
|
+
{
|
|
21307
|
+
Component: DefaultMessageActionComponents.dropdown.Resend,
|
|
21308
|
+
placement: "dropdown",
|
|
21309
|
+
type: "resendMessage"
|
|
21310
|
+
},
|
|
21311
|
+
{
|
|
21312
|
+
Component: DefaultMessageActionComponents.dropdown.Edit,
|
|
21313
|
+
placement: "dropdown",
|
|
21314
|
+
type: "edit"
|
|
21315
|
+
},
|
|
21316
|
+
{
|
|
21317
|
+
Component: DefaultMessageActionComponents.dropdown.MarkUnread,
|
|
21318
|
+
placement: "dropdown",
|
|
21319
|
+
type: "markUnread"
|
|
21320
|
+
},
|
|
21321
|
+
{
|
|
21322
|
+
Component: DefaultMessageActionComponents.dropdown.RemindMe,
|
|
21323
|
+
placement: "dropdown",
|
|
21324
|
+
type: "remindMe"
|
|
21325
|
+
},
|
|
21326
|
+
{
|
|
21327
|
+
Component: DefaultMessageActionComponents.dropdown.SaveForLater,
|
|
21328
|
+
placement: "dropdown",
|
|
21329
|
+
type: "saveForLater"
|
|
21330
|
+
},
|
|
21331
|
+
{
|
|
21332
|
+
Component: DefaultMessageActionComponents.dropdown.Flag,
|
|
21333
|
+
placement: "dropdown",
|
|
21334
|
+
type: "flag"
|
|
21335
|
+
},
|
|
21336
|
+
{
|
|
21337
|
+
Component: DefaultMessageActionComponents.dropdown.Mute,
|
|
21338
|
+
placement: "dropdown",
|
|
21339
|
+
type: "mute"
|
|
21340
|
+
},
|
|
21341
|
+
{
|
|
21342
|
+
Component: DefaultMessageActionComponents.dropdown.Delete,
|
|
21343
|
+
placement: "dropdown",
|
|
21344
|
+
type: "delete"
|
|
21345
|
+
},
|
|
21346
|
+
{
|
|
21347
|
+
Component: DefaultMessageActionComponents.dropdown.BlockUser,
|
|
21348
|
+
placement: "dropdown",
|
|
21349
|
+
type: "blockUser"
|
|
21350
|
+
}
|
|
21351
|
+
];
|
|
21177
21352
|
const useSplitActionSet = (actionSet) => React.useMemo(() => {
|
|
21178
21353
|
const quickActionSet = [];
|
|
21179
21354
|
const dropdownActionSet = [];
|
|
@@ -21207,6 +21382,7 @@ const MessageActions = ({
|
|
|
21207
21382
|
messageId: message.id,
|
|
21208
21383
|
threadList
|
|
21209
21384
|
});
|
|
21385
|
+
const dropdownReactionSelectorDialogId = `${reactionSelectorDialogId}-dropdown`;
|
|
21210
21386
|
const { dialog, dialogManager } = useDialogOnNearestManager({
|
|
21211
21387
|
id: messageActionsDialogId
|
|
21212
21388
|
});
|
|
@@ -21218,6 +21394,10 @@ const MessageActions = ({
|
|
|
21218
21394
|
reactionSelectorDialogId,
|
|
21219
21395
|
dialogManager?.id
|
|
21220
21396
|
);
|
|
21397
|
+
const dropdownReactionSelectorDialogIsOpen = useDialogIsOpen(
|
|
21398
|
+
dropdownReactionSelectorDialogId,
|
|
21399
|
+
dialogManager?.id
|
|
21400
|
+
);
|
|
21221
21401
|
if (dropdownActionSet.length + quickActionSet.length === 0) {
|
|
21222
21402
|
return null;
|
|
21223
21403
|
}
|
|
@@ -21225,7 +21405,7 @@ const MessageActions = ({
|
|
|
21225
21405
|
"div",
|
|
21226
21406
|
{
|
|
21227
21407
|
className: clsx("str-chat__message-options", {
|
|
21228
|
-
"str-chat__message-options--active": messageActionsDialogIsOpen || reactionSelectorDialogIsOpen
|
|
21408
|
+
"str-chat__message-options--active": messageActionsDialogIsOpen || reactionSelectorDialogIsOpen || dropdownReactionSelectorDialogIsOpen
|
|
21229
21409
|
}),
|
|
21230
21410
|
children: [
|
|
21231
21411
|
quickDropdownToggleAction && dropdownActionSet.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -21235,6 +21415,7 @@ const MessageActions = ({
|
|
|
21235
21415
|
{
|
|
21236
21416
|
backLabel: t("Back"),
|
|
21237
21417
|
className: clsx("str-chat__message-actions-box", {
|
|
21418
|
+
"str-chat__message-actions-box--hidden": dropdownReactionSelectorDialogIsOpen,
|
|
21238
21419
|
"str-chat__message-actions-box--open": messageActionsDialogIsOpen
|
|
21239
21420
|
}),
|
|
21240
21421
|
dialogManagerId: dialogManager?.id,
|
|
@@ -21299,6 +21480,7 @@ const MessageUIWithContext = ({
|
|
|
21299
21480
|
() => isMessageAIGenerated?.(message),
|
|
21300
21481
|
[isMessageAIGenerated, message]
|
|
21301
21482
|
);
|
|
21483
|
+
const isDeleted = WithAudioPlayback.isMessageDeleted(message);
|
|
21302
21484
|
const finalAttachments = React.useMemo(
|
|
21303
21485
|
() => !message.shared_location && !message.attachments ? [] : !message.shared_location ? message.attachments : [message.shared_location, ...message.attachments ?? []],
|
|
21304
21486
|
[message]
|
|
@@ -21306,7 +21488,7 @@ const MessageUIWithContext = ({
|
|
|
21306
21488
|
if (WithAudioPlayback.isDateSeparatorMessage(message)) {
|
|
21307
21489
|
return null;
|
|
21308
21490
|
}
|
|
21309
|
-
if (MessageDeleted &&
|
|
21491
|
+
if (MessageDeleted && isDeleted) {
|
|
21310
21492
|
return /* @__PURE__ */ jsxRuntime.jsx(MessageDeleted, { message });
|
|
21311
21493
|
}
|
|
21312
21494
|
if (WithAudioPlayback.isMessageBlocked(message)) {
|
|
@@ -21314,7 +21496,6 @@ const MessageUIWithContext = ({
|
|
|
21314
21496
|
}
|
|
21315
21497
|
const poll = message.poll_id && client.polls.fromState(message.poll_id);
|
|
21316
21498
|
const memberCount = Object.keys(channel?.state?.members ?? {}).length;
|
|
21317
|
-
const isDeleted = !!message.deleted_at;
|
|
21318
21499
|
const hasAttachment = !isDeleted && WithAudioPlayback.messageHasAttachments(message);
|
|
21319
21500
|
const hasSingleAttachment = !isDeleted && WithAudioPlayback.messageHasSingleAttachment(message);
|
|
21320
21501
|
const hasGiphyAttachment = !isDeleted && WithAudioPlayback.messageHasGiphyAttachment(message);
|
|
@@ -21405,7 +21586,7 @@ const MessageUIWithContext = ({
|
|
|
21405
21586
|
thread_participants: message.thread_participants
|
|
21406
21587
|
}
|
|
21407
21588
|
),
|
|
21408
|
-
|
|
21589
|
+
isDeleted ? /* @__PURE__ */ jsxRuntime.jsx(MessageDeletedBubble$1, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21409
21590
|
/* @__PURE__ */ jsxRuntime.jsxs(MessageBubble, { children: [
|
|
21410
21591
|
poll && /* @__PURE__ */ jsxRuntime.jsx(Poll, { poll }),
|
|
21411
21592
|
message.quoted_message && /* @__PURE__ */ jsxRuntime.jsx(QuotedMessage$1, {}),
|
|
@@ -21690,26 +21871,21 @@ const useFloatingDateSeparatorMessageList = ({
|
|
|
21690
21871
|
}
|
|
21691
21872
|
const containerRect = listElement.getBoundingClientRect();
|
|
21692
21873
|
let bestDate = null;
|
|
21693
|
-
let
|
|
21694
|
-
let anyVisible = false;
|
|
21874
|
+
let bestTop = -Infinity;
|
|
21695
21875
|
for (const el of separators) {
|
|
21696
21876
|
const rect = el.getBoundingClientRect();
|
|
21697
21877
|
const dataDate = el.getAttribute("data-date");
|
|
21698
21878
|
if (!dataDate) continue;
|
|
21699
|
-
const
|
|
21700
|
-
|
|
21701
|
-
|
|
21702
|
-
anyVisible = true;
|
|
21703
|
-
}
|
|
21704
|
-
if (isAboveViewport && rect.bottom > bestBottom) {
|
|
21705
|
-
bestBottom = rect.bottom;
|
|
21879
|
+
const isAtOrAboveTopBoundary = rect.top <= containerRect.top;
|
|
21880
|
+
if (isAtOrAboveTopBoundary && rect.top > bestTop) {
|
|
21881
|
+
bestTop = rect.top;
|
|
21706
21882
|
const d = new Date(dataDate);
|
|
21707
21883
|
if (!isNaN(d.getTime())) bestDate = d;
|
|
21708
21884
|
}
|
|
21709
21885
|
}
|
|
21710
21886
|
setState({
|
|
21711
|
-
date:
|
|
21712
|
-
visible:
|
|
21887
|
+
date: bestDate,
|
|
21888
|
+
visible: bestDate !== null
|
|
21713
21889
|
});
|
|
21714
21890
|
}, [disableDateSeparator, listElement, processedMessages]);
|
|
21715
21891
|
React.useEffect(() => {
|
|
@@ -22706,6 +22882,10 @@ function getFloatingDateForFirstMessage(firstMessage, processedMessages, firstMe
|
|
|
22706
22882
|
}
|
|
22707
22883
|
return null;
|
|
22708
22884
|
}
|
|
22885
|
+
function getFloatingDateForFirstItem(firstItem, processedMessages, firstItemIndex) {
|
|
22886
|
+
if (WithAudioPlayback.isDateSeparatorMessage(firstItem)) return firstItem.date;
|
|
22887
|
+
return getFloatingDateForFirstMessage(firstItem, processedMessages, firstItemIndex);
|
|
22888
|
+
}
|
|
22709
22889
|
const HIDDEN_STATE = { date: null, visible: false };
|
|
22710
22890
|
const useFloatingDateSeparator = ({
|
|
22711
22891
|
disableDateSeparator,
|
|
@@ -22724,17 +22904,8 @@ const useFloatingDateSeparator = ({
|
|
|
22724
22904
|
return;
|
|
22725
22905
|
}
|
|
22726
22906
|
const first = valid[0];
|
|
22727
|
-
if (WithAudioPlayback.isDateSeparatorMessage(first)) {
|
|
22728
|
-
setState(HIDDEN_STATE);
|
|
22729
|
-
return;
|
|
22730
|
-
}
|
|
22731
|
-
const hasVisibleDateSeparator = valid.some(WithAudioPlayback.isDateSeparatorMessage);
|
|
22732
|
-
if (hasVisibleDateSeparator) {
|
|
22733
|
-
setState(HIDDEN_STATE);
|
|
22734
|
-
return;
|
|
22735
|
-
}
|
|
22736
22907
|
const firstIndex = processedMessages.findIndex((m) => m.id === first.id);
|
|
22737
|
-
const date = firstIndex >= 0 ?
|
|
22908
|
+
const date = firstIndex >= 0 ? getFloatingDateForFirstItem(first, processedMessages, firstIndex) : null;
|
|
22738
22909
|
const visible = date !== null;
|
|
22739
22910
|
setState((prev) => {
|
|
22740
22911
|
const prevTime = prev.date?.getTime() ?? null;
|
|
@@ -25662,77 +25833,9 @@ const useArchiveActionButtonBehavior = () => {
|
|
|
25662
25833
|
title: membership.archived_at ? t("Unarchive") : t("Archive")
|
|
25663
25834
|
};
|
|
25664
25835
|
};
|
|
25665
|
-
const
|
|
25666
|
-
{
|
|
25667
|
-
|
|
25668
|
-
Component: React.forwardRef((_, ref) => {
|
|
25669
|
-
const { channel } = useChannelListItemContext();
|
|
25670
|
-
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
25671
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
25672
|
-
channelId: channel.id
|
|
25673
|
-
});
|
|
25674
|
-
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
25675
|
-
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
25676
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25677
|
-
WithAudioPlayback.Button,
|
|
25678
|
-
{
|
|
25679
|
-
appearance: "ghost",
|
|
25680
|
-
"aria-expanded": dialogIsOpen,
|
|
25681
|
-
"aria-pressed": dialogIsOpen,
|
|
25682
|
-
circular: true,
|
|
25683
|
-
onClick: (e) => {
|
|
25684
|
-
e.stopPropagation();
|
|
25685
|
-
dialog.toggle();
|
|
25686
|
-
},
|
|
25687
|
-
ref,
|
|
25688
|
-
size: "sm",
|
|
25689
|
-
variant: "secondary",
|
|
25690
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMore, {})
|
|
25691
|
-
}
|
|
25692
|
-
);
|
|
25693
|
-
}),
|
|
25694
|
-
placement: "quick-dropdown-toggle"
|
|
25695
|
-
},
|
|
25696
|
-
{
|
|
25697
|
-
Component() {
|
|
25698
|
-
const behaviorProps = useArchiveActionButtonBehavior();
|
|
25699
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25700
|
-
WithAudioPlayback.Button,
|
|
25701
|
-
{
|
|
25702
|
-
appearance: "ghost",
|
|
25703
|
-
"aria-label": behaviorProps.title,
|
|
25704
|
-
circular: true,
|
|
25705
|
-
size: "sm",
|
|
25706
|
-
variant: "secondary",
|
|
25707
|
-
...behaviorProps,
|
|
25708
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconArchive, {})
|
|
25709
|
-
}
|
|
25710
|
-
);
|
|
25711
|
-
},
|
|
25712
|
-
placement: "quick",
|
|
25713
|
-
type: "archive"
|
|
25714
|
-
},
|
|
25715
|
-
{
|
|
25716
|
-
Component() {
|
|
25717
|
-
const behaviorProps = useMuteActionButtonBehavior();
|
|
25718
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25719
|
-
WithAudioPlayback.Button,
|
|
25720
|
-
{
|
|
25721
|
-
appearance: "ghost",
|
|
25722
|
-
"aria-label": behaviorProps.title,
|
|
25723
|
-
circular: true,
|
|
25724
|
-
size: "sm",
|
|
25725
|
-
variant: "secondary",
|
|
25726
|
-
...behaviorProps,
|
|
25727
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMute, {})
|
|
25728
|
-
}
|
|
25729
|
-
);
|
|
25730
|
-
},
|
|
25731
|
-
placement: "quick",
|
|
25732
|
-
type: "mute"
|
|
25733
|
-
},
|
|
25734
|
-
{
|
|
25735
|
-
Component() {
|
|
25836
|
+
const defaultComponents = {
|
|
25837
|
+
dropdown: {
|
|
25838
|
+
Archive() {
|
|
25736
25839
|
const behaviorProps = useArchiveActionButtonBehavior();
|
|
25737
25840
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25738
25841
|
ContextMenuButton,
|
|
@@ -25744,27 +25847,7 @@ const defaultChannelActionSet = [
|
|
|
25744
25847
|
}
|
|
25745
25848
|
);
|
|
25746
25849
|
},
|
|
25747
|
-
|
|
25748
|
-
type: "archive"
|
|
25749
|
-
},
|
|
25750
|
-
{
|
|
25751
|
-
Component() {
|
|
25752
|
-
const behaviorProps = useMuteActionButtonBehavior();
|
|
25753
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25754
|
-
ContextMenuButton,
|
|
25755
|
-
{
|
|
25756
|
-
"aria-label": behaviorProps.title,
|
|
25757
|
-
Icon: WithAudioPlayback.IconMute,
|
|
25758
|
-
...behaviorProps,
|
|
25759
|
-
children: behaviorProps.title
|
|
25760
|
-
}
|
|
25761
|
-
);
|
|
25762
|
-
},
|
|
25763
|
-
placement: "dropdown",
|
|
25764
|
-
type: "mute"
|
|
25765
|
-
},
|
|
25766
|
-
{
|
|
25767
|
-
Component() {
|
|
25850
|
+
Ban() {
|
|
25768
25851
|
const { client } = WithAudioPlayback.useChatContext();
|
|
25769
25852
|
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
25770
25853
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
@@ -25831,11 +25914,55 @@ const defaultChannelActionSet = [
|
|
|
25831
25914
|
}
|
|
25832
25915
|
);
|
|
25833
25916
|
},
|
|
25834
|
-
|
|
25835
|
-
|
|
25836
|
-
|
|
25837
|
-
|
|
25838
|
-
|
|
25917
|
+
Leave() {
|
|
25918
|
+
const { t } = WithAudioPlayback.useTranslationContext();
|
|
25919
|
+
const { channel } = useChannelListItemContext();
|
|
25920
|
+
const { client } = WithAudioPlayback.useChatContext();
|
|
25921
|
+
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
25922
|
+
const [inProgress, setInProgress] = React.useState(false);
|
|
25923
|
+
const title = t("Leave Channel");
|
|
25924
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25925
|
+
ContextMenuButton,
|
|
25926
|
+
{
|
|
25927
|
+
"aria-label": title,
|
|
25928
|
+
disabled: inProgress,
|
|
25929
|
+
Icon: WithAudioPlayback.IconLeave,
|
|
25930
|
+
onClick: async (e) => {
|
|
25931
|
+
e.stopPropagation();
|
|
25932
|
+
try {
|
|
25933
|
+
setInProgress(true);
|
|
25934
|
+
await channel.removeMembers([client.userID]);
|
|
25935
|
+
addNotification({
|
|
25936
|
+
context: {
|
|
25937
|
+
channel
|
|
25938
|
+
},
|
|
25939
|
+
emitter: ChannelListItemActionButtons.name,
|
|
25940
|
+
message: t("Left channel"),
|
|
25941
|
+
severity: "success",
|
|
25942
|
+
type: "api:channel:leave:success"
|
|
25943
|
+
});
|
|
25944
|
+
} catch (error) {
|
|
25945
|
+
addNotification({
|
|
25946
|
+
context: {
|
|
25947
|
+
channel
|
|
25948
|
+
},
|
|
25949
|
+
emitter: ChannelListItemActionButtons.name,
|
|
25950
|
+
error: error instanceof Error ? error : new Error("An unknown error occurred"),
|
|
25951
|
+
message: t("Failed to leave channel"),
|
|
25952
|
+
severity: "error",
|
|
25953
|
+
type: "api:channel:leave:failed"
|
|
25954
|
+
});
|
|
25955
|
+
} finally {
|
|
25956
|
+
setInProgress(false);
|
|
25957
|
+
}
|
|
25958
|
+
},
|
|
25959
|
+
title,
|
|
25960
|
+
variant: "destructive",
|
|
25961
|
+
children: title
|
|
25962
|
+
}
|
|
25963
|
+
);
|
|
25964
|
+
},
|
|
25965
|
+
Pin() {
|
|
25839
25966
|
const { t } = WithAudioPlayback.useTranslationContext();
|
|
25840
25967
|
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
25841
25968
|
const { channel } = useChannelListItemContext();
|
|
@@ -25902,59 +26029,80 @@ const defaultChannelActionSet = [
|
|
|
25902
26029
|
children: title
|
|
25903
26030
|
}
|
|
25904
26031
|
);
|
|
25905
|
-
}
|
|
25906
|
-
placement: "dropdown",
|
|
25907
|
-
type: "pin"
|
|
26032
|
+
}
|
|
25908
26033
|
},
|
|
25909
|
-
{
|
|
25910
|
-
|
|
25911
|
-
const
|
|
25912
|
-
const { channel } = useChannelListItemContext();
|
|
25913
|
-
const { client } = WithAudioPlayback.useChatContext();
|
|
25914
|
-
const { addNotification } = WithAudioPlayback.useNotificationApi();
|
|
25915
|
-
const [inProgress, setInProgress] = React.useState(false);
|
|
25916
|
-
const title = t("Leave Channel");
|
|
26034
|
+
quick: {
|
|
26035
|
+
Mute() {
|
|
26036
|
+
const behaviorProps = useMuteActionButtonBehavior();
|
|
25917
26037
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25918
|
-
|
|
26038
|
+
WithAudioPlayback.Button,
|
|
25919
26039
|
{
|
|
25920
|
-
"
|
|
25921
|
-
|
|
25922
|
-
|
|
25923
|
-
|
|
25924
|
-
|
|
25925
|
-
|
|
25926
|
-
|
|
25927
|
-
await channel.removeMembers([client.userID]);
|
|
25928
|
-
addNotification({
|
|
25929
|
-
context: {
|
|
25930
|
-
channel
|
|
25931
|
-
},
|
|
25932
|
-
emitter: ChannelListItemActionButtons.name,
|
|
25933
|
-
message: t("Left channel"),
|
|
25934
|
-
severity: "success",
|
|
25935
|
-
type: "api:channel:leave:success"
|
|
25936
|
-
});
|
|
25937
|
-
} catch (error) {
|
|
25938
|
-
addNotification({
|
|
25939
|
-
context: {
|
|
25940
|
-
channel
|
|
25941
|
-
},
|
|
25942
|
-
emitter: ChannelListItemActionButtons.name,
|
|
25943
|
-
error: error instanceof Error ? error : new Error("An unknown error occurred"),
|
|
25944
|
-
message: t("Failed to leave channel"),
|
|
25945
|
-
severity: "error",
|
|
25946
|
-
type: "api:channel:leave:failed"
|
|
25947
|
-
});
|
|
25948
|
-
} finally {
|
|
25949
|
-
setInProgress(false);
|
|
25950
|
-
}
|
|
25951
|
-
},
|
|
25952
|
-
title,
|
|
25953
|
-
variant: "destructive",
|
|
25954
|
-
children: title
|
|
26040
|
+
appearance: "ghost",
|
|
26041
|
+
"aria-label": behaviorProps.title,
|
|
26042
|
+
circular: true,
|
|
26043
|
+
size: "sm",
|
|
26044
|
+
variant: "secondary",
|
|
26045
|
+
...behaviorProps,
|
|
26046
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMute, {})
|
|
25955
26047
|
}
|
|
25956
26048
|
);
|
|
25957
|
-
}
|
|
26049
|
+
}
|
|
26050
|
+
},
|
|
26051
|
+
QuickDropdownToggle: React.forwardRef((_, ref) => {
|
|
26052
|
+
const { channel } = useChannelListItemContext();
|
|
26053
|
+
const dialogId2 = ChannelListItemActionButtons.getDialogId({
|
|
26054
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
26055
|
+
channelId: channel.id
|
|
26056
|
+
});
|
|
26057
|
+
const { dialog, dialogManager } = useDialogOnNearestManager({ id: dialogId2 });
|
|
26058
|
+
const dialogIsOpen = useDialogIsOpen(dialogId2, dialogManager?.id);
|
|
26059
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26060
|
+
WithAudioPlayback.Button,
|
|
26061
|
+
{
|
|
26062
|
+
appearance: "ghost",
|
|
26063
|
+
"aria-expanded": dialogIsOpen,
|
|
26064
|
+
"aria-pressed": dialogIsOpen,
|
|
26065
|
+
circular: true,
|
|
26066
|
+
onClick: (e) => {
|
|
26067
|
+
e.stopPropagation();
|
|
26068
|
+
dialog.toggle();
|
|
26069
|
+
},
|
|
26070
|
+
ref,
|
|
26071
|
+
size: "sm",
|
|
26072
|
+
variant: "secondary",
|
|
26073
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(WithAudioPlayback.IconMore, {})
|
|
26074
|
+
}
|
|
26075
|
+
);
|
|
26076
|
+
})
|
|
26077
|
+
};
|
|
26078
|
+
defaultComponents.QuickDropdownToggle.displayName = "QuickDropdownToggle";
|
|
26079
|
+
const defaultChannelActionSet = [
|
|
26080
|
+
{
|
|
26081
|
+
Component: defaultComponents.QuickDropdownToggle,
|
|
26082
|
+
placement: "quick-dropdown-toggle"
|
|
26083
|
+
},
|
|
26084
|
+
{
|
|
26085
|
+
Component: defaultComponents.quick.Mute,
|
|
26086
|
+
placement: "quick",
|
|
26087
|
+
type: "mute"
|
|
26088
|
+
},
|
|
26089
|
+
{
|
|
26090
|
+
Component: defaultComponents.dropdown.Archive,
|
|
26091
|
+
placement: "dropdown",
|
|
26092
|
+
type: "archive"
|
|
26093
|
+
},
|
|
26094
|
+
{
|
|
26095
|
+
Component: defaultComponents.dropdown.Ban,
|
|
26096
|
+
placement: "dropdown",
|
|
26097
|
+
type: "ban"
|
|
26098
|
+
},
|
|
26099
|
+
{
|
|
26100
|
+
Component: defaultComponents.dropdown.Pin,
|
|
26101
|
+
placement: "dropdown",
|
|
26102
|
+
type: "pin"
|
|
26103
|
+
},
|
|
26104
|
+
{
|
|
26105
|
+
Component: defaultComponents.dropdown.Leave,
|
|
25958
26106
|
placement: "dropdown",
|
|
25959
26107
|
type: "leave"
|
|
25960
26108
|
}
|
|
@@ -25962,8 +26110,6 @@ const defaultChannelActionSet = [
|
|
|
25962
26110
|
const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
25963
26111
|
const { channel } = useChannelListItemContext();
|
|
25964
26112
|
const membership = useChannelMembershipState(channel);
|
|
25965
|
-
const isDirectMessageChannel = channel.type === "messaging" && // assuming one of the users is current user
|
|
25966
|
-
channel.data?.member_count === 2 && channel.id?.startsWith("!members-");
|
|
25967
26113
|
const memberCount = channel.data?.member_count ?? 0;
|
|
25968
26114
|
const connectedUserIsMember = typeof membership.user !== "undefined";
|
|
25969
26115
|
const ownCapabilities = channel.data?.own_capabilities;
|
|
@@ -25972,9 +26118,9 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25972
26118
|
if (action.placement === "quick-dropdown-toggle") return true;
|
|
25973
26119
|
switch (action.type) {
|
|
25974
26120
|
case "archive":
|
|
25975
|
-
return connectedUserIsMember
|
|
26121
|
+
return connectedUserIsMember;
|
|
25976
26122
|
case "mute":
|
|
25977
|
-
return ownCapabilities?.includes("mute-channel")
|
|
26123
|
+
return ownCapabilities?.includes("mute-channel");
|
|
25978
26124
|
case "ban":
|
|
25979
26125
|
return memberCount > 0 && memberCount <= 2 && ownCapabilities?.includes("ban-channel-members");
|
|
25980
26126
|
case "leave":
|
|
@@ -25986,13 +26132,7 @@ const useBaseChannelActionSetFilter = (channelActionSet) => {
|
|
|
25986
26132
|
}
|
|
25987
26133
|
});
|
|
25988
26134
|
return filtered;
|
|
25989
|
-
}, [
|
|
25990
|
-
channelActionSet,
|
|
25991
|
-
isDirectMessageChannel,
|
|
25992
|
-
memberCount,
|
|
25993
|
-
ownCapabilities,
|
|
25994
|
-
connectedUserIsMember
|
|
25995
|
-
]);
|
|
26135
|
+
}, [channelActionSet, memberCount, ownCapabilities, connectedUserIsMember]);
|
|
25996
26136
|
};
|
|
25997
26137
|
const ChannelListItemActionButtons = () => {
|
|
25998
26138
|
const { ContextMenu: ContextMenuComponent = ContextMenu } = WithAudioPlayback.useComponentContext();
|
|
@@ -26122,7 +26262,7 @@ const useLatestMessagePreview = ({
|
|
|
26122
26262
|
} else if (!isOwnMessage && participantCount !== void 0 && participantCount > 2) {
|
|
26123
26263
|
senderName = latestMessage.user?.name || latestMessage.user?.id;
|
|
26124
26264
|
}
|
|
26125
|
-
if (latestMessage
|
|
26265
|
+
if (WithAudioPlayback.isMessageDeleted(latestMessage)) {
|
|
26126
26266
|
return {
|
|
26127
26267
|
deliveryStatus,
|
|
26128
26268
|
senderName,
|
|
@@ -28247,7 +28387,7 @@ const useChat = ({
|
|
|
28247
28387
|
};
|
|
28248
28388
|
React.useEffect(() => {
|
|
28249
28389
|
if (!client) return;
|
|
28250
|
-
const version = "14.0.0-beta.
|
|
28390
|
+
const version = "14.0.0-beta.8";
|
|
28251
28391
|
const userAgent = client.getUserAgent();
|
|
28252
28392
|
if (!userAgent.includes("stream-chat-react")) {
|
|
28253
28393
|
client.setUserAgent(`stream-chat-react-${version}-${userAgent}`);
|
|
@@ -28431,7 +28571,6 @@ const Chat = (props) => {
|
|
|
28431
28571
|
defaultLanguage,
|
|
28432
28572
|
i18nInstance
|
|
28433
28573
|
});
|
|
28434
|
-
useReportLostConnectionSystemNotification();
|
|
28435
28574
|
const channelsQueryState = useChannelsQueryState();
|
|
28436
28575
|
const searchController = React.useMemo(
|
|
28437
28576
|
() => customChannelSearchController ?? new streamChat.SearchController({
|
|
@@ -28651,6 +28790,7 @@ exports.isLanguageSupported = WithAudioPlayback.isLanguageSupported;
|
|
|
28651
28790
|
exports.isLocalMessage = WithAudioPlayback.isLocalMessage;
|
|
28652
28791
|
exports.isMessageBlocked = WithAudioPlayback.isMessageBlocked;
|
|
28653
28792
|
exports.isMessageBounced = WithAudioPlayback.isMessageBounced;
|
|
28793
|
+
exports.isMessageDeleted = WithAudioPlayback.isMessageDeleted;
|
|
28654
28794
|
exports.isMessageEdited = WithAudioPlayback.isMessageEdited;
|
|
28655
28795
|
exports.isMessageErrorRetryable = WithAudioPlayback.isMessageErrorRetryable;
|
|
28656
28796
|
exports.isNetworkSendFailure = WithAudioPlayback.isNetworkSendFailure;
|
|
@@ -28886,6 +29026,10 @@ exports.Streami18n = Streami18n;
|
|
|
28886
29026
|
exports.SuggestPollOptionPrompt = SuggestPollOptionPrompt;
|
|
28887
29027
|
exports.SuggestionList = SuggestionList;
|
|
28888
29028
|
exports.SuggestionListItem = SuggestionListItem;
|
|
29029
|
+
exports.SwitchField = SwitchField;
|
|
29030
|
+
exports.SwitchFieldDescription = SwitchFieldDescription;
|
|
29031
|
+
exports.SwitchFieldLabel = SwitchFieldLabel;
|
|
29032
|
+
exports.SwitchFieldTitle = SwitchFieldTitle;
|
|
28889
29033
|
exports.TextInput = TextInput;
|
|
28890
29034
|
exports.TextInputFieldSet = TextInputFieldSet;
|
|
28891
29035
|
exports.TextareaComposer = TextareaComposer;
|
|
@@ -28926,7 +29070,7 @@ exports.deTranslations = deTranslations;
|
|
|
28926
29070
|
exports.defaultAllowedTagNames = defaultAllowedTagNames;
|
|
28927
29071
|
exports.defaultAttachmentActionsDefaultFocus = defaultAttachmentActionsDefaultFocus;
|
|
28928
29072
|
exports.defaultAttachmentSelectorActionSet = defaultAttachmentSelectorActionSet;
|
|
28929
|
-
exports.defaultComponents = defaultComponents;
|
|
29073
|
+
exports.defaultComponents = defaultComponents$1;
|
|
28930
29074
|
exports.defaultMessageActionSet = defaultMessageActionSet;
|
|
28931
29075
|
exports.defaultReactionOptions = defaultReactionOptions;
|
|
28932
29076
|
exports.defaultRenderMessages = defaultRenderMessages;
|