@oxyhq/services 22.6.1 → 22.6.3
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/commonjs/ui/components/fileManagement/FileViewer.js +99 -77
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +33 -40
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js +92 -88
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +169 -310
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/FileListSection.js +17 -14
- package/lib/commonjs/ui/screens/fileManagement/FileListSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +16 -20
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/UploadBar.js +29 -12
- package/lib/commonjs/ui/screens/fileManagement/UploadBar.js.map +1 -1
- package/lib/commonjs/ui/server.js +1 -1
- package/lib/commonjs/ui/server.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileViewer.js +100 -78
- package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/module/ui/components/fileManagement/UploadPreview.js +34 -41
- package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js +94 -90
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +171 -313
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/FileListSection.js +17 -14
- package/lib/module/ui/screens/fileManagement/FileListSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +17 -21
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/UploadBar.js +30 -13
- package/lib/module/ui/screens/fileManagement/UploadBar.js.map +1 -1
- package/lib/module/ui/server.js +1 -1
- package/lib/module/ui/server.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/FileViewer.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +2 -2
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/FileListSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/UploadBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/server.d.ts +1 -1
- package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/FileViewer.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +2 -2
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/FileListSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/UploadBar.d.ts.map +1 -1
- package/lib/typescript/module/ui/server.d.ts +1 -1
- package/lib/typescript/module/ui/server.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ui/components/fileManagement/FileViewer.tsx +82 -68
- package/src/ui/components/fileManagement/UploadPreview.tsx +34 -29
- package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +14 -12
- package/src/ui/screens/FileManagementScreen.tsx +123 -300
- package/src/ui/screens/fileManagement/FileListSection.tsx +10 -10
- package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +16 -19
- package/src/ui/screens/fileManagement/UploadBar.tsx +29 -14
- package/src/ui/server.ts +1 -1
- package/lib/commonjs/ui/components/fileManagement/styles.js +0 -832
- package/lib/commonjs/ui/components/fileManagement/styles.js.map +0 -1
- package/lib/module/ui/components/fileManagement/styles.js +0 -828
- package/lib/module/ui/components/fileManagement/styles.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts +0 -825
- package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/fileManagement/styles.d.ts +0 -825
- package/lib/typescript/module/ui/components/fileManagement/styles.d.ts.map +0 -1
- package/src/ui/components/fileManagement/styles.ts +0 -823
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Animated,
|
|
13
13
|
Easing,
|
|
14
14
|
AccessibilityInfo,
|
|
15
|
+
useWindowDimensions,
|
|
15
16
|
} from 'react-native';
|
|
16
17
|
import { Image as ExpoImage } from 'expo-image';
|
|
17
18
|
import type { FileManagementScreenProps } from '../types/fileManagement';
|
|
@@ -33,13 +34,29 @@ import { useResolvedFileUrls, fileThumbSource } from '../hooks/useResolvedFileUr
|
|
|
33
34
|
import { FileViewer } from '../components/fileManagement/FileViewer';
|
|
34
35
|
import { FileDetailsModal } from '../components/fileManagement/FileDetailsModal';
|
|
35
36
|
import { UploadPreview } from '../components/fileManagement/UploadPreview';
|
|
36
|
-
import { fileManagementStyles } from '../components/fileManagement/styles';
|
|
37
37
|
import { getErrorMessage } from './fileManagement/shared';
|
|
38
38
|
import { useFileUploadState } from './fileManagement/hooks/useFileUploadState';
|
|
39
39
|
import PhotoPickerView from './fileManagement/PhotoPickerSection';
|
|
40
40
|
import FileListSection, { type FileListItem } from './fileManagement/FileListSection';
|
|
41
41
|
import UploadBar from './fileManagement/UploadBar';
|
|
42
42
|
|
|
43
|
+
// Genuinely-inline-only styles: `viewModeButton` is spread into an Animated.View
|
|
44
|
+
// style array (interpolated backgroundColor), and the photo tiles are
|
|
45
|
+
// `expo-image` (no className remap). Everything else uses NativeWind classNames.
|
|
46
|
+
const screenStyles = StyleSheet.create({
|
|
47
|
+
viewModeButton: {
|
|
48
|
+
paddingHorizontal: 10,
|
|
49
|
+
paddingVertical: 6,
|
|
50
|
+
borderRadius: 999,
|
|
51
|
+
minWidth: 36,
|
|
52
|
+
alignItems: 'center',
|
|
53
|
+
justifyContent: 'center',
|
|
54
|
+
marginHorizontal: 1,
|
|
55
|
+
},
|
|
56
|
+
photoImage: { width: '100%', height: '100%', borderRadius: 8 },
|
|
57
|
+
justifiedPhotoImage: { width: '100%', height: '100%', borderRadius: 6 },
|
|
58
|
+
});
|
|
59
|
+
|
|
43
60
|
// Animated button component for smooth transitions
|
|
44
61
|
const AnimatedButton: React.FC<{
|
|
45
62
|
isSelected: boolean;
|
|
@@ -100,7 +117,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
100
117
|
goBack,
|
|
101
118
|
navigate,
|
|
102
119
|
userId,
|
|
103
|
-
containerWidth
|
|
120
|
+
containerWidth,
|
|
104
121
|
selectMode = false,
|
|
105
122
|
multiSelect = false,
|
|
106
123
|
onSelect,
|
|
@@ -126,8 +143,13 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
126
143
|
const visibilityChangeDialog = useDialogControl();
|
|
127
144
|
const [pendingDeleteFile, setPendingDeleteFile] = useState<{ id: string; name: string } | null>(null);
|
|
128
145
|
const files = useFiles();
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
const { width: windowWidth } = useWindowDimensions();
|
|
147
|
+
// Prefer an explicit sheet width from the router; fall back to the window
|
|
148
|
+
// so photo grids never size against a hardcoded 400px default.
|
|
149
|
+
const safeContainerWidth: number =
|
|
150
|
+
typeof containerWidth === 'number' && containerWidth > 0
|
|
151
|
+
? containerWidth
|
|
152
|
+
: windowWidth;
|
|
131
153
|
const uploading = useUploadingStore();
|
|
132
154
|
const uploadProgress = useUploadAggregateProgress();
|
|
133
155
|
const deleting = useDeletingStore();
|
|
@@ -782,79 +804,26 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
782
804
|
fileDetailsControl.open();
|
|
783
805
|
};
|
|
784
806
|
|
|
785
|
-
const renderSimplePhotoItem = useCallback((photo: FileMetadata, index: number) => {
|
|
786
|
-
const downloadUrl = thumbSourceFor(photo);
|
|
787
|
-
|
|
788
|
-
// Calculate photo item width based on actual container size from bottom sheet
|
|
789
|
-
let itemsPerRow = 3; // Default for mobile
|
|
790
|
-
if (safeContainerWidth > 768) itemsPerRow = 4; // Desktop/tablet
|
|
791
|
-
else if (safeContainerWidth > 480) itemsPerRow = 3; // Large mobile
|
|
792
|
-
|
|
793
|
-
// Account for the photoScrollContainer padding (16px on each side = 32px total)
|
|
794
|
-
const scrollContainerPadding = 32; // Total horizontal padding from photoScrollContainer
|
|
795
|
-
const gaps = (itemsPerRow - 1) * 4; // Gap between items (4px)
|
|
796
|
-
const availableWidth = safeContainerWidth - scrollContainerPadding;
|
|
797
|
-
const itemWidth = (availableWidth - gaps) / itemsPerRow;
|
|
798
|
-
|
|
799
|
-
return (
|
|
800
|
-
<TouchableOpacity
|
|
801
|
-
key={photo.id}
|
|
802
|
-
style={[
|
|
803
|
-
fileManagementStyles.simplePhotoItem,
|
|
804
|
-
{
|
|
805
|
-
width: itemWidth,
|
|
806
|
-
height: itemWidth,
|
|
807
|
-
marginRight: (index + 1) % itemsPerRow === 0 ? 0 : 4,
|
|
808
|
-
...(selectMode && selectedIds.has(photo.id) ? { borderWidth: 2, borderColor: colors.primary } : {})
|
|
809
|
-
}
|
|
810
|
-
]}
|
|
811
|
-
onPress={() => handleFileOpen(photo)}
|
|
812
|
-
activeOpacity={0.8}
|
|
813
|
-
>
|
|
814
|
-
<View style={fileManagementStyles.simplePhotoContainer}>
|
|
815
|
-
<ExpoImage
|
|
816
|
-
source={{ uri: downloadUrl }}
|
|
817
|
-
style={fileManagementStyles.simplePhotoImage}
|
|
818
|
-
contentFit="cover"
|
|
819
|
-
transition={120}
|
|
820
|
-
cachePolicy="memory-disk"
|
|
821
|
-
onError={() => {
|
|
822
|
-
// Photo failed to load, will show placeholder
|
|
823
|
-
}}
|
|
824
|
-
accessibilityLabel={photo.filename}
|
|
825
|
-
/>
|
|
826
|
-
{selectMode && (
|
|
827
|
-
<View style={fileManagementStyles.selectionBadge}>
|
|
828
|
-
<Ionicons name={selectedIds.has(photo.id) ? 'checkmark-circle' : 'ellipse-outline'} size={20} color={selectedIds.has(photo.id) ? colors.primary : colors.text} />
|
|
829
|
-
</View>
|
|
830
|
-
)}
|
|
831
|
-
</View>
|
|
832
|
-
</TouchableOpacity>
|
|
833
|
-
);
|
|
834
|
-
}, [thumbSourceFor, safeContainerWidth, selectMode, selectedIds, colors.primary, colors.text]);
|
|
835
|
-
|
|
836
807
|
const renderJustifiedPhotoItem = useCallback((photo: FileMetadata, width: number, height: number, isLast: boolean) => {
|
|
837
808
|
const downloadUrl = thumbSourceFor(photo);
|
|
838
809
|
|
|
839
810
|
return (
|
|
840
811
|
<TouchableOpacity
|
|
841
812
|
key={photo.id}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
},
|
|
850
|
-
]}
|
|
813
|
+
className="rounded-[6px] overflow-hidden relative"
|
|
814
|
+
style={{
|
|
815
|
+
width,
|
|
816
|
+
height,
|
|
817
|
+
...(selectMode && selectedIds.has(photo.id) ? { borderWidth: 2, borderColor: colors.primary } : {}),
|
|
818
|
+
...(selectMode && multiSelect && selectedIds.size > 0 && !selectedIds.has(photo.id) ? { opacity: 0.4 } : {}),
|
|
819
|
+
}}
|
|
851
820
|
onPress={() => handleFileOpen(photo)}
|
|
852
821
|
activeOpacity={0.8}
|
|
853
822
|
>
|
|
854
|
-
<View
|
|
823
|
+
<View className="w-full h-full relative rounded-[6px] overflow-hidden">
|
|
855
824
|
<ExpoImage
|
|
856
825
|
source={{ uri: downloadUrl }}
|
|
857
|
-
style={
|
|
826
|
+
style={screenStyles.justifiedPhotoImage}
|
|
858
827
|
contentFit="cover"
|
|
859
828
|
transition={120}
|
|
860
829
|
cachePolicy="memory-disk"
|
|
@@ -864,7 +833,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
864
833
|
accessibilityLabel={photo.filename}
|
|
865
834
|
/>
|
|
866
835
|
{selectMode && (
|
|
867
|
-
<View style={
|
|
836
|
+
<View className="absolute top-[4px] right-[4px] rounded-[12px] p-[2px]" style={{ backgroundColor: 'rgba(0,0,0,0.4)' }}>
|
|
868
837
|
<Ionicons name={selectedIds.has(photo.id) ? 'checkmark-circle' : 'ellipse-outline'} size={20} color={selectedIds.has(photo.id) ? colors.primary : colors.text} />
|
|
869
838
|
</View>
|
|
870
839
|
)}
|
|
@@ -884,147 +853,6 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
884
853
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
885
854
|
}, [targetUserId]);
|
|
886
855
|
|
|
887
|
-
const renderFileItem = (file: FileMetadata) => {
|
|
888
|
-
const isImage = file.contentType.startsWith('image/');
|
|
889
|
-
const isPDF = file.contentType.includes('pdf');
|
|
890
|
-
const isVideo = file.contentType.startsWith('video/');
|
|
891
|
-
const isAudio = file.contentType.startsWith('audio/');
|
|
892
|
-
const hasPreview = isImage || isPDF || isVideo;
|
|
893
|
-
const borderColor = colors.border;
|
|
894
|
-
|
|
895
|
-
return (
|
|
896
|
-
<View
|
|
897
|
-
key={file.id}
|
|
898
|
-
style={[fileManagementStyles.fileItem, { backgroundColor: colors.backgroundSecondary, borderColor }, selectMode && selectedIds.has(file.id) && { borderColor: colors.primary, borderWidth: 2 }]}
|
|
899
|
-
>
|
|
900
|
-
<TouchableOpacity
|
|
901
|
-
style={fileManagementStyles.fileContent}
|
|
902
|
-
onPress={() => handleFileOpen(file)}
|
|
903
|
-
>
|
|
904
|
-
{/* Preview Thumbnail */}
|
|
905
|
-
<View style={fileManagementStyles.filePreviewContainer}>
|
|
906
|
-
{hasPreview ? (
|
|
907
|
-
<View style={fileManagementStyles.filePreview}>
|
|
908
|
-
{isImage && (
|
|
909
|
-
<ExpoImage
|
|
910
|
-
source={{ uri: thumbSourceFor(file) }}
|
|
911
|
-
style={fileManagementStyles.previewImage}
|
|
912
|
-
contentFit="cover"
|
|
913
|
-
transition={120}
|
|
914
|
-
cachePolicy="memory-disk"
|
|
915
|
-
onError={() => {
|
|
916
|
-
// Image preview failed to load
|
|
917
|
-
}}
|
|
918
|
-
accessibilityLabel={file.filename}
|
|
919
|
-
/>
|
|
920
|
-
)}
|
|
921
|
-
{isPDF && (
|
|
922
|
-
<View style={fileManagementStyles.pdfPreview}>
|
|
923
|
-
<Ionicons name="document" size={32} color={colors.primary} />
|
|
924
|
-
<Text style={[fileManagementStyles.pdfLabel, { color: colors.primary }]}>PDF</Text>
|
|
925
|
-
</View>
|
|
926
|
-
)}
|
|
927
|
-
{isVideo && (
|
|
928
|
-
<View style={fileManagementStyles.videoPreviewWrapper}>
|
|
929
|
-
<ExpoImage
|
|
930
|
-
source={{ uri: thumbSourceFor(file) }}
|
|
931
|
-
style={fileManagementStyles.videoPosterImage}
|
|
932
|
-
contentFit="cover"
|
|
933
|
-
transition={120}
|
|
934
|
-
cachePolicy="memory-disk"
|
|
935
|
-
onError={(_: unknown) => {
|
|
936
|
-
// If thumbnail not available, we still show icon overlay
|
|
937
|
-
}}
|
|
938
|
-
accessibilityLabel={`${file.filename} video thumbnail`}
|
|
939
|
-
/>
|
|
940
|
-
<View style={fileManagementStyles.videoOverlay}>
|
|
941
|
-
<Ionicons name="play" size={24} color="#FFFFFF" />
|
|
942
|
-
</View>
|
|
943
|
-
</View>
|
|
944
|
-
)}
|
|
945
|
-
{/* Fallback icon (hidden by default for images) */}
|
|
946
|
-
<View
|
|
947
|
-
style={[fileManagementStyles.fallbackIcon, { display: isImage ? 'none' : 'flex' }]}
|
|
948
|
-
>
|
|
949
|
-
<Ionicons
|
|
950
|
-
name={getFileIcon(file.contentType)}
|
|
951
|
-
size={32}
|
|
952
|
-
color={colors.primary}
|
|
953
|
-
/>
|
|
954
|
-
</View>
|
|
955
|
-
|
|
956
|
-
{selectMode && (
|
|
957
|
-
<View style={fileManagementStyles.selectionBadge}>
|
|
958
|
-
<Ionicons name={selectedIds.has(file.id) ? 'checkmark-circle' : 'ellipse-outline'} size={22} color={selectedIds.has(file.id) ? colors.primary : colors.text} />
|
|
959
|
-
</View>
|
|
960
|
-
)}
|
|
961
|
-
</View>
|
|
962
|
-
) : (
|
|
963
|
-
<View style={fileManagementStyles.fileIconContainer}>
|
|
964
|
-
<Ionicons
|
|
965
|
-
name={getFileIcon(file.contentType)}
|
|
966
|
-
size={32}
|
|
967
|
-
color={colors.primary}
|
|
968
|
-
/>
|
|
969
|
-
</View>
|
|
970
|
-
)}
|
|
971
|
-
</View>
|
|
972
|
-
|
|
973
|
-
<View style={fileManagementStyles.fileInfo}>
|
|
974
|
-
<Text style={[fileManagementStyles.fileName, { color: colors.text }]} numberOfLines={1}>
|
|
975
|
-
{file.filename}
|
|
976
|
-
</Text>
|
|
977
|
-
<Text style={[fileManagementStyles.fileDetails, { color: colors.textSecondary }]}>
|
|
978
|
-
{formatFileSize(file.length)} • {new Date(file.uploadDate).toLocaleDateString()}
|
|
979
|
-
</Text>
|
|
980
|
-
{file.metadata?.description && (
|
|
981
|
-
<Text
|
|
982
|
-
style={[fileManagementStyles.fileDescription, { color: colors.textTertiary }]}
|
|
983
|
-
numberOfLines={2}
|
|
984
|
-
>
|
|
985
|
-
{file.metadata.description}
|
|
986
|
-
</Text>
|
|
987
|
-
)}
|
|
988
|
-
</View>
|
|
989
|
-
</TouchableOpacity>
|
|
990
|
-
|
|
991
|
-
{!selectMode && (
|
|
992
|
-
<View style={fileManagementStyles.fileActions}>
|
|
993
|
-
{/* Preview button for supported files */}
|
|
994
|
-
{hasPreview && (
|
|
995
|
-
<TouchableOpacity
|
|
996
|
-
style={[fileManagementStyles.actionButton, { backgroundColor: colors.backgroundSecondary }]}
|
|
997
|
-
onPress={() => handleFileOpen(file)}
|
|
998
|
-
>
|
|
999
|
-
<Ionicons name="eye" size={20} color={colors.primary} />
|
|
1000
|
-
</TouchableOpacity>
|
|
1001
|
-
)}
|
|
1002
|
-
|
|
1003
|
-
<TouchableOpacity
|
|
1004
|
-
style={[fileManagementStyles.actionButton, { backgroundColor: colors.backgroundSecondary }]}
|
|
1005
|
-
onPress={() => handleFileDownload(file.id, file.filename)}
|
|
1006
|
-
>
|
|
1007
|
-
<Ionicons name="download" size={20} color={colors.primary} />
|
|
1008
|
-
</TouchableOpacity>
|
|
1009
|
-
|
|
1010
|
-
{/* Always show delete button for debugging */}
|
|
1011
|
-
<TouchableOpacity
|
|
1012
|
-
style={[fileManagementStyles.actionButton, { backgroundColor: colors.negativeSubtle }]}
|
|
1013
|
-
onPress={() => confirmFileDelete(file.id, file.filename)}
|
|
1014
|
-
disabled={deleting === file.id}
|
|
1015
|
-
>
|
|
1016
|
-
{deleting === file.id ? (
|
|
1017
|
-
<ActivityIndicator size="small" color={colors.error} />
|
|
1018
|
-
) : (
|
|
1019
|
-
<Ionicons name="trash" size={20} color={colors.error} />
|
|
1020
|
-
)}
|
|
1021
|
-
</TouchableOpacity>
|
|
1022
|
-
</View>
|
|
1023
|
-
)}
|
|
1024
|
-
</View>
|
|
1025
|
-
);
|
|
1026
|
-
};
|
|
1027
|
-
|
|
1028
856
|
// SettingsListItem-based file items (for 'all' view)
|
|
1029
857
|
const groupedFileItems: FileListItem[] = useMemo(() => {
|
|
1030
858
|
// filteredFiles is already sorted, so just use it directly
|
|
@@ -1100,23 +928,26 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1100
928
|
},
|
|
1101
929
|
// Hide action buttons when selecting (in selectMode or bulk operations mode)
|
|
1102
930
|
rightElement: (!selectMode && selectedIds.size === 0) ? (
|
|
1103
|
-
<View
|
|
931
|
+
<View className="flex-row items-center gap-[6px] ml-[12px]">
|
|
1104
932
|
{(isImage || isVideo || file.contentType.includes('pdf')) && (
|
|
1105
933
|
<TouchableOpacity
|
|
1106
|
-
|
|
934
|
+
className="w-[34px] h-[34px] rounded-[8px] items-center justify-center"
|
|
935
|
+
style={{ backgroundColor: colors.backgroundSecondary }}
|
|
1107
936
|
onPress={() => handleFileOpen(file)}
|
|
1108
937
|
>
|
|
1109
938
|
<Ionicons name="eye" size={18} color={colors.primary} />
|
|
1110
939
|
</TouchableOpacity>
|
|
1111
940
|
)}
|
|
1112
941
|
<TouchableOpacity
|
|
1113
|
-
|
|
942
|
+
className="w-[34px] h-[34px] rounded-[8px] items-center justify-center"
|
|
943
|
+
style={{ backgroundColor: colors.backgroundSecondary }}
|
|
1114
944
|
onPress={() => handleFileDownload(file.id, file.filename)}
|
|
1115
945
|
>
|
|
1116
946
|
<Ionicons name="download" size={18} color={colors.primary} />
|
|
1117
947
|
</TouchableOpacity>
|
|
1118
948
|
<TouchableOpacity
|
|
1119
|
-
|
|
949
|
+
className="w-[34px] h-[34px] rounded-[8px] items-center justify-center"
|
|
950
|
+
style={{ backgroundColor: colors.negativeSubtle }}
|
|
1120
951
|
onPress={() => confirmFileDelete(file.id, file.filename)}
|
|
1121
952
|
disabled={deleting === file.id}
|
|
1122
953
|
>
|
|
@@ -1235,20 +1066,15 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1235
1066
|
return (
|
|
1236
1067
|
<TouchableOpacity
|
|
1237
1068
|
key={photo.id}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
{
|
|
1241
|
-
width: itemWidth,
|
|
1242
|
-
height: itemWidth,
|
|
1243
|
-
}
|
|
1244
|
-
]}
|
|
1069
|
+
className="rounded-[8px] overflow-hidden"
|
|
1070
|
+
style={{ width: itemWidth, height: itemWidth }}
|
|
1245
1071
|
onPress={() => handleFileOpen(photo)}
|
|
1246
1072
|
activeOpacity={0.8}
|
|
1247
1073
|
>
|
|
1248
|
-
<View
|
|
1074
|
+
<View className="w-full h-full relative rounded-[8px] overflow-hidden">
|
|
1249
1075
|
<ExpoImage
|
|
1250
1076
|
source={{ uri: downloadUrl }}
|
|
1251
|
-
style={
|
|
1077
|
+
style={screenStyles.photoImage}
|
|
1252
1078
|
contentFit="cover"
|
|
1253
1079
|
transition={120}
|
|
1254
1080
|
cachePolicy="memory-disk"
|
|
@@ -1267,17 +1093,18 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1267
1093
|
|
|
1268
1094
|
if (photos.length === 0) {
|
|
1269
1095
|
return (
|
|
1270
|
-
<View
|
|
1096
|
+
<View className="items-center py-[40px] px-[24px]">
|
|
1271
1097
|
<Ionicons name="images-outline" size={64} color={colors.textTertiary} />
|
|
1272
|
-
<Text
|
|
1273
|
-
<Text
|
|
1098
|
+
<Text className="text-[24px] font-bold mt-[16px] mb-[8px]" style={{ color: colors.text }}>{t('fileManagement.emptyPhotos.title')}</Text>
|
|
1099
|
+
<Text className="text-[16px] text-center leading-[24px] mb-[32px]" style={{ color: colors.textSecondary }}> {
|
|
1274
1100
|
user?.id === targetUserId
|
|
1275
1101
|
? t('fileManagement.emptyPhotos.ownDescription')
|
|
1276
1102
|
: t('fileManagement.emptyPhotos.otherDescription')
|
|
1277
1103
|
} </Text>
|
|
1278
1104
|
{user?.id === targetUserId && (
|
|
1279
1105
|
<TouchableOpacity
|
|
1280
|
-
|
|
1106
|
+
className="flex-row items-center px-[24px] py-[12px] rounded-[24px] gap-[8px]"
|
|
1107
|
+
style={{ backgroundColor: colors.primary }}
|
|
1281
1108
|
onPress={handleFileUpload}
|
|
1282
1109
|
disabled={uploading || isPickingDocument}
|
|
1283
1110
|
>
|
|
@@ -1288,7 +1115,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1288
1115
|
) : (
|
|
1289
1116
|
<>
|
|
1290
1117
|
<Ionicons name="cloud-upload" size={20} color="#FFFFFF" />
|
|
1291
|
-
<Text
|
|
1118
|
+
<Text className="text-white text-[16px] font-semibold">{t('fileManagement.uploadPhotos')}</Text>
|
|
1292
1119
|
</>
|
|
1293
1120
|
)}
|
|
1294
1121
|
</TouchableOpacity>
|
|
@@ -1300,8 +1127,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1300
1127
|
return (
|
|
1301
1128
|
<ScrollView
|
|
1302
1129
|
ref={photoScrollViewRef}
|
|
1303
|
-
|
|
1304
|
-
|
|
1130
|
+
className="flex-1"
|
|
1131
|
+
contentContainerClassName="p-[10px]"
|
|
1305
1132
|
refreshControl={
|
|
1306
1133
|
<RefreshControl
|
|
1307
1134
|
refreshing={refreshing}
|
|
@@ -1320,9 +1147,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1320
1147
|
scrollEventThrottle={250}
|
|
1321
1148
|
>
|
|
1322
1149
|
{loadingDimensions && (
|
|
1323
|
-
<View
|
|
1150
|
+
<View className="flex-row items-center justify-center py-[16px] gap-[8px]">
|
|
1324
1151
|
<ActivityIndicator size="small" color={colors.primary} />
|
|
1325
|
-
<Text
|
|
1152
|
+
<Text className="text-[14px] italic" style={{ color: colors.textSecondary }}>{t('fileManagement.loadingPhotoLayout')}</Text>
|
|
1326
1153
|
</View>
|
|
1327
1154
|
)}
|
|
1328
1155
|
|
|
@@ -1361,10 +1188,10 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1361
1188
|
|
|
1362
1189
|
|
|
1363
1190
|
const renderEmptyState = () => (
|
|
1364
|
-
<View
|
|
1191
|
+
<View className="items-center py-[40px] px-[24px]">
|
|
1365
1192
|
<Ionicons name="folder-open-outline" size={64} color={colors.textTertiary} />
|
|
1366
|
-
<Text
|
|
1367
|
-
<Text
|
|
1193
|
+
<Text className="text-[24px] font-bold mt-[16px] mb-[8px]" style={{ color: colors.text }}>{t('fileManagement.emptyFiles.title')}</Text>
|
|
1194
|
+
<Text className="text-[16px] text-center leading-[24px] mb-[32px]" style={{ color: colors.textSecondary }}>
|
|
1368
1195
|
{user?.id === targetUserId
|
|
1369
1196
|
? t('fileManagement.emptyFiles.ownDescription')
|
|
1370
1197
|
: t('fileManagement.emptyFiles.otherDescription')
|
|
@@ -1372,7 +1199,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1372
1199
|
</Text>
|
|
1373
1200
|
{user?.id === targetUserId && (
|
|
1374
1201
|
<TouchableOpacity
|
|
1375
|
-
|
|
1202
|
+
className="flex-row items-center px-[24px] py-[12px] rounded-[24px] gap-[8px]"
|
|
1203
|
+
style={{ backgroundColor: colors.primary }}
|
|
1376
1204
|
onPress={handleFileUpload}
|
|
1377
1205
|
disabled={uploading || isPickingDocument}
|
|
1378
1206
|
>
|
|
@@ -1383,7 +1211,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1383
1211
|
) : (
|
|
1384
1212
|
<>
|
|
1385
1213
|
<Ionicons name="cloud-upload" size={20} color="#FFFFFF" />
|
|
1386
|
-
<Text
|
|
1214
|
+
<Text className="text-white text-[16px] font-semibold">{t('fileManagement.uploadFiles')}</Text>
|
|
1387
1215
|
</>
|
|
1388
1216
|
)}
|
|
1389
1217
|
</TouchableOpacity>
|
|
@@ -1511,11 +1339,14 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1511
1339
|
);
|
|
1512
1340
|
|
|
1513
1341
|
return (
|
|
1514
|
-
<View style={
|
|
1342
|
+
<View className="flex-1" style={{ backgroundColor }}>
|
|
1515
1343
|
{/* Header Skeleton */}
|
|
1516
|
-
<View
|
|
1344
|
+
<View
|
|
1345
|
+
className="flex-row items-center justify-between px-[16px] py-[12px] relative"
|
|
1346
|
+
style={{ borderBottomColor: colors.border, borderBottomWidth: StyleSheet.hairlineWidth }}
|
|
1347
|
+
>
|
|
1517
1348
|
<SkeletonBox width={44} height={44} borderRadius={12} />
|
|
1518
|
-
<View
|
|
1349
|
+
<View className="flex-1 items-center justify-center mx-[16px]">
|
|
1519
1350
|
<SkeletonBox width={140} height={20} style={{ marginBottom: 6 }} />
|
|
1520
1351
|
<SkeletonBox width={100} height={14} />
|
|
1521
1352
|
</View>
|
|
@@ -1523,24 +1354,26 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1523
1354
|
</View>
|
|
1524
1355
|
|
|
1525
1356
|
{/* Controls Bar Skeleton */}
|
|
1526
|
-
<View
|
|
1357
|
+
<View className="flex-row items-center justify-between px-[12px] py-[12px] gap-[12px]">
|
|
1527
1358
|
<SkeletonBox width={100} height={36} borderRadius={18} />
|
|
1528
1359
|
<SkeletonBox width={44} height={44} borderRadius={22} />
|
|
1529
1360
|
</View>
|
|
1530
1361
|
|
|
1531
1362
|
{/* Search Bar Skeleton */}
|
|
1532
|
-
<View
|
|
1533
|
-
|
|
1534
|
-
|
|
1363
|
+
<View
|
|
1364
|
+
className="flex-row items-center px-[14px] py-[10px] mx-[12px] mb-[12px] rounded-full gap-[10px]"
|
|
1365
|
+
style={{ backgroundColor: colors.card }}
|
|
1366
|
+
>
|
|
1535
1367
|
<SkeletonBox width="100%" height={44} borderRadius={12} />
|
|
1536
1368
|
</View>
|
|
1537
1369
|
|
|
1538
1370
|
{/* Stats Container Skeleton */}
|
|
1539
|
-
<View
|
|
1540
|
-
|
|
1541
|
-
|
|
1371
|
+
<View
|
|
1372
|
+
className="flex-row px-[14px] py-[10px] mx-[12px] mb-[12px] rounded-[18px]"
|
|
1373
|
+
style={{ backgroundColor: colors.card }}
|
|
1374
|
+
>
|
|
1542
1375
|
{[1, 2, 3].map((i) => (
|
|
1543
|
-
<View key={i}
|
|
1376
|
+
<View key={i} className="flex-1 items-center py-[4px]">
|
|
1544
1377
|
<SkeletonBox width={50} height={20} style={{ marginBottom: 4 }} delay={i * 30} />
|
|
1545
1378
|
<SkeletonBox width={40} height={14} delay={i * 30 + 15} />
|
|
1546
1379
|
</View>
|
|
@@ -1549,8 +1382,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1549
1382
|
|
|
1550
1383
|
{/* File List Skeleton - Matching SettingsListItem */}
|
|
1551
1384
|
<ScrollView
|
|
1552
|
-
|
|
1553
|
-
|
|
1385
|
+
className="flex-1"
|
|
1386
|
+
contentContainerClassName="px-[12px] pt-0 pb-[12px]"
|
|
1554
1387
|
showsVerticalScrollIndicator={false}
|
|
1555
1388
|
>
|
|
1556
1389
|
<View style={{
|
|
@@ -1654,7 +1487,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1654
1487
|
// If upload preview is showing, render it inline instead of the file list
|
|
1655
1488
|
if (showUploadPreview) {
|
|
1656
1489
|
return (
|
|
1657
|
-
<View
|
|
1490
|
+
<View className="flex-1">
|
|
1658
1491
|
<Header
|
|
1659
1492
|
title={t('fileManagement.reviewFiles')}
|
|
1660
1493
|
subtitle={t('fileManagement.readyToUpload', { count: pendingFiles.length })}
|
|
@@ -1676,7 +1509,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1676
1509
|
}
|
|
1677
1510
|
|
|
1678
1511
|
return (
|
|
1679
|
-
<View
|
|
1512
|
+
<View className="flex-1">
|
|
1680
1513
|
<Header
|
|
1681
1514
|
title={selectMode ? (multiSelect ? (maxSelection ? t('fileManagement.selectedWithMax', { count: selectedIds.size, max: maxSelection }) : t('fileManagement.selected', { count: selectedIds.size })) : t('fileManagement.selectFile')) : (viewMode === 'photos' ? t('fileManagement.photos') : t('fileManagement.title'))}
|
|
1682
1515
|
subtitle={selectMode ? (multiSelect ? t('fileManagement.available', { count: filteredFiles.length }) : t('fileManagement.tapToSelect')) : (filteredFiles.length === 1 ? t('fileManagement.itemCount', { count: filteredFiles.length }) : t('fileManagement.itemCount_plural', { count: filteredFiles.length }))}
|
|
@@ -1722,25 +1555,24 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1722
1555
|
titleAlignment="left"
|
|
1723
1556
|
/>
|
|
1724
1557
|
|
|
1725
|
-
<View
|
|
1558
|
+
<View className="flex-row items-center justify-between px-[12px] py-[12px] gap-[12px]">
|
|
1726
1559
|
<ScrollView
|
|
1727
1560
|
horizontal
|
|
1728
1561
|
showsHorizontalScrollIndicator={false}
|
|
1729
|
-
|
|
1562
|
+
className="flex-1"
|
|
1563
|
+
style={{ maxWidth: '80%' }}
|
|
1730
1564
|
>
|
|
1731
|
-
<View
|
|
1732
|
-
|
|
1733
|
-
{
|
|
1734
|
-
|
|
1735
|
-
}
|
|
1736
|
-
]}>
|
|
1565
|
+
<View
|
|
1566
|
+
className="flex-row rounded-full p-[2px] overflow-hidden"
|
|
1567
|
+
style={{ backgroundColor: colors.card }}
|
|
1568
|
+
>
|
|
1737
1569
|
<AnimatedButton
|
|
1738
1570
|
isSelected={viewMode === 'all'}
|
|
1739
1571
|
onPress={() => setViewMode('all')}
|
|
1740
1572
|
icon={viewMode === 'all' ? 'folder' : 'folder-outline'}
|
|
1741
1573
|
primaryColor={colors.primary}
|
|
1742
1574
|
textColor={colors.text}
|
|
1743
|
-
style={
|
|
1575
|
+
style={screenStyles.viewModeButton}
|
|
1744
1576
|
accessibilityLabel={t('fileManagement.a11y.viewAll') || 'Show all files'}
|
|
1745
1577
|
/>
|
|
1746
1578
|
<AnimatedButton
|
|
@@ -1749,7 +1581,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1749
1581
|
icon={viewMode === 'photos' ? 'image-multiple' : 'image-multiple-outline'}
|
|
1750
1582
|
primaryColor={colors.primary}
|
|
1751
1583
|
textColor={colors.text}
|
|
1752
|
-
style={
|
|
1584
|
+
style={screenStyles.viewModeButton}
|
|
1753
1585
|
accessibilityLabel={t('fileManagement.a11y.viewPhotos') || 'Show photos only'}
|
|
1754
1586
|
/>
|
|
1755
1587
|
{!isImageOnlyPicker && (
|
|
@@ -1760,7 +1592,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1760
1592
|
icon={viewMode === 'videos' ? 'video' : 'video-outline'}
|
|
1761
1593
|
primaryColor={colors.primary}
|
|
1762
1594
|
textColor={colors.text}
|
|
1763
|
-
style={
|
|
1595
|
+
style={screenStyles.viewModeButton}
|
|
1764
1596
|
accessibilityLabel={t('fileManagement.a11y.viewVideos') || 'Show videos only'}
|
|
1765
1597
|
/>
|
|
1766
1598
|
<AnimatedButton
|
|
@@ -1769,7 +1601,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1769
1601
|
icon={viewMode === 'documents' ? 'file-document' : 'file-document-outline'}
|
|
1770
1602
|
primaryColor={colors.primary}
|
|
1771
1603
|
textColor={colors.text}
|
|
1772
|
-
style={
|
|
1604
|
+
style={screenStyles.viewModeButton}
|
|
1773
1605
|
accessibilityLabel={t('fileManagement.a11y.viewDocuments') || 'Show documents only'}
|
|
1774
1606
|
/>
|
|
1775
1607
|
<AnimatedButton
|
|
@@ -1778,7 +1610,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1778
1610
|
icon={viewMode === 'audio' ? 'music-note' : 'music-note-outline'}
|
|
1779
1611
|
primaryColor={colors.primary}
|
|
1780
1612
|
textColor={colors.text}
|
|
1781
|
-
style={
|
|
1613
|
+
style={screenStyles.viewModeButton}
|
|
1782
1614
|
accessibilityLabel={t('fileManagement.a11y.viewAudio') || 'Show audio only'}
|
|
1783
1615
|
/>
|
|
1784
1616
|
</>
|
|
@@ -1786,9 +1618,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1786
1618
|
</View>
|
|
1787
1619
|
</ScrollView>
|
|
1788
1620
|
<TouchableOpacity
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
}]}
|
|
1621
|
+
className="flex-row items-center justify-center px-[10px] py-[6px] rounded-full min-w-[36px] gap-[4px]"
|
|
1622
|
+
style={{ backgroundColor: colors.card }}
|
|
1792
1623
|
accessibilityRole="button"
|
|
1793
1624
|
accessibilityLabel={t('fileManagement.a11y.sortBy', {
|
|
1794
1625
|
field: sortBy,
|
|
@@ -1823,11 +1654,8 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1823
1654
|
</TouchableOpacity>
|
|
1824
1655
|
{user?.id === targetUserId && (!selectMode || (selectMode && allowUploadInSelectMode)) && (
|
|
1825
1656
|
<TouchableOpacity
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
isImageOnlyPicker && fileManagementStyles.uploadButtonExtended,
|
|
1829
|
-
{ backgroundColor: colors.primary },
|
|
1830
|
-
]}
|
|
1657
|
+
className={`h-[44px] rounded-[22px] items-center justify-center ${isImageOnlyPicker ? 'w-auto min-w-[44px] px-[14px]' : 'w-[44px]'}`}
|
|
1658
|
+
style={{ backgroundColor: colors.primary }}
|
|
1831
1659
|
onPress={handleFileUpload}
|
|
1832
1660
|
disabled={uploading || isPickingDocument}
|
|
1833
1661
|
accessibilityRole="button"
|
|
@@ -1839,10 +1667,10 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1839
1667
|
accessibilityState={{ busy: uploading || isPickingDocument }}
|
|
1840
1668
|
>
|
|
1841
1669
|
{uploading ? (
|
|
1842
|
-
<View
|
|
1670
|
+
<View className="items-center justify-center">
|
|
1843
1671
|
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
1844
1672
|
{uploadProgress && (
|
|
1845
|
-
<Text
|
|
1673
|
+
<Text className="text-white text-[10px] font-semibold mt-[2px]">
|
|
1846
1674
|
{uploadProgress.current}/{uploadProgress.total}
|
|
1847
1675
|
</Text>
|
|
1848
1676
|
)}
|
|
@@ -1850,9 +1678,9 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1850
1678
|
) : isPickingDocument ? (
|
|
1851
1679
|
<ActivityIndicator size="small" color="#FFFFFF" />
|
|
1852
1680
|
) : isImageOnlyPicker ? (
|
|
1853
|
-
<View
|
|
1681
|
+
<View className="flex-row items-center gap-[6px]">
|
|
1854
1682
|
<Ionicons name="cloud-upload" size={18} color="#FFFFFF" />
|
|
1855
|
-
<Text
|
|
1683
|
+
<Text className="text-white text-[14px] font-semibold" numberOfLines={1}>
|
|
1856
1684
|
{t('fileManagement.upload') || 'Upload'}
|
|
1857
1685
|
</Text>
|
|
1858
1686
|
</View>
|
|
@@ -1865,15 +1693,14 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1865
1693
|
|
|
1866
1694
|
{/* Search Bar */}
|
|
1867
1695
|
{files.length > 0 && (viewMode === 'all' || files.some(f => f.contentType.startsWith('image/'))) && (
|
|
1868
|
-
<View
|
|
1869
|
-
|
|
1870
|
-
{
|
|
1871
|
-
|
|
1872
|
-
}
|
|
1873
|
-
]}>
|
|
1696
|
+
<View
|
|
1697
|
+
className="flex-row items-center px-[14px] py-[10px] mx-[12px] mb-[12px] rounded-full gap-[10px]"
|
|
1698
|
+
style={{ backgroundColor: colors.card }}
|
|
1699
|
+
>
|
|
1874
1700
|
<Ionicons name="search" size={22} color={colors.icon} />
|
|
1875
1701
|
<TextInput
|
|
1876
|
-
|
|
1702
|
+
className="flex-1 text-[16px] leading-[20px]"
|
|
1703
|
+
style={{ color: colors.text }}
|
|
1877
1704
|
placeholder={viewMode === 'photos' ? t('fileManagement.searchPhotos') : t('fileManagement.searchFiles')}
|
|
1878
1705
|
placeholderTextColor={colors.textSecondary}
|
|
1879
1706
|
value={searchQuery}
|
|
@@ -1882,7 +1709,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1882
1709
|
{searchQuery.length > 0 && (
|
|
1883
1710
|
<TouchableOpacity
|
|
1884
1711
|
onPress={() => setSearchQuery('')}
|
|
1885
|
-
|
|
1712
|
+
className="p-[4px] rounded-[12px] items-center justify-center"
|
|
1886
1713
|
>
|
|
1887
1714
|
<Ionicons name="close-circle" size={22} color={colors.icon} />
|
|
1888
1715
|
</TouchableOpacity>
|
|
@@ -1892,30 +1719,28 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1892
1719
|
|
|
1893
1720
|
{/* File Stats */}
|
|
1894
1721
|
{files.length > 0 && (
|
|
1895
|
-
<View
|
|
1896
|
-
|
|
1897
|
-
{
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
<Text style={[fileManagementStyles.statValue, { color: colors.text }]}>{filteredFiles.length}</Text>
|
|
1903
|
-
<Text style={[fileManagementStyles.statLabel, { color: colors.textSecondary }]}>
|
|
1722
|
+
<View
|
|
1723
|
+
className="flex-row px-[14px] py-[10px] mx-[12px] mb-[12px] rounded-[18px]"
|
|
1724
|
+
style={{ backgroundColor: colors.card }}
|
|
1725
|
+
>
|
|
1726
|
+
<View className="flex-1 items-center py-[4px]">
|
|
1727
|
+
<Text className="text-[20px] font-extrabold leading-[24px]" style={{ color: colors.text, letterSpacing: -0.5 }}>{filteredFiles.length}</Text>
|
|
1728
|
+
<Text className="text-[12px] font-medium mt-[2px]" style={{ color: colors.textSecondary, letterSpacing: 0.2 }}>
|
|
1904
1729
|
{searchQuery.length > 0 ? t('fileManagement.found') : (filteredFiles.length === 1 ? (viewMode === 'photos' ? t('fileManagement.photo') : t('fileManagement.file')) : (viewMode === 'photos' ? t('fileManagement.photos_stat') : t('fileManagement.files')))}
|
|
1905
1730
|
</Text>
|
|
1906
1731
|
</View>
|
|
1907
|
-
<View
|
|
1908
|
-
<Text
|
|
1732
|
+
<View className="flex-1 items-center py-[4px]">
|
|
1733
|
+
<Text className="text-[20px] font-extrabold leading-[24px]" style={{ color: colors.text, letterSpacing: -0.5 }}>
|
|
1909
1734
|
{formatFileSize(filteredFiles.reduce((total, file) => total + file.length, 0))}
|
|
1910
1735
|
</Text>
|
|
1911
|
-
<Text
|
|
1736
|
+
<Text className="text-[12px] font-medium mt-[2px]" style={{ color: colors.textSecondary, letterSpacing: 0.2 }}>
|
|
1912
1737
|
{searchQuery.length > 0 ? t('fileManagement.size') : t('fileManagement.totalSize')}
|
|
1913
1738
|
</Text>
|
|
1914
1739
|
</View>
|
|
1915
1740
|
{searchQuery.length > 0 && (
|
|
1916
|
-
<View
|
|
1917
|
-
<Text
|
|
1918
|
-
<Text
|
|
1741
|
+
<View className="flex-1 items-center py-[4px]">
|
|
1742
|
+
<Text className="text-[20px] font-extrabold leading-[24px]" style={{ color: colors.text, letterSpacing: -0.5 }}>{files.length}</Text>
|
|
1743
|
+
<Text className="text-[12px] font-medium mt-[2px]" style={{ color: colors.textSecondary, letterSpacing: 0.2 }}>
|
|
1919
1744
|
{t('fileManagement.total')}
|
|
1920
1745
|
</Text>
|
|
1921
1746
|
</View>
|
|
@@ -1998,6 +1823,4 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
1998
1823
|
);
|
|
1999
1824
|
};
|
|
2000
1825
|
|
|
2001
|
-
// Styles have been moved to components/fileManagement/styles.ts
|
|
2002
|
-
|
|
2003
1826
|
export default FileManagementScreen;
|