@droppii-org/chat-mobile 0.2.66 → 0.2.67
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/lib/module/components/Avatar/Avatar.js +39 -2
- package/lib/module/components/Avatar/Avatar.js.map +1 -1
- package/lib/module/components/Avatar/DoubleAvatar.js +18 -18
- package/lib/module/components/Avatar/DoubleAvatar.js.map +1 -1
- package/lib/module/components/Avatar/QuadAvatar.js +131 -0
- package/lib/module/components/Avatar/QuadAvatar.js.map +1 -0
- package/lib/module/components/Avatar/TripleAvatar.js +97 -0
- package/lib/module/components/Avatar/TripleAvatar.js.map +1 -0
- package/lib/module/components/Avatar/index.js +2 -0
- package/lib/module/components/Avatar/index.js.map +1 -1
- package/lib/module/components/ThreadCard/AvatarSection.js +41 -0
- package/lib/module/components/ThreadCard/AvatarSection.js.map +1 -1
- package/lib/module/components/ThreadCard/NamePrefixIcon.js +5 -4
- package/lib/module/components/ThreadCard/NamePrefixIcon.js.map +1 -1
- package/lib/module/components/ThreadCard/ThreadCard.js +3 -1
- package/lib/module/components/ThreadCard/ThreadCard.js.map +1 -1
- package/lib/module/components/messages/groupNotificationMessage/index.js +25 -0
- package/lib/module/components/messages/groupNotificationMessage/index.js.map +1 -0
- package/lib/module/context/ChatContext.js +1 -1
- package/lib/module/context/ChatContext.js.map +1 -1
- package/lib/module/context/ChatDetailContext.js +9 -0
- package/lib/module/context/ChatDetailContext.js.map +1 -1
- package/lib/module/core/useChatListener.js +120 -21
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/hooks/conversation/useGetGroupInfo.js +3 -1
- package/lib/module/hooks/conversation/useGetGroupInfo.js.map +1 -1
- package/lib/module/hooks/message/useSendMessage.js +6 -3
- package/lib/module/hooks/message/useSendMessage.js.map +1 -1
- package/lib/module/hooks/useConversationList.js +9 -4
- package/lib/module/hooks/useConversationList.js.map +1 -1
- package/lib/module/screens/ChatInfo/ChatInfoProfile.js +4 -2
- package/lib/module/screens/ChatInfo/ChatInfoProfile.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatComposer.js +11 -6
- package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetail.js +7 -0
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetailHeader.js +10 -3
- package/lib/module/screens/chat-detail/ChatDetailHeader.js.map +1 -1
- package/lib/module/screens/chat-detail/conversationHeader.utils.js +13 -3
- package/lib/module/screens/chat-detail/conversationHeader.utils.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +29 -2
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
- package/lib/module/screens/inbox/MessagesTab.js.map +1 -1
- package/lib/module/store/conversation.js +56 -12
- package/lib/module/store/conversation.js.map +1 -1
- package/lib/module/translation/resources/i18n.js +31 -0
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/module/types/events.js +1 -0
- package/lib/module/types/events.js.map +1 -1
- package/lib/module/utils/messageUtils.js +95 -2
- package/lib/module/utils/messageUtils.js.map +1 -1
- package/lib/typescript/src/components/Avatar/Avatar.d.ts +1 -1
- package/lib/typescript/src/components/Avatar/Avatar.d.ts.map +1 -1
- package/lib/typescript/src/components/Avatar/Avatar.types.d.ts +5 -1
- package/lib/typescript/src/components/Avatar/Avatar.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Avatar/DoubleAvatar.d.ts.map +1 -1
- package/lib/typescript/src/components/Avatar/QuadAvatar.d.ts +16 -0
- package/lib/typescript/src/components/Avatar/QuadAvatar.d.ts.map +1 -0
- package/lib/typescript/src/components/Avatar/TripleAvatar.d.ts +15 -0
- package/lib/typescript/src/components/Avatar/TripleAvatar.d.ts.map +1 -0
- package/lib/typescript/src/components/Avatar/index.d.ts +2 -0
- package/lib/typescript/src/components/Avatar/index.d.ts.map +1 -1
- package/lib/typescript/src/components/ThreadCard/AvatarSection.d.ts +2 -2
- package/lib/typescript/src/components/ThreadCard/AvatarSection.d.ts.map +1 -1
- package/lib/typescript/src/components/ThreadCard/NamePrefixIcon.d.ts +3 -1
- package/lib/typescript/src/components/ThreadCard/NamePrefixIcon.d.ts.map +1 -1
- package/lib/typescript/src/components/ThreadCard/ThreadCard.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/groupNotificationMessage/index.d.ts +3 -0
- package/lib/typescript/src/components/messages/groupNotificationMessage/index.d.ts.map +1 -0
- package/lib/typescript/src/context/ChatDetailContext.d.ts +2 -0
- package/lib/typescript/src/context/ChatDetailContext.d.ts.map +1 -1
- package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
- package/lib/typescript/src/hooks/conversation/useGetGroupInfo.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useConversationList.d.ts.map +1 -1
- package/lib/typescript/src/screens/ChatInfo/ChatInfoProfile.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetailHeader.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/conversationHeader.utils.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/conversationHeader.utils.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/inbox/MessagesTab.d.ts.map +1 -1
- package/lib/typescript/src/store/conversation.d.ts +11 -0
- package/lib/typescript/src/store/conversation.d.ts.map +1 -1
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +6 -1
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/messageUtils.d.ts +6 -1
- package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/build-ignore.d.ts +1 -0
- package/src/components/Avatar/Avatar.tsx +47 -0
- package/src/components/Avatar/Avatar.types.ts +5 -1
- package/src/components/Avatar/DoubleAvatar.tsx +16 -13
- package/src/components/Avatar/QuadAvatar.tsx +161 -0
- package/src/components/Avatar/TripleAvatar.tsx +119 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/ThreadCard/AvatarSection.tsx +58 -2
- package/src/components/ThreadCard/NamePrefixIcon.tsx +32 -25
- package/src/components/ThreadCard/ThreadCard.tsx +2 -0
- package/src/components/messages/groupNotificationMessage/index.tsx +28 -0
- package/src/context/ChatContext.tsx +1 -1
- package/src/context/ChatDetailContext.tsx +15 -0
- package/src/core/useChatListener.ts +175 -23
- package/src/hooks/conversation/useGetGroupInfo.ts +2 -0
- package/src/hooks/message/useSendMessage.ts +11 -3
- package/src/hooks/useConversationList.ts +17 -7
- package/src/screens/ChatInfo/ChatInfoProfile.tsx +6 -3
- package/src/screens/chat-detail/ChatComposer.tsx +19 -10
- package/src/screens/chat-detail/ChatDetail.tsx +12 -1
- package/src/screens/chat-detail/ChatDetailHeader.tsx +19 -3
- package/src/screens/chat-detail/conversationHeader.utils.ts +14 -6
- package/src/screens/chat-detail/legend/LegendChatMessage.tsx +36 -1
- package/src/screens/inbox/MessagesTab.tsx +0 -1
- package/src/store/conversation.ts +62 -17
- package/src/translation/resources/i18n.ts +31 -0
- package/src/types/events.ts +6 -0
- package/src/utils/messageUtils.ts +103 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { create } from 'zustand';
|
|
2
|
-
import {
|
|
2
|
+
import { SessionType } from '@droppii/openim-rn-client-sdk';
|
|
3
|
+
import { getConversationID, sortConversation } from '../utils/conversation';
|
|
3
4
|
import type { ConversationItem } from '@droppii/openim-rn-client-sdk';
|
|
4
5
|
|
|
5
6
|
type ConversationID = string;
|
|
@@ -18,6 +19,13 @@ export interface ConversationStore {
|
|
|
18
19
|
map: Record<ConversationID, ConversationItem>;
|
|
19
20
|
/** Signal incremented when a truly new conversation arrives and a full refetch is needed. */
|
|
20
21
|
newConversationSignal: number;
|
|
22
|
+
/**
|
|
23
|
+
* Group IDs the user just left/was removed from. Any late-arriving SDK
|
|
24
|
+
* event (OnConversationChanged, OnNewConversation, ...) that still carries
|
|
25
|
+
* this group must not resurrect it — without this guard those events race
|
|
26
|
+
* with removeGroupConversation and silently undo the removal.
|
|
27
|
+
*/
|
|
28
|
+
removedGroupIds: Set<string>;
|
|
21
29
|
updateConversation(id: ConversationID, data: Partial<ConversationItem>): void;
|
|
22
30
|
updateConversations(conversations: ConversationItem[]): void;
|
|
23
31
|
/**
|
|
@@ -25,6 +33,10 @@ export interface ConversationStore {
|
|
|
25
33
|
* Returns true if any conversation was not found in the store (triggers refetch).
|
|
26
34
|
*/
|
|
27
35
|
removeConversation(id: ConversationID): void;
|
|
36
|
+
/** Removes a group's conversation and guards it against being re-added. */
|
|
37
|
+
removeGroupConversation(groupID: string): void;
|
|
38
|
+
/** Lifts the removal guard once the user (re)joins the group. */
|
|
39
|
+
restoreGroupConversation(groupID: string): void;
|
|
28
40
|
reset(): void;
|
|
29
41
|
}
|
|
30
42
|
|
|
@@ -32,6 +44,7 @@ export const useConversationStore = create<ConversationStore>()((set, get) => ({
|
|
|
32
44
|
list: [],
|
|
33
45
|
map: {},
|
|
34
46
|
newConversationSignal: 0,
|
|
47
|
+
removedGroupIds: new Set(),
|
|
35
48
|
setCurrentConversation(id, userId, groupId) {
|
|
36
49
|
set({
|
|
37
50
|
currentConversationId: id,
|
|
@@ -49,25 +62,38 @@ export const useConversationStore = create<ConversationStore>()((set, get) => ({
|
|
|
49
62
|
const existing = get().map[id];
|
|
50
63
|
if (!existing) return;
|
|
51
64
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
const merged = { ...existing, ...data };
|
|
66
|
+
const nextMap = { ...get().map };
|
|
67
|
+
if (merged.isNotInGroup || get().removedGroupIds.has(merged.groupID)) {
|
|
68
|
+
delete nextMap[id];
|
|
69
|
+
} else {
|
|
70
|
+
nextMap[id] = merged;
|
|
71
|
+
}
|
|
72
|
+
set(sortConversation(nextMap));
|
|
58
73
|
},
|
|
59
74
|
updateConversations(conversations) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
const removedGroupIds = get().removedGroupIds;
|
|
76
|
+
const nextMap = conversations.reduce(
|
|
77
|
+
(pre, curr) => {
|
|
78
|
+
if (curr.isNotInGroup || removedGroupIds.has(curr.groupID)) {
|
|
79
|
+
// console.log(
|
|
80
|
+
// '[Store] updateConversations: dropping guarded/left group',
|
|
81
|
+
// {
|
|
82
|
+
// conversationID: curr.conversationID,
|
|
83
|
+
// groupID: curr.groupID,
|
|
84
|
+
// isNotInGroup: curr.isNotInGroup,
|
|
85
|
+
// guarded: removedGroupIds.has(curr.groupID),
|
|
86
|
+
// }
|
|
87
|
+
// );
|
|
88
|
+
delete pre[curr.conversationID];
|
|
89
|
+
} else {
|
|
90
|
+
pre[curr.conversationID] = curr;
|
|
91
|
+
}
|
|
92
|
+
return pre;
|
|
93
|
+
},
|
|
94
|
+
{ ...get().map }
|
|
70
95
|
);
|
|
96
|
+
set(sortConversation(nextMap));
|
|
71
97
|
},
|
|
72
98
|
removeConversation(id) {
|
|
73
99
|
const newMap = { ...get().map };
|
|
@@ -78,12 +104,31 @@ export const useConversationStore = create<ConversationStore>()((set, get) => ({
|
|
|
78
104
|
list: get().list.filter((item) => item !== id),
|
|
79
105
|
});
|
|
80
106
|
},
|
|
107
|
+
removeGroupConversation(groupID) {
|
|
108
|
+
const conversationID = getConversationID(SessionType.Group, groupID);
|
|
109
|
+
|
|
110
|
+
const newMap = { ...get().map };
|
|
111
|
+
delete newMap[conversationID];
|
|
112
|
+
|
|
113
|
+
set({
|
|
114
|
+
map: newMap,
|
|
115
|
+
list: get().list.filter((item) => item !== conversationID),
|
|
116
|
+
removedGroupIds: new Set(get().removedGroupIds).add(groupID),
|
|
117
|
+
});
|
|
118
|
+
},
|
|
119
|
+
restoreGroupConversation(groupID) {
|
|
120
|
+
// console.log('[Store] restoreGroupConversation', { groupID });
|
|
121
|
+
const nextRemovedGroupIds = new Set(get().removedGroupIds);
|
|
122
|
+
nextRemovedGroupIds.delete(groupID);
|
|
123
|
+
set({ removedGroupIds: nextRemovedGroupIds });
|
|
124
|
+
},
|
|
81
125
|
reset() {
|
|
82
126
|
set({
|
|
83
127
|
currentConversationId: undefined,
|
|
84
128
|
list: [],
|
|
85
129
|
map: {},
|
|
86
130
|
newConversationSignal: 0,
|
|
131
|
+
removedGroupIds: new Set(),
|
|
87
132
|
});
|
|
88
133
|
},
|
|
89
134
|
}));
|
|
@@ -71,6 +71,37 @@ const i18nKey: Record<string, string> = {
|
|
|
71
71
|
'msg_type_link': '[Liên kết]',
|
|
72
72
|
'msg_type_revoke': 'Đã thu hồi tin nhắn',
|
|
73
73
|
'chat:revoked_by_sender': '{{sender}} đã thu hồi tin nhắn',
|
|
74
|
+
'msg_type_group_created': 'Đã tạo nhóm',
|
|
75
|
+
'chat:group_created_by': '{{sender}} đã tạo nhóm',
|
|
76
|
+
'msg_type_group_name_updated': 'Đã đổi tên nhóm',
|
|
77
|
+
'chat:group_name_updated_by': '{{sender}} đã đổi tên nhóm',
|
|
78
|
+
'msg_type_group_info_updated': 'Đã cập nhật thông tin nhóm',
|
|
79
|
+
'chat:group_info_updated_by': '{{sender}} đã cập nhật thông tin nhóm',
|
|
80
|
+
'msg_type_member_quit': 'Đã rời khỏi nhóm',
|
|
81
|
+
'chat:member_quit_by': '{{sender}} đã rời khỏi nhóm',
|
|
82
|
+
'msg_type_group_owner_transferred': 'Đã chuyển quyền trưởng nhóm',
|
|
83
|
+
'chat:group_owner_transferred_by': '{{sender}} đã chuyển quyền trưởng nhóm',
|
|
84
|
+
'msg_type_member_kicked': 'Đã xoá thành viên khỏi nhóm',
|
|
85
|
+
'chat:member_kicked_by': '{{sender}} đã xoá thành viên khỏi nhóm',
|
|
86
|
+
'msg_type_member_invited': 'Đã thêm thành viên vào nhóm',
|
|
87
|
+
'chat:member_invited_by': '{{sender}} đã thêm thành viên vào nhóm',
|
|
88
|
+
'msg_type_member_enter': 'Đã tham gia nhóm',
|
|
89
|
+
'chat:member_enter_by': '{{sender}} đã tham gia nhóm',
|
|
90
|
+
'msg_type_group_dismissed': 'Nhóm đã bị giải tán',
|
|
91
|
+
'chat:group_dismissed_by': '{{sender}} đã giải tán nhóm',
|
|
92
|
+
'msg_type_group_member_muted': 'Đã tắt tiếng thành viên',
|
|
93
|
+
'chat:group_member_muted_by': '{{sender}} đã tắt tiếng thành viên',
|
|
94
|
+
'msg_type_group_member_cancel_muted': 'Đã bật tiếng thành viên',
|
|
95
|
+
'chat:group_member_cancel_muted_by': '{{sender}} đã bật tiếng thành viên',
|
|
96
|
+
'msg_type_group_muted': 'Đã tắt tiếng cả nhóm',
|
|
97
|
+
'chat:group_muted_by': '{{sender}} đã tắt tiếng cả nhóm',
|
|
98
|
+
'msg_type_group_cancel_muted': 'Đã bật tiếng cả nhóm',
|
|
99
|
+
'chat:group_cancel_muted_by': '{{sender}} đã bật tiếng cả nhóm',
|
|
100
|
+
'msg_type_group_announcement_updated': 'Đã cập nhật thông báo nhóm',
|
|
101
|
+
'chat:group_announcement_updated_by': '{{sender}} đã cập nhật thông báo nhóm',
|
|
102
|
+
'msg_type_friend_added': 'Đã trở thành bạn bè',
|
|
103
|
+
'msg_type_oa_notification': 'Thông báo mới',
|
|
104
|
+
'msg_type_burn_message_change': 'Đã thay đổi cài đặt tin nhắn tự huỷ',
|
|
74
105
|
'chat:mute_action': 'Tắt thông báo',
|
|
75
106
|
'chat:unmute_action': 'Bật thông báo',
|
|
76
107
|
'chat:mute_confirm_title': 'Tắt thông báo',
|
package/src/types/events.ts
CHANGED
|
@@ -5,6 +5,7 @@ export enum ChatEvent {
|
|
|
5
5
|
ScrollToBottom = 'chat:scroll_to_bottom',
|
|
6
6
|
MessageRevoked = 'chat:message_revoked',
|
|
7
7
|
GroupPermissionUpdated = 'chat:group_permission_updated',
|
|
8
|
+
GroupRemoved = 'chat:group_removed',
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export interface ScrollToMessagePayload {
|
|
@@ -18,3 +19,8 @@ export interface MessageRevokedPayload {
|
|
|
18
19
|
export interface GroupPermissionUpdatedPayload {
|
|
19
20
|
permissions: GroupPermission[];
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
export interface GroupRemovedPayload {
|
|
24
|
+
groupID: string;
|
|
25
|
+
reason: 'left' | 'dismissed' | 'kicked';
|
|
26
|
+
}
|
|
@@ -17,6 +17,70 @@ import type { TextProps } from 'react-native';
|
|
|
17
17
|
export const isMessageRevoked = (message: MessageItem): boolean =>
|
|
18
18
|
message.contentType === MessageType.RevokeMessage;
|
|
19
19
|
|
|
20
|
+
// Group system-notification content types (1501-1520 block): each renders as
|
|
21
|
+
// a neutral preview on its own, and as "{{sender}} <action>" once the
|
|
22
|
+
// operator's name is known (see getSenderName/getNotificationOpUserNickname).
|
|
23
|
+
export const GROUP_NOTIFICATION_TEXT: Partial<
|
|
24
|
+
Record<MessageType, { previewKey: string; bySenderKey: string }>
|
|
25
|
+
> = {
|
|
26
|
+
[MessageType.GroupCreated]: {
|
|
27
|
+
previewKey: 'msg_type_group_created',
|
|
28
|
+
bySenderKey: 'chat:group_created_by',
|
|
29
|
+
},
|
|
30
|
+
[MessageType.GroupInfoUpdated]: {
|
|
31
|
+
previewKey: 'msg_type_group_info_updated',
|
|
32
|
+
bySenderKey: 'chat:group_info_updated_by',
|
|
33
|
+
},
|
|
34
|
+
[MessageType.MemberQuit]: {
|
|
35
|
+
previewKey: 'msg_type_member_quit',
|
|
36
|
+
bySenderKey: 'chat:member_quit_by',
|
|
37
|
+
},
|
|
38
|
+
[MessageType.GroupOwnerTransferred]: {
|
|
39
|
+
previewKey: 'msg_type_group_owner_transferred',
|
|
40
|
+
bySenderKey: 'chat:group_owner_transferred_by',
|
|
41
|
+
},
|
|
42
|
+
[MessageType.MemberKicked]: {
|
|
43
|
+
previewKey: 'msg_type_member_kicked',
|
|
44
|
+
bySenderKey: 'chat:member_kicked_by',
|
|
45
|
+
},
|
|
46
|
+
[MessageType.MemberInvited]: {
|
|
47
|
+
previewKey: 'msg_type_member_invited',
|
|
48
|
+
bySenderKey: 'chat:member_invited_by',
|
|
49
|
+
},
|
|
50
|
+
[MessageType.MemberEnter]: {
|
|
51
|
+
previewKey: 'msg_type_member_enter',
|
|
52
|
+
bySenderKey: 'chat:member_enter_by',
|
|
53
|
+
},
|
|
54
|
+
[MessageType.GroupDismissed]: {
|
|
55
|
+
previewKey: 'msg_type_group_dismissed',
|
|
56
|
+
bySenderKey: 'chat:group_dismissed_by',
|
|
57
|
+
},
|
|
58
|
+
[MessageType.GroupMemberMuted]: {
|
|
59
|
+
previewKey: 'msg_type_group_member_muted',
|
|
60
|
+
bySenderKey: 'chat:group_member_muted_by',
|
|
61
|
+
},
|
|
62
|
+
[MessageType.GroupMemberCancelMuted]: {
|
|
63
|
+
previewKey: 'msg_type_group_member_cancel_muted',
|
|
64
|
+
bySenderKey: 'chat:group_member_cancel_muted_by',
|
|
65
|
+
},
|
|
66
|
+
[MessageType.GroupMuted]: {
|
|
67
|
+
previewKey: 'msg_type_group_muted',
|
|
68
|
+
bySenderKey: 'chat:group_muted_by',
|
|
69
|
+
},
|
|
70
|
+
[MessageType.GroupCancelMuted]: {
|
|
71
|
+
previewKey: 'msg_type_group_cancel_muted',
|
|
72
|
+
bySenderKey: 'chat:group_cancel_muted_by',
|
|
73
|
+
},
|
|
74
|
+
[MessageType.GroupAnnouncementUpdated]: {
|
|
75
|
+
previewKey: 'msg_type_group_announcement_updated',
|
|
76
|
+
bySenderKey: 'chat:group_announcement_updated_by',
|
|
77
|
+
},
|
|
78
|
+
[MessageType.GroupNameUpdated]: {
|
|
79
|
+
previewKey: 'msg_type_group_name_updated',
|
|
80
|
+
bySenderKey: 'chat:group_name_updated_by',
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
20
84
|
export const extractTextContent = (message: MessageItem): string => {
|
|
21
85
|
if (message.textElem?.content) return message.textElem.content;
|
|
22
86
|
try {
|
|
@@ -102,8 +166,23 @@ export const getMessagePreview = (message?: MessageItem): string => {
|
|
|
102
166
|
|
|
103
167
|
case MessageType.StickerMessage:
|
|
104
168
|
return '[Sticker]';
|
|
105
|
-
|
|
169
|
+
|
|
170
|
+
case MessageType.FriendAdded:
|
|
171
|
+
return trans('msg_type_friend_added');
|
|
172
|
+
|
|
173
|
+
case MessageType.OANotification:
|
|
174
|
+
return trans('msg_type_oa_notification');
|
|
175
|
+
|
|
176
|
+
case MessageType.BurnMessageChange:
|
|
177
|
+
return trans('msg_type_burn_message_change');
|
|
178
|
+
|
|
179
|
+
default: {
|
|
180
|
+
const groupNotification = GROUP_NOTIFICATION_TEXT[message.contentType];
|
|
181
|
+
if (groupNotification) {
|
|
182
|
+
return trans(groupNotification.previewKey);
|
|
183
|
+
}
|
|
106
184
|
return '[Tin nhắn không được hỗ trợ]';
|
|
185
|
+
}
|
|
107
186
|
}
|
|
108
187
|
};
|
|
109
188
|
|
|
@@ -216,6 +295,23 @@ export const getPinnedMessagePreview = (
|
|
|
216
295
|
}
|
|
217
296
|
};
|
|
218
297
|
|
|
298
|
+
// Group notification messages (renamed/created/etc.) don't always carry
|
|
299
|
+
// `senderNickname` at the top level — the operator's nickname only lives
|
|
300
|
+
// inside the JSON-encoded `notificationElem.detail.opUser`.
|
|
301
|
+
export const getNotificationOpUserNickname = (
|
|
302
|
+
message: MessageItem
|
|
303
|
+
): string | undefined => {
|
|
304
|
+
if (!message.notificationElem?.detail) return undefined;
|
|
305
|
+
try {
|
|
306
|
+
const parsed = JSON.parse(message.notificationElem.detail) as {
|
|
307
|
+
opUser?: { nickname?: string };
|
|
308
|
+
};
|
|
309
|
+
return parsed?.opUser?.nickname;
|
|
310
|
+
} catch {
|
|
311
|
+
return undefined;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
219
315
|
export const getSenderName = (
|
|
220
316
|
message: MessageItem,
|
|
221
317
|
currentUserId?: string,
|
|
@@ -225,6 +321,7 @@ export const getSenderName = (
|
|
|
225
321
|
currentUserId && message.sendID === currentUserId
|
|
226
322
|
? 'Bạn'
|
|
227
323
|
: message?.senderNickname ||
|
|
324
|
+
getNotificationOpUserNickname(message) ||
|
|
228
325
|
(conversation?.peerType === PeerType.Bot
|
|
229
326
|
? conversation?.showName || ''
|
|
230
327
|
: undefined);
|
|
@@ -256,6 +353,11 @@ export const getLastMessageText = ({
|
|
|
256
353
|
return trans('chat:revoked_by_sender', { sender });
|
|
257
354
|
}
|
|
258
355
|
|
|
356
|
+
const groupNotification = GROUP_NOTIFICATION_TEXT[message.contentType];
|
|
357
|
+
if (groupNotification) {
|
|
358
|
+
return trans(groupNotification.bySenderKey, { sender });
|
|
359
|
+
}
|
|
360
|
+
|
|
259
361
|
const hideSenderPrefix =
|
|
260
362
|
hideSenderPrefixForDirectChat && conversation?.peerType === PeerType.User;
|
|
261
363
|
|