@droppii-org/chat-sdk 0.3.1 → 0.3.3
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/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 +3 -2
- 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.map +1 -1
- package/dist/components/group/GroupCompositeAvatar.js +19 -7
- package/dist/components/group/GroupMemberPicker.d.ts.map +1 -1
- package/dist/components/group/GroupMemberPicker.js +3 -2
- 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 +61 -29
- package/dist/components/message/MessageHeader.d.ts.map +1 -1
- package/dist/components/message/MessageHeader.js +16 -5
- package/dist/components/message/footer/index.d.ts.map +1 -1
- package/dist/components/message/footer/index.js +7 -1
- 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 +33 -3
- 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/useEligibleAccounts.d.ts +1 -0
- package/dist/hooks/group/useEligibleAccounts.d.ts.map +1 -1
- package/dist/hooks/group/useEligibleAccounts.js +1 -0
- package/dist/hooks/group/useEligibleAccountsForGroup.d.ts.map +1 -1
- package/dist/hooks/group/useEligibleAccountsForGroup.js +1 -0
- 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 +23 -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/types/dto.d.ts +11 -0
- package/dist/types/dto.d.ts.map +1 -1
- package/dist/utils/common.d.ts +1 -0
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +4 -0
- 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,26 @@ 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
|
+
// Optimistically patch the role in place instead of refetching the
|
|
193
|
+
// whole list — a full refetch replaces every member's object
|
|
194
|
+
// identity and re-sorts, which visibly re-renders/reorders rows that
|
|
195
|
+
// didn't actually change. permissions[] isn't patched here — BE
|
|
196
|
+
// resets it to the new role's defaults server-side, and useGroupMembers'
|
|
197
|
+
// OnGroupMemberInfoChanged listener picks up that real value shortly
|
|
198
|
+
// after, instead of this component predicting it.
|
|
199
|
+
patchMemberRole(member.userID, nextRoleLevel);
|
|
176
200
|
}
|
|
177
201
|
catch (error) {
|
|
178
202
|
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 +253,25 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
229
253
|
return (_jsx("div", { className: "flex flex-col", children: sortedMembers.map((member) => {
|
|
230
254
|
// Send message / Remove and block are not wired yet (no confirmed
|
|
231
255
|
// SDK flow for member-scoped block) — kept disabled per scope.
|
|
256
|
+
const leaveGroupItem = {
|
|
257
|
+
key: "leave-group",
|
|
258
|
+
label: t("leave_group"),
|
|
259
|
+
icon: _jsx(Icon, { icon: "logout-b", size: 16 }),
|
|
260
|
+
onClick: handleLeaveGroup,
|
|
261
|
+
danger: true,
|
|
262
|
+
};
|
|
232
263
|
const menuItems = member.isCurrentUser
|
|
233
|
-
?
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
onClick: handleLeaveGroup,
|
|
245
|
-
danger: true,
|
|
246
|
-
},
|
|
247
|
-
]
|
|
264
|
+
? isRealGroup
|
|
265
|
+
? [
|
|
266
|
+
{
|
|
267
|
+
key: "mute",
|
|
268
|
+
label: t("mute_member"),
|
|
269
|
+
icon: _jsx(Icon, { icon: "bell-off-b", size: 16 }),
|
|
270
|
+
disabled: true,
|
|
271
|
+
},
|
|
272
|
+
leaveGroupItem,
|
|
273
|
+
]
|
|
274
|
+
: [leaveGroupItem]
|
|
248
275
|
: [
|
|
249
276
|
{
|
|
250
277
|
key: "send-message",
|
|
@@ -275,7 +302,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
275
302
|
label: t("admin_permission_settings"),
|
|
276
303
|
icon: _jsx(Icon, { icon: "shield-o", size: 16 }),
|
|
277
304
|
disabled: !permissions.transferOwnership,
|
|
278
|
-
onClick: () =>
|
|
305
|
+
onClick: () => setAdminPermissionMember(member),
|
|
279
306
|
},
|
|
280
307
|
{
|
|
281
308
|
key: "remove-admin",
|
|
@@ -310,18 +337,23 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
310
337
|
disabled: true,
|
|
311
338
|
},
|
|
312
339
|
];
|
|
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));
|
|
340
|
+
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
341
|
}) }));
|
|
315
342
|
};
|
|
316
|
-
return (_jsxs(
|
|
343
|
+
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
344
|
body: {
|
|
318
345
|
padding: 0,
|
|
319
346
|
height: "100%",
|
|
320
347
|
},
|
|
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(
|
|
348
|
+
}, 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
|
|
349
|
+
? {
|
|
350
|
+
userID: adminPermissionMember.userID,
|
|
351
|
+
permissions: adminPermissionMember.permissions,
|
|
352
|
+
}
|
|
353
|
+
: 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
354
|
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", {
|
|
355
|
+
}) }) }), _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
356
|
name: confirmMemberAction === null || confirmMemberAction === void 0 ? void 0 : confirmMemberAction.member.nickname,
|
|
325
|
-
}) }) })
|
|
357
|
+
}) }) })] }));
|
|
326
358
|
};
|
|
327
359
|
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;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,
|
|
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,7 +12,7 @@ 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
17
|
import GroupCompositeAvatar from "../../components/group/GroupCompositeAvatar";
|
|
18
18
|
import GroupMembersDrawer from "./GroupMembersDrawer";
|
|
@@ -27,6 +27,20 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
|
|
|
27
27
|
const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
|
|
28
28
|
const { avatar, displayName } = useConversationDisplayData(conversationData);
|
|
29
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);
|
|
30
44
|
const [currentSessionStatus, setCurrentSessionStatus] = useState(SessionStatus.UNASSIGNED);
|
|
31
45
|
const [currentSessionTag, setCurrentSessionTag] = useState(SessionTag.NONE);
|
|
32
46
|
const statusOptions = useMemo(() => {
|
|
@@ -130,9 +144,6 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
|
|
|
130
144
|
setCurrentSessionStatus(currentSession.status);
|
|
131
145
|
}
|
|
132
146
|
}, [currentSession]);
|
|
133
|
-
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 && (_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, {}),
|
|
134
|
-
isJoined === true &&
|
|
135
|
-
isCrm &&
|
|
136
|
-
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 }) }))] })] }));
|
|
137
148
|
};
|
|
138
149
|
export default MessageHeader;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAEL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAEL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAY/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CA4SpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -30,6 +30,7 @@ import ComposerEditor from "./ComposerEditor";
|
|
|
30
30
|
import SessionClosedModal from "./SessionClosedModal";
|
|
31
31
|
import { useCreateSession, useReopenSession, } from "../../../hooks/session/useReopenOrCreateSession";
|
|
32
32
|
import { emit } from "../../../utils/events";
|
|
33
|
+
import { isGroupConversation } from "../../../utils/imCommon";
|
|
33
34
|
const initialConfig = {
|
|
34
35
|
namespace: "ChatInput",
|
|
35
36
|
theme: editorTheme,
|
|
@@ -63,9 +64,14 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
|
63
64
|
const [activeCannedIndex, setActiveCannedIndex] = useState(0);
|
|
64
65
|
const [maxActiveCannedIndex, setMaxActiveCannedIndex] = useState(0);
|
|
65
66
|
const [isInternal, setIsInternal] = useState(false);
|
|
66
|
-
const canUseInternal = isCrm && accountType === AccountType.Staff;
|
|
67
67
|
const quotedMessage = useConversationStore((state) => state.quotedMessage);
|
|
68
68
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
69
|
+
// Internal notes are a CX-support concept (team-only remarks not sent to
|
|
70
|
+
// the customer) — meaningless inside a real member-managed group, where
|
|
71
|
+
// everyone in the thread already is the "team".
|
|
72
|
+
const canUseInternal = isCrm &&
|
|
73
|
+
accountType === AccountType.Staff &&
|
|
74
|
+
!isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
|
|
69
75
|
const lockToInternal = Boolean((quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.clientMsgID) && (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.isInternal));
|
|
70
76
|
const previewUrl = useMemo(() => {
|
|
71
77
|
const urls = extractLinkUrls(composerText);
|
|
@@ -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,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
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";
|
|
@@ -12,6 +12,8 @@ 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";
|
|
17
19
|
import GroupCompositeAvatar from "../../components/group/GroupCompositeAvatar";
|
|
@@ -35,6 +37,7 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
35
37
|
const [confirmAction, setConfirmAction] = useState(null);
|
|
36
38
|
const [activeRow, setActiveRow] = useState(null);
|
|
37
39
|
const [notifyEnabled, setNotifyEnabled] = useState((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
40
|
+
const avatarInputRef = useRef(null);
|
|
38
41
|
// Q4 (non-block, pending BE/SDK confirmation): openIM's GroupItem has no
|
|
39
42
|
// readable "is send disabled" field for changeGroupMute — tracked locally
|
|
40
43
|
// until BE confirms where (or whether) this persists server-side.
|
|
@@ -43,6 +46,7 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
43
46
|
setNotifyEnabled((conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt) !== MessageReceiveOptType.NotNotify);
|
|
44
47
|
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.recvMsgOpt]);
|
|
45
48
|
const { mutate: updateGroupInfo } = useUpdateGroupInfo();
|
|
49
|
+
const { mutate: uploadFile, isPending: isAvatarUploading } = useUploadFile();
|
|
46
50
|
const { mutate: toggleSendMessage, isPending: isTogglingSendMessage } = useToggleGroupSendMessage();
|
|
47
51
|
const { mutate: toggleNotification, isPending: isTogglingNotification } = useToggleConversationNotification();
|
|
48
52
|
const { mutateAsync: leaveConversation, isPending: isLeaving } = useLeaveConversation();
|
|
@@ -77,6 +81,32 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
77
81
|
return;
|
|
78
82
|
updateGroupInfo({ groupID, introduction: trimmed }, { onError: () => message.error(t("update_group_info_failed")) });
|
|
79
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
|
+
};
|
|
80
110
|
const handleToggleNotification = (checked) => {
|
|
81
111
|
if (!conversationID)
|
|
82
112
|
return;
|
|
@@ -152,6 +182,6 @@ const GroupThreadInfo = ({ onClose, config }) => {
|
|
|
152
182
|
if (!groupID) {
|
|
153
183
|
return null;
|
|
154
184
|
}
|
|
155
|
-
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 }), 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() === ((_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, 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") }) }))] }));
|
|
156
186
|
};
|
|
157
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"}
|