@droppii-org/chat-mobile 0.2.17 → 0.2.18

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 (96) hide show
  1. package/lib/module/assets/images/icon_excel.png +0 -0
  2. package/lib/module/assets/images/icon_img.png +0 -0
  3. package/lib/module/assets/images/icon_pdf.png +0 -0
  4. package/lib/module/assets/images/icon_txt.png +0 -0
  5. package/lib/module/assets/images/icon_word.png +0 -0
  6. package/lib/module/assets/images/index.js +5 -0
  7. package/lib/module/assets/images/index.js.map +1 -1
  8. package/lib/module/components/AttachmentPreview/FilePreview.js +107 -0
  9. package/lib/module/components/AttachmentPreview/FilePreview.js.map +1 -0
  10. package/lib/module/components/AttachmentPreview/MediaPreview.js +212 -0
  11. package/lib/module/components/AttachmentPreview/MediaPreview.js.map +1 -0
  12. package/lib/module/components/AttachmentPreview/index.js +49 -0
  13. package/lib/module/components/AttachmentPreview/index.js.map +1 -0
  14. package/lib/module/components/messages/fileMessage/index.js +122 -12
  15. package/lib/module/components/messages/fileMessage/index.js.map +1 -1
  16. package/lib/module/hooks/useFileAttachment.js +116 -0
  17. package/lib/module/hooks/useFileAttachment.js.map +1 -0
  18. package/lib/module/hooks/useFileDownload.js +175 -0
  19. package/lib/module/hooks/useFileDownload.js.map +1 -0
  20. package/lib/module/index.js +1 -1
  21. package/lib/module/index.js.map +1 -1
  22. package/lib/module/screens/chat-detail/ChatComposer.js +44 -36
  23. package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
  24. package/lib/module/screens/chat-detail/hooks/useAttachmentMapping.js +51 -0
  25. package/lib/module/screens/chat-detail/hooks/useAttachmentMapping.js.map +1 -0
  26. package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js +39 -13
  27. package/lib/module/screens/chat-detail/hooks/useAttachmentSendHandler.js.map +1 -1
  28. package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js +6 -6
  29. package/lib/module/services/attachmentHandlers/fileAttachmentHandler.js.map +1 -1
  30. package/lib/module/services/attachmentHandlers/index.js +1 -1
  31. package/lib/module/services/attachmentHandlers/index.js.map +1 -1
  32. package/lib/module/translation/resources/i18n.js +9 -0
  33. package/lib/module/translation/resources/i18n.js.map +1 -1
  34. package/lib/module/utils/device.js +32 -0
  35. package/lib/module/utils/device.js.map +1 -1
  36. package/lib/module/utils/imageUtils.js +44 -28
  37. package/lib/module/utils/imageUtils.js.map +1 -1
  38. package/lib/typescript/src/assets/images/index.d.ts +5 -0
  39. package/lib/typescript/src/assets/images/index.d.ts.map +1 -1
  40. package/lib/typescript/src/components/AttachmentPreview/FilePreview.d.ts +6 -0
  41. package/lib/typescript/src/components/AttachmentPreview/FilePreview.d.ts.map +1 -0
  42. package/lib/typescript/src/components/AttachmentPreview/MediaPreview.d.ts +9 -0
  43. package/lib/typescript/src/components/AttachmentPreview/MediaPreview.d.ts.map +1 -0
  44. package/lib/typescript/src/components/AttachmentPreview/index.d.ts +9 -0
  45. package/lib/typescript/src/components/AttachmentPreview/index.d.ts.map +1 -0
  46. package/lib/typescript/src/components/messages/fileMessage/index.d.ts.map +1 -1
  47. package/lib/typescript/src/hooks/useFileAttachment.d.ts +20 -0
  48. package/lib/typescript/src/hooks/useFileAttachment.d.ts.map +1 -0
  49. package/lib/typescript/src/hooks/useFileDownload.d.ts +15 -0
  50. package/lib/typescript/src/hooks/useFileDownload.d.ts.map +1 -0
  51. package/lib/typescript/src/hooks/useImageAttachment.d.ts +1 -2
  52. package/lib/typescript/src/hooks/useImageAttachment.d.ts.map +1 -1
  53. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
  54. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentMapping.d.ts +10 -0
  55. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentMapping.d.ts.map +1 -0
  56. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts +4 -1
  57. package/lib/typescript/src/screens/chat-detail/hooks/useAttachmentSendHandler.d.ts.map +1 -1
  58. package/lib/typescript/src/services/attachmentHandlers/fileAttachmentHandler.d.ts +2 -2
  59. package/lib/typescript/src/services/attachmentHandlers/fileAttachmentHandler.d.ts.map +1 -1
  60. package/lib/typescript/src/services/attachmentHandlers/index.d.ts +1 -1
  61. package/lib/typescript/src/services/attachmentHandlers/index.d.ts.map +1 -1
  62. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  63. package/lib/typescript/src/types/attachment.d.ts +22 -1
  64. package/lib/typescript/src/types/attachment.d.ts.map +1 -1
  65. package/lib/typescript/src/utils/device.d.ts +7 -0
  66. package/lib/typescript/src/utils/device.d.ts.map +1 -1
  67. package/lib/typescript/src/utils/imageUtils.d.ts +1 -0
  68. package/lib/typescript/src/utils/imageUtils.d.ts.map +1 -1
  69. package/package.json +5 -1
  70. package/src/assets/images/icon_excel.png +0 -0
  71. package/src/assets/images/icon_img.png +0 -0
  72. package/src/assets/images/icon_pdf.png +0 -0
  73. package/src/assets/images/icon_txt.png +0 -0
  74. package/src/assets/images/icon_word.png +0 -0
  75. package/src/assets/images/index.ts +5 -0
  76. package/src/components/AttachmentPreview/FilePreview.tsx +137 -0
  77. package/src/components/AttachmentPreview/MediaPreview.tsx +238 -0
  78. package/src/components/AttachmentPreview/index.tsx +68 -0
  79. package/src/components/messages/fileMessage/index.tsx +156 -13
  80. package/src/hooks/useFileAttachment.ts +163 -0
  81. package/src/hooks/useFileDownload.ts +200 -0
  82. package/src/hooks/useImageAttachment.ts +1 -1
  83. package/src/screens/chat-detail/ChatComposer.tsx +61 -30
  84. package/src/screens/chat-detail/hooks/useAttachmentMapping.ts +58 -0
  85. package/src/screens/chat-detail/hooks/useAttachmentSendHandler.ts +50 -11
  86. package/src/services/attachmentHandlers/fileAttachmentHandler.ts +8 -7
  87. package/src/services/attachmentHandlers/index.ts +4 -1
  88. package/src/translation/resources/i18n.ts +9 -0
  89. package/src/types/attachment.ts +23 -1
  90. package/src/utils/device.ts +58 -0
  91. package/src/utils/imageUtils.ts +50 -28
  92. package/lib/module/components/AttachmentPreview.js +0 -252
  93. package/lib/module/components/AttachmentPreview.js.map +0 -1
  94. package/lib/typescript/src/components/AttachmentPreview.d.ts +0 -28
  95. package/lib/typescript/src/components/AttachmentPreview.d.ts.map +0 -1
  96. package/src/components/AttachmentPreview.tsx +0 -310
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AA4BA,wBAEE"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../../../src/translation/resources/i18n.ts"],"names":[],"mappings":";;;AAqCA,wBAEE"}
@@ -1,4 +1,4 @@
1
- export type AttachmentType = 'image' | 'video' | 'file' | 'audio';
1
+ export type AttachmentType = 'image' | 'video' | 'file' | 'audio' | 'document';
2
2
  export interface BaseAttachment {
3
3
  id: string;
4
4
  type: AttachmentType;
@@ -69,4 +69,25 @@ export interface AttachmentSendResult {
69
69
  mergedMessageId?: string;
70
70
  errors: Record<string, string>;
71
71
  }
72
+ interface AttachmentMetadata {
73
+ id?: string;
74
+ path: string;
75
+ filename?: string;
76
+ size?: number;
77
+ duration?: number;
78
+ mimeType?: string;
79
+ width?: number;
80
+ height?: number;
81
+ uri?: string;
82
+ }
83
+ export interface AttachmentItem {
84
+ metadata: AttachmentMetadata;
85
+ uploadProgress: number;
86
+ error: string | null;
87
+ isUploading: boolean;
88
+ uploadedUrl?: string;
89
+ thumbnailUrl?: string;
90
+ type: AttachmentType;
91
+ }
92
+ export {};
72
93
  //# sourceMappingURL=attachment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../../../src/types/attachment.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;KACnD,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE;YACV,GAAG,EAAE,MAAM,CAAC;YACZ,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,IAAI,CAAC,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,UAAU,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,CAAC;KACjE,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,eAAe,GACf,cAAc,GACd,eAAe,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAC;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC"}
1
+ {"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../../../src/types/attachment.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,13 @@
1
+ export interface PickedFile {
2
+ uri: string;
3
+ name: string;
4
+ size: number;
5
+ mimeType: string;
6
+ }
1
7
  declare const DeviceUtils: {
2
8
  openImagePicker: (multiple?: boolean) => Promise<(import("react-native-image-crop-picker").Image & any[]) | (import("react-native-image-crop-picker").Video & any[]) | import("react-native-image-crop-picker").ImageOrVideo[]>;
3
9
  openVideoPicker: (multiple?: boolean) => Promise<(import("react-native-image-crop-picker").Video & any[]) | import("react-native-image-crop-picker").Video[]>;
10
+ openFilePicker: (multiple?: boolean) => Promise<PickedFile[] | null>;
4
11
  };
5
12
  export default DeviceUtils;
6
13
  export { DeviceUtils };
@@ -1 +1 @@
1
- {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../../src/utils/device.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,WAAW;iCACmB,OAAO;iCAmCP,OAAO;CAgC1C,CAAC;AAEF,eAAe,WAAW,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../../src/utils/device.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,WAAW;iCACmB,OAAO;iCAmCP,OAAO;gCAkC7B,OAAO,KAChB,OAAO,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC;CAyChC,CAAC;AAEF,eAAe,WAAW,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -3,6 +3,7 @@ export declare const generateUUID: () => string;
3
3
  export declare const isVideoFile: (filename: string | undefined) => boolean;
4
4
  export declare const isVideoFromPicker: (pickedItem: any) => boolean;
5
5
  export declare const getMimeType: (fileName: string) => string;
6
+ export declare const getFileIcon: (mimeType?: string) => number;
6
7
  export declare const formatFileSize: (bytes: number) => string;
7
8
  export declare const validateImageFile: (file: ImageFile) => string | null;
8
9
  export declare const getImageUploadEndpoint: (baseUrl: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"imageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/imageUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,eAAO,MAAM,YAAY,QAAO,MAE/B,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,GAAG,SAAS,KAAG,OAI1D,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,YAAY,GAAG,KAAG,OAInD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,MA+B9C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAM9C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,SAAS,KAAG,MAAM,GAAG,IAmB5D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,KAAG,MAExD,CAAC"}
1
+ {"version":3,"file":"imageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/imageUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,eAAO,MAAM,YAAY,QAAO,MAE/B,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,GAAG,SAAS,KAAG,OAI1D,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAAI,YAAY,GAAG,KAAG,OAInD,CAAC;AA+BF,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,MAG9C,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,KAAG,MAkB/C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAM9C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,SAAS,KAAG,MAAM,GAAG,IAmB5D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,SAAS,MAAM,KAAG,MAExD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-mobile",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Droppii chat mobile",
5
5
  "keywords": [
6
6
  "react-native",
@@ -85,6 +85,7 @@
85
85
  "@eslint/js": "^10.0.1",
86
86
  "@growthbook/growthbook-react": "*",
87
87
  "@jest/globals": "^30.0.0",
88
+ "@react-native-documents/picker": "^12.0.1",
88
89
  "@react-native/babel-preset": "0.85.0",
89
90
  "@react-native/eslint-config": "0.85.0",
90
91
  "@react-native/jest-preset": "0.85.0",
@@ -112,6 +113,7 @@
112
113
  "react-native-builder-bob": "^0.41.0",
113
114
  "react-native-create-thumbnail": "^2.2.0",
114
115
  "react-native-device-info": "*",
116
+ "react-native-file-viewer": "^2.1.5",
115
117
  "react-native-gesture-handler": "^3.0.0",
116
118
  "react-native-image-crop-picker": "^0.51.1",
117
119
  "react-native-keyboard-controller": "1.19.0",
@@ -134,11 +136,13 @@
134
136
  },
135
137
  "peerDependencies": {
136
138
  "@droppii/libs": "*",
139
+ "@react-native-documents/picker": "*",
137
140
  "@tanstack/react-query": "*",
138
141
  "react": "*",
139
142
  "react-native": "*",
140
143
  "react-native-blob-util": "*",
141
144
  "react-native-create-thumbnail": "*",
145
+ "react-native-file-viewer": "*",
142
146
  "react-native-gesture-handler": "*",
143
147
  "react-native-gifted-chat": "*",
144
148
  "react-native-image-crop-picker": "*",
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,5 +1,10 @@
1
1
  const Images = {
2
2
  ICON_BOT: require('./icon_bot.png'),
3
+ ICON_EXCEL: require('./icon_excel.png'),
4
+ ICON_IMG: require('./icon_img.png'),
5
+ ICON_PDF: require('./icon_pdf.png'),
6
+ ICON_TXT: require('./icon_txt.png'),
7
+ ICON_WORD: require('./icon_word.png'),
3
8
  TAG_BOT: require('./tag_bot.png'),
4
9
  TAG_MALL: require('./tag_mall.png'),
5
10
  ICON_DROPPII: require('./icon_droppii.png'),
@@ -0,0 +1,137 @@
1
+ import { memo, useCallback } from 'react';
2
+ import { ActivityIndicator, StyleSheet } from 'react-native';
3
+ import { KContainer, KImage, KLabel, KColors } from '@droppii/libs';
4
+ import FileViewer from 'react-native-file-viewer';
5
+ import UIUtils from '../../utils/ui';
6
+ import { trans } from '../../translation';
7
+ import { formatFileSize, getFileIcon } from '../../utils/imageUtils';
8
+ import type { AttachmentItem } from '../../types/attachment';
9
+
10
+ export const FilePreview = memo(
11
+ ({
12
+ file,
13
+ onRemove,
14
+ }: {
15
+ file: AttachmentItem;
16
+ onRemove: (id: string) => void;
17
+ }) => {
18
+ const handlePress = useCallback(async () => {
19
+ if (file.isUploading || file.error) return;
20
+ try {
21
+ const path = file.metadata.uri?.startsWith('file://')
22
+ ? file.metadata.uri.slice(7)
23
+ : file.metadata.uri;
24
+ await FileViewer.open(path ?? '', {
25
+ showOpenWithDialog: true,
26
+ showAppsSuggestions: true,
27
+ });
28
+ } catch {
29
+ UIUtils.toast.open({
30
+ title: trans('chat:file_preview_unsupported'),
31
+ theme: 'warning',
32
+ });
33
+ }
34
+ }, [file]);
35
+
36
+ const handleRemove = useCallback(() => {
37
+ onRemove(file.metadata.id ?? '');
38
+ }, [file.metadata?.id, onRemove]);
39
+
40
+ const iconSource = getFileIcon(file.metadata.mimeType);
41
+ const hasError = !!file.error;
42
+
43
+ return (
44
+ <KContainer.Touchable
45
+ row
46
+ alignItems
47
+ width={160}
48
+ onPress={handlePress}
49
+ br="3x"
50
+ background={
51
+ !hasError
52
+ ? KColors.hexToRgba(KColors.palette.gray.w400, 0.1)
53
+ : KColors.hexToRgba(KColors.danger.light, 0.2)
54
+ }
55
+ paddingL={'0.5rem'}
56
+ paddingR={'1rem'}
57
+ paddingV={'0.25rem'}
58
+ >
59
+ {/* File icon */}
60
+ <KContainer.VisibleView visible={file.isUploading}>
61
+ <ActivityIndicator
62
+ size="small"
63
+ color={KColors.palette.primary.w400}
64
+ style={styles.loader}
65
+ />
66
+ </KContainer.VisibleView>
67
+ <KContainer.VisibleView visible={!file.isUploading}>
68
+ <KImage.Base
69
+ uri={iconSource}
70
+ style={styles.icon}
71
+ resizeMode="contain"
72
+ />
73
+ </KContainer.VisibleView>
74
+
75
+ {/* File info */}
76
+ <KContainer.View flex>
77
+ <KLabel.Text
78
+ typo="TextSmMedium"
79
+ color={KColors.gray.dark}
80
+ numberOfLines={1}
81
+ ellipsizeMode="middle"
82
+ >
83
+ {file.metadata.filename}
84
+ </KLabel.Text>
85
+ <KLabel.Text
86
+ typo="TextXsNormal"
87
+ color={KColors.palette.gray.w500}
88
+ numberOfLines={1}
89
+ >
90
+ {hasError
91
+ ? file.error
92
+ : file.isUploading
93
+ ? `${file.uploadProgress}%`
94
+ : formatFileSize(file.metadata.size ?? 0)}
95
+ </KLabel.Text>
96
+ </KContainer.View>
97
+
98
+ {/* Remove button */}
99
+ <KContainer.Touchable
100
+ onPress={handleRemove}
101
+ center
102
+ width={20}
103
+ height={20}
104
+ br={'round'}
105
+ background={KColors.gray.dark}
106
+ hitSlop={8}
107
+ style={styles.removeBtn}
108
+ >
109
+ <KImage.VectorIcons
110
+ name="close"
111
+ provider="MaterialCommunityIcons"
112
+ size={18}
113
+ color={KColors.white}
114
+ />
115
+ </KContainer.Touchable>
116
+ </KContainer.Touchable>
117
+ );
118
+ }
119
+ );
120
+
121
+ FilePreview.displayName = 'FilePreview';
122
+
123
+ const styles = StyleSheet.create({
124
+ icon: {
125
+ width: 20,
126
+ height: 20,
127
+ marginRight: 7,
128
+ },
129
+ loader: {
130
+ marginRight: 8,
131
+ },
132
+ removeBtn: {
133
+ position: 'absolute',
134
+ right: -4,
135
+ top: -4,
136
+ },
137
+ });
@@ -0,0 +1,238 @@
1
+ import { memo } from 'react';
2
+ import { KColors, KContainer, KImage, KLabel } from '@droppii/libs';
3
+ import type { AttachmentItem, AttachmentType } from '../../types/attachment';
4
+ import { StyleSheet } from 'react-native';
5
+
6
+ type Props = {
7
+ item: AttachmentItem;
8
+ index: number;
9
+ onRemove(type: AttachmentType, index: number): void;
10
+ };
11
+
12
+ const formatDuration = (seconds: number): string => {
13
+ const totalSecs = Math.floor(seconds);
14
+ const mins = Math.floor(totalSecs / 60);
15
+ const secs = totalSecs % 60;
16
+ return `${mins.toString().padStart(2, '0')}:${secs
17
+ .toString()
18
+ .padStart(2, '0')}`;
19
+ };
20
+
21
+ const getAttachmentIcon = (type: AttachmentType): string => {
22
+ switch (type) {
23
+ case 'image':
24
+ return 'image';
25
+ case 'video':
26
+ return 'play-circle';
27
+ case 'audio':
28
+ return 'music';
29
+ case 'document':
30
+ return 'file-document';
31
+ case 'file':
32
+ default:
33
+ return 'file';
34
+ }
35
+ };
36
+
37
+ export const MediaPreview = memo(({ item, index, onRemove }: Props) => {
38
+ const { type, metadata, uploadProgress, error, isUploading, thumbnailUrl } =
39
+ item;
40
+
41
+ const isImage = type === 'image';
42
+ const isVideo = type === 'video';
43
+ const hasPreview = isImage || isVideo;
44
+
45
+ return (
46
+ <KContainer.View>
47
+ <KContainer.View style={styles.thumbnail} center>
48
+ {/* Video thumbnail */}
49
+ {isVideo && thumbnailUrl && (
50
+ <KImage.Base
51
+ uri={thumbnailUrl}
52
+ width={48}
53
+ height={48}
54
+ resizeMode="cover"
55
+ />
56
+ )}
57
+
58
+ {/* Video placeholder (no thumbnail yet) */}
59
+ {isVideo && !thumbnailUrl && (
60
+ <KContainer.View style={[styles.videoBg, styles.videoThumbnail]} />
61
+ )}
62
+
63
+ {/* Image preview */}
64
+ {isImage && (
65
+ <KImage.Base uri={`file://${metadata.path}`} width={48} height={48} />
66
+ )}
67
+
68
+ {/* Show icon overlay for non-media files */}
69
+ {!hasPreview && (
70
+ <KContainer.View
71
+ style={styles.iconOverlay}
72
+ center
73
+ background={KColors.palette.gray.w100}
74
+ >
75
+ <KImage.VectorIcons
76
+ name={getAttachmentIcon(type)}
77
+ provider="MaterialCommunityIcons"
78
+ size={24}
79
+ color={KColors.palette.primary.w400}
80
+ />
81
+ </KContainer.View>
82
+ )}
83
+
84
+ {/* Video duration badge */}
85
+ {isVideo && !!metadata.duration && (
86
+ <KContainer.View style={styles.durationBadge} center>
87
+ <KLabel.Text
88
+ typo="TextXsNormal"
89
+ color={KColors.white}
90
+ style={styles.durationText}
91
+ >
92
+ {formatDuration(metadata.duration / 1000)}
93
+ </KLabel.Text>
94
+ </KContainer.View>
95
+ )}
96
+
97
+ {/* Type icon for non-preview items */}
98
+ {!hasPreview && (
99
+ <KContainer.View style={styles.typeIcon} center>
100
+ <KImage.VectorIcons
101
+ name={getAttachmentIcon(type)}
102
+ provider="MaterialCommunityIcons"
103
+ size={14}
104
+ color={KColors.white}
105
+ />
106
+ </KContainer.View>
107
+ )}
108
+
109
+ {/* Error state */}
110
+ {error && (
111
+ <KContainer.View style={styles.errorOverlay} center>
112
+ <KImage.VectorIcons
113
+ name="close-circle"
114
+ provider="MaterialCommunityIcons"
115
+ size={28}
116
+ color={KColors.white}
117
+ />
118
+ </KContainer.View>
119
+ )}
120
+
121
+ {/* Progress overlay */}
122
+ {isUploading && (
123
+ <KContainer.View style={styles.progressOverlay} center>
124
+ <KLabel.Text typo="TextSmNormal" color={KColors.white}>
125
+ {uploadProgress}%
126
+ </KLabel.Text>
127
+ </KContainer.View>
128
+ )}
129
+ </KContainer.View>
130
+ {/* Remove button */}
131
+ <KContainer.Touchable
132
+ style={styles.removeButton}
133
+ center
134
+ br="round"
135
+ background={KColors.black}
136
+ onPress={() => onRemove(type, index)}
137
+ disabled={isUploading}
138
+ hitSlop={10}
139
+ >
140
+ <KImage.VectorIcons
141
+ name="close"
142
+ provider="MaterialCommunityIcons"
143
+ size={18}
144
+ color={KColors.white}
145
+ />
146
+ </KContainer.Touchable>
147
+ </KContainer.View>
148
+ );
149
+ });
150
+
151
+ MediaPreview.displayName = 'MediaPreview';
152
+
153
+ const styles = StyleSheet.create({
154
+ thumbnail: {
155
+ position: 'relative',
156
+ width: 48,
157
+ height: 48,
158
+ borderRadius: 4,
159
+ overflow: 'hidden',
160
+ backgroundColor: KColors.palette.gray.w50,
161
+ },
162
+ durationBadge: {
163
+ position: 'absolute',
164
+ bottom: 4,
165
+ right: 4,
166
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
167
+ borderRadius: 3,
168
+ paddingVertical: 2,
169
+ paddingHorizontal: 4,
170
+ },
171
+ durationText: {
172
+ fontSize: 11,
173
+ fontWeight: '600',
174
+ },
175
+ iconOverlay: {
176
+ width: 48,
177
+ height: 48,
178
+ borderRadius: 4,
179
+ },
180
+ videoIcon: {
181
+ position: 'absolute',
182
+ top: 2,
183
+ right: 2,
184
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
185
+ borderRadius: 8,
186
+ width: 20,
187
+ height: 20,
188
+ },
189
+ typeIcon: {
190
+ position: 'absolute',
191
+ bottom: 2,
192
+ right: 2,
193
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
194
+ borderRadius: 6,
195
+ width: 16,
196
+ height: 16,
197
+ },
198
+ videoBg: {
199
+ width: 48,
200
+ height: 48,
201
+ borderRadius: 4,
202
+ },
203
+ videoThumbnail: {
204
+ backgroundColor: KColors.black,
205
+ },
206
+ progressOverlay: {
207
+ position: 'absolute',
208
+ top: 0,
209
+ left: 0,
210
+ right: 0,
211
+ bottom: 0,
212
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
213
+ },
214
+ errorOverlay: {
215
+ position: 'absolute',
216
+ top: 0,
217
+ left: 0,
218
+ right: 0,
219
+ bottom: 0,
220
+ backgroundColor: 'rgba(255, 59, 48, 0.8)',
221
+ },
222
+ removeButton: {
223
+ position: 'absolute',
224
+ right: -4,
225
+ top: -4,
226
+ width: 22,
227
+ height: 22,
228
+ shadowColor: '#000',
229
+ shadowOffset: { width: 0, height: 1 },
230
+ shadowOpacity: 0.2,
231
+ shadowRadius: 2,
232
+ elevation: 3,
233
+ },
234
+ sendButton: {
235
+ width: 48,
236
+ height: 48,
237
+ },
238
+ });
@@ -0,0 +1,68 @@
1
+ import { memo, useCallback } from 'react';
2
+ import { ScrollView, StyleSheet } from 'react-native';
3
+ import type { AttachmentItem, AttachmentType } from '../../types/attachment';
4
+ import { MediaPreview } from './MediaPreview';
5
+ import { FilePreview } from './FilePreview';
6
+
7
+ interface AttachmentPreviewProps {
8
+ visible: boolean;
9
+ attachments?: Array<AttachmentItem>;
10
+ onRemove: (type: AttachmentType, data: unknown) => void;
11
+ }
12
+
13
+ export const AttachmentPreview = memo(
14
+ ({ visible, attachments, onRemove }: AttachmentPreviewProps) => {
15
+ const onFileRemove = useCallback(
16
+ (id: string) => {
17
+ onRemove('file', id);
18
+ },
19
+ [onRemove]
20
+ );
21
+
22
+ if (!visible || !attachments?.length) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <ScrollView
28
+ horizontal
29
+ showsHorizontalScrollIndicator={false}
30
+ scrollEventThrottle={16}
31
+ contentContainerStyle={styles.scrollContent}
32
+ >
33
+ {attachments?.map((item, index) => {
34
+ switch (item.type) {
35
+ case 'file':
36
+ return (
37
+ <FilePreview
38
+ key={`${item.type}-${index}`}
39
+ file={item}
40
+ onRemove={onFileRemove}
41
+ />
42
+ );
43
+
44
+ default:
45
+ return (
46
+ <MediaPreview
47
+ key={`${item.type}-${index}`}
48
+ index={index}
49
+ item={item}
50
+ onRemove={onRemove}
51
+ />
52
+ );
53
+ }
54
+ })}
55
+ </ScrollView>
56
+ );
57
+ }
58
+ );
59
+
60
+ AttachmentPreview.displayName = 'AttachmentPreview';
61
+
62
+ const styles = StyleSheet.create({
63
+ scrollContent: {
64
+ padding: 8,
65
+ paddingTop: 12,
66
+ gap: 8,
67
+ },
68
+ });