@droppii-org/chat-sdk 0.1.97 → 0.2.1
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/images/muteNotificationWarning.png +0 -0
- package/dist/components/compose/ComposeNewMessageModal.d.ts.map +1 -1
- package/dist/components/compose/ComposeNewMessageModal.js +1 -1
- package/dist/components/conversation/SwipeActionButton.d.ts +11 -0
- package/dist/components/conversation/SwipeActionButton.d.ts.map +1 -0
- package/dist/components/conversation/SwipeActionButton.js +7 -0
- package/dist/components/conversation/SwipeableRow.d.ts +10 -0
- package/dist/components/conversation/SwipeableRow.d.ts.map +1 -0
- package/dist/components/conversation/SwipeableRow.js +62 -0
- package/dist/components/conversation/ThreadCard.d.ts +2 -1
- package/dist/components/conversation/ThreadCard.d.ts.map +1 -1
- package/dist/components/conversation/ThreadCard.js +2 -2
- package/dist/components/conversation-inbox/ConversationInboxItem.d.ts.map +1 -1
- package/dist/components/conversation-inbox/ConversationInboxItem.js +14 -1
- package/dist/components/conversation-inbox/ConversationMuteSwipeAction.d.ts +8 -0
- package/dist/components/conversation-inbox/ConversationMuteSwipeAction.d.ts.map +1 -0
- package/dist/components/conversation-inbox/ConversationMuteSwipeAction.js +31 -0
- package/dist/components/conversation-inbox/MuteConversationConfirmModal.d.ts +9 -0
- package/dist/components/conversation-inbox/MuteConversationConfirmModal.d.ts.map +1 -0
- package/dist/components/conversation-inbox/MuteConversationConfirmModal.js +13 -0
- package/dist/components/conversation-inbox/index.d.ts +4 -0
- package/dist/components/conversation-inbox/index.d.ts.map +1 -1
- package/dist/components/conversation-inbox/index.js +2 -0
- package/dist/components/group/AddMemberModal.d.ts +9 -0
- package/dist/components/group/AddMemberModal.d.ts.map +1 -0
- package/dist/components/group/AddMemberModal.js +70 -0
- package/dist/components/group/AdminPermissionModal.d.ts +9 -0
- package/dist/components/group/AdminPermissionModal.d.ts.map +1 -0
- package/dist/components/group/AdminPermissionModal.js +63 -0
- package/dist/components/group/CreateGroupForm.d.ts +1 -2
- package/dist/components/group/CreateGroupForm.d.ts.map +1 -1
- package/dist/components/group/CreateGroupForm.js +4 -4
- package/dist/components/group/GroupMemberPicker.d.ts.map +1 -1
- package/dist/components/group/GroupMemberPicker.js +16 -8
- package/dist/components/group/MemberPermissionPanel.d.ts +8 -0
- package/dist/components/group/MemberPermissionPanel.d.ts.map +1 -0
- package/dist/components/group/MemberPermissionPanel.js +53 -0
- package/dist/components/media-resources/FileResourceList.js +1 -1
- package/dist/components/media-resources/LinkResourceItem.js +1 -1
- package/dist/components/message/GroupMembersDrawer.d.ts.map +1 -1
- package/dist/components/message/GroupMembersDrawer.js +210 -28
- package/dist/components/message/MessageHeader.d.ts +2 -1
- package/dist/components/message/MessageHeader.d.ts.map +1 -1
- package/dist/components/message/MessageHeader.js +7 -2
- package/dist/components/message/MessageList.d.ts +1 -0
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +7 -2
- package/dist/components/message/SelectSession.d.ts.map +1 -1
- package/dist/components/message/SelectSession.js +3 -3
- package/dist/components/session/DeskTeamInbox.js +1 -1
- package/dist/components/thread/GroupThreadInfo.d.ts +11 -0
- package/dist/components/thread/GroupThreadInfo.d.ts.map +1 -0
- package/dist/components/thread/GroupThreadInfo.js +156 -0
- package/dist/components/thread/ManualAssignPopover.js +2 -2
- package/dist/components/thread/SessionSection.d.ts.map +1 -1
- package/dist/components/thread/SessionSection.js +2 -8
- package/dist/components/thread/SingleThreadInfo.d.ts +6 -0
- package/dist/components/thread/SingleThreadInfo.d.ts.map +1 -0
- package/dist/components/thread/SingleThreadInfo.js +70 -0
- package/dist/components/thread/ThreadInfo.d.ts +7 -1
- package/dist/components/thread/ThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/ThreadInfo.js +14 -2
- package/dist/constants/images.d.ts +1 -0
- package/dist/constants/images.d.ts.map +1 -1
- package/dist/constants/images.js +2 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +3 -0
- package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
- package/dist/hooks/global/useGlobalEvent.js +27 -0
- package/dist/hooks/group/useAddGroupMember.d.ts +7 -0
- package/dist/hooks/group/useAddGroupMember.d.ts.map +1 -0
- package/dist/hooks/group/useAddGroupMember.js +20 -0
- package/dist/hooks/group/useDismissGroup.d.ts +4 -0
- package/dist/hooks/group/useDismissGroup.d.ts.map +1 -0
- package/dist/hooks/group/useDismissGroup.js +22 -0
- package/dist/hooks/group/useEligibleAccounts.d.ts +3 -0
- package/dist/hooks/group/useEligibleAccounts.d.ts.map +1 -1
- package/dist/hooks/group/useEligibleAccounts.js +9 -9
- package/dist/hooks/group/useEligibleAccountsForGroup.d.ts +9 -0
- package/dist/hooks/group/useEligibleAccountsForGroup.d.ts.map +1 -0
- package/dist/hooks/group/useEligibleAccountsForGroup.js +26 -0
- package/dist/hooks/group/useGetGroupCandidates.d.ts +7 -2
- package/dist/hooks/group/useGetGroupCandidates.d.ts.map +1 -1
- package/dist/hooks/group/useGetGroupCandidates.js +33 -16
- package/dist/hooks/group/useGroupMemberActions.d.ts +25 -0
- package/dist/hooks/group/useGroupMemberActions.d.ts.map +1 -0
- package/dist/hooks/group/useGroupMemberActions.js +54 -0
- package/dist/hooks/group/useGroupPermission.d.ts +15 -0
- package/dist/hooks/group/useGroupPermission.d.ts.map +1 -0
- package/dist/hooks/group/useGroupPermission.js +70 -0
- package/dist/hooks/group/useSearchGroupMembers.d.ts +8 -0
- package/dist/hooks/group/useSearchGroupMembers.d.ts.map +1 -0
- package/dist/hooks/group/useSearchGroupMembers.js +37 -0
- package/dist/hooks/group/useSetMemberPermission.d.ts +12 -0
- package/dist/hooks/group/useSetMemberPermission.d.ts.map +1 -0
- package/dist/hooks/group/useSetMemberPermission.js +32 -0
- package/dist/hooks/group/useToggleGroupSendMessage.d.ts +7 -0
- package/dist/hooks/group/useToggleGroupSendMessage.d.ts.map +1 -0
- package/dist/hooks/group/useToggleGroupSendMessage.js +22 -0
- package/dist/hooks/group/useUpdateGroupInfo.d.ts +7 -0
- package/dist/hooks/group/useUpdateGroupInfo.d.ts.map +1 -0
- package/dist/hooks/group/useUpdateGroupInfo.js +15 -0
- package/dist/hooks/session/useBlockUser.d.ts +10 -0
- package/dist/hooks/session/useBlockUser.d.ts.map +1 -0
- package/dist/hooks/session/useBlockUser.js +49 -0
- package/dist/hooks/session/useDeleteConversation.d.ts +4 -0
- package/dist/hooks/session/useDeleteConversation.d.ts.map +1 -0
- package/dist/hooks/session/useDeleteConversation.js +20 -0
- package/dist/hooks/session/useGetListSessionByConversation.d.ts +2 -1
- package/dist/hooks/session/useGetListSessionByConversation.d.ts.map +1 -1
- package/dist/hooks/session/useGetListSessionByConversation.js +2 -2
- package/dist/hooks/session/useMuteConversation.d.ts +8 -0
- package/dist/hooks/session/useMuteConversation.d.ts.map +1 -0
- package/dist/hooks/session/useMuteConversation.js +37 -0
- package/dist/hooks/session/useToggleConversationNotification.d.ts +7 -0
- package/dist/hooks/session/useToggleConversationNotification.d.ts.map +1 -0
- package/dist/hooks/session/useToggleConversationNotification.js +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/locales/vi/common.json +63 -1
- package/dist/locales/vi/conversation-inbox.json +22 -0
- package/dist/screens/desk-message/index.d.ts +3 -1
- package/dist/screens/desk-message/index.d.ts.map +1 -1
- package/dist/screens/desk-message/index.js +4 -5
- package/dist/services/query.d.ts +2 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +2 -0
- package/dist/store/groupPermissionOverrides.d.ts +23 -0
- package/dist/store/groupPermissionOverrides.d.ts.map +1 -0
- package/dist/store/groupPermissionOverrides.js +12 -0
- package/dist/styles/global.css +1 -1
- package/dist/utils/events.d.ts +1 -0
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/imCommon.d.ts +1 -0
- package/dist/utils/imCommon.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface MemberPermissionPanelProps {
|
|
2
|
+
open: boolean;
|
|
3
|
+
groupID: string;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
}
|
|
6
|
+
declare const MemberPermissionPanel: ({ open, groupID, onClose }: MemberPermissionPanelProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export default MemberPermissionPanel;
|
|
8
|
+
//# sourceMappingURL=MemberPermissionPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemberPermissionPanel.d.ts","sourceRoot":"","sources":["../../../src/components/group/MemberPermissionPanel.tsx"],"names":[],"mappings":"AAYA,UAAU,0BAA0B;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAMD,QAAA,MAAM,qBAAqB,GAAI,4BAA4B,0BAA0B,mDAqHpF,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { ConfigProvider, Switch, message } from "antd";
|
|
5
|
+
import { useTranslation } from "react-i18next";
|
|
6
|
+
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
7
|
+
import { Icon } from "../../components/icon";
|
|
8
|
+
import { PERMISSION_SWITCH_COLOR } from "../../constants";
|
|
9
|
+
import useGroupPermissionOverridesStore from "../../store/groupPermissionOverrides";
|
|
10
|
+
// Mocked config UI (DROPPII-30248 follow-up, "Configure Member Permissions")
|
|
11
|
+
// — renders inline within the "Thông tin" sidebar (back arrow, no gray
|
|
12
|
+
// background) per the reference recording, not as a Modal popup. No BE
|
|
13
|
+
// persistence yet, committed to the in-memory override store on "Lưu" only.
|
|
14
|
+
const MemberPermissionPanel = ({ open, groupID, onClose }) => {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const permissions = useGroupPermission(groupID);
|
|
17
|
+
const setMemberOverrides = useGroupPermissionOverridesStore((state) => state.setMemberOverrides);
|
|
18
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
19
|
+
const [pending, setPending] = useState({
|
|
20
|
+
sendMessage: permissions.sendMessage,
|
|
21
|
+
addMember: permissions.addMember,
|
|
22
|
+
pinMessage: permissions.pinMessage,
|
|
23
|
+
viewMemberInformation: permissions.viewMemberInformation,
|
|
24
|
+
});
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!open)
|
|
27
|
+
return;
|
|
28
|
+
setPending({
|
|
29
|
+
sendMessage: permissions.sendMessage,
|
|
30
|
+
addMember: permissions.addMember,
|
|
31
|
+
pinMessage: permissions.pinMessage,
|
|
32
|
+
viewMemberInformation: permissions.viewMemberInformation,
|
|
33
|
+
});
|
|
34
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
+
}, [open]);
|
|
36
|
+
const hasChanges = pending.sendMessage !== permissions.sendMessage ||
|
|
37
|
+
pending.addMember !== permissions.addMember ||
|
|
38
|
+
pending.pinMessage !== permissions.pinMessage ||
|
|
39
|
+
pending.viewMemberInformation !== permissions.viewMemberInformation;
|
|
40
|
+
const handleSave = async () => {
|
|
41
|
+
if (!groupID)
|
|
42
|
+
return;
|
|
43
|
+
setIsSaving(true);
|
|
44
|
+
setMemberOverrides(groupID, pending);
|
|
45
|
+
message.success(t("update_member_permissions_success"));
|
|
46
|
+
setIsSaving(false);
|
|
47
|
+
onClose();
|
|
48
|
+
};
|
|
49
|
+
if (!open)
|
|
50
|
+
return null;
|
|
51
|
+
return (_jsxs("div", { className: "absolute inset-0 bg-white flex flex-col z-10", children: [_jsxs("div", { className: "flex w-full items-center border-b border-gray-100 p-2", children: [_jsx("button", { type: "button", className: "flex shrink-0 cursor-pointer items-center justify-center p-2 text-primary-400", onClick: onClose, children: _jsx(Icon, { icon: "arrow-left-o", size: 24 }) }), _jsx("p", { className: "min-w-0 flex-1 truncate px-2 text-[18px] font-bold leading-[1.6] text-gray-900", children: t("member_permission_settings") })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx(ConfigProvider, { theme: { token: { colorPrimary: PERMISSION_SWITCH_COLOR } }, children: _jsxs("div", { className: "flex flex-col py-2", children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [_jsx("span", { className: "text-sm", children: t("permission_send_message") }), _jsx(Switch, { checked: pending.sendMessage, onChange: (checked) => setPending((prev) => (Object.assign(Object.assign({}, prev), { sendMessage: checked }))) })] }), _jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [_jsx("span", { className: "text-sm", children: t("permission_add_member") }), _jsx(Switch, { checked: pending.addMember, onChange: (checked) => setPending((prev) => (Object.assign(Object.assign({}, prev), { addMember: checked }))) })] }), _jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [_jsx("span", { className: "text-sm", children: t("permission_pin_message") }), _jsx(Switch, { checked: pending.pinMessage, onChange: (checked) => setPending((prev) => (Object.assign(Object.assign({}, prev), { pinMessage: checked }))) })] }), _jsxs("div", { className: "flex items-center justify-between px-4 py-3", children: [_jsx("span", { className: "text-sm", children: t("permission_view_member_info") }), _jsx(Switch, { checked: pending.viewMemberInformation, onChange: (checked) => setPending((prev) => (Object.assign(Object.assign({}, prev), { viewMemberInformation: checked }))) })] })] }) }) }), _jsxs("div", { className: "flex items-center justify-end gap-2 px-4 py-3 border-t border-gray-100", children: [_jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full border border-gray-300 text-gray-700 text-sm font-medium", onClick: onClose, children: t("cancel") }), _jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full bg-primary-400 text-white text-sm font-medium disabled:bg-gray-200 disabled:text-gray-400", disabled: !hasChanges || isSaving, onClick: handleSave, children: t("save") })] })] }));
|
|
52
|
+
};
|
|
53
|
+
export default MemberPermissionPanel;
|
|
@@ -11,7 +11,7 @@ const FileResourceList = () => {
|
|
|
11
11
|
return (_jsx(ResourceScrollContainer, Object.assign({}, 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-
|
|
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));
|
|
15
15
|
}) }) })));
|
|
16
16
|
};
|
|
17
17
|
export default FileResourceList;
|
|
@@ -17,6 +17,6 @@ const LinkResourceItem = ({ url, messageMetadata }) => {
|
|
|
17
17
|
const handleOpen = () => {
|
|
18
18
|
openLink(url, t);
|
|
19
19
|
};
|
|
20
|
-
return (_jsxs("div", { "data-testid": "link-resource-item", className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-
|
|
20
|
+
return (_jsxs("div", { "data-testid": "link-resource-item", className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-[#f5f5f5]/20 p-3", onClick: handleOpen, children: [_jsx("div", { className: "flex h-[76px] w-[76px] shrink-0 items-center justify-center", children: shouldShowImage ? (_jsx("img", { src: imageUrl, alt: "", className: "h-full w-full rounded-[8px] object-cover", onError: () => setFailedImageUrl(imageUrl) })) : (_jsx("div", { className: "flex h-full w-full items-center justify-center rounded-[12px] bg-gray-200", children: _jsx(Icon, { icon: "link-b", size: 24, color: "white" }) })) }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [_jsx("p", { className: "truncate text-[14px] font-normal leading-[1.6] tracking-[-0.14px] text-gray-600", children: stripProtocol(url) }), _jsx("p", { className: "line-clamp-2 text-[16px] font-medium leading-[1.6] text-gray-900", children: title || url })] })] }));
|
|
21
21
|
};
|
|
22
22
|
export default LinkResourceItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupMembersDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/message/GroupMembersDrawer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GroupMembersDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/message/GroupMembersDrawer.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAe/C,UAAU,uBAAuB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA4CD,QAAA,MAAM,kBAAkB,GAAI,wDAKzB,uBAAuB,4CAuezB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { GroupMemberRole } from "@droppii-org/wasm-client-sdk";
|
|
3
|
-
import { Avatar, Button, Drawer, Dropdown, Empty, message, Modal, Spin } from "antd";
|
|
3
|
+
import { Avatar, Button, Drawer, Dropdown, Empty, Input, message, Modal, Spin } from "antd";
|
|
4
4
|
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { useDebounce } from "ahooks";
|
|
5
6
|
import { useTranslation } from "react-i18next";
|
|
6
7
|
import { usePathname, useRouter } from "next/navigation";
|
|
7
8
|
import useAuthStore from "../../store/auth";
|
|
8
9
|
import useConversationStore from "../../store/conversation";
|
|
9
10
|
import { useGroupMembers } from "../../hooks/group/useGroupMembers";
|
|
11
|
+
import { useSearchGroupMembers } from "../../hooks/group/useSearchGroupMembers";
|
|
10
12
|
import { useLeaveConversation } from "../../hooks/session/useLeaveConversation";
|
|
13
|
+
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
14
|
+
import { useKickGroupMember, useMuteGroupMember, useSetGroupMemberRole, useTransferGroupOwner, } from "../../hooks/group/useGroupMemberActions";
|
|
11
15
|
import { Icon } from "../../components/icon";
|
|
16
|
+
import AddMemberModal from "../../components/group/AddMemberModal";
|
|
17
|
+
import AdminPermissionModal from "../../components/group/AdminPermissionModal";
|
|
18
|
+
const isMemberMuted = (member) => Boolean(member.muteEndTime) && member.muteEndTime * 1000 > Date.now();
|
|
12
19
|
const getMemberDisplayName = (member) => {
|
|
13
20
|
return member.nickname || member.userID || "";
|
|
14
21
|
};
|
|
@@ -29,10 +36,24 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
29
36
|
const pathname = usePathname();
|
|
30
37
|
const [isOpen, setIsOpen] = useState(false);
|
|
31
38
|
const [showLeaveConfirm, setShowLeaveConfirm] = useState(false);
|
|
39
|
+
const [showAddMember, setShowAddMember] = useState(false);
|
|
40
|
+
const [showAdminPermission, setShowAdminPermission] = useState(false);
|
|
41
|
+
const [confirmMemberAction, setConfirmMemberAction] = useState(null);
|
|
42
|
+
const [search, setSearch] = useState("");
|
|
43
|
+
const debouncedSearch = useDebounce(search, { wait: 300 });
|
|
32
44
|
const authUserID = useAuthStore((state) => state.userID);
|
|
33
45
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
46
|
+
const currentMemberInGroup = useConversationStore((state) => state.currentMemberInGroup);
|
|
34
47
|
const { members, isLoading, error, refetch } = useGroupMembers(groupID);
|
|
48
|
+
const { results: searchResults, isSearching } = useSearchGroupMembers(groupID, debouncedSearch);
|
|
35
49
|
const { mutateAsync: leaveConversation, isPending: isLeaving } = useLeaveConversation();
|
|
50
|
+
const permissions = useGroupPermission(groupID);
|
|
51
|
+
const { mutateAsync: muteMember } = useMuteGroupMember();
|
|
52
|
+
const { mutateAsync: kickMember } = useKickGroupMember();
|
|
53
|
+
const { mutateAsync: setMemberRole } = useSetGroupMemberRole();
|
|
54
|
+
const { mutateAsync: transferOwner } = useTransferGroupOwner();
|
|
55
|
+
const canAddMember = (currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) === GroupMemberRole.Admin ||
|
|
56
|
+
(currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) === GroupMemberRole.Owner;
|
|
36
57
|
let customerUserID = "";
|
|
37
58
|
try {
|
|
38
59
|
const exConversationInfo = JSON.parse((conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex) || "{}");
|
|
@@ -41,21 +62,33 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
41
62
|
catch (error) {
|
|
42
63
|
console.error("Error parsing conversation extra info:", error);
|
|
43
64
|
}
|
|
65
|
+
const isSearchActive = debouncedSearch.trim().length > 0;
|
|
66
|
+
const sourceMembers = isSearchActive ? searchResults : members;
|
|
44
67
|
const sortedMembers = useMemo(() => {
|
|
45
|
-
return [...
|
|
46
|
-
.map((member) =>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
member,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
return [...sourceMembers]
|
|
69
|
+
.map((member) => {
|
|
70
|
+
const isOwner = member.userID === customerUserID ||
|
|
71
|
+
member.roleLevel === GroupMemberRole.Owner;
|
|
72
|
+
return {
|
|
73
|
+
userID: member.userID,
|
|
74
|
+
nickname: getMemberDisplayName(member),
|
|
75
|
+
faceURL: member.faceURL,
|
|
76
|
+
isCustomer: Boolean(customerUserID) && member.userID === customerUserID,
|
|
77
|
+
isCurrentUser: member.userID === authUserID,
|
|
78
|
+
isOwner,
|
|
79
|
+
isAdmin: member.roleLevel === GroupMemberRole.Admin,
|
|
80
|
+
isMuted: isMemberMuted(member),
|
|
81
|
+
// Mockup only shows a role label under the owner/creator row —
|
|
82
|
+
// Admin/Member rows show name only.
|
|
83
|
+
roleLabel: isOwner
|
|
84
|
+
? getMemberRoleLabel({ member, customerUserID, t })
|
|
85
|
+
: "",
|
|
86
|
+
};
|
|
87
|
+
})
|
|
58
88
|
.sort((memberA, memberB) => {
|
|
89
|
+
if (memberA.isCurrentUser !== memberB.isCurrentUser) {
|
|
90
|
+
return memberA.isCurrentUser ? -1 : 1;
|
|
91
|
+
}
|
|
59
92
|
if (memberA.isCustomer !== memberB.isCustomer) {
|
|
60
93
|
return memberA.isCustomer ? -1 : 1;
|
|
61
94
|
}
|
|
@@ -63,7 +96,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
63
96
|
sensitivity: "base",
|
|
64
97
|
});
|
|
65
98
|
});
|
|
66
|
-
}, [authUserID,
|
|
99
|
+
}, [authUserID, sourceMembers, customerUserID, t]);
|
|
67
100
|
const handleOpenDrawer = () => {
|
|
68
101
|
if (!groupID || disabled) {
|
|
69
102
|
return;
|
|
@@ -86,6 +119,79 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
86
119
|
}
|
|
87
120
|
setShowLeaveConfirm(true);
|
|
88
121
|
};
|
|
122
|
+
const handleToggleMuteMember = async (member) => {
|
|
123
|
+
var _a, _b;
|
|
124
|
+
if (!groupID)
|
|
125
|
+
return;
|
|
126
|
+
try {
|
|
127
|
+
await muteMember({
|
|
128
|
+
groupID,
|
|
129
|
+
userID: member.userID,
|
|
130
|
+
mute: !member.isMuted,
|
|
131
|
+
});
|
|
132
|
+
message.success(member.isMuted
|
|
133
|
+
? t("unmute_member_success")
|
|
134
|
+
: t("mute_member_success"));
|
|
135
|
+
void refetch();
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
message.error(((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("update_group_info_failed"));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const handleConfirmRemoveMember = async () => {
|
|
142
|
+
var _a, _b;
|
|
143
|
+
if (!groupID || (confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.type) !== "remove")
|
|
144
|
+
return;
|
|
145
|
+
try {
|
|
146
|
+
await kickMember({ groupID, userID: confirmMemberAction.member.userID });
|
|
147
|
+
message.success(t("remove_member_success"));
|
|
148
|
+
void refetch();
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
message.error(((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("remove_member_failed"));
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
setConfirmMemberAction(null);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const handleToggleAdminRole = async (member) => {
|
|
158
|
+
var _a, _b;
|
|
159
|
+
if (!groupID)
|
|
160
|
+
return;
|
|
161
|
+
try {
|
|
162
|
+
await setMemberRole({
|
|
163
|
+
groupID,
|
|
164
|
+
userID: member.userID,
|
|
165
|
+
roleLevel: member.isAdmin ? GroupMemberRole.Normal : GroupMemberRole.Admin,
|
|
166
|
+
});
|
|
167
|
+
message.success(member.isAdmin
|
|
168
|
+
? t("remove_from_admin_success")
|
|
169
|
+
: t("assign_as_admin_success"));
|
|
170
|
+
void refetch();
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
message.error(((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("update_group_info_failed"));
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const handleConfirmTransferOwner = async () => {
|
|
177
|
+
var _a, _b;
|
|
178
|
+
if (!groupID || (confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.type) !== "transfer-owner")
|
|
179
|
+
return;
|
|
180
|
+
try {
|
|
181
|
+
await transferOwner({
|
|
182
|
+
groupID,
|
|
183
|
+
newOwnerUserID: confirmMemberAction.member.userID,
|
|
184
|
+
});
|
|
185
|
+
message.success(t("transfer_owner_success"));
|
|
186
|
+
void refetch();
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
message.error(((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("update_group_info_failed"));
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
setConfirmMemberAction(null);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
89
195
|
const handleConfirmLeave = async () => {
|
|
90
196
|
var _a, _b;
|
|
91
197
|
if (!conversationId || !groupID)
|
|
@@ -106,26 +212,98 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
106
212
|
setIsOpen(false);
|
|
107
213
|
}, [groupID]);
|
|
108
214
|
const renderContent = () => {
|
|
109
|
-
if (isLoading) {
|
|
215
|
+
if (isLoading || (isSearchActive && isSearching)) {
|
|
110
216
|
return (_jsx("div", { className: "flex items-center justify-center h-full min-h-40", children: _jsx(Spin, {}) }));
|
|
111
217
|
}
|
|
112
218
|
if (error) {
|
|
113
219
|
return (_jsx("div", { className: "flex items-center justify-center h-full min-h-40 px-6 text-center text-sm text-gray-500", children: t(error) }));
|
|
114
220
|
}
|
|
115
221
|
if (!sortedMembers.length) {
|
|
116
|
-
return _jsx(Empty, { description: t("no_group_members") });
|
|
222
|
+
return (_jsx(Empty, { description: isSearchActive ? t("no_member_found") : t("no_group_members") }));
|
|
117
223
|
}
|
|
118
224
|
return (_jsx("div", { className: "flex flex-col", children: sortedMembers.map((member) => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
225
|
+
// Send message / Remove and block are not wired yet (no confirmed
|
|
226
|
+
// SDK flow for member-scoped block) — kept disabled per scope.
|
|
227
|
+
const menuItems = member.isCurrentUser
|
|
228
|
+
? [
|
|
229
|
+
{
|
|
230
|
+
key: "mute",
|
|
231
|
+
label: t("mute_member"),
|
|
232
|
+
icon: _jsx(Icon, { icon: "bell-off-b", size: 16 }),
|
|
233
|
+
disabled: true,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
key: "leave-group",
|
|
237
|
+
label: t("leave_group"),
|
|
238
|
+
icon: _jsx(Icon, { icon: "logout-b", size: 16 }),
|
|
239
|
+
onClick: handleLeaveGroup,
|
|
240
|
+
danger: true,
|
|
241
|
+
},
|
|
242
|
+
]
|
|
243
|
+
: [
|
|
244
|
+
{
|
|
245
|
+
key: "send-message",
|
|
246
|
+
label: t("send_message"),
|
|
247
|
+
icon: _jsx(Icon, { icon: "send-b", size: 16 }),
|
|
248
|
+
disabled: true,
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
key: "mute",
|
|
252
|
+
label: member.isMuted ? t("unmute_member") : t("mute_member"),
|
|
253
|
+
icon: _jsx(Icon, { icon: "bell-off-b", size: 16 }),
|
|
254
|
+
disabled: !permissions.removeMember,
|
|
255
|
+
onClick: () => void handleToggleMuteMember(member),
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
key: "transfer-owner",
|
|
259
|
+
label: t("transfer_owner"),
|
|
260
|
+
icon: _jsx(Icon, { icon: "key-b", size: 16 }),
|
|
261
|
+
disabled: !permissions.transferOwnership,
|
|
262
|
+
onClick: () => setConfirmMemberAction({ type: "transfer-owner", member }),
|
|
263
|
+
},
|
|
264
|
+
...(member.isAdmin
|
|
265
|
+
? [
|
|
266
|
+
{
|
|
267
|
+
key: "configure-admin-permission",
|
|
268
|
+
label: t("admin_permission_settings"),
|
|
269
|
+
icon: _jsx(Icon, { icon: "shield-o", size: 16 }),
|
|
270
|
+
disabled: !permissions.transferOwnership,
|
|
271
|
+
onClick: () => setShowAdminPermission(true),
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
key: "remove-admin",
|
|
275
|
+
label: t("remove_from_admin"),
|
|
276
|
+
icon: _jsx(Icon, { icon: "shield-fail-b", size: 16 }),
|
|
277
|
+
disabled: !permissions.addAdmin,
|
|
278
|
+
onClick: () => void handleToggleAdminRole(member),
|
|
279
|
+
},
|
|
280
|
+
]
|
|
281
|
+
: [
|
|
282
|
+
{
|
|
283
|
+
key: "assign-admin",
|
|
284
|
+
label: t("assign_as_admin"),
|
|
285
|
+
icon: _jsx(Icon, { icon: "shield-b", size: 16 }),
|
|
286
|
+
disabled: !permissions.addAdmin,
|
|
287
|
+
onClick: () => void handleToggleAdminRole(member),
|
|
288
|
+
},
|
|
289
|
+
]),
|
|
290
|
+
{
|
|
291
|
+
key: "remove-member",
|
|
292
|
+
label: t("remove_from_group"),
|
|
293
|
+
icon: _jsx(Icon, { icon: "user-del-b", size: 16 }),
|
|
294
|
+
danger: true,
|
|
295
|
+
disabled: !permissions.removeMember,
|
|
296
|
+
onClick: () => setConfirmMemberAction({ type: "remove", member }),
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
key: "remove-and-block",
|
|
300
|
+
label: t("remove_and_block"),
|
|
301
|
+
icon: _jsx(Icon, { icon: "user-octagon-b", size: 16 }),
|
|
302
|
+
danger: true,
|
|
303
|
+
disabled: true,
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
return (_jsxs("div", { className: "flex items-center gap-3 px-4 py-2", children: [_jsx(Avatar, { src: member.faceURL, size: 40, className: "shrink-0", children: member.nickname.charAt(0) || "A" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("p", { className: "text-sm font-semibold text-gray-900 truncate", children: member.nickname }), member.isCurrentUser && (_jsx("span", { className: "text-xs text-blue-500 shrink-0", children: t("current_account") }))] }), member.roleLabel && (_jsx("p", { className: "text-sm text-gray-500 truncate", children: member.roleLabel }))] }), _jsx(Dropdown, { menu: { items: menuItems }, trigger: ["click"], placement: "bottomRight", children: _jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 rounded-full text-gray-500 hover:bg-gray-100", onClick: (event) => event.stopPropagation(), children: _jsx(Icon, { icon: "more-horizontal-b", size: 18 }) }) })] }, member.userID));
|
|
129
307
|
}) }));
|
|
130
308
|
};
|
|
131
309
|
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleOpenDrawer, disabled: disabled || !groupID, children: _jsx(Icon, { icon: "user-two-check-b", size: 22 }) }), _jsx(Drawer, { open: isOpen, onClose: handleCloseDrawer, mask: false, closeIcon: false, styles: {
|
|
@@ -133,6 +311,10 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
133
311
|
padding: 0,
|
|
134
312
|
height: "100%",
|
|
135
313
|
},
|
|
136
|
-
}, getContainer: false, width: 360, children: _jsxs("div", { className: "flex flex-col h-full bg-white", children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-
|
|
314
|
+
}, getContainer: false, width: 360, children: _jsxs("div", { className: "flex flex-col h-full bg-white py-2", children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-4 border-b border-gray-100", children: [_jsx("span", { className: "text-lg font-medium", children: t("members") }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleCloseDrawer, children: _jsx(Icon, { icon: "close-b", size: 22 }) })] }), _jsxs("div", { className: "flex items-center gap-2 px-4 py-3", children: [_jsx(Input, { value: search, onChange: (event) => setSearch(event.target.value), placeholder: t("search_member_placeholder"), prefix: _jsx(Icon, { icon: "search-o", size: 16, className: "text-gray-400" }), className: "h-10" }), canAddMember && (_jsx(Button, { type: "primary", shape: "default", className: "w-10 h-10 p-0 shrink-0 flex items-center justify-center rounded-lg", onClick: () => setShowAddMember(true), children: _jsx(Icon, { icon: "user-add-b", size: 18 }) }))] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: renderContent() })] }) }), _jsx(Modal, { centered: true, open: showLeaveConfirm, onOk: handleConfirmLeave, onCancel: () => setShowLeaveConfirm(false), title: t("leave_group_confirm_title"), okText: t("leave_group"), cancelText: t("cancel"), okType: "danger", confirmLoading: isLeaving, getContainer: false, children: _jsx("p", { children: t("leave_group_confirm_message") }) }), _jsx(Modal, { centered: true, open: (confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.type) === "remove", onOk: handleConfirmRemoveMember, onCancel: () => setConfirmMemberAction(null), title: t("remove_member_confirm_title"), okText: t("remove_from_group"), cancelText: t("cancel"), okType: "danger", getContainer: false, children: _jsx("p", { children: t("remove_member_confirm_message", {
|
|
315
|
+
name: confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.member.nickname,
|
|
316
|
+
}) }) }), _jsx(Modal, { centered: true, open: (confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.type) === "transfer-owner", onOk: handleConfirmTransferOwner, onCancel: () => setConfirmMemberAction(null), title: t("transfer_owner_confirm_title"), okText: t("transfer_owner"), cancelText: t("cancel"), okType: "danger", getContainer: false, children: _jsx("p", { children: t("transfer_owner_confirm_message", {
|
|
317
|
+
name: confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.member.nickname,
|
|
318
|
+
}) }) }), groupID && (_jsx(AddMemberModal, { open: showAddMember, groupID: groupID, existingMemberIDs: members.map((member) => member.userID), onClose: () => setShowAddMember(false) })), groupID && (_jsx(AdminPermissionModal, { open: showAdminPermission, groupID: groupID, onClose: () => setShowAdminPermission(false) }))] }));
|
|
137
319
|
};
|
|
138
320
|
export default GroupMembersDrawer;
|
|
@@ -4,6 +4,7 @@ interface MessageHeaderProps {
|
|
|
4
4
|
onClose?: () => void;
|
|
5
5
|
currentSession?: ISessionResponse;
|
|
6
6
|
isJoined?: boolean | null;
|
|
7
|
+
onOpenThreadInfo?: () => void;
|
|
7
8
|
}
|
|
8
9
|
type SelectSessionValueType = SessionStatus | SessionTag;
|
|
9
10
|
export interface SelectSessionOption {
|
|
@@ -13,6 +14,6 @@ export interface SelectSessionOption {
|
|
|
13
14
|
tintColorClassnameBg: string;
|
|
14
15
|
bgTintColorClassname: string;
|
|
15
16
|
}
|
|
16
|
-
declare const MessageHeader: ({ onClose, currentSession, isJoined, }: MessageHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare const MessageHeader: ({ onClose, currentSession, isJoined, onOpenThreadInfo, }: MessageHeaderProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
18
|
export default MessageHeader;
|
|
18
19
|
//# sourceMappingURL=MessageHeader.d.ts.map
|
|
@@ -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,cAAc,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageHeader.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAO/C,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;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,0DAKpB,kBAAkB,4CAkNpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -13,8 +13,9 @@ import { useUpdateSession } from "../../hooks/session/useUpdateSession";
|
|
|
13
13
|
import useAuthStore from "../../store/auth";
|
|
14
14
|
import SearchDrawer from "../../components/search-conversation/SearchDrawer";
|
|
15
15
|
import { isGroupSession } from "../../utils/imCommon";
|
|
16
|
+
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
16
17
|
import GroupMembersDrawer from "./GroupMembersDrawer";
|
|
17
|
-
const MessageHeader = ({ onClose, currentSession, isJoined, }) => {
|
|
18
|
+
const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, }) => {
|
|
18
19
|
var _a, _b;
|
|
19
20
|
const { t } = useTranslation();
|
|
20
21
|
const isCx = useAuthStore((state) => state.isCx);
|
|
@@ -22,6 +23,7 @@ const MessageHeader = ({ onClose, currentSession, isJoined, }) => {
|
|
|
22
23
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
23
24
|
const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
|
|
24
25
|
const { mutate: updateSession } = useUpdateSession();
|
|
26
|
+
const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
|
|
25
27
|
const { avatar, displayName } = useConversationDisplayData(conversationData);
|
|
26
28
|
const shouldShowMemberCount = isGroupSession(conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType);
|
|
27
29
|
const [currentSessionStatus, setCurrentSessionStatus] = useState(SessionStatus.UNASSIGNED);
|
|
@@ -127,6 +129,9 @@ const MessageHeader = ({ onClose, currentSession, isJoined, }) => {
|
|
|
127
129
|
setCurrentSessionStatus(currentSession.status);
|
|
128
130
|
}
|
|
129
131
|
}, [currentSession]);
|
|
130
|
-
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, {}), shouldShowMemberCount &&
|
|
132
|
+
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, {}), shouldShowMemberCount &&
|
|
133
|
+
isJoined === true &&
|
|
134
|
+
isCrm &&
|
|
135
|
+
permissions.viewMemberInformation && (_jsx(GroupMembersDrawer, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, conversationId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID, currentSession: currentSession })), _jsx(MediaCollection, {}), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onOpenThreadInfo, 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 }) }))] })] }));
|
|
131
136
|
};
|
|
132
137
|
export default MessageHeader;
|
|
@@ -4,6 +4,7 @@ interface MessageListProps {
|
|
|
4
4
|
className?: string;
|
|
5
5
|
onClose?: () => void;
|
|
6
6
|
openCreateCannedModal?: () => void;
|
|
7
|
+
onOpenThreadInfo?: () => void;
|
|
7
8
|
}
|
|
8
9
|
declare const MessageList: (props: MessageListProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export default MessageList;
|
|
@@ -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":"AA2BA,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;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAuO3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -19,13 +19,18 @@ import { useChatContext } from "../../context/ChatContext";
|
|
|
19
19
|
import { useRevokeMessage } from "../../hooks/message/useRevokeMessage";
|
|
20
20
|
import { useConversationSessionState } from "../../hooks/session/useConversationSessionState";
|
|
21
21
|
import { useJoinGroupFlow } from "../../hooks/session/useJoinGroupFlow";
|
|
22
|
+
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
23
|
+
import { isGroupSession } from "../../utils/imCommon";
|
|
22
24
|
import { ConnectStatus, SessionStatus } from "../../types/chat";
|
|
23
25
|
dayjs.extend(isToday);
|
|
24
26
|
const MessageList = (props) => {
|
|
25
27
|
const { t } = useTranslation();
|
|
26
28
|
const { user, connectStatus } = useChatContext();
|
|
27
|
-
const { onClose, conversationId, searchClientMsgID, openCreateCannedModal } = props;
|
|
29
|
+
const { onClose, conversationId, searchClientMsgID, openCreateCannedModal, onOpenThreadInfo, } = props;
|
|
28
30
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
31
|
+
const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
|
|
32
|
+
const isGroupChat = isGroupSession(conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType);
|
|
33
|
+
const canSendMessage = !isGroupChat || permissions.sendMessage;
|
|
29
34
|
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
30
35
|
const setSearchClientMsgID = useConversationStore((state) => state.setSearchClientMsgID);
|
|
31
36
|
const [openMenuId, setOpenMenuId] = useState(null);
|
|
@@ -102,6 +107,6 @@ const MessageList = (props) => {
|
|
|
102
107
|
if (!conversationData) {
|
|
103
108
|
return (_jsx("div", { className: "flex flex-1 items-center justify-center h-full", children: connectStatus !== ConnectStatus.Connected ? (_jsx(Spin, {})) : (_jsx(Empty, { description: t("no_conversation_data") })) }));
|
|
104
109
|
}
|
|
105
|
-
return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, 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, {}) })), isCheckingMembership ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_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: joinGroup, 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") }) })] }));
|
|
110
|
+
return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, 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, {}) })), isCheckingMembership ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_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: joinGroup, loading: isJoining, children: t("join_group") })] })) : !canSendMessage ? (_jsx("div", { className: "border-t bg-[#f5f5f5] py-3 flex items-center justify-center", children: _jsx("p", { className: "text-sm text-gray-500", children: t("send_message_disabled") }) })) : (_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") }) })] }));
|
|
106
111
|
};
|
|
107
112
|
export default MessageList;
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,4CAmEpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { Icon } from "../../components/icon";
|
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
const SelectSession = ({ options, value, onChange, excludeOptions, placeholder, }) => {
|
|
7
7
|
const selectedOption = options.find((option) => option.value === value);
|
|
8
|
-
const renderOptionLabel = (option) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: clsx("w-2 h-2 rounded-full", option.tintColorClassnameBg) }), _jsx("span", { className: clsx("text-xs
|
|
8
|
+
const renderOptionLabel = (option, truncateLabel = false) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: clsx("w-2 h-2 rounded-full shrink-0", option.tintColorClassnameBg) }), _jsx("span", { className: clsx("text-xs whitespace-nowrap", truncateLabel && "truncate", option.tintColorClassname), children: option.label })] }));
|
|
9
9
|
const filteredOptions = options.filter((option) => option.value === value || !(excludeOptions === null || excludeOptions === void 0 ? void 0 : excludeOptions.includes(option.value)));
|
|
10
10
|
const selectOptions = filteredOptions.map((option) => ({
|
|
11
11
|
label: renderOptionLabel(option),
|
|
@@ -14,10 +14,10 @@ const SelectSession = ({ options, value, onChange, excludeOptions, placeholder,
|
|
|
14
14
|
const handleSelect = (val) => {
|
|
15
15
|
onChange(val);
|
|
16
16
|
};
|
|
17
|
-
return (_jsx("div", { className: "relative", children: _jsx(Select, { className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.bgTintColorClassname} custom-select min-w-[100px]`, placement: "bottomLeft", placeholder: placeholder, options: selectOptions, value: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value, onSelect: handleSelect, suffixIcon: _jsx(Icon, { icon: "angle-down-o", className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.tintColorClassname} mt-[2px]`, size: 14 }), menuItemSelectedIcon: null, labelRender: () => ["NONE", ""].includes(selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value)
|
|
17
|
+
return (_jsx("div", { className: "relative shrink-0", children: _jsx(Select, { className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.bgTintColorClassname} custom-select min-w-[100px]`, placement: "bottomLeft", placeholder: placeholder, options: selectOptions, value: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value, onSelect: handleSelect, popupMatchSelectWidth: false, suffixIcon: _jsx(Icon, { icon: "angle-down-o", className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.tintColorClassname} mt-[2px]`, size: 14 }), menuItemSelectedIcon: null, labelRender: () => ["NONE", ""].includes(selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value)
|
|
18
18
|
? placeholder
|
|
19
19
|
: selectedOption
|
|
20
|
-
? renderOptionLabel(selectedOption)
|
|
20
|
+
? renderOptionLabel(selectedOption, true)
|
|
21
21
|
: undefined }) }));
|
|
22
22
|
};
|
|
23
23
|
export default SelectSession;
|
|
@@ -7,7 +7,7 @@ import { useGetTeamSessionSummary } from "../../hooks/session/useGetTeamSessionS
|
|
|
7
7
|
import useSessionStore from "../../store/session";
|
|
8
8
|
import emitter from "../../utils/events";
|
|
9
9
|
import SessionFilterMenu from "./SessionFilterMenu";
|
|
10
|
-
const TeamGroup = memo(({ team, isExpanded, isSelected, selectedFilter, onToggle, onFilterSelect, }) => (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-2 cursor-pointer hover:bg-
|
|
10
|
+
const TeamGroup = memo(({ team, isExpanded, isSelected, selectedFilter, onToggle, onFilterSelect, }) => (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-2 cursor-pointer hover:bg-[#f5f5f5]", onClick: onToggle, children: [_jsx("span", { className: "text-sm font-semibold text-blue-500 truncate flex-1", children: team.teamName }), _jsx(Icon, { icon: isExpanded ? "angle-up-o" : "angle-down-o", size: 16, className: "text-gray-400 shrink-0" })] }), isExpanded && (_jsx(SessionFilterMenu, { summary: team.summary, isActive: isSelected, filterSummary: selectedFilter, onFilterSelect: onFilterSelect, includeUnassigned: true, activeCount: team.summary.activeSessionCount }))] })));
|
|
11
11
|
const DeskTeamInbox = () => {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
13
|
const { data: teamSummaries, refetch } = useGetTeamSessionSummary();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface GroupThreadInfoConfig {
|
|
2
|
+
showAllowSendMessage?: boolean;
|
|
3
|
+
showMutedChatList?: boolean;
|
|
4
|
+
}
|
|
5
|
+
interface GroupThreadInfoProps {
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
config?: GroupThreadInfoConfig;
|
|
8
|
+
}
|
|
9
|
+
declare const GroupThreadInfo: ({ onClose, config }: GroupThreadInfoProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export default GroupThreadInfo;
|
|
11
|
+
//# sourceMappingURL=GroupThreadInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/GroupThreadInfo.tsx"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC;AAID,QAAA,MAAM,eAAe,GAAI,qBAAqB,oBAAoB,mDAmcjE,CAAC;AAEF,eAAe,eAAe,CAAC"}
|