@droppii-org/chat-mobile 0.2.92 → 0.2.94

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/hooks/conversation/useGetConversationDetail.js +7 -7
  2. package/lib/module/hooks/conversation/useGetConversationDetail.js.map +1 -1
  3. package/lib/module/hooks/flows/useCurrentConversationFlow.js +2 -2
  4. package/lib/module/hooks/flows/useCurrentConversationFlow.js.map +1 -1
  5. package/lib/module/hooks/flows/useFlow.js +4 -4
  6. package/lib/module/hooks/flows/useFlow.js.map +1 -1
  7. package/lib/module/hooks/flows/useGetConversationFlowMainMenu.js +2 -2
  8. package/lib/module/hooks/flows/useGetConversationFlowMainMenu.js.map +1 -1
  9. package/lib/module/hooks/stickers/useFetchStickerByCategory.js +2 -2
  10. package/lib/module/hooks/stickers/useFetchStickerByCategory.js.map +1 -1
  11. package/lib/module/hooks/stickers/useStickerCategories.js +2 -2
  12. package/lib/module/hooks/stickers/useStickerCategories.js.map +1 -1
  13. package/lib/module/hooks/stickers/useStickerHistory.js +2 -2
  14. package/lib/module/hooks/stickers/useStickerHistory.js.map +1 -1
  15. package/lib/module/hooks/useLinkPreview/useFetchUrlMetadata.js +4 -3
  16. package/lib/module/hooks/useLinkPreview/useFetchUrlMetadata.js.map +1 -1
  17. package/lib/module/index.js +1 -1
  18. package/lib/module/index.js.map +1 -1
  19. package/lib/module/screens/chat-detail/ChatDetail.js +15 -11
  20. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  21. package/lib/module/screens/chat-detail/ChatListLegend.js +3 -2
  22. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  23. package/lib/module/screens/chat-detail/PinnedMessagesSheet.js +1 -0
  24. package/lib/module/screens/chat-detail/PinnedMessagesSheet.js.map +1 -1
  25. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +9 -4
  26. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  27. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +16 -9
  28. package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -1
  29. package/lib/module/services/apis.js +14 -1
  30. package/lib/module/services/apis.js.map +1 -1
  31. package/lib/module/services/resourceCenter.js +5 -4
  32. package/lib/module/services/resourceCenter.js.map +1 -1
  33. package/lib/module/store/message.js +9 -5
  34. package/lib/module/store/message.js.map +1 -1
  35. package/lib/module/types/events.js +1 -0
  36. package/lib/module/types/events.js.map +1 -1
  37. package/lib/typescript/src/hooks/useLinkPreview/useFetchUrlMetadata.d.ts.map +1 -1
  38. package/lib/typescript/src/index.d.ts +1 -1
  39. package/lib/typescript/src/index.d.ts.map +1 -1
  40. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  41. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
  42. package/lib/typescript/src/screens/chat-detail/PinnedMessagesSheet.d.ts.map +1 -1
  43. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +11 -1
  44. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  45. package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -1
  46. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts +3 -1
  47. package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts.map +1 -1
  48. package/lib/typescript/src/screens/chat-detail/types.d.ts +2 -2
  49. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  50. package/lib/typescript/src/services/apis.d.ts +21 -1
  51. package/lib/typescript/src/services/apis.d.ts.map +1 -1
  52. package/lib/typescript/src/services/resourceCenter.d.ts.map +1 -1
  53. package/lib/typescript/src/store/message.d.ts.map +1 -1
  54. package/lib/typescript/src/types/events.d.ts +2 -1
  55. package/lib/typescript/src/types/events.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/hooks/conversation/useGetConversationDetail.ts +7 -7
  58. package/src/hooks/flows/useCurrentConversationFlow.ts +2 -2
  59. package/src/hooks/flows/useFlow.ts +4 -4
  60. package/src/hooks/flows/useGetConversationFlowMainMenu.ts +2 -2
  61. package/src/hooks/stickers/useFetchStickerByCategory.ts +2 -2
  62. package/src/hooks/stickers/useStickerCategories.ts +2 -2
  63. package/src/hooks/stickers/useStickerHistory.ts +2 -2
  64. package/src/hooks/useLinkPreview/useFetchUrlMetadata.ts +4 -3
  65. package/src/index.tsx +1 -1
  66. package/src/screens/chat-detail/ChatDetail.tsx +23 -14
  67. package/src/screens/chat-detail/ChatListLegend.tsx +3 -2
  68. package/src/screens/chat-detail/PinnedMessagesSheet.tsx +1 -0
  69. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +20 -4
  70. package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +26 -7
  71. package/src/screens/chat-detail/messageToolbox/types.ts +8 -1
  72. package/src/screens/chat-detail/types.ts +2 -2
  73. package/src/services/apis.ts +31 -1
  74. package/src/services/resourceCenter.ts +5 -4
  75. package/src/store/message.ts +14 -5
  76. package/src/types/events.ts +1 -0
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { MediaItem } from '../../hooks/useMediaViewer';
3
- import type { MeasuredRect } from './messageToolbox/types';
3
+ import type { MessageToolboxShowFn } from './messageToolbox/types';
4
4
  import type { GroupJoinSource, MessageItem } from '@droppii/openim-rn-client-sdk';
5
5
  export type DChatActionIconProvider = 'MaterialCommunityIcons' | 'DroppiiNew';
6
6
  export declare enum DChatPannelActionItemType {
@@ -72,7 +72,7 @@ export interface ChatListProps {
72
72
  hasMoreNew?: boolean;
73
73
  onMediaPress?: (items: MediaItem[], index?: number) => void;
74
74
  onPressUrl?: (url: string) => void;
75
- onLongPress?: (message: MessageItem, rect: MeasuredRect) => void;
75
+ onLongPress?: MessageToolboxShowFn;
76
76
  }
77
77
  export interface ChatDetailProps extends Omit<ChatDetailHeaderProps, 'showAddMember' | 'conversationId'> {
78
78
  targetConversationId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/screens/chat-detail/types.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,28 @@
1
1
  import { type AxiosInstance } from 'axios';
2
2
  export declare let apiInstance: AxiosInstance | null;
3
+ interface InitApiInstanceOptions {
4
+ /**
5
+ * Set true when the injected instance's response interceptor already
6
+ * strips the outer envelope (statusCode/message/pageable/data) down to
7
+ * just the payload (e.g. Mall's shared axios client). Defaults to false —
8
+ * the instance returns the raw `{ statusCode, message, pageable, data }`
9
+ * envelope untouched (e.g. Biz's axios client).
10
+ */
11
+ unwrapped?: boolean;
12
+ }
3
13
  export declare namespace ChatAPI {
4
- function initApiInstance(api: AxiosInstance): void;
14
+ function initApiInstance(api: AxiosInstance, options?: InitApiInstanceOptions): void;
5
15
  const getLoginStatus: (operationID?: string) => Promise<boolean>;
6
16
  const logout: (operationID?: string) => Promise<unknown>;
7
17
  }
18
+ /**
19
+ * Reads the payload out of an apiInstance response, accounting for whichever
20
+ * envelope shape the injected instance produces (see `initApiInstance`'s
21
+ * `unwrapped` option). Consumers should use this instead of reading
22
+ * `res?.data?.data` / `res?.data` directly.
23
+ */
24
+ export declare function unwrapEnvelope<T>(res?: {
25
+ data?: unknown;
26
+ }): T | null;
27
+ export {};
8
28
  //# sourceMappingURL=apis.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apis.d.ts","sourceRoot":"","sources":["../../../../src/services/apis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3C,eAAO,IAAI,WAAW,EAAE,aAAa,GAAG,IAAW,CAAC;AAEpD,yBAAiB,OAAO,CAAC;IACvB,SAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAExD;IAEM,MAAM,cAAc,GAAU,cAAc,MAAM,qBAExD,CAAC;IAEK,MAAM,MAAM,GAAU,cAAc,MAAM,qBAIhD,CAAC;CACH"}
1
+ {"version":3,"file":"apis.d.ts","sourceRoot":"","sources":["../../../../src/services/apis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3C,eAAO,IAAI,WAAW,EAAE,aAAa,GAAG,IAAW,CAAC;AAEpD,UAAU,sBAAsB;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,yBAAiB,OAAO,CAAC;IACvB,SAAgB,eAAe,CAC7B,GAAG,EAAE,aAAa,EAClB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,IAAI,CAGN;IAEM,MAAM,cAAc,GAAU,cAAc,MAAM,qBAExD,CAAC;IAEK,MAAM,MAAM,GAAU,cAAc,MAAM,qBAIhD,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,GAAG,IAAI,CAKpE"}
@@ -1 +1 @@
1
- {"version":3,"file":"resourceCenter.d.ts","sourceRoot":"","sources":["../../../../src/services/resourceCenter.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AA2KvB,yBAAiB,qBAAqB,CAAC;IAC9B,MAAM,oBAAoB,GAC/B,KAAK,sBAAsB,KAC1B,OAAO,CAAC;QAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAWtE,CAAC;CACH"}
1
+ {"version":3,"file":"resourceCenter.d.ts","sourceRoot":"","sources":["../../../../src/services/resourceCenter.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AA2KvB,yBAAiB,qBAAqB,CAAC;IAC9B,MAAM,oBAAoB,GAC/B,KAAK,sBAAsB,KAC1B,OAAO,CAAC;QAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAYtE,CAAC;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/store/message.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,YAAY,EACb,MAAM,eAAe,CAAC;AAYvB,eAAO,MAAM,eAAe,2EAgMzB,CAAC;AAEJ,eAAO,MAAM,kBAAkB,GAAI,aAAa,MAAM,SAiBrD,CAAC"}
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/store/message.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,YAAY,EACb,MAAM,eAAe,CAAC;AAavB,eAAO,MAAM,eAAe,2EAwMzB,CAAC;AAEJ,eAAO,MAAM,kBAAkB,GAAI,aAAa,MAAM,SAiBrD,CAAC"}
@@ -4,7 +4,8 @@ export declare enum ChatEvent {
4
4
  ScrollToBottom = "chat:scroll_to_bottom",
5
5
  MessageRevoked = "chat:message_revoked",
6
6
  GroupPermissionUpdated = "chat:group_permission_updated",
7
- GroupRemoved = "chat:group_removed"
7
+ GroupRemoved = "chat:group_removed",
8
+ TargetMessageUnavailable = "chat:target_message_unavailable"
8
9
  }
9
10
  export interface ScrollToMessagePayload {
10
11
  clientMessageId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/types/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,oBAAY,SAAS;IACnB,eAAe,2BAA2B;IAC1C,cAAc,0BAA0B;IACxC,cAAc,yBAAyB;IACvC,sBAAsB,kCAAkC;IACxD,YAAY,uBAAuB;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;CACzC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/types/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,oBAAY,SAAS;IACnB,eAAe,2BAA2B;IAC1C,cAAc,0BAA0B;IACxC,cAAc,yBAAyB;IACvC,sBAAsB,kCAAkC;IACxD,YAAY,uBAAuB;IACnC,wBAAwB,oCAAoC;CAC7D;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;CACzC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-mobile",
3
- "version": "0.2.92",
3
+ "version": "0.2.94",
4
4
  "description": "Droppii chat mobile",
5
5
  "keywords": [
6
6
  "react-native",
@@ -1,7 +1,7 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
2
  import OpenIMSDK, { SessionType } from '@droppii/openim-rn-client-sdk';
3
3
  import { useConversationStore } from '../../store/conversation';
4
- import { apiInstance } from '../../services/apis';
4
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
5
5
  import type { BaseResponse } from '../../types/auth';
6
6
  import type { DBotStatus, DConversationTarget } from '../../types/chat';
7
7
  import { conversationQueryKeys } from '../query-keys';
@@ -28,7 +28,7 @@ const useBotConversationData = (botId?: string) =>
28
28
  const res = await apiInstance?.get<
29
29
  BaseResponse<{ groupId: string; conversationId: string }>
30
30
  >(ENDPOINTS.chatService.getConversationByBotId(botId || ''));
31
- return res?.data?.data || undefined;
31
+ return unwrapEnvelope<{ groupId: string; conversationId: string }>(res);
32
32
  },
33
33
  enabled: !!botId,
34
34
  });
@@ -40,7 +40,7 @@ export const useGetStatusConversationBot = (botId?: string) => {
40
40
  const res = await apiInstance?.get<BaseResponse<DBotStatus>>(
41
41
  ENDPOINTS.chatService.getConversationStatusByBotId(botId || '')
42
42
  );
43
- return res?.data?.data || undefined;
43
+ return unwrapEnvelope<DBotStatus>(res);
44
44
  },
45
45
  enabled: !!botId,
46
46
  staleTime: 0,
@@ -56,9 +56,9 @@ export const useGetConversationTarget = (conversationId?: string) =>
56
56
  const res = await apiInstance?.get<BaseResponse<DConversationTarget>>(
57
57
  ENDPOINTS.chatService.getConversationTarget(conversationId || '')
58
58
  );
59
- return res?.data?.data || undefined;
59
+ return unwrapEnvelope<DConversationTarget>(res);
60
60
  } catch {
61
- return undefined; // fail-open: unresolved status => compose stays enabled
61
+ return null; // fail-open: unresolved status => compose stays enabled
62
62
  }
63
63
  },
64
64
  enabled: !!conversationId,
@@ -85,7 +85,7 @@ export const useGetOneConversation = ({
85
85
  if (res?.conversationID) {
86
86
  useConversationStore.getState().updateConversations([res]);
87
87
  }
88
- return res || undefined;
88
+ return res ?? null;
89
89
  },
90
90
  enabled: !!targetUserId || !!targetGroupId,
91
91
  });
@@ -132,7 +132,7 @@ export const useSyncConversationById = (
132
132
  if (conversation) {
133
133
  useConversationStore.getState().updateConversations([conversation]);
134
134
  }
135
- return conversation;
135
+ return conversation ?? null;
136
136
  },
137
137
  enabled: !!conversationId && !hasConversation,
138
138
  });
@@ -1,11 +1,11 @@
1
1
  import { ENDPOINTS } from '../../services/endpoints';
2
2
  import type { BaseResponse } from '../../types/auth';
3
- import { apiInstance } from '../../services/apis';
3
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
4
4
  import type { IConversationFlow } from '../../types/flows';
5
5
 
6
6
  export const fechtCurrentConversationFlow = async (conversationId: string) => {
7
7
  const res = await apiInstance?.get<BaseResponse<IConversationFlow>>(
8
8
  ENDPOINTS.chatService.conversationFlow(conversationId)
9
9
  );
10
- return res?.data?.data || undefined;
10
+ return unwrapEnvelope<IConversationFlow>(res) ?? undefined;
11
11
  };
@@ -1,7 +1,7 @@
1
1
  import { useMutation } from '@tanstack/react-query';
2
2
  import { conversationQueryKeys } from '../query-keys';
3
3
  import { useConversationStore } from '../../store';
4
- import { apiInstance } from '../../services/apis';
4
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
5
5
  import type { BaseResponse } from '../../types/auth';
6
6
  import { ENDPOINTS } from '../../services/endpoints';
7
7
  import type {
@@ -34,7 +34,7 @@ export const useResetFlow = () => {
34
34
  ENDPOINTS.chatService.resetConversationFlow(conversationId),
35
35
  {}
36
36
  );
37
- return res?.data?.data || undefined;
37
+ return unwrapEnvelope<IConversationFlow>(res) ?? undefined;
38
38
  },
39
39
  onSuccess: (data) => {
40
40
  if (data?.flowCurrentStep?.id) {
@@ -57,7 +57,7 @@ export const useCloseSupportSession = () => {
57
57
  const res = await apiInstance?.post<BaseResponse<unknown>>(
58
58
  ENDPOINTS.chatService.closeConversationSession(conversationId)
59
59
  );
60
- return res?.data?.data;
60
+ return unwrapEnvelope<unknown>(res);
61
61
  },
62
62
  });
63
63
  };
@@ -77,7 +77,7 @@ export const useRunFlow = () => {
77
77
  const res = await apiInstance?.post<
78
78
  BaseResponse<IRunConversationFlowResponse>
79
79
  >(ENDPOINTS.chatService.runConversationFlow(conversationId), payload);
80
- return res?.data?.data || undefined;
80
+ return unwrapEnvelope<IRunConversationFlowResponse>(res) ?? undefined;
81
81
  },
82
82
  onSuccess: (data) => {
83
83
  setConverationFlowStep(
@@ -1,6 +1,6 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
2
  import { conversationQueryKeys } from '../query-keys';
3
- import { apiInstance } from '../../services/apis';
3
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
4
4
  import type { BaseResponse } from '../../types/auth';
5
5
  import type { InputButtonItem } from '../../types/flows';
6
6
  import { ENDPOINTS } from '../../services/endpoints';
@@ -12,7 +12,7 @@ export const useGetConversationFlowMainMenu = (conversationId?: string) => {
12
12
  const res = await apiInstance?.get<BaseResponse<InputButtonItem[]>>(
13
13
  ENDPOINTS.chatService.conversationFlowMainMenu(conversationId || '')
14
14
  );
15
- return res?.data?.data || ([] as InputButtonItem[]);
15
+ return unwrapEnvelope<InputButtonItem[]>(res) ?? [];
16
16
  },
17
17
  enabled: !!conversationId,
18
18
  });
@@ -1,5 +1,5 @@
1
1
  import { useMutation } from '@tanstack/react-query';
2
- import { apiInstance } from '../../services/apis';
2
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
3
3
  import { ENDPOINTS } from '../../services/endpoints';
4
4
  import type { BaseResponse } from '../../types/auth';
5
5
  import type { StickerItem } from '../../types/sticker';
@@ -10,6 +10,6 @@ export const useFetchStickerByCategory = () =>
10
10
  const res = await apiInstance?.get<BaseResponse<StickerItem[]>>(
11
11
  ENDPOINTS.chatService.stickersByCategoryId(categoryId)
12
12
  );
13
- return res?.data?.data || [];
13
+ return unwrapEnvelope<StickerItem[]>(res) ?? [];
14
14
  },
15
15
  });
@@ -1,5 +1,5 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
- import { apiInstance } from '../../services/apis';
2
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
3
3
  import { stickerQueryKeys } from '../query-keys';
4
4
  import { ENDPOINTS } from '../../services/endpoints';
5
5
  import type { BaseResponse } from '../../types/auth';
@@ -12,6 +12,6 @@ export const useStickerCategories = () =>
12
12
  const res = await apiInstance?.get<BaseResponse<StickerCategory[]>>(
13
13
  ENDPOINTS.chatService.stickerCategories()
14
14
  );
15
- return res?.data?.data || [];
15
+ return unwrapEnvelope<StickerCategory[]>(res) ?? [];
16
16
  },
17
17
  });
@@ -1,5 +1,5 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
- import { apiInstance } from '../../services/apis';
2
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
3
3
  import { stickerQueryKeys } from '../query-keys';
4
4
  import { ENDPOINTS } from '../../services/endpoints';
5
5
  import type { BaseResponse } from '../../types/auth';
@@ -12,7 +12,7 @@ export const useStickerHistory = () =>
12
12
  const res = await apiInstance?.get<BaseResponse<StickerItem[]>>(
13
13
  ENDPOINTS.chatService.stickerHistory()
14
14
  );
15
- return res?.data?.data || [];
15
+ return unwrapEnvelope<StickerItem[]>(res) ?? [];
16
16
  },
17
17
  staleTime: 0,
18
18
  gcTime: 0,
@@ -1,6 +1,6 @@
1
1
  import { useQuery } from '@tanstack/react-query';
2
2
  import { commonQueryKeys } from '../query-keys';
3
- import { apiInstance } from '../../services/apis';
3
+ import { apiInstance, unwrapEnvelope } from '../../services/apis';
4
4
  import type { BaseResponse } from '../../types/auth';
5
5
  import type { IUrlMetadata } from '../../types/common';
6
6
  import { ENDPOINTS } from '../../services/endpoints';
@@ -12,9 +12,10 @@ export const useFetchUrlMetadata = (url?: string) =>
12
12
  queryFn: async () => {
13
13
  const path = `${ENDPOINTS.chatService.urlMetadata}?url=${normalizeUrl(url || '')}`;
14
14
  const res = await apiInstance?.get<BaseResponse<IUrlMetadata>>(path);
15
- return res?.data?.data?.title
15
+ const metadata = unwrapEnvelope<IUrlMetadata>(res);
16
+ return metadata?.title
16
17
  ? {
17
- ...res?.data?.data,
18
+ ...metadata,
18
19
  url,
19
20
  }
20
21
  : null;
package/src/index.tsx CHANGED
@@ -27,7 +27,7 @@ export { Avatar } from './components/Avatar';
27
27
  export { ThreadCard } from './components/ThreadCard';
28
28
  export { AttachmentPreview } from './components/AttachmentPreview';
29
29
  export { MediaViewerModal } from './components/MediaViewerModal';
30
- export { Inbox } from './screens/inbox';
30
+ export { Inbox, MessagesTab } from './screens/inbox';
31
31
  export { default as MediaViewerScreen } from './screens/MediaView';
32
32
  export { default as ResourceCenterScreen } from './screens/ResourceCenter';
33
33
  export type { ResourceCenterScreenProps } from './screens/ResourceCenter/types';
@@ -25,7 +25,10 @@ import { shouldShowAddMember } from './conversationHeader.utils';
25
25
  import type { ChatDetailProps } from './types';
26
26
  import { normalizeUrl } from '../../utils/url';
27
27
  import { MessageToolboxOverlay } from './messageToolbox/MessageToolboxOverlay';
28
- import type { MeasuredRect, MessageToolboxRef } from './messageToolbox/types';
28
+ import type {
29
+ MessageToolboxRef,
30
+ MessageToolboxShowFn,
31
+ } from './messageToolbox/types';
29
32
  import {
30
33
  useGetConversationDetail,
31
34
  useGetConversationTarget,
@@ -39,7 +42,6 @@ import { ChatEvent } from '../../types/events';
39
42
  import { useSetIsShowFLashMessage } from '../../context/global';
40
43
  import { useJoinGroup } from '../../hooks/groups/useJoinGroup';
41
44
  import { useGroupAccessGuard } from '../../hooks/groups/useGroupAccessGuard';
42
- import { isMessageRevoked } from '../../utils/messageUtils';
43
45
  import { UIUtils } from '../../utils/UIUtils';
44
46
  import { trans } from '../../translation';
45
47
 
@@ -136,8 +138,22 @@ const ChatDetail = memo(
136
138
  onBlocked: handleAccessBlocked,
137
139
  });
138
140
 
139
- // Scroll to the target message if it exists in the current message list
140
- // And show a toast if the message is revoked.
141
+ // Go back if the target message is not available
142
+ useEffect(() => {
143
+ const subscription = DeviceEventEmitter.addListener(
144
+ ChatEvent.TargetMessageUnavailable,
145
+ () => {
146
+ UIUtils.toast.open({
147
+ title: trans('chat:target_message_unavailable'),
148
+ theme: 'error',
149
+ });
150
+ (onBack ?? handleBackDefault)();
151
+ }
152
+ );
153
+ return () => subscription.remove();
154
+ }, [onBack, handleBackDefault]);
155
+
156
+ // Handle re-open the same deeplink
141
157
  const params = useRoute().params;
142
158
  useEffect(() => {
143
159
  if (!targetMessageId || initLoading) return;
@@ -149,13 +165,6 @@ const ChatDetail = memo(
149
165
  DeviceEventEmitter.emit(ChatEvent.ScrollToMessage, {
150
166
  clientMessageId: targetMessageId,
151
167
  });
152
-
153
- if (isMessageRevoked(targetMessage)) {
154
- UIUtils.toast.open({
155
- title: trans('chat:target_message_unavailable'),
156
- theme: 'error',
157
- });
158
- }
159
168
  // eslint-disable-next-line react-hooks/exhaustive-deps
160
169
  }, [params]);
161
170
 
@@ -176,9 +185,9 @@ const ChatDetail = memo(
176
185
  [onPressUrl]
177
186
  );
178
187
 
179
- const handleMessageLongPress = useCallback(
180
- (message: MessageItem, rect: MeasuredRect) => {
181
- messageToolboxRef.current?.show(message, rect);
188
+ const handleMessageLongPress = useCallback<MessageToolboxShowFn>(
189
+ (message, rect, groupPosition) => {
190
+ messageToolboxRef.current?.show(message, rect, groupPosition);
182
191
  },
183
192
  []
184
193
  );
@@ -199,10 +199,11 @@ export const ChatListLegend = memo(
199
199
  const node = rowRefsMap.current.get(messageId);
200
200
  node?.measureInWindow((x, y, width, height) => {
201
201
  if (x == null || y == null || width == null || height == null) return;
202
- onLongPress?.(message, { x, y, width, height });
202
+ const groupPosition = messageDataMap.get(messageId)?.groupPosition;
203
+ onLongPress?.(message, { x, y, width, height }, groupPosition);
203
204
  });
204
205
  },
205
- [onLongPress]
206
+ [onLongPress, messageDataMap]
206
207
  );
207
208
 
208
209
  const onRunFlow = useCallback(
@@ -125,6 +125,7 @@ const PinnedMessagesSheetContent = memo(
125
125
  isOutgoing={isOutgoing}
126
126
  createdAtTime={createdAtTime}
127
127
  onPress={handlePressMessage}
128
+ alwaysHandlePress
128
129
  customMessageItemFactory={customMessageItemFactory}
129
130
  />
130
131
 
@@ -46,6 +46,16 @@ interface LegendChatMessageProps {
46
46
  onPressUrl?: (url: string) => void;
47
47
  onRetry?: (message: MessageItem) => void;
48
48
  onPress?: (messageId: string) => void;
49
+ /**
50
+ * Fire `onPress` for every content type, including the ones excluded from
51
+ * tap-to-reveal-time (media/file). For Picture/Video/Merge — which always
52
+ * render their own full-bubble touchable — this also becomes the fallback
53
+ * `onMediaPress` when the caller doesn't supply one, since that touchable
54
+ * would otherwise swallow the tap before it reaches this component's own
55
+ * gesture wrapper. Used by callers that repurpose `onPress` for navigation
56
+ * (e.g. PinnedMessagesSheet) rather than the reveal-time toggle.
57
+ */
58
+ alwaysHandlePress?: boolean;
49
59
  onLongPress?: (messageId: string, message: MessageItem) => void;
50
60
  customMessageItemFactory?: (m: MessageItem) => ReactNode;
51
61
  isHighlighted?: boolean;
@@ -92,7 +102,9 @@ const SYSTEM_MESSAGE_TYPES: number[] = GROUP_NOTIFICATION_TYPES;
92
102
 
93
103
  // Tapping these types must keep opening the media/file as today — they never
94
104
  // participate in tap-to-reveal-time, so no Tap gesture is attached at all for
95
- // them (avoids racing their own internal touchables for the same tap).
105
+ // them (avoids racing their own internal touchables for the same tap). Callers
106
+ // that need every message type tappable regardless (e.g. navigating to the
107
+ // original message from a quote/pin) opt in via `alwaysHandlePress`.
96
108
  const TIME_REVEAL_EXCLUDED_TYPES: number[] = [
97
109
  ...MEDIA_TYPES,
98
110
  MessageType.FileMessage,
@@ -108,6 +120,7 @@ export const LegendChatMessage = memo(
108
120
  onPressUrl,
109
121
  onRetry,
110
122
  onPress,
123
+ alwaysHandlePress,
111
124
  onLongPress,
112
125
  customMessageItemFactory,
113
126
  isHighlighted,
@@ -148,8 +161,10 @@ export const LegendChatMessage = memo(
148
161
  const MessageComponent: ComponentType<MessageProps> =
149
162
  messageComponentMap[message?.contentType] ?? TextMessage;
150
163
 
164
+ const effectiveOnMediaPress =
165
+ onMediaPress ?? (alwaysHandlePress ? handlePress : undefined);
151
166
  const hasMediaPress =
152
- MEDIA_TYPES.includes(message?.contentType) && onMediaPress;
167
+ MEDIA_TYPES.includes(message?.contentType) && !!effectiveOnMediaPress;
153
168
  // AtTextMessage: mention+URL combo attaches its link-preview card via
154
169
  // ex.urlMetadata (see TextMessage's doc comment) and/or the native
155
170
  // AtTextElem.urls (SDK rc39+) for in-text link highlighting — either
@@ -163,6 +178,7 @@ export const LegendChatMessage = memo(
163
178
  const canRevealTime = !TIME_REVEAL_EXCLUDED_TYPES.includes(
164
179
  message?.contentType
165
180
  );
181
+ const shouldHandlePress = canRevealTime || alwaysHandlePress;
166
182
 
167
183
  return (
168
184
  <KContainer.View style={messageStyles.wrapper} row alignItems>
@@ -195,14 +211,14 @@ export const LegendChatMessage = memo(
195
211
  </KLabel.Text>
196
212
  )}
197
213
  <LongPressWrapper
198
- onPress={canRevealTime ? handlePress : undefined}
214
+ onPress={shouldHandlePress ? handlePress : undefined}
199
215
  onLongPress={handleLongPress}
200
216
  >
201
217
  <MessageComponent
202
218
  message={message}
203
219
  isOutgoing={isOutgoing}
204
220
  createdAtTime={createdAtTime}
205
- onMediaPress={hasMediaPress ? onMediaPress : undefined}
221
+ onMediaPress={hasMediaPress ? effectiveOnMediaPress : undefined}
206
222
  onPressUrl={hasUrlPress ? onPressUrl : undefined}
207
223
  isHighlighted={isHighlighted}
208
224
  isTimeRevealed={canRevealTime && isTimeRevealed}
@@ -17,7 +17,11 @@ import {
17
17
  getCopyableMessageText,
18
18
  getMessageToolboxItems,
19
19
  } from './messageToolbox.utils';
20
- import type { MeasuredRect, MessageToolboxRef } from './types';
20
+ import type {
21
+ MeasuredRect,
22
+ MessageToolboxRef,
23
+ MessageToolboxShowFn,
24
+ } from './types';
21
25
  import { MessageToolboxWrapper } from './MessageToolboxWrapper';
22
26
  import type { ReactNode } from 'react';
23
27
  import type { SharedValue } from 'react-native-reanimated';
@@ -28,6 +32,7 @@ import {
28
32
  type MessageItem,
29
33
  } from '@droppii/openim-rn-client-sdk';
30
34
  import { useHasGroupPermission } from '../../../hooks/useGroupPermission';
35
+ import type { GroupPosition } from '../../../utils/legendListMessage';
31
36
 
32
37
  // Android only: this Modal's native window is added/removed asynchronously
33
38
  // relative to its React state, and each of those transitions makes
@@ -64,11 +69,15 @@ export const MessageToolboxOverlay = forwardRef<
64
69
  },
65
70
  ref
66
71
  ) => {
67
- const { setQuotedMessage, conversation } = useChatDetailContext();
72
+ const { setQuotedMessage, conversation, isGroupConversation } =
73
+ useChatDetailContext();
68
74
  const { generateChatDetailLink } = useChatContext();
69
75
  const [visible, setVisible] = useState(false);
70
76
  const [message, setMessage] = useState<MessageItem | undefined>(undefined);
71
77
  const [rect, setRect] = useState<MeasuredRect | null>(null);
78
+ const [groupPosition, setGroupPosition] = useState<
79
+ GroupPosition | undefined
80
+ >(undefined);
72
81
  const toolboxItems = useMemo(
73
82
  () => getMessageToolboxItems(message, currentUserId),
74
83
  [message, currentUserId]
@@ -92,6 +101,7 @@ export const MessageToolboxOverlay = forwardRef<
92
101
  setVisible(false);
93
102
  setMessage(undefined);
94
103
  setRect(null);
104
+ setGroupPosition(undefined);
95
105
  if (freeze) {
96
106
  clearPendingUnfreeze();
97
107
  unfreezeTimeoutRef.current = setTimeout(() => {
@@ -101,8 +111,8 @@ export const MessageToolboxOverlay = forwardRef<
101
111
  }
102
112
  }, [freeze, clearPendingUnfreeze]);
103
113
 
104
- const show = useCallback(
105
- (msg: MessageItem, msgRect: MeasuredRect) => {
114
+ const show = useCallback<MessageToolboxShowFn>(
115
+ (msg, msgRect, msgGroupPosition) => {
106
116
  const toolboxNotAvailable =
107
117
  Object.values(getMessageToolboxItems(msg, currentUserId)).filter(
108
118
  Boolean
@@ -119,6 +129,7 @@ export const MessageToolboxOverlay = forwardRef<
119
129
 
120
130
  setMessage(msg);
121
131
  setRect(msgRect);
132
+ setGroupPosition(msgGroupPosition);
122
133
  setVisible(true);
123
134
  },
124
135
  [currentUserId, freeze, clearPendingUnfreeze]
@@ -145,9 +156,6 @@ export const MessageToolboxOverlay = forwardRef<
145
156
  const link = generateChatDetailLink({
146
157
  targetConversationId: conversation?.conversationID,
147
158
  targetMessageId: message.clientMsgID,
148
- targetGroupId: conversation?.groupID,
149
- targetUserId: conversation?.userID,
150
- // targetBotId: '',
151
159
  });
152
160
  Clipboard.setString(link);
153
161
 
@@ -206,6 +214,13 @@ export const MessageToolboxOverlay = forwardRef<
206
214
  }
207
215
 
208
216
  const isOutgoing = message.sendID === currentUserId;
217
+ const showSenderGutter = isGroupConversation && !isOutgoing;
218
+ const showName =
219
+ showSenderGutter &&
220
+ (groupPosition === 'first' || groupPosition === 'solo');
221
+ const showAvatar =
222
+ showSenderGutter &&
223
+ (groupPosition === 'last' || groupPosition === 'solo');
209
224
 
210
225
  return (
211
226
  <Modal
@@ -227,6 +242,10 @@ export const MessageToolboxOverlay = forwardRef<
227
242
  isOutgoing={isOutgoing}
228
243
  createdAtTime={message.sendTime || message.createTime}
229
244
  customMessageItemFactory={customMessageItemFactory}
245
+ showSenderGutter={showSenderGutter}
246
+ showAvatar={showAvatar}
247
+ showName={showName}
248
+ groupPosition={groupPosition}
230
249
  />
231
250
  }
232
251
  toolbox={
@@ -1,4 +1,5 @@
1
1
  import type { MessageItem } from '@droppii/openim-rn-client-sdk';
2
+ import type { GroupPosition } from '../../../utils/legendListMessage';
2
3
 
3
4
  export interface MeasuredRect {
4
5
  x: number;
@@ -7,7 +8,13 @@ export interface MeasuredRect {
7
8
  height: number;
8
9
  }
9
10
 
11
+ export type MessageToolboxShowFn = (
12
+ message: MessageItem,
13
+ rect: MeasuredRect,
14
+ groupPosition?: GroupPosition
15
+ ) => void;
16
+
10
17
  export interface MessageToolboxRef {
11
- show: (message: MessageItem, rect: MeasuredRect) => void;
18
+ show: MessageToolboxShowFn;
12
19
  hide: () => void;
13
20
  }
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { MediaItem } from '../../hooks/useMediaViewer';
3
- import type { MeasuredRect } from './messageToolbox/types';
3
+ import type { MessageToolboxShowFn } from './messageToolbox/types';
4
4
  import type {
5
5
  GroupJoinSource,
6
6
  MessageItem,
@@ -86,7 +86,7 @@ export interface ChatListProps {
86
86
  hasMoreNew?: boolean;
87
87
  onMediaPress?: (items: MediaItem[], index?: number) => void;
88
88
  onPressUrl?: (url: string) => void;
89
- onLongPress?: (message: MessageItem, rect: MeasuredRect) => void;
89
+ onLongPress?: MessageToolboxShowFn;
90
90
  }
91
91
 
92
92
  export interface ChatDetailProps extends Omit<