@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,156 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Avatar, Input, Modal, Switch, message } from "antd";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import { GroupMemberRole, MessageReceiveOptType } from "@droppii-org/wasm-client-sdk";
|
|
6
|
+
import { Icon } from "../../components/icon";
|
|
7
|
+
import useConversationStore from "../../store/conversation";
|
|
8
|
+
import { useLeaveConversation } from "../../hooks/session/useLeaveConversation";
|
|
9
|
+
import { useDeleteConversation } from "../../hooks/session/useDeleteConversation";
|
|
10
|
+
import { useToggleConversationNotification } from "../../hooks/session/useToggleConversationNotification";
|
|
11
|
+
import { useUpdateGroupInfo } from "../../hooks/group/useUpdateGroupInfo";
|
|
12
|
+
import { useToggleGroupSendMessage } from "../../hooks/group/useToggleGroupSendMessage";
|
|
13
|
+
import { useDismissGroup } from "../../hooks/group/useDismissGroup";
|
|
14
|
+
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
15
|
+
import AdminPermissionModal from "../../components/group/AdminPermissionModal";
|
|
16
|
+
import MemberPermissionPanel from "../../components/group/MemberPermissionPanel";
|
|
17
|
+
const GroupThreadInfo = ({ onClose, config }) => {
|
|
18
|
+
var _a, _b, _c, _d, _e;
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
const conversationData = useConversationStore((state) => state.conversationData);
|
|
21
|
+
const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
|
|
22
|
+
const groupID = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID) || "";
|
|
23
|
+
const conversationID = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "";
|
|
24
|
+
const permissions = useGroupPermission(groupID);
|
|
25
|
+
const currentMemberInGroup = useConversationStore((state) => state.currentMemberInGroup);
|
|
26
|
+
// Muted-chat-list and disband-group aren't part of the 11-permission
|
|
27
|
+
// matrix in the spec — kept as a role check like before, not mocked
|
|
28
|
+
// per-permission.
|
|
29
|
+
const isAdminOrOwner = (currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) === GroupMemberRole.Admin ||
|
|
30
|
+
(currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) === GroupMemberRole.Owner;
|
|
31
|
+
const [editingField, setEditingField] = useState(null);
|
|
32
|
+
const [nameValue, setNameValue] = useState((_a = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName) !== null && _a !== void 0 ? _a : "");
|
|
33
|
+
const [descriptionValue, setDescriptionValue] = useState((_b = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) !== null && _b !== void 0 ? _b : "");
|
|
34
|
+
const [confirmAction, setConfirmAction] = useState(null);
|
|
35
|
+
const [activeRow, setActiveRow] = useState(null);
|
|
36
|
+
const [notifyEnabled, setNotifyEnabled] = useState((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
37
|
+
// Q4 (non-block, pending BE/SDK confirmation): openIM's GroupItem has no
|
|
38
|
+
// readable "is send disabled" field for changeGroupMute — tracked locally
|
|
39
|
+
// until BE confirms where (or whether) this persists server-side.
|
|
40
|
+
const [allowSendMessage, setAllowSendMessage] = useState(true);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
setNotifyEnabled((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
43
|
+
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt]);
|
|
44
|
+
const { mutate: updateGroupInfo } = useUpdateGroupInfo();
|
|
45
|
+
const { mutate: toggleSendMessage, isPending: isTogglingSendMessage } = useToggleGroupSendMessage();
|
|
46
|
+
const { mutate: toggleNotification, isPending: isTogglingNotification } = useToggleConversationNotification();
|
|
47
|
+
const { mutateAsync: leaveConversation, isPending: isLeaving } = useLeaveConversation();
|
|
48
|
+
const { mutateAsync: dismissGroup, isPending: isDismissing } = useDismissGroup();
|
|
49
|
+
const { mutateAsync: deleteConversation, isPending: isDeleting } = useDeleteConversation();
|
|
50
|
+
const startEditName = () => {
|
|
51
|
+
var _a;
|
|
52
|
+
setNameValue((_a = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName) !== null && _a !== void 0 ? _a : "");
|
|
53
|
+
setEditingField("name");
|
|
54
|
+
};
|
|
55
|
+
const startEditDescription = () => {
|
|
56
|
+
var _a;
|
|
57
|
+
setDescriptionValue((_a = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) !== null && _a !== void 0 ? _a : "");
|
|
58
|
+
setEditingField("description");
|
|
59
|
+
};
|
|
60
|
+
const saveName = () => {
|
|
61
|
+
const trimmed = nameValue.trim();
|
|
62
|
+
setEditingField(null);
|
|
63
|
+
if (!groupID || !trimmed || trimmed === (currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName))
|
|
64
|
+
return;
|
|
65
|
+
updateGroupInfo({ groupID, groupName: trimmed }, { onError: () => message.error(t("update_group_info_failed")) });
|
|
66
|
+
};
|
|
67
|
+
const cancelEditDescription = () => {
|
|
68
|
+
var _a;
|
|
69
|
+
setDescriptionValue((_a = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) !== null && _a !== void 0 ? _a : "");
|
|
70
|
+
setEditingField(null);
|
|
71
|
+
};
|
|
72
|
+
const saveDescription = () => {
|
|
73
|
+
const trimmed = descriptionValue.trim();
|
|
74
|
+
setEditingField(null);
|
|
75
|
+
if (!groupID || trimmed === (currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction))
|
|
76
|
+
return;
|
|
77
|
+
updateGroupInfo({ groupID, introduction: trimmed }, { onError: () => message.error(t("update_group_info_failed")) });
|
|
78
|
+
};
|
|
79
|
+
const handleToggleNotification = (checked) => {
|
|
80
|
+
if (!conversationID)
|
|
81
|
+
return;
|
|
82
|
+
const previous = notifyEnabled;
|
|
83
|
+
setNotifyEnabled(checked);
|
|
84
|
+
toggleNotification({ conversationID, notify: checked }, {
|
|
85
|
+
onError: () => {
|
|
86
|
+
setNotifyEnabled(previous);
|
|
87
|
+
message.error(t("update_group_info_failed"));
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
const handleToggleSendMessage = (checked) => {
|
|
92
|
+
if (!groupID)
|
|
93
|
+
return;
|
|
94
|
+
const previous = allowSendMessage;
|
|
95
|
+
setAllowSendMessage(checked);
|
|
96
|
+
toggleSendMessage({ groupID, allowSendMessage: checked }, {
|
|
97
|
+
onError: () => {
|
|
98
|
+
setAllowSendMessage(previous);
|
|
99
|
+
message.error(t("update_group_info_failed"));
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
const handleConfirmLeave = async () => {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
if (!conversationID)
|
|
106
|
+
return;
|
|
107
|
+
try {
|
|
108
|
+
await leaveConversation({ conversationId: conversationID });
|
|
109
|
+
message.success(t("leave_group_success"));
|
|
110
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
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("leave_group_failed"));
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
setConfirmAction(null);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const handleConfirmDisband = async () => {
|
|
120
|
+
var _a, _b;
|
|
121
|
+
if (!groupID)
|
|
122
|
+
return;
|
|
123
|
+
try {
|
|
124
|
+
await dismissGroup({ groupID });
|
|
125
|
+
message.success(t("disband_group_success"));
|
|
126
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
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("disband_group_failed"));
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
setConfirmAction(null);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const handleConfirmDelete = async () => {
|
|
136
|
+
var _a, _b;
|
|
137
|
+
if (!conversationID)
|
|
138
|
+
return;
|
|
139
|
+
try {
|
|
140
|
+
await deleteConversation({ conversationID });
|
|
141
|
+
message.success(t("delete_conversation_success"));
|
|
142
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
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("delete_conversation_failed"));
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
setConfirmAction(null);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
if (!groupID) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return (_jsxs("div", { className: "h-full w-[330px] bg-white shadow-md flex flex-col relative overflow-hidden", 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("thread_info_title") }), _jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 rounded-full text-gray-500 hover:bg-gray-100", onClick: onClose, children: _jsx(Icon, { icon: "close-o", size: 20 }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-4", children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.faceURL, size: 56, children: ((_d = (_c = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName) === null || _c === void 0 ? void 0 : _c.charAt) === null || _d === void 0 ? void 0 : _d.call(_c, 0)) || "G" }), permissions.updateGroupAvatar && (_jsx("span", { className: "absolute -bottom-1 -right-1 flex items-center justify-center w-5 h-5 rounded-full bg-black text-white", children: _jsx(Icon, { icon: "camera-o", size: 12 }) }))] }), _jsx("div", { className: "flex-1 min-w-0", children: editingField === "name" ? (_jsx(Input, { autoFocus: true, value: nameValue, onChange: (event) => setNameValue(event.target.value), onPressEnter: saveName, onBlur: saveName, maxLength: 100 })) : (_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("p", { className: "text-base font-medium truncate", children: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName }), permissions.updateGroupName && (_jsx(Icon, { icon: "edit-o", size: 16, className: "shrink-0 cursor-pointer text-gray-500", onClick: startEditName }))] })) })] }), _jsx("div", { className: "px-4 pb-4", children: editingField === "description" ? (_jsxs("div", { className: "flex flex-col gap-3 bg-[#f5f5f5] rounded-lg p-3", children: [_jsxs("span", { className: "flex items-center gap-2 text-sm font-medium text-gray-900", children: [_jsx(Icon, { icon: "info-circle-o", size: 18, className: "text-gray-500" }), t("description")] }), _jsx(Input.TextArea, { autoFocus: true, value: descriptionValue, onChange: (event) => setDescriptionValue(event.target.value), placeholder: t("enter_group_description"), autoSize: { minRows: 1, maxRows: 4 }, maxLength: 500, className: "bg-white" }), _jsxs("div", { className: "flex items-center justify-end gap-2", children: [_jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full border border-primary-500 text-primary-500 text-sm font-medium", onClick: cancelEditDescription, children: t("cancel") }), _jsx("button", { type: "button", className: "px-4 py-1.5 rounded-full text-primary-500 text-sm font-medium disabled:text-gray-300", disabled: descriptionValue.trim() === ((_e = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) !== null && _e !== void 0 ? _e : ""), onClick: saveDescription, children: t("save") })] })] })) : (_jsxs("div", { className: "flex items-start justify-between gap-2 bg-[#f5f5f5] rounded-lg px-3 py-2.5", children: [_jsxs("div", { className: "flex items-start gap-2 flex-1 min-w-0", children: [_jsx(Icon, { icon: "info-circle-o", size: 18, className: "shrink-0 mt-0.5 text-gray-900" }), _jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [_jsx("span", { className: "text-sm font-semibold text-gray-900", children: t("description") }), _jsx("p", { className: "text-sm text-gray-400 truncate", children: (currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) || t("no_description") })] })] }), permissions.updateGroupDescription && (_jsx(Icon, { icon: "edit-o", size: 16, className: "shrink-0 cursor-pointer text-gray-500", onClick: startEditDescription }))] })) }), _jsxs("div", { className: "flex flex-col gap-1 bg-[#f5f5f5] mx-4 rounded-lg overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between px-3 py-3", children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "bell-o", size: 18 }), t("notification")] }), _jsx(Switch, { checked: notifyEnabled, onChange: handleToggleNotification, loading: isTogglingNotification })] }), (config === null || config === void 0 ? void 0 : config.showAllowSendMessage) && (_jsxs("div", { className: "flex items-center justify-between px-3 py-3", children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "user-check-o", size: 18 }), t("allow_send_message")] }), _jsx(Switch, { checked: allowSendMessage, onChange: handleToggleSendMessage, loading: isTogglingSendMessage })] })), isAdminOrOwner && (config === null || config === void 0 ? void 0 : config.showMutedChatList) && (_jsxs("button", { type: "button", className: "flex items-center justify-between px-3 py-3 text-left", onClick: () => setActiveRow("muted-chat-list"), children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "bell-off-o", size: 18 }), t("muted_chat_list")] }), _jsx(Icon, { icon: "angle-right-o", size: 16, className: "text-gray-400" })] })), _jsxs("button", { type: "button", className: "flex items-center justify-between px-3 py-3 text-left", onClick: () => setActiveRow("block-list"), children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "user-del-o", size: 18 }), t("block_list")] }), _jsx(Icon, { icon: "angle-right-o", size: 16, className: "text-gray-400" })] })] }), permissions.configGroupPermission && (_jsxs("div", { className: "flex flex-col gap-1 bg-[#f5f5f5] mx-4 mt-3 rounded-lg overflow-hidden", children: [_jsxs("button", { type: "button", className: "flex items-center justify-between px-3 py-3 text-left", onClick: () => setActiveRow("member-permission"), children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "shield-o", size: 18 }), t("member_permission_settings")] }), _jsx(Icon, { icon: "angle-right-o", size: 16, className: "text-gray-400" })] }), _jsxs("button", { type: "button", className: "flex items-center justify-between px-3 py-3 text-left", onClick: () => setActiveRow("admin-permission"), children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "shield-done-o", size: 18 }), t("admin_permission_settings")] }), _jsx(Icon, { icon: "angle-right-o", size: 16, className: "text-gray-400" })] })] })), _jsx("div", { className: "mx-4 mt-3 rounded-lg overflow-hidden bg-[#f5f5f5]", children: _jsxs("button", { type: "button", className: "w-full flex items-center gap-3 px-3 py-3 text-left text-sm text-gray-400 cursor-not-allowed", disabled: true, title: t("invite_via_link_pending"), children: [_jsx(Icon, { icon: "link-alt-o", size: 18 }), t("invite_via_link")] }) }), _jsxs("div", { className: "flex flex-col gap-1 bg-[#f5f5f5] mx-4 mt-3 mb-4 rounded-lg overflow-hidden", children: [_jsxs("button", { type: "button", className: "flex items-center gap-3 px-3 py-3 text-left text-sm text-red-500", onClick: () => setConfirmAction("delete"), children: [_jsx(Icon, { icon: "trash-o", size: 18 }), t("delete_conversation")] }), _jsxs("button", { type: "button", className: "flex items-center gap-3 px-3 py-3 text-left text-sm text-red-500", onClick: () => setConfirmAction("leave"), children: [_jsx(Icon, { icon: "logout-o", size: 18 }), t("leave_group")] }), isAdminOrOwner && (_jsxs("button", { type: "button", className: "flex items-center gap-3 px-3 py-3 text-left text-sm text-red-500", onClick: () => setConfirmAction("disband"), children: [_jsx(Icon, { icon: "user-del-o", size: 18 }), t("disband_group")] }))] })] }), _jsx(Modal, { centered: true, open: confirmAction === "leave", onOk: handleConfirmLeave, onCancel: () => setConfirmAction(null), 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: confirmAction === "disband", onOk: handleConfirmDisband, onCancel: () => setConfirmAction(null), title: t("disband_group_confirm_title"), okText: t("disband_group"), cancelText: t("cancel"), okType: "danger", confirmLoading: isDismissing, getContainer: false, children: _jsx("p", { children: t("disband_group_confirm_message") }) }), _jsx(Modal, { centered: true, open: confirmAction === "delete", onOk: handleConfirmDelete, onCancel: () => setConfirmAction(null), title: t("delete_conversation_confirm_title"), okText: t("delete_conversation"), cancelText: t("cancel"), okType: "danger", confirmLoading: isDeleting, getContainer: false, children: _jsx("p", { children: t("delete_conversation_confirm_message") }) }), _jsx(MemberPermissionPanel, { open: activeRow === "member-permission", groupID: groupID, onClose: () => setActiveRow(null) }), _jsx(AdminPermissionModal, { open: activeRow === "admin-permission", groupID: groupID, onClose: () => setActiveRow(null), inline: true }), (activeRow === "muted-chat-list" || activeRow === "block-list") && (_jsx(Modal, { centered: true, open: true, footer: null, onCancel: () => setActiveRow(null), title: t(activeRow === "muted-chat-list" ? "muted_chat_list" : "block_list"), getContainer: false, children: _jsx("p", { className: "text-sm text-gray-500", children: t("feature_coming_soon") }) }))] }));
|
|
155
|
+
};
|
|
156
|
+
export default GroupThreadInfo;
|
|
@@ -15,7 +15,7 @@ const SupporterItem = ({ supporter, onClick, isCurrentUser, }) => {
|
|
|
15
15
|
var _a;
|
|
16
16
|
const { t } = useTranslation();
|
|
17
17
|
const isOnline = supporter.status === "ONLINE";
|
|
18
|
-
return (_jsxs("div", { role: "option", tabIndex: 0, className: "flex items-center gap-3 px-3 py-2 rounded-md transition-colors cursor-pointer hover:bg-
|
|
18
|
+
return (_jsxs("div", { role: "option", tabIndex: 0, className: "flex items-center gap-3 px-3 py-2 rounded-md transition-colors cursor-pointer hover:bg-[#f5f5f5]", onClick: () => onClick(supporter), children: [_jsx(Badge, { dot: true, color: isOnline ? "#52c41a" : "#d9d9d9", offset: [-2, 24], children: _jsx(Avatar, { src: supporter.avatar, size: 32, children: ((_a = supporter.displayName) === null || _a === void 0 ? void 0 : _a.charAt(0)) || "A" }) }), _jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [_jsx("span", { className: "text-sm truncate", children: supporter.displayName }), isCurrentUser && (_jsx("span", { className: "text-xs text-blue-500 shrink-0", children: t("current_account") }))] }), _jsx("div", { className: "flex items-center gap-2 shrink-0", children: !!supporter.openSessionCount && supporter.openSessionCount > 0 && (_jsxs("span", { className: "flex items-center gap-0.5 bg-blue-500 text-white text-xs font-medium px-1.5 py-0.5 rounded-full", children: [_jsx(Icon, { icon: "chat-square-b", size: 11 }), supporter.openSessionCount] })) })] }));
|
|
19
19
|
};
|
|
20
20
|
const ManualAssignPopover = ({ sessionId, supporter, teamId: propTeamId, children, excludeCurrentUser = false, }) => {
|
|
21
21
|
var _a, _b;
|
|
@@ -94,7 +94,7 @@ const ManualAssignPopover = ({ sessionId, supporter, teamId: propTeamId, childre
|
|
|
94
94
|
};
|
|
95
95
|
const popoverContent = (_jsxs("div", { className: "w-64", children: [_jsxs("button", { type: "button", className: clsx("flex w-full items-center gap-3 rounded-md px-3 py-2 text-left text-sm transition-colors", isAutoAssignDisabled
|
|
96
96
|
? "cursor-not-allowed text-gray-400"
|
|
97
|
-
: "text-gray-700 hover:bg-
|
|
97
|
+
: "text-gray-700 hover:bg-[#f5f5f5]"), onClick: handleAutoAssign, disabled: isAutoAssignDisabled, children: [isAutoAssigning ? (_jsx(Spin, { size: "small" })) : (_jsx("span", { className: "text-blue-500", children: _jsx(Icon, { icon: "refresh-b", size: 20 }) })), _jsx("span", { children: t("manual_assign_button_auto_reassign") })] }), _jsx(Divider, { className: "my-2" }), _jsx("div", { className: "mb-2", children: _jsx(Input, { autoFocus: true, placeholder: t("manual_assign_search_placeholder"), value: searchText, onChange: (e) => setSearchText(e.target.value), prefix: _jsx(Icon, { icon: "search-o", size: 16, className: "text-gray-400" }), className: "rounded-lg border-gray-300 focus-within:border-chat-focus focus-within:shadow-chat-focus-ring", allowClear: true }) }), _jsx("div", { className: "max-h-72 overflow-y-auto", role: "listbox", children: isLoading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Spin, {}) })) : supporters && supporters.length > 0 ? (_jsx("div", { className: clsx("flex flex-col transition-opacity duration-200", isFetching && "opacity-50 pointer-events-none"), children: [...supporters]
|
|
98
98
|
.filter((item) => item.memberId !== (supporter === null || supporter === void 0 ? void 0 : supporter.id))
|
|
99
99
|
.filter((item) => !excludeCurrentUser || item.memberId !== authUserID)
|
|
100
100
|
.sort((supporterA, supporterB) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionSection.d.ts","sourceRoot":"","sources":["../../../src/components/thread/SessionSection.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqB/D,eAAO,MAAM,iBAAiB,GAAI,wBAG/B;IACD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,4CAkNA,CAAC;AAiDF,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,cAAc,GAAI,yBAAyB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"SessionSection.d.ts","sourceRoot":"","sources":["../../../src/components/thread/SessionSection.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqB/D,eAAO,MAAM,iBAAiB,GAAI,wBAG/B;IACD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,4CAkNA,CAAC;AAiDF,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,cAAc,GAAI,yBAAyB,mBAAmB,4CAqCnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useDebounce } from "ahooks";
|
|
3
3
|
import { Icon } from "../../components/icon";
|
|
4
4
|
import { Button, Select, Spin, Tag, Input, message, Avatar } from "antd";
|
|
5
5
|
import ManualAssignPopover from "./ManualAssignPopover";
|
|
@@ -133,16 +133,10 @@ const ClosedSessionItem = ({ session, expandedSessionId, onToggleExpand, }) => {
|
|
|
133
133
|
};
|
|
134
134
|
const SessionSection = ({ sessions, isLoading }) => {
|
|
135
135
|
const { t } = useTranslation("common");
|
|
136
|
-
const [isOpen, { toggle }] = useBoolean(true);
|
|
137
136
|
const [expandedSessionId, setExpandedSessionId] = useState(null);
|
|
138
137
|
const handleToggleExpand = (sessionId) => {
|
|
139
138
|
setExpandedSessionId((prevId) => (prevId === sessionId ? null : sessionId));
|
|
140
139
|
};
|
|
141
|
-
|
|
142
|
-
if (!isOpen) {
|
|
143
|
-
setExpandedSessionId(null);
|
|
144
|
-
}
|
|
145
|
-
}, [isOpen]);
|
|
146
|
-
return (_jsxs("div", { className: "flex flex-col border-b", children: [_jsxs("div", { role: "button", onClick: toggle, className: "flex items-center justify-between px-4 py-2 rounded-md hover:bg-gray-100 sticky top-0 bg-white z-10", children: [_jsx("h3", { className: "font-bold text-gray-500 text-xs tracking-wider", children: t("sessions_heading") }), _jsx(Icon, { icon: isOpen ? "angle-up-o" : "angle-down-o", size: 18 })] }), isOpen && (_jsx("div", { className: "px-4 pt-2 pb-4", children: isLoading ? (_jsx("div", { className: "text-center mt-4", children: _jsx(Spin, {}) })) : (_jsx("div", { className: "flex flex-col gap-1", children: sessions.map((session) => (_jsx(ClosedSessionItem, { session: session, expandedSessionId: expandedSessionId, onToggleExpand: handleToggleExpand }, session.id))) })) }))] }));
|
|
140
|
+
return (_jsxs("div", { className: "flex flex-col border-b", children: [_jsx("div", { className: "flex items-center justify-between px-4 py-2 sticky top-0 bg-white z-10", children: _jsx("h3", { className: "font-bold text-gray-500 text-xs tracking-wider", children: t("sessions_heading") }) }), _jsx("div", { className: "px-4 pt-2 pb-4", children: isLoading ? (_jsx("div", { className: "text-center mt-4", children: _jsx(Spin, {}) })) : (_jsx("div", { className: "flex flex-col gap-1", children: sessions.map((session) => (_jsx(ClosedSessionItem, { session: session, expandedSessionId: expandedSessionId, onToggleExpand: handleToggleExpand }, session.id))) })) })] }));
|
|
147
141
|
};
|
|
148
142
|
export default SessionSection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SingleThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/SingleThreadInfo.tsx"],"names":[],"mappings":"AAYA,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,aAAa,qBAAqB,mDAmJ3D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Avatar, Modal, Switch, message } from "antd";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import { MessageReceiveOptType } from "@droppii-org/wasm-client-sdk";
|
|
6
|
+
import { Icon } from "../../components/icon";
|
|
7
|
+
import useConversationStore from "../../store/conversation";
|
|
8
|
+
import { useConversationDisplayData } from "../../hooks/conversation/useConversation";
|
|
9
|
+
import { useIsUserBlocked, useBlockUser } from "../../hooks/session/useBlockUser";
|
|
10
|
+
import { useDeleteConversation } from "../../hooks/session/useDeleteConversation";
|
|
11
|
+
import { useToggleConversationNotification } from "../../hooks/session/useToggleConversationNotification";
|
|
12
|
+
import { PeerType } from "../../types/conversation";
|
|
13
|
+
const SingleThreadInfo = ({ onClose }) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const conversationData = useConversationStore((state) => state.conversationData);
|
|
17
|
+
const { avatar, displayName } = useConversationDisplayData(conversationData);
|
|
18
|
+
const conversationID = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "";
|
|
19
|
+
const peerUserID = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.userID) || "";
|
|
20
|
+
const isBot = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.peerType) === PeerType.BOT;
|
|
21
|
+
const [confirmDelete, setConfirmDelete] = useState(false);
|
|
22
|
+
const [notifyEnabled, setNotifyEnabled] = useState((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
23
|
+
const { isBlocked } = useIsUserBlocked(peerUserID);
|
|
24
|
+
const { mutate: toggleBlock, isPending: isTogglingBlock } = useBlockUser();
|
|
25
|
+
const { mutate: toggleNotification, isPending: isTogglingNotification } = useToggleConversationNotification();
|
|
26
|
+
const { mutateAsync: deleteConversation, isPending: isDeleting } = useDeleteConversation();
|
|
27
|
+
const handleToggleNotification = (checked) => {
|
|
28
|
+
if (!conversationID)
|
|
29
|
+
return;
|
|
30
|
+
const previous = notifyEnabled;
|
|
31
|
+
setNotifyEnabled(checked);
|
|
32
|
+
toggleNotification({ conversationID, notify: checked }, {
|
|
33
|
+
onError: () => {
|
|
34
|
+
setNotifyEnabled(previous);
|
|
35
|
+
message.error(t("update_group_info_failed"));
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
const handleToggleBlock = () => {
|
|
40
|
+
if (!peerUserID)
|
|
41
|
+
return;
|
|
42
|
+
toggleBlock({ userID: peerUserID, block: !isBlocked }, {
|
|
43
|
+
onSuccess: () => {
|
|
44
|
+
message.success(t(isBlocked ? "unblock_user_success" : "block_user_success"));
|
|
45
|
+
},
|
|
46
|
+
onError: () => message.error(t("block_user_failed")),
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const handleConfirmDelete = async () => {
|
|
50
|
+
var _a, _b;
|
|
51
|
+
if (!conversationID)
|
|
52
|
+
return;
|
|
53
|
+
try {
|
|
54
|
+
await deleteConversation({ conversationID });
|
|
55
|
+
message.success(t("delete_conversation_success"));
|
|
56
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
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("delete_conversation_failed"));
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
setConfirmDelete(false);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
if (!conversationID) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return (_jsxs("div", { className: "h-full w-[330px] bg-white shadow-md flex flex-col relative", 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("thread_info_title") }), _jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 rounded-full text-gray-500 hover:bg-gray-100", onClick: onClose, children: _jsx(Icon, { icon: "close-o", size: 20 }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-4", children: [_jsx(Avatar, { src: avatar, size: 56, className: "shrink-0", 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-1 min-w-0 flex items-center gap-2", children: [_jsx("p", { className: "text-base font-medium truncate", children: displayName }), isBot && (_jsx("span", { className: "shrink-0 rounded px-1.5 py-0.5 text-xs font-semibold bg-orange-50 text-orange-500", children: t("bot_tag") }))] })] }), _jsx("div", { className: "bg-[#f5f5f5] mx-4 rounded-lg overflow-hidden", children: _jsxs("div", { className: "flex items-center justify-between px-3 py-3", children: [_jsxs("span", { className: "flex items-center gap-3 text-sm", children: [_jsx(Icon, { icon: "bell-o", size: 18 }), t("notification")] }), _jsx(Switch, { checked: notifyEnabled, onChange: handleToggleNotification, loading: isTogglingNotification })] }) }), _jsx("div", { className: "bg-[#f5f5f5] mx-4 mt-3 rounded-lg overflow-hidden", children: _jsxs("button", { type: "button", className: "flex items-center gap-3 px-3 py-3 text-left text-sm w-full", onClick: handleToggleBlock, disabled: isTogglingBlock, children: [_jsx(Icon, { icon: "user-del-o", size: 18 }), t(isBlocked ? "unblock_user" : "block_user")] }) }), _jsx("div", { className: "flex flex-col gap-1 bg-[#f5f5f5] mx-4 mt-3 rounded-lg overflow-hidden", children: _jsxs("button", { type: "button", className: "flex items-center gap-3 px-3 py-3 text-left text-sm text-red-500", onClick: () => setConfirmDelete(true), children: [_jsx(Icon, { icon: "trash-o", size: 18 }), t("delete_conversation")] }) })] }), _jsx(Modal, { centered: true, open: confirmDelete, onOk: handleConfirmDelete, onCancel: () => setConfirmDelete(false), title: t("delete_conversation_confirm_title"), okText: t("delete_conversation"), cancelText: t("cancel"), okType: "danger", confirmLoading: isDeleting, getContainer: false, children: _jsx("p", { children: t("delete_conversation_confirm_message") }) })] }));
|
|
69
|
+
};
|
|
70
|
+
export default SingleThreadInfo;
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { GroupThreadInfoConfig } from "./GroupThreadInfo";
|
|
2
|
+
export interface ThreadInfoProps {
|
|
3
|
+
isOpen?: boolean;
|
|
4
|
+
onClose?: () => void;
|
|
5
|
+
groupConfig?: GroupThreadInfoConfig;
|
|
6
|
+
}
|
|
7
|
+
declare const ThreadInfo: ({ isOpen, onClose, groupConfig }: ThreadInfoProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
2
8
|
export default ThreadInfo;
|
|
3
9
|
//# sourceMappingURL=ThreadInfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/ThreadInfo.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/ThreadInfo.tsx"],"names":[],"mappings":"AAGA,OAAwB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAO3E,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAED,QAAA,MAAM,UAAU,GAAI,kCAAyC,eAAe,mDAsD3E,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -2,16 +2,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import useConversationStore from "../../store/conversation";
|
|
3
3
|
import UserSection from "./UserSection";
|
|
4
4
|
import SessionSection, { SessionDetailCard } from "./SessionSection";
|
|
5
|
+
import GroupThreadInfo from "./GroupThreadInfo";
|
|
6
|
+
import SingleThreadInfo from "./SingleThreadInfo";
|
|
5
7
|
import { useGetListSessionByConversation } from "../../hooks/session/useGetListSessionByConversation";
|
|
6
8
|
import { useMemo } from "react";
|
|
7
9
|
import { PAGE_SIZE } from "../../constants";
|
|
8
|
-
|
|
10
|
+
import { PeerType } from "../../types/conversation";
|
|
11
|
+
const ThreadInfo = ({ isOpen = true, onClose, groupConfig }) => {
|
|
9
12
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
10
13
|
const conversationId = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "";
|
|
14
|
+
const isGroup = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.peerType) === PeerType.GROUP;
|
|
15
|
+
const isBot = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.peerType) === PeerType.BOT;
|
|
11
16
|
const { data: sessions, isLoading } = useGetListSessionByConversation({
|
|
12
17
|
conversationId,
|
|
13
18
|
page: 1,
|
|
14
19
|
pageSize: PAGE_SIZE.large,
|
|
20
|
+
enabled: isBot,
|
|
15
21
|
});
|
|
16
22
|
const { closedSessions, activeSession } = useMemo(() => {
|
|
17
23
|
if (!sessions)
|
|
@@ -23,6 +29,12 @@ const ThreadInfo = () => {
|
|
|
23
29
|
if (!conversationId) {
|
|
24
30
|
return null;
|
|
25
31
|
}
|
|
26
|
-
|
|
32
|
+
if (isGroup) {
|
|
33
|
+
return isOpen ? _jsx(GroupThreadInfo, { onClose: onClose, config: groupConfig }) : null;
|
|
34
|
+
}
|
|
35
|
+
if (!isOpen && !isBot) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return (_jsxs("div", { className: "h-full flex flex-row", children: [isOpen && _jsx(SingleThreadInfo, { onClose: onClose }), isBot && (_jsxs("div", { className: "h-full w-[330px] bg-white shadow-md flex flex-col relative", children: [_jsxs("div", { className: `flex-grow overflow-y-auto ${activeSession ? "pb-60" : ""}`, children: [_jsx(UserSection, {}), _jsx(SessionSection, { sessions: closedSessions, isLoading: isLoading })] }), activeSession && (_jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 z-20 bg-white backdrop-blur-sm", children: _jsx(SessionDetailCard, { session: activeSession, isActive: true }) }))] }))] }));
|
|
27
39
|
};
|
|
28
40
|
export default ThreadInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../src/constants/images.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"images.d.ts","sourceRoot":"","sources":["../../src/constants/images.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,MAAM;;;;;CAKlB,CAAC"}
|
package/dist/constants/images.js
CHANGED
|
@@ -2,8 +2,10 @@ const conversationBg = new URL("../assets/images/conversationBg.png", import.met
|
|
|
2
2
|
const imageFailed = new URL("../assets/images/imageFailed.png", import.meta.url)
|
|
3
3
|
.href;
|
|
4
4
|
const emptyResources = new URL("../assets/images/emptyResources.png", import.meta.url).href;
|
|
5
|
+
const muteNotificationWarning = new URL("../assets/images/muteNotificationWarning.png", import.meta.url).href;
|
|
5
6
|
export const images = {
|
|
6
7
|
conversationBg,
|
|
7
8
|
imageFailed,
|
|
8
9
|
emptyResources,
|
|
10
|
+
muteNotificationWarning,
|
|
9
11
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAI3D,eAAO,MAAM,uBAAuB,YAAY,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -7,3 +7,6 @@ export const PAGE_SIZE = {
|
|
|
7
7
|
};
|
|
8
8
|
export const MSG_ITEM_PREFIX = "msg-item-";
|
|
9
9
|
export const MSG_ITEM_CONTENT_PREFIX = "msg-item-content-";
|
|
10
|
+
// antd Switch defaults to antd's own purple — override locally with the
|
|
11
|
+
// theme's primary blue (primary-400) to match the permission-config mockups.
|
|
12
|
+
export const PERMISSION_SWITCH_COLOR = "#1B3FE4";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGlobalEvent.d.ts","sourceRoot":"","sources":["../../../src/hooks/global/useGlobalEvent.ts"],"names":[],"mappings":"AAuCA,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"useGlobalEvent.d.ts","sourceRoot":"","sources":["../../../src/hooks/global/useGlobalEvent.ts"],"names":[],"mappings":"AAuCA,eAAO,MAAM,cAAc,YAqY1B,CAAC"}
|
|
@@ -201,6 +201,21 @@ export const useGlobalEvent = () => {
|
|
|
201
201
|
void refreshCurrentGroupState();
|
|
202
202
|
emitter.emit("GROUP_MEMBERS_CHANGED");
|
|
203
203
|
};
|
|
204
|
+
const groupInfoChangedHandler = () => {
|
|
205
|
+
void refreshCurrentGroupState();
|
|
206
|
+
};
|
|
207
|
+
const groupDismissedHandler = ({ data }) => {
|
|
208
|
+
const currentConversation = useConversationStore.getState().currentConversation;
|
|
209
|
+
if ((currentConversation === null || currentConversation === void 0 ? void 0 : currentConversation.groupID) === data.groupID) {
|
|
210
|
+
useConversationStore.getState().clearSelectedConversation();
|
|
211
|
+
}
|
|
212
|
+
useConversationStore.setState((state) => ({
|
|
213
|
+
conversationList: state.conversationList.filter((conversation) => conversation.groupID !== data.groupID),
|
|
214
|
+
}));
|
|
215
|
+
};
|
|
216
|
+
const blackListChangedHandler = () => {
|
|
217
|
+
emitter.emit("BLACK_LIST_CHANGED");
|
|
218
|
+
};
|
|
204
219
|
// createGroup()'s own response resolving is not enough to guarantee the
|
|
205
220
|
// new group shows up in conversationList — OnConversationChanged/
|
|
206
221
|
// OnNewConversation for it can arrive after an unspecified delay (per
|
|
@@ -234,6 +249,12 @@ export const useGlobalEvent = () => {
|
|
|
234
249
|
DChatSDK.on(CbEvents.OnGroupMemberAdded, groupMemberChangedHandler);
|
|
235
250
|
DChatSDK.on(CbEvents.OnGroupMemberDeleted, groupMemberChangedHandler);
|
|
236
251
|
DChatSDK.on(CbEvents.OnJoinedGroupAdded, joinedGroupAddedHandler);
|
|
252
|
+
// group info
|
|
253
|
+
DChatSDK.on(CbEvents.OnGroupInfoChanged, groupInfoChangedHandler);
|
|
254
|
+
DChatSDK.on(CbEvents.OnGroupDismissed, groupDismissedHandler);
|
|
255
|
+
// black list
|
|
256
|
+
DChatSDK.on(CbEvents.OnBlackAdded, blackListChangedHandler);
|
|
257
|
+
DChatSDK.on(CbEvents.OnBlackDeleted, blackListChangedHandler);
|
|
237
258
|
//busines notification
|
|
238
259
|
DChatSDK.on(CbEvents.OnRecvCustomBusinessMessage, businessNotificationHandler);
|
|
239
260
|
};
|
|
@@ -260,6 +281,12 @@ export const useGlobalEvent = () => {
|
|
|
260
281
|
DChatSDK.off(CbEvents.OnGroupMemberAdded, groupMemberChangedHandler);
|
|
261
282
|
DChatSDK.off(CbEvents.OnGroupMemberDeleted, groupMemberChangedHandler);
|
|
262
283
|
DChatSDK.off(CbEvents.OnJoinedGroupAdded, joinedGroupAddedHandler);
|
|
284
|
+
// group info
|
|
285
|
+
DChatSDK.off(CbEvents.OnGroupInfoChanged, groupInfoChangedHandler);
|
|
286
|
+
DChatSDK.off(CbEvents.OnGroupDismissed, groupDismissedHandler);
|
|
287
|
+
// black list
|
|
288
|
+
DChatSDK.off(CbEvents.OnBlackAdded, blackListChangedHandler);
|
|
289
|
+
DChatSDK.off(CbEvents.OnBlackDeleted, blackListChangedHandler);
|
|
263
290
|
//busines notification
|
|
264
291
|
DChatSDK.off(CbEvents.OnRecvCustomBusinessMessage, businessNotificationHandler);
|
|
265
292
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface AddGroupMemberParams {
|
|
2
|
+
groupID: string;
|
|
3
|
+
userIDList: string[];
|
|
4
|
+
}
|
|
5
|
+
export declare const useAddGroupMember: () => import("@tanstack/react-query").UseMutationResult<unknown, Error, AddGroupMemberParams, unknown>;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=useAddGroupMember.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAddGroupMember.d.ts","sourceRoot":"","sources":["../../../src/hooks/group/useAddGroupMember.ts"],"names":[],"mappings":"AAKA,UAAU,oBAAoB;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,eAAO,MAAM,iBAAiB,wGAgB7B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMutation } from "@tanstack/react-query";
|
|
3
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
4
|
+
export const useAddGroupMember = () => {
|
|
5
|
+
return useMutation({
|
|
6
|
+
mutationFn: async ({ groupID, userIDList }) => {
|
|
7
|
+
console.log("[AddGroupMember] inviteUserToGroup", { groupID, userIDList });
|
|
8
|
+
const { data } = await DChatSDK.inviteUserToGroup({
|
|
9
|
+
groupID,
|
|
10
|
+
userIDList,
|
|
11
|
+
reason: "",
|
|
12
|
+
});
|
|
13
|
+
console.log("[AddGroupMember] inviteUserToGroup success", { groupID, userIDList, data });
|
|
14
|
+
return data;
|
|
15
|
+
},
|
|
16
|
+
onError: (error, { groupID, userIDList }) => {
|
|
17
|
+
console.error("[AddGroupMember] inviteUserToGroup failed", { groupID, userIDList, error });
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDismissGroup.d.ts","sourceRoot":"","sources":["../../../src/hooks/group/useDismissGroup.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,eAAe;aAEmB,MAAM;WAYpD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMutation } from "@tanstack/react-query";
|
|
3
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
4
|
+
import useConversationStore from "../../store/conversation";
|
|
5
|
+
import useSessionStore from "../../store/session";
|
|
6
|
+
import { SessionStatus } from "../../types/chat";
|
|
7
|
+
import emitter from "../../utils/events";
|
|
8
|
+
export const useDismissGroup = () => {
|
|
9
|
+
return useMutation({
|
|
10
|
+
mutationFn: async ({ groupID }) => {
|
|
11
|
+
const { data } = await DChatSDK.dismissGroup(groupID);
|
|
12
|
+
emitter.emit("GROUP_MEMBERS_CHANGED");
|
|
13
|
+
return data;
|
|
14
|
+
},
|
|
15
|
+
onSuccess: () => {
|
|
16
|
+
useConversationStore.getState().clearSelectedConversation();
|
|
17
|
+
useSessionStore
|
|
18
|
+
.getState()
|
|
19
|
+
.setFilterSummary({ status: SessionStatus.IN_PROCESS });
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
};
|
|
@@ -6,5 +6,8 @@ export interface EligibleAccountItem {
|
|
|
6
6
|
export declare const useEligibleAccounts: (search: string, enabled?: boolean) => {
|
|
7
7
|
accounts: EligibleAccountItem[];
|
|
8
8
|
isLoading: boolean;
|
|
9
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<import("@tanstack/react-query").InfiniteData<import("../../types/dto").BaseResponse<import("../../types/dto").IGroupCandidateResponse[]>, unknown>, Error>>;
|
|
10
|
+
hasNextPage: boolean;
|
|
11
|
+
isFetchingNextPage: boolean;
|
|
9
12
|
};
|
|
10
13
|
//# sourceMappingURL=useEligibleAccounts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEligibleAccounts.d.ts","sourceRoot":"","sources":["../../../src/hooks/group/useEligibleAccounts.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAKD,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,EAAE,iBAAc
|
|
1
|
+
{"version":3,"file":"useEligibleAccounts.d.ts","sourceRoot":"","sources":["../../../src/hooks/group/useEligibleAccounts.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAKD,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,EAAE,iBAAc;;;;;;CAwBjE,CAAC"}
|
|
@@ -4,20 +4,20 @@ import { useGetGroupCandidates } from "./useGetGroupCandidates";
|
|
|
4
4
|
// only eligible (active) accounts and supports searchTerm filtering, so no
|
|
5
5
|
// client-side active/inactive filtering is needed here (Q3 resolved).
|
|
6
6
|
export const useEligibleAccounts = (search, enabled = true) => {
|
|
7
|
-
const {
|
|
7
|
+
const { candidates, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = useGetGroupCandidates({
|
|
8
8
|
searchTerm: search.trim(),
|
|
9
9
|
enabled,
|
|
10
10
|
});
|
|
11
|
-
const accounts = useMemo(() => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
avatar: candidate.avatar,
|
|
17
|
-
}));
|
|
18
|
-
}, [data]);
|
|
11
|
+
const accounts = useMemo(() => candidates.map((candidate) => ({
|
|
12
|
+
userID: candidate.id,
|
|
13
|
+
displayName: candidate.fullName,
|
|
14
|
+
avatar: candidate.avatar,
|
|
15
|
+
})), [candidates]);
|
|
19
16
|
return {
|
|
20
17
|
accounts,
|
|
21
18
|
isLoading,
|
|
19
|
+
fetchNextPage,
|
|
20
|
+
hasNextPage,
|
|
21
|
+
isFetchingNextPage,
|
|
22
22
|
};
|
|
23
23
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EligibleAccountItem } from "./useEligibleAccounts";
|
|
2
|
+
export declare const useEligibleAccountsForGroup: (search: string, existingMemberIDs: string[], enabled?: boolean) => {
|
|
3
|
+
accounts: EligibleAccountItem[];
|
|
4
|
+
isLoading: boolean;
|
|
5
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<import("@tanstack/react-query").InfiniteData<import("../../types/dto").BaseResponse<import("../../types/dto").IGroupCandidateResponse[]>, unknown>, Error>>;
|
|
6
|
+
hasNextPage: boolean;
|
|
7
|
+
isFetchingNextPage: boolean;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useEligibleAccountsForGroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEligibleAccountsForGroup.d.ts","sourceRoot":"","sources":["../../../src/hooks/group/useEligibleAccountsForGroup.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAKjE,eAAO,MAAM,2BAA2B,GACtC,QAAQ,MAAM,EACd,mBAAmB,MAAM,EAAE,EAC3B,iBAAc;;;;;;CAgCf,CAAC"}
|