@droppii-org/chat-mobile 0.2.51 → 0.2.53
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.
- package/lib/module/assets/images/index.js +2 -1
- package/lib/module/assets/images/index.js.map +1 -1
- package/lib/module/assets/images/resource-center-empty-box.png +0 -0
- package/lib/module/components/MediaViewerModal.js +2 -1
- package/lib/module/components/MediaViewerModal.js.map +1 -1
- package/lib/module/components/MergedImageGrid.js +1 -0
- package/lib/module/components/MergedImageGrid.js.map +1 -1
- package/lib/module/config/api-endpoints.js +2 -1
- package/lib/module/config/api-endpoints.js.map +1 -1
- package/lib/module/context/ChatDetailContext.js +2 -1
- package/lib/module/context/ChatDetailContext.js.map +1 -1
- package/lib/module/core/notification/pushToken.js +7 -7
- package/lib/module/core/notification/pushToken.js.map +1 -1
- package/lib/module/hooks/flows/useFlow.js +10 -0
- package/lib/module/hooks/flows/useFlow.js.map +1 -1
- package/lib/module/hooks/query-keys.js +5 -0
- package/lib/module/hooks/query-keys.js.map +1 -1
- package/lib/module/hooks/resourceCenter/useThreadResources.js +116 -0
- package/lib/module/hooks/resourceCenter/useThreadResources.js.map +1 -0
- package/lib/module/hooks/useImageAttachment.js +0 -2
- package/lib/module/hooks/useImageAttachment.js.map +1 -1
- package/lib/module/hooks/useMediaViewer.js +4 -1
- package/lib/module/hooks/useMediaViewer.js.map +1 -1
- package/lib/module/hooks/useSendAttachment.js +4 -1
- package/lib/module/hooks/useSendAttachment.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/screens/MediaView/index.js +104 -42
- package/lib/module/screens/MediaView/index.js.map +1 -1
- package/lib/module/screens/ResourceCenter/FileResourceRow.js +80 -0
- package/lib/module/screens/ResourceCenter/FileResourceRow.js.map +1 -0
- package/lib/module/screens/ResourceCenter/GridRenderer.js +83 -0
- package/lib/module/screens/ResourceCenter/GridRenderer.js.map +1 -0
- package/lib/module/screens/ResourceCenter/GridThumbnail.js +97 -0
- package/lib/module/screens/ResourceCenter/GridThumbnail.js.map +1 -0
- package/lib/module/screens/ResourceCenter/LinkResourceRow.js +81 -0
- package/lib/module/screens/ResourceCenter/LinkResourceRow.js.map +1 -0
- package/lib/module/screens/ResourceCenter/ListRenderer.js +60 -0
- package/lib/module/screens/ResourceCenter/ListRenderer.js.map +1 -0
- package/lib/module/screens/ResourceCenter/ResourceCenterTabBar.js +75 -0
- package/lib/module/screens/ResourceCenter/ResourceCenterTabBar.js.map +1 -0
- package/lib/module/screens/ResourceCenter/ResourceCenterTabScene.js +122 -0
- package/lib/module/screens/ResourceCenter/ResourceCenterTabScene.js.map +1 -0
- package/lib/module/screens/ResourceCenter/ResourceEmptyState.js +36 -0
- package/lib/module/screens/ResourceCenter/ResourceEmptyState.js.map +1 -0
- package/lib/module/screens/ResourceCenter/index.js +104 -0
- package/lib/module/screens/ResourceCenter/index.js.map +1 -0
- package/lib/module/screens/ResourceCenter/types.js +25 -0
- package/lib/module/screens/ResourceCenter/types.js.map +1 -0
- package/lib/module/screens/chat-detail/BotMenuSheet.js +73 -0
- package/lib/module/screens/chat-detail/BotMenuSheet.js.map +1 -0
- package/lib/module/screens/chat-detail/ChatComposer.js +78 -3
- package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
- package/lib/module/screens/chat-detail/components/ChatMessageInput.js +11 -6
- package/lib/module/screens/chat-detail/components/ChatMessageInput.js.map +1 -1
- package/lib/module/services/attachmentOrchestrator.js +19 -4
- package/lib/module/services/attachmentOrchestrator.js.map +1 -1
- package/lib/module/services/endpoints.js +1 -0
- package/lib/module/services/endpoints.js.map +1 -1
- package/lib/module/services/resourceCenter.js +102 -0
- package/lib/module/services/resourceCenter.js.map +1 -0
- package/lib/module/translation/resources/i18n.js +13 -1
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/module/types/attachment.js +2 -0
- package/lib/module/types/chat.js +20 -0
- package/lib/module/types/chat.js.map +1 -1
- package/lib/module/utils/url.js +11 -0
- package/lib/module/utils/url.js.map +1 -1
- package/lib/typescript/src/assets/images/index.d.ts +1 -0
- package/lib/typescript/src/assets/images/index.d.ts.map +1 -1
- package/lib/typescript/src/components/MediaViewerModal.d.ts +3 -1
- package/lib/typescript/src/components/MediaViewerModal.d.ts.map +1 -1
- package/lib/typescript/src/components/MergedImageGrid.d.ts.map +1 -1
- package/lib/typescript/src/config/api-endpoints.d.ts +1 -0
- package/lib/typescript/src/config/api-endpoints.d.ts.map +1 -1
- package/lib/typescript/src/context/ChatDetailContext.d.ts.map +1 -1
- package/lib/typescript/src/hooks/flows/useFlow.d.ts +1 -0
- package/lib/typescript/src/hooks/flows/useFlow.d.ts.map +1 -1
- package/lib/typescript/src/hooks/query-keys.d.ts +5 -0
- package/lib/typescript/src/hooks/query-keys.d.ts.map +1 -1
- package/lib/typescript/src/hooks/resourceCenter/useThreadResources.d.ts +21 -0
- package/lib/typescript/src/hooks/resourceCenter/useThreadResources.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useImageAttachment.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useMediaViewer.d.ts +5 -1
- package/lib/typescript/src/hooks/useMediaViewer.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useSendAttachment.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/screens/MediaView/index.d.ts.map +1 -1
- package/lib/typescript/src/screens/ResourceCenter/FileResourceRow.d.ts +7 -0
- package/lib/typescript/src/screens/ResourceCenter/FileResourceRow.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/GridRenderer.d.ts +14 -0
- package/lib/typescript/src/screens/ResourceCenter/GridRenderer.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/GridThumbnail.d.ts +10 -0
- package/lib/typescript/src/screens/ResourceCenter/GridThumbnail.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/LinkResourceRow.d.ts +8 -0
- package/lib/typescript/src/screens/ResourceCenter/LinkResourceRow.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/ListRenderer.d.ts +16 -0
- package/lib/typescript/src/screens/ResourceCenter/ListRenderer.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceCenterTabBar.d.ts +3 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceCenterTabBar.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceCenterTabScene.d.ts +16 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceCenterTabScene.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceEmptyState.d.ts +6 -0
- package/lib/typescript/src/screens/ResourceCenter/ResourceEmptyState.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/index.d.ts +4 -0
- package/lib/typescript/src/screens/ResourceCenter/index.d.ts.map +1 -0
- package/lib/typescript/src/screens/ResourceCenter/types.d.ts +28 -0
- package/lib/typescript/src/screens/ResourceCenter/types.d.ts.map +1 -0
- package/lib/typescript/src/screens/chat-detail/BotMenuSheet.d.ts +7 -0
- package/lib/typescript/src/screens/chat-detail/BotMenuSheet.d.ts.map +1 -0
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/components/ChatMessageInput.d.ts +2 -1
- package/lib/typescript/src/screens/chat-detail/components/ChatMessageInput.d.ts.map +1 -1
- package/lib/typescript/src/services/attachmentOrchestrator.d.ts.map +1 -1
- package/lib/typescript/src/services/endpoints.d.ts +1 -0
- package/lib/typescript/src/services/endpoints.d.ts.map +1 -1
- package/lib/typescript/src/services/resourceCenter.d.ts +9 -0
- package/lib/typescript/src/services/resourceCenter.d.ts.map +1 -0
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/lib/typescript/src/types/attachment.d.ts +2 -0
- package/lib/typescript/src/types/attachment.d.ts.map +1 -1
- package/lib/typescript/src/types/chat.d.ts +60 -1
- package/lib/typescript/src/types/chat.d.ts.map +1 -1
- package/lib/typescript/src/utils/url.d.ts +7 -0
- package/lib/typescript/src/utils/url.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/assets/images/index.ts +1 -0
- package/src/assets/images/resource-center-empty-box.png +0 -0
- package/src/components/MediaViewerModal.tsx +8 -3
- package/src/components/MergedImageGrid.tsx +1 -0
- package/src/config/api-endpoints.ts +2 -0
- package/src/context/ChatDetailContext.tsx +1 -0
- package/src/core/notification/pushToken.ts +7 -7
- package/src/hooks/flows/useFlow.ts +14 -0
- package/src/hooks/query-keys.ts +10 -0
- package/src/hooks/resourceCenter/useThreadResources.ts +124 -0
- package/src/hooks/useImageAttachment.ts +1 -2
- package/src/hooks/useMediaViewer.ts +21 -7
- package/src/hooks/useSendAttachment.ts +4 -1
- package/src/index.tsx +2 -0
- package/src/screens/MediaView/index.tsx +117 -54
- package/src/screens/ResourceCenter/FileResourceRow.tsx +99 -0
- package/src/screens/ResourceCenter/GridRenderer.tsx +104 -0
- package/src/screens/ResourceCenter/GridThumbnail.tsx +98 -0
- package/src/screens/ResourceCenter/LinkResourceRow.tsx +96 -0
- package/src/screens/ResourceCenter/ListRenderer.tsx +81 -0
- package/src/screens/ResourceCenter/ResourceCenterTabBar.tsx +89 -0
- package/src/screens/ResourceCenter/ResourceCenterTabScene.tsx +142 -0
- package/src/screens/ResourceCenter/ResourceEmptyState.tsx +39 -0
- package/src/screens/ResourceCenter/index.tsx +129 -0
- package/src/screens/ResourceCenter/types.ts +56 -0
- package/src/screens/chat-detail/BotMenuSheet.tsx +94 -0
- package/src/screens/chat-detail/ChatComposer.tsx +100 -3
- package/src/screens/chat-detail/components/ChatMessageInput.tsx +11 -7
- package/src/services/attachmentOrchestrator.ts +15 -2
- package/src/services/endpoints.ts +2 -0
- package/src/services/resourceCenter.ts +137 -0
- package/src/translation/resources/i18n.ts +13 -0
- package/src/types/attachment.ts +3 -0
- package/src/types/chat.ts +75 -0
- package/src/utils/url.ts +11 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { apiInstance } from './apis';
|
|
2
|
+
import { getApiEndpoint } from '../config/api-endpoints';
|
|
3
|
+
import { extractDomain } from '../utils/url';
|
|
4
|
+
import type { BaseResponse } from '../types/auth';
|
|
5
|
+
import {
|
|
6
|
+
DThreadResourceContentType,
|
|
7
|
+
type DThreadResource,
|
|
8
|
+
type DThreadResourceListResponse,
|
|
9
|
+
type DThreadResourceRawRow,
|
|
10
|
+
type DThreadResourceRequest,
|
|
11
|
+
} from '../types/chat';
|
|
12
|
+
|
|
13
|
+
interface RawPicture {
|
|
14
|
+
url?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface RawPictureContent {
|
|
18
|
+
bigPicture?: RawPicture;
|
|
19
|
+
snapshotPicture?: RawPicture;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface RawUrlTextEx {
|
|
23
|
+
urlMetadata?: {
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
image?: string;
|
|
27
|
+
url?: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Confirmed real: `ex.urlMetadata` is sometimes absent entirely (link preview never
|
|
32
|
+
// resolved by BE) — `content.urls[0]` (the raw URL from the message text) is the
|
|
33
|
+
// fallback so the row still has something to display/open.
|
|
34
|
+
interface RawUrlTextContent {
|
|
35
|
+
urls?: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// FILE/VIDEO shapes verified 2026-07-26 against a real staging response (a 1-1
|
|
39
|
+
// thread, recvID = peer userID) — matched the originally-assumed OpenIM
|
|
40
|
+
// `fileElem`/`videoElem`-style field names exactly.
|
|
41
|
+
interface RawFileContent {
|
|
42
|
+
fileName?: string;
|
|
43
|
+
fileSize?: number;
|
|
44
|
+
fileType?: string;
|
|
45
|
+
sourceUrl?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface RawVideoContent {
|
|
49
|
+
videoUrl?: string;
|
|
50
|
+
snapshotUrl?: string;
|
|
51
|
+
duration?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const safeJsonParse = <T>(raw: string | undefined): T | undefined => {
|
|
55
|
+
if (!raw) return undefined;
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(raw) as T;
|
|
58
|
+
} catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const parseThreadResourceItem = (
|
|
64
|
+
row: DThreadResourceRawRow
|
|
65
|
+
): DThreadResource => {
|
|
66
|
+
const { chatLog } = row;
|
|
67
|
+
const contentType = chatLog.contentType as DThreadResourceContentType;
|
|
68
|
+
const base: DThreadResource = {
|
|
69
|
+
id: chatLog.clientMsgID,
|
|
70
|
+
contentType,
|
|
71
|
+
isRevoked: row.isRevoked,
|
|
72
|
+
createdAt: chatLog.sendTime,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
switch (contentType) {
|
|
76
|
+
case DThreadResourceContentType.IMAGE: {
|
|
77
|
+
const content = safeJsonParse<RawPictureContent>(chatLog.content);
|
|
78
|
+
return {
|
|
79
|
+
...base,
|
|
80
|
+
sourceUrl: content?.bigPicture?.url,
|
|
81
|
+
thumbnailUrl: content?.snapshotPicture?.url,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case DThreadResourceContentType.VIDEO: {
|
|
85
|
+
const content = safeJsonParse<RawVideoContent>(chatLog.content);
|
|
86
|
+
return {
|
|
87
|
+
...base,
|
|
88
|
+
sourceUrl: content?.videoUrl,
|
|
89
|
+
thumbnailUrl: content?.snapshotUrl,
|
|
90
|
+
duration: content?.duration,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
case DThreadResourceContentType.FILE: {
|
|
94
|
+
const content = safeJsonParse<RawFileContent>(chatLog.content);
|
|
95
|
+
return {
|
|
96
|
+
...base,
|
|
97
|
+
sourceUrl: content?.sourceUrl,
|
|
98
|
+
fileName: content?.fileName,
|
|
99
|
+
fileSize: content?.fileSize,
|
|
100
|
+
mimeType: content?.fileType,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
case DThreadResourceContentType.URL_TEXT: {
|
|
104
|
+
const ex = safeJsonParse<RawUrlTextEx>(chatLog.ex);
|
|
105
|
+
const content = safeJsonParse<RawUrlTextContent>(chatLog.content);
|
|
106
|
+
const metadata = ex?.urlMetadata;
|
|
107
|
+
const linkUrl = metadata?.url ?? content?.urls?.[0];
|
|
108
|
+
return {
|
|
109
|
+
...base,
|
|
110
|
+
linkUrl,
|
|
111
|
+
linkTitle: metadata?.title,
|
|
112
|
+
linkDescription: metadata?.description,
|
|
113
|
+
linkImageUrl: metadata?.image,
|
|
114
|
+
linkDomain: linkUrl ? extractDomain(linkUrl) : undefined,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
default:
|
|
118
|
+
return base;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export namespace ResourceCenterService {
|
|
123
|
+
export const fetchThreadResources = async (
|
|
124
|
+
req: DThreadResourceRequest
|
|
125
|
+
): Promise<{ items: DThreadResource[]; page: number; hasMore: boolean }> => {
|
|
126
|
+
const res = await apiInstance?.post<
|
|
127
|
+
BaseResponse<DThreadResourceListResponse>
|
|
128
|
+
>(getApiEndpoint('messagesResources'), req);
|
|
129
|
+
const rows = res?.data?.data ?? [];
|
|
130
|
+
const items = rows.map(parseThreadResourceItem);
|
|
131
|
+
// `pageable.totalPages`/`totalElements` come back as `0` on this endpoint even
|
|
132
|
+
// when rows are present (confirmed against staging) — unreliable, don't use it.
|
|
133
|
+
// Item-count-vs-pageSize is the only trustworthy `hasMore` signal available.
|
|
134
|
+
const hasMore = items.length >= req.pageSize;
|
|
135
|
+
return { items, page: req.page, hasMore };
|
|
136
|
+
};
|
|
137
|
+
}
|
|
@@ -93,6 +93,19 @@ const i18nKey: Record<string, string> = {
|
|
|
93
93
|
'yourself': 'chính mình',
|
|
94
94
|
'you': 'Bạn',
|
|
95
95
|
'recent': 'Gần đây',
|
|
96
|
+
'chat:resource_center_title': 'Tập tin phương tiện',
|
|
97
|
+
'chat:resource_center_tab_image': 'Ảnh',
|
|
98
|
+
'chat:resource_center_tab_video': 'Video',
|
|
99
|
+
'chat:resource_center_tab_file': 'Tập tin',
|
|
100
|
+
'chat:resource_center_tab_link': 'Liên kết',
|
|
101
|
+
'chat:resource_center_empty_generic': 'Không tìm thấy tập tin nào',
|
|
102
|
+
'chat:resource_center_empty_link': 'Không tìm thấy liên kết nào',
|
|
103
|
+
'chat:bot_menu_title': 'Gợi ý',
|
|
104
|
+
'chat:end_support_session_title': 'Kết thúc phiên hỗ trợ',
|
|
105
|
+
'chat:end_support_session_desc':
|
|
106
|
+
'Bạn đang trong phiên hỗ trợ với hỗ trợ viên, bạn có muốn <bold>kết thúc phiên hỗ trợ</bold> ngay bây giờ?',
|
|
107
|
+
'chat:end_support_session_primary': 'Kết thúc',
|
|
108
|
+
'chat:end_support_session_secondary': 'Tiếp tục',
|
|
96
109
|
};
|
|
97
110
|
|
|
98
111
|
export default {
|
package/src/types/attachment.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { DChatApplicationType } from './chat';
|
|
2
|
+
|
|
1
3
|
export type AttachmentType = 'image' | 'video' | 'file' | 'audio' | 'document';
|
|
2
4
|
|
|
3
5
|
export interface BaseAttachment {
|
|
@@ -70,6 +72,7 @@ export type BatchStrategy = 'individual' | 'merged' | 'grouped';
|
|
|
70
72
|
|
|
71
73
|
export interface AttachmentSendOptions {
|
|
72
74
|
strategy: BatchStrategy;
|
|
75
|
+
applicationType?: DChatApplicationType;
|
|
73
76
|
includeCaption?: string;
|
|
74
77
|
uploadConcurrency?: number;
|
|
75
78
|
retryFailedUploads?: boolean;
|
package/src/types/chat.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
DFlowContext,
|
|
9
9
|
IConversationFlow,
|
|
10
10
|
IConversationFlowStep,
|
|
11
|
+
InputButtonItem,
|
|
11
12
|
IRunConversationFlowPayload,
|
|
12
13
|
} from './flows';
|
|
13
14
|
import type { GetOpenIMTokenResponse } from './auth';
|
|
@@ -209,6 +210,7 @@ export interface ChatDetailContextType {
|
|
|
209
210
|
conversation?: ConversationItem;
|
|
210
211
|
quotedMessage?: MessageItem;
|
|
211
212
|
setQuotedMessage: (item?: MessageItem) => void;
|
|
213
|
+
conversationFlowMainMenu?: InputButtonItem[];
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
export interface ChatDetailProviderProps extends PropsWithChildren {}
|
|
@@ -242,3 +244,76 @@ export type CustomElemOrderData = {
|
|
|
242
244
|
export type CustomMessagePayload =
|
|
243
245
|
| { type: typeof CustomMessageType.Order; data: CustomElemOrderData }
|
|
244
246
|
| { type: typeof CustomMessageType.Product; data: Record<string, unknown> };
|
|
247
|
+
|
|
248
|
+
export enum DThreadResourceContentType {
|
|
249
|
+
IMAGE = 102,
|
|
250
|
+
VIDEO = 104,
|
|
251
|
+
FILE = 105,
|
|
252
|
+
URL_TEXT = 160,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface DThreadResourceRequest {
|
|
256
|
+
// ⚠️ U4c: confirmed working for BOTH shapes — a bot/group thread using the
|
|
257
|
+
// groupID-shaped value (`bot_<uuid>_<uuid>`, chatLog.groupID echoes it back,
|
|
258
|
+
// chatLog.recvID empty), AND a plain 1-1 thread using the peer's userID
|
|
259
|
+
// (matches this repo's own `getReceiverId()` convention exactly — chatLog.recvID
|
|
260
|
+
// echoes it back, chatLog.groupID empty). U4c fully resolved.
|
|
261
|
+
recvID: string;
|
|
262
|
+
contentType: DThreadResourceContentType;
|
|
263
|
+
page: number;
|
|
264
|
+
pageSize: number;
|
|
265
|
+
applicationType: DChatApplicationType;
|
|
266
|
+
// Added by BE 2026-07-28 — required. `GROUP` for group/bot threads (matches
|
|
267
|
+
// whichever branch resolved `recvID` to a `groupID`), `SINGLE` for 1-1
|
|
268
|
+
// threads (`recvID` resolved to the peer's `userID`). NOTE: BE's literal
|
|
269
|
+
// value here is `SINGLE`, not `USER` — do not confuse with
|
|
270
|
+
// `DConversationPeer.type`'s unrelated `'USER' | 'GROUP'` union above.
|
|
271
|
+
chatType: 'SINGLE' | 'GROUP';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Fully verified 2026-07-26 against `POST chat-service/v1/app/messages/resources`
|
|
276
|
+
* (staging) for all 4 content types (IMAGE/VIDEO/FILE/URL_TEXT) — see
|
|
277
|
+
* `ResourceCenterService.parseThreadResourceItem` for the exact raw-row → this-shape
|
|
278
|
+
* mapping. All field names matched the original OpenIM-elem-based assumptions exactly.
|
|
279
|
+
*/
|
|
280
|
+
export interface DThreadResource {
|
|
281
|
+
id: string; // chatLog.clientMsgID
|
|
282
|
+
contentType: DThreadResourceContentType;
|
|
283
|
+
isRevoked: boolean; // BE does NOT pre-filter revoked items, client must (U5, confirmed)
|
|
284
|
+
sourceUrl?: string; // IMAGE: content.bigPicture.url · VIDEO: content.videoUrl · FILE: content.sourceUrl
|
|
285
|
+
thumbnailUrl?: string; // IMAGE: content.snapshotPicture.url (640x640 resized) · VIDEO: content.snapshotUrl
|
|
286
|
+
fileName?: string; // FILE: content.fileName
|
|
287
|
+
fileSize?: number; // FILE: content.fileSize
|
|
288
|
+
mimeType?: string; // FILE: content.fileType
|
|
289
|
+
linkUrl?: string; // URL_TEXT: ex.urlMetadata.url
|
|
290
|
+
linkTitle?: string; // URL_TEXT: ex.urlMetadata.title
|
|
291
|
+
linkDomain?: string; // URL_TEXT: NOT provided by BE — derived client-side via extractDomain()
|
|
292
|
+
linkImageUrl?: string; // URL_TEXT: ex.urlMetadata.image
|
|
293
|
+
linkDescription?: string; // URL_TEXT: ex.urlMetadata.description (resolves U8)
|
|
294
|
+
duration?: number; // VIDEO: content.duration (milliseconds)
|
|
295
|
+
createdAt?: number; // chatLog.sendTime (ms)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* `BaseResponse<DThreadResourceListResponse>.data` is a plain array of raw rows
|
|
300
|
+
* (`{ chatLog, isRevoked, tag, displayTag }`), NOT `{ items: [...] }` — corrected
|
|
301
|
+
* after fetching a real response (initial assumption was wrong).
|
|
302
|
+
*/
|
|
303
|
+
export type DThreadResourceListResponse = DThreadResourceRawRow[];
|
|
304
|
+
|
|
305
|
+
export interface DThreadResourceRawRow {
|
|
306
|
+
chatLog: {
|
|
307
|
+
clientMsgID: string;
|
|
308
|
+
serverMsgID: string;
|
|
309
|
+
contentType: number;
|
|
310
|
+
content: string; // JSON string — shape depends on contentType, parse per-type
|
|
311
|
+
ex: string; // JSON string — e.g. `{ applicationType, urlMetadata? }` for URL_TEXT
|
|
312
|
+
sendTime: number;
|
|
313
|
+
createTime: number;
|
|
314
|
+
isRevoked: boolean;
|
|
315
|
+
};
|
|
316
|
+
isRevoked: boolean;
|
|
317
|
+
tag: unknown;
|
|
318
|
+
displayTag: unknown;
|
|
319
|
+
}
|
package/src/utils/url.ts
CHANGED
|
@@ -39,3 +39,14 @@ export function normalizeUrl(url: string) {
|
|
|
39
39
|
}
|
|
40
40
|
return url;
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The resource-center API's `urlMetadata` doesn't include a separate domain field
|
|
45
|
+
* (confirmed against a real staging response — only `title`/`description`/`image`/
|
|
46
|
+
* `url`) — derive it from the full URL instead of relying on `new URL()` (avoids a
|
|
47
|
+
* dependency on a global `URL` polyfill being present on every RN engine target).
|
|
48
|
+
*/
|
|
49
|
+
export function extractDomain(url: string): string {
|
|
50
|
+
const match = url.match(/^(?:https?:\/\/)?(?:www\.)?([^/?#]+)/i);
|
|
51
|
+
return match?.[1] ?? url;
|
|
52
|
+
}
|