@droppii-org/chat-mobile 0.2.63 → 0.2.65
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/flows/inputButtons/index.js +11 -6
- package/lib/module/components/flows/inputButtons/index.js.map +1 -1
- package/lib/module/components/messages/linkMessage/index.js +4 -2
- package/lib/module/components/messages/linkMessage/index.js.map +1 -1
- package/lib/module/components/messages/quotedMessage/index.js +3 -2
- package/lib/module/components/messages/quotedMessage/index.js.map +1 -1
- package/lib/module/components/messages/styles.js +6 -1
- package/lib/module/components/messages/styles.js.map +1 -1
- package/lib/module/components/messages/textMessage/index.js +3 -2
- package/lib/module/components/messages/textMessage/index.js.map +1 -1
- package/lib/module/components/messages/types.js.map +1 -1
- package/lib/module/context/ChatDetailContext.js +29 -6
- package/lib/module/context/ChatDetailContext.js.map +1 -1
- package/lib/module/core/useChatListener.js +21 -10
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/hooks/flows/useFlow.js +1 -1
- package/lib/module/hooks/flows/useFlow.js.map +1 -1
- package/lib/module/hooks/message/useSearchMessage.js +39 -14
- package/lib/module/hooks/message/useSearchMessage.js.map +1 -1
- package/lib/module/hooks/message/useSendMessage.js +13 -3
- package/lib/module/hooks/message/useSendMessage.js.map +1 -1
- package/lib/module/screens/SearchConversation/SearchAllResult.js +25 -10
- package/lib/module/screens/SearchConversation/SearchAllResult.js.map +1 -1
- package/lib/module/screens/SearchConversation/SearchEmpty.js +22 -3
- package/lib/module/screens/SearchConversation/SearchEmpty.js.map +1 -1
- package/lib/module/screens/SearchConversation/SearchMessagesResult.js +23 -7
- package/lib/module/screens/SearchConversation/SearchMessagesResult.js.map +1 -1
- package/lib/module/screens/SearchConversation/SearchResultItem.js +53 -12
- package/lib/module/screens/SearchConversation/SearchResultItem.js.map +1 -1
- package/lib/module/screens/SearchMessage/SearchMessageResult.js +24 -7
- package/lib/module/screens/SearchMessage/SearchMessageResult.js.map +1 -1
- package/lib/module/screens/SearchMessage/SearchResultItem.js +31 -3
- package/lib/module/screens/SearchMessage/SearchResultItem.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatComposer.js +12 -1
- package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatListLegend.js +26 -17
- package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +4 -2
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
- package/lib/module/store/message.js +3 -0
- package/lib/module/store/message.js.map +1 -1
- package/lib/module/translation/resources/i18n.js +7 -2
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/module/types/chat.js.map +1 -1
- package/lib/module/types/events.js +2 -0
- package/lib/module/types/events.js.map +1 -1
- package/lib/module/utils/flows.js +4 -4
- package/lib/module/utils/flows.js.map +1 -1
- package/lib/module/utils/highlightSearch.js +38 -0
- package/lib/module/utils/highlightSearch.js.map +1 -0
- package/lib/module/utils/messageUtils.js +5 -1
- package/lib/module/utils/messageUtils.js.map +1 -1
- package/lib/typescript/src/components/flows/inputButtons/index.d.ts +1 -1
- package/lib/typescript/src/components/flows/inputButtons/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/quotedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/styles.d.ts +5 -0
- package/lib/typescript/src/components/messages/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/types.d.ts +1 -0
- package/lib/typescript/src/components/messages/types.d.ts.map +1 -1
- 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/flows/useFlow.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSearchMessage.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchConversation/SearchAllResult.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchConversation/SearchEmpty.d.ts +7 -1
- package/lib/typescript/src/screens/SearchConversation/SearchEmpty.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchConversation/SearchMessagesResult.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchConversation/SearchResultItem.d.ts +1 -0
- package/lib/typescript/src/screens/SearchConversation/SearchResultItem.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchMessage/SearchMessageResult.d.ts.map +1 -1
- package/lib/typescript/src/screens/SearchMessage/SearchResultItem.d.ts +1 -0
- package/lib/typescript/src/screens/SearchMessage/SearchResultItem.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/ChatListLegend.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +2 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
- package/lib/typescript/src/store/message.d.ts.map +1 -1
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/lib/typescript/src/types/chat.d.ts +3 -2
- package/lib/typescript/src/types/chat.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +10 -1
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/types/flows.d.ts +4 -0
- package/lib/typescript/src/types/flows.d.ts.map +1 -1
- package/lib/typescript/src/utils/flows.d.ts +1 -1
- package/lib/typescript/src/utils/flows.d.ts.map +1 -1
- package/lib/typescript/src/utils/highlightSearch.d.ts +7 -0
- package/lib/typescript/src/utils/highlightSearch.d.ts.map +1 -0
- package/lib/typescript/src/utils/messageUtils.d.ts +1 -0
- package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/flows/inputButtons/index.tsx +20 -12
- package/src/components/messages/linkMessage/index.tsx +3 -0
- package/src/components/messages/quotedMessage/index.tsx +2 -1
- package/src/components/messages/styles.ts +6 -1
- package/src/components/messages/textMessage/index.tsx +7 -1
- package/src/components/messages/types.ts +1 -0
- package/src/context/ChatDetailContext.tsx +57 -11
- package/src/core/useChatListener.ts +53 -17
- package/src/hooks/flows/useFlow.ts +5 -1
- package/src/hooks/message/useSearchMessage.ts +46 -15
- package/src/hooks/message/useSendMessage.ts +21 -2
- package/src/screens/SearchConversation/SearchAllResult.tsx +24 -10
- package/src/screens/SearchConversation/SearchEmpty.tsx +38 -14
- package/src/screens/SearchConversation/SearchMessagesResult.tsx +39 -18
- package/src/screens/SearchConversation/SearchResultItem.tsx +72 -13
- package/src/screens/SearchMessage/SearchMessageResult.tsx +47 -20
- package/src/screens/SearchMessage/SearchResultItem.tsx +37 -5
- package/src/screens/chat-detail/ChatComposer.tsx +17 -1
- package/src/screens/chat-detail/ChatListLegend.tsx +48 -21
- package/src/screens/chat-detail/legend/LegendChatMessage.tsx +3 -0
- package/src/store/message.ts +2 -0
- package/src/translation/resources/i18n.ts +7 -2
- package/src/types/chat.ts +7 -1
- package/src/types/events.ts +12 -0
- package/src/types/flows.ts +4 -0
- package/src/utils/flows.ts +5 -6
- package/src/utils/highlightSearch.ts +48 -0
- package/src/utils/messageUtils.ts +16 -7
|
@@ -29,10 +29,13 @@ import { LegendChatMessage } from './legend/LegendChatMessage';
|
|
|
29
29
|
import { LegendChatDay } from './legend/LegendChatDay';
|
|
30
30
|
import { LegendChatLoadEarlier } from './legend/LegendChatLoadEarlier';
|
|
31
31
|
import { useChatDetailContext } from '../../context/ChatDetailContext';
|
|
32
|
-
import {
|
|
32
|
+
import { getFlowInputButtonsNodes } from '../../utils/flows';
|
|
33
33
|
import { InputButtonFlow } from '../../components/flows/inputButtons';
|
|
34
34
|
import { useResetFlow, useRunFlow } from '../../hooks/flows/useFlow';
|
|
35
|
-
import type {
|
|
35
|
+
import type {
|
|
36
|
+
GroupChild,
|
|
37
|
+
IRunConversationFlowPayload,
|
|
38
|
+
} from '../../types/flows';
|
|
36
39
|
import { useSendMessage } from '../../hooks/message/useSendMessage';
|
|
37
40
|
import { ChatEvent, type ScrollToMessagePayload } from '../../types/events';
|
|
38
41
|
import { useMessageStore } from '../../store/message';
|
|
@@ -110,6 +113,10 @@ export const ChatListLegend = memo(
|
|
|
110
113
|
const scrollDebounceRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
|
111
114
|
const rowRefsMap = useRef<Map<string, View | null>>(new Map());
|
|
112
115
|
const [showBadge, setShowBadge] = useState(false);
|
|
116
|
+
const [highlightedId, setHighlightedId] = useState<string | null>(null);
|
|
117
|
+
const highlightTimerRef = useRef<ReturnType<typeof setTimeout> | null>(
|
|
118
|
+
null
|
|
119
|
+
);
|
|
113
120
|
|
|
114
121
|
const { applicationType } = useChatContext();
|
|
115
122
|
const searchMessages = useMessageStore((s) => s.searchMessages);
|
|
@@ -143,9 +150,9 @@ export const ChatListLegend = memo(
|
|
|
143
150
|
|
|
144
151
|
const message = item as MessageItem;
|
|
145
152
|
const isOutgoing = message.sendID === currentUserId;
|
|
146
|
-
const
|
|
147
|
-
!isOutgoing &&
|
|
153
|
+
const isLastMessage =
|
|
148
154
|
(message.clientMsgID || message.serverMsgID) === lastMessageId;
|
|
155
|
+
const isLastIncoming = !isOutgoing && isLastMessage;
|
|
149
156
|
const messageId =
|
|
150
157
|
message.clientMsgID ||
|
|
151
158
|
message.serverMsgID ||
|
|
@@ -158,9 +165,13 @@ export const ChatListLegend = memo(
|
|
|
158
165
|
|
|
159
166
|
const { dayStart, createdAt } = messageData;
|
|
160
167
|
|
|
161
|
-
let
|
|
162
|
-
if (
|
|
163
|
-
|
|
168
|
+
let flowInputButtonsNodes: GroupChild<'input-buttons'>[] = [];
|
|
169
|
+
if (
|
|
170
|
+
((isLastMessage && conversationFlow?.havingBotMessage === false) ||
|
|
171
|
+
isLastIncoming) &&
|
|
172
|
+
isBotConversation
|
|
173
|
+
) {
|
|
174
|
+
flowInputButtonsNodes = getFlowInputButtonsNodes(
|
|
164
175
|
conversationFlow?.flowCurrentStep
|
|
165
176
|
);
|
|
166
177
|
}
|
|
@@ -193,15 +204,16 @@ export const ChatListLegend = memo(
|
|
|
193
204
|
: undefined
|
|
194
205
|
}
|
|
195
206
|
customMessageItemFactory={customMessageItemFactory}
|
|
207
|
+
isHighlighted={highlightedId === messageId}
|
|
196
208
|
/>
|
|
197
|
-
{!!flowInputButtonsNode && (
|
|
198
|
-
<InputButtonFlow
|
|
199
|
-
nodeData={flowInputButtonsNode}
|
|
200
|
-
onResetFlow={onResetFlow}
|
|
201
|
-
onRunFlow={onRunFlow}
|
|
202
|
-
/>
|
|
203
|
-
)}
|
|
204
209
|
</KContainer.View>
|
|
210
|
+
{flowInputButtonsNodes && flowInputButtonsNodes.length > 0 && (
|
|
211
|
+
<InputButtonFlow
|
|
212
|
+
nodeData={flowInputButtonsNodes}
|
|
213
|
+
onResetFlow={onResetFlow}
|
|
214
|
+
onRunFlow={onRunFlow}
|
|
215
|
+
/>
|
|
216
|
+
)}
|
|
205
217
|
</>
|
|
206
218
|
);
|
|
207
219
|
} catch (error) {
|
|
@@ -229,7 +241,9 @@ export const ChatListLegend = memo(
|
|
|
229
241
|
onResetFlow,
|
|
230
242
|
onRunFlow,
|
|
231
243
|
conversationFlow?.flowCurrentStep,
|
|
244
|
+
conversationFlow?.havingBotMessage,
|
|
232
245
|
retryMessage,
|
|
246
|
+
highlightedId,
|
|
233
247
|
]
|
|
234
248
|
);
|
|
235
249
|
|
|
@@ -320,10 +334,13 @@ export const ChatListLegend = memo(
|
|
|
320
334
|
|
|
321
335
|
const isOutgoing = message.sendID === currentUserId;
|
|
322
336
|
const isLastIncoming = !isOutgoing && messageId === lastMessageId;
|
|
337
|
+
const flowInputButtonsNodes = getFlowInputButtonsNodes(
|
|
338
|
+
conversationFlow?.flowCurrentStep
|
|
339
|
+
);
|
|
323
340
|
if (
|
|
324
341
|
isLastIncoming &&
|
|
325
342
|
isBotConversation &&
|
|
326
|
-
|
|
343
|
+
flowInputButtonsNodes.length > 0
|
|
327
344
|
) {
|
|
328
345
|
return undefined;
|
|
329
346
|
}
|
|
@@ -427,11 +444,21 @@ export const ChatListLegend = memo(
|
|
|
427
444
|
|
|
428
445
|
if (index >= 0) {
|
|
429
446
|
try {
|
|
430
|
-
listRef.current
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
447
|
+
listRef.current
|
|
448
|
+
?.scrollToIndex({
|
|
449
|
+
index,
|
|
450
|
+
animated: true,
|
|
451
|
+
viewPosition: 0.5,
|
|
452
|
+
})
|
|
453
|
+
.finally(() => {
|
|
454
|
+
if (highlightTimerRef.current)
|
|
455
|
+
clearTimeout(highlightTimerRef.current);
|
|
456
|
+
setHighlightedId(clientMessageId);
|
|
457
|
+
highlightTimerRef.current = setTimeout(
|
|
458
|
+
() => setHighlightedId(null),
|
|
459
|
+
5000
|
|
460
|
+
);
|
|
461
|
+
});
|
|
435
462
|
} catch {
|
|
436
463
|
// scrollToIndex throws if item not rendered yet — force refetch messages
|
|
437
464
|
searchMessages({
|
|
@@ -487,7 +514,7 @@ export const ChatListLegend = memo(
|
|
|
487
514
|
getFixedItemSize={getFixedItemSize}
|
|
488
515
|
keyExtractor={(item) => String(item.clientMsgID || item.serverMsgID)}
|
|
489
516
|
recycleItems={false}
|
|
490
|
-
extraData={`${conversationFlow?.flowCurrentStep?.id ?? ''}-${lastMessageId ?? ''}`}
|
|
517
|
+
extraData={`${conversationFlow?.flowCurrentStep?.id ?? ''}-${lastMessageId ?? ''}-${highlightedId ?? ''}`}
|
|
491
518
|
alignItemsAtEnd
|
|
492
519
|
maintainVisibleContentPosition={maintainVisiblePositionConfig}
|
|
493
520
|
maintainScrollAtEnd={true}
|
|
@@ -35,6 +35,7 @@ interface LegendChatMessageProps {
|
|
|
35
35
|
onPress?: (message: MessageItem) => void;
|
|
36
36
|
onLongPress?: () => void;
|
|
37
37
|
customMessageItemFactory?: (m: MessageItem) => ReactNode;
|
|
38
|
+
isHighlighted?: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
const messageComponentMap: Partial<
|
|
@@ -69,6 +70,7 @@ export const LegendChatMessage = memo(
|
|
|
69
70
|
onPress,
|
|
70
71
|
onLongPress,
|
|
71
72
|
customMessageItemFactory,
|
|
73
|
+
isHighlighted,
|
|
72
74
|
}: LegendChatMessageProps) => {
|
|
73
75
|
const handlePress = useCallback(() => {
|
|
74
76
|
onPress?.(message);
|
|
@@ -107,6 +109,7 @@ export const LegendChatMessage = memo(
|
|
|
107
109
|
createdAtTime={createdAtTime}
|
|
108
110
|
onMediaPress={hasMediaPress ? onMediaPress : undefined}
|
|
109
111
|
onPressUrl={hasUrlPress ? onPressUrl : undefined}
|
|
112
|
+
isHighlighted={isHighlighted}
|
|
110
113
|
/>
|
|
111
114
|
</LongPressWrapper>
|
|
112
115
|
|
package/src/store/message.ts
CHANGED
|
@@ -224,6 +224,8 @@ export const markMessageRevoked = (clientMsgID: string) => {
|
|
|
224
224
|
.getState()
|
|
225
225
|
.updateOneMessage({ clientMsgID, contentType: MessageType.RevokeMessage });
|
|
226
226
|
|
|
227
|
+
DeviceEventEmitter.emit(ChatEvent.MessageRevoked, { clientMsgID });
|
|
228
|
+
|
|
227
229
|
revokeQuotedReferences(clientMsgID);
|
|
228
230
|
};
|
|
229
231
|
|
|
@@ -122,9 +122,14 @@ const i18nKey: Record<string, string> = {
|
|
|
122
122
|
'all': 'Tất cả',
|
|
123
123
|
'contacts': 'Liên hệ',
|
|
124
124
|
'messages': 'Tin nhắn',
|
|
125
|
-
'search:empty_description':
|
|
126
|
-
|
|
125
|
+
'search:empty_description': 'Không tìm thấy kết quả nào',
|
|
126
|
+
'search:empty_hint':
|
|
127
|
+
'Bạn có thể tìm kiếm theo liên hệ hoặc nội dung tin nhắn',
|
|
128
|
+
'search_message:empty_hint': 'Bạn có thể tìm kiếm theo nội dung tin nhắn',
|
|
129
|
+
'search_conversation:empty_hint': 'Bạn có thể tìm kiếm theo liên hệ',
|
|
127
130
|
'view_all': 'Xem tất cả',
|
|
131
|
+
'search_message:revoked_message': 'Tin nhắn đã được thu hồi',
|
|
132
|
+
'chat:no_send_permission': 'Bạn không có quyền gửi tin nhắn',
|
|
128
133
|
};
|
|
129
134
|
|
|
130
135
|
export default {
|
package/src/types/chat.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
GroupPermission,
|
|
2
3
|
MessageType,
|
|
3
4
|
type ConversationItem,
|
|
4
5
|
type MessageItem,
|
|
@@ -205,13 +206,18 @@ export interface MessageStore {
|
|
|
205
206
|
export interface ChatDetailContextType {
|
|
206
207
|
conversationFlow?: IConversationFlow;
|
|
207
208
|
isBotConversation: boolean;
|
|
208
|
-
setConverationFlowStep: (
|
|
209
|
+
setConverationFlowStep: (
|
|
210
|
+
step?: IConversationFlowStep,
|
|
211
|
+
isEnd?: boolean,
|
|
212
|
+
havingBotMessage?: boolean
|
|
213
|
+
) => void;
|
|
209
214
|
flowState?: DFlowState;
|
|
210
215
|
runButtonContext: (stringContext: DFlowContext) => Promise<boolean>;
|
|
211
216
|
conversation?: ConversationItem;
|
|
212
217
|
quotedMessage?: MessageItem;
|
|
213
218
|
setQuotedMessage: (item?: MessageItem) => void;
|
|
214
219
|
conversationFlowMainMenu?: InputButtonItem[];
|
|
220
|
+
groupPermissions: GroupPermission[];
|
|
215
221
|
}
|
|
216
222
|
|
|
217
223
|
export interface ChatDetailProviderProps extends PropsWithChildren {}
|
package/src/types/events.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
import type { GroupPermission } from '@droppii/openim-rn-client-sdk';
|
|
2
|
+
|
|
1
3
|
export enum ChatEvent {
|
|
2
4
|
ScrollToMessage = 'chat:scroll_to_message',
|
|
3
5
|
ScrollToBottom = 'chat:scroll_to_bottom',
|
|
6
|
+
MessageRevoked = 'chat:message_revoked',
|
|
7
|
+
GroupPermissionUpdated = 'chat:group_permission_updated',
|
|
4
8
|
}
|
|
5
9
|
|
|
6
10
|
export interface ScrollToMessagePayload {
|
|
7
11
|
clientMessageId: string;
|
|
8
12
|
}
|
|
13
|
+
|
|
14
|
+
export interface MessageRevokedPayload {
|
|
15
|
+
clientMsgID: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GroupPermissionUpdatedPayload {
|
|
19
|
+
permissions: GroupPermission[];
|
|
20
|
+
}
|
package/src/types/flows.ts
CHANGED
|
@@ -91,10 +91,14 @@ export interface IConversationFlow {
|
|
|
91
91
|
chatType: PeerType;
|
|
92
92
|
applicationType: DChatApplicationType;
|
|
93
93
|
flowCurrentStep: IConversationFlowStep | null;
|
|
94
|
+
havingBotMessage: boolean;
|
|
95
|
+
flowIsEnd: boolean;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
export interface IRunConversationFlowResponse {
|
|
97
99
|
flowNextStep: IConversationFlowStep | null;
|
|
100
|
+
isEnd: boolean;
|
|
101
|
+
havingBotMessage: boolean;
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
export interface IRunConversationFlowPayload {
|
package/src/utils/flows.ts
CHANGED
|
@@ -4,15 +4,14 @@ import {
|
|
|
4
4
|
type IConversationFlowStep,
|
|
5
5
|
} from '../types/flows';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const getFlowInputButtonsNodes = (
|
|
8
8
|
step?: IConversationFlowStep | null
|
|
9
9
|
) => {
|
|
10
|
-
if (!step) return
|
|
10
|
+
if (!step) return [];
|
|
11
11
|
const childrenNode = step?.data?.children || [];
|
|
12
|
-
const
|
|
13
|
-
(f) => f.type === NodeTypes.InputButtons
|
|
14
|
-
|
|
15
|
-
return inputButtonsNode;
|
|
12
|
+
const inputButtonsNodes =
|
|
13
|
+
childrenNode?.filter?.((f) => f.type === NodeTypes.InputButtons) || [];
|
|
14
|
+
return inputButtonsNodes as GroupChild<'input-buttons'>[];
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
export const DEFAULT_BUTTON_ID = 'default-item-button';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface HighlightResult {
|
|
2
|
+
before: string;
|
|
3
|
+
match: string;
|
|
4
|
+
after: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const highlightSearch = (
|
|
8
|
+
text: string,
|
|
9
|
+
keyword: string,
|
|
10
|
+
maxLength = 30
|
|
11
|
+
): HighlightResult | null => {
|
|
12
|
+
if (!keyword) return null;
|
|
13
|
+
|
|
14
|
+
const lowerText = text.toLowerCase();
|
|
15
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
16
|
+
const index = lowerText.indexOf(lowerKeyword);
|
|
17
|
+
|
|
18
|
+
if (index === -1) return null;
|
|
19
|
+
|
|
20
|
+
const before = text.slice(0, index);
|
|
21
|
+
const match = text.slice(index, index + keyword.length);
|
|
22
|
+
const after = text.slice(index + keyword.length);
|
|
23
|
+
|
|
24
|
+
if (keyword.length >= maxLength) {
|
|
25
|
+
return { before: '', match: match.slice(0, maxLength), after: '' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const remain = maxLength - match.length;
|
|
29
|
+
let left = Math.floor(remain / 2);
|
|
30
|
+
let right = remain - left;
|
|
31
|
+
|
|
32
|
+
if (before.length < left) {
|
|
33
|
+
right += left - before.length;
|
|
34
|
+
left = before.length;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (after.length < right) {
|
|
38
|
+
left += right - after.length;
|
|
39
|
+
right = after.length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const displayedBefore =
|
|
43
|
+
before.length > left ? '…' + before.slice(before.length - left) : before;
|
|
44
|
+
const displayedAfter =
|
|
45
|
+
after.length > right ? after.slice(0, right) + '…' : after;
|
|
46
|
+
|
|
47
|
+
return { before: displayedBefore, match, after: displayedAfter };
|
|
48
|
+
};
|
|
@@ -216,6 +216,21 @@ export const getPinnedMessagePreview = (
|
|
|
216
216
|
}
|
|
217
217
|
};
|
|
218
218
|
|
|
219
|
+
export const getSenderName = (
|
|
220
|
+
message: MessageItem,
|
|
221
|
+
currentUserId?: string,
|
|
222
|
+
conversation?: ConversationItem
|
|
223
|
+
): string => {
|
|
224
|
+
const sender =
|
|
225
|
+
currentUserId && message.sendID === currentUserId
|
|
226
|
+
? 'Bạn'
|
|
227
|
+
: message?.senderNickname ||
|
|
228
|
+
(conversation?.peerType === PeerType.Bot
|
|
229
|
+
? conversation?.showName || ''
|
|
230
|
+
: undefined);
|
|
231
|
+
return sender || '';
|
|
232
|
+
};
|
|
233
|
+
|
|
219
234
|
export interface GetLastMessageTextParams {
|
|
220
235
|
message: MessageItem | undefined;
|
|
221
236
|
currentUserId?: string;
|
|
@@ -233,13 +248,7 @@ export const getLastMessageText = ({
|
|
|
233
248
|
const preview = getMessagePreview(message);
|
|
234
249
|
if (!preview) return '';
|
|
235
250
|
|
|
236
|
-
const sender =
|
|
237
|
-
currentUserId && message.sendID === currentUserId
|
|
238
|
-
? 'Bạn'
|
|
239
|
-
: message.senderNickname ||
|
|
240
|
-
(conversation?.peerType === PeerType.Bot
|
|
241
|
-
? conversation?.showName || ''
|
|
242
|
-
: undefined);
|
|
251
|
+
const sender = getSenderName(message, currentUserId, conversation);
|
|
243
252
|
|
|
244
253
|
if (!sender) return preview;
|
|
245
254
|
|