@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
|
@@ -17,107 +17,35 @@ import { ChatLinkPreview } from './ChatLinkPreview';
|
|
|
17
17
|
import { ChatMessageInput } from './components/ChatMessageInput';
|
|
18
18
|
import { AttachmentPreview } from '../../components/AttachmentPreview';
|
|
19
19
|
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_ATTACHMENT_ACTIONS,
|
|
22
|
+
DEFAULT_Chat_QUICK_ACTIONS,
|
|
23
|
+
getAttachmentPanelHeight,
|
|
24
|
+
} from './constants';
|
|
25
|
+
import type { DChatAttachmentAction } from './types';
|
|
26
26
|
import { useChatComposerState } from './hooks/useChatComposerState';
|
|
27
27
|
import { useChatComposerAnimation } from './hooks/useChatComposerAnimation';
|
|
28
|
-
import { useAttachmentSendHandler } from './hooks/useAttachmentSendHandler';
|
|
29
28
|
import { useChatDetailContext } from '../../context/ChatDetailContext';
|
|
30
29
|
import { trans } from '../../translation';
|
|
31
30
|
import { useRunFlow } from '../../hooks/flows/useFlow';
|
|
32
31
|
import { ReactFlowsNodeTypes } from '../../types/flows';
|
|
33
32
|
import { useAttachmentMapping } from './hooks/useAttachmentMapping';
|
|
34
33
|
import type { AttachmentType } from '../../types/attachment';
|
|
34
|
+
import { useChatCompose } from '../../hooks/useChatCompose';
|
|
35
|
+
|
|
36
|
+
interface ChatComposerInternalProps {
|
|
37
|
+
isEmptyMessage?: boolean;
|
|
38
|
+
}
|
|
35
39
|
|
|
36
40
|
export const ChatComposer = memo(
|
|
37
|
-
({
|
|
38
|
-
value,
|
|
39
|
-
placeholder = 'Nhập tin nhắn...',
|
|
40
|
-
onChangeText,
|
|
41
|
-
onSend,
|
|
42
|
-
onMessageSent,
|
|
43
|
-
onPressEmoji: _onPressEmoji,
|
|
44
|
-
showQuickActions = true,
|
|
45
|
-
quickActions,
|
|
46
|
-
attachmentActions,
|
|
47
|
-
onQuickActionPress,
|
|
48
|
-
onAttachmentAction,
|
|
49
|
-
renderQuickAction,
|
|
50
|
-
renderQuickActions,
|
|
51
|
-
renderAttachmentAction,
|
|
52
|
-
attachmentColumns,
|
|
53
|
-
isEmptyMessage = false,
|
|
54
|
-
}: ChatComposerProps) => {
|
|
41
|
+
({ isEmptyMessage = false }: ChatComposerInternalProps) => {
|
|
55
42
|
const insets = useSafeAreaInsets();
|
|
56
|
-
const hasAttachmentActions = !!attachmentActions?.length;
|
|
57
43
|
|
|
58
44
|
const { isBotConversation, conversationFlow } = useChatDetailContext();
|
|
59
45
|
const { mutate: runFlow, isPending } = useRunFlow();
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
const {
|
|
63
|
-
isVisible: showLinkPreview,
|
|
64
|
-
metadata: urlMetadata,
|
|
65
|
-
isLoading: isMetadataLoading,
|
|
66
|
-
dismiss: handleDismissPreview,
|
|
67
|
-
} = useLinkPreview(value);
|
|
68
|
-
|
|
69
|
-
// Image attachment
|
|
70
|
-
const {
|
|
71
|
-
selectedImages,
|
|
72
|
-
isImagePreviewVisible,
|
|
73
|
-
handleImageAttach,
|
|
74
|
-
handleImageRemove,
|
|
75
|
-
clearAllImages,
|
|
76
|
-
} = useImageAttachment();
|
|
77
|
-
|
|
78
|
-
// File attachment
|
|
79
|
-
const {
|
|
80
|
-
selectedFiles,
|
|
81
|
-
isFilePreviewVisible,
|
|
82
|
-
handleFileAttach,
|
|
83
|
-
handleFileRemove,
|
|
84
|
-
clearAllFiles,
|
|
85
|
-
} = useFileAttachment();
|
|
86
|
-
|
|
87
|
-
// Send attachment
|
|
88
|
-
const { send: sendAttachments } = useSendAttachment();
|
|
89
|
-
|
|
90
|
-
// Callback to send text message (with optional preview link)
|
|
91
|
-
// This is used when sending text after attachments
|
|
92
|
-
const handleSendText = useCallback(
|
|
93
|
-
(text: string, previewMetadata?: any) => {
|
|
94
|
-
// Send with the captured text and preview metadata
|
|
95
|
-
// Note: ChatDetail's handleSend will read currentInput, but for text sent
|
|
96
|
-
// after attachments, we want to use the captured text instead
|
|
97
|
-
// So we pass it via a special handling in the metadata
|
|
98
|
-
const metadataWithText = previewMetadata
|
|
99
|
-
? { ...previewMetadata, _capturedText: text }
|
|
100
|
-
: undefined;
|
|
101
|
-
onSend?.(metadataWithText);
|
|
102
|
-
},
|
|
103
|
-
[onSend]
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
// Attachment send handler
|
|
107
|
-
const { handleSend: handleAttachmentSend } = useAttachmentSendHandler({
|
|
108
|
-
selectedImages,
|
|
109
|
-
selectedFiles,
|
|
110
|
-
sendAttachments,
|
|
111
|
-
clearAllImages,
|
|
112
|
-
clearAllFiles,
|
|
113
|
-
onSend,
|
|
114
|
-
onMessageSent,
|
|
115
|
-
textMessage: (value ?? '').trim(),
|
|
116
|
-
urlMetadata: showLinkPreview ? urlMetadata : undefined,
|
|
117
|
-
onSendText: handleSendText,
|
|
118
|
-
});
|
|
47
|
+
const compose = useChatCompose();
|
|
119
48
|
|
|
120
|
-
// Composer state
|
|
121
49
|
const {
|
|
122
50
|
isAttachmentOpen,
|
|
123
51
|
setIsAttachmentOpen,
|
|
@@ -126,21 +54,13 @@ export const ChatComposer = memo(
|
|
|
126
54
|
setIsInputWrapped,
|
|
127
55
|
isMultilineInput,
|
|
128
56
|
inputRef,
|
|
129
|
-
} = useChatComposerState(
|
|
57
|
+
} = useChatComposerState(compose.text);
|
|
130
58
|
|
|
131
|
-
// Panel height calculation
|
|
132
59
|
const panelHeight = useMemo(
|
|
133
|
-
() =>
|
|
134
|
-
|
|
135
|
-
? getAttachmentPanelHeight(
|
|
136
|
-
attachmentActions.length,
|
|
137
|
-
attachmentColumns
|
|
138
|
-
)
|
|
139
|
-
: 0,
|
|
140
|
-
[attachmentActions, attachmentColumns, hasAttachmentActions]
|
|
60
|
+
() => getAttachmentPanelHeight(DEFAULT_ATTACHMENT_ACTIONS.length),
|
|
61
|
+
[]
|
|
141
62
|
);
|
|
142
63
|
|
|
143
|
-
// Animation
|
|
144
64
|
const { accessorySlotStyle, toggleAttachmentVisibility, closeAttachment } =
|
|
145
65
|
useChatComposerAnimation({
|
|
146
66
|
isAttachmentOpen,
|
|
@@ -148,70 +68,18 @@ export const ChatComposer = memo(
|
|
|
148
68
|
onAttachmentOpenChange: setIsAttachmentOpen,
|
|
149
69
|
});
|
|
150
70
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Send handler - includes attachment and preview link features
|
|
160
|
-
const handleSend = useCallback(() => {
|
|
161
|
-
const hasAttachments =
|
|
162
|
-
selectedImages.length > 0 || selectedFiles.length > 0;
|
|
163
|
-
const hasText = (value ?? '').trim().length > 0;
|
|
164
|
-
// Only send metadata if preview is CURRENTLY visible (user didn't dismiss it)
|
|
165
|
-
const previewMetadata =
|
|
166
|
-
showLinkPreview && !!urlMetadata ? urlMetadata : undefined;
|
|
167
|
-
const hasPreview = !!previewMetadata;
|
|
168
|
-
|
|
169
|
-
// Prevent sending while files are uploading
|
|
170
|
-
if (isUploadingAttachments) {
|
|
171
|
-
console.warn(
|
|
172
|
-
'[ChatComposer] Cannot send message while files are uploading'
|
|
173
|
-
);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Validate: must have at least one of: attachments, text, or preview link
|
|
178
|
-
if (!hasAttachments && !hasText && !hasPreview) {
|
|
179
|
-
console.warn(
|
|
180
|
-
'[ChatComposer] No attachments, text, or preview link to send'
|
|
181
|
-
);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (hasAttachments) {
|
|
186
|
-
// Send attachments (+ text if present, handled in attachment handler)
|
|
187
|
-
handleAttachmentSend();
|
|
188
|
-
} else {
|
|
189
|
-
// Send text/preview link only
|
|
190
|
-
console.log('[ChatComposer] handleSend - text message:', {
|
|
191
|
-
hasText,
|
|
192
|
-
hasPreview,
|
|
193
|
-
previewUrl: previewMetadata?.url,
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
onSend?.(previewMetadata);
|
|
71
|
+
const handleSend = useCallback(async () => {
|
|
72
|
+
if (compose.isUploading || !compose.canSend) return;
|
|
73
|
+
try {
|
|
74
|
+
await compose.send();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (__DEV__) console.error('[ChatComposer] Failed to send:', error);
|
|
197
77
|
}
|
|
198
|
-
}, [
|
|
199
|
-
onSend,
|
|
200
|
-
urlMetadata,
|
|
201
|
-
showLinkPreview,
|
|
202
|
-
selectedImages,
|
|
203
|
-
selectedFiles,
|
|
204
|
-
handleAttachmentSend,
|
|
205
|
-
value,
|
|
206
|
-
isUploadingAttachments,
|
|
207
|
-
]);
|
|
78
|
+
}, [compose]);
|
|
208
79
|
|
|
209
80
|
const handleInputFocus = useCallback(() => {
|
|
210
81
|
setIsInputFocused(true);
|
|
211
|
-
|
|
212
|
-
if (isAttachmentOpen) {
|
|
213
|
-
closeAttachment();
|
|
214
|
-
}
|
|
82
|
+
if (isAttachmentOpen) closeAttachment();
|
|
215
83
|
}, [closeAttachment, isAttachmentOpen, setIsInputFocused]);
|
|
216
84
|
|
|
217
85
|
const handleInputBlur = useCallback(() => {
|
|
@@ -220,13 +88,13 @@ export const ChatComposer = memo(
|
|
|
220
88
|
|
|
221
89
|
const handleChangeText = useCallback(
|
|
222
90
|
(text?: string) => {
|
|
223
|
-
|
|
91
|
+
compose.setText(text ?? '');
|
|
224
92
|
},
|
|
225
|
-
[
|
|
93
|
+
[compose]
|
|
226
94
|
);
|
|
227
95
|
|
|
228
96
|
const handleInputContentSizeChange = useCallback(
|
|
229
|
-
(event:
|
|
97
|
+
(event: { nativeEvent: { contentSize: { height: number } } }) => {
|
|
230
98
|
const { height } = event.nativeEvent.contentSize;
|
|
231
99
|
setIsInputWrapped(height > WRAPPED_HEIGHT_THRESHOLD);
|
|
232
100
|
},
|
|
@@ -242,69 +110,57 @@ export const ChatComposer = memo(
|
|
|
242
110
|
});
|
|
243
111
|
}, [runFlow, conversationFlow]);
|
|
244
112
|
|
|
245
|
-
// Reset wrapped state when value is cleared
|
|
246
113
|
useEffect(() => {
|
|
247
|
-
if (!
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
}, [value, setIsInputWrapped]);
|
|
114
|
+
if (!compose.text) setIsInputWrapped(false);
|
|
115
|
+
}, [compose.text, setIsInputWrapped]);
|
|
251
116
|
|
|
252
|
-
const
|
|
253
|
-
|
|
117
|
+
const addImagesRef = useRef(compose.addImages);
|
|
118
|
+
addImagesRef.current = compose.addImages;
|
|
254
119
|
const debouncedImagePickerRef = useRef(
|
|
255
|
-
debounce(() =>
|
|
120
|
+
debounce(() => addImagesRef.current?.(), 300, {
|
|
256
121
|
leading: true,
|
|
257
122
|
trailing: false,
|
|
258
123
|
})
|
|
259
124
|
);
|
|
260
125
|
|
|
261
|
-
const
|
|
262
|
-
|
|
126
|
+
const addFilesRef = useRef(compose.addFiles);
|
|
127
|
+
addFilesRef.current = compose.addFiles;
|
|
263
128
|
const debouncedFilePickerRef = useRef(
|
|
264
|
-
debounce(() =>
|
|
129
|
+
debounce(() => addFilesRef.current?.(), 300, {
|
|
265
130
|
leading: true,
|
|
266
131
|
trailing: false,
|
|
267
132
|
})
|
|
268
133
|
);
|
|
269
134
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
async (action: any) => {
|
|
135
|
+
const handleAttachmentAction = useCallback(
|
|
136
|
+
async (action: DChatAttachmentAction) => {
|
|
273
137
|
if (action.id === 'gallery') {
|
|
274
138
|
debouncedImagePickerRef.current();
|
|
275
139
|
} else if (action.id === 'file') {
|
|
276
140
|
debouncedFilePickerRef.current();
|
|
277
141
|
} else {
|
|
278
|
-
|
|
142
|
+
console.log('[ChatComposer] attachment action:', action.id);
|
|
279
143
|
}
|
|
280
144
|
},
|
|
281
|
-
[
|
|
145
|
+
[]
|
|
282
146
|
);
|
|
283
147
|
|
|
284
|
-
// Input row padding
|
|
285
148
|
const inputRowStyle = useMemo(
|
|
286
|
-
() => ({
|
|
287
|
-
paddingBottom: isAttachmentOpen ? 8 : insets.bottom + 12,
|
|
288
|
-
}),
|
|
149
|
+
() => ({ paddingBottom: isAttachmentOpen ? 8 : insets.bottom + 12 }),
|
|
289
150
|
[insets.bottom, isAttachmentOpen]
|
|
290
151
|
);
|
|
291
152
|
|
|
292
153
|
const attachments = useAttachmentMapping({
|
|
293
|
-
selectedImages,
|
|
294
|
-
selectedFiles,
|
|
154
|
+
selectedImages: compose.selectedImages,
|
|
155
|
+
selectedFiles: compose.selectedFiles,
|
|
295
156
|
});
|
|
296
157
|
|
|
297
158
|
const onRemove = useCallback(
|
|
298
159
|
(type: AttachmentType, data: unknown) => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return handleFileRemove(data as string);
|
|
302
|
-
|
|
303
|
-
default:
|
|
304
|
-
return handleImageRemove(data as number);
|
|
305
|
-
}
|
|
160
|
+
if (type === 'file') return compose.removeFile(data as string);
|
|
161
|
+
return compose.removeImage(data as number);
|
|
306
162
|
},
|
|
307
|
-
[
|
|
163
|
+
[compose]
|
|
308
164
|
);
|
|
309
165
|
|
|
310
166
|
if (
|
|
@@ -318,10 +174,7 @@ export const ChatComposer = memo(
|
|
|
318
174
|
size="md"
|
|
319
175
|
label={trans('start')}
|
|
320
176
|
stretch
|
|
321
|
-
icon={{
|
|
322
|
-
vectorName: 'chat-square-o',
|
|
323
|
-
size: 20,
|
|
324
|
-
}}
|
|
177
|
+
icon={{ vectorName: 'chat-square-o', size: 20 }}
|
|
325
178
|
loading={isPending}
|
|
326
179
|
onPress={onStartConversationFlow}
|
|
327
180
|
/>
|
|
@@ -332,23 +185,25 @@ export const ChatComposer = memo(
|
|
|
332
185
|
return (
|
|
333
186
|
<KContainer.View background={'rgba(131, 137, 157, 0.05)'}>
|
|
334
187
|
<ChatQuickActions
|
|
335
|
-
visible
|
|
336
|
-
actions={
|
|
337
|
-
onActionPress={
|
|
338
|
-
|
|
339
|
-
|
|
188
|
+
visible
|
|
189
|
+
actions={DEFAULT_Chat_QUICK_ACTIONS}
|
|
190
|
+
onActionPress={(action) =>
|
|
191
|
+
console.log('[ChatComposer] quick action:', action.id)
|
|
192
|
+
}
|
|
340
193
|
/>
|
|
341
194
|
|
|
342
|
-
{showLinkPreview && (
|
|
195
|
+
{compose.showLinkPreview && (
|
|
343
196
|
<ChatLinkPreview
|
|
344
|
-
metadata={urlMetadata}
|
|
345
|
-
isLoading={isMetadataLoading}
|
|
346
|
-
onDismiss={
|
|
197
|
+
metadata={compose.urlMetadata}
|
|
198
|
+
isLoading={compose.isMetadataLoading}
|
|
199
|
+
onDismiss={compose.dismissPreview}
|
|
347
200
|
/>
|
|
348
201
|
)}
|
|
349
202
|
|
|
350
203
|
<AttachmentPreview
|
|
351
|
-
visible={
|
|
204
|
+
visible={
|
|
205
|
+
compose.isImagePreviewVisible || compose.isFilePreviewVisible
|
|
206
|
+
}
|
|
352
207
|
attachments={attachments}
|
|
353
208
|
onRemove={onRemove}
|
|
354
209
|
/>
|
|
@@ -361,51 +216,48 @@ export const ChatComposer = memo(
|
|
|
361
216
|
paddingB="0.75rem"
|
|
362
217
|
style={inputRowStyle}
|
|
363
218
|
>
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
</KContainer.Touchable>
|
|
380
|
-
)}
|
|
219
|
+
<KContainer.Touchable
|
|
220
|
+
onPress={toggleAttachmentVisibility}
|
|
221
|
+
center
|
|
222
|
+
br="round"
|
|
223
|
+
>
|
|
224
|
+
<KImage.VectorIcons
|
|
225
|
+
name={isAttachmentOpen ? 'close-circle-o' : 'plus-circle-o'}
|
|
226
|
+
size={24}
|
|
227
|
+
color={
|
|
228
|
+
isAttachmentOpen
|
|
229
|
+
? KColors.palette.primary.w400
|
|
230
|
+
: KColors.palette.gray.w600
|
|
231
|
+
}
|
|
232
|
+
/>
|
|
233
|
+
</KContainer.Touchable>
|
|
381
234
|
|
|
382
235
|
<ChatMessageInput
|
|
383
|
-
value={
|
|
384
|
-
placeholder=
|
|
236
|
+
value={compose.text}
|
|
237
|
+
placeholder="Nhập tin nhắn..."
|
|
385
238
|
onChangeText={handleChangeText}
|
|
386
239
|
onFocus={handleInputFocus}
|
|
387
240
|
onBlur={handleInputBlur}
|
|
388
241
|
onContentSizeChange={handleInputContentSizeChange}
|
|
389
242
|
isInputFocused={isInputFocused}
|
|
390
243
|
isMultilineInput={isMultilineInput}
|
|
391
|
-
// onEmojiPress={onPressEmoji}
|
|
392
244
|
inputRef={inputRef}
|
|
393
245
|
/>
|
|
394
246
|
|
|
395
247
|
<KContainer.Touchable
|
|
396
|
-
onPress={
|
|
397
|
-
pointerEvents={
|
|
248
|
+
onPress={compose.isUploading ? undefined : handleSend}
|
|
249
|
+
pointerEvents={compose.isUploading ? 'none' : 'auto'}
|
|
398
250
|
width={40}
|
|
399
251
|
height={40}
|
|
400
252
|
center
|
|
401
253
|
br="round"
|
|
402
254
|
background={
|
|
403
|
-
|
|
255
|
+
compose.isUploading
|
|
404
256
|
? KColors.palette.gray.w400
|
|
405
257
|
: KColors.palette.primary.w400
|
|
406
258
|
}
|
|
407
259
|
marginL="0.75rem"
|
|
408
|
-
opacity={
|
|
260
|
+
opacity={compose.isUploading ? 0.6 : 1}
|
|
409
261
|
>
|
|
410
262
|
<KImage.VectorIcons
|
|
411
263
|
name="send"
|
|
@@ -416,19 +268,15 @@ export const ChatComposer = memo(
|
|
|
416
268
|
</KContainer.Touchable>
|
|
417
269
|
</KContainer.View>
|
|
418
270
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
renderAction={renderAttachmentAction}
|
|
429
|
-
/>
|
|
430
|
-
</Reanimated.View>
|
|
431
|
-
)}
|
|
271
|
+
<Reanimated.View
|
|
272
|
+
style={[styles.accessorySlot, accessorySlotStyle]}
|
|
273
|
+
pointerEvents={isAttachmentOpen ? 'auto' : 'none'}
|
|
274
|
+
>
|
|
275
|
+
<ChatAttachmentPanel
|
|
276
|
+
actions={DEFAULT_ATTACHMENT_ACTIONS}
|
|
277
|
+
onActionPress={handleAttachmentAction}
|
|
278
|
+
/>
|
|
279
|
+
</Reanimated.View>
|
|
432
280
|
</KContainer.View>
|
|
433
281
|
);
|
|
434
282
|
}
|