@droppii-org/chat-mobile 0.2.30 → 0.2.32

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 (91) hide show
  1. package/lib/module/assets/images/index.js +1 -0
  2. package/lib/module/assets/images/index.js.map +1 -1
  3. package/lib/module/assets/images/notification-warning.png +0 -0
  4. package/lib/module/components/ThreadCard/MuteThread.js +71 -31
  5. package/lib/module/components/ThreadCard/MuteThread.js.map +1 -1
  6. package/lib/module/components/ThreadCard/ThreadCard.js +13 -4
  7. package/lib/module/components/ThreadCard/ThreadCard.js.map +1 -1
  8. package/lib/module/components/messages/fileMessage/index.js +2 -1
  9. package/lib/module/components/messages/fileMessage/index.js.map +1 -1
  10. package/lib/module/context/ChatContext.js +46 -12
  11. package/lib/module/context/ChatContext.js.map +1 -1
  12. package/lib/module/context/global.js +6 -0
  13. package/lib/module/context/global.js.map +1 -0
  14. package/lib/module/core/useChatListener.js +33 -12
  15. package/lib/module/core/useChatListener.js.map +1 -1
  16. package/lib/module/hooks/message/useSendMessage.js +9 -3
  17. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  18. package/lib/module/hooks/query-keys.js +2 -1
  19. package/lib/module/hooks/query-keys.js.map +1 -1
  20. package/lib/module/hooks/useChatMessages.js +5 -1
  21. package/lib/module/hooks/useChatMessages.js.map +1 -1
  22. package/lib/module/hooks/useImageAttachment.js +2 -0
  23. package/lib/module/hooks/useImageAttachment.js.map +1 -1
  24. package/lib/module/hooks/useIsJoinedGroup.js +15 -0
  25. package/lib/module/hooks/useIsJoinedGroup.js.map +1 -0
  26. package/lib/module/index.js +9 -1
  27. package/lib/module/index.js.map +1 -1
  28. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +1 -4
  29. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  30. package/lib/module/services/attachmentOrchestrator.js +3 -1
  31. package/lib/module/services/attachmentOrchestrator.js.map +1 -1
  32. package/lib/module/translation/resources/i18n.js +1 -1
  33. package/lib/module/translation/resources/i18n.js.map +1 -1
  34. package/lib/module/types/chat.js.map +1 -1
  35. package/lib/module/utils/device.js +1 -1
  36. package/lib/module/utils/device.js.map +1 -1
  37. package/lib/module/utils/messageUtils.js +1 -1
  38. package/lib/module/utils/messageUtils.js.map +1 -1
  39. package/lib/module/utils/toastFlashMessage.js +56 -0
  40. package/lib/module/utils/toastFlashMessage.js.map +1 -0
  41. package/lib/typescript/src/assets/images/index.d.ts +1 -0
  42. package/lib/typescript/src/assets/images/index.d.ts.map +1 -1
  43. package/lib/typescript/src/components/ThreadCard/MuteThread.d.ts.map +1 -1
  44. package/lib/typescript/src/components/ThreadCard/ThreadCard.d.ts.map +1 -1
  45. package/lib/typescript/src/context/ChatContext.d.ts.map +1 -1
  46. package/lib/typescript/src/context/global.d.ts +3 -0
  47. package/lib/typescript/src/context/global.d.ts.map +1 -0
  48. package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
  49. package/lib/typescript/src/hooks/message/useSendMessage.d.ts +3 -1
  50. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  51. package/lib/typescript/src/hooks/query-keys.d.ts +1 -0
  52. package/lib/typescript/src/hooks/query-keys.d.ts.map +1 -1
  53. package/lib/typescript/src/hooks/useChatMessages.d.ts.map +1 -1
  54. package/lib/typescript/src/hooks/useImageAttachment.d.ts.map +1 -1
  55. package/lib/typescript/src/hooks/useIsJoinedGroup.d.ts +2 -0
  56. package/lib/typescript/src/hooks/useIsJoinedGroup.d.ts.map +1 -0
  57. package/lib/typescript/src/index.d.ts +4 -3
  58. package/lib/typescript/src/index.d.ts.map +1 -1
  59. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +1 -1
  60. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  61. package/lib/typescript/src/services/attachmentOrchestrator.d.ts.map +1 -1
  62. package/lib/typescript/src/types/chat.d.ts +4 -0
  63. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  64. package/lib/typescript/src/types/imageUpload.d.ts +1 -1
  65. package/lib/typescript/src/types/imageUpload.d.ts.map +1 -1
  66. package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
  67. package/lib/typescript/src/utils/toastFlashMessage.d.ts +12 -0
  68. package/lib/typescript/src/utils/toastFlashMessage.d.ts.map +1 -0
  69. package/package.json +5 -3
  70. package/src/assets/images/index.ts +1 -0
  71. package/src/assets/images/notification-warning.png +0 -0
  72. package/src/components/ThreadCard/MuteThread.tsx +70 -36
  73. package/src/components/ThreadCard/ThreadCard.tsx +11 -3
  74. package/src/components/messages/fileMessage/index.tsx +1 -0
  75. package/src/context/ChatContext.tsx +66 -9
  76. package/src/context/global.ts +6 -0
  77. package/src/core/useChatListener.ts +47 -11
  78. package/src/hooks/message/useSendMessage.ts +13 -9
  79. package/src/hooks/query-keys.ts +1 -0
  80. package/src/hooks/useChatMessages.ts +6 -2
  81. package/src/hooks/useImageAttachment.ts +2 -0
  82. package/src/hooks/useIsJoinedGroup.ts +13 -0
  83. package/src/index.tsx +10 -18
  84. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +1 -5
  85. package/src/services/attachmentOrchestrator.ts +2 -0
  86. package/src/translation/resources/i18n.ts +1 -1
  87. package/src/types/chat.ts +4 -0
  88. package/src/types/imageUpload.ts +1 -1
  89. package/src/utils/device.ts +1 -1
  90. package/src/utils/messageUtils.ts +1 -3
  91. package/src/utils/toastFlashMessage.ts +67 -0
@@ -1,5 +1,6 @@
1
1
  import { useCallback } from 'react';
2
2
  import { useConversationStore } from '../../store/conversation';
3
+ import { useUserStore } from '../../store/user';
3
4
  import type {
4
5
  CustomMsgParams,
5
6
  MessageItem,
@@ -50,15 +51,15 @@ export const useSendMessage = () => {
50
51
  pushNewMessage({ ...message, status: MessageStatus.Sending });
51
52
 
52
53
  try {
53
- const sent = await OpenIMSDK.sendMessage(
54
- buildSendParams(
55
- message,
56
- recvID,
57
- groupID,
58
- extendMessageInfo,
59
- plainText
60
- )
54
+ const sendParams = buildSendParams(
55
+ message,
56
+ recvID,
57
+ groupID,
58
+ extendMessageInfo,
59
+ plainText
61
60
  );
61
+ console.log('[useSendMessage] dispatchSend params', sendParams);
62
+ const sent = await OpenIMSDK.sendMessage(sendParams);
62
63
  deleteOneMessage(message.clientMsgID);
63
64
  pushNewMessage(sent);
64
65
  } catch {
@@ -162,6 +163,7 @@ export const useSendMessage = () => {
162
163
  recvID: recvID || '',
163
164
  groupID: groupID || '',
164
165
  message,
166
+ offlinePushInfo: generateOfflinePushInfo(message.contentType, ''),
165
167
  };
166
168
 
167
169
  try {
@@ -208,13 +210,14 @@ export const useSendMessage = () => {
208
210
  };
209
211
  };
210
212
 
211
- const generateOfflinePushInfo = (
213
+ export const generateOfflinePushInfo = (
212
214
  contentType: MessageType,
213
215
  plainText: string
214
216
  ) => {
215
217
  const conversationData = useConversationStore
216
218
  ?.getState?.()
217
219
  ?.getCurrentConversation();
220
+ const operatorUserID = useUserStore.getState().user?.userID || '';
218
221
  const title = conversationData?.showName || 'Droppii';
219
222
  const desc = generateContentBasedOnMessageType(contentType, plainText);
220
223
  return {
@@ -223,6 +226,7 @@ const generateOfflinePushInfo = (
223
226
  ex: JSON.stringify({
224
227
  icon: conversationData?.faceURL || '',
225
228
  conversationId: conversationData?.conversationID || '',
229
+ operatorUserID,
226
230
  title,
227
231
  desc,
228
232
  }),
@@ -23,6 +23,7 @@ export const conversationQueryKeys = {
23
23
  runFlow: (conversationId: string) => ['runConversationFlow', conversationId],
24
24
  detailByBotId: (botId: string) => ['conversationByBotId', botId],
25
25
  detailBySourceId: (sourceId: string) => ['detailBySourceId', sourceId],
26
+ joinedGroup: (groupId?: string) => [...conversationQueryKeys.all, groupId],
26
27
  };
27
28
 
28
29
  export type ConversationQueryKeys = typeof conversationQueryKeys;
@@ -14,6 +14,7 @@ import { useMessageStore } from '../store/message';
14
14
  import { useUserStore } from '../store/user';
15
15
  import { useChatContext } from '../context';
16
16
  import { allSettled } from '../utils/promise';
17
+ import { useSetIsShowFLashMessage } from '../context/global';
17
18
 
18
19
  type UseChatMessagesOptions = {
19
20
  conversationId: string;
@@ -46,6 +47,8 @@ export function useChatMessages({
46
47
  const conversationIdRef = useRef(conversationId);
47
48
  conversationIdRef.current = conversationId;
48
49
 
50
+ const setIsShowFlashMessage = useSetIsShowFLashMessage();
51
+
49
52
  const fetchInitial = useCallback(async () => {
50
53
  if (!conversationId) return;
51
54
 
@@ -217,16 +220,17 @@ export function useChatMessages({
217
220
 
218
221
  useEffect(() => {
219
222
  if (!enabled || !conversationId) return;
220
-
223
+ setIsShowFlashMessage(false);
221
224
  const handleNewMessages = (incoming: MessageItem[]) =>
222
225
  appendIncomingMessages(incoming);
223
226
 
224
227
  OpenIMSDK.on(OpenIMEvent.OnRecvNewMessages, handleNewMessages);
225
228
 
226
229
  return () => {
230
+ setIsShowFlashMessage(true);
227
231
  OpenIMSDK.off(OpenIMEvent.OnRecvNewMessages, handleNewMessages);
228
232
  };
229
- }, [appendIncomingMessages, conversationId, enabled]);
233
+ }, [appendIncomingMessages, conversationId, enabled, setIsShowFlashMessage]);
230
234
 
231
235
  return {
232
236
  messages,
@@ -171,6 +171,8 @@ export const useImageAttachment = (): UseImageAttachmentReturn => {
171
171
  const maxSize = isVideoFromPicker(item)
172
172
  ? UPLOAD_LIMITS.video
173
173
  : UPLOAD_LIMITS.image;
174
+ console.log('maxSize', maxSize);
175
+ console.log('item.size', item.size);
174
176
  return (item.size || 0) <= maxSize;
175
177
  };
176
178
 
@@ -0,0 +1,13 @@
1
+ import { useQuery } from '@tanstack/react-query';
2
+ import OpenIMSDK from '@droppii/openim-rn-client-sdk';
3
+ import { conversationQueryKeys } from './query-keys';
4
+
5
+ export const useIsJoinedGroup = (groupId?: string) => {
6
+ return useQuery({
7
+ queryKey: conversationQueryKeys.joinedGroup(groupId),
8
+ enabled: Boolean(groupId),
9
+ queryFn: async () => {
10
+ return await OpenIMSDK.isJoinGroup(groupId!);
11
+ },
12
+ });
13
+ };
package/src/index.tsx CHANGED
@@ -29,17 +29,16 @@ export { AttachmentPreview } from './components/AttachmentPreview';
29
29
  export { MediaViewerModal } from './components/MediaViewerModal';
30
30
  export { Inbox } from './screens/inbox';
31
31
  export { default as MediaViewerScreen } from './screens/MediaView';
32
- export {
33
- ChatDetail,
34
- ChatDetailHeader,
35
- ChatComposer,
36
- ChatQuickActions,
37
- ChatAttachmentPanel,
38
- DEFAULT_QUICK_ACTIONS,
39
- DEFAULT_PANNEL_ACTIONS,
40
- DChatPannelActionItemType,
41
- DChatQuickActionItemType,
42
- } from './screens/chat-detail';
32
+ export * from './screens/chat-detail';
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';
40
+ export { LoginStatus, MessageType } from '@droppii/openim-rn-client-sdk';
41
+ export * from './screens/chat-detail';
43
42
  export type {
44
43
  DChatActionItem,
45
44
  DChatActionIconProvider,
@@ -54,13 +53,6 @@ export type {
54
53
  ChatPanelProps,
55
54
  } from './screens/chat-detail';
56
55
 
57
- export { LoginStatus, MessageType } from '@droppii/openim-rn-client-sdk';
58
- export type {
59
- PeerType,
60
- ConversationItem,
61
- MessageItem,
62
- } from '@droppii/openim-rn-client-sdk';
63
-
64
56
  export { registerUIUtils, UIUtils } from './utils/UIUtils';
65
57
 
66
58
  export { DFlowContext } from './types/flows';
@@ -71,11 +71,7 @@ export const LegendChatMessage = memo(
71
71
  const customNode = customMessageItemFactory?.(message);
72
72
 
73
73
  if (customNode) {
74
- return (
75
- <LongPressWrapper onLongPress={onLongPress}>
76
- {customNode}
77
- </LongPressWrapper>
78
- );
74
+ return customNode;
79
75
  }
80
76
 
81
77
  const MessageComponent: ComponentType<MessageProps> =
@@ -16,6 +16,7 @@ import {
16
16
  type AttachmentType,
17
17
  } from '../config/attachment-priority';
18
18
  import { allSettled } from '../utils/promise';
19
+ import { generateOfflinePushInfo } from '../hooks/message/useSendMessage';
19
20
 
20
21
  export namespace AttachmentOrchestratorService {
21
22
  export async function sendPreparedAttachments(
@@ -290,6 +291,7 @@ export namespace AttachmentOrchestratorService {
290
291
  recvID,
291
292
  groupID,
292
293
  message,
294
+ offlinePushInfo: generateOfflinePushInfo(message.contentType, ''),
293
295
  });
294
296
 
295
297
  if (result) {
@@ -45,7 +45,7 @@ const i18nKey: Record<string, string> = {
45
45
  'chat:unmute_action': 'Bật thông báo',
46
46
  'chat:mute_confirm_title': 'Tắt thông báo',
47
47
  'chat:mute_confirm_desc':
48
- 'Bạn có thể bỏ lỡ tin nhắn quan trọng nếu tắt thông báo! Bạn có chắc chắn muốn tắt thông báo?',
48
+ 'Bạn có thể bỏ lỡ tin nhắn quan trọng nếu tắt thông báo! Bạn có chắc chắn muốn <b>tắt thông báo</b>?',
49
49
  'chat:mute_confirm_primary': 'Tắt thông báo',
50
50
  'chat:mute_confirm_secondary': 'Quay lại',
51
51
  'chat:mute_toast_success': 'Đã tắt thông báo',
package/src/types/chat.ts CHANGED
@@ -33,12 +33,16 @@ export interface ChatUIAdapter {
33
33
  export interface ChatContextType {
34
34
  logGA?: LogGA;
35
35
  applicationType: DChatApplicationType;
36
+ onPressFlashMessage?: (message: ConversationItem) => void;
37
+ isShowFLashMessage: boolean;
38
+ setIsShowFLashMessage: (value: boolean) => void;
36
39
  }
37
40
 
38
41
  export type ChatProviderProps = PropsWithChildren<{
39
42
  logGA?: LogGA;
40
43
  applicationType: DChatApplicationType;
41
44
  getChatToken: () => Promise<GetOpenIMTokenResponse | null>;
45
+ onFlashMessagePress?: (c: ConversationItem) => void;
42
46
  }>;
43
47
 
44
48
  export enum DChatApplicationType {
@@ -21,7 +21,7 @@ export interface ImageUploadConfig {
21
21
  retryAttempts?: number;
22
22
  }
23
23
 
24
- export interface UploadProgress {
24
+ export interface IUploadProgress {
25
25
  completed: number;
26
26
  total: number;
27
27
  percentage: number;
@@ -132,7 +132,7 @@ const DeviceUtils = {
132
132
  try {
133
133
  const results = await pickDocument({
134
134
  allowMultiSelection: multiple,
135
- type: [documentTypes.allFiles],
135
+ type: [documentTypes.pdf, documentTypes.doc, documentTypes.docx],
136
136
  mode: 'import',
137
137
  });
138
138
 
@@ -86,8 +86,7 @@ export const getMessagePreview = (message: DMessageItem): string => {
86
86
  if (message?.customElem?.description) {
87
87
  return message?.customElem?.description;
88
88
  }
89
- break;
90
-
89
+ return '';
91
90
  default:
92
91
  return '[Tin nhắn không được hỗ trợ]';
93
92
  }
@@ -99,7 +98,6 @@ export const getLastMessageText = (
99
98
  conversation?: ConversationItem
100
99
  ): string => {
101
100
  if (!message) return '';
102
-
103
101
  const preview = getMessagePreview(message);
104
102
  if (!preview) return '';
105
103
 
@@ -0,0 +1,67 @@
1
+ import Toast from 'react-native-toast-message';
2
+
3
+ interface ShowFlashMessageParams {
4
+ key: string;
5
+ title: string;
6
+ body?: string;
7
+ onPress?: () => void;
8
+ }
9
+
10
+ let currentKey: string | null = null;
11
+ const queue: ShowFlashMessageParams[] = [];
12
+
13
+ const VISIBILITY_TIME_MS = 2000;
14
+
15
+ const displayToast = (params: ShowFlashMessageParams) => {
16
+ currentKey = params.key;
17
+ Toast.show({
18
+ type: 'info',
19
+ text1: params.title,
20
+ text2: params.body,
21
+ onPress: params.onPress,
22
+ onHide: advanceQueue,
23
+ visibilityTime: VISIBILITY_TIME_MS,
24
+ });
25
+ };
26
+
27
+ function advanceQueue() {
28
+ const next = queue.shift();
29
+ if (!next) {
30
+ currentKey = null;
31
+ return;
32
+ }
33
+ displayToast(next);
34
+ }
35
+
36
+ export const ToastFlashMessage = {
37
+ show: (params: ShowFlashMessageParams) => {
38
+ if (params.key === currentKey) {
39
+ displayToast(params);
40
+ return;
41
+ }
42
+
43
+ const queuedIndex = queue.findIndex((item) => item.key === params.key);
44
+ if (queuedIndex !== -1) {
45
+ queue[queuedIndex] = params;
46
+ return;
47
+ }
48
+
49
+ if (currentKey === null) {
50
+ displayToast(params);
51
+ } else {
52
+ queue.push(params);
53
+ }
54
+ },
55
+ hide: (key: string) => {
56
+ if (key === currentKey) {
57
+ Toast.hide();
58
+ currentKey = null;
59
+ advanceQueue();
60
+ } else {
61
+ const index = queue.findIndex((item) => item.key === key);
62
+ if (index !== -1) {
63
+ queue.splice(index, 1);
64
+ }
65
+ }
66
+ },
67
+ };