@droppii-org/chat-sdk 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/droppiiFontSelection.json +14521 -14521
- package/dist/assets/sdk/sql-wasm.wasm +0 -0
- package/dist/assets/svg/cannedResponse.tsx +48 -48
- package/dist/assets/svg/document.tsx +37 -37
- package/dist/assets/svg/index.ts +2 -2
- package/dist/components/cannedResponse/CannedResponseBody.d.ts.map +1 -1
- package/dist/components/cannedResponse/CannedResponseBody.js +54 -3
- package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +7 -2
- package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
- package/dist/components/conversation/DeskConversationList.js +22 -17
- package/dist/components/message/MessageHeader.d.ts +2 -2
- package/dist/components/message/MessageHeader.d.ts.map +1 -1
- package/dist/components/message/MessageHeader.js +5 -2
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +31 -22
- package/dist/components/message/SelectSession.d.ts.map +1 -1
- package/dist/components/message/SelectSession.js +7 -9
- package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
- package/dist/components/message/footer/ActionBar.js +3 -2
- package/dist/components/message/footer/CannedResponsePlugin.d.ts.map +1 -1
- package/dist/components/message/footer/CannedResponsePlugin.js +37 -1
- package/dist/components/message/footer/ComposerEditor.d.ts +7 -0
- package/dist/components/message/footer/ComposerEditor.d.ts.map +1 -0
- package/dist/components/message/footer/ComposerEditor.js +13 -0
- package/dist/components/message/footer/ComposerTabs.d.ts +9 -0
- package/dist/components/message/footer/ComposerTabs.d.ts.map +1 -0
- package/dist/components/message/footer/ComposerTabs.js +37 -0
- package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
- package/dist/components/message/footer/EnterHandler.js +10 -1
- package/dist/components/message/footer/index.d.ts +2 -2
- package/dist/components/message/footer/index.d.ts.map +1 -1
- package/dist/components/message/footer/index.js +45 -9
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +11 -1
- package/dist/components/session/DeskAssignedSession.d.ts.map +1 -1
- package/dist/components/session/DeskAssignedSession.js +14 -109
- package/dist/components/session/DeskTeamInbox.d.ts +3 -0
- package/dist/components/session/DeskTeamInbox.d.ts.map +1 -0
- package/dist/components/session/DeskTeamInbox.js +56 -0
- package/dist/components/session/SessionFilterMenu.d.ts +13 -0
- package/dist/components/session/SessionFilterMenu.d.ts.map +1 -0
- package/dist/components/session/SessionFilterMenu.js +27 -0
- package/dist/components/session/sessionMenuItems.d.ts +26 -0
- package/dist/components/session/sessionMenuItems.d.ts.map +1 -0
- package/dist/components/session/sessionMenuItems.js +108 -0
- package/dist/hooks/conversation/useConversationPreview.d.ts +12 -0
- package/dist/hooks/conversation/useConversationPreview.d.ts.map +1 -0
- package/dist/hooks/conversation/useConversationPreview.js +22 -0
- package/dist/hooks/message/useConversationMessages.d.ts +27 -0
- package/dist/hooks/message/useConversationMessages.d.ts.map +1 -0
- package/dist/hooks/message/useConversationMessages.js +29 -0
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/usePullSessionMessages.d.ts +9 -0
- package/dist/hooks/message/usePullSessionMessages.d.ts.map +1 -0
- package/dist/hooks/message/usePullSessionMessages.js +27 -0
- package/dist/hooks/message/useSendMessage.d.ts +8 -6
- package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
- package/dist/hooks/message/useSendMessage.js +8 -8
- package/dist/hooks/session/useConversationSessionState.d.ts +21 -0
- package/dist/hooks/session/useConversationSessionState.d.ts.map +1 -0
- package/dist/hooks/session/useConversationSessionState.js +41 -0
- package/dist/hooks/session/useGetSession.d.ts.map +1 -1
- package/dist/hooks/session/useGetSession.js +138 -52
- package/dist/hooks/session/useGetTeamSessionSummary.d.ts +3 -0
- package/dist/hooks/session/useGetTeamSessionSummary.d.ts.map +1 -0
- package/dist/hooks/session/useGetTeamSessionSummary.js +12 -0
- package/dist/hooks/session/useIsJoinedGroup.d.ts +5 -0
- package/dist/hooks/session/useIsJoinedGroup.d.ts.map +1 -0
- package/dist/hooks/session/useIsJoinedGroup.js +24 -0
- package/dist/hooks/session/useJoinGroupFlow.d.ts +12 -0
- package/dist/hooks/session/useJoinGroupFlow.d.ts.map +1 -0
- package/dist/hooks/session/useJoinGroupFlow.js +59 -0
- package/dist/hooks/session/useJoinSession.d.ts +3 -0
- package/dist/hooks/session/useJoinSession.d.ts.map +1 -0
- package/dist/hooks/session/useJoinSession.js +38 -0
- package/dist/hooks/user/useCurrentUserAccountType.d.ts +3 -0
- package/dist/hooks/user/useCurrentUserAccountType.d.ts.map +1 -0
- package/dist/hooks/user/useCurrentUserAccountType.js +30 -0
- package/dist/locales/i18n.ts +18 -18
- package/dist/locales/vi/common.json +112 -102
- package/dist/screens/chatBubble/index.d.ts +2 -2
- package/dist/screens/chatBubble/index.d.ts.map +1 -1
- package/dist/screens/chatBubble/index.js +13 -7
- package/dist/services/query.d.ts +5 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +5 -0
- package/dist/services/routes.d.ts +5 -0
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +5 -0
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +41 -12
- package/dist/store/session.js +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/chat.d.ts +18 -1
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/chat.js +9 -0
- package/dist/types/dto.d.ts +87 -0
- package/dist/types/dto.d.ts.map +1 -1
- package/dist/utils/events.d.ts +1 -0
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/messageTransform.d.ts +5 -0
- package/dist/utils/messageTransform.d.ts.map +1 -0
- package/dist/utils/messageTransform.js +106 -0
- package/dist/utils/queryHelpers.d.ts.map +1 -1
- package/dist/utils/queryHelpers.js +2 -0
- package/package.json +11 -11
|
File without changes
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
interface ISvgProps {
|
|
2
|
-
size?: number;
|
|
3
|
-
className?: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
const CannedResponseIcon = (props: ISvgProps) => (
|
|
7
|
-
<svg
|
|
8
|
-
width={props.size || 18}
|
|
9
|
-
height={props.size || 18}
|
|
10
|
-
viewBox={`${0} ${0} ${props.size || 18} ${props.size || 18}`}
|
|
11
|
-
fill="none"
|
|
12
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
-
className={props?.className}
|
|
14
|
-
>
|
|
15
|
-
<g clipPath="url(#clip0_4070_70030)">
|
|
16
|
-
<path
|
|
17
|
-
fillRule="evenodd"
|
|
18
|
-
clipRule="evenodd"
|
|
19
|
-
d="M6.66732 0.833374C7.12755 0.833374 7.50065 1.20647 7.50065 1.66671L5.00065 18.3334C5.00065 18.7936 4.62755 19.1667 4.16732 19.1667C3.70708 19.1667 3.33398 18.7936 3.33398 18.3334L5.83398 1.66671C5.83398 1.20647 6.20708 0.833374 6.66732 0.833374Z"
|
|
20
|
-
fill="currentColor"
|
|
21
|
-
/>
|
|
22
|
-
<path
|
|
23
|
-
fillRule="evenodd"
|
|
24
|
-
clipRule="evenodd"
|
|
25
|
-
d="M14.9993 0.833374C15.4596 0.833374 15.8327 1.20647 15.8327 1.66671L13.3327 18.3334C13.3327 18.7936 12.9596 19.1667 12.4993 19.1667C12.0391 19.1667 11.666 18.7936 11.666 18.3334L14.166 1.66671C14.166 1.20647 14.5391 0.833374 14.9993 0.833374Z"
|
|
26
|
-
fill="currentColor"
|
|
27
|
-
/>
|
|
28
|
-
<path
|
|
29
|
-
fillRule="evenodd"
|
|
30
|
-
clipRule="evenodd"
|
|
31
|
-
d="M19.1673 5.83333C19.1673 6.29357 18.7942 6.66667 18.334 6.66667H1.66732C1.20708 6.66667 0.833984 6.29357 0.833984 5.83333C0.833984 5.37309 1.20708 5 1.66732 5H18.334C18.7942 5 19.1673 5.3731 19.1673 5.83333Z"
|
|
32
|
-
fill="currentColor"
|
|
33
|
-
/>
|
|
34
|
-
<path
|
|
35
|
-
fillRule="evenodd"
|
|
36
|
-
clipRule="evenodd"
|
|
37
|
-
d="M19.1673 14.1667C19.1673 14.627 18.7942 15 18.334 15H1.66732C1.20708 15 0.833984 14.627 0.833984 14.1667C0.833984 13.7065 1.20708 13.3334 1.66732 13.3334H18.334C18.7942 13.3334 19.1673 13.7065 19.1673 14.1667Z"
|
|
38
|
-
fill="currentColor"
|
|
39
|
-
/>
|
|
40
|
-
</g>
|
|
41
|
-
<defs>
|
|
42
|
-
<clipPath id="clip0_4070_70030">
|
|
43
|
-
<rect width={props.size || 18} height={props.size || 18} fill="white" />
|
|
44
|
-
</clipPath>
|
|
45
|
-
</defs>
|
|
46
|
-
</svg>
|
|
47
|
-
);
|
|
48
|
-
export default CannedResponseIcon;
|
|
1
|
+
interface ISvgProps {
|
|
2
|
+
size?: number;
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const CannedResponseIcon = (props: ISvgProps) => (
|
|
7
|
+
<svg
|
|
8
|
+
width={props.size || 18}
|
|
9
|
+
height={props.size || 18}
|
|
10
|
+
viewBox={`${0} ${0} ${props.size || 18} ${props.size || 18}`}
|
|
11
|
+
fill="none"
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
className={props?.className}
|
|
14
|
+
>
|
|
15
|
+
<g clipPath="url(#clip0_4070_70030)">
|
|
16
|
+
<path
|
|
17
|
+
fillRule="evenodd"
|
|
18
|
+
clipRule="evenodd"
|
|
19
|
+
d="M6.66732 0.833374C7.12755 0.833374 7.50065 1.20647 7.50065 1.66671L5.00065 18.3334C5.00065 18.7936 4.62755 19.1667 4.16732 19.1667C3.70708 19.1667 3.33398 18.7936 3.33398 18.3334L5.83398 1.66671C5.83398 1.20647 6.20708 0.833374 6.66732 0.833374Z"
|
|
20
|
+
fill="currentColor"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
fillRule="evenodd"
|
|
24
|
+
clipRule="evenodd"
|
|
25
|
+
d="M14.9993 0.833374C15.4596 0.833374 15.8327 1.20647 15.8327 1.66671L13.3327 18.3334C13.3327 18.7936 12.9596 19.1667 12.4993 19.1667C12.0391 19.1667 11.666 18.7936 11.666 18.3334L14.166 1.66671C14.166 1.20647 14.5391 0.833374 14.9993 0.833374Z"
|
|
26
|
+
fill="currentColor"
|
|
27
|
+
/>
|
|
28
|
+
<path
|
|
29
|
+
fillRule="evenodd"
|
|
30
|
+
clipRule="evenodd"
|
|
31
|
+
d="M19.1673 5.83333C19.1673 6.29357 18.7942 6.66667 18.334 6.66667H1.66732C1.20708 6.66667 0.833984 6.29357 0.833984 5.83333C0.833984 5.37309 1.20708 5 1.66732 5H18.334C18.7942 5 19.1673 5.3731 19.1673 5.83333Z"
|
|
32
|
+
fill="currentColor"
|
|
33
|
+
/>
|
|
34
|
+
<path
|
|
35
|
+
fillRule="evenodd"
|
|
36
|
+
clipRule="evenodd"
|
|
37
|
+
d="M19.1673 14.1667C19.1673 14.627 18.7942 15 18.334 15H1.66732C1.20708 15 0.833984 14.627 0.833984 14.1667C0.833984 13.7065 1.20708 13.3334 1.66732 13.3334H18.334C18.7942 13.3334 19.1673 13.7065 19.1673 14.1667Z"
|
|
38
|
+
fill="currentColor"
|
|
39
|
+
/>
|
|
40
|
+
</g>
|
|
41
|
+
<defs>
|
|
42
|
+
<clipPath id="clip0_4070_70030">
|
|
43
|
+
<rect width={props.size || 18} height={props.size || 18} fill="white" />
|
|
44
|
+
</clipPath>
|
|
45
|
+
</defs>
|
|
46
|
+
</svg>
|
|
47
|
+
);
|
|
48
|
+
export default CannedResponseIcon;
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
export const documentIcon = (
|
|
2
|
-
<svg
|
|
3
|
-
width="40"
|
|
4
|
-
height="40"
|
|
5
|
-
viewBox="0 0 40 40"
|
|
6
|
-
fill="none"
|
|
7
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
-
>
|
|
9
|
-
<path
|
|
10
|
-
d="M10.1923 5.83301L23.4363 5.83301L34.1656 14.2054V29.8639C34.1656 31.8997 32.5286 34.1663 29.8068 34.1663C27.0849 34.1663 10.1923 34.1663 10.1923 34.1663C7.4704 34.1663 5.8335 31.8997 5.8335 29.8639V10.0305C5.8335 7.99475 7.4704 5.83301 10.1923 5.83301Z"
|
|
11
|
-
fill="#24B0FF"
|
|
12
|
-
></path>
|
|
13
|
-
<path
|
|
14
|
-
d="M10.8335 28.1394V20.833H16.0309V22.4222H12.7026V23.5916H15.3612V25.1708H12.7026V28.1394H10.8335Z"
|
|
15
|
-
fill="#edf6ff"
|
|
16
|
-
></path>
|
|
17
|
-
<path
|
|
18
|
-
d="M19.0073 28.0885V20.833H20.8613V26.5118H24.0146V28.0885L19.0073 28.0885Z"
|
|
19
|
-
fill="#edf6ff"
|
|
20
|
-
></path>
|
|
21
|
-
<path
|
|
22
|
-
d="M16.5918 28.1001V20.833H18.4485V28.1001H16.5918Z"
|
|
23
|
-
fill="#edf6ff"
|
|
24
|
-
></path>
|
|
25
|
-
<path
|
|
26
|
-
d="M24.5737 20.833V28.1393H29.7723V26.5573H26.439L26.4422 25.1708H29.1017V23.5916H26.4422V22.4222H29.7723V20.833H24.5737Z"
|
|
27
|
-
fill="#edf6ff"
|
|
28
|
-
></path>
|
|
29
|
-
<path
|
|
30
|
-
opacity="0.302"
|
|
31
|
-
fillRule="evenodd"
|
|
32
|
-
clipRule="evenodd"
|
|
33
|
-
d="M23.2686 5.83301V14.2281H34.1655L23.2686 5.83301Z"
|
|
34
|
-
fill="#edf6ff"
|
|
35
|
-
></path>
|
|
36
|
-
</svg>
|
|
37
|
-
);
|
|
1
|
+
export const documentIcon = (
|
|
2
|
+
<svg
|
|
3
|
+
width="40"
|
|
4
|
+
height="40"
|
|
5
|
+
viewBox="0 0 40 40"
|
|
6
|
+
fill="none"
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
>
|
|
9
|
+
<path
|
|
10
|
+
d="M10.1923 5.83301L23.4363 5.83301L34.1656 14.2054V29.8639C34.1656 31.8997 32.5286 34.1663 29.8068 34.1663C27.0849 34.1663 10.1923 34.1663 10.1923 34.1663C7.4704 34.1663 5.8335 31.8997 5.8335 29.8639V10.0305C5.8335 7.99475 7.4704 5.83301 10.1923 5.83301Z"
|
|
11
|
+
fill="#24B0FF"
|
|
12
|
+
></path>
|
|
13
|
+
<path
|
|
14
|
+
d="M10.8335 28.1394V20.833H16.0309V22.4222H12.7026V23.5916H15.3612V25.1708H12.7026V28.1394H10.8335Z"
|
|
15
|
+
fill="#edf6ff"
|
|
16
|
+
></path>
|
|
17
|
+
<path
|
|
18
|
+
d="M19.0073 28.0885V20.833H20.8613V26.5118H24.0146V28.0885L19.0073 28.0885Z"
|
|
19
|
+
fill="#edf6ff"
|
|
20
|
+
></path>
|
|
21
|
+
<path
|
|
22
|
+
d="M16.5918 28.1001V20.833H18.4485V28.1001H16.5918Z"
|
|
23
|
+
fill="#edf6ff"
|
|
24
|
+
></path>
|
|
25
|
+
<path
|
|
26
|
+
d="M24.5737 20.833V28.1393H29.7723V26.5573H26.439L26.4422 25.1708H29.1017V23.5916H26.4422V22.4222H29.7723V20.833H24.5737Z"
|
|
27
|
+
fill="#edf6ff"
|
|
28
|
+
></path>
|
|
29
|
+
<path
|
|
30
|
+
opacity="0.302"
|
|
31
|
+
fillRule="evenodd"
|
|
32
|
+
clipRule="evenodd"
|
|
33
|
+
d="M23.2686 5.83301V14.2281H34.1655L23.2686 5.83301Z"
|
|
34
|
+
fill="#edf6ff"
|
|
35
|
+
></path>
|
|
36
|
+
</svg>
|
|
37
|
+
);
|
package/dist/assets/svg/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./document";
|
|
2
|
-
export * from "./cannedResponse";
|
|
1
|
+
export * from "./document";
|
|
2
|
+
export * from "./cannedResponse";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CannedResponseBody.d.ts","sourceRoot":"","sources":["../../../src/components/cannedResponse/CannedResponseBody.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CannedResponseBody.d.ts","sourceRoot":"","sources":["../../../src/components/cannedResponse/CannedResponseBody.tsx"],"names":[],"mappings":"AAiBA,UAAU,wBAAwB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD,QAAA,MAAM,kBAAkB,GAAI,OAAO,wBAAwB,4CA8M1D,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Empty, Segmented, Spin } from "antd";
|
|
3
3
|
import { useFetchMyTeams } from "../../hooks/team/useFetchMyTeam";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { CannedResponseVisibleScope } from "../../types/chat";
|
|
7
7
|
import TeamItem from "./team/TeamItem";
|
|
8
8
|
import { useFetchCannedResponse } from "../../hooks/cannedResponse/useFetchCannedResponse";
|
|
@@ -10,9 +10,24 @@ import InfiniteScroll from "react-infinite-scroll-component";
|
|
|
10
10
|
import { Icon } from "../icon";
|
|
11
11
|
import { sanitizeHtml } from "../../utils/common";
|
|
12
12
|
import { useDebounce } from "ahooks";
|
|
13
|
+
import clsx from "clsx";
|
|
14
|
+
import emitter from "../../utils/events";
|
|
15
|
+
import { isArray } from "lodash";
|
|
16
|
+
import { useMessageFooterContext } from "../message/footer";
|
|
17
|
+
const parseIndex = (index, length) => {
|
|
18
|
+
if (index === null)
|
|
19
|
+
return null;
|
|
20
|
+
if (index < 0)
|
|
21
|
+
return 0;
|
|
22
|
+
if (index >= length)
|
|
23
|
+
return length - 1;
|
|
24
|
+
return index;
|
|
25
|
+
};
|
|
13
26
|
const CannedResponseBody = (props) => {
|
|
14
27
|
var _a, _b;
|
|
15
28
|
const { search, onSelectCannedResponse, cannedQuery } = props;
|
|
29
|
+
const { activeCannedIndex, setActiveCannedIndex, setMaxActiveCannedIndex } = useMessageFooterContext();
|
|
30
|
+
const itemRefs = useRef([]);
|
|
16
31
|
const { t } = useTranslation();
|
|
17
32
|
const { data: myTeams, isLoading: isLoadingTeams } = useFetchMyTeams();
|
|
18
33
|
const [scope, setScope] = useState(CannedResponseVisibleScope.TEAM);
|
|
@@ -25,6 +40,9 @@ const CannedResponseBody = (props) => {
|
|
|
25
40
|
categoryId: selectedCategoryId,
|
|
26
41
|
shortcut: search || cannedQueryDebounced || "",
|
|
27
42
|
});
|
|
43
|
+
const validActiveCannedIndex = useMemo(() => {
|
|
44
|
+
return parseIndex(activeCannedIndex, (cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length) || 0);
|
|
45
|
+
}, [activeCannedIndex, cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length]);
|
|
28
46
|
const options = useMemo(() => {
|
|
29
47
|
return [
|
|
30
48
|
{ label: t("team"), value: CannedResponseVisibleScope.TEAM },
|
|
@@ -43,12 +61,45 @@ const CannedResponseBody = (props) => {
|
|
|
43
61
|
setSelectedTeamId(myTeams[0].teamId);
|
|
44
62
|
}
|
|
45
63
|
}, [isLoadingTeams, myTeams]);
|
|
46
|
-
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const handler = (index) => {
|
|
66
|
+
var _a;
|
|
67
|
+
const validIndex = parseIndex(index, cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length);
|
|
68
|
+
if (validIndex !== null && !!(cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses[validIndex])) {
|
|
69
|
+
const htmlContent = ((_a = cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses[validIndex]) === null || _a === void 0 ? void 0 : _a.content) || "";
|
|
70
|
+
// 🔒 Sanitize HTML to prevent XSS attacks
|
|
71
|
+
const sanitizedContent = sanitizeHtml(htmlContent);
|
|
72
|
+
onSelectCannedResponse === null || onSelectCannedResponse === void 0 ? void 0 : onSelectCannedResponse(sanitizedContent);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
emitter.on("CANNED_RESPONSE_SELECT", handler);
|
|
76
|
+
return () => {
|
|
77
|
+
emitter.off("CANNED_RESPONSE_SELECT", handler);
|
|
78
|
+
};
|
|
79
|
+
}, [cannedResponses, onSelectCannedResponse]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
setActiveCannedIndex(0);
|
|
82
|
+
}, [search, cannedQueryDebounced, setActiveCannedIndex]);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
if (activeCannedIndex !== null) {
|
|
86
|
+
(_b = (_a = itemRefs.current) === null || _a === void 0 ? void 0 : _a[activeCannedIndex]) === null || _b === void 0 ? void 0 : _b.scrollIntoView({
|
|
87
|
+
block: "nearest",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}, [activeCannedIndex]);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
setMaxActiveCannedIndex((cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length) - 1 > 0 ? (cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length) - 1 : 0);
|
|
93
|
+
}, [cannedResponses, setMaxActiveCannedIndex]);
|
|
94
|
+
return (_jsxs("div", { className: "flex flex-1 flex-row h-[400px]", children: [_jsxs("div", { className: "w-[170px] p-2 border-r border-gray-200", children: [_jsx(Segmented, { options: options, block: true, size: "small", value: scope, onChange: setScope }), _jsx("div", { className: "overflow-y-auto h-full", children: scope === CannedResponseVisibleScope.TEAM && (_jsx("div", { className: "mt-1 flex flex-col", children: (_a = myTeams === null || myTeams === void 0 ? void 0 : myTeams.map) === null || _a === void 0 ? void 0 : _a.call(myTeams, (team, index) => renderTeamItem(team, index)) })) })] }), _jsxs("div", { id: "scrollableCannedDiv", className: "flex flex-col flex-1 h-full overflow-y-auto", children: [!!cannedQuery && !search && (_jsx("div", { className: "px-3 py-2 border-b border-gray-200", children: _jsxs("span", { className: "text-sm text-gray-500", children: [t("canned_response_quick_search_placeholder"), _jsx("span", { className: "text-blue-600", children: ` #${cannedQuery}` })] }) })), _jsx(InfiniteScroll, { dataLength: (cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length) || 0, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableCannedDiv", children: !isArray(cannedResponses) || (cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.length) === 0 ? (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Empty, { image: _jsx(Icon, { icon: "chat-square-b", size: 80, className: "text-gray-300" }), description: t("no_canned_response") }) })) : ((_b = cannedResponses === null || cannedResponses === void 0 ? void 0 : cannedResponses.map) === null || _b === void 0 ? void 0 : _b.call(cannedResponses, (canned, index) => {
|
|
47
95
|
var _a, _b;
|
|
96
|
+
const isActive = index === validActiveCannedIndex;
|
|
48
97
|
const htmlContent = (canned === null || canned === void 0 ? void 0 : canned.content) || "";
|
|
49
98
|
// 🔒 Sanitize HTML to prevent XSS attacks
|
|
50
99
|
const sanitizedContent = sanitizeHtml(htmlContent);
|
|
51
|
-
return (_jsxs("div", {
|
|
100
|
+
return (_jsxs("div", { ref: (el) => {
|
|
101
|
+
itemRefs.current[index] = el;
|
|
102
|
+
}, className: clsx("flex flex-col flex-1 px-3 py-2 cursor-pointer hover:bg-blue-100 w-full border-b border-gray-200", isActive && "bg-blue-100"), onClick: () => onSelectCannedResponse === null || onSelectCannedResponse === void 0 ? void 0 : onSelectCannedResponse(sanitizedContent), children: [_jsxs("span", { className: "text-xs truncate text-gray-500", children: [`${((_a = canned === null || canned === void 0 ? void 0 : canned.category) === null || _a === void 0 ? void 0 : _a.name)
|
|
52
103
|
? `${(_b = canned === null || canned === void 0 ? void 0 : canned.category) === null || _b === void 0 ? void 0 : _b.name} / `
|
|
53
104
|
: ""}`, _jsx("span", { className: "text-black", children: `${(canned === null || canned === void 0 ? void 0 : canned.name) || ""} ` }), _jsx("span", { children: "/" }), _jsx("span", { className: "text-blue-500", children: ` #${(canned === null || canned === void 0 ? void 0 : canned.shortcut) || ""}` })] }), _jsx("div", { dangerouslySetInnerHTML: {
|
|
54
105
|
__html: sanitizedContent,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationBySessionItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationBySessionItem.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationBySessionItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ConversationBySessionItem.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AASpD,UAAU,8BAA8B;IACtC,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,QAAA,MAAM,yBAAyB,GAAI,kBAEhC,8BAA8B,mDAgGhC,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
|
|
@@ -6,6 +6,7 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
|
6
6
|
import { Avatar, Badge } from "antd";
|
|
7
7
|
import { useChatContext } from "../../context/ChatContext";
|
|
8
8
|
import { useConversationDisplayData } from "../../hooks/conversation/useConversation";
|
|
9
|
+
import { useConversationPreview } from "../../hooks/conversation/useConversationPreview";
|
|
9
10
|
import { formatTimestamp, parseLatestMessage } from "../../utils/common";
|
|
10
11
|
const ConversationBySessionItem = ({ sessionItem, }) => {
|
|
11
12
|
var _a;
|
|
@@ -30,10 +31,14 @@ const ConversationBySessionItem = ({ sessionItem, }) => {
|
|
|
30
31
|
setSelectedConversationId(conversation.conversationID);
|
|
31
32
|
};
|
|
32
33
|
const { avatar, displayName = "" } = useConversationDisplayData(conversation || null);
|
|
34
|
+
const { latestMsg, latestMsgSendTime } = useConversationPreview({
|
|
35
|
+
conversation,
|
|
36
|
+
ownerUserID: sessionItem.ownerId,
|
|
37
|
+
});
|
|
33
38
|
if (!conversation)
|
|
34
39
|
return null;
|
|
35
|
-
return (_jsxs("div", { onClick: () => handleConversationClick(conversation), className: `relative p-3 border-b border-gray-100 hover:bg-gray-100 cursor-pointer transition-colors ${isSelected ? "bg-blue-50" : "bg-white"}`, children: [isSelected && (_jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1 bg-blue-500" })), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "relative flex-shrink-0", children: _jsx(Badge, { dot: true, status: "success", offset: [-2, 36], children: _jsx(Avatar, { size: 48, src: avatar, children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" }) }) }), _jsx("div", { className: "flex-1 min-w-0", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-gray-900 text-sm truncate", children: displayName }), _jsx("p", { className: "text-xs text-gray-500 truncate mt-0.5", children: parseLatestMessage(
|
|
40
|
+
return (_jsxs("div", { onClick: () => handleConversationClick(conversation), className: `relative p-3 border-b border-gray-100 hover:bg-gray-100 cursor-pointer transition-colors ${isSelected ? "bg-blue-50" : "bg-white"}`, children: [isSelected && (_jsx("div", { className: "absolute left-0 top-0 bottom-0 w-1 bg-blue-500" })), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("div", { className: "relative flex-shrink-0", children: _jsx(Badge, { dot: true, status: "success", offset: [-2, 36], children: _jsx(Avatar, { size: 48, src: avatar, children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" }) }) }), _jsx("div", { className: "flex-1 min-w-0", children: _jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "font-semibold text-gray-900 text-sm truncate", children: displayName }), _jsx("p", { className: "text-xs text-gray-500 truncate mt-0.5", children: parseLatestMessage(latestMsg, user === null || user === void 0 ? void 0 : user.userID, t) })] }), _jsxs("div", { className: "flex flex-col items-end gap-1 ml-2", children: [latestMsgSendTime > 0 && (_jsx("span", { className: "text-xs text-gray-400", children: formatTimestamp(latestMsgSendTime, {
|
|
36
41
|
hasTime: true,
|
|
37
|
-
}) }), _jsx("div", { className: "flex items-center gap-1", children: conversation.unreadCount > 0 && (_jsx(Badge, { count: conversation.unreadCount })) })] })] }) })] })] }, conversation.conversationID));
|
|
42
|
+
}) })), _jsx("div", { className: "flex items-center gap-1", children: conversation.unreadCount > 0 && (_jsx(Badge, { count: conversation.unreadCount })) })] })] }) })] })] }, conversation.conversationID));
|
|
38
43
|
};
|
|
39
44
|
export default ConversationBySessionItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DeskConversationList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/DeskConversationList.tsx"],"names":[],"mappings":"AAoBA,QAAA,MAAM,oBAAoB,+CAoMzB,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -12,10 +12,12 @@ import useSessionStore from "../../store/session";
|
|
|
12
12
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
13
13
|
import ConversationBySessionItem from "./ConversationBySessionItem";
|
|
14
14
|
import { useGetSession } from "../../hooks/session/useGetSession";
|
|
15
|
+
import { useGetTeamSessionSummary } from "../../hooks/session/useGetTeamSessionSummary";
|
|
15
16
|
import { DChatSDK } from "../../constants/sdk";
|
|
16
17
|
import emitter from "../../utils/events";
|
|
18
|
+
import { getFilterConfig } from "../session/sessionMenuItems";
|
|
17
19
|
const DeskConversationList = () => {
|
|
18
|
-
var _a;
|
|
20
|
+
var _a, _b;
|
|
19
21
|
const searchInputRef = useRef(null);
|
|
20
22
|
const { t } = useTranslation();
|
|
21
23
|
const [search, setSearch] = useState("");
|
|
@@ -26,9 +28,13 @@ const DeskConversationList = () => {
|
|
|
26
28
|
const conversationList = useConversationStore((state) => state.conversationList);
|
|
27
29
|
const updateConversationList = useConversationStore((state) => state.updateConversationList);
|
|
28
30
|
const filterSummary = useSessionStore((state) => state.filterSummary);
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const { data: teamSummaries } = useGetTeamSessionSummary();
|
|
32
|
+
const { dataFlatten: sessions, hasNextPage, fetchNextPage, refetch } = useGetSession({ filter: filterSummary });
|
|
33
|
+
const currentFilterKey = filterSummary.status || filterSummary.tag || "";
|
|
34
|
+
const filterConfig = getFilterConfig(currentFilterKey);
|
|
35
|
+
const pathName = filterSummary.teamId
|
|
36
|
+
? ((_a = teamSummaries === null || teamSummaries === void 0 ? void 0 : teamSummaries.find((team) => team.teamId === filterSummary.teamId)) === null || _a === void 0 ? void 0 : _a.teamName) || ""
|
|
37
|
+
: t("my_messages");
|
|
32
38
|
const debouncedSearch = useDebounce(search, { wait: 500 });
|
|
33
39
|
const onCloseSearch = () => {
|
|
34
40
|
setSearch("");
|
|
@@ -65,28 +71,27 @@ const DeskConversationList = () => {
|
|
|
65
71
|
}
|
|
66
72
|
}, [searchParams, conversationList]);
|
|
67
73
|
useEffect(() => {
|
|
68
|
-
|
|
74
|
+
const handler = (sessionUpdated) => {
|
|
69
75
|
if (sessionUpdated.status !== filterSummary.status ||
|
|
70
76
|
sessionUpdated.tag !== filterSummary.tag) {
|
|
71
77
|
refetch();
|
|
72
78
|
}
|
|
73
|
-
}
|
|
79
|
+
};
|
|
80
|
+
emitter.on("UPDATE_SESSION", handler);
|
|
74
81
|
return () => {
|
|
75
|
-
emitter.off("UPDATE_SESSION",
|
|
76
|
-
refetch();
|
|
77
|
-
});
|
|
82
|
+
emitter.off("UPDATE_SESSION", handler);
|
|
78
83
|
};
|
|
79
|
-
}, [filterSummary]);
|
|
80
|
-
return (_jsxs("div", { className:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
}, [filterSummary, refetch]);
|
|
85
|
+
return (_jsxs("div", { className: "flex flex-col h-full bg-white border-r border-gray-200 w-[320px]", children: [_jsxs("div", { className: "p-3 border-b border-gray-100", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { ref: searchInputRef, placeholder: t("search"), prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), onChange: (e) => {
|
|
86
|
+
if (!showSearch && e.target.value) {
|
|
87
|
+
setShowSearchTrue();
|
|
88
|
+
}
|
|
89
|
+
setSearch(e.target.value);
|
|
90
|
+
}, className: "rounded-lg text-sm flex-1 h-[36px]", size: "large", allowClear: true, onClick: setShowSearchTrue, value: search, autoFocus: false, onClear: onCloseSearch }), showSearch && (_jsx(Button, { onClick: onCloseSearch, variant: "outlined", className: "p-0 w-[36px] h-[36px] text-gray-500", children: _jsx(Icon, { icon: "close-b", size: 22 }) }))] }), _jsxs("div", { className: "flex items-center justify-between mt-2", children: [_jsx("span", { className: "text-sm font-semibold text-blue-500 truncate", children: pathName }), filterConfig && (_jsxs("span", { className: "flex items-center gap-1.5 shrink-0", children: [_jsx(Icon, { icon: filterConfig.iconName, size: 16, className: "text-gray-500" }), _jsx("span", { className: "text-sm font-semibold text-gray-800", children: t(filterConfig.labelKey) })] }))] })] }), _jsxs("div", { id: "scrollableConversationsDiv", style: {
|
|
86
91
|
height: "100%",
|
|
87
92
|
overflow: showSearch ? "hidden" : "auto",
|
|
88
93
|
position: "relative",
|
|
89
|
-
}, children: [_jsx(InfiniteScroll, { dataLength: (sessions === null || sessions === void 0 ? void 0 : sessions.length) || 0, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableConversationsDiv", children: (sessions === null || sessions === void 0 ? void 0 : sessions.length) === 0 ? (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Empty, { image: _jsx(Icon, { icon: "chat-square-b", size: 80, className: "text-gray-300" }), description: t("no_conversation") }) })) : ((
|
|
94
|
+
}, children: [_jsx(InfiniteScroll, { dataLength: (sessions === null || sessions === void 0 ? void 0 : sessions.length) || 0, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableConversationsDiv", children: (sessions === null || sessions === void 0 ? void 0 : sessions.length) === 0 ? (_jsx("div", { className: "flex items-center justify-center py-12", children: _jsx(Empty, { image: _jsx(Icon, { icon: "chat-square-b", size: 80, className: "text-gray-300" }), description: t("no_conversation") }) })) : ((_b = sessions === null || sessions === void 0 ? void 0 : sessions.map) === null || _b === void 0 ? void 0 : _b.call(sessions, (session) => (_jsx(ConversationBySessionItem, { sessionItem: session }, session.conversationId)))) }), _jsx(Drawer, { open: showSearch, mask: false, closeIcon: false, styles: {
|
|
90
95
|
body: {
|
|
91
96
|
padding: 0,
|
|
92
97
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SessionStatus, SessionTag } from "../../types/chat";
|
|
2
|
-
import {
|
|
2
|
+
import { ISessionResponse } from "../../types/dto";
|
|
3
3
|
interface MessageHeaderProps {
|
|
4
4
|
onClose?: () => void;
|
|
5
|
-
currentSession?:
|
|
5
|
+
currentSession?: ISessionResponse;
|
|
6
6
|
}
|
|
7
7
|
type SelectSessionValueType = SessionStatus | SessionTag;
|
|
8
8
|
export interface SelectSessionOption {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageHeader.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"MessageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageHeader.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAKnD,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,gBAAgB,CAAC;CACnC;AAED,KAAK,sBAAsB,GAAG,aAAa,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,sBAAsB,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,QAAA,MAAM,aAAa,GAAI,6BAA6B,kBAAkB,4CAoMrE,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -12,13 +12,16 @@ import SelectSession from "./SelectSession";
|
|
|
12
12
|
import { useUpdateSession } from "../../hooks/session/useUpdateSession";
|
|
13
13
|
import useAuthStore from "../../store/auth";
|
|
14
14
|
import SearchDrawer from "../searchConversation/SearchDrawer";
|
|
15
|
+
import { isGroupSession } from "../../utils/imCommon";
|
|
15
16
|
const MessageHeader = ({ onClose, currentSession }) => {
|
|
16
|
-
var _a;
|
|
17
|
+
var _a, _b;
|
|
17
18
|
const { t } = useTranslation();
|
|
18
19
|
const isCx = useAuthStore((state) => state.isCx);
|
|
19
20
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
21
|
+
const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
|
|
20
22
|
const { mutate: updateSession } = useUpdateSession();
|
|
21
23
|
const { avatar, displayName } = useConversationDisplayData(conversationData);
|
|
24
|
+
const shouldShowMemberCount = isGroupSession(conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType);
|
|
22
25
|
const [currentSessionStatus, setCurrentSessionStatus] = useState(SessionStatus.UNASSIGNED);
|
|
23
26
|
const [currentSessionTag, setCurrentSessionTag] = useState(SessionTag.NONE);
|
|
24
27
|
const statusOptions = useMemo(() => {
|
|
@@ -122,6 +125,6 @@ const MessageHeader = ({ onClose, currentSession }) => {
|
|
|
122
125
|
setCurrentSessionStatus(currentSession.status);
|
|
123
126
|
}
|
|
124
127
|
}, [currentSession]);
|
|
125
|
-
return (_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3 bg-white flex-wrap", children: [_jsx(Avatar, { src: avatar, size: "large", className: "min-w-10 min-h-10", children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" }), _jsxs("div", { className: "flex flex-col overflow-hidden flex-1", children: [_jsx("p", { className: "text-base truncate", children: displayName || "" }), _jsx("p", { className: "text-xs text-gray-500 truncate", children: t("member_count", { count:
|
|
128
|
+
return (_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3 bg-white flex-wrap", children: [_jsx(Avatar, { src: avatar, size: "large", className: "min-w-10 min-h-10", children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" }), _jsxs("div", { className: "flex flex-col overflow-hidden flex-1", children: [_jsx("p", { className: "text-base truncate", children: displayName || "" }), shouldShowMemberCount && (_jsx("p", { className: "text-xs text-gray-500 truncate", children: t("member_count", { count: (_b = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.memberCount) !== null && _b !== void 0 ? _b : 0 }) }))] }), _jsxs("div", { className: "flex items-center gap-2 justify-end overflow-hidden", children: [isCx && (_jsx(SelectSession, { placeholder: t("select_tag"), options: tagOptions, value: currentSessionTag, onChange: (value) => handleUpdateSession(value, "tag", value === currentSessionTag), excludeOptions: [SessionTag.SLOW_PROCESSING, SessionTag.NONE] })), isCx && (_jsx(SelectSession, { placeholder: t("select_status"), options: statusOptions, value: currentSessionStatus, onChange: (value) => handleUpdateSession(value, "status", value === currentSessionStatus) })), _jsx(SearchDrawer, {}), _jsx(MediaCollection, {}), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", children: _jsx(Icon, { icon: "align-justify-o", size: 22 }) }), !!onClose && (_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onClose, children: _jsx(Icon, { icon: "close-b", size: 22 }) }))] })] }));
|
|
126
129
|
};
|
|
127
130
|
export default MessageHeader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AA0BA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAGD,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CA4U3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { Empty, Modal, Spin } from "antd";
|
|
5
|
-
import { useCallback, useEffect,
|
|
3
|
+
import { useConversationMessages } from "../../hooks/message/useConversationMessages";
|
|
4
|
+
import { Button, Empty, Modal, Spin } from "antd";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
6
|
import dayjs from "dayjs";
|
|
7
7
|
import isToday from "dayjs/plugin/isToday";
|
|
8
8
|
import emitter from "../../utils/events";
|
|
@@ -18,8 +18,9 @@ import { useBoolean, useDebounceFn } from "ahooks";
|
|
|
18
18
|
import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../constants";
|
|
19
19
|
import { markConversationMessageAsRead } from "../../hooks/conversation/useConversation";
|
|
20
20
|
import { useChatContext } from "../../context/ChatContext";
|
|
21
|
-
import { useGetSession } from "../../hooks/session/useGetSession";
|
|
22
21
|
import { useRevokeMessage } from "../../hooks/message/useRevokeMessage";
|
|
22
|
+
import { useConversationSessionState } from "../../hooks/session/useConversationSessionState";
|
|
23
|
+
import { useJoinGroupFlow } from "../../hooks/session/useJoinGroupFlow";
|
|
23
24
|
dayjs.extend(isToday);
|
|
24
25
|
const BOTTOM_THRESHOLD = -5;
|
|
25
26
|
const MessageList = (props) => {
|
|
@@ -28,19 +29,31 @@ const MessageList = (props) => {
|
|
|
28
29
|
const { user } = useChatContext();
|
|
29
30
|
const { onClose, conversationId, searchClientMsgID, openCreateCannedModal } = props;
|
|
30
31
|
const scrollRef = useRef(null);
|
|
31
|
-
const { getMoreOldMessages, moreOldLoading, loadState, getMoreNewMessages, moreNewLoading, latestLoadState, } = useMessage(conversationId, searchClientMsgID);
|
|
32
32
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
33
33
|
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
34
34
|
const setSearchClientMsgID = useConversationStore((state) => state.setSearchClientMsgID);
|
|
35
|
-
const { dataFlatten: sessions, refetch: refetchSession } = useGetSession({
|
|
36
|
-
filter: {
|
|
37
|
-
conversationIds: !!conversationId ? [conversationId] : [],
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
35
|
const [openMenuId, setOpenMenuId] = useState(null);
|
|
41
36
|
const [selectedItem, setSelectedItem] = useState(null);
|
|
42
37
|
const [showConfirmRevoke, { setTrue: openConfirmRevoke, setFalse: closeConfirmRevoke },] = useBoolean(false);
|
|
43
38
|
const { revokeMessage, loading: isRevoking } = useRevokeMessage();
|
|
39
|
+
const { isNotGroupMember, latestConversationSession, customerUserID, refetchConversationSessions, refetchIsJoined, } = useConversationSessionState({
|
|
40
|
+
conversationId,
|
|
41
|
+
conversationType: conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType,
|
|
42
|
+
groupId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID,
|
|
43
|
+
userID: user === null || user === void 0 ? void 0 : user.userID,
|
|
44
|
+
});
|
|
45
|
+
const { getMoreOldMessages, moreOldLoading, loadState, getMoreNewMessages, moreNewLoading, latestLoadState, } = useConversationMessages({
|
|
46
|
+
conversationId,
|
|
47
|
+
searchClientMsgID,
|
|
48
|
+
restrictToLastSession: isNotGroupMember,
|
|
49
|
+
customerUserID,
|
|
50
|
+
});
|
|
51
|
+
const { handleJoinGroup, isJoining } = useJoinGroupFlow({
|
|
52
|
+
groupId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID,
|
|
53
|
+
latestConversationSessionId: latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.id,
|
|
54
|
+
refetchConversationSessions,
|
|
55
|
+
refetchIsJoined,
|
|
56
|
+
});
|
|
44
57
|
const handleOpenRevoke = useCallback((clientMsgID) => {
|
|
45
58
|
setSelectedItem(clientMsgID);
|
|
46
59
|
openConfirmRevoke();
|
|
@@ -58,9 +71,6 @@ const MessageList = (props) => {
|
|
|
58
71
|
revokeMessage,
|
|
59
72
|
handleCloseRevoke,
|
|
60
73
|
]);
|
|
61
|
-
const currentSession = useMemo(() => {
|
|
62
|
-
return sessions === null || sessions === void 0 ? void 0 : sessions.find((session) => session.conversationId === conversationId);
|
|
63
|
-
}, [sessions, conversationId]);
|
|
64
74
|
const handleMarkConversationMessageAsRead = () => {
|
|
65
75
|
var _a, _b, _c, _d, _e;
|
|
66
76
|
const lastMessage = (_b = (_a = latestLoadState === null || latestLoadState === void 0 ? void 0 : latestLoadState.current) === null || _a === void 0 ? void 0 : _a.messageList) === null || _b === void 0 ? void 0 : _b[0];
|
|
@@ -136,17 +146,16 @@ const MessageList = (props) => {
|
|
|
136
146
|
};
|
|
137
147
|
}, []);
|
|
138
148
|
useEffect(() => {
|
|
139
|
-
|
|
149
|
+
const handler = (sessionUpdated) => {
|
|
140
150
|
if (sessionUpdated.conversationId === conversationId) {
|
|
141
|
-
|
|
151
|
+
refetchConversationSessions();
|
|
142
152
|
}
|
|
143
|
-
}
|
|
153
|
+
};
|
|
154
|
+
emitter.on("UPDATE_SESSION", handler);
|
|
144
155
|
return () => {
|
|
145
|
-
emitter.off("UPDATE_SESSION",
|
|
146
|
-
refetchSession();
|
|
147
|
-
});
|
|
156
|
+
emitter.off("UPDATE_SESSION", handler);
|
|
148
157
|
};
|
|
149
|
-
}, [conversationId]);
|
|
158
|
+
}, [conversationId, refetchConversationSessions]);
|
|
150
159
|
useEffect(() => {
|
|
151
160
|
if (!loadState.hasMoreNew && !loadState.initLoading) {
|
|
152
161
|
handleMarkConversationMessageAsRead();
|
|
@@ -174,7 +183,7 @@ const MessageList = (props) => {
|
|
|
174
183
|
backgroundSize: "cover",
|
|
175
184
|
backgroundPosition: "center",
|
|
176
185
|
overflowX: "hidden",
|
|
177
|
-
}, children: [_jsx(MessageHeader, { onClose: onClose, currentSession:
|
|
186
|
+
}, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession }), _jsx("div", { id: "scrollableMessagesDiv", ref: scrollRef, style: {
|
|
178
187
|
height: "100%",
|
|
179
188
|
overflowY: "auto",
|
|
180
189
|
overflowX: "hidden",
|
|
@@ -192,6 +201,6 @@ const MessageList = (props) => {
|
|
|
192
201
|
handleMarkConversationMessageAsRead();
|
|
193
202
|
loadMoreNewMessage();
|
|
194
203
|
}
|
|
195
|
-
}, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage }, message.clientMsgID))) }) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), _jsx(MessageFooter, { currentSession:
|
|
204
|
+
}, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage }, message.clientMsgID))) }) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), isNotGroupMember ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: handleJoinGroup, loading: isJoining, children: t("join_group") })] })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(Modal, { centered: true, open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, getContainer: false, forceRender: true, children: _jsx("p", { children: t("revoke_message_confirm_message") }) })] }));
|
|
196
205
|
};
|
|
197
206
|
export default MessageList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectSession.d.ts","sourceRoot":"","sources":["../../../src/components/message/SelectSession.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SelectSession.d.ts","sourceRoot":"","sources":["../../../src/components/message/SelectSession.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,UAAU,kBAAkB;IAC1B,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACxD,cAAc,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,QAAA,MAAM,aAAa,GAAI,4DAMpB,kBAAkB,4CAwDpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|