@droppii-org/chat-sdk 0.8.2 → 0.8.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.
Files changed (63) hide show
  1. package/dist/components/canned-response/CannedResponseBody.js +1 -1
  2. package/dist/components/common/ShadowSafeInfiniteScroll.d.ts +15 -0
  3. package/dist/components/common/ShadowSafeInfiniteScroll.d.ts.map +1 -0
  4. package/dist/components/common/ShadowSafeInfiniteScroll.js +45 -0
  5. package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
  6. package/dist/components/conversation/DeskConversationList.js +7 -5
  7. package/dist/components/conversation/folderEmptyState.d.ts.map +1 -1
  8. package/dist/components/conversation/folderEmptyState.js +2 -0
  9. package/dist/components/conversation/listHeading.d.ts +1 -1
  10. package/dist/components/conversation/listHeading.d.ts.map +1 -1
  11. package/dist/components/conversation/listHeading.js +7 -1
  12. package/dist/components/conversation-detail/ConversationMessageList.js +2 -2
  13. package/dist/components/conversation-detail/thread-search/ThreadSearchContent.js +1 -1
  14. package/dist/components/conversation-inbox/ConversationInboxList.js +1 -1
  15. package/dist/components/conversation-inbox/PublicGroupList.js +1 -1
  16. package/dist/components/conversation-inbox/contact-search/ContactSearchMessagesTab.js +1 -1
  17. package/dist/components/conversation-inbox/contact-search/ContactSearchPanel.js +1 -1
  18. package/dist/components/media-collection/FileCollection.js +3 -3
  19. package/dist/components/media-collection/ImageCollection.js +1 -1
  20. package/dist/components/media-collection/LinkCollection.js +2 -2
  21. package/dist/components/media-collection/VideoCollection.js +1 -1
  22. package/dist/components/media-resources/FileResourceList.js +2 -2
  23. package/dist/components/media-resources/ResourceScrollContainer.js +1 -1
  24. package/dist/components/message/MessageInfiniteScroll.js +1 -1
  25. package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
  26. package/dist/components/message/footer/EnterHandler.js +14 -1
  27. package/dist/components/message/footer/ToolbarPlugin.d.ts.map +1 -1
  28. package/dist/components/message/footer/ToolbarPlugin.js +9 -1
  29. package/dist/components/message/footer/resetEditorAfterSend.d.ts.map +1 -1
  30. package/dist/components/message/footer/resetEditorAfterSend.js +7 -11
  31. package/dist/components/message/item/FileMessage.js +2 -2
  32. package/dist/components/message/item/index.js +2 -2
  33. package/dist/components/search-conversation/SearchConversationAsGroups.js +1 -1
  34. package/dist/components/search-conversation/SearchConversationAsMessages.js +1 -1
  35. package/dist/components/search-conversation/SearchConversationAsUsers.js +1 -1
  36. package/dist/components/search-conversation/SearchMessageOnCurrentConversation.js +1 -1
  37. package/dist/components/session/SessionFolderList.d.ts +4 -3
  38. package/dist/components/session/SessionFolderList.d.ts.map +1 -1
  39. package/dist/components/session/SessionFolderList.js +14 -5
  40. package/dist/hooks/message/useMessage.d.ts +1 -1
  41. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  42. package/dist/hooks/message/useMessage.js +6 -8
  43. package/dist/hooks/message/useMessageListScroll.d.ts.map +1 -1
  44. package/dist/hooks/message/useMessageListScroll.js +10 -3
  45. package/dist/hooks/session/useGetSession.d.ts.map +1 -1
  46. package/dist/hooks/session/useGetSession.js +2 -0
  47. package/dist/hooks/session/useGetSessionList.d.ts +235 -0
  48. package/dist/hooks/session/useGetSessionList.d.ts.map +1 -0
  49. package/dist/hooks/session/useGetSessionList.js +23 -0
  50. package/dist/locales/vi/common.json +1 -0
  51. package/dist/store/session.d.ts +1 -13
  52. package/dist/store/session.d.ts.map +1 -1
  53. package/dist/store/session.js +10 -9
  54. package/dist/store/sessionFolder.d.ts +2 -0
  55. package/dist/store/sessionFolder.d.ts.map +1 -1
  56. package/dist/store/sessionFolder.js +3 -1
  57. package/dist/store/type.d.ts +4 -0
  58. package/dist/store/type.d.ts.map +1 -1
  59. package/dist/styles/global.css +1 -1
  60. package/dist/utils/download.d.ts +10 -0
  61. package/dist/utils/download.d.ts.map +1 -1
  62. package/dist/utils/download.js +51 -0
  63. package/package.json +1 -1
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
7
7
  import { CannedResponseVisibleScope } from "../../types/chat";
8
8
  import TeamItem from "./team/TeamItem";
9
9
  import { useFetchCannedResponse } from "../../hooks/canned-response/useFetchCannedResponse";
10
- import InfiniteScroll from "react-infinite-scroll-component";
10
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
11
11
  import { Icon } from "../../components/icon";
12
12
  import { sanitizeHtml } from "../../utils/common";
13
13
  import { useDebounce } from "ahooks";
@@ -0,0 +1,15 @@
1
+ import { ComponentProps } from "react";
2
+ import InfiniteScroll from "react-infinite-scroll-component";
3
+ type InfiniteScrollProps = ComponentProps<typeof InfiniteScroll>;
4
+ /**
5
+ * Drop-in replacement for `react-infinite-scroll-component` that resolves a
6
+ * string `scrollableTarget` inside the tree the list is mounted in.
7
+ *
8
+ * The library looks the id up with `document.getElementById`, which cannot see
9
+ * into a shadow root (Mall renders the chat in one), so the scroll listener
10
+ * never attached and page 2 was never requested. Here the id is resolved
11
+ * through the probe's own root node and the element is handed to the library.
12
+ */
13
+ declare const ShadowSafeInfiniteScroll: ({ scrollableTarget, children, ...rest }: InfiniteScrollProps) => import("react/jsx-runtime").JSX.Element;
14
+ export default ShadowSafeInfiniteScroll;
15
+ //# sourceMappingURL=ShadowSafeInfiniteScroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShadowSafeInfiniteScroll.d.ts","sourceRoot":"","sources":["../../../src/components/common/ShadowSafeInfiniteScroll.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAyB,MAAM,OAAO,CAAC;AAC9D,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAE7D,KAAK,mBAAmB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AAEjE;;;;;;;;GAQG;AACH,QAAA,MAAM,wBAAwB,GAAI,yCAI/B,mBAAmB,4CA2CrB,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import { useCallback, useState } from "react";
15
+ import InfiniteScroll from "react-infinite-scroll-component";
16
+ /**
17
+ * Drop-in replacement for `react-infinite-scroll-component` that resolves a
18
+ * string `scrollableTarget` inside the tree the list is mounted in.
19
+ *
20
+ * The library looks the id up with `document.getElementById`, which cannot see
21
+ * into a shadow root (Mall renders the chat in one), so the scroll listener
22
+ * never attached and page 2 was never requested. Here the id is resolved
23
+ * through the probe's own root node and the element is handed to the library.
24
+ */
25
+ const ShadowSafeInfiniteScroll = (_a) => {
26
+ var { scrollableTarget, children } = _a, rest = __rest(_a, ["scrollableTarget", "children"]);
27
+ const targetId = typeof scrollableTarget === "string" ? scrollableTarget : null;
28
+ const [resolved, setResolved] = useState(null);
29
+ const probeRef = useCallback((node) => {
30
+ if (!node || !targetId)
31
+ return;
32
+ const root = node.getRootNode();
33
+ const element = typeof root.getElementById === "function"
34
+ ? root.getElementById(targetId)
35
+ : null;
36
+ setResolved({ id: targetId, target: element !== null && element !== void 0 ? element : targetId });
37
+ }, [targetId]);
38
+ if (!targetId) {
39
+ return (_jsx(InfiniteScroll, Object.assign({}, rest, { scrollableTarget: scrollableTarget, children: children })));
40
+ }
41
+ return (_jsxs(_Fragment, { children: [_jsx("span", { ref: probeRef, hidden: true, "aria-hidden": "true" }), (resolved === null || resolved === void 0 ? void 0 : resolved.id) === targetId && (
42
+ // The library types the prop as ReactNode but accepts an element.
43
+ _jsx(InfiniteScroll, Object.assign({}, rest, { scrollableTarget: resolved.target, children: children })))] }));
44
+ };
45
+ export default ShadowSafeInfiniteScroll;
@@ -1 +1 @@
1
- {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AAiCA,UAAU,yBAAyB;IACjC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,QAAA,MAAM,oBAAoB,GAAI,mBAAmB,yBAAyB,4CA2RzE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AAiCA,UAAU,yBAAyB;IACjC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;CACtD;AAED,QAAA,MAAM,oBAAoB,GAAI,mBAAmB,yBAAyB,4CA6RzE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -8,10 +8,10 @@ import { useTranslation } from "react-i18next";
8
8
  import { useBoolean, useDebounce } from "ahooks";
9
9
  import SearchConversation from "../../components/search-conversation";
10
10
  import useSessionStore from "../../store/session";
11
- import InfiniteScroll from "react-infinite-scroll-component";
11
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
12
12
  import ConversationBySessionItem from "./ConversationBySessionItem";
13
13
  import ConversationByGroupItem from "./ConversationByGroupItem";
14
- import { useGetSession } from "../../hooks/session/useGetSession";
14
+ import { useGetSessionList } from "../../hooks/session/useGetSessionList";
15
15
  import { useSortedSessions } from "../../hooks/session/useSortedSessions";
16
16
  import { useSessionLatestPreview } from "../../hooks/session/useSessionLatestPreview";
17
17
  import { useGetTeamSessionSummary } from "../../hooks/session/useGetTeamSessionSummary";
@@ -43,9 +43,9 @@ const DeskConversationList = ({ onOpenAppMenu }) => {
43
43
  const viewMode = useSessionStore((state) => state.viewMode);
44
44
  const isAllGroupsView = viewMode === "allGroups";
45
45
  const { data: teamSummaries } = useGetTeamSessionSummary();
46
- const { dataFlatten: rawSessions, hasNextPage, fetchNextPage, refetch, isSyncing, isLoading: isSessionsLoading, } = useGetSession({
46
+ const { dataFlatten: rawSessions, hasNextPage, fetchNextPage, refetch, isSyncing, isLoading: isSessionsLoading, } = useGetSessionList({
47
47
  filter: filterSummary,
48
- options: { isEnabled: !isAllGroupsView },
48
+ isEnabled: !isAllGroupsView,
49
49
  });
50
50
  const { groups: conversationGroups, fetchNextPage: fetchNextGroupsPage, hasNextPage: hasNextGroupsPage, isLoading: isConversationGroupsLoading, } = useConversationGroups({ enabled: isAllGroupsView });
51
51
  const { previews: latestPreviewMap, isLoading: isSessionPreviewLoading } = useSessionLatestPreview(rawSessions);
@@ -146,7 +146,9 @@ const DeskConversationList = ({ onOpenAppMenu }) => {
146
146
  }, [searchParams]);
147
147
  useEffect(() => {
148
148
  const handler = (sessionUpdated) => {
149
- if (sessionUpdated.status !== filterSummary.status ||
149
+ // The open group holds every non-completed status, so any update may move a row.
150
+ if (filterSummary.open ||
151
+ sessionUpdated.status !== filterSummary.status ||
150
152
  sessionUpdated.tag !== filterSummary.tag) {
151
153
  refetch();
152
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"folderEmptyState.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/folderEmptyState.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,KAAG,MACI,CAAC"}
1
+ {"version":3,"file":"folderEmptyState.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/folderEmptyState.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,KAAG,MACI,CAAC"}
@@ -1,7 +1,9 @@
1
1
  import { SessionStatus, SessionTag } from "../../types/chat";
2
+ import { OPEN_FOLDER_KEY } from "../../store/sessionFolder";
2
3
  import { ALL_GROUPS_KEY } from "../../components/session/sessionFilters";
3
4
  /** i18n key of the empty-list sentence for each folder; never reuses the search screen's wording. */
4
5
  const EMPTY_KEY_BY_FILTER = {
6
+ [OPEN_FOLDER_KEY]: "folder_empty_open",
5
7
  [SessionTag.SLOW_PROCESSING]: "folder_empty_slow_processing",
6
8
  [SessionStatus.WAITING_PROCESS]: "folder_empty_waiting_process",
7
9
  [SessionTag.AWAITING_REPLY]: "folder_empty_awaiting_reply",
@@ -1,4 +1,4 @@
1
- import type { ActiveFolder } from "../../store/sessionFolder";
1
+ import { type ActiveFolder } from "../../store/sessionFolder";
2
2
  import type { ISessionSummaryResponse, ITeamSessionSummaryItem } from "../../types/dto";
3
3
  export interface ListHeading {
4
4
  /** Small line above the title: "my messages" or the team name. */
@@ -1 +1 @@
1
- {"version":3,"file":"listHeading.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/listHeading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAMpF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,uBAAuB,CAAC;IACpC,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,4EAA4E;AAC5E,eAAO,MAAM,cAAc,GAAI,8BAA8B,YAAY,KAAG,WAoB3E,CAAC"}
1
+ {"version":3,"file":"listHeading.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/listHeading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAMpF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,uBAAuB,CAAC;IACpC,KAAK,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,4EAA4E;AAC5E,eAAO,MAAM,cAAc,GAAI,8BAA8B,YAAY,KAAG,WAyB3E,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { OPEN_FOLDER_KEY } from "../../store/sessionFolder";
1
2
  import { getFilterConfig, getFilterCount, } from "../../components/session/sessionFilters";
2
3
  /** Heading text that always describes the folder the list is built from. */
3
4
  export const getListHeading = ({ folder, mySummary, teams }) => {
@@ -16,9 +17,14 @@ export const getListHeading = ({ folder, mySummary, teams }) => {
16
17
  count: config ? getFilterCount(config, team === null || team === void 0 ? void 0 : team.summary) : undefined,
17
18
  };
18
19
  }
20
+ const isOpenGroup = folder.filterKey === OPEN_FOLDER_KEY;
19
21
  return {
20
22
  contextKey: "my_messages",
21
23
  titleKey,
22
- count: config ? getFilterCount(config, mySummary) : undefined,
24
+ count: isOpenGroup
25
+ ? mySummary === null || mySummary === void 0 ? void 0 : mySummary.activeSessionCount
26
+ : config
27
+ ? getFilterCount(config, mySummary)
28
+ : undefined,
23
29
  };
24
30
  };
@@ -43,8 +43,8 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
43
43
  const canReply = usePeerLinkState(conversation) !== "unlinked";
44
44
  const viewerUserID = (user === null || user === void 0 ? void 0 : user.userID) || authUserID;
45
45
  const isAgentView = isSupportSessionAgentView(Object.assign(Object.assign({}, conversation), { conversationID: conversationId }), viewerUserID);
46
- // App history strips the assignment log and session dividers, which an
47
- // agent handling someone else's session needs — load the full history.
46
+ // An agent handling someone else's session keeps loading the full history;
47
+ // the assignment log and session dividers in it are hidden at render.
48
48
  const useAppHistory = !isAgentView;
49
49
  const messageController = useMessage(conversationId, searchClientMsgID, true, useAppHistory, onSearchMessageRevoked);
50
50
  useViewOnlyGroupRefresh({
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Input, Spin, message as toastMessage } from "antd";
5
5
  import { useDebounce } from "ahooks";
6
- import InfiniteScroll from "react-infinite-scroll-component";
6
+ import InfiniteScroll from "../../common/ShadowSafeInfiniteScroll";
7
7
  import { useTranslation } from "react-i18next";
8
8
  import { MessageType, } from "@droppii-org/wasm-client-sdk";
9
9
  import { Icon } from "../../../components/icon";
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import { Empty } from "antd";
5
- import InfiniteScroll from "react-infinite-scroll-component";
5
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
6
6
  import useConversationStore from "../../store/conversation";
7
7
  import { useChatNavigate } from "../../hooks/conversation/useChatNavigate";
8
8
  import { Icon } from "../../components/icon";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Spin } from "antd";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import { useTranslation } from "react-i18next";
6
6
  import { useChatContext } from "../../context/ChatContext";
7
7
  import { useChatNavigate } from "../../hooks/conversation/useChatNavigate";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Spin } from "antd";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../../common/ShadowSafeInfiniteScroll";
5
5
  import { useTranslation } from "react-i18next";
6
6
  import ContactSearchMessageResultItem from "./ContactSearchMessageResultItem";
7
7
  import ContactSearchStateMessage from "./ContactSearchStateMessage";
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useEffect, useState } from "react";
4
4
  import { Drawer, Input, Spin, message as toastMessage, } from "antd";
5
5
  import { useDebounce } from "ahooks";
6
- import InfiniteScroll from "react-infinite-scroll-component";
6
+ import InfiniteScroll from "../../common/ShadowSafeInfiniteScroll";
7
7
  import { useTranslation } from "react-i18next";
8
8
  import { MessageType } from "@droppii-org/wasm-client-sdk";
9
9
  import { Icon } from "../../../components/icon";
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MessageType } from "@droppii-org/wasm-client-sdk";
3
3
  import { useSearchMessage } from "../../hooks/search/useSearchMessage";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import { Empty, Spin } from "antd";
6
6
  import { useCallback } from "react";
7
7
  import dayjs from "dayjs";
@@ -10,7 +10,7 @@ import useConversationStore from "../../store/conversation";
10
10
  import { useTranslation } from "react-i18next";
11
11
  import { documentIcon } from "../../assets/svg";
12
12
  import { renderFileSize, shortenFileName } from "../../utils/common";
13
- import { downloadFileFromUrl } from "../../utils/download";
13
+ import { openFileOrDownload } from "../../utils/download";
14
14
  const FileCollection = () => {
15
15
  const { t } = useTranslation();
16
16
  const selectedSourceId = useConversationStore((state) => state.selectedSourceId);
@@ -24,7 +24,7 @@ const FileCollection = () => {
24
24
  return (_jsxs("div", { className: "px-3", children: [_jsx("span", { className: "text-sm font-medium text-gray-500", children: dayjs(date).format(LIBRARY_DATE_HEADER_FORMAT) }), _jsx("div", { className: "flex flex-col gap-1 mt-2", children: items.map((item) => {
25
25
  var _a, _b, _c;
26
26
  const fileContent = JSON.parse(((_a = item === null || item === void 0 ? void 0 : item.chatLog) === null || _a === void 0 ? void 0 : _a.content) || "{}");
27
- return (_jsxs("div", { className: "relative flex flex-row items-center gap-2 align-center bg-gray-100 rounded-md p-2 cursor-pointer", onClick: () => downloadFileFromUrl((fileContent === null || fileContent === void 0 ? void 0 : fileContent.sourceUrl) || "", (fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || ""), children: [documentIcon, _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("span", { className: "text-sm font-medium", children: shortenFileName((fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || "", {
27
+ return (_jsxs("div", { className: "relative flex flex-row items-center gap-2 align-center bg-gray-100 rounded-md p-2 cursor-pointer", onClick: () => void openFileOrDownload((fileContent === null || fileContent === void 0 ? void 0 : fileContent.sourceUrl) || "", (fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || ""), children: [documentIcon, _jsxs("div", { className: "flex flex-col flex-1", children: [_jsx("span", { className: "text-sm font-medium", children: shortenFileName((fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || "", {
28
28
  maxLength: 32,
29
29
  }) }), _jsx("span", { className: "text-xs text-gray-500", children: `${renderFileSize(fileContent.fileSize || 0)} - ${dayjs(((_b = item === null || item === void 0 ? void 0 : item.chatLog) === null || _b === void 0 ? void 0 : _b.sendTime) || 0).format("HH:mm")}` })] })] }, (_c = item.chatLog) === null || _c === void 0 ? void 0 : _c.clientMsgID));
30
30
  }) })] }, date));
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MessageType } from "@droppii-org/wasm-client-sdk";
3
3
  import { useSearchMessage } from "../../hooks/search/useSearchMessage";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import { Empty, Image, Spin } from "antd";
6
6
  import { useCallback } from "react";
7
7
  import dayjs from "dayjs";
@@ -6,7 +6,7 @@ import { useSearchMessage } from "../../hooks/search/useSearchMessage";
6
6
  import { useCallback } from "react";
7
7
  import dayjs from "dayjs";
8
8
  import { LIBRARY_DATE_HEADER_FORMAT } from "../../constants/dateFormat";
9
- import InfiniteScroll from "react-infinite-scroll-component";
9
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
10
10
  import { MessageType, SessionType } from "@droppii-org/wasm-client-sdk";
11
11
  import { Icon } from "../../components/icon";
12
12
  import { DChatSDK } from "../../constants/sdk";
@@ -72,7 +72,7 @@ const LinkCollection = ({ onClose }) => {
72
72
  }) })] }, date));
73
73
  }, []);
74
74
  if (dataFlatten.length === 0 && !isLoading)
75
- return _jsx(Empty, { description: t("no_media_files") });
75
+ return _jsx(Empty, { description: t("no_resource_links") });
76
76
  if (isLoading)
77
77
  return (_jsx("div", { className: "flex items-center justify-center", children: _jsx(Spin, {}) }));
78
78
  return (_jsx("div", { id: "scrollableFileDiv", "data-cp-name": "LinkCollection", className: "h-full overflow-auto", children: _jsx(InfiniteScroll, { dataLength: Object.keys(groupedData).length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableFileDiv", children: Object.entries(groupedData).map(([date, items]) => renderItem(date, items)) }) }));
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MessageType } from "@droppii-org/wasm-client-sdk";
3
3
  import { useSearchMessage } from "../../hooks/search/useSearchMessage";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import { Empty, Image, Spin } from "antd";
6
6
  import { useState } from "react";
7
7
  import dayjs from "dayjs";
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { documentIcon } from "../../assets/svg";
4
4
  import { parseMessageContent, renderFileSize, shortenFileName, } from "../../utils/common";
5
- import { downloadFileFromUrl } from "../../utils/download";
5
+ import { openFileOrDownload } from "../../utils/download";
6
6
  import { MediaResourceTabKey } from "./constants";
7
7
  import ResourceScrollContainer from "./ResourceScrollContainer";
8
8
  import { useResourceTab } from "./useResourceTab";
@@ -11,7 +11,7 @@ const FileResourceList = () => {
11
11
  return (_jsx(ResourceScrollContainer, Object.assign({ "data-cp-name": "FileResourceList" }, containerProps, { itemCount: items.length, children: _jsx("div", { className: "flex flex-col gap-2 p-3", children: items.map((item) => {
12
12
  var _a, _b;
13
13
  const fileContent = parseMessageContent((_a = item === null || item === void 0 ? void 0 : item.chatLog) === null || _a === void 0 ? void 0 : _a.content);
14
- return (_jsxs("div", { className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-[#f5f5f5]/20 p-3", onClick: () => downloadFileFromUrl((fileContent === null || fileContent === void 0 ? void 0 : fileContent.sourceUrl) || "", (fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || ""), children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-auto", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[16px] font-medium leading-[1.6] text-gray-900", children: shortenFileName(fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) }), _jsx("span", { className: "text-[13px] font-normal leading-[1.6] text-gray-400", children: renderFileSize((fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileSize) || 0) })] })] }, (_b = item.chatLog) === null || _b === void 0 ? void 0 : _b.clientMsgID));
14
+ return (_jsxs("div", { className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-[#f5f5f5]/20 p-3", onClick: () => void openFileOrDownload((fileContent === null || fileContent === void 0 ? void 0 : fileContent.sourceUrl) || "", (fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || ""), children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-auto", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[16px] font-medium leading-[1.6] text-gray-900", children: shortenFileName(fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) }), _jsx("span", { className: "text-[13px] font-normal leading-[1.6] text-gray-400", children: renderFileSize((fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileSize) || 0) })] })] }, (_b = item.chatLog) === null || _b === void 0 ? void 0 : _b.clientMsgID));
15
15
  }) }) })));
16
16
  };
17
17
  export default FileResourceList;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import { Button, Spin } from "antd";
6
6
  import { useTranslation } from "react-i18next";
7
7
  import ResourceEmptyState from "./ResourceEmptyState";
@@ -2,6 +2,6 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Spin } from "antd";
4
4
  import clsx from "clsx";
5
- import InfiniteScroll from "react-infinite-scroll-component";
5
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
6
6
  const MessageInfiniteScroll = ({ scrollRef, scrollableTargetId, loadState, moreOldLoading = false, onLoadMoreOld, onScroll, children, empty, containerClassName, containerProps, }) => (_jsx("div", Object.assign({ id: scrollableTargetId, ref: scrollRef, className: clsx("flex h-full flex-col-reverse overflow-x-hidden overflow-y-auto pb-3", containerClassName), "data-cp-name": "MessageInfiniteScroll" }, containerProps, { children: empty && loadState.messageList.length === 0 ? (empty) : (_jsx(InfiniteScroll, { dataLength: loadState.messageList.length, next: onLoadMoreOld, className: "flex w-full min-w-0 flex-col-reverse", inverse: true, hasMore: loadState.hasMoreOld, loader: moreOldLoading ? (_jsx("div", { className: "flex w-full items-center justify-center py-2", children: _jsx(Spin, { size: "small" }) })) : (_jsx("span", { className: "sr-only" })), scrollableTarget: scrollableTargetId, onScroll: (e) => onScroll(e), children: children })) })));
7
7
  export default MessageInfiniteScroll;
@@ -1 +1 @@
1
- {"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"AAoBA,MAAM,CAAC,OAAO,UAAU,YAAY,SAkHnC"}
1
+ {"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"AA+BA,MAAM,CAAC,OAAO,UAAU,YAAY,SAyHnC"}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
3
- import { KEY_ENTER_COMMAND, COMMAND_PRIORITY_NORMAL, $createParagraphNode, $getRoot, } from "lexical";
3
+ import { KEY_ENTER_COMMAND, COMMAND_PRIORITY_NORMAL, $createParagraphNode, $getRoot, $getSelection, $isRangeSelection, } from "lexical";
4
+ import { $isListNode } from "@lexical/list";
4
5
  import { clearComposerHistoryAfterUpdate } from "./clearComposerHistory";
5
6
  import { resetEditorAfterSend, resetEditorIfUnchanged } from "./resetEditorAfterSend";
6
7
  import { useEffect, useRef } from "react";
@@ -11,6 +12,12 @@ import emitter, { emit } from "../../../utils/events";
11
12
  import { extractMentions } from "./mention/extractMentions";
12
13
  import useAuthStore from "../../../store/auth";
13
14
  import { LAYOUT_MEDIA } from "../../../constants/layout";
15
+ const isCaretInList = (editor) => editor.getEditorState().read(() => {
16
+ const selection = $getSelection();
17
+ if (!$isRangeSelection(selection))
18
+ return false;
19
+ return $isListNode(selection.anchor.getNode().getTopLevelElement());
20
+ });
14
21
  export default function EnterHandler() {
15
22
  const [editor] = useLexicalComposerContext();
16
23
  const { onSendMessage, isInternal, listUploadFiles, isOpenCanned, activeCannedIndex, isMentionMenuOpen, } = useMessageFooterContext();
@@ -37,6 +44,12 @@ export default function EnterHandler() {
37
44
  // A null event (IME composition end) has nothing to send or cancel on desktop.
38
45
  if (isCrm && !event)
39
46
  return true;
47
+ // Enter inside a list item continues (or, on an empty item, leaves) the
48
+ // list through Lexical's own handler; Ctrl/Cmd+Enter or the Send button
49
+ // sends from there.
50
+ if (!isOpenCanned && event && !event.ctrlKey && !event.metaKey && isCaretInList(editor)) {
51
+ return false;
52
+ }
40
53
  event.preventDefault();
41
54
  if (isOpenCanned) {
42
55
  emit("CANNED_RESPONSE_SELECT", activeCannedIndex);
@@ -1 +1 @@
1
- {"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ToolbarPlugin.tsx"],"names":[],"mappings":"AA4DA,eAAO,MAAM,aAAa,GAAI,aAAqB;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,4CA2NvE,CAAC"}
1
+ {"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ToolbarPlugin.tsx"],"names":[],"mappings":"AA6DA,eAAO,MAAM,aAAa,GAAI,aAAqB;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,4CAkOvE,CAAC"}
@@ -6,7 +6,7 @@ import { $isListNode, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND
6
6
  import { $createQuoteNode, $isQuoteNode } from "@lexical/rich-text";
7
7
  import { TOGGLE_LINK_COMMAND } from "@lexical/link";
8
8
  import { useCallback, useEffect, useMemo, useState } from "react";
9
- import { BoldOutlined, ItalicOutlined, StrikethroughOutlined, OrderedListOutlined, UnorderedListOutlined, } from "@ant-design/icons";
9
+ import { BoldOutlined, ItalicOutlined, StrikethroughOutlined, UnderlineOutlined, OrderedListOutlined, UnorderedListOutlined, } from "@ant-design/icons";
10
10
  import { Button } from "antd";
11
11
  const quoteIcon = (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M5.24615 10.5714C4.5616 10.5714 3.99078 10.5715 3.53762 10.5105C3.0593 10.4462 2.62745 10.3047 2.28042 9.95769C1.9334 9.61072 1.79194 9.17887 1.72763 8.70055C1.6667 8.24737 1.66673 7.67654 1.66675 6.99199V6.91274C1.66673 6.22819 1.6667 5.65734 1.72763 5.20419C1.79194 4.72586 1.9334 4.29401 2.28043 3.94699C2.62746 3.59997 3.0593 3.4585 3.53762 3.3942C3.99078 3.33327 4.56161 3.33329 5.24615 3.33331H5.32541C6.00995 3.33329 6.5808 3.33327 7.03397 3.3942C7.51228 3.4585 7.94413 3.59997 8.29116 3.94699C8.63817 4.29401 8.77966 4.72586 8.84396 5.20419C8.90491 5.65734 8.90484 6.22817 8.90484 6.91272V6.99198C8.90484 7.67652 8.90491 8.24737 8.84396 8.70055C8.77966 9.17887 8.63817 9.61072 8.29116 9.95769C7.94413 10.3047 7.51228 10.4462 7.03397 10.5105C6.5808 10.5715 6.00998 10.5714 5.32544 10.5714H5.24615Z", fill: "currentColor" }), _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M2.84403 16.1313C2.71884 15.7295 2.94301 15.3023 3.34474 15.1772C5.71249 14.4393 7.38095 12.3426 7.38095 9.914V6.76172C7.38095 6.34094 7.72207 5.99982 8.14286 5.99982C8.56366 5.99982 8.90476 6.34094 8.90476 6.76172V9.914C8.90476 13.0731 6.73976 15.7152 3.79812 16.6319C3.39638 16.7572 2.96923 16.533 2.84403 16.1313Z", fill: "currentColor" }), _jsx("path", { d: "M14.389 10.5714C13.7044 10.5714 13.1336 10.5715 12.6804 10.5105C12.2021 10.4462 11.7703 10.3047 11.4233 9.95769C11.0762 9.61072 10.9348 9.17887 10.8704 8.70055C10.8095 8.24737 10.8096 7.67654 10.8096 6.99199V6.91274C10.8096 6.22819 10.8095 5.65734 10.8704 5.20419C10.9348 4.72586 11.0762 4.29401 11.4233 3.94699C11.7703 3.59997 12.2021 3.4585 12.6804 3.3942C13.1336 3.33327 13.7044 3.33329 14.389 3.33331H14.4682C15.1528 3.33329 15.7236 3.33327 16.1768 3.3942C16.6551 3.4585 17.087 3.59997 17.4339 3.94699C17.781 4.29401 17.9225 4.72586 17.9868 5.20419C18.0477 5.65734 18.0477 6.22817 18.0477 6.91272V6.99198C18.0477 7.67652 18.0477 8.24737 17.9868 8.70055C17.9225 9.17887 17.781 9.61072 17.4339 9.95769C17.087 10.3047 16.6551 10.4462 16.1768 10.5105C15.7236 10.5715 15.1528 10.5714 14.4682 10.5714H14.389Z", fill: "currentColor" }), _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M11.9869 16.1313C11.8617 15.7295 12.0858 15.3023 12.4876 15.1772C14.8553 14.4393 16.5238 12.3426 16.5238 9.914V6.76172C16.5238 6.34094 16.8649 5.99982 17.2857 5.99982C17.7065 5.99982 18.0476 6.34094 18.0476 6.76172V9.914C18.0476 13.0731 15.8825 15.7152 12.9409 16.6319C12.5392 16.7572 12.112 16.533 11.9869 16.1313Z", fill: "currentColor" })] }));
12
12
  export const ToolbarPlugin = ({ compact = false }) => {
@@ -26,6 +26,12 @@ export const ToolbarPlugin = ({ compact = false }) => {
26
26
  onPress: () => formatText("italic"),
27
27
  isActive: activeMarks.includes("italic"),
28
28
  },
29
+ {
30
+ key: "underline",
31
+ icon: _jsx(UnderlineOutlined, { size: 22 }),
32
+ onPress: () => formatText("underline"),
33
+ isActive: activeMarks.includes("underline"),
34
+ },
29
35
  {
30
36
  key: "strikethrough",
31
37
  icon: _jsx(StrikethroughOutlined, { size: 22 }),
@@ -120,6 +126,8 @@ export const ToolbarPlugin = ({ compact = false }) => {
120
126
  marks.push("bold");
121
127
  if (selection.hasFormat("italic"))
122
128
  marks.push("italic");
129
+ if (selection.hasFormat("underline"))
130
+ marks.push("underline");
123
131
  if (selection.hasFormat("strikethrough"))
124
132
  marks.push("strikethrough");
125
133
  // block
@@ -1 +1 @@
1
- {"version":3,"file":"resetEditorAfterSend.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/resetEditorAfterSend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAoE,MAAM,SAAS,CAAC;AAW1G,eAAO,MAAM,sBAAsB,GACjC,QAAQ,aAAa,EACrB,MAAM;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,SAU9C,CAAC;AAIF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,aAAa,SAgDzD,CAAC"}
1
+ {"version":3,"file":"resetEditorAfterSend.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/resetEditorAfterSend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAoE,MAAM,SAAS,CAAC;AAW1G,eAAO,MAAM,sBAAsB,GACjC,QAAQ,aAAa,EACrB,MAAM;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,SAU9C,CAAC;AAIF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,aAAa,SA4CzD,CAAC"}
@@ -16,8 +16,8 @@ export const resetEditorIfUnchanged = (editor, sent) => {
16
16
  return;
17
17
  resetEditorAfterSend(editor);
18
18
  };
19
- // Empties the composer after a send but keeps the typing format, list and quote
20
- // context, so the next message continues in the same block style.
19
+ // Empties the composer after a send. Inline marks are cleared; the list and
20
+ // quote context stays so the next message continues in the same block style.
21
21
  export const resetEditorAfterSend = (editor) => {
22
22
  clearComposerHistoryAfterUpdate(editor);
23
23
  editor.update(() => {
@@ -35,15 +35,11 @@ export const resetEditorAfterSend = (editor) => {
35
35
  const listType = isListNode
36
36
  ? topLevelNode.getListType()
37
37
  : undefined;
38
- if (selection.hasFormat("bold")) {
39
- selection.formatText("bold");
40
- }
41
- if (selection.hasFormat("italic")) {
42
- selection.formatText("italic");
43
- }
44
- if (selection.hasFormat("strikethrough")) {
45
- selection.formatText("strikethrough");
46
- }
38
+ // paragraph.select() keeps the previous selection's typing format, so a
39
+ // mark switched on before sending (bold, italic, underline...) would carry
40
+ // into the next message. Drop every mark instead of toggling known ones.
41
+ selection.format = 0;
42
+ selection.style = "";
47
43
  if (isQuoteNode) {
48
44
  // Nếu đang là QuoteNode → chuyển về Paragraph (bình thường)
49
45
  const paragraph = $createParagraphNode();
@@ -4,7 +4,7 @@ import { Spin } from "antd";
4
4
  import { Icon } from "../../../components/icon";
5
5
  import { documentIcon } from "../../../assets/svg";
6
6
  import { renderFileSize, shortenFileName } from "../../../utils/common";
7
- import { downloadFileFromUrl } from "../../../utils/download";
7
+ import { downloadFileFromUrl, openFileOrDownload } from "../../../utils/download";
8
8
  const FileMessageItem = (props) => {
9
9
  var _a;
10
10
  const { message } = props;
@@ -17,7 +17,7 @@ const FileMessageItem = (props) => {
17
17
  const handleView = () => {
18
18
  if (!hasUrl)
19
19
  return;
20
- window.open(sourceUrl, "_blank", "noopener,noreferrer");
20
+ void openFileOrDownload(sourceUrl, fileName);
21
21
  };
22
22
  const handleDownload = () => {
23
23
  downloadFileFromUrl(sourceUrl, fileName);
@@ -186,7 +186,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
186
186
  const isSystemLogMessage = isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType);
187
187
  const isGroupNotificationMessage = isGroupNotificationMessageType(message === null || message === void 0 ? void 0 : message.contentType);
188
188
  const isSessionEvent = isSessionEventMessage(message);
189
- const showsSessionEvents = isCrm || isSessionAgentView;
189
+ const showsSessionEvents = isCrm;
190
190
  const isStickerMessage = (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.StickerMessage;
191
191
  const hasContextMenu = contextMenuItems.length > 0;
192
192
  const isLatestMine = ((_a = allMessages.find((m) => m.sendID === userID)) === null || _a === void 0 ? void 0 : _a.clientMsgID) ===
@@ -265,7 +265,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
265
265
  memberRun ? (_jsx(MemberEventSummary, { messages: memberRun.messages })) : (_jsx(GroupNotificationMessageItem, { message: message }))));
266
266
  }
267
267
  if (isSessionEvent) {
268
- // Owners in consumer apps don't see session dividers; CRM and agents do.
268
+ // Only CRM shows session dividers; consumer apps and PDP agents do not.
269
269
  if (!showsSessionEvents)
270
270
  return hiddenMessageNode;
271
271
  return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Empty, Spin } from "antd";
4
4
  import { useTranslation } from "react-i18next";
5
- import InfiniteScroll from "react-infinite-scroll-component";
5
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
6
6
  import SearchItemAsGroup from "./item/SearchItemAsGroup";
7
7
  import { useSearchGroups } from "../../hooks/search/useSearchGroups";
8
8
  import { useSearchScope } from "./SearchScopeContext";
@@ -3,7 +3,7 @@ import { Empty, Spin } from "antd";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import { useSearchMessage } from "../../hooks/search/useSearchMessage";
5
5
  import { MessageType } from "@droppii-org/wasm-client-sdk";
6
- import InfiniteScroll from "react-infinite-scroll-component";
6
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
7
7
  import SearchItemAsMessage from "./item/SearchItemAsMessage";
8
8
  import { useSearchScope } from "./SearchScopeContext";
9
9
  const SearchConversationAsMessages = (props) => {
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Empty, Spin } from "antd";
3
3
  import { useTranslation } from "react-i18next";
4
- import InfiniteScroll from "react-infinite-scroll-component";
4
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
5
5
  import SearchItemAsUser from "./item/SearchItemAsUser";
6
6
  import { useSearchUsers } from "../../hooks/search/useSearchUsers";
7
7
  import { useSearchScope } from "./SearchScopeContext";
@@ -3,7 +3,7 @@ import { Empty, Spin } from "antd";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import { useSearchMessage } from "../../hooks/search/useSearchMessage";
5
5
  import { MessageType } from "@droppii-org/wasm-client-sdk";
6
- import InfiniteScroll from "react-infinite-scroll-component";
6
+ import InfiniteScroll from "../common/ShadowSafeInfiniteScroll";
7
7
  import SearchItemAsMessage from "./item/SearchItemAsMessage";
8
8
  import useConversationStore from "../../store/conversation";
9
9
  const SearchMessageOnCurrentConversation = (props) => {
@@ -14,9 +14,10 @@ interface SessionFolderListProps {
14
14
  };
15
15
  }
16
16
  /**
17
- * Folders of one scope. The "open" parent has two click targets: the label
18
- * only reveals its children, the chevron collapses them. The API cannot list
19
- * all open sessions at once, so the label never changes the filter.
17
+ * Folders of one scope. In "my messages" the "open" parent has two click
18
+ * targets: the label selects every open session (and reveals the children), the
19
+ * chevron collapses them. A team's parent label only reveals its children: the
20
+ * team query has no "all open" list.
20
21
  */
21
22
  declare const SessionFolderList: ({ summary, teamId, activeFolderId, onFilterSelect, allGroups, }: SessionFolderListProps) => import("react/jsx-runtime").JSX.Element;
22
23
  export default SessionFolderList;
@@ -1 +1 @@
1
- {"version":3,"file":"SessionFolderList.d.ts","sourceRoot":"","sources":["../../../src/components/session/SessionFolderList.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAQ3D,UAAU,sBAAsB;IAC9B,OAAO,EAAE,uBAAuB,CAAC;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,gEAAgE;IAChE,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CACvD;AAED;;;;GAIG;AACH,QAAA,MAAM,iBAAiB,GAAI,iEAMxB,sBAAsB,4CAyFxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"SessionFolderList.d.ts","sourceRoot":"","sources":["../../../src/components/session/SessionFolderList.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAQ3D,UAAU,sBAAsB;IAC9B,OAAO,EAAE,uBAAuB,CAAC;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,gEAAgE;IAChE,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CACvD;AAED;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,GAAI,iEAMxB,sBAAsB,4CAoGxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}