@droppii-org/chat-sdk 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/conversation/ConversationByGroupItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationByGroupItem.js +2 -3
- package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +3 -1
- package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
- package/dist/components/conversation/DeskConversationList.js +1 -1
- package/dist/components/conversation-detail/PinnedMessagesPanel.d.ts.map +1 -1
- package/dist/components/conversation-detail/PinnedMessagesPanel.js +1 -1
- package/dist/components/conversation-detail/ThreadProfilePanel.d.ts.map +1 -1
- package/dist/components/conversation-detail/ThreadProfilePanel.js +1 -1
- package/dist/components/conversation-detail/bot/BotMenuSheet.d.ts.map +1 -1
- package/dist/components/conversation-detail/bot/BotMenuSheet.js +1 -1
- package/dist/components/group/AddMemberModal.d.ts.map +1 -1
- package/dist/components/group/AddMemberModal.js +1 -1
- package/dist/components/group/AdminPermissionModal.d.ts +7 -1
- package/dist/components/group/AdminPermissionModal.d.ts.map +1 -1
- package/dist/components/group/AdminPermissionModal.js +88 -33
- package/dist/components/group/CreateGroupForm.d.ts.map +1 -1
- package/dist/components/group/CreateGroupForm.js +44 -10
- package/dist/components/group/GroupCompositeAvatar.d.ts +11 -0
- package/dist/components/group/GroupCompositeAvatar.d.ts.map +1 -0
- package/dist/components/group/GroupCompositeAvatar.js +52 -0
- package/dist/components/media-collection/index.d.ts.map +1 -1
- package/dist/components/media-collection/index.js +3 -3
- package/dist/components/media-resources/MediaResourcePanel.d.ts.map +1 -1
- package/dist/components/media-resources/MediaResourcePanel.js +1 -1
- package/dist/components/message/GroupMembersDrawer.d.ts.map +1 -1
- package/dist/components/message/GroupMembersDrawer.js +57 -29
- package/dist/components/message/MessageHeader.d.ts.map +1 -1
- package/dist/components/message/MessageHeader.js +17 -5
- package/dist/components/message/item/GroupNotificationMessage.d.ts +7 -0
- package/dist/components/message/item/GroupNotificationMessage.d.ts.map +1 -0
- package/dist/components/message/item/GroupNotificationMessage.js +13 -0
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +10 -2
- package/dist/components/message/item/renderMessageContent.d.ts.map +1 -1
- package/dist/components/message/item/renderMessageContent.js +18 -0
- package/dist/components/search-conversation/SearchDrawer.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchDrawer.js +1 -1
- package/dist/components/thread/GroupThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/GroupThreadInfo.js +36 -5
- package/dist/components/thread/SingleThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/SingleThreadInfo.js +1 -1
- package/dist/components/thread/ThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/ThreadInfo.js +2 -1
- package/dist/components/video-player/VideoPlayerModal.d.ts.map +1 -1
- package/dist/components/video-player/VideoPlayerModal.js +1 -1
- package/dist/hooks/common/useUploadFile.d.ts +3 -0
- package/dist/hooks/common/useUploadFile.d.ts.map +1 -0
- package/dist/hooks/common/useUploadFile.js +15 -0
- package/dist/hooks/group/useCreateGroup.d.ts.map +1 -1
- package/dist/hooks/group/useCreateGroup.js +4 -2
- package/dist/hooks/group/useGroupMembers.d.ts +3 -1
- package/dist/hooks/group/useGroupMembers.d.ts.map +1 -1
- package/dist/hooks/group/useGroupMembers.js +9 -0
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/useMessage.js +2 -1
- package/dist/locales/vi/common.json +1 -0
- package/dist/locales/vi/conversation-inbox.json +4 -2
- package/dist/services/routes.d.ts +3 -0
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +3 -0
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +10 -0
- package/dist/store/session.d.ts +13 -1
- package/dist/store/session.d.ts.map +1 -1
- package/dist/store/session.js +6 -2
- package/dist/styles/global.css +1 -1
- package/dist/types/dto.d.ts +11 -0
- package/dist/types/dto.d.ts.map +1 -1
- package/dist/utils/imCommon.d.ts +4 -0
- package/dist/utils/imCommon.d.ts.map +1 -1
- package/dist/utils/imCommon.js +16 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { GroupMemberRole } from "@droppii-org/wasm-client-sdk";
|
|
3
3
|
import { Avatar, Button, Drawer, Dropdown, Empty, Input, message, Modal, Spin } from "antd";
|
|
4
4
|
import { useEffect, useMemo, useState } from "react";
|
|
@@ -16,6 +16,7 @@ import { useKickGroupMember, useSetGroupMemberPermissions, useSetGroupMemberRole
|
|
|
16
16
|
import { Icon } from "../../components/icon";
|
|
17
17
|
import AddMemberModal from "../../components/group/AddMemberModal";
|
|
18
18
|
import AdminPermissionModal from "../../components/group/AdminPermissionModal";
|
|
19
|
+
import { isGroupConversation } from "../../utils/imCommon";
|
|
19
20
|
const getMemberDisplayName = (member) => {
|
|
20
21
|
return member.nickname || member.userID || "";
|
|
21
22
|
};
|
|
@@ -37,13 +38,20 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
37
38
|
const [isOpen, setIsOpen] = useState(false);
|
|
38
39
|
const [showLeaveConfirm, setShowLeaveConfirm] = useState(false);
|
|
39
40
|
const [showAddMember, setShowAddMember] = useState(false);
|
|
40
|
-
const [
|
|
41
|
+
const [adminPermissionMember, setAdminPermissionMember] = useState(null);
|
|
41
42
|
const [confirmMemberAction, setConfirmMemberAction] = useState(null);
|
|
42
43
|
const [search, setSearch] = useState("");
|
|
43
44
|
const debouncedSearch = useDebounce(search, { wait: 300 });
|
|
44
45
|
const authUserID = useAuthStore((state) => state.userID);
|
|
45
46
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
46
|
-
|
|
47
|
+
// Admin-management actions (assign/remove admin, transfer owner, kick,
|
|
48
|
+
// configure permissions) only make sense for a real group (peerType
|
|
49
|
+
// GROUP) — for a CX thread that merely uses a Group/WorkingGroup session
|
|
50
|
+
// under the hood, roleLevel/permissions reflect a technical role with no
|
|
51
|
+
// relation to who may manage "members", so those actions are hidden
|
|
52
|
+
// entirely rather than shown disabled.
|
|
53
|
+
const isRealGroup = isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
|
|
54
|
+
const { members, isLoading, error, refetch, patchMemberRole, patchMemberPermissions } = useGroupMembers(groupID);
|
|
47
55
|
const { results: searchResults, isSearching } = useSearchGroupMembers(groupID, debouncedSearch);
|
|
48
56
|
const { mutateAsync: leaveConversation, isPending: isLeaving } = useLeaveConversation();
|
|
49
57
|
const permissions = useGroupPermission(groupID);
|
|
@@ -79,14 +87,20 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
79
87
|
isAdmin: member.roleLevel === GroupMemberRole.Admin,
|
|
80
88
|
permissions,
|
|
81
89
|
isSendMessageDisabled: !permissions.includes(GROUP_PERMISSION_KEY.sendMessage),
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
roleLabel: isOwner
|
|
90
|
+
// Owner and Admin rows show a role label; plain Member rows show
|
|
91
|
+
// name only.
|
|
92
|
+
roleLabel: isOwner || member.roleLevel === GroupMemberRole.Admin
|
|
85
93
|
? getMemberRoleLabel({ member, customerUserID, t })
|
|
86
94
|
: "",
|
|
87
95
|
};
|
|
88
96
|
})
|
|
89
97
|
.sort((memberA, memberB) => {
|
|
98
|
+
// Group by role first (Owner > Admin > Member), then within each
|
|
99
|
+
// role group put "me" first, then the group owner, then by name.
|
|
100
|
+
const roleRank = (member) => member.isOwner ? 0 : member.isAdmin ? 1 : 2;
|
|
101
|
+
const rankDiff = roleRank(memberA) - roleRank(memberB);
|
|
102
|
+
if (rankDiff !== 0)
|
|
103
|
+
return rankDiff;
|
|
90
104
|
if (memberA.isCurrentUser !== memberB.isCurrentUser) {
|
|
91
105
|
return memberA.isCurrentUser ? -1 : 1;
|
|
92
106
|
}
|
|
@@ -163,16 +177,22 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
163
177
|
var _a, _b;
|
|
164
178
|
if (!groupID)
|
|
165
179
|
return;
|
|
180
|
+
const nextRoleLevel = member.isAdmin
|
|
181
|
+
? GroupMemberRole.Normal
|
|
182
|
+
: GroupMemberRole.Admin;
|
|
166
183
|
try {
|
|
167
184
|
await setMemberRole({
|
|
168
185
|
groupID,
|
|
169
186
|
userID: member.userID,
|
|
170
|
-
roleLevel:
|
|
187
|
+
roleLevel: nextRoleLevel,
|
|
171
188
|
});
|
|
172
189
|
message.success(member.isAdmin
|
|
173
190
|
? t("remove_from_admin_success")
|
|
174
191
|
: t("assign_as_admin_success"));
|
|
175
|
-
|
|
192
|
+
// Patch the role in place instead of refetching the whole list — a
|
|
193
|
+
// full refetch replaces every member's object identity and re-sorts,
|
|
194
|
+
// which visibly re-renders/reorders rows that didn't actually change.
|
|
195
|
+
patchMemberRole(member.userID, nextRoleLevel);
|
|
176
196
|
}
|
|
177
197
|
catch (error) {
|
|
178
198
|
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"));
|
|
@@ -229,22 +249,25 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
229
249
|
return (_jsx("div", { className: "flex flex-col", children: sortedMembers.map((member) => {
|
|
230
250
|
// Send message / Remove and block are not wired yet (no confirmed
|
|
231
251
|
// SDK flow for member-scoped block) — kept disabled per scope.
|
|
252
|
+
const leaveGroupItem = {
|
|
253
|
+
key: "leave-group",
|
|
254
|
+
label: t("leave_group"),
|
|
255
|
+
icon: _jsx(Icon, { icon: "logout-b", size: 16 }),
|
|
256
|
+
onClick: handleLeaveGroup,
|
|
257
|
+
danger: true,
|
|
258
|
+
};
|
|
232
259
|
const menuItems = member.isCurrentUser
|
|
233
|
-
?
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
onClick: handleLeaveGroup,
|
|
245
|
-
danger: true,
|
|
246
|
-
},
|
|
247
|
-
]
|
|
260
|
+
? isRealGroup
|
|
261
|
+
? [
|
|
262
|
+
{
|
|
263
|
+
key: "mute",
|
|
264
|
+
label: t("mute_member"),
|
|
265
|
+
icon: _jsx(Icon, { icon: "bell-off-b", size: 16 }),
|
|
266
|
+
disabled: true,
|
|
267
|
+
},
|
|
268
|
+
leaveGroupItem,
|
|
269
|
+
]
|
|
270
|
+
: [leaveGroupItem]
|
|
248
271
|
: [
|
|
249
272
|
{
|
|
250
273
|
key: "send-message",
|
|
@@ -275,7 +298,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
275
298
|
label: t("admin_permission_settings"),
|
|
276
299
|
icon: _jsx(Icon, { icon: "shield-o", size: 16 }),
|
|
277
300
|
disabled: !permissions.transferOwnership,
|
|
278
|
-
onClick: () =>
|
|
301
|
+
onClick: () => setAdminPermissionMember(member),
|
|
279
302
|
},
|
|
280
303
|
{
|
|
281
304
|
key: "remove-admin",
|
|
@@ -310,18 +333,23 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
310
333
|
disabled: true,
|
|
311
334
|
},
|
|
312
335
|
];
|
|
313
|
-
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));
|
|
336
|
+
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 }))] }), (isRealGroup || member.isCurrentUser) && (_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));
|
|
314
337
|
}) }));
|
|
315
338
|
};
|
|
316
|
-
return (_jsxs(
|
|
339
|
+
return (_jsxs("div", { className: "inline-flex shrink-0", 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: {
|
|
317
340
|
body: {
|
|
318
341
|
padding: 0,
|
|
319
342
|
height: "100%",
|
|
320
343
|
},
|
|
321
|
-
}, 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-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(
|
|
344
|
+
}, getContainer: false, forceRender: true, 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-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() })] }) }), groupID && (_jsx(AddMemberModal, { open: showAddMember, groupID: groupID, onClose: () => setShowAddMember(false) })), groupID && (_jsx(AdminPermissionModal, { open: Boolean(adminPermissionMember), groupID: groupID, onClose: () => setAdminPermissionMember(null), member: adminPermissionMember
|
|
345
|
+
? {
|
|
346
|
+
userID: adminPermissionMember.userID,
|
|
347
|
+
permissions: adminPermissionMember.permissions,
|
|
348
|
+
}
|
|
349
|
+
: undefined, onMemberPermissionsSaved: patchMemberPermissions })), _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, forceRender: true, 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, forceRender: true, children: _jsx("p", { children: t("remove_member_confirm_message", {
|
|
322
350
|
name: confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.member.nickname,
|
|
323
|
-
}) }) }), _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", {
|
|
351
|
+
}) }) }), _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, forceRender: true, children: _jsx("p", { children: t("transfer_owner_confirm_message", {
|
|
324
352
|
name: confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.member.nickname,
|
|
325
|
-
}) }) })
|
|
353
|
+
}) }) })] }));
|
|
326
354
|
};
|
|
327
355
|
export default GroupMembersDrawer;
|
|
@@ -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;AAQ/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,4CAyOpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -12,8 +12,9 @@ import SelectSession from "./SelectSession";
|
|
|
12
12
|
import { useUpdateSession } from "../../hooks/session/useUpdateSession";
|
|
13
13
|
import useAuthStore from "../../store/auth";
|
|
14
14
|
import SearchDrawer from "../../components/search-conversation/SearchDrawer";
|
|
15
|
-
import { isGroupSession } from "../../utils/imCommon";
|
|
15
|
+
import { isGroupSession, isGroupConversation } from "../../utils/imCommon";
|
|
16
16
|
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
17
|
+
import GroupCompositeAvatar from "../../components/group/GroupCompositeAvatar";
|
|
17
18
|
import GroupMembersDrawer from "./GroupMembersDrawer";
|
|
18
19
|
const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, }) => {
|
|
19
20
|
var _a, _b;
|
|
@@ -26,6 +27,20 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
|
|
|
26
27
|
const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
|
|
27
28
|
const { avatar, displayName } = useConversationDisplayData(conversationData);
|
|
28
29
|
const shouldShowMemberCount = isGroupSession(conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType);
|
|
30
|
+
// A "real" group (peerType GROUP) vs a CX support thread that happens to
|
|
31
|
+
// use a Group/WorkingGroup session under the hood (e.g. a multi-agent
|
|
32
|
+
// support conversation with several members) — only the former hides
|
|
33
|
+
// tag/status/Phiên hỗ trợ. permissions.viewMemberInformation (derived
|
|
34
|
+
// from the current user's own roleLevel in that Group/WorkingGroup
|
|
35
|
+
// session) is likewise only meaningful for a real group — for a CX
|
|
36
|
+
// thread it reflects a technical role that has nothing to do with who
|
|
37
|
+
// may view the member list, so it's bypassed there. The member list
|
|
38
|
+
// button itself still shows for both (shouldShowMemberCount).
|
|
39
|
+
const isRealGroup = isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
|
|
40
|
+
const canViewMemberList = shouldShowMemberCount &&
|
|
41
|
+
isJoined === true &&
|
|
42
|
+
isCrm &&
|
|
43
|
+
(!isRealGroup || permissions.viewMemberInformation);
|
|
29
44
|
const [currentSessionStatus, setCurrentSessionStatus] = useState(SessionStatus.UNASSIGNED);
|
|
30
45
|
const [currentSessionTag, setCurrentSessionTag] = useState(SessionTag.NONE);
|
|
31
46
|
const statusOptions = useMemo(() => {
|
|
@@ -129,9 +144,6 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
|
|
|
129
144
|
setCurrentSessionStatus(currentSession.status);
|
|
130
145
|
}
|
|
131
146
|
}, [currentSession]);
|
|
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, {}),
|
|
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 }) }))] })] }));
|
|
147
|
+
return (_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3 bg-white flex-wrap", children: [shouldShowMemberCount ? (_jsx(GroupCompositeAvatar, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, faceURL: avatar, ownerUserID: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.ownerUserID, groupName: displayName, size: 40, className: "min-w-10 min-h-10" })) : (_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 && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_tag"), options: tagOptions, value: currentSessionTag, onChange: (value) => handleUpdateSession(value, "tag", value === currentSessionTag), excludeOptions: [SessionTag.SLOW_PROCESSING, SessionTag.NONE] })), isCx && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_status"), options: statusOptions, value: currentSessionStatus, onChange: (value) => handleUpdateSession(value, "status", value === currentSessionStatus) })), _jsx(SearchDrawer, {}), canViewMemberList && (_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 }) }))] })] }));
|
|
136
148
|
};
|
|
137
149
|
export default MessageHeader;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MessageItem } from "@droppii-org/wasm-client-sdk";
|
|
2
|
+
interface GroupNotificationMessageItemProps {
|
|
3
|
+
message: MessageItem;
|
|
4
|
+
}
|
|
5
|
+
declare const GroupNotificationMessageItem: ({ message }: GroupNotificationMessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export default GroupNotificationMessageItem;
|
|
7
|
+
//# sourceMappingURL=GroupNotificationMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupNotificationMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/GroupNotificationMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAI3D,UAAU,iCAAiC;IACzC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,4BAA4B,GAAI,aAAa,iCAAiC,mDAiBnF,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { getGroupNotificationText } from "../../../utils/messageLog";
|
|
5
|
+
const GroupNotificationMessageItem = ({ message }) => {
|
|
6
|
+
var _a;
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
const text = getGroupNotificationText(message.contentType, (_a = message.notificationElem) === null || _a === void 0 ? void 0 : _a.detail, t);
|
|
9
|
+
if (!text)
|
|
10
|
+
return null;
|
|
11
|
+
return (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "rounded-full bg-gray-200 px-3 py-1.5 text-center text-[13px] font-normal text-gray-900", children: text }) }));
|
|
12
|
+
};
|
|
13
|
+
export default GroupNotificationMessageItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,8BAA8B,CAAC;AAkCtC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAoBD,QAAA,MAAM,WAAW,GAAI,qMAalB,gBAAgB,mDA8RlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -18,7 +18,8 @@ import MessageStatusIndicator from "./MessageStatusIndicator";
|
|
|
18
18
|
import { useSendMessage, isMediaResendable, } from "../../../hooks/message/useSendMessage";
|
|
19
19
|
import { Icon } from "../../../components/icon";
|
|
20
20
|
import SystemLogMessageItem from "./SystemLogMessage";
|
|
21
|
-
import
|
|
21
|
+
import GroupNotificationMessageItem from "./GroupNotificationMessage";
|
|
22
|
+
import { isGroupNotificationMessageType, isSystemLogMessageType } from "../../../utils/messageLog";
|
|
22
23
|
import { buildMessageToolboxMenuItems, getCopyableMessageText, isCopyableMessageType, isPinnableMessageType, MessageToolboxActionKey, MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, useMessageToolboxVisibility, } from "../../../components/message/toolbox";
|
|
23
24
|
const MESSAGE_AVATAR_SIZE = 24;
|
|
24
25
|
const MessageAvatar = ({ avatarUrl, senderNickname, }) => {
|
|
@@ -35,7 +36,8 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
35
36
|
const { isDeliveredForUi, isRevocable, isMine } = useMessageToolboxVisibility(message, userID);
|
|
36
37
|
const contextMenuItems = useMemo(() => {
|
|
37
38
|
if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.RevokeMessage ||
|
|
38
|
-
isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType)
|
|
39
|
+
isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType) ||
|
|
40
|
+
isGroupNotificationMessageType(message === null || message === void 0 ? void 0 : message.contentType)) {
|
|
39
41
|
return [];
|
|
40
42
|
}
|
|
41
43
|
const closeToolbox = () => onContextMenuOpenChange === null || onContextMenuOpenChange === void 0 ? void 0 : onContextMenuOpenChange(false);
|
|
@@ -118,6 +120,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
118
120
|
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm, message === null || message === void 0 ? void 0 : message.sendID, userID]);
|
|
119
121
|
const isInternalMessage = Boolean(message === null || message === void 0 ? void 0 : message.isInternal);
|
|
120
122
|
const isSystemLogMessage = isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType);
|
|
123
|
+
const isGroupNotificationMessage = isGroupNotificationMessageType(message === null || message === void 0 ? void 0 : message.contentType);
|
|
121
124
|
const isStickerMessage = (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.StickerMessage;
|
|
122
125
|
const hasContextMenu = contextMenuItems.length > 0;
|
|
123
126
|
const isLatestMine = ((_a = allMessages.find((m) => m.sendID === userID)) === null || _a === void 0 ? void 0 : _a.clientMsgID) ===
|
|
@@ -145,6 +148,11 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
145
148
|
timeBreakNode,
|
|
146
149
|
_jsx(SystemLogMessageItem, { message: message })));
|
|
147
150
|
}
|
|
151
|
+
if (isGroupNotificationMessage) {
|
|
152
|
+
return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
|
|
153
|
+
timeBreakNode,
|
|
154
|
+
_jsx(GroupNotificationMessageItem, { message: message })));
|
|
155
|
+
}
|
|
148
156
|
const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent(message, onPressQuoteMessage), isTransparent: isStickerMessage }));
|
|
149
157
|
const showPinnedBadge = Boolean(message === null || message === void 0 ? void 0 : message.isPinned) && Boolean(onPinMessage);
|
|
150
158
|
const pinnedBadgeNode = showPinnedBadge ? (_jsx("span", { "data-testid": "message-pinned-badge", className: clsx("absolute -top-2.5 z-[1] flex h-[22px] w-[26px] items-center justify-center rounded-full border border-white bg-gray-25", isMine ? "left-0" : "right-0"), children: _jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }) })) : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderMessageContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/renderMessageContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAe,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"renderMessageContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/renderMessageContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAe,MAAM,8BAA8B,CAAC;AAc3F,eAAO,MAAM,mBAAmB,GAAI,SAAS,eAAe,4CA4C3D,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,eAAe,EACxB,sBAAsB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,4CAwBpD,CAAC"}
|
|
@@ -11,6 +11,7 @@ import QuoteMessageItem from "./QuoteMessage";
|
|
|
11
11
|
import SystemLogMessageItem from "./SystemLogMessage";
|
|
12
12
|
import CustomMessageItem from "./CustomMessage";
|
|
13
13
|
import StickerMessageItem from "./StickerMessage";
|
|
14
|
+
import GroupNotificationMessageItem from "./GroupNotificationMessage";
|
|
14
15
|
export const renderMessageByType = (message) => {
|
|
15
16
|
switch (message === null || message === void 0 ? void 0 : message.contentType) {
|
|
16
17
|
case MessageType.TextMessage:
|
|
@@ -34,6 +35,23 @@ export const renderMessageByType = (message) => {
|
|
|
34
35
|
return _jsx(CustomMessageItem, { message: message });
|
|
35
36
|
case MessageType.StickerMessage:
|
|
36
37
|
return _jsx(StickerMessageItem, { message: message });
|
|
38
|
+
case MessageType.GroupCreated:
|
|
39
|
+
case MessageType.GroupInfoUpdated:
|
|
40
|
+
case MessageType.MemberQuit:
|
|
41
|
+
case MessageType.GroupOwnerTransferred:
|
|
42
|
+
case MessageType.MemberKicked:
|
|
43
|
+
case MessageType.MemberInvited:
|
|
44
|
+
case MessageType.MemberEnter:
|
|
45
|
+
case MessageType.GroupDismissed:
|
|
46
|
+
case MessageType.GroupMemberMuted:
|
|
47
|
+
case MessageType.GroupMemberCancelMuted:
|
|
48
|
+
case MessageType.GroupMuted:
|
|
49
|
+
case MessageType.GroupCancelMuted:
|
|
50
|
+
case MessageType.GroupAnnouncementUpdated:
|
|
51
|
+
case MessageType.GroupNameUpdated:
|
|
52
|
+
{
|
|
53
|
+
return _jsx(GroupNotificationMessageItem, { message: message });
|
|
54
|
+
}
|
|
37
55
|
default:
|
|
38
56
|
return _jsx(TextMessageItem, { message: message });
|
|
39
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchDrawer.tsx"],"names":[],"mappings":"AAQA,QAAA,MAAM,YAAY,+
|
|
1
|
+
{"version":3,"file":"SearchDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchDrawer.tsx"],"names":[],"mappings":"AAQA,QAAA,MAAM,YAAY,+CAiFjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -26,7 +26,7 @@ const SearchDrawer = () => {
|
|
|
26
26
|
padding: 0,
|
|
27
27
|
height: "100%",
|
|
28
28
|
},
|
|
29
|
-
}, getContainer: false, width: isMobile ? "100%" : 360, children: _jsxs("div", { className: "flex flex-col h-full", children: [_jsxs("div", { className: "flex items-center justify-between p-3", children: [_jsx("span", { className: "text-lg font-medium", children: t("search_message_title") }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: toggle, children: _jsx(Icon, { icon: "close-b", size: 22 }) })] }), _jsx("div", { className: "px-3", children: _jsx(Input, { ref: searchInputRef, placeholder: t("search"), prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), onChange: (e) => {
|
|
29
|
+
}, getContainer: false, forceRender: true, width: isMobile ? "100%" : 360, children: _jsxs("div", { className: "flex flex-col h-full", children: [_jsxs("div", { className: "flex items-center justify-between p-3", children: [_jsx("span", { className: "text-lg font-medium", children: t("search_message_title") }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: toggle, children: _jsx(Icon, { icon: "close-b", size: 22 }) })] }), _jsx("div", { className: "px-3", children: _jsx(Input, { ref: searchInputRef, placeholder: t("search"), prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), onChange: (e) => {
|
|
30
30
|
setSearch(e.target.value);
|
|
31
31
|
}, className: "rounded-lg text-sm", size: "large", allowClear: true, value: search, autoFocus: false }) }), _jsx("div", { className: "flex-1 py-3 overflow-auto", children: _jsx(SearchMessageOnCurrentConversation, { searchTerm: search, onClose: toggle }) })] }) })] }));
|
|
32
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/GroupThreadInfo.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GroupThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/GroupThreadInfo.tsx"],"names":[],"mappings":"AAmBA,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,mDA4fjE,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Input, Modal, Switch, message } from "antd";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import { GroupMemberRole, MessageReceiveOptType } from "@droppii-org/wasm-client-sdk";
|
|
6
6
|
import { Icon } from "../../components/icon";
|
|
@@ -12,10 +12,13 @@ import { useUpdateGroupInfo } from "../../hooks/group/useUpdateGroupInfo";
|
|
|
12
12
|
import { useToggleGroupSendMessage } from "../../hooks/group/useToggleGroupSendMessage";
|
|
13
13
|
import { useDismissGroup } from "../../hooks/group/useDismissGroup";
|
|
14
14
|
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
15
|
+
import { useUploadFile } from "../../hooks/common/useUploadFile";
|
|
16
|
+
import { validateFile } from "../../utils/fileValidation";
|
|
15
17
|
import AdminPermissionModal from "../../components/group/AdminPermissionModal";
|
|
16
18
|
import MemberPermissionPanel from "../../components/group/MemberPermissionPanel";
|
|
19
|
+
import GroupCompositeAvatar from "../../components/group/GroupCompositeAvatar";
|
|
17
20
|
const GroupThreadInfo = ({ onClose, config }) => {
|
|
18
|
-
var _a, _b, _c
|
|
21
|
+
var _a, _b, _c;
|
|
19
22
|
const { t } = useTranslation();
|
|
20
23
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
21
24
|
const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
|
|
@@ -34,6 +37,7 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
34
37
|
const [confirmAction, setConfirmAction] = useState(null);
|
|
35
38
|
const [activeRow, setActiveRow] = useState(null);
|
|
36
39
|
const [notifyEnabled, setNotifyEnabled] = useState((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
40
|
+
const avatarInputRef = useRef(null);
|
|
37
41
|
// Q4 (non-block, pending BE/SDK confirmation): openIM's GroupItem has no
|
|
38
42
|
// readable "is send disabled" field for changeGroupMute — tracked locally
|
|
39
43
|
// until BE confirms where (or whether) this persists server-side.
|
|
@@ -42,6 +46,7 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
42
46
|
setNotifyEnabled((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
43
47
|
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt]);
|
|
44
48
|
const { mutate: updateGroupInfo } = useUpdateGroupInfo();
|
|
49
|
+
const { mutate: uploadFile, isPending: isAvatarUploading } = useUploadFile();
|
|
45
50
|
const { mutate: toggleSendMessage, isPending: isTogglingSendMessage } = useToggleGroupSendMessage();
|
|
46
51
|
const { mutate: toggleNotification, isPending: isTogglingNotification } = useToggleConversationNotification();
|
|
47
52
|
const { mutateAsync: leaveConversation, isPending: isLeaving } = useLeaveConversation();
|
|
@@ -76,6 +81,32 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
76
81
|
return;
|
|
77
82
|
updateGroupInfo({ groupID, introduction: trimmed }, { onError: () => message.error(t("update_group_info_failed")) });
|
|
78
83
|
};
|
|
84
|
+
const handleAvatarClick = () => {
|
|
85
|
+
var _a;
|
|
86
|
+
if (isAvatarUploading)
|
|
87
|
+
return;
|
|
88
|
+
(_a = avatarInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
89
|
+
};
|
|
90
|
+
const handleAvatarSelect = (event) => {
|
|
91
|
+
var _a;
|
|
92
|
+
const file = (_a = event.target.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
93
|
+
event.target.value = "";
|
|
94
|
+
if (!file || !groupID)
|
|
95
|
+
return;
|
|
96
|
+
const validation = validateFile(file, t);
|
|
97
|
+
if (!validation.isValid) {
|
|
98
|
+
message.error(validation.error);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
uploadFile(file, {
|
|
102
|
+
onSuccess: (uploaded) => {
|
|
103
|
+
if (!(uploaded === null || uploaded === void 0 ? void 0 : uploaded.publicUrl))
|
|
104
|
+
return;
|
|
105
|
+
updateGroupInfo({ groupID, faceURL: uploaded.publicUrl }, { onError: () => message.error(t("update_group_info_failed")) });
|
|
106
|
+
},
|
|
107
|
+
onError: () => message.error(t("avatar_upload_failed")),
|
|
108
|
+
});
|
|
109
|
+
};
|
|
79
110
|
const handleToggleNotification = (checked) => {
|
|
80
111
|
if (!conversationID)
|
|
81
112
|
return;
|
|
@@ -151,6 +182,6 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
151
182
|
if (!groupID) {
|
|
152
183
|
return null;
|
|
153
184
|
}
|
|
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") }) }))] }));
|
|
185
|
+
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(GroupCompositeAvatar, { groupID: groupID, faceURL: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.faceURL, ownerUserID: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.ownerUserID, groupName: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupName, size: 56 }), isAvatarUploading && (_jsx("span", { className: "absolute inset-0 flex items-center justify-center rounded-full bg-black/30", children: _jsx("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" }) })), permissions.updateGroupAvatar && (_jsxs(_Fragment, { children: [_jsx("input", { ref: avatarInputRef, type: "file", accept: "image/jpeg, image/png, image/jpg", className: "hidden", onChange: handleAvatarSelect }), _jsx("button", { type: "button", disabled: isAvatarUploading, onClick: handleAvatarClick, 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() === ((_c = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.introduction) !== null && _c !== void 0 ? _c : ""), 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, forceRender: true, 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, forceRender: true, 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, forceRender: true, 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, forceRender: true, children: _jsx("p", { className: "text-sm text-gray-500", children: t("feature_coming_soon") }) }))] }));
|
|
155
186
|
};
|
|
156
187
|
export default GroupThreadInfo;
|
|
@@ -1 +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,
|
|
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,mDAoJ3D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -65,6 +65,6 @@ const SingleThreadInfo = ({ onClose }) => {
|
|
|
65
65
|
if (!conversationID) {
|
|
66
66
|
return null;
|
|
67
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") }) })] }));
|
|
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, forceRender: true, children: _jsx("p", { children: t("delete_conversation_confirm_message") }) })] }));
|
|
69
69
|
};
|
|
70
70
|
export default SingleThreadInfo;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/ThreadInfo.tsx"],"names":[],"mappings":"AAGA,OAAwB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ThreadInfo.d.ts","sourceRoot":"","sources":["../../../src/components/thread/ThreadInfo.tsx"],"names":[],"mappings":"AAGA,OAAwB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAQ3E,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"}
|
|
@@ -8,10 +8,11 @@ import { useGetListSessionByConversation } from "../../hooks/session/useGetListS
|
|
|
8
8
|
import { useMemo } from "react";
|
|
9
9
|
import { PAGE_SIZE } from "../../constants";
|
|
10
10
|
import { PeerType } from "../../types/conversation";
|
|
11
|
+
import { isGroupConversation } from "../../utils/imCommon";
|
|
11
12
|
const ThreadInfo = ({ isOpen = true, onClose, groupConfig }) => {
|
|
12
13
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
13
14
|
const conversationId = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "";
|
|
14
|
-
const isGroup = (conversationData
|
|
15
|
+
const isGroup = isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
|
|
15
16
|
const isBot = (conversationData === null || conversationData === void 0 ? void 0 : conversationData.peerType) === PeerType.BOT;
|
|
16
17
|
const { data: sessions, isLoading } = useGetListSessionByConversation({
|
|
17
18
|
conversationId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayerModal.d.ts","sourceRoot":"","sources":["../../../src/components/video-player/VideoPlayerModal.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAQD,eAAO,MAAM,oBAAoB,GAC/B,OAAO,iBAAiB,EAAE,KACzB,iBAAiB,EAWhB,CAAC;AAEL,QAAA,MAAM,gBAAgB,GAAI,0CAKvB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"VideoPlayerModal.d.ts","sourceRoot":"","sources":["../../../src/components/video-player/VideoPlayerModal.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAQD,eAAO,MAAM,oBAAoB,GAC/B,OAAO,iBAAiB,EAAE,KACzB,iBAAiB,EAWhB,CAAC;AAEL,QAAA,MAAM,gBAAgB,GAAI,0CAKvB,qBAAqB,4CAsFvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -34,7 +34,7 @@ const VideoPlayerModal = ({ open, videos, initialIndex, onClose, }) => {
|
|
|
34
34
|
const currentVideo = videos[currentIndex];
|
|
35
35
|
const { snapshotWidth = 0, snapshotHeight = 0 } = currentVideo || {};
|
|
36
36
|
const hasSnapshotSize = snapshotWidth > 0 && snapshotHeight > 0;
|
|
37
|
-
return (_jsx(Modal, { open: open, onCancel: onClose, footer: null, centered: true, destroyOnHidden: true, getContainer: false, closeIcon: _jsx("span", { className: CLOSE_BUTTON_CLASS, children: _jsx(Icon, { icon: "close-b", size: 18 }) }), styles: {
|
|
37
|
+
return (_jsx(Modal, { open: open, onCancel: onClose, footer: null, centered: true, destroyOnHidden: true, getContainer: false, forceRender: true, closeIcon: _jsx("span", { className: CLOSE_BUTTON_CLASS, children: _jsx(Icon, { icon: "close-b", size: 18 }) }), styles: {
|
|
38
38
|
content: {
|
|
39
39
|
padding: 0,
|
|
40
40
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUploadFile.d.ts","sourceRoot":"","sources":["../../../src/hooks/common/useUploadFile.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAC;AAI/D,eAAO,MAAM,aAAa,8FAgBtB,CAAC"}
|