@droppii-org/chat-mobile 0.2.23 → 0.2.24

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 (93) hide show
  1. package/lib/module/config/uploadLimits.js +13 -0
  2. package/lib/module/config/uploadLimits.js.map +1 -0
  3. package/lib/module/hooks/useChatCompose.js +142 -0
  4. package/lib/module/hooks/useChatCompose.js.map +1 -0
  5. package/lib/module/hooks/useImageAttachment.js +71 -151
  6. package/lib/module/hooks/useImageAttachment.js.map +1 -1
  7. package/lib/module/hooks/useSendAttachment.js +2 -2
  8. package/lib/module/hooks/useSendAttachment.js.map +1 -1
  9. package/lib/module/hooks/useVideoAttachment.js +4 -4
  10. package/lib/module/hooks/useVideoAttachment.js.map +1 -1
  11. package/lib/module/index.js +0 -1
  12. package/lib/module/index.js.map +1 -1
  13. package/lib/module/screens/chat-detail/ChatComposer.js +50 -185
  14. package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
  15. package/lib/module/screens/chat-detail/ChatDetail.js +16 -137
  16. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  17. package/lib/module/screens/chat-detail/index.js +0 -1
  18. package/lib/module/screens/chat-detail/index.js.map +1 -1
  19. package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js +2 -2
  20. package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js.map +1 -1
  21. package/lib/module/services/attachmentHandlers/imageAttachmentHandler.js +3 -3
  22. package/lib/module/services/attachmentHandlers/imageAttachmentHandler.js.map +1 -1
  23. package/lib/module/services/attachmentHandlers/videoAttachmentHandler.js +2 -1
  24. package/lib/module/services/attachmentHandlers/videoAttachmentHandler.js.map +1 -1
  25. package/lib/module/services/attachmentOrchestrator.js +6 -5
  26. package/lib/module/services/attachmentOrchestrator.js.map +1 -1
  27. package/lib/module/utils/imageUtils.js +3 -3
  28. package/lib/module/utils/imageUtils.js.map +1 -1
  29. package/lib/module/utils/pLimit.js +19 -0
  30. package/lib/module/utils/pLimit.js.map +1 -0
  31. package/lib/module/utils/videoThumbnail.js +8 -3
  32. package/lib/module/utils/videoThumbnail.js.map +1 -1
  33. package/lib/module/utils/videoThumbnailUpload.js +76 -0
  34. package/lib/module/utils/videoThumbnailUpload.js.map +1 -0
  35. package/lib/typescript/src/config/uploadLimits.d.ts +7 -0
  36. package/lib/typescript/src/config/uploadLimits.d.ts.map +1 -0
  37. package/lib/typescript/src/hooks/useChatCompose.d.ts +27 -0
  38. package/lib/typescript/src/hooks/useChatCompose.d.ts.map +1 -0
  39. package/lib/typescript/src/hooks/useImageAttachment.d.ts +2 -2
  40. package/lib/typescript/src/hooks/useImageAttachment.d.ts.map +1 -1
  41. package/lib/typescript/src/hooks/useSendAttachment.d.ts +1 -1
  42. package/lib/typescript/src/hooks/useSendAttachment.d.ts.map +1 -1
  43. package/lib/typescript/src/hooks/useVideoAttachment.d.ts.map +1 -1
  44. package/lib/typescript/src/index.d.ts +0 -2
  45. package/lib/typescript/src/index.d.ts.map +1 -1
  46. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts +5 -2
  47. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
  48. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts +1 -1
  49. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  50. package/lib/typescript/src/screens/chat-detail/index.d.ts +0 -2
  51. package/lib/typescript/src/screens/chat-detail/index.d.ts.map +1 -1
  52. package/lib/typescript/src/screens/chat-detail/types.d.ts +1 -35
  53. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  54. package/lib/typescript/src/services/attachmentHandlers/fileAttachmentHandler.d.ts.map +1 -1
  55. package/lib/typescript/src/services/attachmentHandlers/imageAttachmentHandler.d.ts.map +1 -1
  56. package/lib/typescript/src/services/attachmentHandlers/videoAttachmentHandler.d.ts.map +1 -1
  57. package/lib/typescript/src/services/attachmentOrchestrator.d.ts +1 -1
  58. package/lib/typescript/src/services/attachmentOrchestrator.d.ts.map +1 -1
  59. package/lib/typescript/src/utils/imageUtils.d.ts.map +1 -1
  60. package/lib/typescript/src/utils/pLimit.d.ts +6 -0
  61. package/lib/typescript/src/utils/pLimit.d.ts.map +1 -0
  62. package/lib/typescript/src/utils/videoThumbnail.d.ts.map +1 -1
  63. package/lib/typescript/src/utils/videoThumbnailUpload.d.ts +11 -0
  64. package/lib/typescript/src/utils/videoThumbnailUpload.d.ts.map +1 -0
  65. package/package.json +1 -1
  66. package/src/config/uploadLimits.ts +11 -0
  67. package/src/hooks/useChatCompose.ts +186 -0
  68. package/src/hooks/useImageAttachment.ts +110 -197
  69. package/src/hooks/useSendAttachment.ts +3 -6
  70. package/src/hooks/useVideoAttachment.ts +4 -4
  71. package/src/index.tsx +1 -5
  72. package/src/screens/chat-detail/ChatComposer.tsx +88 -240
  73. package/src/screens/chat-detail/ChatDetail.tsx +24 -195
  74. package/src/screens/chat-detail/index.ts +1 -5
  75. package/src/screens/chat-detail/types.ts +1 -38
  76. package/src/services/attachmentHandlers/fileAttachmentHandler.ts +3 -2
  77. package/src/services/attachmentHandlers/imageAttachmentHandler.ts +6 -3
  78. package/src/services/attachmentHandlers/videoAttachmentHandler.ts +2 -1
  79. package/src/services/attachmentOrchestrator.ts +6 -8
  80. package/src/utils/imageUtils.ts +3 -4
  81. package/src/utils/pLimit.ts +20 -0
  82. package/src/utils/videoThumbnail.ts +10 -3
  83. package/src/utils/videoThumbnailUpload.ts +103 -0
  84. package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js +0 -288
  85. package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js.map +0 -1
  86. package/lib/module/utils/giftedChatMessage.js +0 -90
  87. package/lib/module/utils/giftedChatMessage.js.map +0 -1
  88. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts +0 -26
  89. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts.map +0 -1
  90. package/lib/typescript/src/utils/giftedChatMessage.d.ts +0 -10
  91. package/lib/typescript/src/utils/giftedChatMessage.d.ts.map +0 -1
  92. package/src/screens/chat-detail/hooks/useAttachmentSendHandler.ts +0 -386
  93. package/src/utils/giftedChatMessage.ts +0 -137
@@ -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 { getAttachmentPanelHeight } from './constants';
21
- import type { ChatComposerProps } from './types';
22
- import { useLinkPreview } from '../../hooks/useLinkPreview/useLinkPreview';
23
- import { useImageAttachment } from '../../hooks/useImageAttachment';
24
- import { useFileAttachment } from '../../hooks/useFileAttachment';
25
- import { useSendAttachment } from '../../hooks/useSendAttachment';
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
- // Link preview
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(value as string);
57
+ } = useChatComposerState(compose.text);
130
58
 
131
- // Panel height calculation
132
59
  const panelHeight = useMemo(
133
- () =>
134
- hasAttachmentActions
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
- // Check if any attachments are currently uploading or have errors
152
- const isUploadingAttachments = useMemo(
153
- () =>
154
- selectedImages.some((img: any) => img.isUploading) ||
155
- selectedFiles.some((f) => f.isUploading || !!f.error),
156
- [selectedImages, selectedFiles]
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
- // Close attachment panel with animation when input is focused
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
- onChangeText?.(text);
91
+ compose.setText(text ?? '');
224
92
  },
225
- [onChangeText]
93
+ [compose]
226
94
  );
227
95
 
228
96
  const handleInputContentSizeChange = useCallback(
229
- (event: any) => {
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 (!value) {
248
- setIsInputWrapped(false);
249
- }
250
- }, [value, setIsInputWrapped]);
114
+ if (!compose.text) setIsInputWrapped(false);
115
+ }, [compose.text, setIsInputWrapped]);
251
116
 
252
- const handleImageAttachRef = useRef(handleImageAttach);
253
- handleImageAttachRef.current = handleImageAttach;
117
+ const addImagesRef = useRef(compose.addImages);
118
+ addImagesRef.current = compose.addImages;
254
119
  const debouncedImagePickerRef = useRef(
255
- debounce(() => handleImageAttachRef.current(), 300, {
120
+ debounce(() => addImagesRef.current?.(), 300, {
256
121
  leading: true,
257
122
  trailing: false,
258
123
  })
259
124
  );
260
125
 
261
- const handleFileAttachRef = useRef(handleFileAttach);
262
- handleFileAttachRef.current = handleFileAttach;
126
+ const addFilesRef = useRef(compose.addFiles);
127
+ addFilesRef.current = compose.addFiles;
263
128
  const debouncedFilePickerRef = useRef(
264
- debounce(() => handleFileAttachRef.current(), 300, {
129
+ debounce(() => addFilesRef.current?.(), 300, {
265
130
  leading: true,
266
131
  trailing: false,
267
132
  })
268
133
  );
269
134
 
270
- // Attachment action handler
271
- const handleAttachmentActionInternal = useCallback(
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
- onAttachmentAction?.(action);
142
+ console.log('[ChatComposer] attachment action:', action.id);
279
143
  }
280
144
  },
281
- [onAttachmentAction]
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
- switch (type) {
300
- case 'file':
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
- [handleImageRemove, handleFileRemove]
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={showQuickActions}
336
- actions={quickActions}
337
- onActionPress={onQuickActionPress}
338
- renderAction={renderQuickAction}
339
- renderQuickActions={renderQuickActions}
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={handleDismissPreview}
197
+ metadata={compose.urlMetadata}
198
+ isLoading={compose.isMetadataLoading}
199
+ onDismiss={compose.dismissPreview}
347
200
  />
348
201
  )}
349
202
 
350
203
  <AttachmentPreview
351
- visible={isImagePreviewVisible || isFilePreviewVisible}
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
- {hasAttachmentActions && (
365
- <KContainer.Touchable
366
- onPress={toggleAttachmentVisibility}
367
- center
368
- br="round"
369
- >
370
- <KImage.VectorIcons
371
- name={isAttachmentOpen ? 'close-circle-o' : 'plus-circle-o'}
372
- size={24}
373
- color={
374
- isAttachmentOpen
375
- ? KColors.palette.primary.w400
376
- : KColors.palette.gray.w600
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={value as string}
384
- placeholder={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={isUploadingAttachments ? undefined : handleSend}
397
- pointerEvents={isUploadingAttachments ? 'none' : 'auto'}
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
- isUploadingAttachments
255
+ compose.isUploading
404
256
  ? KColors.palette.gray.w400
405
257
  : KColors.palette.primary.w400
406
258
  }
407
259
  marginL="0.75rem"
408
- opacity={isUploadingAttachments ? 0.6 : 1}
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
- {hasAttachmentActions && (
420
- <Reanimated.View
421
- style={[styles.accessorySlot, accessorySlotStyle]}
422
- pointerEvents={isAttachmentOpen ? 'auto' : 'none'}
423
- >
424
- <ChatAttachmentPanel
425
- actions={attachmentActions}
426
- columns={attachmentColumns}
427
- onActionPress={handleAttachmentActionInternal}
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
  }