react-native-chatbot-ai 0.1.38 → 0.1.40

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.
Files changed (55) hide show
  1. package/lib/module/components/Drawer/RenameSessionPopup.js +2 -1
  2. package/lib/module/components/Drawer/RenameSessionPopup.js.map +1 -1
  3. package/lib/module/components/Drawer/SessionOptionsBottomSheet.js +1 -1
  4. package/lib/module/components/Drawer/SessionOptionsBottomSheet.js.map +1 -1
  5. package/lib/module/components/chat/ChatEmpty.js +2 -6
  6. package/lib/module/components/chat/ChatEmpty.js.map +1 -1
  7. package/lib/module/components/chat/ChatMessageList.js +21 -30
  8. package/lib/module/components/chat/ChatMessageList.js.map +1 -1
  9. package/lib/module/components/chat/footer/index.js +17 -11
  10. package/lib/module/components/chat/footer/index.js.map +1 -1
  11. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js +7 -1
  12. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js.map +1 -1
  13. package/lib/module/components/chat/item/ChatAIThinkingMessageItem.js +1 -6
  14. package/lib/module/components/chat/item/ChatAIThinkingMessageItem.js.map +1 -1
  15. package/lib/module/components/chat/item/index.js +5 -5
  16. package/lib/module/components/chat/item/index.js.map +1 -1
  17. package/lib/module/components/portal/Popup.js +6 -0
  18. package/lib/module/components/portal/Popup.js.map +1 -1
  19. package/lib/module/components/product/CardHorizontal.js +1 -1
  20. package/lib/module/components/product/CardHorizontal.js.map +1 -1
  21. package/lib/module/constants/events.js +0 -1
  22. package/lib/module/constants/events.js.map +1 -1
  23. package/lib/module/hooks/message/useMessage.js +22 -10
  24. package/lib/module/hooks/message/useMessage.js.map +1 -1
  25. package/lib/module/hooks/message/useSendMessage.js +1 -1
  26. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  27. package/lib/module/hooks/message/useStreamMessage.js +10 -12
  28. package/lib/module/hooks/message/useStreamMessage.js.map +1 -1
  29. package/lib/typescript/src/components/chat/ChatMessageList.d.ts.map +1 -1
  30. package/lib/typescript/src/components/chat/footer/index.d.ts.map +1 -1
  31. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts.map +1 -1
  32. package/lib/typescript/src/components/chat/item/ChatAIThinkingMessageItem.d.ts.map +1 -1
  33. package/lib/typescript/src/components/chat/item/index.d.ts +2 -2
  34. package/lib/typescript/src/components/chat/item/index.d.ts.map +1 -1
  35. package/lib/typescript/src/components/portal/Popup.d.ts.map +1 -1
  36. package/lib/typescript/src/constants/events.d.ts +0 -1
  37. package/lib/typescript/src/constants/events.d.ts.map +1 -1
  38. package/lib/typescript/src/hooks/message/useMessage.d.ts.map +1 -1
  39. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  40. package/lib/typescript/src/hooks/message/useStreamMessage.d.ts.map +1 -1
  41. package/package.json +2 -2
  42. package/src/components/Drawer/RenameSessionPopup.tsx +1 -0
  43. package/src/components/Drawer/SessionOptionsBottomSheet.tsx +1 -1
  44. package/src/components/chat/ChatEmpty.tsx +2 -2
  45. package/src/components/chat/ChatMessageList.tsx +21 -32
  46. package/src/components/chat/footer/index.tsx +16 -12
  47. package/src/components/chat/item/ChatAIAnswerMessageItem.tsx +12 -2
  48. package/src/components/chat/item/ChatAIThinkingMessageItem.tsx +1 -7
  49. package/src/components/chat/item/index.tsx +6 -6
  50. package/src/components/portal/Popup.tsx +4 -1
  51. package/src/components/product/CardHorizontal.tsx +1 -1
  52. package/src/constants/events.ts +0 -1
  53. package/src/hooks/message/useMessage.ts +27 -14
  54. package/src/hooks/message/useSendMessage.ts +5 -1
  55. package/src/hooks/message/useStreamMessage.ts +25 -15
@@ -1,5 +1,5 @@
1
1
  import { KColors, KContainer, KLabel, KSpacingValue } from '@droppii/libs';
2
- import { StyleSheet, Platform } from 'react-native';
2
+ import { StyleSheet } from 'react-native';
3
3
  import { useFetchSuggestions } from '../../hooks/suggestions/useFetchSuggestions';
4
4
  import SuggestionItem from './SuggestionItem';
5
5
  import { useSendMessage } from '../../hooks/message/useSendMessage';
@@ -72,7 +72,7 @@ const styles = StyleSheet.create({
72
72
  gap: KSpacingValue['0.5rem'],
73
73
  },
74
74
  transformStyle: {
75
- transform: [Platform.OS === 'android' ? { scale: -1 } : { scaleY: -1 }],
75
+ // transform: [Platform.OS === 'android' ? { scale: -1 } : { scaleY: -1 }],
76
76
  },
77
77
  disclaimer: {
78
78
  fontSize: 11,
@@ -1,11 +1,11 @@
1
- import { FlatList, StyleSheet, DeviceEventEmitter, View } from 'react-native';
1
+ import { FlatList, StyleSheet, View } from 'react-native';
2
2
  import type { ComponentType } from 'react';
3
3
  import { useCallback, useRef, useEffect, useState } from 'react';
4
4
  import ChatEmpty from './ChatEmpty';
5
5
  import ChatItem from './item';
6
6
  import { KSpacingValue, KColors, KImage, KContainer } from '@droppii/libs';
7
7
  import type { IMessageItem } from '../../types';
8
- import { events, GAEvents } from '../../constants/events';
8
+ import { GAEvents } from '../../constants/events';
9
9
  import { useChatContext } from '../../context/ChatContext';
10
10
  import useSessionStore from '../../store/session';
11
11
 
@@ -25,37 +25,18 @@ const ChatMessageList = ({ messageList = [] }: IChatMessageListProps) => {
25
25
 
26
26
  const onScroll = useCallback((event: any) => {
27
27
  const offsetY = event?.nativeEvent?.contentOffset?.y ?? 0;
28
+ const layoutHeight = event?.nativeEvent?.layoutMeasurement?.height ?? 0;
29
+ const contentHeight = event?.nativeEvent?.contentSize?.height ?? 0;
28
30
  scrollOffsetRef.current = offsetY;
29
31
 
30
- const threshold = 50;
31
- setShowScrollToBottom(offsetY > threshold);
32
+ const threshold = 20;
33
+ const atBottom = layoutHeight + offsetY >= contentHeight - threshold;
34
+ setShowScrollToBottom(!atBottom);
32
35
  }, []);
33
36
 
34
- const scrollToBottom = useCallback(() => {
35
- flatListRef.current?.scrollToOffset({ offset: 0, animated: true }); // inverted => bottom = offset 0
36
- }, []);
37
-
38
- useEffect(() => {
39
- const subExpandThinkingStep = DeviceEventEmitter.addListener(
40
- events.expandThinkingStep,
41
- (isExpand: boolean) => {
42
- try {
43
- const scrollToOffset = flatListRef.current?.scrollToOffset({
44
- offset: scrollOffsetRef.current + (isExpand ? 60 : -60),
45
- animated: true,
46
- });
47
- setTimeout(() => {
48
- scrollToOffset?.();
49
- }, 100);
50
- } catch (error) {
51
- console.error(error);
52
- }
53
- }
54
- );
55
-
56
- return () => {
57
- subExpandThinkingStep.remove();
58
- };
37
+ const scrollToBottom = useCallback(async () => {
38
+ await new Promise((resolve) => setTimeout(resolve, 300));
39
+ flatListRef.current?.scrollToEnd({ animated: true });
59
40
  }, []);
60
41
 
61
42
  useEffect(() => {
@@ -68,6 +49,12 @@ const ChatMessageList = ({ messageList = [] }: IChatMessageListProps) => {
68
49
  }
69
50
  }, [sessionId, logGA]);
70
51
 
52
+ useEffect(() => {
53
+ if (messageList.length > 0) {
54
+ scrollToBottom();
55
+ }
56
+ }, [messageList, scrollToBottom]);
57
+
71
58
  return (
72
59
  <View style={{ flex: 1 }}>
73
60
  <FlatListComponent
@@ -79,10 +66,12 @@ const ChatMessageList = ({ messageList = [] }: IChatMessageListProps) => {
79
66
  }: {
80
67
  item: IMessageItem;
81
68
  index: number;
82
- }) => <ChatItem item={item} index={index} />}
69
+ }) => (
70
+ <ChatItem item={item} isLastItem={index === messageList.length - 1} />
71
+ )}
83
72
  keyExtractor={(item: IMessageItem) => item.id}
84
73
  contentContainerStyle={styles.container}
85
- inverted
74
+ // inverted
86
75
  ListEmptyComponent={<ChatEmpty />}
87
76
  onScroll={onScroll}
88
77
  scrollEventThrottle={16}
@@ -111,7 +100,7 @@ const styles = StyleSheet.create({
111
100
  flexGrow: 1,
112
101
  gap: KSpacingValue['0.5rem'],
113
102
  paddingVertical: KSpacingValue['1rem'],
114
- justifyContent: 'flex-end',
103
+ // justifyContent: 'flex-end',
115
104
  },
116
105
  scrollButton: {
117
106
  position: 'absolute',
@@ -54,6 +54,7 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
54
54
  const logGA = useChatContext().logGA;
55
55
  const { onSendMessage } = useSendMessage();
56
56
  const [message, setMessage] = useState('');
57
+ const sessionId = useSessionStore((state) => state.sessionId);
57
58
  const isStreaming = useStreamMessageStore((state) => state.isStreaming);
58
59
  const stopStream = useStreamMessageStore((state) => state.stopStream);
59
60
 
@@ -103,6 +104,7 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
103
104
  }, [onPressImagePicker, onPressCameraPicker]);
104
105
 
105
106
  const onPressSend = useCallback(() => {
107
+ if (isDisabledSend) return;
106
108
  if (isStreaming) {
107
109
  stopStream();
108
110
  logGA(GAEvents.chatDetailStopChatBtnTap, {
@@ -132,6 +134,7 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
132
134
  fileUpload,
133
135
  logGA,
134
136
  clearFileUpload,
137
+ isDisabledSend,
135
138
  ]);
136
139
 
137
140
  const renderUploadItem = useCallback(
@@ -164,7 +167,7 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
164
167
  return () => {
165
168
  stopStream();
166
169
  };
167
- }, [stopStream]);
170
+ }, [stopStream, sessionId]);
168
171
 
169
172
  return (
170
173
  <KContainer.View style={styles.container}>
@@ -239,17 +242,18 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
239
242
  />
240
243
  </KContainer.Touchable>
241
244
  <KContainer.View flex />
242
- <KButton.Solid
243
- kind="primary"
244
- icon={{
245
- vectorName: isStreaming ? 'square-b' : 'send-b',
246
- size: 20,
247
- tintColor: KColors.white,
248
- }}
249
- onPress={onPressSend}
250
- br="round"
251
- disabled={isDisabledSend}
252
- />
245
+ <KContainer.View style={{ opacity: isDisabledSend ? 0.5 : 1 }}>
246
+ <KButton.Solid
247
+ kind="primary"
248
+ icon={{
249
+ vectorName: isStreaming ? 'square-b' : 'send-b',
250
+ size: 20,
251
+ tintColor: KColors.white,
252
+ }}
253
+ onPress={onPressSend}
254
+ br="round"
255
+ />
256
+ </KContainer.View>
253
257
  </KContainer.View>
254
258
  </KContainer.View>
255
259
  </KContainer.View>
@@ -199,7 +199,11 @@ class CustomRenderer extends Renderer implements RendererInterface {
199
199
  );
200
200
  default:
201
201
  return (
202
- <KLabel.Text typo="TextMdNormal" key={this.getKey()}>
202
+ <KLabel.Text
203
+ typo="TextMdNormal"
204
+ key={this.getKey()}
205
+ selectable={true}
206
+ >
203
207
  {match?.[2] || ''}
204
208
  </KLabel.Text>
205
209
  );
@@ -225,6 +229,7 @@ class CustomRenderer extends Renderer implements RendererInterface {
225
229
  key={this.getKey()}
226
230
  typo="TextMdNormal"
227
231
  color={KColors.black}
232
+ selectable={true}
228
233
  >
229
234
  {text}
230
235
  </KLabel.Text>
@@ -237,6 +242,7 @@ class CustomRenderer extends Renderer implements RendererInterface {
237
242
  key={this.getKey()}
238
243
  typo="TextMdNormal"
239
244
  color={KColors.black}
245
+ selectable={true}
240
246
  >
241
247
  {text}
242
248
  </KLabel.Text>
@@ -250,6 +256,7 @@ class CustomRenderer extends Renderer implements RendererInterface {
250
256
  typo="TextMdBold"
251
257
  style={styles.mdStrong}
252
258
  color={KColors.black}
259
+ selectable={true}
253
260
  >
254
261
  {children}
255
262
  </KLabel.Text>
@@ -262,6 +269,7 @@ class CustomRenderer extends Renderer implements RendererInterface {
262
269
  typo="TextMdNormal"
263
270
  style={styles.mdEm}
264
271
  color={KColors.black}
272
+ selectable={true}
265
273
  >
266
274
  {children}
267
275
  </KLabel.Text>
@@ -286,6 +294,7 @@ class CustomRenderer extends Renderer implements RendererInterface {
286
294
  typo="TextMdNormal"
287
295
  style={textStyle}
288
296
  color={KColors.gray.dark}
297
+ selectable={true}
289
298
  >
290
299
  {text}
291
300
  </KLabel.Text>
@@ -500,10 +509,11 @@ const ChatAIAnswerMessageItem = ({
500
509
  ))}
501
510
 
502
511
  {/* Message Actions Bar */}
512
+
503
513
  <MessageActionsBar
504
514
  messageId={item.id}
505
515
  messageContent={item.content}
506
- isVisible={!isStreaming}
516
+ isVisible={!isStreaming || (isStreaming && !isLast)}
507
517
  productImages={productImages}
508
518
  message={item}
509
519
  />
@@ -8,14 +8,13 @@ import {
8
8
  } from '@droppii/libs';
9
9
  import FastImage from '@d11/react-native-fast-image';
10
10
  import type { IMessageItem } from '../../../types';
11
- import { StyleSheet, DeviceEventEmitter } from 'react-native';
11
+ import { StyleSheet } from 'react-native';
12
12
  import { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
13
13
  import { IconThinkingStep } from '../../../assets/svgIcon/IconThinkingStep';
14
14
  import { IconChatArrow } from '../../../assets/svgIcon/IconChatArrow';
15
15
  import useStreamMessageStore from '../../../store/streamMessage';
16
16
  import Markdown, { Renderer, RendererInterface } from 'react-native-marked';
17
17
  import icons from '../../../assets/icons';
18
- import { events } from '../../../constants/events';
19
18
  import { trans } from '../../../translation';
20
19
 
21
20
  interface ChatAIThinkingMessageItemProps {
@@ -91,10 +90,6 @@ const ChatAIThinkingMessageItem = ({
91
90
  const [display, setDisplay] = useState('');
92
91
  const indexRef = useRef(0);
93
92
 
94
- const onPressExpandThinkingStep = useCallback((expand: boolean) => {
95
- DeviceEventEmitter.emit(events.expandThinkingStep, expand);
96
- }, []);
97
-
98
93
  const renderHeader = useCallback(() => {
99
94
  return (
100
95
  <KContainer.View style={styles.header}>
@@ -158,7 +153,6 @@ const ChatAIThinkingMessageItem = ({
158
153
  containerStyle={styles.container}
159
154
  headerStyle={styles.mHeader}
160
155
  defaultValue={true}
161
- onChangeValue={onPressExpandThinkingStep}
162
156
  >
163
157
  {renderThinkingContent()}
164
158
  </KListItem.Accordion>
@@ -5,18 +5,18 @@ import ChatUserMessageItem from './ChatUserMessageItem';
5
5
 
6
6
  interface ChatItemProps {
7
7
  item: IMessageItem;
8
- index: number;
8
+ isLastItem: boolean;
9
9
  }
10
- const ChatItem = ({ item, index }: ChatItemProps) => {
10
+ const ChatItem = ({ item, isLastItem = false }: ChatItemProps) => {
11
11
  switch (item.type) {
12
12
  case MessageType.user_message:
13
- return <ChatUserMessageItem item={item} isLast={index === 0} />;
13
+ return <ChatUserMessageItem item={item} isLast={isLastItem} />;
14
14
  case MessageType.ai_answer:
15
- return <ChatAIAnswerMessageItem item={item} isLast={index === 0} />;
15
+ return <ChatAIAnswerMessageItem item={item} isLast={isLastItem} />;
16
16
  case MessageType.ai_thinking:
17
- return <ChatAIThinkingMessageItem item={item} isLast={index === 0} />;
17
+ return <ChatAIThinkingMessageItem item={item} isLast={isLastItem} />;
18
18
  default:
19
- return <ChatUserMessageItem item={item} isLast={index === 0} />;
19
+ return <ChatUserMessageItem item={item} isLast={isLastItem} />;
20
20
  }
21
21
  };
22
22
 
@@ -45,6 +45,7 @@ import {
45
45
  import { Z_INDEX_PRIORITY } from '../../constants';
46
46
  import { ScrollView } from 'react-native-gesture-handler';
47
47
  import { WithPopupProps } from '../../types';
48
+ import { useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller';
48
49
 
49
50
  const UNIT = KSpacingValue['1rem'];
50
51
  const STATUS_BAR_HEIGHT = KDims.os === 'ios' ? 0 : StatusBar.currentHeight || 0;
@@ -248,8 +249,10 @@ const Popup = forwardRef<WithPopupProps>((_, ref) => {
248
249
  e.stopPropagation();
249
250
  }, []);
250
251
 
252
+ const { height } = useReanimatedKeyboardAnimation();
253
+
251
254
  const rStyle = useAnimatedStyle(() => ({
252
- transform: [{ scale: scale.value }],
255
+ transform: [{ scale: scale.value }, { translateY: height.value / 2 }],
253
256
  }));
254
257
 
255
258
  if (!data) {
@@ -349,7 +349,7 @@ const ProductHorizontalCard = memo(
349
349
  background={KColors.palette.primary.w25}
350
350
  tintColor={KColors.primary.normal}
351
351
  icon={{
352
- vectorName: 'cart-alt-o',
352
+ vectorName: 'cart-plus-o',
353
353
  size: 16,
354
354
  }}
355
355
  size="sm"
@@ -2,7 +2,6 @@ export const events = {
2
2
  updateOneMessage: 'update_one_message',
3
3
  updateMultipleMessage: 'update_multiple_message',
4
4
  forceUpdateMessages: 'force_update_messages',
5
- expandThinkingStep: 'expand_thinking_step',
6
5
  updateMessageError: 'update_message_error',
7
6
  };
8
7
 
@@ -28,8 +28,7 @@ export const useMessage = () => {
28
28
  if (!res) return;
29
29
  setLoadState((prev) => ({
30
30
  ...res,
31
- messages:
32
- res?.messages?.length > 0 ? res.messages.reverse() : prev.messages,
31
+ messages: res?.messages?.length > 0 ? res.messages : prev.messages,
33
32
  }));
34
33
  }, [sessionId, getSessionById]);
35
34
 
@@ -44,8 +43,12 @@ export const useMessage = () => {
44
43
  useEffect(() => {
45
44
  const subOneMessage = DeviceEventEmitter.addListener(
46
45
  events.updateOneMessage,
47
- (messageItem: IMessageItem) => {
46
+ (messageItem: IMessageItem, sID?: string) => {
48
47
  setLoadState((prev) => {
48
+ if (sID !== prev.id) {
49
+ return prev;
50
+ }
51
+
49
52
  const messageIndex = prev.messages.findIndex(
50
53
  (m) => m.id === messageItem.id
51
54
  );
@@ -65,7 +68,7 @@ export const useMessage = () => {
65
68
 
66
69
  return {
67
70
  ...prev,
68
- messages: [messageItem, ...prev.messages],
71
+ messages: [...prev.messages, messageItem],
69
72
  };
70
73
  });
71
74
  }
@@ -73,23 +76,29 @@ export const useMessage = () => {
73
76
 
74
77
  const subMultipleMessage = DeviceEventEmitter.addListener(
75
78
  events.updateMultipleMessage,
76
- (messageItems: IMessageItem[]) => {
79
+ (messageItems: IMessageItem[], sID?: string) => {
77
80
  setLoadState((prev) => {
81
+ if (sID !== prev.id) {
82
+ return prev;
83
+ }
84
+
78
85
  const existingIds = new Set(prev.messages.map((m) => m?.id));
79
- const filtered = messageItems
80
- .filter((m) => !existingIds.has(m?.id))
81
- .reverse();
86
+ const filtered = messageItems.filter((m) => !existingIds.has(m?.id));
82
87
  return {
83
88
  ...prev,
84
- messages: [...filtered, ...prev.messages],
89
+ messages: [...prev.messages, ...filtered],
85
90
  };
86
91
  });
87
92
  }
88
93
  );
89
94
  const subForceUpdateMessages = DeviceEventEmitter.addListener(
90
95
  events.forceUpdateMessages,
91
- (messages: IMessageItem[]) => {
96
+ (messages: IMessageItem[], sID?: string) => {
92
97
  setLoadState((prev) => {
98
+ if (sID !== prev.id) {
99
+ return prev;
100
+ }
101
+
93
102
  const merged = prev.messages.map((msg) => {
94
103
  const update = messages.find((u) => u.id === msg.id);
95
104
  return update ? { ...msg, ...update } : msg;
@@ -99,23 +108,27 @@ export const useMessage = () => {
99
108
  const newItems = messages.filter((u) => !existingIds.has(u.id));
100
109
  return {
101
110
  ...prev,
102
- messages: [...newItems, ...merged],
111
+ messages: [...merged, ...newItems],
103
112
  };
104
113
  });
105
114
  }
106
115
  );
107
116
  const subUpdateMessageError = DeviceEventEmitter.addListener(
108
117
  events.updateMessageError,
109
- (messageId: string, metadata: Record<string, any>) => {
118
+ (messageId: string, metadata: Record<string, any>, sID?: string) => {
110
119
  setLoadState((prev) => {
120
+ if (sID !== prev.id) {
121
+ return prev;
122
+ }
123
+
111
124
  const messageIndex = prev.messages.findIndex(
112
125
  (m) => m.id === messageId
113
126
  );
114
127
  if (messageIndex === -1) return prev;
115
- const updatedMessages = prev.messages
128
+ const updatedMessages: IMessageItem[] = prev.messages
116
129
  .slice(messageIndex)
117
130
  .map((m, i) =>
118
- i === 0
131
+ i === updatedMessages?.length - 1
119
132
  ? {
120
133
  ...m,
121
134
  metadata: {
@@ -46,7 +46,11 @@ export const useSendMessage = () => {
46
46
  manual_retry_attempts: 0,
47
47
  group_suggestion_id: null,
48
48
  };
49
- DeviceEventEmitter.emit(events.updateOneMessage, messageItem);
49
+ DeviceEventEmitter.emit(
50
+ events.updateOneMessage,
51
+ messageItem,
52
+ useSessionStore.getState().sessionId
53
+ );
50
54
 
51
55
  let latestSessionId;
52
56
  if (!useSessionStore.getState().sessionId) {
@@ -69,11 +69,12 @@ export const useStreamMessage = () => {
69
69
  () => {
70
70
  DeviceEventEmitter.emit(
71
71
  events.updateMultipleMessage,
72
- Object.values(buffers).map((m) => ({ ...m, content: '' }))
72
+ Object.values(buffers).map((m) => ({ ...m, content: '' })),
73
+ useSessionStore.getState().sessionId
73
74
  );
74
75
  setStreamMessage(buffers);
75
76
  },
76
- 150,
77
+ 250,
77
78
  { leading: true, trailing: true }
78
79
  );
79
80
 
@@ -83,19 +84,23 @@ export const useStreamMessage = () => {
83
84
  ) => {
84
85
  await new Promise((resolve) => setTimeout(resolve, 500));
85
86
  if (isError) {
86
- DeviceEventEmitter.emit(events.updateMessageError, [
87
+ DeviceEventEmitter.emit(
88
+ events.updateMessageError,
89
+ messageId,
87
90
  {
88
- id: messageId,
89
- metadata: {
90
- needs_retry: true,
91
- original_message_id: localMessageId || messageId,
92
- status: 'error',
93
- },
91
+ needs_retry: true,
92
+ original_message_id: localMessageId || messageId,
93
+ status: 'error',
94
94
  },
95
- ]);
95
+ useSessionStore.getState().sessionId
96
+ );
96
97
  } else {
97
98
  const arrMessages = Object.values(buffers);
98
- DeviceEventEmitter.emit(events.forceUpdateMessages, arrMessages);
99
+ DeviceEventEmitter.emit(
100
+ events.forceUpdateMessages,
101
+ arrMessages,
102
+ useSessionStore.getState().sessionId
103
+ );
99
104
  arrMessages.forEach((m: any) => {
100
105
  if (m?.suggestions?.length > 0) {
101
106
  logGA?.(GAEvents.chatDetailInConvPrmSuggReturn, {
@@ -149,6 +154,7 @@ export const useStreamMessage = () => {
149
154
  });
150
155
 
151
156
  es.addEventListener('close', async () => {
157
+ throttledFlush.cancel();
152
158
  console.log('✅ Stream closed');
153
159
  });
154
160
  },
@@ -157,10 +163,14 @@ export const useStreamMessage = () => {
157
163
 
158
164
  const retryStream = useCallback(
159
165
  (messageItem: IMessageItem) => {
160
- DeviceEventEmitter.emit(events.updateOneMessage, {
161
- ...messageItem,
162
- metadata: {},
163
- });
166
+ DeviceEventEmitter.emit(
167
+ events.updateOneMessage,
168
+ {
169
+ ...messageItem,
170
+ metadata: {},
171
+ },
172
+ sessionId
173
+ );
164
174
 
165
175
  logGA(GAEvents.chatDetailSendBtnTap, {
166
176
  chat_type: useSessionStore.getState().sessionLogType,