@droppii-org/chat-sdk 0.7.2 → 0.7.4
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/components/boot/BootProgressBar.d.ts +13 -0
- package/dist/components/boot/BootProgressBar.d.ts.map +1 -0
- package/dist/components/boot/BootProgressBar.js +18 -0
- package/dist/components/canned-response/CannedResponsePanel.d.ts.map +1 -1
- package/dist/components/canned-response/CannedResponsePanel.js +2 -2
- package/dist/components/common/BottomSheet.d.ts +18 -0
- package/dist/components/common/BottomSheet.d.ts.map +1 -0
- package/dist/components/common/BottomSheet.js +49 -0
- package/dist/components/common/DeskPanelDrawer.d.ts.map +1 -1
- package/dist/components/common/DeskPanelDrawer.js +29 -15
- package/dist/components/common/DeskSidePanel.d.ts.map +1 -1
- package/dist/components/common/DeskSidePanel.js +1 -1
- package/dist/components/compose/ComposeNewMessageModal.d.ts.map +1 -1
- package/dist/components/compose/ComposeNewMessageModal.js +3 -3
- package/dist/components/conversation/ConversationByGroupItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationByGroupItem.js +3 -8
- package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +3 -8
- package/dist/components/conversation/DeskConversationList.d.ts +4 -1
- package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
- package/dist/components/conversation/DeskConversationList.js +2 -2
- package/dist/components/conversation/DeskListHeader.d.ts +2 -0
- package/dist/components/conversation/DeskListHeader.d.ts.map +1 -1
- package/dist/components/conversation/DeskListHeader.js +3 -3
- package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.js +23 -5
- package/dist/components/conversation-inbox/ConversationInboxItem.d.ts.map +1 -1
- package/dist/components/conversation-inbox/ConversationInboxItem.js +1 -1
- package/dist/components/conversation-inbox/ConversationInboxList.d.ts.map +1 -1
- package/dist/components/conversation-inbox/ConversationInboxList.js +12 -3
- package/dist/components/conversation-inbox/InboxBootStatus.d.ts +10 -0
- package/dist/components/conversation-inbox/InboxBootStatus.d.ts.map +1 -0
- package/dist/components/conversation-inbox/InboxBootStatus.js +34 -0
- package/dist/components/conversation-inbox/InboxListSkeleton.d.ts +6 -0
- package/dist/components/conversation-inbox/InboxListSkeleton.d.ts.map +1 -0
- package/dist/components/conversation-inbox/InboxListSkeleton.js +8 -0
- package/dist/components/group/GroupPanelHeader.js +1 -1
- package/dist/components/icon/strokeIconNodes.d.ts +6 -0
- package/dist/components/icon/strokeIconNodes.d.ts.map +1 -1
- package/dist/components/icon/strokeIconNodes.js +5 -0
- package/dist/components/message/MessageHeader.d.ts +3 -1
- package/dist/components/message/MessageHeader.d.ts.map +1 -1
- package/dist/components/message/MessageHeader.js +10 -6
- package/dist/components/message/MessageList.d.ts +2 -0
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +15 -4
- package/dist/components/message/SelectSession.js +1 -1
- package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
- package/dist/components/message/footer/ActionBar.js +2 -2
- package/dist/components/message/footer/ComposerTabs.js +1 -1
- package/dist/components/message/footer/CrmComposerCard.js +1 -1
- package/dist/components/message/footer/EmojiPicker.d.ts +3 -1
- package/dist/components/message/footer/EmojiPicker.d.ts.map +1 -1
- package/dist/components/message/footer/EmojiPicker.js +3 -2
- package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
- package/dist/components/message/footer/EnterHandler.js +16 -2
- package/dist/components/message/footer/MediaActions.d.ts +2 -1
- package/dist/components/message/footer/MediaActions.d.ts.map +1 -1
- package/dist/components/message/footer/MediaActions.js +4 -4
- package/dist/components/message/footer/ToolbarPlugin.js +1 -1
- package/dist/components/message/footer/mention/MentionMenu.js +1 -1
- package/dist/components/message/headerIconButton.js +1 -1
- package/dist/components/message/item/ConsultantChatButton.d.ts +6 -0
- package/dist/components/message/item/ConsultantChatButton.d.ts.map +1 -0
- package/dist/components/message/item/ConsultantChatButton.js +19 -0
- package/dist/components/message/item/CustomMessage.d.ts.map +1 -1
- package/dist/components/message/item/CustomMessage.js +6 -1
- package/dist/components/message/item/EventMessage.d.ts +11 -0
- package/dist/components/message/item/EventMessage.d.ts.map +1 -0
- package/dist/components/message/item/EventMessage.js +28 -0
- package/dist/components/message/item/MessageMoreButton.d.ts.map +1 -1
- package/dist/components/message/item/MessageMoreButton.js +18 -5
- package/dist/components/message/item/QuoteMessage.d.ts.map +1 -1
- package/dist/components/message/item/QuoteMessage.js +3 -50
- package/dist/components/message/item/consultantCta.d.ts +8 -0
- package/dist/components/message/item/consultantCta.d.ts.map +1 -0
- package/dist/components/message/item/consultantCta.js +5 -0
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +10 -4
- package/dist/components/message/item/otherSenders.d.ts.map +1 -1
- package/dist/components/message/item/otherSenders.js +4 -1
- package/dist/components/message/reply/ReplyPreviewBar.d.ts.map +1 -1
- package/dist/components/message/reply/ReplyPreviewBar.js +4 -13
- package/dist/components/rich-text-editor/RichTextEditor.d.ts +3 -1
- package/dist/components/rich-text-editor/RichTextEditor.d.ts.map +1 -1
- package/dist/components/rich-text-editor/RichTextEditor.js +4 -2
- package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsGroup.js +3 -3
- package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsMessage.js +10 -0
- package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsUser.js +6 -0
- package/dist/components/session/DeskAssignedSession.js +2 -2
- package/dist/components/session/FolderRow.js +1 -1
- package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -1
- package/dist/components/thread/ManualAssignPopover.js +13 -6
- package/dist/components/thread/SessionDetailCard.js +1 -1
- package/dist/components/thread/SessionTagPicker.js +1 -1
- package/dist/components/thread/SupportSessionPanel.d.ts +1 -1
- package/dist/components/thread/SupportSessionPanel.d.ts.map +1 -1
- package/dist/components/thread/SupportSessionPanel.js +1 -1
- package/dist/components/thread/ThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/ThreadInfo.js +3 -1
- package/dist/components/thread/ThreadInfoHeader.d.ts +1 -1
- package/dist/components/thread/ThreadInfoHeader.d.ts.map +1 -1
- package/dist/components/thread/ThreadInfoHeader.js +1 -1
- package/dist/components/thread/UserSection.js +2 -2
- package/dist/constants/layout.d.ts +10 -1
- package/dist/constants/layout.d.ts.map +1 -1
- package/dist/constants/layout.js +10 -1
- package/dist/hooks/common/useDeskShortcuts.d.ts.map +1 -1
- package/dist/hooks/common/useDeskShortcuts.js +3 -1
- package/dist/hooks/common/useIsDeskWorkspaceMounted.d.ts +3 -0
- package/dist/hooks/common/useIsDeskWorkspaceMounted.d.ts.map +1 -0
- package/dist/hooks/common/useIsDeskWorkspaceMounted.js +4 -0
- package/dist/hooks/common/useViewportTier.d.ts +4 -0
- package/dist/hooks/common/useViewportTier.d.ts.map +1 -0
- package/dist/hooks/common/useViewportTier.js +9 -0
- package/dist/hooks/common/useVisualViewportHeight.d.ts +10 -0
- package/dist/hooks/common/useVisualViewportHeight.d.ts.map +1 -0
- package/dist/hooks/common/useVisualViewportHeight.js +30 -0
- package/dist/hooks/conversation/useConsultantChatNavigation.d.ts +12 -0
- package/dist/hooks/conversation/useConsultantChatNavigation.d.ts.map +1 -0
- package/dist/hooks/conversation/useConsultantChatNavigation.js +94 -0
- package/dist/hooks/conversation/useConversationList.d.ts.map +1 -1
- package/dist/hooks/conversation/useConversationList.js +31 -0
- package/dist/hooks/conversation/useDeskOfflineLock.d.ts +9 -0
- package/dist/hooks/conversation/useDeskOfflineLock.d.ts.map +1 -0
- package/dist/hooks/conversation/useDeskOfflineLock.js +46 -0
- package/dist/hooks/conversation/useDeskThreadNavigation.d.ts +19 -0
- package/dist/hooks/conversation/useDeskThreadNavigation.d.ts.map +1 -0
- package/dist/hooks/conversation/useDeskThreadNavigation.js +68 -0
- package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
- package/dist/hooks/global/useGlobalEvent.js +22 -2
- package/dist/hooks/group/useCreateGroup.d.ts.map +1 -1
- package/dist/hooks/group/useCreateGroup.js +4 -4
- package/dist/hooks/init/useChatBootPhase.d.ts +30 -0
- package/dist/hooks/init/useChatBootPhase.d.ts.map +1 -0
- package/dist/hooks/init/useChatBootPhase.js +72 -0
- package/dist/hooks/message/useMessage.d.ts +1 -1
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/useMessage.js +7 -4
- package/dist/hooks/message/useNewMessageAnnouncement.d.ts.map +1 -1
- package/dist/hooks/message/useNewMessageAnnouncement.js +3 -1
- package/dist/hooks/message/usePinMessage.d.ts +0 -2
- package/dist/hooks/message/usePinMessage.d.ts.map +1 -1
- package/dist/hooks/message/usePinMessage.js +7 -11
- package/dist/hooks/message/useQuotedSenderName.d.ts +14 -0
- package/dist/hooks/message/useQuotedSenderName.d.ts.map +1 -0
- package/dist/hooks/message/useQuotedSenderName.js +41 -0
- package/dist/hooks/user/useAuth.d.ts.map +1 -1
- package/dist/hooks/user/useAuth.js +2 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/locales/i18n.d.ts.map +1 -1
- package/dist/locales/i18n.js +3 -2
- package/dist/locales/i18n.ts +3 -2
- package/dist/locales/vi/boot.json +28 -0
- package/dist/locales/vi/common.json +2 -1
- package/dist/screens/conversation-detail/index.d.ts.map +1 -1
- package/dist/screens/conversation-detail/index.js +28 -4
- package/dist/screens/desk-message/DeskBootCard.d.ts +7 -0
- package/dist/screens/desk-message/DeskBootCard.d.ts.map +1 -0
- package/dist/screens/desk-message/DeskBootCard.js +69 -0
- package/dist/screens/desk-message/DeskOfflineOverlay.d.ts +10 -0
- package/dist/screens/desk-message/DeskOfflineOverlay.d.ts.map +1 -0
- package/dist/screens/desk-message/DeskOfflineOverlay.js +11 -0
- package/dist/screens/desk-message/DeskWorkspace.d.ts +7 -1
- package/dist/screens/desk-message/DeskWorkspace.d.ts.map +1 -1
- package/dist/screens/desk-message/DeskWorkspace.js +82 -13
- package/dist/screens/desk-message/DeskWorkspaceSkeleton.d.ts +10 -0
- package/dist/screens/desk-message/DeskWorkspaceSkeleton.d.ts.map +1 -0
- package/dist/screens/desk-message/DeskWorkspaceSkeleton.js +18 -0
- package/dist/screens/desk-message/PhoneThreadFallbackHeader.d.ts +8 -0
- package/dist/screens/desk-message/PhoneThreadFallbackHeader.d.ts.map +1 -0
- package/dist/screens/desk-message/PhoneThreadFallbackHeader.js +11 -0
- package/dist/screens/desk-message/index.d.ts +2 -0
- package/dist/screens/desk-message/index.d.ts.map +1 -1
- package/dist/screens/desk-message/index.js +47 -3
- package/dist/store/boot.d.ts +29 -0
- package/dist/store/boot.d.ts.map +1 -0
- package/dist/store/boot.js +21 -0
- package/dist/store/conversation.d.ts +2 -0
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +16 -12
- package/dist/store/deskPanelHost.d.ts +2 -0
- package/dist/store/deskPanelHost.d.ts.map +1 -1
- package/dist/store/deskPanelHost.js +1 -0
- package/dist/store/type.d.ts +12 -1
- package/dist/store/type.d.ts.map +1 -1
- package/dist/store/workspaceLayout.d.ts +3 -0
- package/dist/store/workspaceLayout.d.ts.map +1 -1
- package/dist/store/workspaceLayout.js +2 -0
- package/dist/styles/global.css +1 -1
- package/dist/types/customMessage.d.ts +17 -0
- package/dist/types/customMessage.d.ts.map +1 -1
- package/dist/types/customMessage.js +8 -0
- package/dist/utils/common.d.ts +2 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +14 -4
- package/dist/utils/conversation.d.ts +1 -0
- package/dist/utils/conversation.d.ts.map +1 -1
- package/dist/utils/conversation.js +1 -1
- package/dist/utils/customMessage.d.ts +7 -1
- package/dist/utils/customMessage.d.ts.map +1 -1
- package/dist/utils/customMessage.js +55 -1
- package/package.json +1 -1
- package/dist/screens/desk-message/ViewportNotice.d.ts +0 -4
- package/dist/screens/desk-message/ViewportNotice.d.ts.map +0 -1
- package/dist/screens/desk-message/ViewportNotice.js +0 -9
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type BootProgressBarMode = "pending" | "indeterminate" | "progress" | "complete";
|
|
2
|
+
interface BootProgressBarProps {
|
|
3
|
+
mode: BootProgressBarMode;
|
|
4
|
+
/** 0-100, read in "progress" mode. */
|
|
5
|
+
value?: number;
|
|
6
|
+
/** Accessible name, announced only in "progress" mode. */
|
|
7
|
+
label?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Thin bar for one boot step: not started, running for an unknown time, a known percentage, or done. */
|
|
11
|
+
declare const BootProgressBar: ({ mode, value, label, className }: BootProgressBarProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export default BootProgressBar;
|
|
13
|
+
//# sourceMappingURL=BootProgressBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BootProgressBar.d.ts","sourceRoot":"","sources":["../../../src/components/boot/BootProgressBar.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,eAAe,GAAG,UAAU,GAAG,UAAU,CAAC;AAExF,UAAU,oBAAoB;IAC5B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yGAAyG;AACzG,QAAA,MAAM,eAAe,GAAI,mCAAuC,oBAAoB,4CAiCnF,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
/** Thin bar for one boot step: not started, running for an unknown time, a known percentage, or done. */
|
|
5
|
+
const BootProgressBar = ({ mode, value = 0, label, className }) => {
|
|
6
|
+
const scale = mode === "complete" ? 1 : mode === "progress" ? value / 100 : 0;
|
|
7
|
+
const a11yProps = mode === "progress"
|
|
8
|
+
? {
|
|
9
|
+
role: "progressbar",
|
|
10
|
+
"aria-label": label,
|
|
11
|
+
"aria-valuemin": 0,
|
|
12
|
+
"aria-valuemax": 100,
|
|
13
|
+
"aria-valuenow": Math.round(value),
|
|
14
|
+
}
|
|
15
|
+
: { "aria-hidden": true };
|
|
16
|
+
return (_jsx("div", Object.assign({ "data-cp-name": "BootProgressBar", "data-mode": mode, className: clsx("relative h-1 overflow-hidden rounded-full bg-[var(--dc-color-primary-light)]", className) }, a11yProps, { children: mode === "indeterminate" ? (_jsx("span", { className: "absolute inset-y-0 left-0 w-full rounded-full bg-[var(--dc-color-primary)] opacity-40 motion-safe:w-[35%] motion-safe:animate-[dchat-boot-indeterminate_1.3s_ease-in-out_infinite] motion-safe:opacity-100" })) : (_jsx("span", { className: "absolute inset-0 origin-left rounded-full bg-[var(--dc-color-primary)] transition-transform duration-300 ease-out motion-reduce:transition-none", style: { transform: `scaleX(${scale})` } })) })));
|
|
17
|
+
};
|
|
18
|
+
export default BootProgressBar;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CannedResponsePanel.d.ts","sourceRoot":"","sources":["../../../src/components/canned-response/CannedResponsePanel.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,mBAAmB,EAA8B,MAAM,cAAc,CAAC;AAQ/E,UAAU,wBAAwB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACnD;AAaD,QAAA,MAAM,mBAAmB,GAAI,oCAI1B,wBAAwB,
|
|
1
|
+
{"version":3,"file":"CannedResponsePanel.d.ts","sourceRoot":"","sources":["../../../src/components/canned-response/CannedResponsePanel.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,mBAAmB,EAA8B,MAAM,cAAc,CAAC;AAQ/E,UAAU,wBAAwB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACnD;AAaD,QAAA,MAAM,mBAAmB,GAAI,oCAI1B,wBAAwB,4CAmJ1B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -65,8 +65,8 @@ const CannedResponsePanel = ({ query, viewedTeamId, onCreate, }) => {
|
|
|
65
65
|
};
|
|
66
66
|
const noQuery = query.length === 0;
|
|
67
67
|
const empty = !noQuery && !settling && !isLoading && rows.length === 0;
|
|
68
|
-
return (_jsxs("div", { "data-cp-name": "CannedResponsePanel", role: "region", "aria-label": t("composer_quick_reply"), className: "absolute inset-x-4 bottom-full z-20 mb-2 overflow-hidden rounded-xl bg-white shadow-[0_16px_16px_-8px_rgba(27,63,228,0.2),0_0_0_1px_rgba(57,62,64,0.06)]", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-gray-25 px-3 py-2.5", children: [_jsx("span", { className: "shrink-0 text-[13px] font-semibold text-gray-900", children: t("composer_quick_reply") }), _jsx("span", { className: "flex-1" }), _jsx(CannedScopeChips, { scopes: scopes, value: filter, onChange: setFilter })] }), _jsxs("div", { className: "max-h-[260px] min-h-[96px] overflow-y-auto p-1", children: [noQuery && (_jsx("p", { className: "px-3 py-6 text-center text-sm text-gray-600", children: t("canned_search_prompt") })), !noQuery && (settling || isLoading) && (_jsx("div", { className: "flex justify-center py-6", children: _jsx(Spin, { size: "small" }) })), isError && !settling && (_jsx("p", { role: "alert", className: "px-3 py-6 text-center text-sm text-danger-600", children: t("canned_loading_failed") })), empty && !isError && (_jsxs("div", { className: "flex flex-col items-center gap-3 px-3 py-5", children: [_jsx("p", { className: "text-center text-sm text-gray-600", children: t("canned_search_empty", { query }) }), _jsxs("button", { type: "button", tabIndex: -1, onMouseDown: (e) => e.preventDefault(), onClick: create, className: "flex h-8 items-center gap-1.5 rounded-lg border border-gray-50 bg-white px-3.5 text-sm font-medium text-gray-900 hover:bg-gray-5", children: [_jsx(StrokeIcon, { name: "plus", size: 16 }), t("canned_create_new")] })] })), !settling && rows.length > 0 && (_jsx("ul", { className: "m-0 flex list-none flex-col gap-0.5 p-0", children: rows.map((row, index) => (_jsx(CannedResponseRow, { ref: (el) => {
|
|
68
|
+
return (_jsxs("div", { "data-cp-name": "CannedResponsePanel", role: "region", "aria-label": t("composer_quick_reply"), className: "absolute inset-x-4 bottom-full z-20 mb-2 overflow-hidden rounded-xl bg-white shadow-[0_16px_16px_-8px_rgba(27,63,228,0.2),0_0_0_1px_rgba(57,62,64,0.06)]", children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-gray-25 px-3 py-2.5", children: [_jsx("span", { className: "shrink-0 text-[13px] font-semibold text-gray-900", children: t("composer_quick_reply") }), _jsx("span", { className: "flex-1" }), _jsx(CannedScopeChips, { scopes: scopes, value: filter, onChange: setFilter })] }), _jsxs("div", { className: "max-h-[260px] min-h-[96px] touch:min-h-0 touch:max-h-[min(260px,calc(var(--dc-desk-height,100dvh)-var(--dc-composer-reserve,280px)))] overflow-y-auto p-1", children: [noQuery && (_jsx("p", { className: "px-3 py-6 text-center text-sm text-gray-600", children: t("canned_search_prompt") })), !noQuery && (settling || isLoading) && (_jsx("div", { className: "flex justify-center py-6", children: _jsx(Spin, { size: "small" }) })), isError && !settling && (_jsx("p", { role: "alert", className: "px-3 py-6 text-center text-sm text-danger-600", children: t("canned_loading_failed") })), empty && !isError && (_jsxs("div", { className: "flex flex-col items-center gap-3 px-3 py-5", children: [_jsx("p", { className: "text-center text-sm text-gray-600", children: t("canned_search_empty", { query }) }), _jsxs("button", { type: "button", tabIndex: -1, onMouseDown: (e) => e.preventDefault(), onClick: create, className: "flex h-8 items-center gap-1.5 rounded-lg border border-gray-50 bg-white px-3.5 text-sm font-medium text-gray-900 hover:bg-gray-5", children: [_jsx(StrokeIcon, { name: "plus", size: 16 }), t("canned_create_new")] })] })), !settling && rows.length > 0 && (_jsx("ul", { className: "m-0 flex list-none flex-col gap-0.5 p-0", children: rows.map((row, index) => (_jsx(CannedResponseRow, { ref: (el) => {
|
|
69
69
|
itemRefs.current[index] = el;
|
|
70
|
-
}, row: row, preview: toPreview(row.content || ""), active: index === activeCannedIndex, onSelect: () => insertRow(row) }, row.id))) }))] }), _jsxs("div", { className: "flex items-center gap-2 border-t border-gray-25 px-3 py-2 text-xs text-gray-600", children: [_jsx(Kbd, { children: "\u2191" }), _jsx(Kbd, { children: "\u2193" }), " ", t("canned_hint_select"), " \u00B7 ", _jsx(Kbd, { children: "Enter" }), " ", t("canned_hint_insert"), " \u00B7", " ", _jsx(Kbd, { children: "Esc" }), " ", t("canned_hint_close"), _jsx("span", { className: "flex-1" }), _jsxs("button", { type: "button", tabIndex: -1, onMouseDown: (e) => e.preventDefault(), onClick: create, className: "flex h-7 items-center gap-1.5 rounded-lg px-2 text-[13px] font-medium text-primary-500 hover:bg-primary-25", children: [_jsx(StrokeIcon, { name: "plus", size: 16 }), t("canned_create_quick")] })] })] }));
|
|
70
|
+
}, row: row, preview: toPreview(row.content || ""), active: index === activeCannedIndex, onSelect: () => insertRow(row) }, row.id))) }))] }), _jsxs("div", { className: "flex items-center gap-2 border-t border-gray-25 px-3 py-2 text-xs text-gray-600", children: [_jsxs("span", { className: "contents touch:hidden", children: [_jsx(Kbd, { children: "\u2191" }), _jsx(Kbd, { children: "\u2193" }), " ", t("canned_hint_select"), " \u00B7 ", _jsx(Kbd, { children: "Enter" }), " ", t("canned_hint_insert"), " \u00B7", " ", _jsx(Kbd, { children: "Esc" }), " ", t("canned_hint_close")] }), _jsx("span", { className: "flex-1" }), _jsxs("button", { type: "button", tabIndex: -1, onMouseDown: (e) => e.preventDefault(), onClick: create, className: "flex h-7 items-center gap-1.5 rounded-lg px-2 text-[13px] font-medium text-primary-500 hover:bg-primary-25", children: [_jsx(StrokeIcon, { name: "plus", size: 16 }), t("canned_create_quick")] })] })] }));
|
|
71
71
|
};
|
|
72
72
|
export default CannedResponsePanel;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
interface BottomSheetProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
title: string;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/** Row style for actions inside a BottomSheet: 48px minimum hit area. */
|
|
9
|
+
export declare const BOTTOM_SHEET_ROW = "flex min-h-12 w-full items-center gap-3 rounded-lg px-3 text-left text-base text-gray-900 active:bg-gray-5";
|
|
10
|
+
/**
|
|
11
|
+
* After a sheet closes, rc-drawer refocuses its trigger; hand focus to a modal the sheet's
|
|
12
|
+
* action opened (one not in `alreadyOpen`), via a node rc-dialog makes focusable.
|
|
13
|
+
*/
|
|
14
|
+
export declare const restoreModalFocus: (alreadyOpen?: ReadonlySet<HTMLElement>) => number;
|
|
15
|
+
/** CRM bottom sheet for phone actions: fixed 56px header, rows scroll within 85dvh. */
|
|
16
|
+
declare const BottomSheet: ({ open, title, onClose, children }: BottomSheetProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default BottomSheet;
|
|
18
|
+
//# sourceMappingURL=BottomSheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/components/common/BottomSheet.tsx"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI1D,UAAU,gBAAgB;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,+GACiF,CAAC;AAO/G;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,cAAa,WAAW,CAAC,WAAW,CAAa,WAW5C,CAAC;AAER,uFAAuF;AACvF,QAAA,MAAM,WAAW,GAAI,oCAAoC,gBAAgB,4CA0CxE,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { Drawer } from "antd";
|
|
5
|
+
import GroupPanelHeader from "../../components/group/GroupPanelHeader";
|
|
6
|
+
/** Row style for actions inside a BottomSheet: 48px minimum hit area. */
|
|
7
|
+
export const BOTTOM_SHEET_ROW = "flex min-h-12 w-full items-center gap-3 rounded-lg px-3 text-left text-base text-gray-900 active:bg-gray-5";
|
|
8
|
+
const visibleModalWraps = () => Array.from(document.querySelectorAll(".ant-modal-wrap")).filter((wrap) => wrap.style.display !== "none");
|
|
9
|
+
/**
|
|
10
|
+
* After a sheet closes, rc-drawer refocuses its trigger; hand focus to a modal the sheet's
|
|
11
|
+
* action opened (one not in `alreadyOpen`), via a node rc-dialog makes focusable.
|
|
12
|
+
*/
|
|
13
|
+
export const restoreModalFocus = (alreadyOpen = new Set()) => window.setTimeout(() => {
|
|
14
|
+
var _a;
|
|
15
|
+
const wrap = visibleModalWraps()
|
|
16
|
+
.filter((candidate) => !alreadyOpen.has(candidate))
|
|
17
|
+
.pop();
|
|
18
|
+
if (!wrap || wrap.contains(document.activeElement))
|
|
19
|
+
return;
|
|
20
|
+
const target = (_a = wrap.querySelector('[role="dialog"] > [tabindex="0"]')) !== null && _a !== void 0 ? _a : wrap;
|
|
21
|
+
target.focus({ preventScroll: true });
|
|
22
|
+
}, 0);
|
|
23
|
+
/** CRM bottom sheet for phone actions: fixed 56px header, rows scroll within 85dvh. */
|
|
24
|
+
const BottomSheet = ({ open, title, onClose, children }) => {
|
|
25
|
+
const modalsAtOpen = useRef(new Set());
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (open)
|
|
28
|
+
modalsAtOpen.current = new Set(visibleModalWraps());
|
|
29
|
+
}, [open]);
|
|
30
|
+
return (_jsxs(Drawer, { open: open, "aria-label": title, onClose: onClose, afterOpenChange: (opened) => {
|
|
31
|
+
if (!opened)
|
|
32
|
+
restoreModalFocus(modalsAtOpen.current);
|
|
33
|
+
}, placement: "bottom", height: "auto", closeIcon: false, destroyOnHidden: true, styles: {
|
|
34
|
+
mask: { background: "rgba(57, 62, 64, 0.45)" },
|
|
35
|
+
wrapper: {
|
|
36
|
+
borderTopLeftRadius: 12,
|
|
37
|
+
borderTopRightRadius: 12,
|
|
38
|
+
overflow: "hidden",
|
|
39
|
+
},
|
|
40
|
+
content: { maxHeight: "min(85dvh, var(--dc-visual-height, 85dvh))" },
|
|
41
|
+
body: {
|
|
42
|
+
padding: 0,
|
|
43
|
+
display: "flex",
|
|
44
|
+
flexDirection: "column",
|
|
45
|
+
minHeight: 0,
|
|
46
|
+
},
|
|
47
|
+
}, children: [_jsx(GroupPanelHeader, { title: title, onClose: onClose }), _jsx("div", { "data-desk-shortcuts-off": true, className: "min-h-0 flex-1 overflow-y-auto px-2 pt-1 pb-[max(12px,env(safe-area-inset-bottom))]", children: children })] }));
|
|
48
|
+
};
|
|
49
|
+
export default BottomSheet;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskPanelDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/common/DeskPanelDrawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DeskPanelDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/common/DeskPanelDrawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,UAAU,oBAAoB;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,qFAAqF;IACrF,SAAS,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,gHAAgH;AAChH,QAAA,MAAM,eAAe,GAAI,qEAQtB,oBAAoB,4CA4CtB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Drawer } from "antd";
|
|
4
|
+
import useDeskPanelHostStore from "../../store/deskPanelHost";
|
|
4
5
|
import { LAYOUT_WIDTHS } from "../../constants/layout";
|
|
5
6
|
/** Overlay drawer for a desk side panel (inset 8px, rounded, light scrim). Sits below modals opened from it. */
|
|
6
|
-
const DeskPanelDrawer = ({ open, label, onClose, container, autoFocus = true, keyboard = true, children, }) =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
const DeskPanelDrawer = ({ open, label, onClose, container, autoFocus = true, keyboard = true, children, }) => {
|
|
8
|
+
const isFullScreen = useDeskPanelHostStore((state) => state.isFullScreen);
|
|
9
|
+
return (_jsx(Drawer, { open: open, "aria-label": label, onClose: onClose, autoFocus: autoFocus, keyboard: keyboard,
|
|
10
|
+
// antd slides a drawer 180px aside when one opens inside it; panels here stack in place.
|
|
11
|
+
push: false, destroyOnHidden: true, closeIcon: false, getContainer: container !== null && container !== void 0 ? container : false, rootStyle: { position: "absolute" }, zIndex: 900, width: isFullScreen ? "100%" : LAYOUT_WIDTHS.infoDrawer, styles: {
|
|
12
|
+
mask: { background: "rgba(57, 62, 64, 0.16)" },
|
|
13
|
+
wrapper: isFullScreen
|
|
14
|
+
? {
|
|
15
|
+
top: 0,
|
|
16
|
+
right: 0,
|
|
17
|
+
bottom: 0,
|
|
18
|
+
height: "auto",
|
|
19
|
+
borderRadius: 0,
|
|
20
|
+
overflow: "hidden",
|
|
21
|
+
boxShadow: "none",
|
|
22
|
+
}
|
|
23
|
+
: {
|
|
24
|
+
top: 8,
|
|
25
|
+
right: 8,
|
|
26
|
+
bottom: 8,
|
|
27
|
+
height: "auto",
|
|
28
|
+
borderRadius: 12,
|
|
29
|
+
overflow: "hidden",
|
|
30
|
+
boxShadow: "0 8px 24px rgba(57, 62, 64, 0.16)",
|
|
31
|
+
},
|
|
32
|
+
body: { padding: 0, background: "transparent" },
|
|
33
|
+
}, children: children }));
|
|
34
|
+
};
|
|
21
35
|
export default DeskPanelDrawer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskSidePanel.d.ts","sourceRoot":"","sources":["../../../src/components/common/DeskSidePanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,UAAU,kBAAkB;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uEAAuE;IACvE,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAC;CAC5C;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,GAAI,gDAMpB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"DeskSidePanel.d.ts","sourceRoot":"","sources":["../../../src/components/common/DeskSidePanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,UAAU,kBAAkB;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uEAAuE;IACvE,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAC;CAC5C;AAED;;;GAGG;AACH,QAAA,MAAM,aAAa,GAAI,gDAMpB,kBAAkB,mDAmCpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -16,7 +16,7 @@ const DeskSidePanel = ({ open, label, onClose, autoFocus, children, }) => {
|
|
|
16
16
|
: null;
|
|
17
17
|
}
|
|
18
18
|
if (host.workspace) {
|
|
19
|
-
return (_jsx(DeskPanelDrawer, { open: open, label: label, onClose: onClose, container: host.workspace, autoFocus: autoFocus, children: _jsx("div", { className:
|
|
19
|
+
return (_jsx(DeskPanelDrawer, { open: open, label: label, onClose: onClose, container: host.workspace, autoFocus: autoFocus, children: _jsx("div", { className: `h-full overflow-hidden bg-white ${host.isFullScreen ? "" : "rounded-xl"}`, children: children(false) }) }));
|
|
20
20
|
}
|
|
21
21
|
return null;
|
|
22
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposeNewMessageModal.d.ts","sourceRoot":"","sources":["../../../src/components/compose/ComposeNewMessageModal.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAID,QAAA,MAAM,sBAAsB,GAAI,oBAG7B,2BAA2B,
|
|
1
|
+
{"version":3,"file":"ComposeNewMessageModal.d.ts","sourceRoot":"","sources":["../../../src/components/compose/ComposeNewMessageModal.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAID,QAAA,MAAM,sBAAsB,GAAI,oBAG7B,2BAA2B,4CA2O7B,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -14,7 +14,7 @@ import CreateGroupForm from "../../components/group/CreateGroupForm";
|
|
|
14
14
|
import useAuthStore from "../../store/auth";
|
|
15
15
|
import { StrokeIcon } from "../../components/icon/StrokeIcon";
|
|
16
16
|
import TintedAvatar from "../../components/common/TintedAvatar";
|
|
17
|
-
import {
|
|
17
|
+
import { useDeskThreadNavigation } from "../../hooks/conversation/useDeskThreadNavigation";
|
|
18
18
|
const ComposeNewMessageModal = ({ open, onClose, }) => {
|
|
19
19
|
const { t } = useTranslation("conversation-inbox");
|
|
20
20
|
const isCrm = useAuthStore((state) => state.isCrm);
|
|
@@ -24,7 +24,7 @@ const ComposeNewMessageModal = ({ open, onClose, }) => {
|
|
|
24
24
|
const [openingUserID, setOpeningUserID] = useState(null);
|
|
25
25
|
const debouncedSearch = useDebounce(search, { wait: 300 });
|
|
26
26
|
const { accounts, isLoading } = useEligibleAccounts(debouncedSearch, open);
|
|
27
|
-
const
|
|
27
|
+
const { openThread } = useDeskThreadNavigation();
|
|
28
28
|
const setConversationData = useConversationStore((state) => state.setConversationData);
|
|
29
29
|
const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
|
|
30
30
|
const handleClose = () => {
|
|
@@ -53,7 +53,7 @@ const ComposeNewMessageModal = ({ open, onClose, }) => {
|
|
|
53
53
|
newSearchParams.delete("userId");
|
|
54
54
|
newSearchParams.delete("groupId");
|
|
55
55
|
newSearchParams.delete("botId");
|
|
56
|
-
|
|
56
|
+
openThread({ threadId: conversation.conversationID }, `${window.location.pathname}?${newSearchParams.toString()}`);
|
|
57
57
|
handleClose();
|
|
58
58
|
}
|
|
59
59
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationByGroupItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationByGroupItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAaxF,UAAU,4BAA4B;IACpC,KAAK,EAAE,4BAA4B,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,QAAA,MAAM,uBAAuB,GAAI,2BAG9B,4BAA4B,
|
|
1
|
+
{"version":3,"file":"ConversationByGroupItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationByGroupItem.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAaxF,UAAU,4BAA4B;IACpC,KAAK,EAAE,4BAA4B,CAAC;IACpC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,QAAA,MAAM,uBAAuB,GAAI,2BAG9B,4BAA4B,4CA8D9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import useConversationStore from "../../store/conversation";
|
|
5
5
|
import { useChatContext } from "../../context/ChatContext";
|
|
6
|
-
import {
|
|
6
|
+
import { useDeskThreadNavigation } from "../../hooks/conversation/useDeskThreadNavigation";
|
|
7
7
|
import { parseLatestMessage } from "../../utils/common";
|
|
8
8
|
import GroupCompositeAvatar from "../../components/group/GroupCompositeAvatar";
|
|
9
9
|
import DeskConversationRow from "./DeskConversationRow";
|
|
@@ -15,7 +15,7 @@ import MentionIndicatorIcon from "./MentionIndicatorIcon";
|
|
|
15
15
|
const ConversationByGroupItem = ({ group, latestPreview, }) => {
|
|
16
16
|
const { t } = useTranslation();
|
|
17
17
|
const { user } = useChatContext();
|
|
18
|
-
const
|
|
18
|
+
const { openFromList } = useDeskThreadNavigation();
|
|
19
19
|
const setConversationData = useConversationStore((state) => state.setConversationData);
|
|
20
20
|
const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
|
|
21
21
|
const isSelected = useConversationStore((state) => state.selectedConversationId === group.conversationId);
|
|
@@ -23,12 +23,7 @@ const ConversationByGroupItem = ({ group, latestPreview, }) => {
|
|
|
23
23
|
const handleClick = () => {
|
|
24
24
|
setConversationData(conversation);
|
|
25
25
|
setSelectedConversationId(conversation.conversationID);
|
|
26
|
-
|
|
27
|
-
newSearchParams.set("threadId", conversation.conversationID);
|
|
28
|
-
newSearchParams.delete("userId");
|
|
29
|
-
newSearchParams.delete("groupId");
|
|
30
|
-
newSearchParams.delete("botId");
|
|
31
|
-
onNavigate(`${window.location.pathname}?${newSearchParams.toString()}`);
|
|
26
|
+
openFromList({ threadId: conversation.conversationID });
|
|
32
27
|
};
|
|
33
28
|
const latestMsg = (latestPreview === null || latestPreview === void 0 ? void 0 : latestPreview.latestMsg) || "";
|
|
34
29
|
const latestMsgSendTime = (latestPreview === null || latestPreview === void 0 ? void 0 : latestPreview.latestMsgSendTime) || 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationBySessionItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationBySessionItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQhD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU1C,UAAU,8BAA8B;IACtC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,qFAAqF;IACrF,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB;AAaD,QAAA,MAAM,yBAAyB,GAAI,4CAIhC,8BAA8B,
|
|
1
|
+
{"version":3,"file":"ConversationBySessionItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationBySessionItem.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQhD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAU1C,UAAU,8BAA8B;IACtC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,qFAAqF;IACrF,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB;AAaD,QAAA,MAAM,yBAAyB,GAAI,4CAIhC,8BAA8B,mDAiGhC,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { PeerType } from "../../types/conversation";
|
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import useConversationStore from "../../store/conversation";
|
|
6
6
|
import { useChatContext } from "../../context/ChatContext";
|
|
7
|
-
import {
|
|
7
|
+
import { useDeskThreadNavigation } from "../../hooks/conversation/useDeskThreadNavigation";
|
|
8
8
|
import { useConversationDisplayData } from "../../hooks/conversation/useConversation";
|
|
9
9
|
import { isGroupSession } from "../../utils/imCommon";
|
|
10
10
|
import { resolveBotSessionOwnerIdentity } from "../../utils/conversation";
|
|
@@ -29,7 +29,7 @@ const ConversationBySessionItem = ({ sessionItem, latestPreview, folderTag, }) =
|
|
|
29
29
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
30
30
|
const { t } = useTranslation();
|
|
31
31
|
const { user } = useChatContext();
|
|
32
|
-
const
|
|
32
|
+
const { openFromList } = useDeskThreadNavigation();
|
|
33
33
|
const isSelected = useConversationStore((state) => {
|
|
34
34
|
var _a;
|
|
35
35
|
return state.selectedConversationId ===
|
|
@@ -40,12 +40,7 @@ const ConversationBySessionItem = ({ sessionItem, latestPreview, folderTag, }) =
|
|
|
40
40
|
const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
|
|
41
41
|
const handleConversationClick = (conversation) => {
|
|
42
42
|
setConversationData(conversation);
|
|
43
|
-
|
|
44
|
-
newSearchParams.set("threadId", conversation.conversationID);
|
|
45
|
-
newSearchParams.delete("userId");
|
|
46
|
-
newSearchParams.delete("groupId");
|
|
47
|
-
newSearchParams.delete("botId");
|
|
48
|
-
onNavigate(`${window.location.pathname}?${newSearchParams.toString()}`);
|
|
43
|
+
openFromList({ threadId: conversation.conversationID });
|
|
49
44
|
setSelectedConversationId(conversation.conversationID);
|
|
50
45
|
};
|
|
51
46
|
const { avatar, displayName = "" } = useConversationDisplayData(conversation || null);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
interface DeskConversationListProps {
|
|
2
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
3
|
+
}
|
|
4
|
+
declare const DeskConversationList: ({ onOpenAppMenu }: DeskConversationListProps) => import("react/jsx-runtime").JSX.Element;
|
|
2
5
|
export default DeskConversationList;
|
|
3
6
|
//# sourceMappingURL=DeskConversationList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AA+BA,QAAA,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AA+BA,UAAU,yBAAyB;IACjC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,QAAA,MAAM,oBAAoB,GAAI,mBAAmB,yBAAyB,4CAiRzE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -27,7 +27,7 @@ import DeskListSkeleton from "./DeskListSkeleton";
|
|
|
27
27
|
import { getListHeading } from "./listHeading";
|
|
28
28
|
import ComposeNewMessageModal from "../../components/compose/ComposeNewMessageModal";
|
|
29
29
|
import { useCloseOnSidePanelOpen } from "../../hooks/common/useCloseOnSidePanelOpen";
|
|
30
|
-
const DeskConversationList = () => {
|
|
30
|
+
const DeskConversationList = ({ onOpenAppMenu }) => {
|
|
31
31
|
const searchInputRef = useRef(null);
|
|
32
32
|
const { t } = useTranslation();
|
|
33
33
|
const [search, setSearch] = useState("");
|
|
@@ -150,7 +150,7 @@ const DeskConversationList = () => {
|
|
|
150
150
|
if (!showSearch && value)
|
|
151
151
|
setShowSearchTrue();
|
|
152
152
|
setSearch(value);
|
|
153
|
-
}, onSearchFocus: onSearchFocus, onCloseSearch: onCloseSearch, onCompose: () => setIsComposeOpen(true) }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [_jsx("div", { id: "scrollableConversationsDiv", "aria-busy": isListLoading, style: {
|
|
153
|
+
}, onSearchFocus: onSearchFocus, onCloseSearch: onCloseSearch, onCompose: () => setIsComposeOpen(true), onOpenAppMenu: onOpenAppMenu }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [_jsx("div", { id: "scrollableConversationsDiv", "aria-busy": isListLoading, style: {
|
|
154
154
|
height: "100%",
|
|
155
155
|
overflow: showSearch ? "hidden" : "auto",
|
|
156
156
|
}, children: isAllGroupsView ? (isConversationGroupsLoading ? (_jsx(DeskListSkeleton, { rows: 8 })) : !(conversationGroups === null || conversationGroups === void 0 ? void 0 : conversationGroups.length) ? (_jsx(DeskListEmptyState, { filterKey: emptyFilterKey })) : (_jsx(InfiniteScroll, { dataLength: conversationGroups.length, next: fetchNextGroupsPage, hasMore: !!hasNextGroupsPage, loader: _jsx(DeskListSkeleton, { rows: 2 }), scrollableTarget: "scrollableConversationsDiv", children: _jsx("div", { className: "flex flex-col gap-0.5 px-1 pb-2", children: conversationGroups.map((group) => (_jsx(ConversationByGroupItem, { group: group, latestPreview: groupLatestPreviewMap.get(group.conversationId) }, group.groupId))) }) }))) : isSessionsLoading || (isSyncing && !(sessions === null || sessions === void 0 ? void 0 : sessions.length)) ? (
|
|
@@ -7,6 +7,8 @@ interface DeskListHeaderProps {
|
|
|
7
7
|
onSearchFocus: () => void;
|
|
8
8
|
onCloseSearch: () => void;
|
|
9
9
|
onCompose: () => void;
|
|
10
|
+
/** Phone only: ☰ that opens the host app menu. */
|
|
11
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
10
12
|
}
|
|
11
13
|
/** Search row plus a title that names the folder the list below is built from. */
|
|
12
14
|
declare const DeskListHeader: import("react").ForwardRefExoticComponent<DeskListHeaderProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskListHeader.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskListHeader.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,UAAU,mBAAmB;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"DeskListHeader.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskListHeader.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,UAAU,mBAAmB;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,kFAAkF;AAClF,QAAA,MAAM,cAAc,kHA8JnB,CAAC;AAGF,eAAe,cAAc,CAAC"}
|
|
@@ -9,7 +9,7 @@ import useWorkspaceLayoutStore from "../../store/workspaceLayout";
|
|
|
9
9
|
import useShortcutPrefsStore from "../../store/shortcutPrefs";
|
|
10
10
|
import { LAYOUT_BREAKPOINTS } from "../../constants/layout";
|
|
11
11
|
/** Search row plus a title that names the folder the list below is built from. */
|
|
12
|
-
const DeskListHeader = forwardRef(({ heading, search, isSearching, onSearchChange, onSearchFocus, onCloseSearch, onCompose, }, inputRef) => {
|
|
12
|
+
const DeskListHeader = forwardRef(({ heading, search, isSearching, onSearchChange, onSearchFocus, onCloseSearch, onCompose, onOpenAppMenu, }, inputRef) => {
|
|
13
13
|
var _a, _b;
|
|
14
14
|
const { t } = useTranslation();
|
|
15
15
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -18,7 +18,7 @@ const DeskListHeader = forwardRef(({ heading, search, isSearching, onSearchChang
|
|
|
18
18
|
const singleKeyEnabled = useShortcutPrefsStore((s) => s.singleKeyEnabled);
|
|
19
19
|
const context = (_a = heading.contextText) !== null && _a !== void 0 ? _a : t((_b = heading.contextKey) !== null && _b !== void 0 ? _b : "my_messages");
|
|
20
20
|
const showSlashHint = singleKeyEnabled && !isFocused && !search && !isSearching;
|
|
21
|
-
return (_jsxs("div", { "data-cp-name": "DeskListHeader", children: [_jsxs("div", { className: "flex items-center gap-2 p-3", children: [!isFolderInline && (_jsx(Tooltip, { title: t("folder_panel_open"), children: _jsx(Button, { onClick: () => setFolderOverlayOpen(true), className: "flex h-9 w-9 shrink-0 items-center justify-center border-0 bg-gray-5 p-0 text-gray-900", "aria-label": t("folder_panel_open"), children: _jsx(StrokeIcon, { name: "panel-left", size: 20 }) }) })), _jsx("label", { htmlFor: "desk-list-search", className: "sr-only", children: t("search_conversation_label") }), _jsxs("div", { className: "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-lg bg-gray-5 pl-2.5 pr-2 text-gray-600 focus-within:ring-2 focus-within:ring-primary-200", children: [_jsx(StrokeIcon, { name: "search", size: 18 }), _jsx("input", { id: "desk-list-search", ref: inputRef, type: "text", "data-desk-search": true, autoComplete: "off",
|
|
21
|
+
return (_jsxs("div", { "data-cp-name": "DeskListHeader", children: [_jsxs("div", { className: "flex items-center gap-2 p-3", children: [onOpenAppMenu && (_jsx("button", { type: "button", "data-app-menu-button": true, onClick: (event) => onOpenAppMenu(event.currentTarget), className: "hidden phone:flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border-0 bg-transparent p-0 text-gray-900 touch:min-h-10 touch:min-w-10 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", "aria-label": t("app_menu_open"), children: _jsx(StrokeIcon, { name: "menu", size: 20 }) })), !isFolderInline && (_jsx(Tooltip, { title: t("folder_panel_open"), children: _jsx(Button, { onClick: () => setFolderOverlayOpen(true), className: "flex h-9 w-9 shrink-0 items-center justify-center border-0 bg-gray-5 p-0 text-gray-900 max-lg:!hidden", "aria-label": t("folder_panel_open"), children: _jsx(StrokeIcon, { name: "panel-left", size: 20 }) }) })), _jsx("label", { htmlFor: "desk-list-search", className: "sr-only", children: t("search_conversation_label") }), _jsxs("div", { className: "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-lg bg-gray-5 pl-2.5 pr-2 text-gray-600 focus-within:ring-2 focus-within:ring-primary-200", children: [_jsx(StrokeIcon, { name: "search", size: 18 }), _jsx("input", { id: "desk-list-search", ref: inputRef, type: "text", "data-desk-search": true, autoComplete: "off",
|
|
22
22
|
// The narrow list (folder toggle shown) has no room for the long hint.
|
|
23
23
|
placeholder: t(isFolderInline ? "desk_search_placeholder" : "search_conversation_label"), value: search, onChange: (e) => onSearchChange(e.target.value), onFocus: () => {
|
|
24
24
|
setIsFocused(true);
|
|
@@ -33,7 +33,7 @@ const DeskListHeader = forwardRef(({ heading, search, isSearching, onSearchChang
|
|
|
33
33
|
e.stopPropagation();
|
|
34
34
|
onCloseSearch();
|
|
35
35
|
}
|
|
36
|
-
}, className: "min-w-0 flex-1 border-0 bg-transparent p-0 text-sm text-gray-900 outline-none placeholder:text-gray-600" }), search && (_jsx("button", { type: "button", "aria-label": t("clear"), onClick: onCloseSearch, className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-gray-600 hover:text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", children: _jsx(StrokeIcon, { name: "x", size: 14 }) })), showSlashHint && (_jsx("kbd", { "aria-hidden": "true", className: "inline-flex h-6 min-w-[24px] items-center justify-center rounded border border-b-2 border-gray-50 bg-white px-1.5 font-sans text-xs font-semibold text-gray-900", children: "/" }))] }), isSearching ? (_jsx(Tooltip, { title: t("close"), children: _jsx(Button, { onClick: onCloseSearch, "aria-label": t("close"), className: "h-9 w-9 shrink-0 p-0 text-gray-600", children: _jsx(StrokeIcon, { name: "x", size: 20 }) }) })) : (_jsx(Tooltip, { title: t("compose_new_message"), children: _jsx(Button, { "data-testid": "conversation-list-compose-icon", onClick: onCompose, "aria-label": t("compose_new_message"), className: "flex !h-8 !w-8 shrink-0 items-center justify-center rounded-lg border-0 bg-primary-25 p-0 text-primary-500", children: _jsx(StrokeIcon, { name: "edit", size: 18 }) }) }))] }), !isSearching && (_jsxs("div", { className: "flex flex-col gap-0.5 border-b border-gray-25 px-4 pb-3 pt-1", children: [isFolderInline ? (_jsx("span", { className: "truncate text-xs font-medium text-gray-600", children: context })) : (_jsxs("button", { type: "button", "aria-label": `${t("folder_panel_open")}: ${context}`, onClick: () => setFolderOverlayOpen(true), className: "flex min-w-0 items-center gap-1 self-start rounded border-0 bg-transparent p-0 text-xs font-medium leading-[1.4] text-gray-600 hover:text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", children: [_jsx("span", { className: "truncate", children: context }), _jsx(StrokeIcon, { name: "chevron-down", size: 14 })] })), _jsxs("h2", { className: "m-0 flex min-w-0 items-center gap-2 text-lg font-bold text-gray-900", children: [_jsx("span", { className: "truncate", children: t(heading.titleKey) }), " ", !!heading.count && (_jsx("span", { className: "inline-flex h-6 shrink-0 items-center rounded-full bg-primary-25 px-2 text-sm font-semibold tabular-nums text-primary-500", children: heading.count }))] })] }))] }));
|
|
36
|
+
}, className: "min-w-0 flex-1 border-0 bg-transparent p-0 text-sm text-gray-900 outline-none placeholder:text-gray-600" }), search && (_jsx("button", { type: "button", "aria-label": t("clear"), onClick: onCloseSearch, className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-gray-600 hover:text-gray-900 touch:min-h-8 touch:min-w-8 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", children: _jsx(StrokeIcon, { name: "x", size: 14 }) })), showSlashHint && (_jsx("kbd", { "aria-hidden": "true", className: "touch:hidden inline-flex h-6 min-w-[24px] items-center justify-center rounded border border-b-2 border-gray-50 bg-white px-1.5 font-sans text-xs font-semibold text-gray-900", children: "/" }))] }), isSearching ? (_jsx(Tooltip, { title: t("close"), children: _jsx(Button, { onClick: onCloseSearch, "aria-label": t("close"), className: "h-9 w-9 shrink-0 p-0 text-gray-600 touch:min-h-10 touch:min-w-10", children: _jsx(StrokeIcon, { name: "x", size: 20 }) }) })) : (_jsx(Tooltip, { title: t("compose_new_message"), children: _jsx(Button, { "data-testid": "conversation-list-compose-icon", onClick: onCompose, "aria-label": t("compose_new_message"), className: "flex !h-8 !w-8 shrink-0 items-center justify-center rounded-lg border-0 bg-primary-25 p-0 text-primary-500 touch:!min-h-10 touch:!min-w-10", children: _jsx(StrokeIcon, { name: "edit", size: 18 }) }) }))] }), !isSearching && (_jsxs("div", { className: "flex flex-col gap-0.5 border-b border-gray-25 px-4 pb-3 pt-1", children: [isFolderInline ? (_jsx("span", { className: "truncate text-xs font-medium text-gray-600", children: context })) : (_jsxs("button", { type: "button", "aria-label": `${t("folder_panel_open")}: ${context}`, onClick: () => setFolderOverlayOpen(true), className: "flex min-w-0 items-center gap-1 self-start rounded border-0 bg-transparent p-0 touch:-my-3 touch:py-3 text-xs font-medium leading-[1.4] text-gray-600 hover:text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", children: [_jsx("span", { className: "truncate", children: context }), _jsx(StrokeIcon, { name: "chevron-down", size: 14 })] })), _jsxs("h2", { className: "m-0 flex min-w-0 items-center gap-2 text-lg font-bold text-gray-900", children: [_jsx("span", { className: "truncate", children: t(heading.titleKey) }), " ", !!heading.count && (_jsx("span", { className: "inline-flex h-6 shrink-0 items-center rounded-full bg-primary-25 px-2 text-sm font-semibold tabular-nums text-primary-500", children: heading.count }))] })] }))] }));
|
|
37
37
|
});
|
|
38
38
|
DeskListHeader.displayName = "DeskListHeader";
|
|
39
39
|
export default DeskListHeader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAiCf,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,QAAA,MAAM,uBAAuB,GAAI,4DAI9B,4BAA4B,4CAsS9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useState, } from "react";
|
|
4
4
|
import { Empty, Spin, message as toastMessage } from "antd";
|
|
5
5
|
import { useEventListener } from "ahooks";
|
|
6
6
|
import { useTranslation } from "react-i18next";
|
|
@@ -13,12 +13,15 @@ import { usePinMessage } from "../../hooks/message/usePinMessage";
|
|
|
13
13
|
import { useRevokeMessage } from "../../hooks/message/useRevokeMessage";
|
|
14
14
|
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
15
15
|
import { useViewOnlyGroupRefresh } from "../../hooks/conversation/useViewOnlyGroupRefresh";
|
|
16
|
+
import { useConsultantChatNavigation } from "../../hooks/conversation/useConsultantChatNavigation";
|
|
16
17
|
import useConversationStore from "../../store/conversation";
|
|
17
18
|
import { PeerType } from "../../types/conversation";
|
|
18
19
|
import useAuthStore from "../../store/auth";
|
|
19
|
-
import { isGroupChat as resolveIsGroupChat, isSupportSessionAgentView, } from "../../utils/conversation";
|
|
20
|
+
import { isBotPeer, isGroupChat as resolveIsGroupChat, isSupportSessionAgentView, } from "../../utils/conversation";
|
|
20
21
|
import emitter from "../../utils/events";
|
|
21
22
|
import MessageItem from "../../components/message/item";
|
|
23
|
+
import { ConsultantCtaContext, } from "../../components/message/item/consultantCta";
|
|
24
|
+
import { findConsultantCtaMessageId } from "../../utils/customMessage";
|
|
22
25
|
import UnreadMessageJumpButton from "../../components/message/UnreadMessageJumpButton";
|
|
23
26
|
import PinLimitModal from "./PinLimitModal";
|
|
24
27
|
const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessageRevoked, }) => {
|
|
@@ -39,9 +42,10 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
|
|
|
39
42
|
// the permission check would hide a feature that is live for them.
|
|
40
43
|
const canPinMessage = !isGroupChat || permissions.pinMessage || allowPinMessageWithoutPermission;
|
|
41
44
|
const viewerUserID = (user === null || user === void 0 ? void 0 : user.userID) || authUserID;
|
|
45
|
+
const isAgentView = isSupportSessionAgentView(Object.assign(Object.assign({}, conversation), { conversationID: conversationId }), viewerUserID);
|
|
42
46
|
// App history strips the assignment log and session dividers, which an
|
|
43
47
|
// agent handling someone else's session needs — load the full history.
|
|
44
|
-
const useAppHistory = !
|
|
48
|
+
const useAppHistory = !isAgentView;
|
|
45
49
|
const messageController = useMessage(conversationId, searchClientMsgID, true, useAppHistory, onSearchMessageRevoked);
|
|
46
50
|
useViewOnlyGroupRefresh({
|
|
47
51
|
enabled: isViewOnlyMember && (conversation === null || conversation === void 0 ? void 0 : conversation.peerType) === PeerType.GROUP,
|
|
@@ -56,6 +60,20 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
|
|
|
56
60
|
const { scrollRef, loadMoreOldMessage, handleInfiniteScroll, scrollToBottomIfAtBottom, scrollToMessage, } = useMessageListScroll(Object.assign({ conversationId, userId: viewerUserID, isGroupChat, markAsReadBlocked: !isUnreadLookupResolved }, messageController));
|
|
57
61
|
const { loadState, moreOldLoading } = messageController;
|
|
58
62
|
const isMessageLoading = !conversationId || loadState.initLoading;
|
|
63
|
+
const { openConsultantChat } = useConsultantChatNavigation();
|
|
64
|
+
// The button is the owner's way to their own consultant, in their bot thread.
|
|
65
|
+
const canOpenConsultantChat = !!conversation && isBotPeer(conversation) && !isAgentView;
|
|
66
|
+
const consultantCta = useMemo(() => ({
|
|
67
|
+
ctaMessageId: canOpenConsultantChat
|
|
68
|
+
? findConsultantCtaMessageId(loadState.messageList, loadState.hasMoreNew)
|
|
69
|
+
: null,
|
|
70
|
+
onOpenConsultantChat: openConsultantChat,
|
|
71
|
+
}), [
|
|
72
|
+
canOpenConsultantChat,
|
|
73
|
+
loadState.messageList,
|
|
74
|
+
loadState.hasMoreNew,
|
|
75
|
+
openConsultantChat,
|
|
76
|
+
]);
|
|
59
77
|
const [openToolboxMessageId, setOpenToolboxMessageId] = useState(null);
|
|
60
78
|
const closeToolbox = useCallback(() => setOpenToolboxMessageId(null), []);
|
|
61
79
|
const [revealedTimeMsgId, setRevealedTimeMsgId] = useState(null);
|
|
@@ -140,7 +158,7 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
|
|
|
140
158
|
target: scrollRef,
|
|
141
159
|
enable: !!openToolboxMessageId,
|
|
142
160
|
});
|
|
143
|
-
return (_jsxs("div", { "data-testid": "conversation-message-list", "data-cp-name": "ConversationMessageList", 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: [_jsx("div", { "aria-hidden": "true", className: "h-3 shrink-0" }), 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: handleRevokeMessage, timeRevealed: revealedTimeMsgId === message.clientMsgID, onToggleTimeReveal: handleToggleTimeReveal, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined, onCopyMessageLink: handleCopyMessageLink, showUnreadDivider: !!unreadDividerMessageId &&
|
|
144
|
-
|
|
161
|
+
return (_jsxs("div", { "data-testid": "conversation-message-list", "data-cp-name": "ConversationMessageList", 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: [_jsx("div", { "aria-hidden": "true", className: "h-3 shrink-0" }), bottomSlot, _jsx(ConsultantCtaContext.Provider, { value: consultantCta, children: 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: handleRevokeMessage, timeRevealed: revealedTimeMsgId === message.clientMsgID, onToggleTimeReveal: handleToggleTimeReveal, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined, onCopyMessageLink: onCopyMessageLink ? handleCopyMessageLink : undefined, showUnreadDivider: !!unreadDividerMessageId &&
|
|
162
|
+
message.clientMsgID === unreadDividerMessageId, onUnreadDividerSeen: markDividerSeen, enableLongPress: true }, message.clientMsgID))) })] })), !isMessageLoading && showJumpButton && (_jsx(UnreadMessageJumpButton, { className: "absolute right-0 top-4 z-10", onClick: handleJumpToFirstUnread })), _jsx(PinLimitModal, { open: pinLimitModalOpen, max: pinnedTotalCount, onClose: () => setPinLimitModalOpen(false) })] }));
|
|
145
163
|
};
|
|
146
164
|
export default ConversationMessageList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationInboxItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxItem.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAoBjE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;CAC/C;AAQD,QAAA,MAAM,qBAAqB,GAAI,mBAAmB,0BAA0B,
|
|
1
|
+
{"version":3,"file":"ConversationInboxItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxItem.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAoBjE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;CAC/C;AAQD,QAAA,MAAM,qBAAqB,GAAI,mBAAmB,0BAA0B,4CAkG3E,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -51,7 +51,7 @@ const ConversationInboxItem = ({ item, onClick }) => {
|
|
|
51
51
|
peerType: item.peerType,
|
|
52
52
|
conversationType: item.conversationType,
|
|
53
53
|
showName: item.showName,
|
|
54
|
-
});
|
|
54
|
+
}, { showEventMessages: !isCrm });
|
|
55
55
|
const latestMessageTime = formatLatestMessageTime(item.latestMsgSendTime || null);
|
|
56
56
|
const unreadCount = (_a = item.unreadCount) !== null && _a !== void 0 ? _a : 0;
|
|
57
57
|
const isMuted = isConversationMuted(item.recvMsgOpt);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationInboxList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxList.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationInboxList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxList.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAYjE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACvD;AAYD,QAAA,MAAM,qBAAqB,GAAI,oFAO5B,0BAA0B,4CA8F5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
|
-
import { Empty
|
|
4
|
+
import { Empty } from "antd";
|
|
5
5
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
6
6
|
import useConversationStore from "../../store/conversation";
|
|
7
7
|
import { useChatNavigate } from "../../hooks/conversation/useChatNavigate";
|
|
8
8
|
import { Icon } from "../../components/icon";
|
|
9
|
+
import useBootStore from "../../store/boot";
|
|
10
|
+
import { useChatBootPhase } from "../../hooks/init/useChatBootPhase";
|
|
9
11
|
import ConversationInboxItem from "./ConversationInboxItem";
|
|
12
|
+
import InboxBootStatus from "./InboxBootStatus";
|
|
13
|
+
import InboxListSkeleton from "./InboxListSkeleton";
|
|
14
|
+
const INBOX_SLOW_AFTER_MS = 8000;
|
|
10
15
|
const FooterSkeleton = () => (_jsxs("div", { className: "flex items-center gap-3 p-3", children: [_jsx("div", { className: "h-10 w-10 animate-pulse rounded-full bg-neutral-200" }), _jsxs("div", { className: "flex flex-1 flex-col gap-2", children: [_jsx("div", { className: "h-3 w-1/2 animate-pulse rounded bg-neutral-200" }), _jsx("div", { className: "h-2.5 w-1/3 animate-pulse rounded bg-neutral-200" })] })] }));
|
|
11
16
|
const ConversationInboxList = ({ items, isLoading, isFetchingNextPage, hasNextPage, onLoadMore, onSelectThread, }) => {
|
|
12
17
|
const { t } = useTranslation("conversation-inbox");
|
|
13
18
|
const onNavigate = useChatNavigate();
|
|
19
|
+
const boot = useChatBootPhase({ slowAfterMs: INBOX_SLOW_AFTER_MS });
|
|
20
|
+
const isListSettled = useBootStore((state) => state.isListSettled);
|
|
14
21
|
const setConversationData = useConversationStore((state) => state.setConversationData);
|
|
15
22
|
const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
|
|
16
23
|
const handleSelectThread = (item) => {
|
|
@@ -29,8 +36,10 @@ const ConversationInboxList = ({ items, isLoading, isFetchingNextPage, hasNextPa
|
|
|
29
36
|
onLoadMore();
|
|
30
37
|
}
|
|
31
38
|
};
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
// Until the list has loaded once after the first sync, an empty list means "not loaded yet".
|
|
40
|
+
if (items.length === 0 && (!isListSettled || isLoading)) {
|
|
41
|
+
return (_jsxs("div", { "data-testid": "conversation-inbox-thread-list", className: "min-h-0 w-full flex-1 overflow-hidden", children: [!isListSettled && (_jsx(InboxBootStatus, { boot: boot.phase === "ready"
|
|
42
|
+
? Object.assign(Object.assign({}, boot), { phase: "sync", syncProgress: 100 }) : boot })), boot.phase !== "error" && _jsx(InboxListSkeleton, { rows: 6 })] }));
|
|
34
43
|
}
|
|
35
44
|
return (_jsx("div", { id: "scrollableConversationThreadsDiv", "data-testid": "conversation-inbox-thread-list", "data-cp-name": "ConversationInboxList", className: "min-h-0 w-full flex-1 overflow-auto", children: _jsx(InfiniteScroll, { dataLength: items.length, next: handleEndReached, hasMore: hasNextPage, loader: isFetchingNextPage ? _jsx(FooterSkeleton, {}) : null, scrollableTarget: "scrollableConversationThreadsDiv", children: items.length === 0 ? (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Empty, { image: _jsx("div", { className: "flex justify-center", children: _jsx(Icon, { icon: "chat-square-b", size: 80, className: "text-[var(--dc-color-primary-light)]" }) }), description: t("empty.no_conversations") }) })) : (items.map((item) => (_jsx(ConversationInboxItem, { item: item, onClick: handleSelectThread }, item.conversationID)))) }) }));
|
|
36
45
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatBootState } from "../../hooks/init/useChatBootPhase";
|
|
2
|
+
/**
|
|
3
|
+
* "Đang tải tin nhắn" block shown above the inbox skeleton until the list first loads.
|
|
4
|
+
* Three bars, one per boot step; no percentage text (PO decision for end-customer apps).
|
|
5
|
+
*/
|
|
6
|
+
declare const InboxBootStatus: ({ boot }: {
|
|
7
|
+
boot: ChatBootState;
|
|
8
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export default InboxBootStatus;
|
|
10
|
+
//# sourceMappingURL=InboxBootStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InboxBootStatus.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/InboxBootStatus.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAyCnE;;;GAGG;AACH,QAAA,MAAM,eAAe,GAAI,UAAU;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,mDAmDzD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|