@droppii-org/chat-mobile 0.2.46 → 0.2.48

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 (68) hide show
  1. package/lib/module/config/api-endpoints.js +1 -1
  2. package/lib/module/config/api-endpoints.js.map +1 -1
  3. package/lib/module/core/useChatListener.js +3 -2
  4. package/lib/module/core/useChatListener.js.map +1 -1
  5. package/lib/module/hooks/message/useSendMessage.js +5 -4
  6. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  7. package/lib/module/hooks/query-keys.js +6 -1
  8. package/lib/module/hooks/query-keys.js.map +1 -1
  9. package/lib/module/hooks/useChatCompose.js +18 -1
  10. package/lib/module/hooks/useChatCompose.js.map +1 -1
  11. package/lib/module/hooks/users/useGetUsersInfo.js +14 -0
  12. package/lib/module/hooks/users/useGetUsersInfo.js.map +1 -0
  13. package/lib/module/screens/chat-detail/ChatDetail.js +6 -15
  14. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  15. package/lib/module/screens/chat-detail/ChatDetailHeader.js +21 -4
  16. package/lib/module/screens/chat-detail/ChatDetailHeader.js.map +1 -1
  17. package/lib/module/screens/chat-detail/ChatListLegend.js +0 -2
  18. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  19. package/lib/module/screens/inbox/Inbox.js +3 -3
  20. package/lib/module/screens/inbox/Inbox.js.map +1 -1
  21. package/lib/module/services/endpoints.js +6 -5
  22. package/lib/module/services/endpoints.js.map +1 -1
  23. package/lib/module/store/conversation.js +24 -3
  24. package/lib/module/store/conversation.js.map +1 -1
  25. package/lib/module/utils/message.js +2 -2
  26. package/lib/module/utils/message.js.map +1 -1
  27. package/lib/typescript/src/config/api-endpoints.d.ts +1 -1
  28. package/lib/typescript/src/config/api-endpoints.d.ts.map +1 -1
  29. package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
  30. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  31. package/lib/typescript/src/hooks/query-keys.d.ts +5 -0
  32. package/lib/typescript/src/hooks/query-keys.d.ts.map +1 -1
  33. package/lib/typescript/src/hooks/useChatCompose.d.ts.map +1 -1
  34. package/lib/typescript/src/hooks/users/useGetUsersInfo.d.ts +2 -0
  35. package/lib/typescript/src/hooks/users/useGetUsersInfo.d.ts.map +1 -0
  36. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  37. package/lib/typescript/src/screens/chat-detail/ChatDetailHeader.d.ts +1 -1
  38. package/lib/typescript/src/screens/chat-detail/ChatDetailHeader.d.ts.map +1 -1
  39. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts +1 -2
  40. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
  41. package/lib/typescript/src/screens/chat-detail/types.d.ts +1 -0
  42. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  43. package/lib/typescript/src/screens/inbox/Inbox.d.ts +2 -2
  44. package/lib/typescript/src/screens/inbox/Inbox.d.ts.map +1 -1
  45. package/lib/typescript/src/services/endpoints.d.ts +1 -0
  46. package/lib/typescript/src/services/endpoints.d.ts.map +1 -1
  47. package/lib/typescript/src/store/conversation.d.ts +6 -1
  48. package/lib/typescript/src/store/conversation.d.ts.map +1 -1
  49. package/lib/typescript/src/types/chat.d.ts +19 -0
  50. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  51. package/lib/typescript/src/utils/message.d.ts +1 -1
  52. package/lib/typescript/src/utils/message.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/config/api-endpoints.ts +2 -2
  55. package/src/core/useChatListener.ts +3 -2
  56. package/src/hooks/message/useSendMessage.ts +8 -2
  57. package/src/hooks/query-keys.ts +6 -0
  58. package/src/hooks/useChatCompose.ts +19 -0
  59. package/src/hooks/users/useGetUsersInfo.ts +13 -0
  60. package/src/screens/chat-detail/ChatDetail.tsx +10 -16
  61. package/src/screens/chat-detail/ChatDetailHeader.tsx +20 -4
  62. package/src/screens/chat-detail/ChatListLegend.tsx +0 -3
  63. package/src/screens/chat-detail/types.ts +1 -0
  64. package/src/screens/inbox/Inbox.tsx +9 -4
  65. package/src/services/endpoints.ts +5 -5
  66. package/src/store/conversation.ts +37 -3
  67. package/src/types/chat.ts +21 -0
  68. package/src/utils/message.ts +7 -2
@@ -1,10 +1,7 @@
1
1
  import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
2
- import { DeviceEventEmitter, View } from 'react-native';
2
+ import { DeviceEventEmitter } from 'react-native';
3
3
 
4
- import {
5
- useKeyboardChatComposerInset,
6
- useKeyboardScrollToEnd,
7
- } from '@legendapp/list/keyboard';
4
+ import { useKeyboardScrollToEnd } from '@legendapp/list/keyboard';
8
5
  import type { LegendListRef } from '@legendapp/list/react-native';
9
6
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
10
7
  import { KContainer } from '@droppii/libs';
@@ -114,13 +111,15 @@ const ChatDetail = memo(
114
111
  usePinMessage(conversationId);
115
112
 
116
113
  useEffect(() => {
117
- if (conversationId) {
118
- useConversationStore.getState().setCurrentConversation(conversationId);
119
- }
114
+ useConversationStore
115
+ .getState()
116
+ .setCurrentConversation(conversationId, targetUserId, targetGroupId);
120
117
  return () => {
121
- useConversationStore.getState().setCurrentConversation(undefined);
118
+ useConversationStore
119
+ .getState()
120
+ .setCurrentConversation(undefined, undefined, undefined);
122
121
  };
123
- }, [conversationId]);
122
+ }, [conversationId, targetUserId, targetGroupId]);
124
123
 
125
124
  const resolvedShowAddMember =
126
125
  showAddMember ?? shouldShowAddMember(conversation);
@@ -128,9 +127,6 @@ const ChatDetail = memo(
128
127
  const insets = useSafeAreaInsets();
129
128
 
130
129
  const listRef = useRef<LegendListRef>(null);
131
- const composerRef = useRef<View>(null);
132
- const { contentInsetEndAdjustment, onComposerLayout } =
133
- useKeyboardChatComposerInset(listRef, composerRef);
134
130
  const { freeze, scrollMessageToEnd } = useKeyboardScrollToEnd({
135
131
  listRef,
136
132
  });
@@ -166,6 +162,7 @@ const ChatDetail = memo(
166
162
  <KContainer.Page flex edges={['bottom']}>
167
163
  <ChatDetailHeader
168
164
  conversationId={conversationId}
165
+ targetUserId={targetUserId}
169
166
  showAddMember={resolvedShowAddMember}
170
167
  onBack={onBack ?? handleBackDefault}
171
168
  onPressSearch={onPressSearch}
@@ -195,7 +192,6 @@ const ChatDetail = memo(
195
192
  onPressUrl={handlePressUrl}
196
193
  onLongPress={handleMessageLongPress}
197
194
  listRef={listRef}
198
- contentInsetEndAdjustment={contentInsetEndAdjustment}
199
195
  freeze={freeze}
200
196
  scrollMessageToEnd={scrollMessageToEnd}
201
197
  keyboardOffset={insets.bottom}
@@ -205,8 +201,6 @@ const ChatDetail = memo(
205
201
  isEmptyMessage={messages?.length === 0}
206
202
  pannelActions={pannelActions}
207
203
  isDisableCompose={botStatus === DBotStatusValue.INACTIVE}
208
- composerRef={composerRef}
209
- onComposerLayout={onComposerLayout}
210
204
  />
211
205
 
212
206
  <MediaViewerModal ref={mediaViewerRef} />
@@ -11,11 +11,13 @@ import { NamePrefixIcon } from '../../components/ThreadCard/NamePrefixIcon';
11
11
  import type { ChatDetailHeaderProps } from './types';
12
12
  import { useConversation } from '../../store';
13
13
  import { getConversationSubtitle } from './conversationHeader.utils';
14
+ import { useGetUsersInfo } from '../../hooks/users/useGetUsersInfo';
14
15
 
15
16
  const ChatDetailHeader = memo(
16
17
  ({
17
18
  showAddMember = false,
18
19
  conversationId,
20
+ targetUserId,
19
21
  onBack,
20
22
  onPressSearch,
21
23
  onPressAddMember,
@@ -23,6 +25,20 @@ const ChatDetailHeader = memo(
23
25
  onPressAvatar,
24
26
  }: ChatDetailHeaderProps) => {
25
27
  const conversation = useConversation(conversationId);
28
+ const { data: usersInfo } = useGetUsersInfo(
29
+ targetUserId ? [targetUserId] : []
30
+ );
31
+
32
+ const { faceURL, showName } = useMemo(() => {
33
+ const userInfo = usersInfo?.[0];
34
+ const resolvedFaceURL = conversation?.faceURL || userInfo?.faceURL;
35
+ const resolvedShowName = conversation?.showName || userInfo?.nickname;
36
+
37
+ return {
38
+ faceURL: resolvedFaceURL,
39
+ showName: resolvedShowName,
40
+ };
41
+ }, [conversation, usersInfo]);
26
42
  const rightButtons = useMemo(() => {
27
43
  const buttons = [
28
44
  {
@@ -76,8 +92,8 @@ const ChatDetailHeader = memo(
76
92
  activeOpacity={0.7}
77
93
  >
78
94
  <AvatarSection
79
- avatar={conversation?.faceURL ?? null}
80
- fullName={conversation?.showName || ''}
95
+ avatar={faceURL || null}
96
+ fullName={showName || ''}
81
97
  peerType={conversation?.peerType}
82
98
  />
83
99
 
@@ -90,7 +106,7 @@ const ChatDetailHeader = memo(
90
106
  numberOfLines={1}
91
107
  flex
92
108
  >
93
- {conversation?.showName || ''}
109
+ {showName || ''}
94
110
  </KLabel.Text>
95
111
  </KContainer.View>
96
112
  {!!conversation && (
@@ -106,7 +122,7 @@ const ChatDetailHeader = memo(
106
122
  </KContainer.Touchable>
107
123
  </KContainer.View>
108
124
  ),
109
- [onBack, onPressAvatar, conversation]
125
+ [onBack, onPressAvatar, conversation, faceURL, showName]
110
126
  );
111
127
 
112
128
  return (
@@ -38,7 +38,6 @@ import { ChatMessageAPI } from '../../services';
38
38
 
39
39
  interface ChatListLegendInternalProps extends ChatListProps {
40
40
  listRef: RefObject<LegendListRef | null>;
41
- contentInsetEndAdjustment: SharedValue<number>;
42
41
  freeze: SharedValue<boolean>;
43
42
  scrollMessageToEnd: (opts: {
44
43
  animated: boolean;
@@ -62,7 +61,6 @@ export const ChatListLegend = memo(
62
61
  onPressUrl,
63
62
  onLongPress,
64
63
  listRef,
65
- contentInsetEndAdjustment,
66
64
  freeze,
67
65
  scrollMessageToEnd,
68
66
  keyboardOffset,
@@ -411,7 +409,6 @@ export const ChatListLegend = memo(
411
409
  alignItemsAtEnd
412
410
  maintainVisibleContentPosition={maintainVisiblePositionConfig}
413
411
  maintainScrollAtEnd={maintainScrollConfig}
414
- contentInsetEndAdjustment={contentInsetEndAdjustment}
415
412
  freeze={freeze}
416
413
  keyboardOffset={keyboardOffset}
417
414
  scrollEventThrottle={16}
@@ -45,6 +45,7 @@ export interface ChatDetailHeaderProps {
45
45
  onPressMenu?: () => void;
46
46
  onPressAvatar?: () => void;
47
47
  conversationId: string;
48
+ targetUserId?: string;
48
49
  }
49
50
 
50
51
  export interface ChatQuickActionsRenderParams {
@@ -8,13 +8,18 @@ interface InboxProps {
8
8
  onPressThread?: (item: string) => void;
9
9
  onPressSearch?: () => void;
10
10
  onPressEdit?: () => void;
11
- onPressGroup?: () => void;
11
+ onPressContact?: () => void;
12
12
  }
13
13
 
14
14
  type TabRoute = { key: string; title: string };
15
15
 
16
16
  const Inbox = memo(
17
- ({ onPressThread, onPressSearch, onPressEdit, onPressGroup }: InboxProps) => {
17
+ ({
18
+ onPressThread,
19
+ onPressSearch,
20
+ onPressEdit,
21
+ onPressContact,
22
+ }: InboxProps) => {
18
23
  const [index, setIndex] = useState(0);
19
24
  const [routes] = useState<TabRoute[]>([
20
25
  { key: 'messages', title: 'Tin nhắn' },
@@ -91,7 +96,7 @@ const Inbox = memo(
91
96
  />
92
97
  </KContainer.Touchable>
93
98
  <KContainer.Touchable
94
- onPress={onPressGroup}
99
+ onPress={onPressContact}
95
100
  padding="0.5rem"
96
101
  activeOpacity={0.7}
97
102
  >
@@ -105,7 +110,7 @@ const Inbox = memo(
105
110
  </KContainer.View>
106
111
  </KContainer.View>
107
112
  ),
108
- [onPressSearch, onPressEdit, onPressGroup]
113
+ [onPressSearch, onPressEdit, onPressContact]
109
114
  );
110
115
 
111
116
  return (
@@ -16,18 +16,18 @@ export const ENDPOINTS = {
16
16
  get urlMetadata() {
17
17
  return getApiEndpoint('urlMetadata');
18
18
  },
19
- conversationFlow: (id: string) =>
20
- `${getApiEndpoint('conversationFlow')}/${id}`,
19
+ conversationFlow: (id: string) => `${getApiEndpoint('conversation')}/${id}`,
21
20
  resetConversationFlow: (id: string) =>
22
- `${getApiEndpoint('conversationFlow')}/${id}/bot-flows/reset`,
21
+ `${getApiEndpoint('conversation')}/${id}/bot-flows/reset`,
23
22
  runConversationFlow: (id: string) =>
24
- `${getApiEndpoint('conversationFlow')}/${id}/bot-flows/run`,
23
+ `${getApiEndpoint('conversation')}/${id}/bot-flows/run`,
25
24
  getConversationByBotId: (botId: string) =>
26
25
  `${getApiEndpoint('bot')}/${botId}/conversation`,
27
26
  conversationFlowMainMenu: (id: string) =>
28
- `${getApiEndpoint('conversationFlow')}/${id}/bot-flows/main-menu`,
27
+ `${getApiEndpoint('conversation')}/${id}/bot-flows/main-menu`,
29
28
  getConversationStatusByBotId: (botId: string) =>
30
29
  `${getApiEndpoint('bot')}/${botId}`,
30
+ createConversation: () => getApiEndpoint('conversation'),
31
31
  },
32
32
  uploaderService: {
33
33
  get uploadImage() {
@@ -1,12 +1,27 @@
1
1
  import { create } from 'zustand';
2
2
  import { sortConversation } from '../utils/conversation';
3
3
  import type { ConversationItem } from '@droppii/openim-rn-client-sdk';
4
+ import type {
5
+ CreateConversationParams,
6
+ CreateConversationResponse,
7
+ } from '../types/chat';
8
+ import { apiInstance } from '../services/apis';
9
+ import { ENDPOINTS } from '../services/endpoints';
10
+ import type { BaseResponse } from '../types/auth';
4
11
 
5
12
  type ConversationID = string;
6
13
 
7
14
  export interface ConversationStore {
8
15
  currentConversationId?: ConversationID;
9
- setCurrentConversation(id?: ConversationID): void;
16
+ currentUserId?: string;
17
+ currentGroupId?: string;
18
+ isCreatingConversation?: boolean;
19
+ createConversation: (params: CreateConversationParams) => Promise<void>;
20
+ setCurrentConversation(
21
+ id?: ConversationID,
22
+ userId?: string,
23
+ groupId?: string
24
+ ): void;
10
25
  getCurrentConversation(): ConversationItem | undefined;
11
26
  list: ConversationID[];
12
27
  map: Record<ConversationID, ConversationItem>;
@@ -26,8 +41,12 @@ export const useConversationStore = create<ConversationStore>()((set, get) => ({
26
41
  list: [],
27
42
  map: {},
28
43
  newConversationSignal: 0,
29
- setCurrentConversation(id) {
30
- set({ currentConversationId: id });
44
+ setCurrentConversation(id, userId, groupId) {
45
+ set({
46
+ currentConversationId: id,
47
+ currentUserId: userId,
48
+ currentGroupId: groupId,
49
+ });
31
50
  },
32
51
  getCurrentConversation() {
33
52
  const id = get().currentConversationId;
@@ -68,12 +87,27 @@ export const useConversationStore = create<ConversationStore>()((set, get) => ({
68
87
  list: get().list.filter((item) => item !== id),
69
88
  });
70
89
  },
90
+ createConversation: async (params) => {
91
+ set({ isCreatingConversation: true });
92
+ const res = await apiInstance?.post<
93
+ BaseResponse<CreateConversationResponse>
94
+ >(ENDPOINTS.chatService.createConversation(), params);
95
+ if (res?.data?.data?.conversationId) {
96
+ set({
97
+ currentConversationId: res?.data?.data?.conversationId,
98
+ isCreatingConversation: false,
99
+ });
100
+ } else {
101
+ set({ isCreatingConversation: false });
102
+ }
103
+ },
71
104
  reset() {
72
105
  set({
73
106
  currentConversationId: undefined,
74
107
  list: [],
75
108
  map: {},
76
109
  newConversationSignal: 0,
110
+ isCreatingConversation: false,
77
111
  });
78
112
  },
79
113
  }));
package/src/types/chat.ts CHANGED
@@ -218,3 +218,24 @@ export type CustomElemOrderData = {
218
218
  export type CustomMessagePayload =
219
219
  | { type: typeof CustomMessageType.Order; data: CustomElemOrderData }
220
220
  | { type: typeof CustomMessageType.Product; data: Record<string, unknown> };
221
+
222
+ export interface CreateConversationParams {
223
+ peerUserId: string;
224
+ chatCategory: DChatCategory;
225
+ applicationType: DChatApplicationType;
226
+ chatType: 'SINGLE' | 'GROUP';
227
+ }
228
+
229
+ export interface CreateConversationResponse {
230
+ conversationId: string;
231
+ groupId?: string;
232
+ groupName?: string;
233
+ groupAvatar?: string;
234
+ chatCategory: DChatCategory;
235
+ applicationType: DChatApplicationType;
236
+ chatType: 'SINGLE' | 'GROUP';
237
+ members?: {
238
+ userId: string;
239
+ memberRole?: string;
240
+ }[];
241
+ }
@@ -100,7 +100,8 @@ export const hasNewHistoryMessages = (
100
100
 
101
101
  export const belongsToConversation = (
102
102
  message: MessageItem,
103
- conversationId: string
103
+ conversationId?: string,
104
+ targetUserId?: string
104
105
  ): boolean => {
105
106
  switch (message.sessionType) {
106
107
  case SessionType.Single: {
@@ -114,7 +115,11 @@ export const belongsToConversation = (
114
115
  message.recvID,
115
116
  message.sendID
116
117
  );
117
- return conversationId === forwardId || conversationId === reverseId;
118
+ return conversationId
119
+ ? conversationId === forwardId || conversationId === reverseId
120
+ : targetUserId
121
+ ? message.sendID === targetUserId || message.recvID === targetUserId
122
+ : false;
118
123
  }
119
124
 
120
125
  case SessionType.Group: {