@droppii-org/chat-sdk 0.1.59 → 0.1.60
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/assets/droppiiFontSelection.json +13195 -3192
- package/dist/components/conversation-detail/ConversationDetailInput.js +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.js +33 -2
- package/dist/components/conversation-detail/PinLimitModal.d.ts +7 -0
- package/dist/components/conversation-detail/PinLimitModal.d.ts.map +1 -0
- package/dist/components/conversation-detail/PinLimitModal.js +11 -0
- package/dist/components/conversation-detail/PinnedMessageBar.d.ts +3 -0
- package/dist/components/conversation-detail/PinnedMessageBar.d.ts.map +1 -0
- package/dist/components/conversation-detail/PinnedMessageBar.js +95 -0
- package/dist/components/conversation-detail/index.d.ts +2 -0
- package/dist/components/conversation-detail/index.d.ts.map +1 -1
- package/dist/components/conversation-detail/index.js +2 -0
- package/dist/components/conversation-inbox/ConversationInboxTitle.js +1 -1
- package/dist/components/message/item/index.d.ts +3 -1
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +29 -11
- package/dist/components/message/reply/ReplyPreviewMedia.d.ts.map +1 -1
- package/dist/components/message/reply/ReplyPreviewMedia.js +3 -14
- package/dist/components/message/toolbox/index.d.ts +1 -0
- package/dist/components/message/toolbox/index.d.ts.map +1 -1
- package/dist/components/message/toolbox/index.js +1 -0
- package/dist/components/message/toolbox/isPinnableMessageType.d.ts +3 -0
- package/dist/components/message/toolbox/isPinnableMessageType.d.ts.map +1 -0
- package/dist/components/message/toolbox/isPinnableMessageType.js +11 -0
- package/dist/components/message/toolbox/types.d.ts +1 -0
- package/dist/components/message/toolbox/types.d.ts.map +1 -1
- package/dist/components/message/toolbox/types.js +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -0
- package/dist/hooks/message/usePinMessage.d.ts +7 -0
- package/dist/hooks/message/usePinMessage.d.ts.map +1 -0
- package/dist/hooks/message/usePinMessage.js +42 -0
- package/dist/hooks/message/usePinnedMessages.d.ts +6 -0
- package/dist/hooks/message/usePinnedMessages.d.ts.map +1 -0
- package/dist/hooks/message/usePinnedMessages.js +33 -0
- package/dist/locales/vi/common.json +13 -0
- package/dist/screens/conversation-detail/index.d.ts.map +1 -1
- package/dist/screens/conversation-detail/index.js +2 -2
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +21 -1
- package/dist/store/pinnedMessage.d.ts +4 -0
- package/dist/store/pinnedMessage.d.ts.map +1 -0
- package/dist/store/pinnedMessage.js +17 -0
- package/dist/store/type.d.ts +4 -0
- package/dist/store/type.d.ts.map +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/common.d.ts +2 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +11 -0
- package/package.json +127 -126
|
@@ -252,7 +252,7 @@ const ConversationDetailInput = ({ placeholder, onSendMessage, onInputChange, })
|
|
|
252
252
|
event.preventDefault();
|
|
253
253
|
void handleSend();
|
|
254
254
|
};
|
|
255
|
-
return (_jsxs("div", { ref: containerRef, "data-testid": "conversation-detail-input", className: "flex w-full shrink-0 flex-col bg-chat-bubble-neutral/[0.05]", children: [_jsx("input", { ref: mediaInputRef, type: "file", accept: "image/jpeg,image/png,image/jpg,video/*", multiple: true, className: "hidden", onChange: handleMediaInputChange }), _jsx("input", { ref: documentInputRef, type: "file", accept: ".pdf,.doc,.docx", multiple: true, className: "hidden", onChange: handleDocumentInputChange }), _jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && (_jsx(FilePreviewList, { files: listUploadFiles, onRemove: (file) => handleRemoveFile(file.uid), onVideoReady: () => setIsVideoLoading(false) })), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setPreviewDismissed(true) })), _jsxs("div", { className: "flex items-end gap-3 px-3 py-2", children: [_jsx("div", { className: "flex shrink-0 items-center", children: _jsx("button", { type: "button", onClick: handleToggleMoreOption, "aria-label": t("thread_detail.more_option.toggle"), "aria-expanded": isMoreOptionOpen, "data-testid": "conversation-detail-more-option-toggle", className: "flex py-3 items-center justify-center rounded-full", children: isMoreOptionOpen ? (_jsx(Icon, { icon: "close-circle-
|
|
255
|
+
return (_jsxs("div", { ref: containerRef, "data-testid": "conversation-detail-input", className: "flex w-full shrink-0 flex-col bg-chat-bubble-neutral/[0.05]", children: [_jsx("input", { ref: mediaInputRef, type: "file", accept: "image/jpeg,image/png,image/jpg,video/*", multiple: true, className: "hidden", onChange: handleMediaInputChange }), _jsx("input", { ref: documentInputRef, type: "file", accept: ".pdf,.doc,.docx", multiple: true, className: "hidden", onChange: handleDocumentInputChange }), _jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && (_jsx(FilePreviewList, { files: listUploadFiles, onRemove: (file) => handleRemoveFile(file.uid), onVideoReady: () => setIsVideoLoading(false) })), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setPreviewDismissed(true) })), _jsxs("div", { className: "flex items-end gap-3 px-3 py-2", children: [_jsx("div", { className: "flex shrink-0 items-center", children: _jsx("button", { type: "button", onClick: handleToggleMoreOption, "aria-label": t("thread_detail.more_option.toggle"), "aria-expanded": isMoreOptionOpen, "data-testid": "conversation-detail-more-option-toggle", className: "flex py-3 items-center justify-center rounded-full", children: isMoreOptionOpen ? (_jsx(Icon, { icon: "close-circle-b", size: 24, className: "text-primary-400" })) : (_jsx(Icon, { icon: "plus-circle-o", size: 24, className: "text-gray-900" })) }) }), _jsx("div", { className: clsx("flex min-w-0 flex-1 overflow-hidden rounded-xl border bg-white transition-shadow", isFocused
|
|
256
256
|
? "border-primary-200 shadow-primary-focus"
|
|
257
257
|
: "border-gray-50"), style: { minHeight: CONTAINER_MIN_HEIGHT }, children: _jsx("div", { className: "flex min-w-0 flex-[1_0_0] items-center gap-2 self-stretch px-3 py-1", children: _jsx("textarea", { ref: textareaRef, value: value, rows: 1, onChange: (event) => handleChange(event.target.value), onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : t("thread_detail.input_placeholder"), "data-testid": "conversation-detail-message-input", className: "conversation-message-input-scrollbar min-h-0 min-w-0 flex-1 resize-none appearance-none border-0 bg-transparent p-0 text-[16px] leading-[1.6] tracking-[0.16px] text-black outline-none ring-0 placeholder:text-gray-400 focus:border-0 focus:outline-none focus:ring-0" }) }) }), _jsx("div", { className: "flex shrink-0 items-center pb-1", children: _jsx("button", { type: "button", onClick: () => void handleSend(), disabled: !canSend, "data-testid": "conversation-detail-send", className: clsx("flex h-10 w-10 items-center justify-center rounded-full", canSend ? "bg-chat-send" : "bg-chat-send opacity-25"), children: _jsx(Icon, { icon: "send-b", size: 20, className: "text-white" }) }) })] }), isMoreOptionOpen && (_jsx(ConversationMoreOptionPanel, { disabled: !isConversationReady, onTriggerMediaInput: () => { var _a; return (_a = mediaInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, onTriggerDocumentInput: () => { var _a; return (_a = documentInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); } }))] }));
|
|
258
258
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAkBzE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,QAAA,MAAM,uBAAuB,GAAI,gBAAgB,4BAA4B,4CAiK5E,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useCallback, useEffect, useState } from "react";
|
|
4
|
-
import { Empty, Spin } from "antd";
|
|
4
|
+
import { Empty, Spin, message as toastMessage } from "antd";
|
|
5
5
|
import { useEventListener } from "ahooks";
|
|
6
6
|
import { useTranslation } from "react-i18next";
|
|
7
7
|
import { useChatContext } from "../../context/ChatContext";
|
|
8
8
|
import MessageInfiniteScroll from "../../components/message/MessageInfiniteScroll";
|
|
9
9
|
import { useMessage } from "../../hooks/message/useMessage";
|
|
10
10
|
import { useMessageListScroll } from "../../hooks/message/useMessageListScroll";
|
|
11
|
+
import { usePinMessage } from "../../hooks/message/usePinMessage";
|
|
11
12
|
import useConversationStore from "../../store/conversation";
|
|
12
13
|
import useAuthStore from "../../store/auth";
|
|
13
14
|
import { isGroupChat as resolveIsGroupChat } from "../../utils/conversation";
|
|
14
15
|
import emitter from "../../utils/events";
|
|
15
16
|
import MessageItem from "../../components/message/item";
|
|
17
|
+
import PinLimitModal from "./PinLimitModal";
|
|
18
|
+
import { MAX_PINNED_MESSAGES_PER_CONVERSATION } from "../../constants";
|
|
16
19
|
const ConversationMessageList = ({ bottomSlot }) => {
|
|
17
20
|
const { t } = useTranslation("conversation-inbox");
|
|
21
|
+
const { t: tCommon } = useTranslation();
|
|
18
22
|
const { user } = useChatContext();
|
|
19
23
|
const authUserID = useAuthStore((state) => state.userID);
|
|
20
24
|
const conversation = useConversationStore((state) => state.conversationData);
|
|
@@ -30,6 +34,33 @@ const ConversationMessageList = ({ bottomSlot }) => {
|
|
|
30
34
|
const isMessageLoading = !conversationId || loadState.initLoading;
|
|
31
35
|
const [openToolboxMessageId, setOpenToolboxMessageId] = useState(null);
|
|
32
36
|
const closeToolbox = useCallback(() => setOpenToolboxMessageId(null), []);
|
|
37
|
+
const { pinMessage, unpinMessage } = usePinMessage();
|
|
38
|
+
const pinnedTotalCount = useConversationStore((state) => state.pinnedTotalCount);
|
|
39
|
+
const [pinLimitModalOpen, setPinLimitModalOpen] = useState(false);
|
|
40
|
+
const handlePinMessage = useCallback(async (message) => {
|
|
41
|
+
if (pinnedTotalCount >= MAX_PINNED_MESSAGES_PER_CONVERSATION) {
|
|
42
|
+
setPinLimitModalOpen(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
await pinMessage(conversationId, message.clientMsgID);
|
|
47
|
+
toastMessage.success(tCommon("pin_message_success"));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error("pinMessage failed", error);
|
|
51
|
+
toastMessage.error(tCommon("pin_message_failed"));
|
|
52
|
+
}
|
|
53
|
+
}, [conversationId, pinMessage, pinnedTotalCount, tCommon]);
|
|
54
|
+
const handleUnpinMessage = useCallback(async (message) => {
|
|
55
|
+
try {
|
|
56
|
+
await unpinMessage(conversationId, message.clientMsgID);
|
|
57
|
+
toastMessage.success(tCommon("unpin_message_success"));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error("unpinMessage failed", error);
|
|
61
|
+
toastMessage.error(tCommon("unpin_message_failed"));
|
|
62
|
+
}
|
|
63
|
+
}, [conversationId, unpinMessage, tCommon]);
|
|
33
64
|
const onPressQuoteMessage = useCallback((clientMsgID) => {
|
|
34
65
|
const hasMessage = loadState.messageList.some((msg) => msg.clientMsgID === clientMsgID);
|
|
35
66
|
if (hasMessage) {
|
|
@@ -51,6 +82,6 @@ const ConversationMessageList = ({ bottomSlot }) => {
|
|
|
51
82
|
target: scrollRef,
|
|
52
83
|
enable: !!openToolboxMessageId,
|
|
53
84
|
});
|
|
54
|
-
return (
|
|
85
|
+
return (_jsxs("div", { "data-testid": "conversation-message-list", className: "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden bg-white", children: [isMessageLoading ? (_jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Spin, {}) })) : (_jsxs(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableConversationMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, containerClassName: "h-full", empty: _jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Empty, { description: t("empty.no_messages") }) }), children: [bottomSlot, loadState.messageList.map((message, index, array) => (_jsx(MessageItem, { message: message, allMessages: array, isGroupChat: isGroupChat, forceHideTip: index === 0 && !!bottomSlot, contextMenuOpen: openToolboxMessageId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenToolboxMessageId(open ? message.clientMsgID : null), onQuoteMessage: setQuotedMessage, onRevokeMessage: closeToolbox, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: handlePinMessage, onUnpinMessage: handleUnpinMessage, enableLongPress: true }, message.clientMsgID)))] })), _jsx(PinLimitModal, { open: pinLimitModalOpen, onClose: () => setPinLimitModalOpen(false) })] }));
|
|
55
86
|
};
|
|
56
87
|
export default ConversationMessageList;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PinLimitModal.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinLimitModal.tsx"],"names":[],"mappings":"AAIA,UAAU,kBAAkB;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,aAAa,GAAI,mBAAmB,kBAAkB,4CAoC3D,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Modal, Button } from "antd";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { MAX_PINNED_MESSAGES_PER_CONVERSATION } from "../../constants";
|
|
5
|
+
const PinLimitModal = ({ open, onClose }) => {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
return (_jsx(Modal, { open: open, onCancel: onClose, footer: null, centered: true, width: 400, children: _jsxs("div", { className: "flex flex-col gap-2 pt-2", role: "alertdialog", "aria-label": t("pin_limit_modal_title"), children: [_jsx("p", { className: "text-lg font-semibold text-gray-900", children: t("pin_limit_modal_title") }), _jsx("p", { className: "text-base text-gray-600", children: t("pin_limit_modal_description", {
|
|
8
|
+
max: MAX_PINNED_MESSAGES_PER_CONVERSATION,
|
|
9
|
+
}) }), _jsx(Button, { type: "primary", size: "large", block: true, className: "mt-2", onClick: onClose, children: t("pin_limit_modal_confirm") })] }) }));
|
|
10
|
+
};
|
|
11
|
+
export default PinLimitModal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PinnedMessageBar.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageBar.tsx"],"names":[],"mappings":"AA8GA,QAAA,MAAM,gBAAgB,sDAuErB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import { MessageType } from "@openim/wasm-client-sdk";
|
|
6
|
+
import { Icon } from "../../components/icon";
|
|
7
|
+
import { documentIcon } from "../../assets/svg";
|
|
8
|
+
import useAuthStore from "../../store/auth";
|
|
9
|
+
import useConversationStore from "../../store/conversation";
|
|
10
|
+
import { usePinnedMessages } from "../../hooks/message/usePinnedMessages";
|
|
11
|
+
import { parseUrlMetadata } from "../../utils/common";
|
|
12
|
+
const PINNED_SUBTITLE_KEY_BY_TYPE = {
|
|
13
|
+
[MessageType.UrlTextMessage]: "pinned_from_link",
|
|
14
|
+
[MessageType.PictureMessage]: "pinned_from_image",
|
|
15
|
+
[MessageType.MergeMessage]: "pinned_from_image",
|
|
16
|
+
[MessageType.VideoMessage]: "pinned_from_video",
|
|
17
|
+
[MessageType.FileMessage]: "pinned_from_file",
|
|
18
|
+
};
|
|
19
|
+
const TITLE_LESS_MESSAGE_TYPES = [
|
|
20
|
+
MessageType.PictureMessage,
|
|
21
|
+
MessageType.MergeMessage,
|
|
22
|
+
MessageType.VideoMessage,
|
|
23
|
+
];
|
|
24
|
+
const getPinnedMessageTitle = (message) => {
|
|
25
|
+
var _a, _b, _c, _d, _e;
|
|
26
|
+
switch (message.contentType) {
|
|
27
|
+
case MessageType.UrlTextMessage: {
|
|
28
|
+
const urlMetadata = parseUrlMetadata(message.ex);
|
|
29
|
+
return ((urlMetadata === null || urlMetadata === void 0 ? void 0 : urlMetadata.title) ||
|
|
30
|
+
((_a = message.urlTextElem) === null || _a === void 0 ? void 0 : _a.content) ||
|
|
31
|
+
((_b = message.textElem) === null || _b === void 0 ? void 0 : _b.content) ||
|
|
32
|
+
"");
|
|
33
|
+
}
|
|
34
|
+
case MessageType.FileMessage:
|
|
35
|
+
return ((_c = message.fileElem) === null || _c === void 0 ? void 0 : _c.fileName) || "";
|
|
36
|
+
default:
|
|
37
|
+
return ((_d = message.textElem) === null || _d === void 0 ? void 0 : _d.content) || ((_e = message.quoteElem) === null || _e === void 0 ? void 0 : _e.text) || "";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const PinnedMessageThumbnail = ({ message }) => {
|
|
41
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
42
|
+
if (message.contentType === MessageType.FileMessage) {
|
|
43
|
+
return (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }));
|
|
44
|
+
}
|
|
45
|
+
if (message.contentType === MessageType.PictureMessage ||
|
|
46
|
+
message.contentType === MessageType.MergeMessage) {
|
|
47
|
+
const firstSubMessage = (_b = (_a = message.mergeElem) === null || _a === void 0 ? void 0 : _a.multiMessage) === null || _b === void 0 ? void 0 : _b[0];
|
|
48
|
+
const imageUrl = ((_d = (_c = firstSubMessage === null || firstSubMessage === void 0 ? void 0 : firstSubMessage.pictureElem) === null || _c === void 0 ? void 0 : _c.snapshotPicture) === null || _d === void 0 ? void 0 : _d.url) ||
|
|
49
|
+
((_f = (_e = firstSubMessage === null || firstSubMessage === void 0 ? void 0 : firstSubMessage.pictureElem) === null || _e === void 0 ? void 0 : _e.sourcePicture) === null || _f === void 0 ? void 0 : _f.url) ||
|
|
50
|
+
((_h = (_g = message.pictureElem) === null || _g === void 0 ? void 0 : _g.snapshotPicture) === null || _h === void 0 ? void 0 : _h.url) ||
|
|
51
|
+
((_k = (_j = message.pictureElem) === null || _j === void 0 ? void 0 : _j.sourcePicture) === null || _k === void 0 ? void 0 : _k.url);
|
|
52
|
+
if (!imageUrl)
|
|
53
|
+
return null;
|
|
54
|
+
return (_jsx("img", { src: imageUrl, alt: "", className: "h-[51px] w-[51px] shrink-0 object-cover" }));
|
|
55
|
+
}
|
|
56
|
+
if (message.contentType === MessageType.VideoMessage) {
|
|
57
|
+
const posterUrl = (_l = message.videoElem) === null || _l === void 0 ? void 0 : _l.snapshotUrl;
|
|
58
|
+
return (_jsxs("div", { className: "relative h-[51px] w-[51px] shrink-0 overflow-hidden bg-gray-900", children: [posterUrl && (_jsx("img", { src: posterUrl, alt: "", className: "h-full w-full object-cover" })), _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-black/60", children: _jsx(Icon, { icon: "play-o", size: 12, className: "text-white" }) }) })] }));
|
|
59
|
+
}
|
|
60
|
+
if (message.contentType === MessageType.UrlTextMessage) {
|
|
61
|
+
const imageUrl = (_m = parseUrlMetadata(message.ex)) === null || _m === void 0 ? void 0 : _m.image;
|
|
62
|
+
if (!imageUrl) {
|
|
63
|
+
return (_jsx("div", { className: "flex h-[51px] w-[51px] shrink-0 items-center justify-center", children: _jsx(Icon, { icon: "link-alt-o", size: 24, className: "text-primary-400" }) }));
|
|
64
|
+
}
|
|
65
|
+
return (_jsx("img", { src: imageUrl, alt: "", className: "h-[51px] w-[51px] shrink-0 object-cover" }));
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
};
|
|
69
|
+
const PinnedMessageBar = () => {
|
|
70
|
+
const { t } = useTranslation();
|
|
71
|
+
const userID = useAuthStore((state) => state.userID);
|
|
72
|
+
const conversation = useConversationStore((state) => state.conversationData);
|
|
73
|
+
const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
|
|
74
|
+
const conversationId = selectedConversationId || (conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) || "";
|
|
75
|
+
const { pinnedMessageList, pinnedTotalCount } = usePinnedMessages(conversationId);
|
|
76
|
+
const latestPinnedMessage = pinnedMessageList[0];
|
|
77
|
+
if (!latestPinnedMessage)
|
|
78
|
+
return null;
|
|
79
|
+
const isMe = latestPinnedMessage.sendID === userID;
|
|
80
|
+
const senderName = isMe
|
|
81
|
+
? t("your_self")
|
|
82
|
+
: latestPinnedMessage.senderNickname || t("message_sender_unnamed");
|
|
83
|
+
const subtitleKey = PINNED_SUBTITLE_KEY_BY_TYPE[latestPinnedMessage.contentType] ||
|
|
84
|
+
"pinned_from_text";
|
|
85
|
+
const title = getPinnedMessageTitle(latestPinnedMessage);
|
|
86
|
+
const showTitle = !TITLE_LESS_MESSAGE_TYPES.includes(latestPinnedMessage.contentType) &&
|
|
87
|
+
Boolean(title);
|
|
88
|
+
const hasThumbnail = latestPinnedMessage.contentType !== MessageType.TextMessage &&
|
|
89
|
+
latestPinnedMessage.contentType !== MessageType.QuoteMessage;
|
|
90
|
+
const hasFlushThumbnail = hasThumbnail &&
|
|
91
|
+
latestPinnedMessage.contentType !== MessageType.FileMessage;
|
|
92
|
+
const remainingPinnedCount = pinnedTotalCount - 1;
|
|
93
|
+
return (_jsxs("div", { "data-testid": "pinned-message-bar", className: clsx("flex w-full shrink-0 items-center gap-3 bg-gray-cool-25 pr-3", hasFlushThumbnail ? "py-0 pl-0" : "py-1 pl-3"), children: [hasThumbnail && _jsx(PinnedMessageThumbnail, { message: latestPinnedMessage }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [showTitle && (_jsx("p", { className: "truncate text-sm font-medium leading-[160%] text-gray-900", children: title })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: t(subtitleKey, { name: senderName }) })] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [remainingPinnedCount > 0 && (_jsxs("span", { className: "flex min-w-[26px] items-center justify-center rounded-full border-2 border-white bg-gradient-danger-light px-1 text-xs font-bold leading-[160%] text-white", children: ["+", remainingPinnedCount] })), _jsx(Icon, { icon: "angle-down-o", size: 20, className: "text-gray-600" })] })] }));
|
|
94
|
+
};
|
|
95
|
+
export default PinnedMessageBar;
|
|
@@ -3,6 +3,8 @@ export type { ConversationDetailHeaderProps } from "./ConversationDetailHeader";
|
|
|
3
3
|
export { default as ConversationDetailInput } from "./ConversationDetailInput";
|
|
4
4
|
export type { ConversationDetailInputProps } from "./ConversationDetailInput";
|
|
5
5
|
export { default as ConversationMessageList } from "./ConversationMessageList";
|
|
6
|
+
export { default as PinnedMessageBar } from "./PinnedMessageBar";
|
|
7
|
+
export { default as PinLimitModal } from "./PinLimitModal";
|
|
6
8
|
export { default as ConversationMoreOptionPanel } from "./ConversationMoreOptionPanel";
|
|
7
9
|
export type { ConversationMoreOptionPanelProps } from "./ConversationMoreOptionPanel";
|
|
8
10
|
export { default as ConversationMoreOptionItem } from "./ConversationMoreOptionItem";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,YAAY,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAEhF,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,YAAY,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AACrF,YAAY,EAAE,+BAA+B,EAAE,MAAM,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,YAAY,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAEhF,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,YAAY,EAAE,gCAAgC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AACrF,YAAY,EAAE,+BAA+B,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { default as ConversationDetailHeader } from "./ConversationDetailHeader";
|
|
2
2
|
export { default as ConversationDetailInput } from "./ConversationDetailInput";
|
|
3
3
|
export { default as ConversationMessageList } from "./ConversationMessageList";
|
|
4
|
+
export { default as PinnedMessageBar } from "./PinnedMessageBar";
|
|
5
|
+
export { default as PinLimitModal } from "./PinLimitModal";
|
|
4
6
|
export { default as ConversationMoreOptionPanel } from "./ConversationMoreOptionPanel";
|
|
5
7
|
export { default as ConversationMoreOptionItem } from "./ConversationMoreOptionItem";
|
|
@@ -3,5 +3,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { Icon } from "../../components/icon";
|
|
5
5
|
import { PeerType } from "../../types/conversation";
|
|
6
|
-
const ConversationInboxTitle = ({ peerType, displayName, hasUnread = false, }) => (_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [peerType === PeerType.GROUP && (_jsx(Icon, { icon: "user-two-b", size: 12, className: "shrink-0 text-black" })), peerType === PeerType.BOT && (_jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-black text-white", children: _jsx(Icon, { icon: "droppii-
|
|
6
|
+
const ConversationInboxTitle = ({ peerType, displayName, hasUnread = false, }) => (_jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [peerType === PeerType.GROUP && (_jsx(Icon, { icon: "user-two-b", size: 12, className: "shrink-0 text-black" })), peerType === PeerType.BOT && (_jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-black text-white", children: _jsx(Icon, { icon: "droppii-b", size: 8 }) })), _jsx("span", { className: clsx("min-w-0 truncate text-[16px] leading-[160%] text-black [font-feature-settings:'liga'_off,'clig'_off]", hasUnread ? "font-bold tracking-[0.16px]" : "font-[510]"), children: displayName })] }));
|
|
7
7
|
export default ConversationInboxTitle;
|
|
@@ -9,8 +9,10 @@ interface MessageItemProps {
|
|
|
9
9
|
onRevokeMessage?: (clientMsgID: string) => void;
|
|
10
10
|
onQuoteMessage?: (message: MessageItemType) => void;
|
|
11
11
|
onPressQuoteMessage?: (clientMsgID: string) => void;
|
|
12
|
+
onPinMessage?: (message: MessageItemType) => void;
|
|
13
|
+
onUnpinMessage?: (message: MessageItemType) => void;
|
|
12
14
|
enableLongPress?: boolean;
|
|
13
15
|
}
|
|
14
|
-
declare const MessageItem: ({ message, allMessages, isGroupChat, forceHideTip, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, enableLongPress, }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
16
|
+
declare const MessageItem: ({ message, allMessages, isGroupChat, forceHideTip, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, onPinMessage, onUnpinMessage, enableLongPress, }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
15
17
|
export default MessageItem;
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,yBAAyB,CAAC;AAwCjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAeD,QAAA,MAAM,WAAW,GAAI,qMAalB,gBAAgB,mDA4UlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -26,9 +26,9 @@ import RevokeMessageItem from "./RevokeMessage";
|
|
|
26
26
|
import QuoteMessageItem from "./QuoteMessage";
|
|
27
27
|
import SystemLogMessageItem from "./SystemLogMessage";
|
|
28
28
|
import { isSystemLogMessageType } from "../../../utils/messageLog";
|
|
29
|
-
import { buildMessageToolboxMenuItems, getCopyableMessageText, isCopyableMessageType, MessageToolboxActionKey, MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, useMessageToolboxVisibility, } from "../../../components/message/toolbox";
|
|
30
|
-
const MessageAvatar = ({ avatarUrl }) => avatarUrl ? (_jsx("img", { src: avatarUrl, alt: "", className: "h-6 w-6 shrink-0 self-end rounded-full object-cover" })) : (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center self-end rounded-full bg-chat-avatar", children: _jsx(Icon, { icon: "droppii-
|
|
31
|
-
const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip = false, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, enableLongPress = false, }) => {
|
|
29
|
+
import { buildMessageToolboxMenuItems, getCopyableMessageText, isCopyableMessageType, isPinnableMessageType, MessageToolboxActionKey, MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, useMessageToolboxVisibility, } from "../../../components/message/toolbox";
|
|
30
|
+
const MessageAvatar = ({ avatarUrl }) => avatarUrl ? (_jsx("img", { src: avatarUrl, alt: "", className: "h-6 w-6 shrink-0 self-end rounded-full object-cover" })) : (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center self-end rounded-full bg-chat-avatar", children: _jsx(Icon, { icon: "droppii-b", size: 14, className: "text-white" }) }));
|
|
31
|
+
const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip = false, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, onPinMessage, onUnpinMessage, enableLongPress = false, }) => {
|
|
32
32
|
var _a;
|
|
33
33
|
const { t } = useTranslation();
|
|
34
34
|
const { resendMessage } = useSendMessage();
|
|
@@ -74,12 +74,26 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
74
74
|
onClick: () => onQuoteMessage(message),
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
|
-
if (isDeliveredForUi
|
|
77
|
+
if (isDeliveredForUi &&
|
|
78
|
+
isPinnableMessageType(message === null || message === void 0 ? void 0 : message.contentType) &&
|
|
79
|
+
onPinMessage &&
|
|
80
|
+
onUnpinMessage) {
|
|
81
|
+
const isMessagePinned = Boolean(message === null || message === void 0 ? void 0 : message.isPinned);
|
|
78
82
|
actions.push({
|
|
79
|
-
key:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
key: isMessagePinned
|
|
84
|
+
? MessageToolboxActionKey.UNPIN
|
|
85
|
+
: MessageToolboxActionKey.PIN,
|
|
86
|
+
label: isMessagePinned ? t("context_menu_unpin") : t("context_menu_pin"),
|
|
87
|
+
icon: isMessagePinned ? "thumbtack-off-o" : "thumbtack-o",
|
|
88
|
+
onClick: () => {
|
|
89
|
+
if (isMessagePinned) {
|
|
90
|
+
onUnpinMessage(message);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
onPinMessage(message);
|
|
94
|
+
}
|
|
95
|
+
closeToolbox();
|
|
96
|
+
},
|
|
83
97
|
});
|
|
84
98
|
}
|
|
85
99
|
if (isDeliveredForUi && isCopyableMessageType(message === null || message === void 0 ? void 0 : message.contentType)) {
|
|
@@ -98,7 +112,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
98
112
|
actions.push({
|
|
99
113
|
key: MessageToolboxActionKey.REVOKE,
|
|
100
114
|
label: t("context_menu_revoke"),
|
|
101
|
-
icon: "trash-
|
|
115
|
+
icon: "trash-o",
|
|
102
116
|
danger: true,
|
|
103
117
|
onClick: () => onRevokeMessage((message === null || message === void 0 ? void 0 : message.clientMsgID) || ""),
|
|
104
118
|
});
|
|
@@ -111,6 +125,8 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
111
125
|
onRevokeMessage,
|
|
112
126
|
message,
|
|
113
127
|
onQuoteMessage,
|
|
128
|
+
onPinMessage,
|
|
129
|
+
onUnpinMessage,
|
|
114
130
|
onContextMenuOpenChange,
|
|
115
131
|
]);
|
|
116
132
|
const bubbleWrapperRef = useRef(null);
|
|
@@ -170,12 +186,14 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
170
186
|
return renderMessageByType(message);
|
|
171
187
|
};
|
|
172
188
|
const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent() }));
|
|
173
|
-
const
|
|
189
|
+
const showPinnedBadge = Boolean(message === null || message === void 0 ? void 0 : message.isPinned) && Boolean(onPinMessage);
|
|
190
|
+
const pinnedBadgeNode = showPinnedBadge ? (_jsx("span", { "data-testid": "message-pinned-badge", className: clsx("absolute -top-2.5 z-[1] flex h-[22px] w-[26px] items-center justify-center rounded-full border border-white bg-gray-25", isMine ? "left-0" : "right-0"), children: _jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }) })) : null;
|
|
191
|
+
const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { ref: bubbleWrapperRef, className: "relative min-w-0", children: [bubbleNode, pinnedBadgeNode] }) })) : (_jsxs("div", { className: "relative min-w-0", children: [bubbleNode, pinnedBadgeNode] }));
|
|
174
192
|
return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
|
|
175
193
|
timeBreakNode,
|
|
176
194
|
_jsxs("div", { className: clsx("flex min-w-0 items-end gap-1", isMine ? "justify-end pl-12 pr-3" : "justify-start pl-3 pr-12"), children: [!isMine &&
|
|
177
195
|
showPeerInfo &&
|
|
178
|
-
(showAvatar ? (_jsx(MessageAvatar, { avatarUrl: message === null || message === void 0 ? void 0 : message.senderFaceUrl })) : (_jsx("div", { className: "h-6 w-6 shrink-0 self-end" }))), _jsxs("div", { className: clsx("flex min-w-0 max-w-[75%] flex-col gap-1", isMine ? "items-end" : "items-start"), children: [_jsxs("div", { className: "flex items-end gap-1.5", children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), wrappedBubble] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "mt-1 text-xs text-red-500", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
|
|
196
|
+
(showAvatar ? (_jsx(MessageAvatar, { avatarUrl: message === null || message === void 0 ? void 0 : message.senderFaceUrl })) : (_jsx("div", { className: "h-6 w-6 shrink-0 self-end" }))), _jsxs("div", { className: clsx("flex min-w-0 max-w-[75%] flex-col gap-1", isMine ? "items-end" : "items-start"), children: [_jsxs("div", { className: clsx("flex items-end gap-1.5", showPinnedBadge && "mt-1.5"), children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), wrappedBubble] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "mt-1 text-xs text-red-500", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
|
|
179
197
|
bold: (_jsx("strong", { className: "cursor-pointer", onClick: () => resendMessage(message) })),
|
|
180
198
|
} })) : (t("message_send_failed_no_retry")) }))] })] })));
|
|
181
199
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReplyPreviewMedia.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewMedia.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAKnE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"ReplyPreviewMedia.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewMedia.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAKnE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,iBAAiB,GAAI,aAAa,sBAAsB,mDAoD7D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -2,20 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { MessageType } from "@openim/wasm-client-sdk";
|
|
3
3
|
import { documentIcon } from "../../../assets/svg";
|
|
4
4
|
import { Icon } from "../../../components/icon";
|
|
5
|
-
|
|
6
|
-
var _a;
|
|
7
|
-
if (!ex)
|
|
8
|
-
return undefined;
|
|
9
|
-
try {
|
|
10
|
-
const extendMessageInfo = JSON.parse(ex);
|
|
11
|
-
return (_a = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.urlMetadata) === null || _a === void 0 ? void 0 : _a.image;
|
|
12
|
-
}
|
|
13
|
-
catch (_b) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
};
|
|
5
|
+
import { parseUrlMetadata } from "../../../utils/common";
|
|
17
6
|
const ReplyPreviewMedia = ({ message }) => {
|
|
18
|
-
var _a, _b, _c, _d, _e;
|
|
7
|
+
var _a, _b, _c, _d, _e, _f;
|
|
19
8
|
if (message.contentType === MessageType.FileMessage) {
|
|
20
9
|
return (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }));
|
|
21
10
|
}
|
|
@@ -31,7 +20,7 @@ const ReplyPreviewMedia = ({ message }) => {
|
|
|
31
20
|
return (_jsxs("div", { className: "relative h-[42px] w-[42px] shrink-0 overflow-hidden rounded-lg bg-gray-900", children: [posterUrl && (_jsx("img", { src: posterUrl, alt: "", className: "h-full w-full object-cover" })), _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-black/60", children: _jsx(Icon, { icon: "play-o", size: 12, className: "text-white" }) }) })] }));
|
|
32
21
|
}
|
|
33
22
|
if (message.contentType === MessageType.UrlTextMessage) {
|
|
34
|
-
const imageUrl =
|
|
23
|
+
const imageUrl = (_f = parseUrlMetadata(message.ex)) === null || _f === void 0 ? void 0 : _f.image;
|
|
35
24
|
if (!imageUrl)
|
|
36
25
|
return null;
|
|
37
26
|
return (_jsx("img", { src: imageUrl, alt: "", className: "h-[42px] w-[42px] shrink-0 rounded-lg object-cover" }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isPinnableMessageType.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/isPinnableMessageType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAYtD,eAAO,MAAM,qBAAqB,GAAI,cAAc,WAAW,YACY,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MessageType } from "@openim/wasm-client-sdk";
|
|
2
|
+
const PINNABLE_MESSAGE_TYPES = [
|
|
3
|
+
MessageType.TextMessage,
|
|
4
|
+
MessageType.QuoteMessage,
|
|
5
|
+
MessageType.UrlTextMessage,
|
|
6
|
+
MessageType.PictureMessage,
|
|
7
|
+
MessageType.VideoMessage,
|
|
8
|
+
MessageType.FileMessage,
|
|
9
|
+
MessageType.MergeMessage
|
|
10
|
+
];
|
|
11
|
+
export const isPinnableMessageType = (contentType) => contentType !== undefined && PINNABLE_MESSAGE_TYPES.includes(contentType);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;CAM1B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,uBAAuB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAE3D,eAAO,MAAM,oCAAoC,IAAI,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const usePinMessage: () => {
|
|
2
|
+
pinMessage: (conversationID: string, clientMsgID: string) => Promise<void>;
|
|
3
|
+
unpinMessage: (conversationID: string, clientMsgID: string) => Promise<void>;
|
|
4
|
+
pinLoading: boolean;
|
|
5
|
+
unpinLoading: boolean;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=usePinMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePinMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/usePinMessage.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa;;;;;CA6CzB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useRequest } from "ahooks";
|
|
2
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
3
|
+
import useAuthStore from "../../store/auth";
|
|
4
|
+
import { updateOneMessage } from "../../hooks/message/useMessage";
|
|
5
|
+
import { fetchPinnedMessages } from "./usePinnedMessages";
|
|
6
|
+
export const usePinMessage = () => {
|
|
7
|
+
const userID = useAuthStore((state) => state.userID);
|
|
8
|
+
const { runAsync: pinMessage, loading: pinLoading } = useRequest(async (conversationID, clientMsgID) => {
|
|
9
|
+
await DChatSDK.pinMsg({
|
|
10
|
+
conversationID,
|
|
11
|
+
clientMsgID,
|
|
12
|
+
});
|
|
13
|
+
updateOneMessage({
|
|
14
|
+
clientMsgID,
|
|
15
|
+
isPinned: true,
|
|
16
|
+
pinnedByUserID: userID,
|
|
17
|
+
pinnedTime: Date.now(),
|
|
18
|
+
});
|
|
19
|
+
await fetchPinnedMessages(conversationID);
|
|
20
|
+
}, {
|
|
21
|
+
manual: true,
|
|
22
|
+
});
|
|
23
|
+
const { runAsync: unpinMessage, loading: unpinLoading } = useRequest(async (conversationID, clientMsgID) => {
|
|
24
|
+
await DChatSDK.unpinMsg({
|
|
25
|
+
conversationID,
|
|
26
|
+
clientMsgID,
|
|
27
|
+
});
|
|
28
|
+
updateOneMessage({
|
|
29
|
+
clientMsgID,
|
|
30
|
+
isPinned: false,
|
|
31
|
+
});
|
|
32
|
+
await fetchPinnedMessages(conversationID);
|
|
33
|
+
}, {
|
|
34
|
+
manual: true,
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
pinMessage,
|
|
38
|
+
unpinMessage,
|
|
39
|
+
pinLoading,
|
|
40
|
+
unpinLoading,
|
|
41
|
+
};
|
|
42
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const fetchPinnedMessages: (conversationID: string) => Promise<void>;
|
|
2
|
+
export declare const usePinnedMessages: (conversationID: string) => {
|
|
3
|
+
pinnedMessageList: import("@openim/wasm-client-sdk").MessageItem[];
|
|
4
|
+
pinnedTotalCount: number;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=usePinnedMessages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePinnedMessages.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/usePinnedMessages.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,GAAU,gBAAgB,MAAM,kBAmB/D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,MAAM;;;CAiBvD,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
3
|
+
import { PAGE_SIZE } from "../../constants";
|
|
4
|
+
import useConversationStore from "../../store/conversation";
|
|
5
|
+
export const fetchPinnedMessages = async (conversationID) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const { setPinnedMessageData } = useConversationStore.getState();
|
|
8
|
+
try {
|
|
9
|
+
const { data } = await DChatSDK.getPinnedMessageList({
|
|
10
|
+
conversationID,
|
|
11
|
+
offset: 0,
|
|
12
|
+
pageSize: PAGE_SIZE.small,
|
|
13
|
+
});
|
|
14
|
+
const sortedMessageList = [...(data.messageList || [])].sort((first, second) => (second.pinnedTime || 0) - (first.pinnedTime || 0));
|
|
15
|
+
setPinnedMessageData(sortedMessageList, data.totalCount || 0, (_a = data.isEnd) !== null && _a !== void 0 ? _a : true);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
console.error("fetchPinnedMessages failed", error);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const usePinnedMessages = (conversationID) => {
|
|
22
|
+
const pinnedMessageList = useConversationStore((state) => state.pinnedMessageList);
|
|
23
|
+
const pinnedTotalCount = useConversationStore((state) => state.pinnedTotalCount);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!conversationID)
|
|
26
|
+
return;
|
|
27
|
+
void fetchPinnedMessages(conversationID);
|
|
28
|
+
}, [conversationID]);
|
|
29
|
+
return {
|
|
30
|
+
pinnedMessageList,
|
|
31
|
+
pinnedTotalCount,
|
|
32
|
+
};
|
|
33
|
+
};
|