react-native-chatbot-ai 0.1.22 → 0.1.24

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 (76) hide show
  1. package/lib/module/components/Drawer/DeleteSessionPopup.js +5 -5
  2. package/lib/module/components/Drawer/DeleteSessionPopup.js.map +1 -1
  3. package/lib/module/components/Drawer/RenameSessionPopup.js +34 -24
  4. package/lib/module/components/Drawer/RenameSessionPopup.js.map +1 -1
  5. package/lib/module/components/Drawer/SessionItem.js +6 -5
  6. package/lib/module/components/Drawer/SessionItem.js.map +1 -1
  7. package/lib/module/components/Drawer/SessionList.js +5 -4
  8. package/lib/module/components/Drawer/SessionList.js.map +1 -1
  9. package/lib/module/components/Drawer/SessionOptionsBottomSheet.js +13 -7
  10. package/lib/module/components/Drawer/SessionOptionsBottomSheet.js.map +1 -1
  11. package/lib/module/components/Drawer/ShareSessionPopup.js +6 -6
  12. package/lib/module/components/Drawer/ShareSessionPopup.js.map +1 -1
  13. package/lib/module/components/chat/footer/index.js +40 -33
  14. package/lib/module/components/chat/footer/index.js.map +1 -1
  15. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js +26 -13
  16. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js.map +1 -1
  17. package/lib/module/components/chat/item/DeeplinkItem.js +3 -3
  18. package/lib/module/components/chat/item/DeeplinkItem.js.map +1 -1
  19. package/lib/module/components/chat/item/MessageActionsBar.js +9 -9
  20. package/lib/module/components/chat/item/MessageActionsBar.js.map +1 -1
  21. package/lib/module/components/portal/Popup.js +8 -3
  22. package/lib/module/components/portal/Popup.js.map +1 -1
  23. package/lib/module/components/product/CardHorizontal.js +50 -46
  24. package/lib/module/components/product/CardHorizontal.js.map +1 -1
  25. package/lib/module/hooks/message/useStreamMessage.js +13 -2
  26. package/lib/module/hooks/message/useStreamMessage.js.map +1 -1
  27. package/lib/module/hooks/messageActions/useAudioPlayer.js +109 -24
  28. package/lib/module/hooks/messageActions/useAudioPlayer.js.map +1 -1
  29. package/lib/module/hooks/messageActions/useFeedback.js +2 -2
  30. package/lib/module/hooks/messageActions/useFeedback.js.map +1 -1
  31. package/lib/module/hooks/messageActions/useShareMessage.js +1 -1
  32. package/lib/module/hooks/messageActions/useShareMessage.js.map +1 -1
  33. package/lib/module/store/session.js +1 -1
  34. package/lib/module/store/session.js.map +1 -1
  35. package/lib/module/utils/ui.js.map +1 -1
  36. package/lib/typescript/src/components/Drawer/RenameSessionPopup.d.ts +1 -1
  37. package/lib/typescript/src/components/Drawer/RenameSessionPopup.d.ts.map +1 -1
  38. package/lib/typescript/src/components/Drawer/SessionItem.d.ts.map +1 -1
  39. package/lib/typescript/src/components/Drawer/SessionList.d.ts.map +1 -1
  40. package/lib/typescript/src/components/Drawer/SessionOptionsBottomSheet.d.ts.map +1 -1
  41. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts.map +1 -1
  42. package/lib/typescript/src/components/portal/Popup.d.ts +4 -0
  43. package/lib/typescript/src/components/portal/Popup.d.ts.map +1 -1
  44. package/lib/typescript/src/components/product/CardHorizontal.d.ts +1 -0
  45. package/lib/typescript/src/components/product/CardHorizontal.d.ts.map +1 -1
  46. package/lib/typescript/src/hooks/message/useStreamMessage.d.ts.map +1 -1
  47. package/lib/typescript/src/hooks/messageActions/useAudioPlayer.d.ts +1 -0
  48. package/lib/typescript/src/hooks/messageActions/useAudioPlayer.d.ts.map +1 -1
  49. package/lib/typescript/src/store/products.d.ts +1 -1
  50. package/lib/typescript/src/store/products.d.ts.map +1 -1
  51. package/lib/typescript/src/types/ui.d.ts +3 -2
  52. package/lib/typescript/src/types/ui.d.ts.map +1 -1
  53. package/lib/typescript/src/utils/ui.d.ts +3 -2
  54. package/lib/typescript/src/utils/ui.d.ts.map +1 -1
  55. package/package.json +2 -2
  56. package/src/components/Drawer/DeleteSessionPopup.tsx +5 -5
  57. package/src/components/Drawer/RenameSessionPopup.tsx +49 -40
  58. package/src/components/Drawer/SessionItem.tsx +5 -4
  59. package/src/components/Drawer/SessionList.tsx +8 -3
  60. package/src/components/Drawer/SessionOptionsBottomSheet.tsx +12 -6
  61. package/src/components/Drawer/ShareSessionPopup.tsx +6 -6
  62. package/src/components/chat/footer/index.tsx +37 -35
  63. package/src/components/chat/item/ChatAIAnswerMessageItem.tsx +29 -13
  64. package/src/components/chat/item/DeeplinkItem.tsx +3 -3
  65. package/src/components/chat/item/MessageActionsBar.tsx +9 -9
  66. package/src/components/portal/Popup.tsx +14 -4
  67. package/src/components/product/CardHorizontal.tsx +46 -45
  68. package/src/hooks/message/useStreamMessage.ts +17 -5
  69. package/src/hooks/messageActions/useAudioPlayer.ts +116 -22
  70. package/src/hooks/messageActions/useFeedback.ts +2 -2
  71. package/src/hooks/messageActions/useSendFeedback.ts +1 -1
  72. package/src/hooks/messageActions/useShareMessage.ts +1 -1
  73. package/src/store/products.ts +1 -1
  74. package/src/store/session.ts +1 -1
  75. package/src/types/ui.ts +3 -2
  76. package/src/utils/ui.tsx +3 -2
@@ -70,15 +70,19 @@ export type UploadItem = ImageUpload | FileUpload;
70
70
  const MAX_FILE_UPLOAD = 3;
71
71
  const MAX_FILE_SIZE = 30 * 1024 * 1024;
72
72
  const MAX_IMAGE_SIZE = 7 * 1024 * 1024;
73
- const SCROLL_IDLE_TIME = 60000;
73
+ const COUNTDOWN_MS = 60000;
74
74
 
75
75
  interface IChatFooterProps {
76
76
  lastMessage?: IMessageItem;
77
77
  }
78
78
 
79
79
  const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
80
- const idleTimerRef = useRef<NodeJS.Timeout | null>(null);
81
- const hasScrolledRef = useRef(false);
80
+ const countdownRef = useRef<NodeJS.Timeout | null>(null);
81
+ const isInCountdownRef = useRef(false);
82
+ const firstVisibleItemRef = useRef<ISuggestionItem | null>(null);
83
+
84
+ const viewabilityConfig = useRef({ itemVisiblePercentThreshold: 10 }).current;
85
+
82
86
  const menuRef = useRef(null);
83
87
  const logGA = useChatContext().logGA;
84
88
  const { onSendMessage, stopStream } = useSendMessage();
@@ -92,9 +96,9 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
92
96
 
93
97
  const isDisabledSend = useMemo(() => {
94
98
  return (
95
- isStreaming ||
96
- message.trim() === '' ||
97
- (fileUpload.length > 0 && fileUpload.some((i) => !i.remoteUrl))
99
+ !isStreaming &&
100
+ (message.trim() === '' ||
101
+ (fileUpload.length > 0 && fileUpload.some((i) => !i.remoteUrl)))
98
102
  );
99
103
  }, [isStreaming, message, fileUpload]);
100
104
 
@@ -364,39 +368,34 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
364
368
  [onPressItemSuggestion]
365
369
  );
366
370
 
367
- const clearIdleTimer = () => {
368
- if (idleTimerRef.current) {
369
- clearTimeout(idleTimerRef.current);
370
- idleTimerRef.current = null;
371
+ const onViewableItemsChanged = useRef(({ viewableItems }: any) => {
372
+ if (viewableItems && viewableItems.length > 0) {
373
+ firstVisibleItemRef.current = viewableItems[0].item;
371
374
  }
372
- };
375
+ }).current;
376
+
377
+ const logFirstVisibleItem = useCallback(() => {
378
+ if (!firstVisibleItemRef.current) return;
373
379
 
374
- const onUserIdleAfterScroll = useCallback(() => {
375
380
  logGA(GAEvents.chatDetailInConvPrmSuggScroll, {
376
381
  group_id: lastMessage?.group_suggestion_id,
377
- message_id: lastMessage?.id,
382
+ message_chat_id: lastMessage?.id,
383
+ suggestion_id: firstVisibleItemRef.current.suggestion_id,
378
384
  });
379
- }, [lastMessage, logGA]);
380
-
381
- const resetIdleTimer = useCallback(() => {
382
- clearIdleTimer();
383
-
384
- hasScrolledRef.current = true;
385
385
 
386
- idleTimerRef.current = setTimeout(() => {
387
- if (hasScrolledRef.current) {
388
- onUserIdleAfterScroll();
389
- }
390
- }, SCROLL_IDLE_TIME);
391
- }, [onUserIdleAfterScroll]);
392
-
393
- const handleScroll = () => {
394
- resetIdleTimer();
395
- };
386
+ // Bắt đầu countdown
387
+ isInCountdownRef.current = true;
388
+ countdownRef.current = setTimeout(() => {
389
+ isInCountdownRef.current = false;
390
+ countdownRef.current = null;
391
+ }, COUNTDOWN_MS);
392
+ }, [lastMessage, logGA]);
396
393
 
397
- const handleMomentumEnd = () => {
398
- resetIdleTimer();
399
- };
394
+ const handleMomentumEnd = useCallback(() => {
395
+ if (!isInCountdownRef.current) {
396
+ logFirstVisibleItem();
397
+ }
398
+ }, [logFirstVisibleItem]);
400
399
 
401
400
  return (
402
401
  <KContainer.View style={styles.container}>
@@ -413,9 +412,10 @@ const ChatFooter = ({ lastMessage }: IChatFooterProps) => {
413
412
  horizontal
414
413
  keyExtractor={(item: ISuggestionItem) => item.suggestion_id}
415
414
  contentContainerStyle={styles.suggessionContainer}
416
- onScroll={handleScroll}
415
+ onViewableItemsChanged={onViewableItemsChanged}
416
+ viewabilityConfig={viewabilityConfig}
417
+ scrollEventThrottle={16}
417
418
  onMomentumScrollEnd={handleMomentumEnd}
418
- scrollEventThrottle={200}
419
419
  />
420
420
  </KContainer.VisibleView>
421
421
  <KContainer.VisibleView visible={fileUpload.length > 0}>
@@ -503,7 +503,6 @@ const styles = StyleSheet.create({
503
503
  container: {
504
504
  paddingHorizontal: KSpacingValue['0.75rem'],
505
505
  paddingVertical: KSpacingValue['0.5rem'],
506
- gap: KSpacingValue['0.5rem'],
507
506
  borderWidth: 1,
508
507
  borderColor: KColors.hexToRgba(KColors.black, 0.15),
509
508
  borderBottomWidth: 0,
@@ -521,6 +520,7 @@ const styles = StyleSheet.create({
521
520
  },
522
521
  input: {
523
522
  maxHeight: 100,
523
+ marginBottom: 8,
524
524
  },
525
525
  popover: {
526
526
  borderRadius: KRadiusValue['4x'],
@@ -540,9 +540,11 @@ const styles = StyleSheet.create({
540
540
  listUploadItem: {
541
541
  gap: KSpacingValue['0.75rem'],
542
542
  paddingTop: 6,
543
+ paddingBottom: 8,
543
544
  },
544
545
  suggessionContainer: {
545
546
  gap: KSpacingValue['0.25rem'],
547
+ paddingBottom: 8,
546
548
  },
547
549
  suggestionItem: {
548
550
  backgroundColor: KColors.palette.gray.w25,
@@ -170,25 +170,30 @@ export function useStreamingMarkdownBlocks(text: string) {
170
170
  class CustomRenderer extends Renderer implements RendererInterface {
171
171
  constructor(
172
172
  openImageViewer?: (images: { url: string }[], index: number) => void,
173
- messageId?: string
173
+ messageId?: string,
174
+ productIds?: string[]
174
175
  ) {
175
176
  super();
176
177
  this.openImageViewer = openImageViewer;
177
178
  this.messageId = messageId;
179
+ this.productIds = productIds;
178
180
  }
179
181
 
180
182
  openImageViewer?: (images: { url: string }[], index: number) => void;
181
183
  messageId?: string;
184
+ productIds?: string[];
182
185
 
183
186
  html(text: string): ReactNode {
184
187
  const match = /^<!--\s*@component:(\w+)\(id:([\w-]+)\)\s*-->/.exec(text);
185
188
  switch (match?.[1]) {
186
189
  case 'product':
190
+ const productIndex = this.productIds?.indexOf(match?.[2] || '');
187
191
  return (
188
192
  <ProductHorizontalCard
189
193
  productId={match?.[2]}
190
194
  key={this.getKey()}
191
195
  messageId={this.messageId}
196
+ index={productIndex}
192
197
  />
193
198
  );
194
199
  default:
@@ -300,12 +305,14 @@ class CustomRenderer extends Renderer implements RendererInterface {
300
305
 
301
306
  hr(_styles?: any): ReactNode {
302
307
  return (
303
- <KDivider
304
- key={this.getKey()}
305
- type="line"
306
- size="sm"
307
- background={KColors.hexToRgba(KColors.gray.dark, 0.2)}
308
- />
308
+ <KContainer.View marginV={'0.5rem'}>
309
+ <KDivider
310
+ key={this.getKey()}
311
+ type="line"
312
+ size="sm"
313
+ background={KColors.hexToRgba(KColors.gray.dark, 0.2)}
314
+ />
315
+ </KContainer.View>
309
316
  );
310
317
  }
311
318
 
@@ -356,18 +363,27 @@ class CustomRenderer extends Renderer implements RendererInterface {
356
363
  />
357
364
  );
358
365
  }
366
+
367
+ heading(text: string | ReactNode[]): ReactNode {
368
+ return (
369
+ <KLabel.Text key={this.getKey()} typo="TextMdBold">
370
+ {text}
371
+ </KLabel.Text>
372
+ );
373
+ }
359
374
  }
360
375
 
361
376
  const markedStyles: MarkedStyles = {
362
377
  paragraph: {
363
- marginVertical: 5,
378
+ marginVertical: 4,
364
379
  },
365
380
  blockquote: {
366
- marginVertical: 5,
381
+ marginVertical: 4,
367
382
  },
368
383
  li: {
369
- marginVertical: 5,
384
+ marginVertical: 4,
370
385
  justifyContent: 'center',
386
+ color: KColors.gray.dark,
371
387
  },
372
388
  };
373
389
 
@@ -408,13 +424,13 @@ const ChatAIAnswerMessageItem = ({
408
424
  return ids;
409
425
  }, [isStreaming, streamMessage, item]);
410
426
 
411
- const {} = useSearchProduct({ productIds });
427
+ useSearchProduct({ productIds });
412
428
 
413
429
  const products = useProductsStore((state) => state.products);
414
430
 
415
431
  const renderer = useMemo(
416
- () => new CustomRenderer(openImageViewer, item.id),
417
- [openImageViewer, item.id]
432
+ () => new CustomRenderer(openImageViewer, item.id, productIds),
433
+ [openImageViewer, item.id, productIds]
418
434
  );
419
435
  const tokenizer = useMemo(() => new CustomTokenizer(), []);
420
436
 
@@ -63,7 +63,7 @@ const DeeplinkItem = ({ children, href, messageId }: DeeplinkItemProps) => {
63
63
  if (data?.type === 'gift') {
64
64
  logGA(GAEvents.chatDetailGiftDetailBtnTap, {
65
65
  conversation_id: useSessionStore.getState().sessionId,
66
- message_id: messageId,
66
+ message_chat_id: messageId,
67
67
  gift_id: data?.id,
68
68
  });
69
69
  return;
@@ -71,7 +71,7 @@ const DeeplinkItem = ({ children, href, messageId }: DeeplinkItemProps) => {
71
71
  if (data?.type === 'faq') {
72
72
  logGA(GAEvents.chatDetailFAQTap, {
73
73
  conversation_id: useSessionStore.getState().sessionId,
74
- message_id: messageId,
74
+ message_chat_id: messageId,
75
75
  deeplink_id: data?.id,
76
76
  });
77
77
  return;
@@ -79,7 +79,7 @@ const DeeplinkItem = ({ children, href, messageId }: DeeplinkItemProps) => {
79
79
  if (data?.type === 'cx-support') {
80
80
  logGA(GAEvents.chatDetailLivechatBtnTap, {
81
81
  conversation_id: useSessionStore.getState().sessionId,
82
- message_id: messageId,
82
+ message_chat_id: messageId,
83
83
  });
84
84
  return;
85
85
  }
@@ -98,7 +98,7 @@ const MessageActionsBar = ({
98
98
  // Handlers
99
99
  const handleCopy = useCallback(() => {
100
100
  logGA(GAEvents.chatDetailCopyBtnTap, {
101
- message_id: messageId,
101
+ message_chat_id: messageId,
102
102
  });
103
103
  copyToClipboard(messageContent);
104
104
  }, [messageContent, copyToClipboard, logGA, messageId]);
@@ -159,8 +159,8 @@ const MessageActionsBar = ({
159
159
  ]}
160
160
  >
161
161
  <KImage.VectorIcons
162
- name="like-thumbup-b"
163
- size={16}
162
+ name="thumb-like-o"
163
+ size={20}
164
164
  color={
165
165
  isLikeActive ? KColors.primary.normal : KColors.gray.light
166
166
  }
@@ -215,8 +215,8 @@ const MessageActionsBar = ({
215
215
  ]}
216
216
  >
217
217
  <KImage.VectorIcons
218
- name="like-thumbdown-b"
219
- size={16}
218
+ name="thumb-dislike-o"
219
+ size={20}
220
220
  color={
221
221
  isDislikeActive
222
222
  ? KColors.primary.normal
@@ -253,7 +253,7 @@ const MessageActionsBar = ({
253
253
  {/* Audio Button */}
254
254
  <ActionButton
255
255
  icon={audioButtonProps.icon}
256
- iconSize={16}
256
+ iconSize={20}
257
257
  iconColor={audioButtonProps.iconColor}
258
258
  isActive={audioButtonProps.isActive}
259
259
  isLoading={isAudioLoading}
@@ -264,7 +264,7 @@ const MessageActionsBar = ({
264
264
  {/* Copy Button */}
265
265
  <ActionButton
266
266
  icon="copy-o"
267
- iconSize={16}
267
+ iconSize={20}
268
268
  isLoading={isCopying}
269
269
  onPress={handleCopy}
270
270
  testID="copy-button"
@@ -272,8 +272,8 @@ const MessageActionsBar = ({
272
272
 
273
273
  {/* Share Button */}
274
274
  <ActionButton
275
- icon="share-o"
276
- iconSize={16}
275
+ icon="text-share-o"
276
+ iconSize={20}
277
277
  isLoading={isSharing}
278
278
  onPress={shareMessage}
279
279
  testID="share-button"
@@ -57,9 +57,13 @@ const PADDING_VERTICAL = KDims.isIphoneX ? UNIT * 3 : UNIT * 2.25;
57
57
  const PADDING_HORIZONTAL = UNIT;
58
58
  const CONTENT_MAX_HEIGHT = VIEWABLE_HEIGHT - 2 * PADDING_VERTICAL;
59
59
 
60
+ export type IPopupProps = KPopupProps & {
61
+ onPressClose?: () => void;
62
+ };
63
+
60
64
  const Popup = forwardRef<WithPopupProps>((_, ref) => {
61
- const queue = useRef<KPopupProps[]>([]);
62
- const [data, setData] = useState<KPopupProps | undefined>(undefined);
65
+ const queue = useRef<IPopupProps[]>([]);
66
+ const [data, setData] = useState<IPopupProps | undefined>(undefined);
63
67
 
64
68
  const scale = useSharedValue(1);
65
69
 
@@ -69,6 +73,7 @@ const Popup = forwardRef<WithPopupProps>((_, ref) => {
69
73
  actions,
70
74
  backgroundColor = KColors.white,
71
75
  wrapperStyle = {},
76
+ onPressClose,
72
77
  } = data || {};
73
78
 
74
79
  const { showCloseButton, subTitle, title, alignment } = header || {};
@@ -84,6 +89,11 @@ const Popup = forwardRef<WithPopupProps>((_, ref) => {
84
89
  setData(newPayload);
85
90
  }, [scale]);
86
91
 
92
+ const handleDismiss = useCallback(() => {
93
+ dismiss();
94
+ onPressClose?.();
95
+ }, [dismiss, onPressClose]);
96
+
87
97
  useImperativeHandle(
88
98
  ref,
89
99
  () => ({
@@ -177,12 +187,12 @@ const Popup = forwardRef<WithPopupProps>((_, ref) => {
177
187
  </KContainer.View>
178
188
  {showCloseButton && (
179
189
  <KContainer.View marginL={'1rem'}>
180
- <KButton.Close onPress={dismiss} />
190
+ <KButton.Close onPress={handleDismiss} />
181
191
  </KContainer.View>
182
192
  )}
183
193
  </KContainer.View>
184
194
  );
185
- }, [alignment, data, dismiss, showCloseButton, subTitle, title]);
195
+ }, [alignment, data, handleDismiss, showCloseButton, subTitle, title]);
186
196
 
187
197
  const renderActions = useMemo(() => {
188
198
  if (!actions?.buttons) {
@@ -2,7 +2,7 @@ import {
2
2
  KButton,
3
3
  KColors,
4
4
  KContainer,
5
- KDims,
5
+ // KDims,
6
6
  KImage,
7
7
  KLabel,
8
8
  KRadiusValue,
@@ -16,17 +16,18 @@ import { StyleSheet } from 'react-native';
16
16
  import useProductsStore from '../../store/products';
17
17
  import { PRODUCT_STATUSES } from '../../types';
18
18
  import { useChatContext } from '../../context/ChatContext';
19
- import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
19
+ // import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
20
20
  import { GAEvents } from '../../constants/events';
21
21
  import useSessionStore from '../../store/session';
22
22
 
23
23
  interface IProductHorizontalCardProps {
24
24
  productId?: string;
25
25
  messageId?: string;
26
+ index?: number;
26
27
  }
27
28
 
28
29
  const ProductHorizontalCard = (props: IProductHorizontalCardProps) => {
29
- const { productId, messageId } = props;
30
+ const { productId, messageId, index } = props;
30
31
  const item = useProductsStore((state) =>
31
32
  state.products.find((p) => p.id === productId)
32
33
  );
@@ -142,9 +143,9 @@ const ProductHorizontalCard = (props: IProductHorizontalCardProps) => {
142
143
  logGA(GAEvents.chatDetailProductCardTap, {
143
144
  conversation_id: useSessionStore.getState().sessionId,
144
145
  product_id: item.id,
145
- position_in_list: -1, //TODO: fix
146
+ position_in_list: index,
146
147
  });
147
- }, [onNavigateToProduct, logGA, item]);
148
+ }, [onNavigateToProduct, logGA, item, index]);
148
149
 
149
150
  const onPressAddToCart = useCallback(() => {
150
151
  if (!item) return;
@@ -152,11 +153,11 @@ const ProductHorizontalCard = (props: IProductHorizontalCardProps) => {
152
153
  logGA(GAEvents.chatDetailAddToCartBtnTap, {
153
154
  conversation_id: useSessionStore.getState().sessionId,
154
155
  product_id: item.id,
155
- position_in_list: -1, //TODO: fix
156
+ position_in_list: index,
156
157
  pdp_id: item.pdpId,
157
- message_id: messageId,
158
+ message_chat_id: messageId,
158
159
  });
159
- }, [onAddToCart, logGA, item, messageId]);
160
+ }, [onAddToCart, logGA, item, messageId, index]);
160
161
 
161
162
  const onPressBuyNow = useCallback(() => {
162
163
  if (!item) return;
@@ -166,46 +167,46 @@ const ProductHorizontalCard = (props: IProductHorizontalCardProps) => {
166
167
  product_id: item.id,
167
168
  position_in_list: -1, //TODO: fix
168
169
  pdp_id: item.pdpId,
169
- message_id: messageId,
170
+ message_chat_id: messageId,
170
171
  });
171
172
  }, [onBuyNow, logGA, item, messageId]);
172
173
 
173
- if (!item) {
174
- return (
175
- <KContainer.View style={styles.container}>
176
- <SkeletonPlaceholder borderRadius={4} speed={2000} direction="right">
177
- <SkeletonPlaceholder.Item flexDirection="row" gap={12}>
178
- <SkeletonPlaceholder.Item
179
- width={72}
180
- height={72}
181
- borderRadius={12}
182
- />
183
- <SkeletonPlaceholder.Item
184
- gap={12}
185
- width={KDims.width - 160}
186
- justifyContent="space-between"
187
- >
188
- <SkeletonPlaceholder.Item
189
- height={16}
190
- width={KDims.width / 2}
191
- borderRadius={4}
192
- />
193
- <SkeletonPlaceholder.Item
194
- height={16}
195
- width={160}
196
- borderRadius={4}
197
- />
198
- <SkeletonPlaceholder.Item
199
- height={16}
200
- width={80}
201
- borderRadius={4}
202
- />
203
- </SkeletonPlaceholder.Item>
204
- </SkeletonPlaceholder.Item>
205
- </SkeletonPlaceholder>
206
- </KContainer.View>
207
- );
208
- }
174
+ // if (!item) {
175
+ // return (
176
+ // <KContainer.View style={styles.container}>
177
+ // <SkeletonPlaceholder borderRadius={4} speed={2000} direction="right">
178
+ // <SkeletonPlaceholder.Item flexDirection="row" gap={12}>
179
+ // <SkeletonPlaceholder.Item
180
+ // width={72}
181
+ // height={72}
182
+ // borderRadius={12}
183
+ // />
184
+ // <SkeletonPlaceholder.Item
185
+ // gap={12}
186
+ // width={KDims.width - 160}
187
+ // justifyContent="space-between"
188
+ // >
189
+ // <SkeletonPlaceholder.Item
190
+ // height={16}
191
+ // width={KDims.width / 2}
192
+ // borderRadius={4}
193
+ // />
194
+ // <SkeletonPlaceholder.Item
195
+ // height={16}
196
+ // width={160}
197
+ // borderRadius={4}
198
+ // />
199
+ // <SkeletonPlaceholder.Item
200
+ // height={16}
201
+ // width={80}
202
+ // borderRadius={4}
203
+ // />
204
+ // </SkeletonPlaceholder.Item>
205
+ // </SkeletonPlaceholder.Item>
206
+ // </SkeletonPlaceholder>
207
+ // </KContainer.View>
208
+ // );
209
+ // }
209
210
 
210
211
  return (
211
212
  <KContainer.Touchable style={styles.container} onPress={onPress}>
@@ -2,6 +2,7 @@ import { useEffect, useRef, useCallback } from 'react';
2
2
  import { useChatContext } from '../../context/ChatContext';
3
3
  import { ENDPOINTS } from '../../services/endpoints';
4
4
  import {
5
+ ISuggestionItem,
5
6
  SendActionLogType,
6
7
  type IMessageItem,
7
8
  type StreamMessageRequest,
@@ -91,10 +92,21 @@ export const useStreamMessage = () => {
91
92
  },
92
93
  ]);
93
94
  } else {
94
- DeviceEventEmitter.emit(
95
- events.forceUpdateMessages,
96
- Object.values(buffers)
97
- );
95
+ const arrMessages = Object.values(buffers);
96
+ DeviceEventEmitter.emit(events.forceUpdateMessages, arrMessages);
97
+ arrMessages.forEach((m) => {
98
+ if (m?.metadata?.suggestion?.length > 0) {
99
+ logGA?.(GAEvents.chatDetailInConvPrmSuggReturn, {
100
+ conversation_id: sessionId,
101
+ message_chat_id: m?.id,
102
+ group_id: m?.group_suggestion_id,
103
+ suggestion_id:
104
+ m?.suggestions
105
+ ?.map((s: ISuggestionItem) => s?.suggestion_id)
106
+ ?.join(',') || '',
107
+ });
108
+ }
109
+ });
98
110
  }
99
111
  es.close();
100
112
  buffers = {};
@@ -144,7 +156,7 @@ export const useStreamMessage = () => {
144
156
 
145
157
  esRef.current = es;
146
158
  },
147
- [apiAddress, setIsStreaming, setStreamMessage]
159
+ [apiAddress, setIsStreaming, setStreamMessage, logGA, sessionId]
148
160
  );
149
161
 
150
162
  const stopStream = useCallback(() => {