@droppii-org/chat-mobile 0.2.35 → 0.2.38

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 (160) hide show
  1. package/lib/module/components/messages/linkMessage/index.js +1 -10
  2. package/lib/module/components/messages/linkMessage/index.js.map +1 -1
  3. package/lib/module/components/messages/quotedMessage/index.js +173 -0
  4. package/lib/module/components/messages/quotedMessage/index.js.map +1 -0
  5. package/lib/module/context/ChatContext.js +26 -22
  6. package/lib/module/context/ChatContext.js.map +1 -1
  7. package/lib/module/context/ChatDetailContext.js +7 -4
  8. package/lib/module/context/ChatDetailContext.js.map +1 -1
  9. package/lib/module/core/useChatListener.js +0 -1
  10. package/lib/module/core/useChatListener.js.map +1 -1
  11. package/lib/module/core/useUserListener.js +12 -21
  12. package/lib/module/core/useUserListener.js.map +1 -1
  13. package/lib/module/hooks/message/useSendMessage.js +26 -4
  14. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  15. package/lib/module/hooks/useChatMessages.js.map +1 -1
  16. package/lib/module/hooks/useFileAttachment.js +3 -1
  17. package/lib/module/hooks/useFileAttachment.js.map +1 -1
  18. package/lib/module/index.js +0 -7
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/screens/chat-detail/ChatComposer.js +2 -1
  21. package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
  22. package/lib/module/screens/chat-detail/ChatCurrentQuotedMessage.js +142 -0
  23. package/lib/module/screens/chat-detail/ChatCurrentQuotedMessage.js.map +1 -0
  24. package/lib/module/screens/chat-detail/ChatDetail.js +10 -1
  25. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  26. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  27. package/lib/module/screens/chat-detail/PinnedMessageBar.js +8 -3
  28. package/lib/module/screens/chat-detail/PinnedMessageBar.js.map +1 -1
  29. package/lib/module/screens/chat-detail/PinnedMessagesSheet.js +173 -0
  30. package/lib/module/screens/chat-detail/PinnedMessagesSheet.js.map +1 -0
  31. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +2 -1
  32. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  33. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxMenu.js +17 -1
  34. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxMenu.js.map +1 -1
  35. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +11 -1
  36. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -1
  37. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxWrapper.js +1 -0
  38. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxWrapper.js.map +1 -1
  39. package/lib/module/screens/chat-detail/messageToolbox/messageToolbox.utils.js +5 -2
  40. package/lib/module/screens/chat-detail/messageToolbox/messageToolbox.utils.js.map +1 -1
  41. package/lib/module/screens/inbox/Inbox.js +1 -5
  42. package/lib/module/screens/inbox/Inbox.js.map +1 -1
  43. package/lib/module/services/apis.js +0 -3
  44. package/lib/module/services/apis.js.map +1 -1
  45. package/lib/module/services/message.js.map +1 -1
  46. package/lib/module/store/message.js.map +1 -1
  47. package/lib/module/store/pinnedMessage.js.map +1 -1
  48. package/lib/module/store/user.js +2 -3
  49. package/lib/module/store/user.js.map +1 -1
  50. package/lib/module/translation/resources/i18n.js +9 -2
  51. package/lib/module/translation/resources/i18n.js.map +1 -1
  52. package/lib/module/types/auth.js +0 -7
  53. package/lib/module/types/auth.js.map +1 -1
  54. package/lib/module/types/chat.js +12 -0
  55. package/lib/module/types/chat.js.map +1 -1
  56. package/lib/module/utils/UIUtils.js +6 -0
  57. package/lib/module/utils/UIUtils.js.map +1 -1
  58. package/lib/module/utils/legendListMessage.js +1 -0
  59. package/lib/module/utils/legendListMessage.js.map +1 -1
  60. package/lib/module/utils/message.js.map +1 -1
  61. package/lib/module/utils/messageUtils.js +18 -1
  62. package/lib/module/utils/messageUtils.js.map +1 -1
  63. package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
  64. package/lib/typescript/src/components/messages/quotedMessage/index.d.ts +7 -0
  65. package/lib/typescript/src/components/messages/quotedMessage/index.d.ts.map +1 -0
  66. package/lib/typescript/src/components/messages/types.d.ts +2 -2
  67. package/lib/typescript/src/components/messages/types.d.ts.map +1 -1
  68. package/lib/typescript/src/context/ChatContext.d.ts.map +1 -1
  69. package/lib/typescript/src/context/ChatDetailContext.d.ts.map +1 -1
  70. package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
  71. package/lib/typescript/src/core/useUserListener.d.ts.map +1 -1
  72. package/lib/typescript/src/hooks/message/usePinMessage.d.ts +1 -1
  73. package/lib/typescript/src/hooks/message/useSendMessage.d.ts +2 -1
  74. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  75. package/lib/typescript/src/hooks/useChatMessages.d.ts +2 -2
  76. package/lib/typescript/src/hooks/useChatMessages.d.ts.map +1 -1
  77. package/lib/typescript/src/hooks/useFileAttachment.d.ts.map +1 -1
  78. package/lib/typescript/src/index.d.ts +1 -1
  79. package/lib/typescript/src/index.d.ts.map +1 -1
  80. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
  81. package/lib/typescript/src/screens/chat-detail/ChatCurrentQuotedMessage.d.ts +2 -0
  82. package/lib/typescript/src/screens/chat-detail/ChatCurrentQuotedMessage.d.ts.map +1 -0
  83. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  84. package/lib/typescript/src/screens/chat-detail/PinnedMessageBar.d.ts +4 -3
  85. package/lib/typescript/src/screens/chat-detail/PinnedMessageBar.d.ts.map +1 -1
  86. package/lib/typescript/src/screens/chat-detail/PinnedMessagesSheet.d.ts +9 -0
  87. package/lib/typescript/src/screens/chat-detail/PinnedMessagesSheet.d.ts.map +1 -0
  88. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +2 -3
  89. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  90. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.d.ts +11 -7
  91. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.d.ts.map +1 -1
  92. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts +4 -4
  93. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -1
  94. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.d.ts.map +1 -1
  95. package/lib/typescript/src/screens/chat-detail/messageToolbox/messageToolbox.utils.d.ts +5 -3
  96. package/lib/typescript/src/screens/chat-detail/messageToolbox/messageToolbox.utils.d.ts.map +1 -1
  97. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts +2 -2
  98. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts.map +1 -1
  99. package/lib/typescript/src/screens/chat-detail/types.d.ts +5 -5
  100. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  101. package/lib/typescript/src/screens/inbox/Inbox.d.ts.map +1 -1
  102. package/lib/typescript/src/services/apis.d.ts +0 -1
  103. package/lib/typescript/src/services/apis.d.ts.map +1 -1
  104. package/lib/typescript/src/services/message.d.ts +1 -2
  105. package/lib/typescript/src/services/message.d.ts.map +1 -1
  106. package/lib/typescript/src/store/message.d.ts.map +1 -1
  107. package/lib/typescript/src/store/pinnedMessage.d.ts +4 -4
  108. package/lib/typescript/src/store/pinnedMessage.d.ts.map +1 -1
  109. package/lib/typescript/src/store/user.d.ts +4 -4
  110. package/lib/typescript/src/store/user.d.ts.map +1 -1
  111. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  112. package/lib/typescript/src/types/auth.d.ts +0 -5
  113. package/lib/typescript/src/types/auth.d.ts.map +1 -1
  114. package/lib/typescript/src/types/chat.d.ts +19 -36
  115. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  116. package/lib/typescript/src/utils/UIUtils.d.ts.map +1 -1
  117. package/lib/typescript/src/utils/legendListMessage.d.ts +4 -4
  118. package/lib/typescript/src/utils/legendListMessage.d.ts.map +1 -1
  119. package/lib/typescript/src/utils/message.d.ts +4 -5
  120. package/lib/typescript/src/utils/message.d.ts.map +1 -1
  121. package/lib/typescript/src/utils/messageUtils.d.ts +9 -7
  122. package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
  123. package/package.json +2 -2
  124. package/src/components/messages/linkMessage/index.tsx +1 -11
  125. package/src/components/messages/quotedMessage/index.tsx +197 -0
  126. package/src/components/messages/types.ts +2 -2
  127. package/src/context/ChatContext.tsx +30 -25
  128. package/src/context/ChatDetailContext.tsx +9 -3
  129. package/src/core/useChatListener.ts +0 -1
  130. package/src/core/useUserListener.ts +9 -25
  131. package/src/hooks/message/useSendMessage.ts +25 -4
  132. package/src/hooks/useChatMessages.ts +4 -6
  133. package/src/hooks/useFileAttachment.ts +3 -1
  134. package/src/index.tsx +5 -6
  135. package/src/screens/chat-detail/ChatComposer.tsx +2 -0
  136. package/src/screens/chat-detail/ChatCurrentQuotedMessage.tsx +150 -0
  137. package/src/screens/chat-detail/ChatDetail.tsx +13 -2
  138. package/src/screens/chat-detail/ChatListLegend.tsx +3 -3
  139. package/src/screens/chat-detail/PinnedMessageBar.tsx +53 -49
  140. package/src/screens/chat-detail/PinnedMessagesSheet.tsx +243 -0
  141. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +4 -4
  142. package/src/screens/chat-detail/messageToolbox/MessageToolboxMenu.tsx +30 -6
  143. package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +15 -6
  144. package/src/screens/chat-detail/messageToolbox/MessageToolboxWrapper.tsx +1 -0
  145. package/src/screens/chat-detail/messageToolbox/messageToolbox.utils.ts +21 -12
  146. package/src/screens/chat-detail/messageToolbox/types.ts +2 -2
  147. package/src/screens/chat-detail/types.ts +5 -5
  148. package/src/screens/inbox/Inbox.tsx +1 -5
  149. package/src/services/apis.ts +0 -4
  150. package/src/services/message.ts +1 -2
  151. package/src/store/message.ts +3 -3
  152. package/src/store/pinnedMessage.ts +4 -4
  153. package/src/store/user.ts +5 -5
  154. package/src/translation/resources/i18n.ts +10 -1
  155. package/src/types/auth.ts +0 -6
  156. package/src/types/chat.ts +19 -40
  157. package/src/utils/UIUtils.ts +5 -0
  158. package/src/utils/legendListMessage.ts +4 -5
  159. package/src/utils/message.ts +10 -11
  160. package/src/utils/messageUtils.ts +37 -9
@@ -0,0 +1,197 @@
1
+ import { memo, useCallback, useMemo } from 'react';
2
+ import { messageStyles } from '../styles';
3
+ import { formatMessageTime, type BaseLegendMessageProps } from '../types';
4
+ import {
5
+ KColors,
6
+ KContainer,
7
+ KImage,
8
+ KLabel,
9
+ KRadiusValue,
10
+ KSpacingValue,
11
+ } from '@droppii/libs';
12
+ import { StyleSheet } from 'react-native';
13
+ import { CHAT_BUBBLE_COLORS } from '../../../screens/chat-detail/constants';
14
+ import { MessageType } from '@droppii/openim-rn-client-sdk';
15
+ import {
16
+ getMessagePreview,
17
+ getReplySenderName,
18
+ parseUrlMetadata,
19
+ } from '../../../utils/messageUtils';
20
+ import { getFileIcon, getMimeType } from '../../../utils/imageUtils';
21
+ import { useUserStore } from '../../../store';
22
+ import { useChatDetailContext } from '../../../context';
23
+
24
+ interface QuotedMessageProps extends BaseLegendMessageProps {
25
+ onPressQuotedMessage?: (clientMsgId: string) => void;
26
+ }
27
+
28
+ const QuotedMessage = memo((props: QuotedMessageProps) => {
29
+ const { message, isOutgoing, onPressQuotedMessage, createdAtTime } =
30
+ props || {};
31
+
32
+ const { conversation } = useChatDetailContext();
33
+
34
+ const currentUserId = useUserStore((s) => s.user?.userID);
35
+
36
+ const quotedMessage = message?.quoteElem?.quoteMessage;
37
+
38
+ const timeLabel = formatMessageTime(createdAtTime);
39
+
40
+ const imageUrl = useMemo(() => {
41
+ switch (quotedMessage?.contentType) {
42
+ case MessageType.PictureMessage:
43
+ return quotedMessage?.pictureElem?.snapshotPicture?.url || '';
44
+ case MessageType.VideoMessage:
45
+ return quotedMessage?.videoElem?.snapshotUrl || '';
46
+ case MessageType.UrlTextMessage:
47
+ const metadata = parseUrlMetadata(quotedMessage?.ex);
48
+ return metadata?.image || '';
49
+ default:
50
+ return '';
51
+ }
52
+ }, [quotedMessage]);
53
+
54
+ const iconSource = useMemo(() => {
55
+ if (quotedMessage?.contentType !== MessageType.FileMessage) return '';
56
+ const mimeType = getMimeType(quotedMessage?.fileElem?.fileName || '');
57
+ return getFileIcon(mimeType);
58
+ }, [quotedMessage]);
59
+
60
+ const handlePressQuotedMessage = useCallback(() => {
61
+ onPressQuotedMessage?.(quotedMessage?.clientMsgID || '');
62
+ }, [quotedMessage, onPressQuotedMessage]);
63
+
64
+ return (
65
+ <>
66
+ <KContainer.View
67
+ style={[
68
+ messageStyles.bubble,
69
+ styles.container,
70
+ isOutgoing ? messageStyles.bubbleSent : messageStyles.bubbleReceived,
71
+ ]}
72
+ >
73
+ <KContainer.Touchable
74
+ style={styles.quotedContainer}
75
+ onPress={handlePressQuotedMessage}
76
+ >
77
+ <KContainer.View style={styles.dot} />
78
+ <KContainer.VisibleView visible={!!imageUrl}>
79
+ <KContainer.View style={styles.imageContainer}>
80
+ <KImage.Base uri={imageUrl} style={styles.imageContainer} />
81
+ <KContainer.VisibleView
82
+ visible={
83
+ quotedMessage?.contentType === MessageType.VideoMessage
84
+ }
85
+ >
86
+ <KContainer.View style={styles.playIconContainer}>
87
+ <KContainer.View style={styles.playIcon}>
88
+ <KImage.VectorIcons
89
+ name="play-b"
90
+ size={12}
91
+ color={KColors.white}
92
+ />
93
+ </KContainer.View>
94
+ </KContainer.View>
95
+ </KContainer.VisibleView>
96
+ </KContainer.View>
97
+ </KContainer.VisibleView>
98
+ <KContainer.VisibleView visible={!!iconSource}>
99
+ <KImage.Base
100
+ uri={iconSource}
101
+ style={styles.icon}
102
+ resizeMode="contain"
103
+ />
104
+ </KContainer.VisibleView>
105
+ <KContainer.View style={styles.content}>
106
+ <KLabel.Text typo="TextNmMedium" numberOfLines={1}>
107
+ {getReplySenderName(
108
+ quotedMessage,
109
+ currentUserId,
110
+ conversation,
111
+ true
112
+ )}
113
+ </KLabel.Text>
114
+ <KLabel.Text
115
+ typo="TextSmNormal"
116
+ color={KColors.gray.light}
117
+ numberOfLines={1}
118
+ >
119
+ {getMessagePreview(quotedMessage)}
120
+ </KLabel.Text>
121
+ </KContainer.View>
122
+ </KContainer.Touchable>
123
+ <KLabel.Text typo="TextMdNormal" color={CHAT_BUBBLE_COLORS.text}>
124
+ {message?.quoteElem?.text || ''}
125
+ </KLabel.Text>
126
+ </KContainer.View>
127
+
128
+ <KContainer.View row alignItems style={styles.timeLabel}>
129
+ {!isOutgoing && timeLabel ? (
130
+ <KLabel.Text
131
+ typo="TextXsNormal"
132
+ color={CHAT_BUBBLE_COLORS.timestamp}
133
+ marginL="0.25rem"
134
+ >
135
+ {timeLabel}
136
+ </KLabel.Text>
137
+ ) : null}
138
+ </KContainer.View>
139
+ </>
140
+ );
141
+ });
142
+
143
+ QuotedMessage.displayName = 'QuotedMessage';
144
+
145
+ export default QuotedMessage;
146
+
147
+ const styles = StyleSheet.create({
148
+ container: {
149
+ gap: KSpacingValue['0.25rem'],
150
+ },
151
+ quotedContainer: {
152
+ backgroundColor: KColors.white,
153
+ flexDirection: 'row',
154
+ alignItems: 'center',
155
+ gap: KSpacingValue['0.5rem'],
156
+ borderTopRightRadius: KRadiusValue['3x'],
157
+ borderBottomRightRadius: KRadiusValue['3x'],
158
+ paddingRight: KSpacingValue['0.5rem'],
159
+ },
160
+ dot: {
161
+ width: 3,
162
+ height: '100%',
163
+ backgroundColor: KColors.palette.grayCool.w200,
164
+ borderRadius: KRadiusValue.x,
165
+ marginRight: -2,
166
+ },
167
+ content: {
168
+ paddingHorizontal: KSpacingValue['0.25rem'],
169
+ paddingVertical: KSpacingValue['0.25rem'],
170
+ },
171
+ icon: {
172
+ width: 24,
173
+ height: 24,
174
+ },
175
+ imageContainer: {
176
+ width: 42,
177
+ height: 42,
178
+ borderRadius: KRadiusValue['2x'],
179
+ },
180
+ playIconContainer: {
181
+ position: 'absolute',
182
+ top: 0,
183
+ left: 0,
184
+ right: 0,
185
+ bottom: 0,
186
+ justifyContent: 'center',
187
+ alignItems: 'center',
188
+ },
189
+ playIcon: {
190
+ borderRadius: 8,
191
+ padding: KSpacingValue['0.25rem'],
192
+ backgroundColor: KColors.hexToRgba(KColors.black, 0.6),
193
+ justifyContent: 'center',
194
+ alignItems: 'center',
195
+ },
196
+ timeLabel: { gap: 4, marginTop: 2 },
197
+ });
@@ -1,8 +1,8 @@
1
- import type { DMessageItem } from '../../types/chat';
2
1
  import type { MediaItem } from '../../hooks/useMediaViewer';
2
+ import type { MessageItem } from '@droppii/openim-rn-client-sdk';
3
3
 
4
4
  export interface BaseLegendMessageProps {
5
- message: DMessageItem;
5
+ message: MessageItem;
6
6
  isOutgoing: boolean;
7
7
  createdAtTime: number;
8
8
  onMediaPress?: (items: MediaItem[], index?: number) => void;
@@ -12,9 +12,10 @@ import OpenIMSDK, {
12
12
  type ConversationItem,
13
13
  } from '@droppii/openim-rn-client-sdk';
14
14
  import Toast from 'react-native-toast-message';
15
- import { useUserStore } from '../store';
16
15
  import { useChatSdk } from '../core';
17
16
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
17
+ import uuid from 'react-native-uuid';
18
+ import { useUserStore } from '../store';
18
19
 
19
20
  export const ChatContext = createContext<ChatContextType | undefined>(
20
21
  undefined
@@ -35,30 +36,35 @@ const ChatProviderInner = ({
35
36
  getChatToken,
36
37
  onFlashMessagePress,
37
38
  }: ChatProviderProps) => {
38
- const connectStatus = useUserStore((state) => state.connectStatus);
39
39
  const [isShowFLashMessage, setShow] = useState(true);
40
40
 
41
- const handleSdkLogin = useCallback(async () => {
42
- if (!!getChatToken && connectStatus === LoginStatus.Logout) {
43
- const res = await getChatToken();
44
- if (!!res?.id && !!res?.token) {
45
- OpenIMSDK.login({
46
- token: res.token,
47
- userID: res.id,
48
- })
49
- .then(() => {
50
- useUserStore.getState().updateConnectStatus(LoginStatus.Logged);
51
- })
52
- .catch((error) => {
53
- console.error('Failed to login', error);
54
- });
41
+ const handleLoginSdk = useCallback(async () => {
42
+ if (getChatToken) {
43
+ try {
44
+ const res = await getChatToken();
45
+ const loginStatus = await OpenIMSDK.getLoginStatus();
46
+ if (!!res?.id && !!res?.token && loginStatus === LoginStatus.Logout) {
47
+ await OpenIMSDK.login(
48
+ {
49
+ token: res.token,
50
+ userID: res.id,
51
+ },
52
+ uuid.v4()
53
+ );
54
+ const userInfo = await OpenIMSDK.getSelfUserInfo();
55
+ if (userInfo) {
56
+ useUserStore.getState().setUser(userInfo);
57
+ }
58
+ }
59
+ } catch (error) {
60
+ console.error('Failed to login chat sdk', error);
55
61
  }
56
62
  }
57
- }, [getChatToken, connectStatus]);
63
+ }, [getChatToken]);
58
64
 
59
65
  useEffect(() => {
60
- handleSdkLogin();
61
- }, [handleSdkLogin]);
66
+ handleLoginSdk();
67
+ }, [handleLoginSdk]);
62
68
 
63
69
  const onPressFlashMessage = useCallback(
64
70
  (c: ConversationItem) => {
@@ -68,26 +74,25 @@ const ChatProviderInner = ({
68
74
  );
69
75
 
70
76
  const setIsShowFLashMessage = useCallback((v: boolean) => {
71
- console.log('setIsShowFLashMessage');
72
77
  setShow(v);
73
78
  }, []);
74
79
 
75
- const value = useMemo(
80
+ const value: ChatContextType = useMemo(
76
81
  () => ({
77
82
  logGA,
78
83
  applicationType,
79
- getChatToken,
80
84
  onPressFlashMessage,
81
- isShowFLashMessage: isShowFLashMessage,
82
- setIsShowFLashMessage: setIsShowFLashMessage,
85
+ isShowFLashMessage,
86
+ setIsShowFLashMessage,
87
+ handleLoginSdk,
83
88
  }),
84
89
  [
85
90
  logGA,
86
91
  applicationType,
87
- getChatToken,
88
92
  onPressFlashMessage,
89
93
  isShowFLashMessage,
90
94
  setIsShowFLashMessage,
95
+ handleLoginSdk,
91
96
  ]
92
97
  );
93
98
 
@@ -13,7 +13,7 @@ import {
13
13
  } from '../types/chat';
14
14
  import { fechtCurrentConversationFlow } from '../hooks/flows/useCurrentConversationFlow';
15
15
  import { useConversationStore } from '../store';
16
- import { PeerType } from '@droppii/openim-rn-client-sdk';
16
+ import { PeerType, type MessageItem } from '@droppii/openim-rn-client-sdk';
17
17
  import {
18
18
  DFlowContext,
19
19
  NodeTypes,
@@ -27,11 +27,12 @@ import { CONTEXT_BUTTON_PREFIX, isContextButton } from '../utils/flows';
27
27
  export const ChatDetailContext = createContext<ChatDetailContextType>({
28
28
  isBotConversation: false,
29
29
  conversationFlow: undefined,
30
- refetchConversationFlow: () => {},
31
30
  setConverationFlowStep: () => {},
32
31
  flowState: undefined,
33
32
  runButtonContext: () => Promise.resolve(false),
34
33
  conversation: undefined,
34
+ quotedMessage: undefined,
35
+ setQuotedMessage: () => {},
35
36
  });
36
37
 
37
38
  export const useChatDetailContext = (): ChatDetailContextType => {
@@ -55,6 +56,10 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
55
56
  IConversationFlow | undefined
56
57
  >(undefined);
57
58
 
59
+ const [quotedMessage, setQuotedMessage] = useState<MessageItem | undefined>(
60
+ undefined
61
+ );
62
+
58
63
  const flowState = useMemo(() => {
59
64
  return conversationFlow
60
65
  ? conversationFlow?.flowCurrentStep?.data?.children?.some(
@@ -124,12 +129,13 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
124
129
  <ChatDetailContext.Provider
125
130
  value={{
126
131
  conversationFlow,
127
- refetchConversationFlow: () => {},
128
132
  setConverationFlowStep,
129
133
  isBotConversation,
130
134
  flowState,
131
135
  runButtonContext,
132
136
  conversation,
137
+ quotedMessage,
138
+ setQuotedMessage,
133
139
  }}
134
140
  >
135
141
  {children}
@@ -37,7 +37,6 @@ export const useChatListener = () => {
37
37
 
38
38
  const onConversationChanged = useCallback(
39
39
  (conversations: ConversationItem[]) => {
40
- // console.log('isShowFLashMessage', isShowFLashMessage);
41
40
  useConversationStore.getState().updateConversations(conversations);
42
41
  if (isShowFLashMessage) {
43
42
  for (const conversation of conversations) {
@@ -1,45 +1,28 @@
1
1
  import OpenIMSDK, {
2
- LoginStatus,
3
2
  OpenIMEvent,
4
3
  type OpenIMEventBaseErrorType,
5
4
  } from '@droppii/openim-rn-client-sdk';
6
5
  import { useCallback, useEffect } from 'react';
7
6
  import { useUserStore } from '../store';
8
- import { SyncStatus } from '../types/auth';
9
- import { ChatAPI } from '../services';
7
+ import { ConnectStatus, SyncStatus } from '../types/chat';
8
+ import { useChatContext } from '../context';
10
9
 
11
10
  export const useUserListener = () => {
12
- const isLoggedIn = useUserStore(
13
- (state) => state.connectStatus === LoginStatus.Logged
14
- );
15
-
16
- const fetchAndUpdateUser = useCallback(async () => {
17
- try {
18
- const user = await ChatAPI.getUser();
19
- useUserStore.getState().setUser(user);
20
- } catch (error) {
21
- console.error('OpenIM get user failed', error);
22
- }
23
- }, []);
24
-
25
- useEffect(() => {
26
- if (isLoggedIn) {
27
- fetchAndUpdateUser();
28
- }
29
- }, [isLoggedIn, fetchAndUpdateUser]);
11
+ const { handleLoginSdk } = useChatContext();
30
12
 
31
13
  const onConnecting = useCallback(() => {
32
14
  console.log('[Listener] OnConnecting');
33
- useUserStore.getState().updateConnectStatus(LoginStatus.Logging);
15
+ useUserStore.getState().updateConnectStatus(ConnectStatus.Connecting);
34
16
  }, []);
35
17
 
36
18
  const onConnectSuccess = useCallback(() => {
37
19
  console.log('[Listener] OnConnectSuccess');
38
- useUserStore.getState().updateConnectStatus(LoginStatus.Logged);
20
+ useUserStore.getState().updateConnectStatus(ConnectStatus.Connected);
39
21
  }, []);
40
22
 
41
23
  const onConnectFailed = useCallback((data: OpenIMEventBaseErrorType) => {
42
24
  console.log('[Listener] OnConnectFailed', data);
25
+ useUserStore.getState().updateConnectStatus(ConnectStatus.Disconnected);
43
26
  }, []);
44
27
 
45
28
  const onSyncServerStart = useCallback((isSyncing: boolean) => {
@@ -59,7 +42,8 @@ export const useUserListener = () => {
59
42
 
60
43
  const onUserToken = useCallback(() => {
61
44
  console.log('[Listener] OnUserToken expired/invalid');
62
- }, []);
45
+ handleLoginSdk();
46
+ }, [handleLoginSdk]);
63
47
 
64
48
  useEffect(() => {
65
49
  // User
@@ -88,5 +72,5 @@ export const useUserListener = () => {
88
72
  OpenIMSDK.off(OpenIMEvent.OnSyncServerFailed, onSyncServerFailed);
89
73
  };
90
74
  // eslint-disable-next-line react-hooks/exhaustive-deps
91
- }, []);
75
+ }, [onUserToken]);
92
76
  };
@@ -5,6 +5,7 @@ import type {
5
5
  CustomMsgParams,
6
6
  MessageItem,
7
7
  OfflinePush,
8
+ QuoteMsgParams,
8
9
  } from '@droppii/openim-rn-client-sdk';
9
10
  import { MessageStatus, MessageType } from '@droppii/openim-rn-client-sdk';
10
11
  import { extractUrls } from '../../utils/url';
@@ -14,7 +15,7 @@ import {
14
15
  type CustomMessagePayload,
15
16
  type IMessageItemEx,
16
17
  } from '../../types/chat';
17
- import { useChatContext } from '../../context';
18
+ import { useChatContext, useChatDetailContext } from '../../context';
18
19
  import { generateContentBasedOnMessageType } from '../../utils/conversation';
19
20
  import { markMessageRevoked, useMessageStore } from '../../store/message';
20
21
  import uuid from 'react-native-uuid';
@@ -40,6 +41,8 @@ export const useSendMessage = () => {
40
41
  const pushNewMessage = useMessageStore((state) => state.pushNewMessage);
41
42
  const updateOneMessage = useMessageStore((state) => state.updateOneMessage);
42
43
  const deleteOneMessage = useMessageStore((state) => state.deleteOneMessage);
44
+ const { quotedMessage, setQuotedMessage } = useChatDetailContext();
45
+
43
46
  const dispatchSend = useCallback(
44
47
  async (
45
48
  message: MessageItem,
@@ -91,12 +94,18 @@ export const useSendMessage = () => {
91
94
  const hasPreview = !!urlMetadata?.url;
92
95
 
93
96
  //text msg
94
- if (hasText || hasPreview) {
97
+ if (hasText) {
95
98
  const urls = hasText ? extractUrls(plainText) : [];
96
99
  const isUrlMessage = urls.length > 0 || hasPreview;
97
100
  let message: MessageItem | null = null;
98
101
 
99
- if (isUrlMessage) {
102
+ if (quotedMessage) {
103
+ message = await createQuotedMessage({
104
+ text: plainText || '',
105
+ message: quotedMessage,
106
+ });
107
+ setQuotedMessage(undefined);
108
+ } else if (isUrlMessage) {
100
109
  message = await createUrlTextMessage(plainText || '', urls);
101
110
  } else if (hasText) {
102
111
  message = await createTextMessage(plainText);
@@ -137,7 +146,7 @@ export const useSendMessage = () => {
137
146
  );
138
147
  }
139
148
  },
140
- [applicationType, dispatchSend]
149
+ [applicationType, dispatchSend, quotedMessage, setQuotedMessage]
141
150
  );
142
151
 
143
152
  const retryMessage = useCallback(
@@ -274,3 +283,15 @@ export const createCustomMessage = async (params: CustomMsgParams) => {
274
283
  });
275
284
  return customMessage;
276
285
  };
286
+
287
+ export const createQuotedMessage = async (params: QuoteMsgParams) => {
288
+ let quotedMessage = await OpenIMSDK.createQuoteMessage(params, uuid.v4())
289
+ .then((data) => {
290
+ return data;
291
+ })
292
+ .catch(({ errCode, errMsg }) => {
293
+ console.error('createQuotedMessage', errCode, errMsg);
294
+ return null;
295
+ });
296
+ return quotedMessage;
297
+ };
@@ -4,7 +4,6 @@ import OpenIMSDK, {
4
4
  } from '@droppii/openim-rn-client-sdk';
5
5
  import { useCallback, useEffect, useRef, useState } from 'react';
6
6
  import { ChatMessageAPI } from '../services/message';
7
- import type { DMessageItem } from '../types/chat';
8
7
  import {
9
8
  belongsToConversation,
10
9
  hasNewHistoryMessages,
@@ -71,8 +70,7 @@ export function useChatMessages({
71
70
  }
72
71
 
73
72
  if (historyResult.status === 'fulfilled') {
74
- const initialMessages = historyResult.value
75
- .messageList as DMessageItem[];
73
+ const initialMessages = historyResult.value.messageList;
76
74
  setMessages(
77
75
  mergeMessages([], initialMessages),
78
76
  !historyResult.value.isEnd
@@ -92,7 +90,7 @@ export function useChatMessages({
92
90
  );
93
91
  const localMessages = (localResult?.searchResultItems ?? []).flatMap(
94
92
  (item: any) => item.messageList ?? []
95
- ) as DMessageItem[];
93
+ );
96
94
  console.log(
97
95
  '[useChatMessages] searchLocalMessages fallback result:',
98
96
  localMessages.length,
@@ -126,7 +124,7 @@ export function useChatMessages({
126
124
  }
127
125
  );
128
126
 
129
- const incoming = history.messageList as DMessageItem[];
127
+ const incoming = history.messageList;
130
128
  const hasNew = hasNewHistoryMessages(messages, incoming);
131
129
 
132
130
  if (hasNew) {
@@ -166,7 +164,7 @@ export function useChatMessages({
166
164
  }
167
165
  );
168
166
 
169
- const incoming = history.messageList as DMessageItem[];
167
+ const incoming = history.messageList;
170
168
  const hasNew = incoming.length > 0;
171
169
 
172
170
  if (hasNew) {
@@ -99,7 +99,9 @@ export const useFileAttachment = (): UseFileAttachmentReturn => {
99
99
  let candidates = picked;
100
100
  if (oversized.length > 0) {
101
101
  UIUtils.toast.open({
102
- title: trans('chat:file_too_large'),
102
+ title: trans('chat:file_too_large', {
103
+ maxSize: String(MAX_FILE_SIZE / 1024 / 1024),
104
+ }),
103
105
  theme: 'danger',
104
106
  });
105
107
  candidates = picked.filter((f) => f.size <= MAX_FILE_SIZE);
package/src/index.tsx CHANGED
@@ -31,12 +31,11 @@ export { Inbox } from './screens/inbox';
31
31
  export { default as MediaViewerScreen } from './screens/MediaView';
32
32
  export * from './screens/chat-detail';
33
33
 
34
- // export type {
35
- // PeerType,
36
- // MessageItem,
37
- // ConversationItem,
38
- // } from '@droppii/openim-rn-client-sdk';
39
- export type { ConversationItem } from '@droppii/openim-rn-client-sdk';
34
+ export type {
35
+ PeerType,
36
+ MessageItem,
37
+ ConversationItem,
38
+ } from '@droppii/openim-rn-client-sdk';
40
39
  export { LoginStatus, MessageType } from '@droppii/openim-rn-client-sdk';
41
40
  export * from './screens/chat-detail';
42
41
  export type {
@@ -32,6 +32,7 @@ import { ReactFlowsNodeTypes } from '../../types/flows';
32
32
  import { useAttachmentMapping } from './hooks/useAttachmentMapping';
33
33
  import type { AttachmentType } from '../../types/attachment';
34
34
  import { useChatCompose } from '../../hooks/useChatCompose';
35
+ import { ChatCurrentQuotedMessage } from './ChatCurrentQuotedMessage';
35
36
 
36
37
  interface ChatComposerInternalProps {
37
38
  isEmptyMessage?: boolean;
@@ -213,6 +214,7 @@ export const ChatComposer = memo(
213
214
 
214
215
  return (
215
216
  <KContainer.View background={'rgba(131, 137, 157, 0.05)'}>
217
+ <ChatCurrentQuotedMessage />
216
218
  <ChatQuickActions
217
219
  visible
218
220
  actions={DEFAULT_QUICK_ACTIONS}