@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
package/dist/index.js
CHANGED
|
@@ -18,6 +18,8 @@ export { openLink } from "./utils/openLink";
|
|
|
18
18
|
//Components
|
|
19
19
|
export { DChatDeskMessage, DChatBubble, Icon, SkipLinks };
|
|
20
20
|
export { StrokeIcon } from "./components/icon/StrokeIcon";
|
|
21
|
+
// The desk's loading placeholder, for hosts whose app shell renders before ChatProvider.
|
|
22
|
+
export { default as DeskWorkspaceSkeleton } from "./screens/desk-message/DeskWorkspaceSkeleton";
|
|
21
23
|
export { default as RichTextEditor } from "./components/rich-text-editor/RichTextEditor";
|
|
22
24
|
export { default as ShadowStyleBoundary } from "./components/shadow-style-boundary/ShadowStyleBoundary";
|
|
23
25
|
export { default as DChatConversationInbox } from "./screens/conversation-inbox";
|
|
@@ -49,7 +51,7 @@ export { fetchBotConversationDetail, } from "./hooks/conversation/useBotConversa
|
|
|
49
51
|
export { fetchConversationByBotId, } from "./hooks/conversation/useResolveConversation";
|
|
50
52
|
export { useSwitchToCsTeam, SwitchToCsTeamResult, } from "./hooks/conversation/useSwitchToCsTeam";
|
|
51
53
|
//Custom message
|
|
52
|
-
export { CustomMessageType } from "./types/customMessage";
|
|
54
|
+
export { CustomMessageType, MallEventType } from "./types/customMessage";
|
|
53
55
|
//Hooks
|
|
54
56
|
export { useDChatAuth } from "./hooks/user/useAuth";
|
|
55
57
|
export { useSendMessage } from "./hooks/message/useSendMessage";
|
|
@@ -68,5 +70,7 @@ export { getDChatSDK } from "./constants/sdk";
|
|
|
68
70
|
export { MediaEntryCard, MediaResourcePanel, MediaResourceTabs, MediaResourceTabKey, } from "./components/media-resources";
|
|
69
71
|
export { useMessageResources } from "./hooks/message/useMessageResources";
|
|
70
72
|
export { PAGE_SIZE } from "./constants";
|
|
71
|
-
export { LAYOUT_BREAKPOINTS, LAYOUT_WIDTHS } from "./constants/layout";
|
|
73
|
+
export { LAYOUT_BREAKPOINTS, LAYOUT_MEDIA, LAYOUT_WIDTHS } from "./constants/layout";
|
|
72
74
|
export { useMediaQuery } from "./hooks/common/useMediaQuery";
|
|
75
|
+
export { useViewportTier } from "./hooks/common/useViewportTier";
|
|
76
|
+
export { useIsDeskWorkspaceMounted } from "./hooks/common/useIsDeskWorkspaceMounted";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locales/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locales/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,SAAS,CAAC;AAmB3B,eAAe,IAAI,CAAC"}
|
package/dist/locales/i18n.js
CHANGED
|
@@ -2,15 +2,16 @@ import i18n from "i18next";
|
|
|
2
2
|
import { initReactI18next } from "react-i18next";
|
|
3
3
|
import vi from "./vi/common.json";
|
|
4
4
|
import viConversationInbox from "./vi/conversation-inbox.json";
|
|
5
|
+
import viBoot from "./vi/boot.json";
|
|
5
6
|
if (!i18n.isInitialized) {
|
|
6
7
|
i18n.use(initReactI18next).init({
|
|
7
8
|
resources: {
|
|
8
|
-
vi: { common: vi, "conversation-inbox": viConversationInbox },
|
|
9
|
+
vi: { common: vi, "conversation-inbox": viConversationInbox, boot: viBoot },
|
|
9
10
|
},
|
|
10
11
|
lng: "vi",
|
|
11
12
|
fallbackLng: "vi",
|
|
12
13
|
interpolation: { escapeValue: false },
|
|
13
|
-
ns: ["common", "conversation-inbox"],
|
|
14
|
+
ns: ["common", "conversation-inbox", "boot"],
|
|
14
15
|
defaultNS: "common",
|
|
15
16
|
});
|
|
16
17
|
}
|
package/dist/locales/i18n.ts
CHANGED
|
@@ -2,16 +2,17 @@ import i18n from "i18next";
|
|
|
2
2
|
import { initReactI18next } from "react-i18next";
|
|
3
3
|
import vi from "./vi/common.json";
|
|
4
4
|
import viConversationInbox from "./vi/conversation-inbox.json";
|
|
5
|
+
import viBoot from "./vi/boot.json";
|
|
5
6
|
|
|
6
7
|
if (!i18n.isInitialized) {
|
|
7
8
|
i18n.use(initReactI18next).init({
|
|
8
9
|
resources: {
|
|
9
|
-
vi: { common: vi, "conversation-inbox": viConversationInbox },
|
|
10
|
+
vi: { common: vi, "conversation-inbox": viConversationInbox, boot: viBoot },
|
|
10
11
|
},
|
|
11
12
|
lng: "vi",
|
|
12
13
|
fallbackLng: "vi",
|
|
13
14
|
interpolation: { escapeValue: false },
|
|
14
|
-
ns: ["common", "conversation-inbox"],
|
|
15
|
+
ns: ["common", "conversation-inbox", "boot"],
|
|
15
16
|
defaultNS: "common",
|
|
16
17
|
});
|
|
17
18
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"desk": {
|
|
3
|
+
"title": {
|
|
4
|
+
"engine": "Đang khởi động Livechat",
|
|
5
|
+
"connect": "Đang kết nối máy chủ chat",
|
|
6
|
+
"sync": "Đang đồng bộ tin nhắn",
|
|
7
|
+
"error": "Không kết nối được Livechat"
|
|
8
|
+
},
|
|
9
|
+
"steps": {
|
|
10
|
+
"engine": "Khởi động Livechat",
|
|
11
|
+
"connect": "Kết nối máy chủ chat",
|
|
12
|
+
"sync": "Đồng bộ tin nhắn"
|
|
13
|
+
},
|
|
14
|
+
"slow": "Mạng đang chậm hơn bình thường. Livechat vẫn đang tải, bạn không cần làm gì thêm.",
|
|
15
|
+
"error_hint": "Kiểm tra kết nối mạng rồi bấm Thử lại. Nếu vẫn lỗi, báo bộ phận kỹ thuật: dừng ở bước {{step}}."
|
|
16
|
+
},
|
|
17
|
+
"inbox": {
|
|
18
|
+
"title": "Đang tải tin nhắn",
|
|
19
|
+
"engine": "Đang chuẩn bị hộp thư…",
|
|
20
|
+
"connect": "Đang kết nối…",
|
|
21
|
+
"sync": "Đang đồng bộ…",
|
|
22
|
+
"slow": "Lần đầu mở có thể mất một chút thời gian. Những lần sau sẽ nhanh hơn.",
|
|
23
|
+
"error_title": "Chưa tải được tin nhắn",
|
|
24
|
+
"error_hint": "Kiểm tra kết nối mạng rồi thử lại."
|
|
25
|
+
},
|
|
26
|
+
"retry": "Thử lại",
|
|
27
|
+
"sync_progress_label": "Tiến độ đồng bộ tin nhắn"
|
|
28
|
+
}
|
|
@@ -147,6 +147,7 @@
|
|
|
147
147
|
"group_notification_message_pinned": "{{name}} đã ghim một tin nhắn",
|
|
148
148
|
"group_notification_message_unpinned": "{{name}} đã bỏ ghim một tin nhắn",
|
|
149
149
|
"invalid_message": "Tin nhắn không hợp lệ",
|
|
150
|
+
"consultant_chat_button": "Nhắn với người hướng dẫn",
|
|
150
151
|
"session_started": "Phiên chat đã bắt đầu",
|
|
151
152
|
"session_ended": "Phiên chat đã kết thúc",
|
|
152
153
|
"new_message": "Bạn có tin nhắn mới",
|
|
@@ -224,6 +225,7 @@
|
|
|
224
225
|
"join_link_unavailable_message": "Liên kết đã bị thu hồi, thay thế hoặc nhóm không còn tồn tại. Vui lòng liên hệ người gửi để nhận liên kết mới.",
|
|
225
226
|
"join_link_unavailable_action": "Đã hiểu",
|
|
226
227
|
"close": "Đóng",
|
|
228
|
+
"app_menu_open": "Mở menu",
|
|
227
229
|
"leave_group_confirm_title": "Rời khỏi nhóm?",
|
|
228
230
|
"leave_group_confirm_message": "Bạn có chắc chắn muốn rời khỏi nhóm này không?",
|
|
229
231
|
"leave_group_success": "Rời khỏi nhóm thành công",
|
|
@@ -313,7 +315,6 @@
|
|
|
313
315
|
"no_message_yet": "Chưa có tin nhắn",
|
|
314
316
|
"folder_group_collapse": "Thu gọn {{name}}",
|
|
315
317
|
"folder_group_expand": "Mở rộng {{name}}",
|
|
316
|
-
"viewport_too_narrow": "Vui lòng dùng màn hình rộng từ 1024px",
|
|
317
318
|
"thread_info_open": "Thông tin hội thoại",
|
|
318
319
|
"thread_info_close": "Đóng thông tin (Esc)",
|
|
319
320
|
"search_in_conversation": "Tìm trong hội thoại",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-detail/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-detail/index.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAWrF,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,6CAA6C,CAAC;AAQrD,MAAM,WAAW,4BACf,SAAQ,4BAA4B,EAClC,4BAA4B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;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,8IAc9B,4BAA4B,mDA4Q9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
|
-
import { useState } from "react";
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
15
|
import { useTranslation } from "react-i18next";
|
|
16
16
|
import { useChatContext } from "../../context/ChatContext";
|
|
17
17
|
import { useChatNavigate } from "../../hooks/conversation/useChatNavigate";
|
|
@@ -19,6 +19,7 @@ import { useBoolean } from "ahooks";
|
|
|
19
19
|
import clsx from "clsx";
|
|
20
20
|
import { Empty, Spin } from "antd";
|
|
21
21
|
import { Icon } from "../../components/icon";
|
|
22
|
+
import useAuthStore from "../../store/auth";
|
|
22
23
|
import useConversationStore from "../../store/conversation";
|
|
23
24
|
import ThreadProfilePanel from "../../components/conversation-detail/ThreadProfilePanel";
|
|
24
25
|
import MediaResourcePanel from "../../components/media-resources/MediaResourcePanel";
|
|
@@ -29,7 +30,8 @@ import { BotButtonMessage, BotInactiveNotice, BotMenuSheet, BotStartButton, BotS
|
|
|
29
30
|
import { useBotFlow } from "../../hooks/conversation/useBotFlow";
|
|
30
31
|
import { BOT_TYPE } from "../../constants/botFlow";
|
|
31
32
|
import { useResolveConversation, } from "../../hooks/conversation/useResolveConversation";
|
|
32
|
-
import {
|
|
33
|
+
import { nextConsultantReturnTarget, useConsultantChatNavigation, } from "../../hooks/conversation/useConsultantChatNavigation";
|
|
34
|
+
import { isBotPeer, isSupportSessionAgentView } from "../../utils/conversation";
|
|
33
35
|
import { COMPOSER_DISMISS_ZONE_ATTR } from "../../hooks/common/useOutsideTapDismiss";
|
|
34
36
|
const DChatConversationDetail = (_a) => {
|
|
35
37
|
var _b;
|
|
@@ -38,9 +40,10 @@ const DChatConversationDetail = (_a) => {
|
|
|
38
40
|
// inputProps goes to ConversationDetailInput, which has no business with it.
|
|
39
41
|
onCopyMessageLink, onSearchMessageRevoked } = _a, inputProps = __rest(_a, ["className", "children", "onBack", "conversationId", "messageId", "userId", "groupId", "botId", "onCopyMessageLink", "onSearchMessageRevoked"]);
|
|
40
42
|
const { t } = useTranslation("conversation-inbox");
|
|
41
|
-
const { useUrlState = true } = useChatContext();
|
|
43
|
+
const { useUrlState = true, user } = useChatContext();
|
|
42
44
|
const onNavigate = useChatNavigate();
|
|
43
45
|
const conversation = useConversationStore((state) => state.conversationData);
|
|
46
|
+
const authUserID = useAuthStore((state) => state.userID);
|
|
44
47
|
const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
|
|
45
48
|
const clearSelectedConversation = useConversationStore((state) => state.clearSelectedConversation);
|
|
46
49
|
const setPendingResolveTarget = useConversationStore((state) => state.setPendingResolveTarget);
|
|
@@ -51,7 +54,10 @@ const DChatConversationDetail = (_a) => {
|
|
|
51
54
|
botId,
|
|
52
55
|
messageId,
|
|
53
56
|
});
|
|
54
|
-
|
|
57
|
+
// The bot flow belongs to the session owner; an agent (PDP CS) just chats.
|
|
58
|
+
const isBotThread = !!conversation &&
|
|
59
|
+
isBotPeer(conversation) &&
|
|
60
|
+
!isSupportSessionAgentView(conversation, (user === null || user === void 0 ? void 0 : user.userID) || authUserID);
|
|
55
61
|
const botFlow = useBotFlow({
|
|
56
62
|
conversationId: (_b = conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) !== null && _b !== void 0 ? _b : "",
|
|
57
63
|
isBotThread,
|
|
@@ -60,7 +66,25 @@ const DChatConversationDetail = (_a) => {
|
|
|
60
66
|
const hasMenuItems = botFlow.menuItems.length > 0;
|
|
61
67
|
const [isProfileOpen, { setTrue: openProfile, setFalse: closeProfile }] = useBoolean(false);
|
|
62
68
|
const [resourceTab, setResourceTab] = useState(null);
|
|
69
|
+
const { returnTarget: consultantReturnTarget, returnToBotThread, clearReturnTarget, setReturnTarget, } = useConsultantChatNavigation();
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const next = nextConsultantReturnTarget(consultantReturnTarget, conversation);
|
|
72
|
+
if (next !== consultantReturnTarget)
|
|
73
|
+
setReturnTarget(next);
|
|
74
|
+
}, [consultantReturnTarget, conversation, setReturnTarget]);
|
|
75
|
+
// Leaving the detail (inbox list, bubble closed) ends the button's journey.
|
|
76
|
+
useEffect(() => clearReturnTarget, [clearReturnTarget]);
|
|
63
77
|
const handleBack = () => {
|
|
78
|
+
if (consultantReturnTarget) {
|
|
79
|
+
const isOnBotThread = !error &&
|
|
80
|
+
(conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) ===
|
|
81
|
+
consultantReturnTarget.botConversationId;
|
|
82
|
+
if (!isOnBotThread) {
|
|
83
|
+
returnToBotThread();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
clearReturnTarget();
|
|
87
|
+
}
|
|
64
88
|
// Bubble mode owns no page/URL to go "back" to — window.history.back()
|
|
65
89
|
// would instead navigate the host app itself. The store is the only
|
|
66
90
|
// source of truth here, so clear it directly.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChatBootState } from "../../hooks/init/useChatBootPhase";
|
|
2
|
+
/** CRM boot status: the three named steps, sync progress, a slow-network note and a retry on failure. */
|
|
3
|
+
declare const DeskBootCard: ({ boot }: {
|
|
4
|
+
boot: ChatBootState;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export default DeskBootCard;
|
|
7
|
+
//# sourceMappingURL=DeskBootCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeskBootCard.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/DeskBootCard.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAkEnE,yGAAyG;AACzG,QAAA,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,mDAgFtD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { Button } from "antd";
|
|
6
|
+
import { useTranslation } from "react-i18next";
|
|
7
|
+
import BootProgressBar from "../../components/boot/BootProgressBar";
|
|
8
|
+
import { StrokeIcon } from "../../components/icon/StrokeIcon";
|
|
9
|
+
const STEPS = ["engine", "connect", "sync"];
|
|
10
|
+
/** A fresh device's sync reports 1, 4 and 10 before messages arrive; only higher values say much. */
|
|
11
|
+
const SYNC_PERCENT_MIN = 10;
|
|
12
|
+
const STEP_TEXT_CLASS = {
|
|
13
|
+
done: "text-gray-900",
|
|
14
|
+
active: "font-medium text-gray-900",
|
|
15
|
+
pending: "text-gray-400",
|
|
16
|
+
error: "font-medium text-danger-600",
|
|
17
|
+
};
|
|
18
|
+
const getStepStates = (boot) => {
|
|
19
|
+
var _a;
|
|
20
|
+
const isError = boot.phase === "error";
|
|
21
|
+
const current = STEPS.indexOf((isError ? ((_a = boot.failedStep) !== null && _a !== void 0 ? _a : "engine") : boot.phase));
|
|
22
|
+
return STEPS.map((_, index) => {
|
|
23
|
+
if (index < current)
|
|
24
|
+
return "done";
|
|
25
|
+
if (index > current)
|
|
26
|
+
return "pending";
|
|
27
|
+
return isError ? "error" : "active";
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const StepMarker = ({ state }) => {
|
|
31
|
+
if (state === "done") {
|
|
32
|
+
return (_jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-success-400 text-white", children: _jsx(StrokeIcon, { name: "check", size: 11, strokeWidth: 3 }) }));
|
|
33
|
+
}
|
|
34
|
+
if (state === "error") {
|
|
35
|
+
return (_jsx("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-danger-500 text-[11px] font-bold leading-none text-white", children: "!" }));
|
|
36
|
+
}
|
|
37
|
+
if (state === "active") {
|
|
38
|
+
return (_jsx("span", { className: "h-4 w-4 shrink-0 rounded-full border-2 border-primary-25 border-t-primary-400 motion-safe:animate-spin" }));
|
|
39
|
+
}
|
|
40
|
+
return _jsx("span", { className: "h-4 w-4 shrink-0 rounded-full border-[1.5px] border-gray-100" });
|
|
41
|
+
};
|
|
42
|
+
const BootMark = ({ isError }) => (_jsxs("span", { "aria-hidden": "true", className: "relative flex h-12 w-12 shrink-0", children: [!isError && (_jsx("span", { className: "absolute inset-0 rounded-xl bg-primary-200 motion-safe:animate-[dchat-boot-breathe_2s_ease-out_infinite] motion-reduce:hidden" })), _jsx("span", { className: "relative flex h-12 w-12 items-center justify-center rounded-xl bg-primary-400 text-white", children: _jsx(StrokeIcon, { name: "message-circle", size: 26 }) }), isError && (_jsx("span", { className: "absolute -bottom-1.5 -right-1.5 flex h-[22px] w-[22px] items-center justify-center rounded-full border-2 border-white bg-danger-500 text-xs font-bold leading-none text-white", children: "!" }))] }));
|
|
43
|
+
/** CRM boot status: the three named steps, sync progress, a slow-network note and a retry on failure. */
|
|
44
|
+
const DeskBootCard = ({ boot }) => {
|
|
45
|
+
var _a;
|
|
46
|
+
const { t } = useTranslation("boot");
|
|
47
|
+
const errorRef = useRef(null);
|
|
48
|
+
const isError = boot.phase === "error";
|
|
49
|
+
// Agents work from the keyboard, so Enter should retry; but never pull focus off the rail.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
var _a, _b;
|
|
52
|
+
if (!isError)
|
|
53
|
+
return;
|
|
54
|
+
const active = document.activeElement;
|
|
55
|
+
if (active && active !== document.body)
|
|
56
|
+
return;
|
|
57
|
+
(_b = (_a = errorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("button")) === null || _b === void 0 ? void 0 : _b.focus();
|
|
58
|
+
}, [isError]);
|
|
59
|
+
if (boot.phase === "ready")
|
|
60
|
+
return null;
|
|
61
|
+
const title = t(`desk.title.${isError ? "error" : boot.phase}`);
|
|
62
|
+
const errorHint = t("desk.error_hint", {
|
|
63
|
+
step: t(`desk.steps.${(_a = boot.failedStep) !== null && _a !== void 0 ? _a : "engine"}`),
|
|
64
|
+
});
|
|
65
|
+
const stepStates = getStepStates(boot);
|
|
66
|
+
const showPercent = boot.phase === "sync" && boot.syncProgress > SYNC_PERCENT_MIN;
|
|
67
|
+
return (_jsxs("div", { "data-cp-name": "DeskBootCard", "data-phase": boot.phase, className: clsx("flex w-full max-w-[340px] flex-col gap-4 rounded-2xl border border-gray-25 bg-white p-6 shadow-sm transition-opacity duration-200", !boot.isStatusVisible && "opacity-0"), children: [_jsx("p", { role: "status", "aria-live": "polite", className: "sr-only", children: boot.isStatusVisible ? (isError ? `${title}. ${errorHint}` : title) : "" }), _jsx(BootMark, { isError: isError }), _jsx("p", { "aria-hidden": "true", className: "text-lg font-semibold text-gray-900", children: title }), _jsx("ol", { className: "flex flex-col gap-2.5", children: STEPS.map((step, index) => (_jsxs("li", { "aria-current": ["active", "error"].includes(stepStates[index]) ? "step" : undefined, className: clsx("flex items-center gap-2.5 text-sm", STEP_TEXT_CLASS[stepStates[index]]), children: [_jsx(StepMarker, { state: stepStates[index] }), _jsx("span", { className: "flex-1", children: t(`desk.steps.${step}`) }), step === "sync" && showPercent && (_jsxs("span", { className: "text-[13px] font-semibold tabular-nums text-primary-400", children: [boot.syncProgress, "%"] }))] }, step))) }), !isError && (_jsx(BootProgressBar, { mode: boot.phase === "sync" && boot.syncProgress > 0 ? "progress" : "indeterminate", value: boot.syncProgress, label: t("sync_progress_label") })), boot.isSlow && !isError && (_jsx("p", { className: "rounded-lg bg-warning-25 px-3 py-2 text-[13px] leading-normal text-warning-900", children: t("desk.slow") })), isError && (_jsxs("div", { ref: errorRef, className: "flex flex-col gap-3.5", children: [_jsx("p", { "aria-hidden": "true", className: "text-[13px] leading-normal text-gray-600", children: errorHint }), _jsx(Button, { type: "primary", className: "self-start", onClick: () => window.location.reload(), children: t("retry") })] }))] }));
|
|
68
|
+
};
|
|
69
|
+
export default DeskBootCard;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
interface DeskOfflineOverlayProps {
|
|
3
|
+
isPhone: boolean;
|
|
4
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/** Covers a locked desk with the reconnect status; on phone it keeps a way to the app menu. */
|
|
8
|
+
declare const DeskOfflineOverlay: ({ isPhone, onOpenAppMenu, children }: DeskOfflineOverlayProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default DeskOfflineOverlay;
|
|
10
|
+
//# sourceMappingURL=DeskOfflineOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeskOfflineOverlay.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/DeskOfflineOverlay.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,UAAU,uBAAuB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,+FAA+F;AAC/F,QAAA,MAAM,kBAAkB,GAAI,sCAAsC,uBAAuB,4CAsBxF,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { StrokeIcon } from "../../components/icon/StrokeIcon";
|
|
5
|
+
import { DESK_OFFLINE_OVERLAY_ATTR } from "../../hooks/conversation/useDeskOfflineLock";
|
|
6
|
+
/** Covers a locked desk with the reconnect status; on phone it keeps a way to the app menu. */
|
|
7
|
+
const DeskOfflineOverlay = ({ isPhone, onOpenAppMenu, children }) => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
return (_jsxs("div", { [DESK_OFFLINE_OVERLAY_ATTR]: "", "data-testid": "desk-offline-overlay", className: "absolute inset-0 z-[1000] flex flex-col items-center justify-center gap-4 bg-white/70 p-4", children: [isPhone && onOpenAppMenu && (_jsx("button", { type: "button", "data-app-menu-button": true, "aria-label": t("app_menu_open"), onClick: (event) => onOpenAppMenu(event.currentTarget), className: "absolute left-2 top-2 flex h-10 w-10 items-center justify-center rounded-lg border-0 bg-transparent p-0 text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200", children: _jsx(StrokeIcon, { name: "menu", size: 20 }) })), children] }));
|
|
10
|
+
};
|
|
11
|
+
export default DeskOfflineOverlay;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
1
2
|
import { GroupThreadInfoConfig } from "../../components/thread/GroupThreadInfo";
|
|
2
3
|
import type { CannedCreateRequest } from "../../types/chat";
|
|
3
4
|
interface DeskWorkspaceProps {
|
|
@@ -5,8 +6,13 @@ interface DeskWorkspaceProps {
|
|
|
5
6
|
groupThreadInfoConfig?: GroupThreadInfoConfig;
|
|
6
7
|
onCopyMessageLink?: (conversationId: string, clientMsgID: string) => void;
|
|
7
8
|
onSearchMessageRevoked?: () => void;
|
|
9
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
10
|
+
/** Connection dropped after the first connect: the desk stays visible but can't be used. */
|
|
11
|
+
isOffline?: boolean;
|
|
12
|
+
/** Shown in the offline overlay: reconnect status, and Retry once the reconnect has failed. */
|
|
13
|
+
offlineContent?: ReactNode;
|
|
8
14
|
}
|
|
9
15
|
/** Bright Workspace: folder, list, chat and info as separate white panels on the page canvas. */
|
|
10
|
-
declare const DeskWorkspace: ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMessageLink, onSearchMessageRevoked, }: DeskWorkspaceProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
declare const DeskWorkspace: ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMessageLink, onSearchMessageRevoked, onOpenAppMenu, isOffline, offlineContent, }: DeskWorkspaceProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
17
|
export default DeskWorkspace;
|
|
12
18
|
//# sourceMappingURL=DeskWorkspace.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskWorkspace.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/DeskWorkspace.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DeskWorkspace.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/DeskWorkspace.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAkB5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,UAAU,kBAAkB;IAC1B,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAChE,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+FAA+F;IAC/F,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAID,iGAAiG;AACjG,QAAA,MAAM,aAAa,GAAI,wIAQpB,kBAAkB,4CAiLpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -1,29 +1,38 @@
|
|
|
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, useRef, useState } from "react";
|
|
4
|
+
import { useSearchParams } from "next/navigation";
|
|
4
5
|
import MessageList from "../../components/message/MessageList";
|
|
5
6
|
import DeskConversationList from "../../components/conversation/DeskConversationList";
|
|
6
7
|
import DeskAssignedSession from "../../components/session/DeskAssignedSession";
|
|
7
8
|
import ThreadInfo from "../../components/thread/ThreadInfo";
|
|
8
9
|
import { useMediaQuery } from "../../hooks/common/useMediaQuery";
|
|
9
10
|
import { useSidePanel } from "../../hooks/common/useSidePanel";
|
|
11
|
+
import { useVisualViewportHeight } from "../../hooks/common/useVisualViewportHeight";
|
|
12
|
+
import { useViewportTier } from "../../hooks/common/useViewportTier";
|
|
13
|
+
import { useDeskOfflineLock } from "../../hooks/conversation/useDeskOfflineLock";
|
|
14
|
+
import { useDeskThreadNavigation } from "../../hooks/conversation/useDeskThreadNavigation";
|
|
15
|
+
import useSidePanelStore from "../../store/sidePanel";
|
|
10
16
|
import useConversationStore from "../../store/conversation";
|
|
11
17
|
import useDeskPanelHostStore from "../../store/deskPanelHost";
|
|
12
18
|
import useWorkspaceLayoutStore from "../../store/workspaceLayout";
|
|
13
|
-
import { LAYOUT_BREAKPOINTS, LAYOUT_WIDTHS } from "../../constants/layout";
|
|
19
|
+
import { LAYOUT_BREAKPOINTS, LAYOUT_MEDIA, LAYOUT_WIDTHS } from "../../constants/layout";
|
|
14
20
|
import { useDeskShortcuts } from "../../hooks/common/useDeskShortcuts";
|
|
15
21
|
import { useNewMessageAnnouncement } from "../../hooks/message/useNewMessageAnnouncement";
|
|
16
22
|
import ShortcutHelpModal from "../../components/shortcut-help/ShortcutHelpModal";
|
|
17
23
|
import FolderOverlay from "./FolderOverlay";
|
|
18
|
-
import
|
|
24
|
+
import PhoneThreadFallbackHeader from "./PhoneThreadFallbackHeader";
|
|
25
|
+
import DeskOfflineOverlay from "./DeskOfflineOverlay";
|
|
19
26
|
import { PeerType } from "../../types/conversation";
|
|
20
27
|
const minWidth = (px) => `(min-width: ${px}px)`;
|
|
21
28
|
/** Bright Workspace: folder, list, chat and info as separate white panels on the page canvas. */
|
|
22
|
-
const DeskWorkspace = ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMessageLink, onSearchMessageRevoked, }) => {
|
|
29
|
+
const DeskWorkspace = ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMessageLink, onSearchMessageRevoked, onOpenAppMenu, isOffline = false, offlineContent, }) => {
|
|
23
30
|
const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
|
|
24
31
|
const searchClientMsgID = useConversationStore((state) => state.searchClientMsgID);
|
|
25
32
|
const { isOpen: isInfoOpen, toggle: toggleInfo, close: closeInfo } = useSidePanel("info");
|
|
26
|
-
const
|
|
33
|
+
const tier = useViewportTier();
|
|
34
|
+
const isPhone = tier === "phone";
|
|
35
|
+
const isDesktop = tier === "desktop";
|
|
27
36
|
const isFolderInline = useMediaQuery(minWidth(LAYOUT_BREAKPOINTS.folderInline));
|
|
28
37
|
const isInfoInline = useMediaQuery(minWidth(LAYOUT_BREAKPOINTS.infoInline));
|
|
29
38
|
const isSupportPanelInline = useMediaQuery(minWidth(LAYOUT_BREAKPOINTS.supportPanelInline));
|
|
@@ -31,13 +40,67 @@ const DeskWorkspace = ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMes
|
|
|
31
40
|
const isBotThread = useConversationStore((state) => { var _a; return ((_a = state.conversationData) === null || _a === void 0 ? void 0 : _a.peerType) === PeerType.BOT; });
|
|
32
41
|
const sidePanelsInline = isInfoInline && !(isBotThread && isSupportPanelInline);
|
|
33
42
|
const [workspaceEl, setWorkspaceEl] = useState(null);
|
|
43
|
+
// Touch below desktop: size the desk (and sheets) to the visible viewport, keyboard included.
|
|
44
|
+
const isTouch = useMediaQuery(LAYOUT_MEDIA.touch);
|
|
45
|
+
useVisualViewportHeight(workspaceEl, isTouch && tier !== "desktop");
|
|
34
46
|
const [panelSlotEl, setPanelSlotEl] = useState(null);
|
|
35
47
|
useEffect(() => {
|
|
36
48
|
useDeskPanelHostStore
|
|
37
49
|
.getState()
|
|
38
|
-
.setHost({
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
.setHost({
|
|
51
|
+
workspace: workspaceEl,
|
|
52
|
+
slot: panelSlotEl,
|
|
53
|
+
isInline: sidePanelsInline,
|
|
54
|
+
isFullScreen: isPhone,
|
|
55
|
+
});
|
|
56
|
+
}, [workspaceEl, panelSlotEl, sidePanelsInline, isPhone]);
|
|
57
|
+
useEffect(() => () => {
|
|
58
|
+
useDeskPanelHostStore
|
|
59
|
+
.getState()
|
|
60
|
+
.setHost({ workspace: null, slot: null, isFullScreen: false });
|
|
61
|
+
useWorkspaceLayoutStore.getState().setPhonePendingPane(null);
|
|
62
|
+
}, []);
|
|
63
|
+
// Phone shows one pane: the URL thread unless an open/back tap is still settling.
|
|
64
|
+
const urlThreadId = useSearchParams().get("threadId");
|
|
65
|
+
const pendingPane = useWorkspaceLayoutStore((state) => state.phonePendingPane);
|
|
66
|
+
const setPhonePendingPane = useWorkspaceLayoutStore((state) => state.setPhonePendingPane);
|
|
67
|
+
const showThread = pendingPane ? pendingPane === "thread" : Boolean(urlThreadId);
|
|
68
|
+
const { backToList } = useDeskThreadNavigation();
|
|
69
|
+
const hasConversationData = useConversationStore((state) => Boolean(state.conversationData));
|
|
70
|
+
const listPaneRef = useRef(null);
|
|
71
|
+
const chatPaneRef = useRef(null);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
setPhonePendingPane(null);
|
|
74
|
+
}, [urlThreadId, setPhonePendingPane]);
|
|
75
|
+
// A panel left open from thread A must not cover thread B.
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (isPhone)
|
|
78
|
+
useSidePanelStore.getState().closePanel();
|
|
79
|
+
}, [isPhone, selectedConversationId]);
|
|
80
|
+
const wasShowingThread = useRef(showThread);
|
|
81
|
+
useDeskOfflineLock(workspaceEl, isOffline, () => {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
return isPhone
|
|
84
|
+
? showThread
|
|
85
|
+
? (_b = (_a = chatPaneRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-desk-back]")) !== null && _b !== void 0 ? _b : null
|
|
86
|
+
: listPaneRef.current
|
|
87
|
+
: null;
|
|
88
|
+
});
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
var _a, _b, _c;
|
|
91
|
+
if (!isPhone)
|
|
92
|
+
return;
|
|
93
|
+
// Overlays that set the shortcuts-off marker (nav drawer, sheets, offline lock) own focus.
|
|
94
|
+
const navOpen = document.querySelector("[data-desk-shortcuts-off]") !== null;
|
|
95
|
+
if (showThread) {
|
|
96
|
+
if (!navOpen)
|
|
97
|
+
(_b = (_a = chatPaneRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-desk-back]")) === null || _b === void 0 ? void 0 : _b.focus();
|
|
98
|
+
}
|
|
99
|
+
else if (wasShowingThread.current) {
|
|
100
|
+
(_c = listPaneRef.current) === null || _c === void 0 ? void 0 : _c.focus();
|
|
101
|
+
}
|
|
102
|
+
wasShowingThread.current = showThread;
|
|
103
|
+
}, [isPhone, showThread, hasConversationData]);
|
|
41
104
|
const setFolderOverlayOpen = useWorkspaceLayoutStore((state) => state.setFolderOverlayOpen);
|
|
42
105
|
const [isHelpOpen, setIsHelpOpen] = useState(false);
|
|
43
106
|
const openHelp = useCallback(() => setIsHelpOpen(true), []);
|
|
@@ -48,10 +111,16 @@ const DeskWorkspace = ({ openCreateCannedModal, groupThreadInfoConfig, onCopyMes
|
|
|
48
111
|
if (isFolderInline)
|
|
49
112
|
setFolderOverlayOpen(false);
|
|
50
113
|
}, [isFolderInline, setFolderOverlayOpen]);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return (_jsxs("div", { ref: setWorkspaceEl, className:
|
|
54
|
-
|
|
55
|
-
|
|
114
|
+
const messageList = (_jsx(MessageList, { conversationId: selectedConversationId, searchClientMsgID: searchClientMsgID, openCreateCannedModal: openCreateCannedModal, onOpenThreadInfo: toggleInfo, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked, onBack: isPhone ? backToList : undefined, showPinnedMessageBar: true }));
|
|
115
|
+
// One child layout for every tier, so crossing a breakpoint never remounts the panes.
|
|
116
|
+
return (_jsxs("div", { ref: setWorkspaceEl, className: isPhone
|
|
117
|
+
? "relative flex flex-1 h-[var(--dc-desk-height,var(--dc-app-height,100vh))] overflow-hidden bg-white"
|
|
118
|
+
: "relative flex flex-1 flex-row h-[var(--dc-desk-height,var(--dc-app-height,100vh))] gap-2 p-2 overflow-hidden bg-gray-5", "data-cp-name": "DeskWorkspace", children: [_jsx("div", { "aria-live": "polite", role: "status", className: "sr-only", children: announcement }), isFolderInline && _jsx(DeskAssignedSession, {}), _jsxs("div", { ref: listPaneRef, tabIndex: isPhone ? -1 : undefined, className: isPhone
|
|
119
|
+
? `absolute inset-0 overflow-hidden bg-white outline-none ${showThread ? "invisible" : ""}`
|
|
120
|
+
: "relative h-full shrink-0 overflow-hidden rounded-xl bg-white shadow-sm", style: isPhone
|
|
121
|
+
? undefined
|
|
122
|
+
: { width: isFolderInline ? LAYOUT_WIDTHS.list : LAYOUT_WIDTHS.listCompact }, children: [_jsx(DeskConversationList, { onOpenAppMenu: onOpenAppMenu }), !isFolderInline && _jsx(FolderOverlay, {})] }), _jsxs("div", { ref: chatPaneRef, className: isPhone
|
|
123
|
+
? `absolute inset-0 flex flex-col overflow-hidden bg-white ${showThread ? "" : "invisible"}`
|
|
124
|
+
: "flex h-full flex-1 overflow-hidden rounded-xl bg-white shadow-sm", style: isPhone ? undefined : { minWidth: isDesktop ? LAYOUT_WIDTHS.chatMin : 0 }, children: [isPhone && !hasConversationData && (_jsx(PhoneThreadFallbackHeader, { onBack: backToList, onOpenAppMenu: onOpenAppMenu })), messageList] }), _jsx(ThreadInfo, { isOpen: isInfoOpen, onClose: closeInfo, groupConfig: groupThreadInfoConfig, supportPanelInline: isSupportPanelInline, drawerContainer: workspaceEl }), _jsx("div", { ref: setPanelSlotEl, className: "contents" }), _jsx(ShortcutHelpModal, { open: isHelpOpen, onClose: () => setIsHelpOpen(false) }), isOffline && (_jsx(DeskOfflineOverlay, { isPhone: isPhone, onOpenAppMenu: onOpenAppMenu, children: offlineContent }))] }));
|
|
56
125
|
};
|
|
57
126
|
export default DeskWorkspace;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Placeholder with DeskWorkspace's panels (folder, list, chat) so the desk keeps its shape while
|
|
4
|
+
* the chat engine boots. `children` sits centred in the chat panel. Also used by the CRM app shell.
|
|
5
|
+
*/
|
|
6
|
+
declare const DeskWorkspaceSkeleton: ({ children }: {
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default DeskWorkspaceSkeleton;
|
|
10
|
+
//# sourceMappingURL=DeskWorkspaceSkeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeskWorkspaceSkeleton.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/DeskWorkspaceSkeleton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;GAGG;AACH,QAAA,MAAM,qBAAqB,GAAI,cAAc;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,4CA2CpE,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import DeskListSkeleton from "../../components/conversation/DeskListSkeleton";
|
|
4
|
+
import { LAYOUT_BREAKPOINTS, LAYOUT_WIDTHS } from "../../constants/layout";
|
|
5
|
+
import { useMediaQuery } from "../../hooks/common/useMediaQuery";
|
|
6
|
+
const minWidth = (px) => `(min-width: ${px}px)`;
|
|
7
|
+
const FOLDER_ROW_WIDTHS = ["w-3/4", "w-2/3", "w-4/5", "w-1/2", "w-3/5"];
|
|
8
|
+
const PULSE = "bg-gray-25 motion-safe:animate-pulse";
|
|
9
|
+
/**
|
|
10
|
+
* Placeholder with DeskWorkspace's panels (folder, list, chat) so the desk keeps its shape while
|
|
11
|
+
* the chat engine boots. `children` sits centred in the chat panel. Also used by the CRM app shell.
|
|
12
|
+
*/
|
|
13
|
+
const DeskWorkspaceSkeleton = ({ children }) => {
|
|
14
|
+
const isSupported = useMediaQuery(minWidth(LAYOUT_BREAKPOINTS.minWorkspace));
|
|
15
|
+
const isFolderInline = useMediaQuery(minWidth(LAYOUT_BREAKPOINTS.folderInline));
|
|
16
|
+
return (_jsxs("div", { "data-cp-name": "DeskWorkspaceSkeleton", className: "relative flex h-full min-h-0 flex-1 flex-row gap-2 overflow-hidden bg-gray-5 p-2", children: [isSupported && isFolderInline && (_jsxs("div", { "aria-hidden": "true", className: "flex h-full shrink-0 flex-col gap-4 rounded-xl bg-white p-4 shadow-sm", style: { width: LAYOUT_WIDTHS.folder }, children: [_jsx("span", { className: `h-4 w-24 rounded ${PULSE}` }), FOLDER_ROW_WIDTHS.map((width) => (_jsx("span", { className: `h-3 rounded ${width} ${PULSE}` }, width)))] })), isSupported && (_jsxs("div", { "aria-hidden": "true", className: "flex h-full shrink-0 flex-col overflow-hidden rounded-xl bg-white shadow-sm", style: { width: isFolderInline ? LAYOUT_WIDTHS.list : LAYOUT_WIDTHS.listCompact }, children: [_jsxs("div", { className: "flex items-center gap-2 p-3", children: [!isFolderInline && _jsx("span", { className: `h-9 w-9 shrink-0 rounded-lg ${PULSE}` }), _jsx("span", { className: `h-9 flex-1 rounded-lg ${PULSE}` }), _jsx("span", { className: `h-8 w-8 shrink-0 rounded-lg ${PULSE}` })] }), _jsx("div", { className: "border-b border-gray-25 px-4 pb-3 pt-1", children: _jsx("span", { className: `block h-3 w-28 rounded ${PULSE}` }) }), _jsx(DeskListSkeleton, { rows: 8 })] })), _jsx("div", { className: "flex h-full min-w-0 flex-1 items-center justify-center overflow-hidden rounded-xl bg-white p-6 shadow-sm", children: children })] }));
|
|
17
|
+
};
|
|
18
|
+
export default DeskWorkspaceSkeleton;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface PhoneThreadFallbackHeaderProps {
|
|
2
|
+
onBack: () => void;
|
|
3
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
4
|
+
}
|
|
5
|
+
/** Phone exit from a thread whose header can't render (still loading, removed or no access). */
|
|
6
|
+
declare const PhoneThreadFallbackHeader: ({ onBack, onOpenAppMenu, }: PhoneThreadFallbackHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default PhoneThreadFallbackHeader;
|
|
8
|
+
//# sourceMappingURL=PhoneThreadFallbackHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhoneThreadFallbackHeader.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/PhoneThreadFallbackHeader.tsx"],"names":[],"mappings":"AAIA,UAAU,8BAA8B;IACtC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAKD,gGAAgG;AAChG,QAAA,MAAM,yBAAyB,GAAI,4BAGhC,8BAA8B,4CA6BhC,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { StrokeIcon } from "../../components/icon/StrokeIcon";
|
|
5
|
+
const buttonClass = "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border-0 bg-transparent p-0 text-gray-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary-200";
|
|
6
|
+
/** Phone exit from a thread whose header can't render (still loading, removed or no access). */
|
|
7
|
+
const PhoneThreadFallbackHeader = ({ onBack, onOpenAppMenu, }) => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
return (_jsxs("div", { className: "flex h-14 shrink-0 items-center gap-1 border-b border-gray-25 bg-white px-2", "data-cp-name": "PhoneThreadFallbackHeader", children: [_jsx("button", { type: "button", "data-desk-back": true, "aria-label": t("back"), onClick: onBack, className: buttonClass, children: _jsx(StrokeIcon, { name: "chevron-left", size: 20 }) }), onOpenAppMenu && (_jsx("button", { type: "button", "data-app-menu-button": true, "aria-label": t("app_menu_open"), onClick: (event) => onOpenAppMenu(event.currentTarget), className: buttonClass, children: _jsx(StrokeIcon, { name: "menu", size: 20 }) }))] }));
|
|
10
|
+
};
|
|
11
|
+
export default PhoneThreadFallbackHeader;
|
|
@@ -6,6 +6,8 @@ interface DChatDeskMessageProps {
|
|
|
6
6
|
onCopyMessageLink?: (conversationId: string, clientMsgID: string) => void;
|
|
7
7
|
/** Called instead of the SDK's default toast when a jumped-to message turns out to be revoked. */
|
|
8
8
|
onSearchMessageRevoked?: () => void;
|
|
9
|
+
/** Phone: opens the host's app menu from the list header or thread fallback header; gets the tapped button. */
|
|
10
|
+
onOpenAppMenu?: (opener: HTMLElement | null) => void;
|
|
9
11
|
}
|
|
10
12
|
declare const DChatDeskMessage: (props: DChatDeskMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
13
|
export default DChatDeskMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/index.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAK5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,UAAU,qBAAqB;IAC7B,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAChE,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,+GAA+G;IAC/G,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAWD,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CA4CrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|