@droppii-org/chat-mobile 0.2.23 → 0.2.25
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/btn_resend.png +0 -0
- package/lib/module/assets/images/index.js +2 -1
- package/lib/module/assets/images/index.js.map +1 -1
- package/lib/module/components/AttachmentPreview/FilePreview.js +1 -1
- package/lib/module/components/AttachmentPreview/FilePreview.js.map +1 -1
- package/lib/module/components/messages/MessageStatusIndicator.js +70 -0
- package/lib/module/components/messages/MessageStatusIndicator.js.map +1 -0
- package/lib/module/components/messages/fileMessage/index.js.map +1 -1
- package/lib/module/components/messages/imageMessage/index.js +59 -50
- package/lib/module/components/messages/imageMessage/index.js.map +1 -1
- package/lib/module/components/messages/linkMessage/index.js +14 -6
- package/lib/module/components/messages/linkMessage/index.js.map +1 -1
- package/lib/module/components/messages/mergedMessage/index.js.map +1 -1
- package/lib/module/components/messages/textMessage/index.js +14 -6
- package/lib/module/components/messages/textMessage/index.js.map +1 -1
- package/lib/module/components/messages/videoMessage/index.js.map +1 -1
- package/lib/module/config/uploadLimits.js +13 -0
- package/lib/module/config/uploadLimits.js.map +1 -0
- package/lib/module/core/useChatListener.js +35 -4
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/core/useUserListener.js +17 -7
- package/lib/module/core/useUserListener.js.map +1 -1
- package/lib/module/hooks/message/useSendMessage.js +62 -15
- package/lib/module/hooks/message/useSendMessage.js.map +1 -1
- package/lib/module/hooks/useChatCompose.js +153 -0
- package/lib/module/hooks/useChatCompose.js.map +1 -0
- package/lib/module/hooks/useChatMessages.js +39 -8
- package/lib/module/hooks/useChatMessages.js.map +1 -1
- package/lib/module/hooks/useFileAttachment.js +1 -1
- package/lib/module/hooks/useFileAttachment.js.map +1 -1
- package/lib/module/hooks/useFileDownload.js +1 -1
- package/lib/module/hooks/useFileDownload.js.map +1 -1
- package/lib/module/hooks/useImageAttachment.js +81 -152
- package/lib/module/hooks/useImageAttachment.js.map +1 -1
- package/lib/module/hooks/useSendAttachment.js +2 -2
- package/lib/module/hooks/useSendAttachment.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatComposer.js +50 -185
- package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetail.js +29 -137
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatListLegend.js +20 -15
- package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
- package/lib/module/screens/chat-detail/index.js +0 -1
- package/lib/module/screens/chat-detail/index.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +18 -13
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
- package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js +2 -2
- package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js.map +1 -1
- package/lib/module/services/attachmentHandlers/imageAttachmentHandler.js +3 -3
- package/lib/module/services/attachmentHandlers/imageAttachmentHandler.js.map +1 -1
- package/lib/module/services/attachmentHandlers/videoAttachmentHandler.js +2 -1
- package/lib/module/services/attachmentHandlers/videoAttachmentHandler.js.map +1 -1
- package/lib/module/services/attachmentOrchestrator.js +40 -17
- package/lib/module/services/attachmentOrchestrator.js.map +1 -1
- package/lib/module/services/message.js +13 -5
- package/lib/module/services/message.js.map +1 -1
- package/lib/module/translation/resources/i18n.js +4 -3
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/module/types/chat.js.map +1 -1
- package/lib/module/types/global.d.js +2 -0
- package/lib/module/types/global.d.js.map +1 -0
- package/lib/module/types/index.d.js +3 -0
- package/lib/module/types/index.d.js.map +1 -0
- package/lib/module/utils/UIUtils.js +37 -0
- package/lib/module/utils/UIUtils.js.map +1 -0
- package/lib/module/utils/imageUtils.js +3 -3
- package/lib/module/utils/imageUtils.js.map +1 -1
- package/lib/module/utils/pLimit.js +19 -0
- package/lib/module/utils/pLimit.js.map +1 -0
- package/lib/module/utils/videoThumbnail.js +8 -3
- package/lib/module/utils/videoThumbnail.js.map +1 -1
- package/lib/module/utils/videoThumbnailUpload.js +76 -0
- package/lib/module/utils/videoThumbnailUpload.js.map +1 -0
- 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/messages/MessageStatusIndicator.d.ts +9 -0
- package/lib/typescript/src/components/messages/MessageStatusIndicator.d.ts.map +1 -0
- package/lib/typescript/src/components/messages/fileMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/imageMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts +3 -8
- package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/mergedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts +2 -8
- package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/videoMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/config/uploadLimits.d.ts +7 -0
- package/lib/typescript/src/config/uploadLimits.d.ts.map +1 -0
- package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
- package/lib/typescript/src/core/useUserListener.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts +2 -0
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useChatCompose.d.ts +27 -0
- package/lib/typescript/src/hooks/useChatCompose.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useChatMessages.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useImageAttachment.d.ts +2 -2
- package/lib/typescript/src/hooks/useImageAttachment.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useSendAttachment.d.ts +1 -1
- package/lib/typescript/src/hooks/useSendAttachment.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts +5 -2
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/index.d.ts +0 -2
- package/lib/typescript/src/screens/chat-detail/index.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +3 -5
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts +1 -35
- package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
- package/lib/typescript/src/services/attachmentHandlers/fileAttachmentHandler.d.ts.map +1 -1
- package/lib/typescript/src/services/attachmentHandlers/imageAttachmentHandler.d.ts.map +1 -1
- package/lib/typescript/src/services/attachmentHandlers/videoAttachmentHandler.d.ts.map +1 -1
- package/lib/typescript/src/services/attachmentOrchestrator.d.ts +1 -1
- package/lib/typescript/src/services/attachmentOrchestrator.d.ts.map +1 -1
- package/lib/typescript/src/services/message.d.ts +7 -0
- package/lib/typescript/src/services/message.d.ts.map +1 -1
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/lib/typescript/src/types/chat.d.ts +11 -0
- package/lib/typescript/src/types/chat.d.ts.map +1 -1
- package/lib/typescript/src/utils/UIUtils.d.ts +4 -0
- package/lib/typescript/src/utils/UIUtils.d.ts.map +1 -0
- package/lib/typescript/src/utils/imageUtils.d.ts.map +1 -1
- package/lib/typescript/src/utils/pLimit.d.ts +6 -0
- package/lib/typescript/src/utils/pLimit.d.ts.map +1 -0
- package/lib/typescript/src/utils/videoThumbnail.d.ts.map +1 -1
- package/lib/typescript/src/utils/videoThumbnailUpload.d.ts +11 -0
- package/lib/typescript/src/utils/videoThumbnailUpload.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/assets/images/btn_resend.png +0 -0
- package/src/assets/images/index.ts +1 -0
- package/src/components/AttachmentPreview/FilePreview.tsx +1 -1
- package/src/components/messages/MessageStatusIndicator.tsx +82 -0
- package/src/components/messages/fileMessage/index.tsx +0 -1
- package/src/components/messages/imageMessage/index.tsx +71 -57
- package/src/components/messages/linkMessage/index.tsx +13 -19
- package/src/components/messages/mergedMessage/index.tsx +0 -1
- package/src/components/messages/textMessage/index.tsx +13 -18
- package/src/components/messages/videoMessage/index.tsx +0 -1
- package/src/config/uploadLimits.ts +11 -0
- package/src/core/useChatListener.ts +38 -4
- package/src/core/useUserListener.ts +17 -7
- package/src/hooks/message/useSendMessage.ts +103 -24
- package/src/hooks/useChatCompose.ts +195 -0
- package/src/hooks/useChatMessages.ts +54 -10
- package/src/hooks/useFileAttachment.ts +1 -1
- package/src/hooks/useFileDownload.ts +1 -1
- package/src/hooks/useImageAttachment.ts +120 -199
- package/src/hooks/useSendAttachment.ts +3 -6
- package/src/index.tsx +3 -5
- package/src/screens/chat-detail/ChatComposer.tsx +88 -240
- package/src/screens/chat-detail/ChatDetail.tsx +36 -195
- package/src/screens/chat-detail/ChatListLegend.tsx +16 -13
- package/src/screens/chat-detail/index.ts +1 -5
- package/src/screens/chat-detail/legend/LegendChatMessage.tsx +19 -12
- package/src/screens/chat-detail/types.ts +1 -38
- package/src/services/attachmentHandlers/fileAttachmentHandler.ts +3 -2
- package/src/services/attachmentHandlers/imageAttachmentHandler.ts +6 -3
- package/src/services/attachmentHandlers/videoAttachmentHandler.ts +2 -1
- package/src/services/attachmentOrchestrator.ts +49 -27
- package/src/services/message.ts +21 -4
- package/src/translation/resources/i18n.ts +6 -3
- package/src/types/chat.ts +6 -0
- package/src/types/global.d.ts +299 -0
- package/src/types/index.d.ts +1 -0
- package/src/utils/UIUtils.ts +31 -0
- package/src/utils/imageUtils.ts +3 -4
- package/src/utils/pLimit.ts +20 -0
- package/src/utils/videoThumbnail.ts +10 -3
- package/src/utils/videoThumbnailUpload.ts +103 -0
- package/lib/module/hooks/useVideoAttachment.js +0 -251
- package/lib/module/hooks/useVideoAttachment.js.map +0 -1
- package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js +0 -288
- package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js.map +0 -1
- package/lib/module/utils/giftedChatMessage.js +0 -90
- package/lib/module/utils/giftedChatMessage.js.map +0 -1
- package/lib/module/utils/ui.js +0 -17
- package/lib/module/utils/ui.js.map +0 -1
- package/lib/typescript/src/hooks/useVideoAttachment.d.ts +0 -29
- package/lib/typescript/src/hooks/useVideoAttachment.d.ts.map +0 -1
- package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts +0 -26
- package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts.map +0 -1
- package/lib/typescript/src/utils/giftedChatMessage.d.ts +0 -10
- package/lib/typescript/src/utils/giftedChatMessage.d.ts.map +0 -1
- package/lib/typescript/src/utils/ui.d.ts +0 -13
- package/lib/typescript/src/utils/ui.d.ts.map +0 -1
- package/src/hooks/useVideoAttachment.ts +0 -334
- package/src/screens/chat-detail/hooks/useAttachmentSendHandler.ts +0 -386
- package/src/utils/giftedChatMessage.ts +0 -137
- package/src/utils/ui.ts +0 -19
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { memo,
|
|
1
|
+
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { Platform, StyleSheet } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { KeyboardAvoidingView } from 'react-native-keyboard-controller';
|
|
@@ -14,26 +14,16 @@ import { useConversation, useConversationStore } from '../../store';
|
|
|
14
14
|
import ChatDetailHeader from './ChatDetailHeader';
|
|
15
15
|
import { ChatListLegend } from './ChatListLegend';
|
|
16
16
|
import { ChatComposer } from './ChatComposer';
|
|
17
|
-
import {
|
|
18
|
-
DEFAULT_ATTACHMENT_ACTIONS,
|
|
19
|
-
DEFAULT_Chat_QUICK_ACTIONS,
|
|
20
|
-
} from './constants';
|
|
21
17
|
import {
|
|
22
18
|
getConversationAvatarUri,
|
|
23
19
|
getConversationSubtitle,
|
|
24
20
|
getConversationTitle,
|
|
25
21
|
shouldShowAddMember,
|
|
26
22
|
} from './conversationHeader.utils';
|
|
27
|
-
import type {
|
|
28
|
-
ChatDetailProps,
|
|
29
|
-
DChatQuickAction,
|
|
30
|
-
DChatAttachmentAction,
|
|
31
|
-
} from './types';
|
|
32
|
-
import { useSendMessage } from '../../hooks/message/useSendMessage';
|
|
33
|
-
import type { IUrlMetadata } from '../../types/common';
|
|
34
|
-
import { useMessageStore } from '../../store/message';
|
|
23
|
+
import type { ChatDetailProps } from './types';
|
|
35
24
|
import { ChatDetailProvider } from '../../context/ChatDetailContext';
|
|
36
25
|
import { normalizeUrl } from '../../utils/url';
|
|
26
|
+
// import { ChatMessageAPI } from '../../services/message';
|
|
37
27
|
|
|
38
28
|
const ChatDetail = memo(
|
|
39
29
|
({
|
|
@@ -50,58 +40,27 @@ const ChatDetail = memo(
|
|
|
50
40
|
onPressAddMember,
|
|
51
41
|
onPressMenu,
|
|
52
42
|
onPressAvatar,
|
|
53
|
-
showQuickActions = true,
|
|
54
|
-
quickActions,
|
|
55
|
-
inputPlaceholder,
|
|
56
|
-
onChangeInput,
|
|
57
|
-
onPressAttach,
|
|
58
|
-
onPressEmoji,
|
|
59
|
-
attachmentActions,
|
|
60
|
-
onQuickActionPress,
|
|
61
|
-
onAttachmentAction,
|
|
62
|
-
renderQuickAction,
|
|
63
|
-
renderQuickActions,
|
|
64
|
-
renderAttachmentAction,
|
|
65
|
-
attachmentColumns,
|
|
66
43
|
onPressUrl,
|
|
67
44
|
customMessageItemFactory,
|
|
68
45
|
}: ChatDetailProps) => {
|
|
69
46
|
const navigation = useNavigation();
|
|
70
|
-
const [internalInput, setInternalInput] = useState<string>('');
|
|
71
47
|
const mediaViewerRef = useRef<MediaViewerModalHandle>(null);
|
|
72
48
|
const conversation = useConversation(conversationId);
|
|
73
|
-
// const user = conversation?.peer;
|
|
74
49
|
|
|
75
|
-
// Default handlers when props not provided
|
|
76
50
|
const handleBackDefault = useCallback(() => {
|
|
77
51
|
navigation.goBack();
|
|
78
52
|
}, [navigation]);
|
|
79
53
|
|
|
80
|
-
const
|
|
81
|
-
(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
})),
|
|
88
|
-
[]
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const attachmentActionsDefault = useMemo<DChatAttachmentAction[]>(
|
|
92
|
-
() =>
|
|
93
|
-
DEFAULT_ATTACHMENT_ACTIONS.map((action) => ({
|
|
94
|
-
...action,
|
|
95
|
-
onPress: () => {
|
|
96
|
-
console.log('[attachment-action]', action.id);
|
|
97
|
-
},
|
|
98
|
-
})),
|
|
54
|
+
const handleMediaPress = useCallback(
|
|
55
|
+
(
|
|
56
|
+
items: Parameters<MediaViewerModalHandle['show']>[0],
|
|
57
|
+
index?: number
|
|
58
|
+
) => {
|
|
59
|
+
mediaViewerRef.current?.show(items, index);
|
|
60
|
+
},
|
|
99
61
|
[]
|
|
100
62
|
);
|
|
101
63
|
|
|
102
|
-
const { sendMessage } = useSendMessage();
|
|
103
|
-
const { pushNewMessage } = useMessageStore();
|
|
104
|
-
|
|
105
64
|
const {
|
|
106
65
|
messages,
|
|
107
66
|
currentUserId,
|
|
@@ -109,30 +68,23 @@ const ChatDetail = memo(
|
|
|
109
68
|
isLoading,
|
|
110
69
|
isLoadingEarlier,
|
|
111
70
|
hasMoreEarlier,
|
|
112
|
-
} = useChatMessages({
|
|
113
|
-
conversationId,
|
|
114
|
-
enabled,
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
// Callback for attachment messages - add them to the message list
|
|
118
|
-
const handleAttachmentMessageSent = useCallback(
|
|
119
|
-
(message: any) => {
|
|
120
|
-
if (__DEV__)
|
|
121
|
-
console.log('[ChatDetail] Attachment message received:', {
|
|
122
|
-
clientMsgID: message?.clientMsgID,
|
|
123
|
-
contentType: message?.contentType,
|
|
124
|
-
});
|
|
125
|
-
if (message) {
|
|
126
|
-
pushNewMessage(message);
|
|
127
|
-
}
|
|
128
|
-
},
|
|
129
|
-
[pushNewMessage]
|
|
130
|
-
);
|
|
71
|
+
} = useChatMessages({ conversationId, enabled });
|
|
131
72
|
|
|
132
73
|
useEffect(() => {
|
|
133
74
|
useConversationStore.getState().setCurrentConversation(conversationId);
|
|
134
75
|
}, [conversationId]);
|
|
135
76
|
|
|
77
|
+
// useEffect(() => {
|
|
78
|
+
// if (!conversationId) return;
|
|
79
|
+
// ChatMessageAPI.searchLocalMessages(conversationId, { count: 20 })
|
|
80
|
+
// .then((result) => {
|
|
81
|
+
// console.log('[TEST searchLocalMessages] success:', result);
|
|
82
|
+
// })
|
|
83
|
+
// .catch((err) => {
|
|
84
|
+
// console.log('[TEST searchLocalMessages] error:', err);
|
|
85
|
+
// });
|
|
86
|
+
// }, [conversationId]);
|
|
87
|
+
|
|
136
88
|
const resolvedTitle = title ?? getConversationTitle(conversation);
|
|
137
89
|
const resolvedAvatarUri =
|
|
138
90
|
avatarUri ?? getConversationAvatarUri(conversation);
|
|
@@ -140,84 +92,18 @@ const ChatDetail = memo(
|
|
|
140
92
|
const resolvedShowAddMember =
|
|
141
93
|
showAddMember ?? shouldShowAddMember(conversation);
|
|
142
94
|
const resolvedSubtitle = useMemo(() => {
|
|
143
|
-
if (subtitle !== undefined)
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (getSubtitle && conversation) {
|
|
148
|
-
return getSubtitle(conversation);
|
|
149
|
-
}
|
|
150
|
-
|
|
95
|
+
if (subtitle !== undefined) return subtitle;
|
|
96
|
+
if (getSubtitle && conversation) return getSubtitle(conversation);
|
|
151
97
|
return getConversationSubtitle(conversation);
|
|
152
98
|
}, [conversation, getSubtitle, subtitle]);
|
|
153
99
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
const handleChangeText = useCallback(
|
|
157
|
-
(text?: string) => {
|
|
158
|
-
const newText = text ?? '';
|
|
159
|
-
if (onChangeInput) {
|
|
160
|
-
onChangeInput(newText);
|
|
161
|
-
} else {
|
|
162
|
-
setInternalInput(newText);
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
[onChangeInput]
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
const handleSend = useCallback(
|
|
169
|
-
async (urlMetadata?: any) => {
|
|
170
|
-
// Support captured text passed from attachment handler
|
|
171
|
-
const capturedText = (urlMetadata as any)?._capturedText;
|
|
172
|
-
const cleanMetadata = capturedText
|
|
173
|
-
? (({ _capturedText, ...rest }) => rest)(urlMetadata)
|
|
174
|
-
: (urlMetadata as IUrlMetadata);
|
|
175
|
-
|
|
176
|
-
const text = (capturedText || currentInput).trim();
|
|
177
|
-
|
|
178
|
-
// Validate: must have text OR preview metadata (text is optional if preview exists)
|
|
179
|
-
// If metadata exists, trust it (useLinkPreview is responsible for validity)
|
|
180
|
-
if (!text && !cleanMetadata) {
|
|
181
|
-
if (__DEV__)
|
|
182
|
-
console.warn('[ChatDetail] No text or preview link to send');
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Log if metadata seems incomplete
|
|
187
|
-
if (cleanMetadata && !cleanMetadata.url) {
|
|
188
|
-
if (__DEV__)
|
|
189
|
-
console.warn(
|
|
190
|
-
'[ChatDetail] Preview metadata missing URL - check useLinkPreview'
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
await sendMessage({
|
|
196
|
-
files: [],
|
|
197
|
-
plainText: text,
|
|
198
|
-
urlMetadata: cleanMetadata || undefined,
|
|
199
|
-
});
|
|
100
|
+
const insets = useSafeAreaInsets();
|
|
200
101
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
} else {
|
|
205
|
-
setInternalInput('');
|
|
206
|
-
}
|
|
207
|
-
} catch (error) {
|
|
208
|
-
if (__DEV__)
|
|
209
|
-
console.error('[ChatDetail] Failed to send message:', {
|
|
210
|
-
error,
|
|
211
|
-
text: text.substring(0, 50),
|
|
212
|
-
hasPreview: !!cleanMetadata,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
[currentInput, onChangeInput, sendMessage]
|
|
102
|
+
const keyboardVerticalOffset = useMemo(
|
|
103
|
+
() => Platform.select({ android: insets.bottom, default: 0 }),
|
|
104
|
+
[insets.bottom]
|
|
217
105
|
);
|
|
218
106
|
|
|
219
|
-
const insets = useSafeAreaInsets();
|
|
220
|
-
|
|
221
107
|
const handlePressUrl = useCallback(
|
|
222
108
|
(url: string) => {
|
|
223
109
|
onPressUrl?.(normalizeUrl(url));
|
|
@@ -236,25 +122,16 @@ const ChatDetail = memo(
|
|
|
236
122
|
avatarFullName={resolvedAvatarFullName}
|
|
237
123
|
showAddMember={resolvedShowAddMember}
|
|
238
124
|
onBack={onBack ?? handleBackDefault}
|
|
239
|
-
onPressSearch={
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
onPressAddMember ?? (() => console.log('[onPressAddMember]'))
|
|
244
|
-
}
|
|
245
|
-
onPressMenu={onPressMenu ?? (() => console.log('[onPressMenu]'))}
|
|
246
|
-
onPressAvatar={
|
|
247
|
-
onPressAvatar ?? (() => console.log('[onPressAvatar]'))
|
|
248
|
-
}
|
|
125
|
+
onPressSearch={onPressSearch}
|
|
126
|
+
onPressAddMember={onPressAddMember}
|
|
127
|
+
onPressMenu={onPressMenu}
|
|
128
|
+
onPressAvatar={onPressAvatar}
|
|
249
129
|
/>
|
|
250
130
|
|
|
251
131
|
<KeyboardAvoidingView
|
|
252
132
|
style={styles.keyboardAvoiding}
|
|
253
133
|
behavior="padding"
|
|
254
|
-
keyboardVerticalOffset={
|
|
255
|
-
android: insets.bottom,
|
|
256
|
-
default: 0,
|
|
257
|
-
})}
|
|
134
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
258
135
|
>
|
|
259
136
|
<ChatListLegend
|
|
260
137
|
messages={messages}
|
|
@@ -264,45 +141,11 @@ const ChatDetail = memo(
|
|
|
264
141
|
isLoading={isLoading}
|
|
265
142
|
isLoadingEarlier={isLoadingEarlier}
|
|
266
143
|
hasMoreEarlier={hasMoreEarlier}
|
|
267
|
-
onMediaPress={
|
|
268
|
-
mediaViewerRef.current?.show(items, index);
|
|
269
|
-
}}
|
|
144
|
+
onMediaPress={handleMediaPress}
|
|
270
145
|
onPressUrl={handlePressUrl}
|
|
271
146
|
/>
|
|
272
147
|
|
|
273
|
-
<ChatComposer
|
|
274
|
-
value={currentInput}
|
|
275
|
-
placeholder={inputPlaceholder}
|
|
276
|
-
onChangeText={handleChangeText}
|
|
277
|
-
onSend={handleSend}
|
|
278
|
-
onMessageSent={handleAttachmentMessageSent}
|
|
279
|
-
onPressAttach={
|
|
280
|
-
onPressAttach ?? (() => console.log('[onPressAttach]'))
|
|
281
|
-
}
|
|
282
|
-
onPressEmoji={
|
|
283
|
-
onPressEmoji ?? (() => console.log('[onPressEmoji]'))
|
|
284
|
-
}
|
|
285
|
-
showQuickActions={showQuickActions}
|
|
286
|
-
quickActions={quickActions ?? quickActionsDefault}
|
|
287
|
-
attachmentActions={attachmentActions ?? attachmentActionsDefault}
|
|
288
|
-
onQuickActionPress={
|
|
289
|
-
onQuickActionPress ??
|
|
290
|
-
((action: DChatQuickAction) => {
|
|
291
|
-
console.log('[onQuickActionPress]', action.id, action.meta);
|
|
292
|
-
})
|
|
293
|
-
}
|
|
294
|
-
onAttachmentAction={
|
|
295
|
-
onAttachmentAction ??
|
|
296
|
-
((action: DChatAttachmentAction) => {
|
|
297
|
-
console.log('[onAttachmentAction]', action.id, action.meta);
|
|
298
|
-
})
|
|
299
|
-
}
|
|
300
|
-
renderQuickAction={renderQuickAction}
|
|
301
|
-
renderQuickActions={renderQuickActions}
|
|
302
|
-
renderAttachmentAction={renderAttachmentAction}
|
|
303
|
-
attachmentColumns={attachmentColumns}
|
|
304
|
-
isEmptyMessage={messages?.length === 0}
|
|
305
|
-
/>
|
|
148
|
+
<ChatComposer isEmptyMessage={messages?.length === 0} />
|
|
306
149
|
</KeyboardAvoidingView>
|
|
307
150
|
|
|
308
151
|
<MediaViewerModal ref={mediaViewerRef} />
|
|
@@ -315,9 +158,7 @@ const ChatDetail = memo(
|
|
|
315
158
|
ChatDetail.displayName = 'ChatDetail';
|
|
316
159
|
|
|
317
160
|
const styles = StyleSheet.create({
|
|
318
|
-
keyboardAvoiding: {
|
|
319
|
-
flex: 1,
|
|
320
|
-
},
|
|
161
|
+
keyboardAvoiding: { flex: 1 },
|
|
321
162
|
});
|
|
322
163
|
|
|
323
164
|
export default ChatDetail;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { memo, useCallback, useMemo, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
3
|
import Animated, {
|
|
4
4
|
useSharedValue,
|
|
5
5
|
useAnimatedStyle,
|
|
@@ -18,6 +18,7 @@ import { getFlowInputButtonsNode } from '../../utils/flows';
|
|
|
18
18
|
import { InputButtonFlow } from '../../components/flows/inputButtons';
|
|
19
19
|
import { useResetFlow, useRunFlow } from '../../hooks/flows/useFlow';
|
|
20
20
|
import type { IRunConversationFlowPayload } from '../../types/flows';
|
|
21
|
+
import { useSendMessage } from '../../hooks/message/useSendMessage';
|
|
21
22
|
|
|
22
23
|
export const ChatListLegend = memo(
|
|
23
24
|
({
|
|
@@ -25,7 +26,6 @@ export const ChatListLegend = memo(
|
|
|
25
26
|
currentUserId = '',
|
|
26
27
|
customMessageItemFactory,
|
|
27
28
|
onLoadEarlier,
|
|
28
|
-
isLoading,
|
|
29
29
|
isLoadingEarlier,
|
|
30
30
|
hasMoreEarlier,
|
|
31
31
|
onLoadNewer,
|
|
@@ -41,6 +41,7 @@ export const ChatListLegend = memo(
|
|
|
41
41
|
);
|
|
42
42
|
|
|
43
43
|
const { isBotConversation, conversationFlow } = useChatDetailContext();
|
|
44
|
+
const { retryMessage } = useSendMessage();
|
|
44
45
|
|
|
45
46
|
const lastMessageId = useMemo(() => {
|
|
46
47
|
const last = messages[messages.length - 1];
|
|
@@ -143,6 +144,7 @@ export const ChatListLegend = memo(
|
|
|
143
144
|
createdAtTime={createdAt}
|
|
144
145
|
onMediaPress={onMediaPress}
|
|
145
146
|
onPressUrl={onPressUrl}
|
|
147
|
+
onRetry={retryMessage}
|
|
146
148
|
customMessageItemFactory={customMessageItemFactory}
|
|
147
149
|
/>
|
|
148
150
|
{!!flowInputButtonsNode && (
|
|
@@ -179,6 +181,7 @@ export const ChatListLegend = memo(
|
|
|
179
181
|
onRunFlow,
|
|
180
182
|
conversationFlow?.flowCurrentStep,
|
|
181
183
|
handleItemLayout,
|
|
184
|
+
retryMessage,
|
|
182
185
|
]
|
|
183
186
|
);
|
|
184
187
|
|
|
@@ -327,16 +330,16 @@ export const ChatListLegend = memo(
|
|
|
327
330
|
};
|
|
328
331
|
}, []);
|
|
329
332
|
|
|
330
|
-
if (isLoading) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
333
|
+
// if (isLoading) {
|
|
334
|
+
// return (
|
|
335
|
+
// <KContainer.View flex center background={KColors.white}>
|
|
336
|
+
// <ActivityIndicator
|
|
337
|
+
// color={KColors.palette.primary.w400}
|
|
338
|
+
// size="small"
|
|
339
|
+
// />
|
|
340
|
+
// </KContainer.View>
|
|
341
|
+
// );
|
|
342
|
+
// }
|
|
340
343
|
|
|
341
344
|
return (
|
|
342
345
|
<KContainer.View flex background={KColors.white} style={styles.container}>
|
|
@@ -346,7 +349,7 @@ export const ChatListLegend = memo(
|
|
|
346
349
|
renderItem={renderItem}
|
|
347
350
|
estimatedItemSize={avgItemHeightRef.current}
|
|
348
351
|
keyExtractor={(item) => String(item.clientMsgID || item.serverMsgID)}
|
|
349
|
-
recycleItems={
|
|
352
|
+
recycleItems={true}
|
|
350
353
|
extraData={`${conversationFlow?.flowCurrentStep?.id ?? ''}-${lastMessageId ?? ''}`}
|
|
351
354
|
alignItemsAtEnd
|
|
352
355
|
maintainVisibleContentPosition={maintainVisiblePositionConfig}
|
|
@@ -27,12 +27,8 @@ export type {
|
|
|
27
27
|
ChatQuickActionsRenderParams,
|
|
28
28
|
ChatAttachmentPanelProps,
|
|
29
29
|
} from './types';
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
export {
|
|
32
32
|
DChatMessageType,
|
|
33
33
|
CUSTOM_MESSAGE_DATA_TYPE,
|
|
34
34
|
} from '../../types/message';
|
|
35
|
-
export {
|
|
36
|
-
mapOpenIMMessageToGiftedChat,
|
|
37
|
-
mapOpenIMMessagesToGiftedChat,
|
|
38
|
-
} from '../../utils/giftedChatMessage';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { memo } from 'react';
|
|
2
2
|
import type { ComponentType, ReactNode } from 'react';
|
|
3
|
+
import { KContainer } from '@droppii/libs';
|
|
3
4
|
import { MessageType } from '@droppii/openim-rn-client-sdk';
|
|
5
|
+
import type { MessageItem } from '@droppii/openim-rn-client-sdk';
|
|
4
6
|
import type { DMessageItem } from '../../../types/chat';
|
|
5
7
|
import type { MediaItem } from '../../../hooks/useMediaViewer';
|
|
6
8
|
import { TextMessage } from '../../../components/messages/textMessage';
|
|
@@ -9,6 +11,7 @@ import { VideoMessage } from '../../../components/messages/videoMessage';
|
|
|
9
11
|
import { FileMessage } from '../../../components/messages/fileMessage';
|
|
10
12
|
import { LinkMessage } from '../../../components/messages/linkMessage';
|
|
11
13
|
import { MergedMessage } from '../../../components/messages/mergedMessage';
|
|
14
|
+
import { MessageStatusIndicator } from '../../../components/messages/MessageStatusIndicator';
|
|
12
15
|
import type { BaseLegendMessageProps } from '../../../components/messages/types';
|
|
13
16
|
|
|
14
17
|
type MessageProps = BaseLegendMessageProps & {
|
|
@@ -21,6 +24,7 @@ interface LegendChatMessageProps {
|
|
|
21
24
|
createdAtTime: number;
|
|
22
25
|
onMediaPress?: (items: MediaItem[], index?: number) => void;
|
|
23
26
|
onPressUrl?: (url: string) => void;
|
|
27
|
+
onRetry?: (message: MessageItem) => void;
|
|
24
28
|
customMessageItemFactory?: (m: DMessageItem) => ReactNode;
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -46,10 +50,6 @@ const MEDIA_TYPES: number[] = [
|
|
|
46
50
|
MERGED_MESSAGE_TYPE,
|
|
47
51
|
];
|
|
48
52
|
|
|
49
|
-
/**
|
|
50
|
-
* Dispatcher component - renders the appropriate message component
|
|
51
|
-
* based on message type. Extensible for new message types.
|
|
52
|
-
*/
|
|
53
53
|
export const LegendChatMessage = memo(
|
|
54
54
|
({
|
|
55
55
|
message,
|
|
@@ -57,9 +57,9 @@ export const LegendChatMessage = memo(
|
|
|
57
57
|
createdAtTime,
|
|
58
58
|
onMediaPress,
|
|
59
59
|
onPressUrl,
|
|
60
|
+
onRetry,
|
|
60
61
|
customMessageItemFactory,
|
|
61
62
|
}: LegendChatMessageProps) => {
|
|
62
|
-
console.log('customMessageItemFactory', customMessageItemFactory);
|
|
63
63
|
const customNode = customMessageItemFactory?.(message);
|
|
64
64
|
if (customNode) {
|
|
65
65
|
return customNode;
|
|
@@ -74,13 +74,20 @@ export const LegendChatMessage = memo(
|
|
|
74
74
|
onPressUrl && message?.contentType === MessageType.UrlTextMessage;
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
<KContainer.View row alignItems>
|
|
78
|
+
<MessageStatusIndicator
|
|
79
|
+
message={message}
|
|
80
|
+
isOutgoing={isOutgoing}
|
|
81
|
+
onRetry={onRetry}
|
|
82
|
+
/>
|
|
83
|
+
<MessageComponent
|
|
84
|
+
message={message}
|
|
85
|
+
isOutgoing={isOutgoing}
|
|
86
|
+
createdAtTime={createdAtTime}
|
|
87
|
+
onMediaPress={hasMediaPress ? onMediaPress : undefined}
|
|
88
|
+
onPressUrl={hasUrlPress ? onPressUrl : undefined}
|
|
89
|
+
/>
|
|
90
|
+
</KContainer.View>
|
|
84
91
|
);
|
|
85
92
|
}
|
|
86
93
|
);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
2
|
import type { MediaItem } from '../../hooks/useMediaViewer';
|
|
4
3
|
import type { DMessageItem } from '../../types/chat';
|
|
5
|
-
import type { IUrlMetadata } from '../../types/common';
|
|
6
4
|
import type { ConversationItem } from '@droppii/openim-rn-client-sdk';
|
|
7
5
|
|
|
8
6
|
export type DChatActionIconProvider = 'MaterialCommunityIcons' | 'DroppiiNew';
|
|
@@ -58,23 +56,7 @@ export interface ChatAttachmentPanelProps {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
export interface ChatComposerProps {
|
|
61
|
-
|
|
62
|
-
placeholder?: string;
|
|
63
|
-
onChangeText?: (text?: string) => void;
|
|
64
|
-
onSend?: (urlMetadata?: IUrlMetadata) => void;
|
|
65
|
-
onPressAttach?: () => void;
|
|
66
|
-
onPressEmoji?: () => void;
|
|
67
|
-
onMessageSent?: (message: DMessageItem) => void;
|
|
68
|
-
showQuickActions?: boolean;
|
|
69
|
-
quickActions?: DChatQuickAction[];
|
|
70
|
-
attachmentActions?: DChatAttachmentAction[];
|
|
71
|
-
onQuickActionPress?: (action: DChatQuickAction) => void;
|
|
72
|
-
onAttachmentAction?: (action: DChatAttachmentAction) => void;
|
|
73
|
-
renderQuickAction?: ChatQuickActionsProps['renderAction'];
|
|
74
|
-
renderQuickActions?: ChatQuickActionsProps['renderQuickActions'];
|
|
75
|
-
renderAttachmentAction?: ChatAttachmentPanelProps['renderAction'];
|
|
76
|
-
attachmentColumns?: number;
|
|
77
|
-
isEmptyMessage: boolean;
|
|
59
|
+
isEmptyMessage?: boolean;
|
|
78
60
|
}
|
|
79
61
|
|
|
80
62
|
export interface ChatListProps {
|
|
@@ -110,25 +92,6 @@ export interface ChatDetailProps extends Omit<
|
|
|
110
92
|
avatarFullName?: string;
|
|
111
93
|
showAddMember?: boolean;
|
|
112
94
|
getSubtitle?: (conversation: ConversationItem) => string | undefined;
|
|
113
|
-
renderChat?: (item: DMessageItem) => ReactNode;
|
|
114
|
-
showQuickActions?: boolean;
|
|
115
|
-
showAttachmentActions?: boolean;
|
|
116
|
-
quickActions?: DChatQuickAction[];
|
|
117
|
-
getQuickActions?: (
|
|
118
|
-
conversation: ConversationItem
|
|
119
|
-
) => DChatQuickAction[] | undefined;
|
|
120
|
-
attachmentActions?: DChatAttachmentAction[];
|
|
121
|
-
inputPlaceholder?: string;
|
|
122
|
-
onChangeInput?: (text: string) => void;
|
|
123
|
-
onSend?: () => void;
|
|
124
|
-
onPressAttach?: () => void;
|
|
125
|
-
onPressEmoji?: () => void;
|
|
126
|
-
onQuickActionPress?: (action: DChatQuickAction) => void;
|
|
127
|
-
onAttachmentAction?: (action: DChatAttachmentAction) => void;
|
|
128
|
-
renderQuickAction?: ChatQuickActionsProps['renderAction'];
|
|
129
|
-
renderQuickActions?: ChatQuickActionsProps['renderQuickActions'];
|
|
130
|
-
renderAttachmentAction?: ChatAttachmentPanelProps['renderAction'];
|
|
131
|
-
attachmentColumns?: number;
|
|
132
95
|
onPressUrl?: (url: string) => void;
|
|
133
96
|
customMessageItemFactory?: (item: DMessageItem) => ReactNode;
|
|
134
97
|
}
|
|
@@ -9,8 +9,9 @@ interface FileElem {
|
|
|
9
9
|
sourceUrl: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
import { UPLOAD_LIMITS } from '../../config/uploadLimits';
|
|
13
|
+
|
|
14
|
+
export const MAX_FILE_SIZE = UPLOAD_LIMITS.file;
|
|
14
15
|
|
|
15
16
|
export class FileAttachmentHandler implements IAttachmentHandler {
|
|
16
17
|
validate(
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { ImageAttachment } from '../../types/attachment';
|
|
2
2
|
import type { IAttachmentHandler } from '../../types/attachmentHandler';
|
|
3
3
|
import { generateUUID } from '../../utils/imageUtils';
|
|
4
|
+
import { UPLOAD_LIMITS } from '../../config/uploadLimits';
|
|
4
5
|
|
|
5
6
|
export const ImageAttachmentHandler: IAttachmentHandler = {
|
|
6
7
|
validate(attachment: ImageAttachment) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if (attachment.sourceFile.size > UPLOAD_LIMITS.image) {
|
|
9
|
+
return {
|
|
10
|
+
valid: false,
|
|
11
|
+
reason: `Image exceeds ${UPLOAD_LIMITS.image / 1024 / 1024}MB limit`,
|
|
12
|
+
};
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
const validMimes = [
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Attachment, VideoAttachment } from '../../types/attachment';
|
|
2
2
|
import type { IAttachmentHandler } from '../../types/attachmentHandler';
|
|
3
|
+
import { UPLOAD_LIMITS } from '../../config/uploadLimits';
|
|
3
4
|
|
|
4
5
|
interface VideoPicInfo {
|
|
5
6
|
videoUUID: string;
|
|
@@ -18,7 +19,7 @@ interface VideoPicInfo {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export class VideoAttachmentHandler implements IAttachmentHandler {
|
|
21
|
-
private static readonly MAX_VIDEO_SIZE =
|
|
22
|
+
private static readonly MAX_VIDEO_SIZE = UPLOAD_LIMITS.video;
|
|
22
23
|
private static readonly SUPPORTED_TYPES = ['video/mp4', 'video/quicktime'];
|
|
23
24
|
|
|
24
25
|
validate(
|