@oxyhq/services 22.10.0 → 22.11.0
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/AvatarCameraBadge.js +42 -0
- package/lib/commonjs/ui/components/AvatarCameraBadge.js.map +1 -0
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +41 -19
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +640 -168
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileButton.js +14 -0
- package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileSummaryCard.js +3 -23
- package/lib/commonjs/ui/components/ProfileSummaryCard.js.map +1 -1
- package/lib/commonjs/ui/components/SurfaceScreen.js +41 -5
- package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/commonjs/ui/components/oxyAuthChooserStyles.js +78 -26
- package/lib/commonjs/ui/components/oxyAuthChooserStyles.js.map +1 -1
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js +83 -23
- package/lib/commonjs/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +73 -37
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/queryKeys.js +18 -1
- package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useFileQueries.js +129 -0
- package/lib/commonjs/ui/hooks/queries/useFileQueries.js.map +1 -0
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +36 -48
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/commonjs/ui/hooks/useReduceMotion.js +57 -0
- package/lib/commonjs/ui/hooks/useReduceMotion.js.map +1 -0
- package/lib/commonjs/ui/hooks/useSurfaceHeader.js +1 -1
- package/lib/commonjs/ui/hooks/useSurfaceHeader.js.map +1 -1
- package/lib/commonjs/ui/navigation/accountDialogManager.js +22 -0
- package/lib/commonjs/ui/navigation/accountDialogManager.js.map +1 -1
- package/lib/commonjs/ui/navigation/bottomSheetManager.js +5 -6
- package/lib/commonjs/ui/navigation/bottomSheetManager.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +1 -0
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaceNavStack.js +62 -15
- package/lib/commonjs/ui/navigation/surfaceNavStack.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaceRegistry.js +38 -17
- package/lib/commonjs/ui/navigation/surfaceRegistry.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaces.js +98 -21
- package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
- package/lib/commonjs/ui/screens/AvatarCropScreen.js +281 -279
- package/lib/commonjs/ui/screens/AvatarCropScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js +301 -0
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/FileManagementScreen.js +194 -431
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +16 -48
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js +63 -0
- package/lib/commonjs/ui/screens/fileManagement/FileLibraryError.js.map +1 -0
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +54 -41
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +44 -81
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/commonjs/ui/stores/resetSessionScopedStores.js +8 -3
- package/lib/commonjs/ui/stores/resetSessionScopedStores.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +11 -2
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/commonjs/ui/utils/fileManagement.js +0 -79
- package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
- package/lib/module/ui/components/AvatarCameraBadge.js +40 -0
- package/lib/module/ui/components/AvatarCameraBadge.js.map +1 -0
- package/lib/module/ui/components/OxyAccountDialogScreen.js +41 -19
- package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +642 -171
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/ProfileButton.js +15 -1
- package/lib/module/ui/components/ProfileButton.js.map +1 -1
- package/lib/module/ui/components/ProfileSummaryCard.js +2 -23
- package/lib/module/ui/components/ProfileSummaryCard.js.map +1 -1
- package/lib/module/ui/components/SurfaceScreen.js +43 -7
- package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/module/ui/components/oxyAuthChooserStyles.js +78 -26
- package/lib/module/ui/components/oxyAuthChooserStyles.js.map +1 -1
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js +83 -25
- package/lib/module/ui/components/photogrid/JustifiedPhotoGrid.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +74 -38
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/queries/queryKeys.js +16 -0
- package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -1
- package/lib/module/ui/hooks/queries/useFileQueries.js +120 -0
- package/lib/module/ui/hooks/queries/useFileQueries.js.map +1 -0
- package/lib/module/ui/hooks/useAvatarPicker.js +37 -49
- package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/module/ui/hooks/useReduceMotion.js +53 -0
- package/lib/module/ui/hooks/useReduceMotion.js.map +1 -0
- package/lib/module/ui/hooks/useSurfaceHeader.js +1 -1
- package/lib/module/ui/hooks/useSurfaceHeader.js.map +1 -1
- package/lib/module/ui/navigation/accountDialogManager.js +20 -0
- package/lib/module/ui/navigation/accountDialogManager.js.map +1 -1
- package/lib/module/ui/navigation/bottomSheetManager.js +6 -7
- package/lib/module/ui/navigation/bottomSheetManager.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +1 -0
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/navigation/surfaceNavStack.js +62 -15
- package/lib/module/ui/navigation/surfaceNavStack.js.map +1 -1
- package/lib/module/ui/navigation/surfaceRegistry.js +38 -17
- package/lib/module/ui/navigation/surfaceRegistry.js.map +1 -1
- package/lib/module/ui/navigation/surfaces.js +97 -22
- package/lib/module/ui/navigation/surfaces.js.map +1 -1
- package/lib/module/ui/screens/AvatarCropScreen.js +283 -281
- package/lib/module/ui/screens/AvatarCropScreen.js.map +1 -1
- package/lib/module/ui/screens/ChangeAvatarScreen.js +298 -0
- package/lib/module/ui/screens/ChangeAvatarScreen.js.map +1 -0
- package/lib/module/ui/screens/FileManagementScreen.js +196 -433
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +17 -49
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/FileLibraryError.js +59 -0
- package/lib/module/ui/screens/fileManagement/FileLibraryError.js.map +1 -0
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +54 -42
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +45 -81
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/module/ui/stores/resetSessionScopedStores.js +8 -3
- package/lib/module/ui/stores/resetSessionScopedStores.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +11 -2
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/ui/utils/fileManagement.js +0 -78
- package/lib/module/ui/utils/fileManagement.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/AvatarCameraBadge.d.ts +4 -0
- package/lib/typescript/commonjs/ui/components/AvatarCameraBadge.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts +2 -1
- package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ProfileSummaryCard.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts +1 -4
- package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts +71 -19
- package/lib/typescript/commonjs/ui/components/oxyAuthChooserStyles.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/photogrid/JustifiedPhotoGrid.d.ts +10 -8
- package/lib/typescript/commonjs/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts +9 -0
- package/lib/typescript/commonjs/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useFileQueries.d.ts +50 -0
- package/lib/typescript/commonjs/ui/hooks/queries/useFileQueries.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts +15 -10
- package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useReduceMotion.d.ts +14 -0
- package/lib/typescript/commonjs/ui/hooks/useReduceMotion.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useSurfaceHeader.d.ts +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSurfaceHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts +13 -0
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/bottomSheetManager.d.ts +4 -5
- package/lib/typescript/commonjs/ui/navigation/bottomSheetManager.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts +21 -0
- package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts +73 -13
- package/lib/typescript/commonjs/ui/navigation/surfaceRegistry.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts +42 -11
- package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts +18 -5
- package/lib/typescript/commonjs/ui/screens/AvatarCropScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts +34 -0
- package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/FileLibraryError.d.ts +23 -0
- package/lib/typescript/commonjs/ui/screens/fileManagement/FileLibraryError.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts +4 -0
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +10 -2
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/stores/resetSessionScopedStores.d.ts +8 -1
- package/lib/typescript/commonjs/ui/stores/resetSessionScopedStores.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +2 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +0 -48
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AvatarCameraBadge.d.ts +4 -0
- package/lib/typescript/module/ui/components/AvatarCameraBadge.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts +2 -1
- package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ProfileSummaryCard.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SurfaceScreen.d.ts +1 -4
- package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts +71 -19
- package/lib/typescript/module/ui/components/oxyAuthChooserStyles.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/photogrid/JustifiedPhotoGrid.d.ts +10 -8
- package/lib/typescript/module/ui/components/photogrid/JustifiedPhotoGrid.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts +9 -0
- package/lib/typescript/module/ui/hooks/queries/queryKeys.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/useFileQueries.d.ts +50 -0
- package/lib/typescript/module/ui/hooks/queries/useFileQueries.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts +15 -10
- package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useReduceMotion.d.ts +14 -0
- package/lib/typescript/module/ui/hooks/useReduceMotion.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useSurfaceHeader.d.ts +1 -1
- package/lib/typescript/module/ui/hooks/useSurfaceHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts +13 -0
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts +4 -5
- package/lib/typescript/module/ui/navigation/bottomSheetManager.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts +21 -0
- package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts +73 -13
- package/lib/typescript/module/ui/navigation/surfaceRegistry.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaces.d.ts +42 -11
- package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts +18 -5
- package/lib/typescript/module/ui/screens/AvatarCropScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts +34 -0
- package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/FileLibraryError.d.ts +23 -0
- package/lib/typescript/module/ui/screens/fileManagement/FileLibraryError.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts +4 -0
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +10 -2
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/module/ui/stores/resetSessionScopedStores.d.ts +8 -1
- package/lib/typescript/module/ui/stores/resetSessionScopedStores.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +2 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/fileManagement.d.ts +0 -48
- package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/ui/components/AvatarCameraBadge.tsx +35 -0
- package/src/ui/components/OxyAccountDialogScreen.tsx +38 -15
- package/src/ui/components/OxyAuthChooser.tsx +722 -185
- package/src/ui/components/ProfileButton.tsx +16 -1
- package/src/ui/components/ProfileSummaryCard.tsx +2 -25
- package/src/ui/components/SurfaceScreen.tsx +48 -14
- package/src/ui/components/oxyAuthChooserStyles.ts +75 -23
- package/src/ui/components/photogrid/JustifiedPhotoGrid.tsx +158 -84
- package/src/ui/components/photogrid/__tests__/chunkPhotos.test.ts +51 -0
- package/src/ui/context/OxyContext.tsx +74 -34
- package/src/ui/hooks/queries/queryKeys.ts +15 -0
- package/src/ui/hooks/queries/useFileQueries.ts +162 -0
- package/src/ui/hooks/useAvatarPicker.ts +38 -53
- package/src/ui/hooks/useReduceMotion.ts +58 -0
- package/src/ui/hooks/useSurfaceHeader.ts +2 -1
- package/src/ui/navigation/__tests__/getSurfaceConfig.test.ts +55 -7
- package/src/ui/navigation/__tests__/surfaceNavStack.test.ts +81 -0
- package/src/ui/navigation/accountDialogManager.ts +28 -0
- package/src/ui/navigation/bottomSheetManager.ts +6 -7
- package/src/ui/navigation/routes.ts +3 -1
- package/src/ui/navigation/surfaceNavStack.ts +72 -9
- package/src/ui/navigation/surfaceRegistry.ts +91 -17
- package/src/ui/navigation/surfaces.ts +108 -29
- package/src/ui/screens/AvatarCropScreen.tsx +336 -298
- package/src/ui/screens/ChangeAvatarScreen.tsx +359 -0
- package/src/ui/screens/FileManagementScreen.tsx +189 -432
- package/src/ui/screens/WelcomeNewUserScreen.tsx +18 -48
- package/src/ui/screens/fileManagement/FileLibraryError.tsx +56 -0
- package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +56 -46
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +55 -71
- package/src/ui/stores/resetSessionScopedStores.ts +8 -3
- package/src/ui/types/navigation.ts +2 -0
- package/src/ui/utils/avatarUtils.ts +11 -2
- package/src/ui/utils/fileManagement.ts +1 -101
- package/lib/commonjs/ui/stores/fileStore.js +0 -153
- package/lib/commonjs/ui/stores/fileStore.js.map +0 -1
- package/lib/module/ui/stores/fileStore.js +0 -145
- package/lib/module/ui/stores/fileStore.js.map +0 -1
- package/lib/typescript/commonjs/ui/stores/fileStore.d.ts +0 -31
- package/lib/typescript/commonjs/ui/stores/fileStore.d.ts.map +0 -1
- package/lib/typescript/module/ui/stores/fileStore.d.ts +0 -31
- package/lib/typescript/module/ui/stores/fileStore.d.ts.map +0 -1
- package/src/ui/stores/fileStore.ts +0 -118
|
@@ -6,18 +6,21 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
|
+
var _reactQuery = require("@tanstack/react-query");
|
|
9
10
|
var _expoImage = require("expo-image");
|
|
10
11
|
var _bloom = require("@oxyhq/bloom");
|
|
11
12
|
var _surfaces = require("@oxyhq/bloom/surfaces");
|
|
12
13
|
var Skeleton = _interopRequireWildcard(require("@oxyhq/bloom/skeleton"));
|
|
13
14
|
var _vectorIcons = require("@expo/vector-icons");
|
|
14
|
-
var
|
|
15
|
+
var _queryKeys = require("../hooks/queries/queryKeys.js");
|
|
16
|
+
var _useFileQueries = require("../hooks/queries/useFileQueries.js");
|
|
15
17
|
var _useSurfaceHeader = require("../hooks/useSurfaceHeader.js");
|
|
16
18
|
var _SurfaceHeaderAction = require("../components/SurfaceHeaderAction.js");
|
|
17
19
|
var _JustifiedPhotoGrid = _interopRequireDefault(require("../components/photogrid/JustifiedPhotoGrid.js"));
|
|
18
20
|
var _theme = require("@oxyhq/bloom/theme");
|
|
19
21
|
var _OxyContext = require("../context/OxyContext.js");
|
|
20
22
|
var _useI18n = require("../hooks/useI18n.js");
|
|
23
|
+
var _useReduceMotion = require("../hooks/useReduceMotion.js");
|
|
21
24
|
var _useAccountMutations = require("../hooks/mutations/useAccountMutations.js");
|
|
22
25
|
var _fileManagement = require("../utils/fileManagement.js");
|
|
23
26
|
var _useResolvedFileUrls = require("../hooks/useResolvedFileUrls.js");
|
|
@@ -29,6 +32,7 @@ var _shared = require("./fileManagement/shared.js");
|
|
|
29
32
|
var _useFileUploadState = require("./fileManagement/hooks/useFileUploadState.js");
|
|
30
33
|
var _PhotoPickerSection = _interopRequireDefault(require("./fileManagement/PhotoPickerSection.js"));
|
|
31
34
|
var _FileListSection = _interopRequireDefault(require("./fileManagement/FileListSection.js"));
|
|
35
|
+
var _FileLibraryError = _interopRequireDefault(require("./fileManagement/FileLibraryError.js"));
|
|
32
36
|
var _UploadBar = _interopRequireDefault(require("./fileManagement/UploadBar.js"));
|
|
33
37
|
var _AnimatedButton = require("../components/fileManagement/AnimatedButton.js");
|
|
34
38
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -61,11 +65,6 @@ const screenStyles = _reactNative.StyleSheet.create({
|
|
|
61
65
|
justifyContent: 'center',
|
|
62
66
|
marginHorizontal: 1
|
|
63
67
|
},
|
|
64
|
-
photoImage: {
|
|
65
|
-
width: '100%',
|
|
66
|
-
height: '100%',
|
|
67
|
-
borderRadius: 8
|
|
68
|
-
},
|
|
69
68
|
justifiedPhotoImage: {
|
|
70
69
|
width: '100%',
|
|
71
70
|
height: '100%',
|
|
@@ -74,7 +73,6 @@ const screenStyles = _reactNative.StyleSheet.create({
|
|
|
74
73
|
});
|
|
75
74
|
const FileManagementScreen = ({
|
|
76
75
|
onClose,
|
|
77
|
-
theme,
|
|
78
76
|
goBack,
|
|
79
77
|
navigate,
|
|
80
78
|
dismiss,
|
|
@@ -103,50 +101,49 @@ const FileManagementScreen = ({
|
|
|
103
101
|
const {
|
|
104
102
|
t
|
|
105
103
|
} = (0, _useI18n.useI18n)();
|
|
104
|
+
const queryClient = (0, _reactQuery.useQueryClient)();
|
|
106
105
|
const uploadFileMutation = (0, _useAccountMutations.useUploadFile)();
|
|
107
|
-
|
|
106
|
+
|
|
107
|
+
// Files are owned by the ACTIVE account. `targetUserId` scopes the query key,
|
|
108
|
+
// so switching accounts (or an explicit `userId` prop) shows that account's
|
|
109
|
+
// library with no manual reset.
|
|
110
|
+
const targetUserId = userId || user?.id;
|
|
111
|
+
|
|
112
|
+
// The file list is React Query's, NOT a store: infinite-paginated, fetched on
|
|
113
|
+
// mount + on owner change, edited optimistically via cache helpers. The
|
|
114
|
+
// rendered list is the flattened pages.
|
|
115
|
+
const filesQuery = (0, _useFileQueries.useUserFilesInfinite)(targetUserId);
|
|
116
|
+
const files = (0, _react.useMemo)(() => filesQuery.data?.pages.flatMap(page => page.files) ?? [], [filesQuery.data]);
|
|
117
|
+
// No owner resolved yet reads as "loading" (matches the old skeleton-until-
|
|
118
|
+
// first-load behaviour); `isLoading` is the first-page fetch only.
|
|
119
|
+
const isLoadingFiles = !targetUserId || filesQuery.isLoading;
|
|
120
|
+
const isRefreshingFiles = filesQuery.isRefetching;
|
|
121
|
+
const isFetchingMore = filesQuery.isFetchingNextPage;
|
|
122
|
+
const hasMoreFiles = filesQuery.hasNextPage ?? false;
|
|
123
|
+
// Terminal load failure with nothing cached — render a DISTINCT error state
|
|
124
|
+
// (not the empty state) so a failed load never looks like an empty library.
|
|
125
|
+
const hasLoadError = filesQuery.isError && files.length === 0;
|
|
126
|
+
const invalidateFiles = (0, _react.useCallback)(() => {
|
|
127
|
+
queryClient.invalidateQueries({
|
|
128
|
+
queryKey: _queryKeys.queryKeys.files.list(targetUserId)
|
|
129
|
+
});
|
|
130
|
+
}, [queryClient, targetUserId]);
|
|
108
131
|
const {
|
|
109
132
|
width: windowWidth
|
|
110
133
|
} = (0, _reactNative.useWindowDimensions)();
|
|
111
134
|
// Prefer an explicit sheet width from the router; fall back to the window
|
|
112
135
|
// so photo grids never size against a hardcoded 400px default.
|
|
113
136
|
const safeContainerWidth = typeof containerWidth === 'number' && containerWidth > 0 ? containerWidth : windowWidth;
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
const deleting = (0, _fileStore.useDeleting)();
|
|
117
|
-
const [loading, setLoading] = (0, _react.useState)(true);
|
|
118
|
-
const [refreshing, setRefreshing] = (0, _react.useState)(false);
|
|
119
|
-
const [paging, setPaging] = (0, _react.useState)({
|
|
120
|
-
offset: 0,
|
|
121
|
-
limit: 40,
|
|
122
|
-
total: 0,
|
|
123
|
-
hasMore: true,
|
|
124
|
-
loadingMore: false
|
|
125
|
-
});
|
|
137
|
+
// In-flight delete target (local UI state — was in the file store).
|
|
138
|
+
const [deletingId, setDeletingId] = (0, _react.useState)(null);
|
|
126
139
|
// In selectMode we never open the detailed viewer
|
|
127
140
|
const [openedFile, setOpenedFile] = (0, _react.useState)(null);
|
|
128
141
|
const [fileContent, setFileContent] = (0, _react.useState)(null);
|
|
129
142
|
const [loadingFileContent, setLoadingFileContent] = (0, _react.useState)(false);
|
|
130
143
|
const [showFileDetailsInViewer, setShowFileDetailsInViewer] = (0, _react.useState)(false);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// Used by `PhotoPickerView` to skip cell stagger animations.
|
|
135
|
-
(0, _react.useEffect)(() => {
|
|
136
|
-
let cancelled = false;
|
|
137
|
-
_reactNative.AccessibilityInfo.isReduceMotionEnabled().then(enabled => {
|
|
138
|
-
if (!cancelled) setReduceMotion(enabled);
|
|
139
|
-
}).catch(() => {
|
|
140
|
-
// Defaults to false; no action needed.
|
|
141
|
-
});
|
|
142
|
-
const sub = _reactNative.AccessibilityInfo.addEventListener('reduceMotionChanged', enabled => {
|
|
143
|
-
setReduceMotion(enabled);
|
|
144
|
-
});
|
|
145
|
-
return () => {
|
|
146
|
-
cancelled = true;
|
|
147
|
-
sub.remove();
|
|
148
|
-
};
|
|
149
|
-
}, []);
|
|
144
|
+
// Reduce-motion preference, read as an external store (no effect). Passed to
|
|
145
|
+
// `PhotoPickerView` to skip cell stagger animations.
|
|
146
|
+
const reduceMotion = (0, _useReduceMotion.useReduceMotion)();
|
|
150
147
|
|
|
151
148
|
// Image-only picker mode: when the consumer restricts to image MIME types
|
|
152
149
|
// (e.g. avatar picker), photos grid is the more useful default view.
|
|
@@ -198,24 +195,59 @@ const FileManagementScreen = ({
|
|
|
198
195
|
});
|
|
199
196
|
return sorted;
|
|
200
197
|
}, [files, searchQuery, viewMode, sortBy, sortOrder]);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const [
|
|
205
|
-
// Selection state
|
|
206
|
-
const [selectedIds, setSelectedIds] = (0, _react.useState)(new Set(initialSelectedIds));
|
|
207
|
-
const [lastSelectedFileId, setLastSelectedFileId] = (0, _react.useState)(null);
|
|
198
|
+
// Selection state. `initialSelectedIds` is the INITIAL selection only (lazy
|
|
199
|
+
// init) — there is no prop→state sync effect, since no caller mutates it
|
|
200
|
+
// after mount.
|
|
201
|
+
const [selectedIds, setSelectedIds] = (0, _react.useState)(() => new Set(initialSelectedIds));
|
|
208
202
|
const scrollViewRef = (0, _react.useRef)(null);
|
|
209
203
|
const photoScrollViewRef = (0, _react.useRef)(null);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
204
|
+
|
|
205
|
+
// Scroll the browse list/grid to a just-selected file. Driven directly from
|
|
206
|
+
// the selection event handler (double-rAF so the selection re-render has
|
|
207
|
+
// committed first) — not an effect. No-ops in the image-only picker, whose
|
|
208
|
+
// own FlatList is not either ScrollView ref.
|
|
209
|
+
const scrollToSelectedFile = (0, _react.useCallback)(fileId => {
|
|
210
|
+
if (viewMode === 'all' && scrollViewRef.current) {
|
|
211
|
+
const itemIndex = filteredFiles.findIndex(file => file.id === fileId);
|
|
212
|
+
if (itemIndex < 0) return;
|
|
213
|
+
// GroupedItem dense rows are ~65px, +30px when a description wraps.
|
|
214
|
+
const baseItemHeight = 65;
|
|
215
|
+
const descriptionHeight = 30;
|
|
216
|
+
let scrollPosition = 0;
|
|
217
|
+
for (let i = 0; i <= itemIndex && i < filteredFiles.length; i++) {
|
|
218
|
+
scrollPosition += baseItemHeight;
|
|
219
|
+
if (filteredFiles[i].metadata?.description) scrollPosition += descriptionHeight;
|
|
220
|
+
}
|
|
221
|
+
// Offset for the header/controls/search/stats chrome (~250px) so the
|
|
222
|
+
// item lands near the top, not under the chrome.
|
|
223
|
+
const finalScrollPosition = 250 + scrollPosition - 150;
|
|
224
|
+
requestAnimationFrame(() => {
|
|
225
|
+
requestAnimationFrame(() => {
|
|
226
|
+
scrollViewRef.current?.scrollTo({
|
|
227
|
+
y: Math.max(0, finalScrollPosition),
|
|
228
|
+
animated: true
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
} else if (viewMode === 'photos' && photoScrollViewRef.current) {
|
|
233
|
+
const photos = filteredFiles.filter(file => file.contentType.startsWith('image/'));
|
|
234
|
+
const photoIndex = photos.findIndex(p => p.id === fileId);
|
|
235
|
+
if (photoIndex < 0) return;
|
|
236
|
+
// Rough estimate for the justified grid (3 photos/row, variable heights).
|
|
237
|
+
const row = Math.floor(photoIndex / 3);
|
|
238
|
+
const finalScrollPosition = row * (150 + 4) - 100;
|
|
239
|
+
requestAnimationFrame(() => {
|
|
240
|
+
requestAnimationFrame(() => {
|
|
241
|
+
photoScrollViewRef.current?.scrollTo({
|
|
242
|
+
y: Math.max(0, finalScrollPosition),
|
|
243
|
+
animated: true
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
});
|
|
214
247
|
}
|
|
215
|
-
}, [
|
|
248
|
+
}, [viewMode, filteredFiles]);
|
|
216
249
|
const toggleSelect = (0, _react.useCallback)(async file => {
|
|
217
|
-
//
|
|
218
|
-
// if (!selectMode) return;
|
|
250
|
+
// Selection is allowed in regular mode too (for bulk operations).
|
|
219
251
|
if (disabledMimeTypes.length) {
|
|
220
252
|
const blocked = disabledMimeTypes.some(mt => file.contentType === mt || file.contentType.startsWith(mt.endsWith('/') ? mt : `${mt}/`));
|
|
221
253
|
if (blocked) {
|
|
@@ -234,9 +266,6 @@ const FileManagementScreen = ({
|
|
|
234
266
|
}
|
|
235
267
|
}
|
|
236
268
|
|
|
237
|
-
// Track the selected file for scrolling
|
|
238
|
-
setLastSelectedFileId(file.id);
|
|
239
|
-
|
|
240
269
|
// Link file to entity if linkContext is provided
|
|
241
270
|
if (linkContext) {
|
|
242
271
|
try {
|
|
@@ -278,13 +307,14 @@ const FileManagementScreen = ({
|
|
|
278
307
|
}
|
|
279
308
|
return next;
|
|
280
309
|
});
|
|
281
|
-
|
|
310
|
+
scrollToSelectedFile(file.id);
|
|
311
|
+
}, [multiSelect, onSelect, onClose, goBack, dismiss, disabledMimeTypes, maxSelection, afterSelect, defaultVisibility, oxyServices, linkContext, t, scrollToSelectedFile]);
|
|
282
312
|
const confirmMultiSelection = (0, _react.useCallback)(async () => {
|
|
283
313
|
if (!selectMode || !multiSelect) return;
|
|
284
314
|
const map = {};
|
|
285
|
-
|
|
315
|
+
for (const f of files) {
|
|
286
316
|
map[f.id] = f;
|
|
287
|
-
}
|
|
317
|
+
}
|
|
288
318
|
const chosen = Array.from(selectedIds).map(id => map[id]).filter(Boolean);
|
|
289
319
|
|
|
290
320
|
// Update visibility and link files if needed
|
|
@@ -338,81 +368,16 @@ const FileManagementScreen = ({
|
|
|
338
368
|
// FileManagementScreen uses a slightly elevated page background.
|
|
339
369
|
const backgroundColor = colors.backgroundSecondary;
|
|
340
370
|
const borderColor = colors.border;
|
|
341
|
-
const targetUserId = userId || user?.id;
|
|
342
|
-
const storeSetDeleting = (0, _fileStore.useFileStore)(s => s.setDeleting);
|
|
343
|
-
const loadFiles = (0, _react.useCallback)(async (mode = 'initial') => {
|
|
344
|
-
if (!targetUserId) return;
|
|
345
|
-
try {
|
|
346
|
-
if (mode === 'refresh') {
|
|
347
|
-
setRefreshing(true);
|
|
348
|
-
} else if (mode === 'initial') {
|
|
349
|
-
setLoading(true);
|
|
350
|
-
setPaging(p => ({
|
|
351
|
-
...p,
|
|
352
|
-
offset: 0,
|
|
353
|
-
hasMore: true
|
|
354
|
-
}));
|
|
355
|
-
} else if (mode === 'more') {
|
|
356
|
-
// Prevent duplicate fetches
|
|
357
|
-
setPaging(p => ({
|
|
358
|
-
...p,
|
|
359
|
-
loadingMore: true
|
|
360
|
-
}));
|
|
361
|
-
}
|
|
362
|
-
const currentPaging = mode === 'more' ? prevPagingRef.current ?? paging : paging;
|
|
363
|
-
const effectiveOffset = mode === 'more' ? currentPaging.offset + currentPaging.limit : 0;
|
|
364
|
-
const response = await oxyServices.listUserFiles(currentPaging.limit, effectiveOffset);
|
|
365
|
-
const assets = (response.files || []).map(f => ({
|
|
366
|
-
id: f.id,
|
|
367
|
-
filename: f.originalName ?? f.sha256 ?? '',
|
|
368
|
-
contentType: f.mime ?? '',
|
|
369
|
-
length: f.size ?? 0,
|
|
370
|
-
chunkSize: 0,
|
|
371
|
-
uploadDate: f.createdAt ?? '',
|
|
372
|
-
metadata: f.metadata ?? {},
|
|
373
|
-
variants: f.variants ?? []
|
|
374
|
-
}));
|
|
375
|
-
if (mode === 'more') {
|
|
376
|
-
// append
|
|
377
|
-
_fileStore.useFileStore.getState().setFiles(assets, {
|
|
378
|
-
merge: true
|
|
379
|
-
});
|
|
380
|
-
setPaging(p => ({
|
|
381
|
-
...p,
|
|
382
|
-
offset: effectiveOffset,
|
|
383
|
-
total: response.total || effectiveOffset + assets.length,
|
|
384
|
-
hasMore: response.hasMore,
|
|
385
|
-
loadingMore: false
|
|
386
|
-
}));
|
|
387
|
-
} else {
|
|
388
|
-
_fileStore.useFileStore.getState().setFiles(assets, {
|
|
389
|
-
merge: false
|
|
390
|
-
});
|
|
391
|
-
setPaging(p => ({
|
|
392
|
-
...p,
|
|
393
|
-
offset: 0,
|
|
394
|
-
total: response.total || assets.length,
|
|
395
|
-
hasMore: response.hasMore,
|
|
396
|
-
loadingMore: false
|
|
397
|
-
}));
|
|
398
|
-
}
|
|
399
|
-
} catch (error) {
|
|
400
|
-
_bloom.toast.error((0, _shared.getErrorMessage)(error) || t('fileManagement.toasts.loadFailed'));
|
|
401
|
-
} finally {
|
|
402
|
-
setLoading(false);
|
|
403
|
-
setRefreshing(false);
|
|
404
|
-
setPaging(p => ({
|
|
405
|
-
...p,
|
|
406
|
-
loadingMore: false
|
|
407
|
-
}));
|
|
408
|
-
}
|
|
409
|
-
}, [targetUserId, oxyServices, paging]);
|
|
410
371
|
|
|
411
372
|
// Self-contained document-picking + upload-preview state and handlers.
|
|
373
|
+
// Optimistic uploads edit the file query cache directly (see
|
|
374
|
+
// useFileQueries), so no loader is threaded in.
|
|
412
375
|
const {
|
|
413
376
|
isPickingDocument,
|
|
414
377
|
pendingFiles,
|
|
415
378
|
showUploadPreview,
|
|
379
|
+
uploading,
|
|
380
|
+
uploadProgress,
|
|
416
381
|
handleFileUpload,
|
|
417
382
|
handleConfirmUpload,
|
|
418
383
|
handleCancelUpload,
|
|
@@ -429,105 +394,8 @@ const FileManagementScreen = ({
|
|
|
429
394
|
onClose,
|
|
430
395
|
selectedIds,
|
|
431
396
|
setSelectedIds,
|
|
432
|
-
loadFiles,
|
|
433
397
|
t
|
|
434
398
|
});
|
|
435
|
-
|
|
436
|
-
// Keep a ref to avoid stale closure when calculating next offset
|
|
437
|
-
const prevPagingRef = (0, _react.useRef)(paging);
|
|
438
|
-
(0, _react.useEffect)(() => {
|
|
439
|
-
prevPagingRef.current = paging;
|
|
440
|
-
}, [paging]);
|
|
441
|
-
|
|
442
|
-
// (removed effect; filteredFiles is memoized)
|
|
443
|
-
|
|
444
|
-
// Load photo dimensions for justified grid - unified approach using Image.getSize
|
|
445
|
-
const loadPhotoDimensions = (0, _react.useCallback)(async photos => {
|
|
446
|
-
if (photos.length === 0) return;
|
|
447
|
-
setLoadingDimensions(true);
|
|
448
|
-
|
|
449
|
-
// Snapshot ids missing from the cache at kick-off; concurrent runs may
|
|
450
|
-
// overlap but each merge is applied via a functional updater.
|
|
451
|
-
const photosToLoad = photos.filter(photo => !photoDimensionsRef.current[photo.id]);
|
|
452
|
-
if (photosToLoad.length === 0) {
|
|
453
|
-
setLoadingDimensions(false);
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
try {
|
|
457
|
-
const measured = {};
|
|
458
|
-
await Promise.all(photosToLoad.map(async photo => {
|
|
459
|
-
try {
|
|
460
|
-
const downloadUrl = thumbSourceFor(photo);
|
|
461
|
-
// URL not resolved yet — skip (do NOT record fallback
|
|
462
|
-
// dims) so this photo is re-measured once its private-safe
|
|
463
|
-
// URL resolves. Measuring the broken public URL is exactly
|
|
464
|
-
// the bug we are fixing.
|
|
465
|
-
if (!downloadUrl) {
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
// Unified approach using Image.getSize (works on all platforms)
|
|
470
|
-
await new Promise(resolve => {
|
|
471
|
-
_reactNative.Image.getSize(downloadUrl, (width, height) => {
|
|
472
|
-
measured[photo.id] = {
|
|
473
|
-
width,
|
|
474
|
-
height
|
|
475
|
-
};
|
|
476
|
-
resolve();
|
|
477
|
-
}, () => {
|
|
478
|
-
// Fallback dimensions
|
|
479
|
-
measured[photo.id] = {
|
|
480
|
-
width: 1,
|
|
481
|
-
height: 1
|
|
482
|
-
};
|
|
483
|
-
resolve();
|
|
484
|
-
});
|
|
485
|
-
});
|
|
486
|
-
} catch (error) {
|
|
487
|
-
// Fallback dimensions for any errors
|
|
488
|
-
measured[photo.id] = {
|
|
489
|
-
width: 1,
|
|
490
|
-
height: 1
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
}));
|
|
494
|
-
if (Object.keys(measured).length > 0) {
|
|
495
|
-
setPhotoDimensions(prev => ({
|
|
496
|
-
...prev,
|
|
497
|
-
...measured
|
|
498
|
-
}));
|
|
499
|
-
}
|
|
500
|
-
} catch (error) {
|
|
501
|
-
// Photo dimensions loading failed, continue without dimensions
|
|
502
|
-
} finally {
|
|
503
|
-
setLoadingDimensions(false);
|
|
504
|
-
}
|
|
505
|
-
}, [thumbSourceFor]);
|
|
506
|
-
|
|
507
|
-
// Re-measure photo dimensions when their private-safe URLs resolve. The
|
|
508
|
-
// justified grid's own trigger fires on the photo SET, not on URL
|
|
509
|
-
// availability, so newly-resolved private tiles would otherwise keep their
|
|
510
|
-
// skipped (unmeasured) state and render with fallback geometry.
|
|
511
|
-
(0, _react.useEffect)(() => {
|
|
512
|
-
if (viewMode !== 'photos') return;
|
|
513
|
-
const photos = filteredFiles.filter(file => file.contentType.startsWith('image/'));
|
|
514
|
-
if (photos.length > 0) {
|
|
515
|
-
loadPhotoDimensions(photos);
|
|
516
|
-
}
|
|
517
|
-
}, [resolvedThumbUrls, viewMode, filteredFiles, loadPhotoDimensions]);
|
|
518
|
-
|
|
519
|
-
// Create justified rows from photos with responsive algorithm
|
|
520
|
-
const createJustifiedRows = (0, _react.useCallback)((photos, containerWidth) => {
|
|
521
|
-
if (photos.length === 0) return [];
|
|
522
|
-
const rows = [];
|
|
523
|
-
const photosPerRow = 3; // Fixed 3 photos per row for consistency
|
|
524
|
-
|
|
525
|
-
for (let i = 0; i < photos.length; i += photosPerRow) {
|
|
526
|
-
const rowPhotos = photos.slice(i, i + photosPerRow);
|
|
527
|
-
rows.push(rowPhotos);
|
|
528
|
-
}
|
|
529
|
-
return rows;
|
|
530
|
-
}, []);
|
|
531
399
|
const confirmFileDelete = (0, _react.useCallback)(async (fileId, filename) => {
|
|
532
400
|
const confirmed = await _surfaces.surfaces.confirm({
|
|
533
401
|
title: t('fileManagement.deleteFile') || 'Delete File',
|
|
@@ -540,30 +408,28 @@ const FileManagementScreen = ({
|
|
|
540
408
|
});
|
|
541
409
|
if (!confirmed) return;
|
|
542
410
|
try {
|
|
543
|
-
|
|
411
|
+
setDeletingId(fileId);
|
|
544
412
|
await oxyServices.deleteFile(fileId);
|
|
545
413
|
_bloom.toast.success(t('fileManagement.toasts.deleteSuccess'));
|
|
546
414
|
|
|
547
|
-
//
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
// Silent background reconcile
|
|
551
|
-
setTimeout(() => loadFiles('silent'), 800);
|
|
415
|
+
// Remove from the query cache, then reconcile against the server.
|
|
416
|
+
(0, _useFileQueries.removeFileFromCache)(queryClient, targetUserId, fileId);
|
|
417
|
+
invalidateFiles();
|
|
552
418
|
} catch (error) {
|
|
553
419
|
// Provide specific error messages
|
|
554
420
|
if ((0, _shared.getErrorMessage)(error)?.includes('File not found') || (0, _shared.getErrorMessage)(error)?.includes('404')) {
|
|
555
421
|
_bloom.toast.error(t('fileManagement.toasts.fileNotFound'));
|
|
556
|
-
//
|
|
557
|
-
|
|
422
|
+
// It's already gone server-side — reconcile the list.
|
|
423
|
+
invalidateFiles();
|
|
558
424
|
} else if ((0, _shared.getErrorMessage)(error)?.includes('permission') || (0, _shared.getErrorMessage)(error)?.includes('403')) {
|
|
559
425
|
_bloom.toast.error(t('fileManagement.toasts.noPermission'));
|
|
560
426
|
} else {
|
|
561
427
|
_bloom.toast.error((0, _shared.getErrorMessage)(error) || t('fileManagement.toasts.deleteFailed'));
|
|
562
428
|
}
|
|
563
429
|
} finally {
|
|
564
|
-
|
|
430
|
+
setDeletingId(null);
|
|
565
431
|
}
|
|
566
|
-
}, [
|
|
432
|
+
}, [oxyServices, queryClient, targetUserId, invalidateFiles, t]);
|
|
567
433
|
const confirmBulkDelete = (0, _react.useCallback)(async () => {
|
|
568
434
|
if (selectedIds.size === 0) return;
|
|
569
435
|
const confirmed = await _surfaces.surfaces.confirm({
|
|
@@ -580,7 +446,7 @@ const FileManagementScreen = ({
|
|
|
580
446
|
const deletePromises = Array.from(selectedIds).map(async fileId => {
|
|
581
447
|
try {
|
|
582
448
|
await oxyServices.deleteFile(fileId);
|
|
583
|
-
|
|
449
|
+
(0, _useFileQueries.removeFileFromCache)(queryClient, targetUserId, fileId);
|
|
584
450
|
return {
|
|
585
451
|
success: true,
|
|
586
452
|
fileId
|
|
@@ -607,11 +473,11 @@ const FileManagementScreen = ({
|
|
|
607
473
|
}));
|
|
608
474
|
}
|
|
609
475
|
setSelectedIds(new Set());
|
|
610
|
-
|
|
476
|
+
invalidateFiles();
|
|
611
477
|
} catch (error) {
|
|
612
478
|
_bloom.toast.error((0, _shared.getErrorMessage)(error) || t('fileManagement.toasts.bulkDeleteError'));
|
|
613
479
|
}
|
|
614
|
-
}, [selectedIds, oxyServices,
|
|
480
|
+
}, [selectedIds, oxyServices, queryClient, targetUserId, invalidateFiles, t]);
|
|
615
481
|
const handleBulkVisibilityChange = (0, _react.useCallback)(async visibility => {
|
|
616
482
|
if (selectedIds.size === 0) return;
|
|
617
483
|
try {
|
|
@@ -638,26 +504,23 @@ const FileManagementScreen = ({
|
|
|
638
504
|
count: successful,
|
|
639
505
|
visibility
|
|
640
506
|
}));
|
|
641
|
-
//
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
...files.find(f => f.id === fileId)?.metadata,
|
|
646
|
-
visibility
|
|
647
|
-
}
|
|
507
|
+
// Reflect the new visibility in the cached files.
|
|
508
|
+
for (const fileId of selectedIds) {
|
|
509
|
+
(0, _useFileQueries.patchFileMetadataInCache)(queryClient, targetUserId, fileId, {
|
|
510
|
+
visibility
|
|
648
511
|
});
|
|
649
|
-
}
|
|
512
|
+
}
|
|
650
513
|
}
|
|
651
514
|
if (failed > 0) {
|
|
652
515
|
_bloom.toast.error(t('fileManagement.toasts.visibilityFailed', {
|
|
653
516
|
count: failed
|
|
654
517
|
}));
|
|
655
518
|
}
|
|
656
|
-
|
|
519
|
+
invalidateFiles();
|
|
657
520
|
} catch (error) {
|
|
658
521
|
_bloom.toast.error((0, _shared.getErrorMessage)(error) || t('fileManagement.toasts.visibilityError'));
|
|
659
522
|
}
|
|
660
|
-
}, [selectedIds, oxyServices,
|
|
523
|
+
}, [selectedIds, oxyServices, queryClient, targetUserId, invalidateFiles, t]);
|
|
661
524
|
const handleVisibilityChange = (0, _react.useCallback)(async () => {
|
|
662
525
|
if (selectedIds.size === 0) return;
|
|
663
526
|
const visibility = await (0, _ActionSheetSurface.presentActionSheet)({
|
|
@@ -681,7 +544,7 @@ const FileManagementScreen = ({
|
|
|
681
544
|
}, [selectedIds.size, handleBulkVisibilityChange, t]);
|
|
682
545
|
|
|
683
546
|
// Unified download function - works on all platforms
|
|
684
|
-
const handleFileDownload = async (fileId, filename) => {
|
|
547
|
+
const handleFileDownload = (0, _react.useCallback)(async (fileId, filename) => {
|
|
685
548
|
try {
|
|
686
549
|
// Resolve an authenticated, private-safe URL. The synchronous
|
|
687
550
|
// `getFileDownloadUrl` yields the public CDN origin, which 404s for
|
|
@@ -724,8 +587,8 @@ const FileManagementScreen = ({
|
|
|
724
587
|
} catch (error) {
|
|
725
588
|
_bloom.toast.error((0, _shared.getErrorMessage)(error) || t('fileManagement.toasts.downloadFailed'));
|
|
726
589
|
}
|
|
727
|
-
};
|
|
728
|
-
const handleFileOpen = async file => {
|
|
590
|
+
}, [oxyServices, t]);
|
|
591
|
+
const handleFileOpen = (0, _react.useCallback)(async file => {
|
|
729
592
|
if (selectMode) {
|
|
730
593
|
toggleSelect(file);
|
|
731
594
|
return;
|
|
@@ -765,21 +628,21 @@ const FileManagementScreen = ({
|
|
|
765
628
|
} finally {
|
|
766
629
|
setLoadingFileContent(false);
|
|
767
630
|
}
|
|
768
|
-
};
|
|
769
|
-
const handleCloseFile = () => {
|
|
631
|
+
}, [selectMode, toggleSelect, oxyServices, t]);
|
|
632
|
+
const handleCloseFile = (0, _react.useCallback)(() => {
|
|
770
633
|
setOpenedFile(null);
|
|
771
634
|
setFileContent(null);
|
|
772
635
|
setShowFileDetailsInViewer(false);
|
|
773
636
|
// Don't reset view mode when closing a file
|
|
774
|
-
};
|
|
775
|
-
const showFileDetailsModal = file => {
|
|
637
|
+
}, []);
|
|
638
|
+
const showFileDetailsModal = (0, _react.useCallback)(file => {
|
|
776
639
|
(0, _FileDetailsModal.presentFileDetails)({
|
|
777
640
|
file,
|
|
778
641
|
onDownload: handleFileDownload,
|
|
779
642
|
onDelete: confirmFileDelete,
|
|
780
643
|
isOwner: user?.id === targetUserId
|
|
781
644
|
});
|
|
782
|
-
};
|
|
645
|
+
}, [handleFileDownload, confirmFileDelete, user?.id, targetUserId]);
|
|
783
646
|
const renderJustifiedPhotoItem = (0, _react.useCallback)((photo, width, height, isLast) => {
|
|
784
647
|
const downloadUrl = thumbSourceFor(photo);
|
|
785
648
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
@@ -824,18 +687,7 @@ const FileManagementScreen = ({
|
|
|
824
687
|
})]
|
|
825
688
|
})
|
|
826
689
|
}, photo.id);
|
|
827
|
-
}, [thumbSourceFor, selectMode, selectedIds, multiSelect, colors.primary, colors.text]);
|
|
828
|
-
|
|
829
|
-
// Run initial load once per targetUserId change to avoid accidental loops
|
|
830
|
-
const lastLoadedFor = (0, _react.useRef)(undefined);
|
|
831
|
-
(0, _react.useEffect)(() => {
|
|
832
|
-
const key = targetUserId || 'anonymous';
|
|
833
|
-
if (lastLoadedFor.current !== key) {
|
|
834
|
-
lastLoadedFor.current = key;
|
|
835
|
-
loadFiles('initial');
|
|
836
|
-
}
|
|
837
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
838
|
-
}, [targetUserId]);
|
|
690
|
+
}, [thumbSourceFor, selectMode, selectedIds, multiSelect, colors.primary, colors.text, handleFileOpen]);
|
|
839
691
|
|
|
840
692
|
// SettingsListItem-based file items (for 'all' view)
|
|
841
693
|
const groupedFileItems = (0, _react.useMemo)(() => {
|
|
@@ -986,8 +838,8 @@ const FileManagementScreen = ({
|
|
|
986
838
|
backgroundColor: colors.negativeSubtle
|
|
987
839
|
},
|
|
988
840
|
onPress: () => confirmFileDelete(file.id, file.filename),
|
|
989
|
-
disabled:
|
|
990
|
-
children:
|
|
841
|
+
disabled: deletingId === file.id,
|
|
842
|
+
children: deletingId === file.id ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
991
843
|
size: "small",
|
|
992
844
|
color: colors.error
|
|
993
845
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
@@ -999,85 +851,27 @@ const FileManagementScreen = ({
|
|
|
999
851
|
}) : undefined
|
|
1000
852
|
};
|
|
1001
853
|
});
|
|
1002
|
-
}, [filteredFiles,
|
|
1003
|
-
|
|
1004
|
-
// Scroll to selected file after selection
|
|
1005
|
-
(0, _react.useEffect)(() => {
|
|
1006
|
-
if (lastSelectedFileId && selectMode) {
|
|
1007
|
-
if (viewMode === 'all' && scrollViewRef.current) {
|
|
1008
|
-
// Find the index of the selected file (filteredFiles is already sorted)
|
|
1009
|
-
const itemIndex = filteredFiles.findIndex(file => file.id === lastSelectedFileId);
|
|
1010
|
-
if (itemIndex >= 0) {
|
|
1011
|
-
// Estimate item height (GroupedItem with dense mode is approximately 60-70px)
|
|
1012
|
-
// Account for description rows which add extra height
|
|
1013
|
-
const baseItemHeight = 65;
|
|
1014
|
-
const descriptionHeight = 30; // Approximate height for description
|
|
1015
|
-
// Use filteredFiles which is already sorted according to user's selection
|
|
1016
|
-
const sortedFiles = filteredFiles;
|
|
1017
|
-
|
|
1018
|
-
// Calculate total height up to this item
|
|
1019
|
-
let scrollPosition = 0;
|
|
1020
|
-
for (let i = 0; i <= itemIndex && i < sortedFiles.length; i++) {
|
|
1021
|
-
const file = sortedFiles[i];
|
|
1022
|
-
scrollPosition += baseItemHeight;
|
|
1023
|
-
if (file.metadata?.description) {
|
|
1024
|
-
scrollPosition += descriptionHeight;
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
// Add header, controls, search, and stats height (approximately 250px)
|
|
1029
|
-
const headerHeight = 250;
|
|
1030
|
-
const finalScrollPosition = headerHeight + scrollPosition - 150; // Offset to show item near top
|
|
1031
|
-
|
|
1032
|
-
// Use requestAnimationFrame to ensure DOM is updated before scrolling
|
|
1033
|
-
requestAnimationFrame(() => {
|
|
1034
|
-
requestAnimationFrame(() => {
|
|
1035
|
-
scrollViewRef.current?.scrollTo({
|
|
1036
|
-
y: Math.max(0, finalScrollPosition),
|
|
1037
|
-
animated: true
|
|
1038
|
-
});
|
|
1039
|
-
});
|
|
1040
|
-
});
|
|
1041
|
-
}
|
|
1042
|
-
} else if (viewMode === 'photos' && photoScrollViewRef.current) {
|
|
1043
|
-
// For photo grid, find the photo index
|
|
1044
|
-
const photos = filteredFiles.filter(file => file.contentType.startsWith('image/'));
|
|
1045
|
-
const photoIndex = photos.findIndex(p => p.id === lastSelectedFileId);
|
|
1046
|
-
if (photoIndex >= 0) {
|
|
1047
|
-
// Rough scroll estimate for the justified grid (3 photos/row; variable row heights).
|
|
1048
|
-
const itemsPerRow = 3;
|
|
1049
|
-
const estimatedRowHeight = 150;
|
|
1050
|
-
const rowGap = 4;
|
|
1051
|
-
const row = Math.floor(photoIndex / itemsPerRow);
|
|
1052
|
-
const finalScrollPosition = row * (estimatedRowHeight + rowGap) - 100;
|
|
854
|
+
}, [filteredFiles, colors, deletingId, toggleSelect, handleFileDownload, confirmFileDelete, handleFileOpen, thumbSourceFor, selectMode, selectedIds]);
|
|
1053
855
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
}
|
|
1066
|
-
}, [lastSelectedFileId, selectMode, viewMode, filteredFiles, safeContainerWidth]);
|
|
1067
|
-
|
|
1068
|
-
// Clear selected file ID after scroll animation completes
|
|
1069
|
-
(0, _react.useEffect)(() => {
|
|
1070
|
-
if (lastSelectedFileId && scrollViewRef.current) {
|
|
1071
|
-
const timeoutId = setTimeout(() => {
|
|
1072
|
-
setLastSelectedFileId(null);
|
|
1073
|
-
}, 600); // Allow time for scroll animation to complete
|
|
856
|
+
// Browse-themed terminal load-failure state — DISTINCT from the empty state.
|
|
857
|
+
const renderLoadError = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_FileLibraryError.default, {
|
|
858
|
+
title: t('fileManagement.loadError.title'),
|
|
859
|
+
description: t('fileManagement.loadError.description'),
|
|
860
|
+
retryLabel: t('fileManagement.retry'),
|
|
861
|
+
onRetry: () => filesQuery.refetch(),
|
|
862
|
+
iconColor: colors.error,
|
|
863
|
+
titleColor: colors.text,
|
|
864
|
+
descriptionColor: colors.textSecondary,
|
|
865
|
+
buttonColor: colors.primary
|
|
866
|
+
});
|
|
1074
867
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
const renderPhotoGrid = (
|
|
868
|
+
// Browse "photos" view. The justified grid owns its own dimension
|
|
869
|
+
// measurement + reflow (see JustifiedPhotoGrid); this only supplies the
|
|
870
|
+
// photo set, the private-safe URL resolver, and the tile renderer.
|
|
871
|
+
const renderPhotoGrid = () => {
|
|
1079
872
|
const photos = filteredFiles.filter(file => file.contentType.startsWith('image/'));
|
|
1080
873
|
if (photos.length === 0) {
|
|
874
|
+
if (hasLoadError) return renderLoadError();
|
|
1081
875
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1082
876
|
className: "items-center py-[40px] px-[24px]",
|
|
1083
877
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
@@ -1103,10 +897,7 @@ const FileManagementScreen = ({
|
|
|
1103
897
|
},
|
|
1104
898
|
onPress: handleFileUpload,
|
|
1105
899
|
disabled: uploading || isPickingDocument,
|
|
1106
|
-
children: uploading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1107
|
-
size: "small",
|
|
1108
|
-
color: "#FFFFFF"
|
|
1109
|
-
}) : isPickingDocument ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
900
|
+
children: uploading || isPickingDocument ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1110
901
|
size: "small",
|
|
1111
902
|
color: "#FFFFFF"
|
|
1112
903
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
@@ -1122,13 +913,13 @@ const FileManagementScreen = ({
|
|
|
1122
913
|
})]
|
|
1123
914
|
});
|
|
1124
915
|
}
|
|
1125
|
-
return /*#__PURE__*/(0, _jsxRuntime.
|
|
916
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
1126
917
|
ref: photoScrollViewRef,
|
|
1127
918
|
className: "flex-1",
|
|
1128
919
|
contentContainerClassName: "p-[10px]",
|
|
1129
920
|
refreshControl: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.RefreshControl, {
|
|
1130
|
-
refreshing:
|
|
1131
|
-
onRefresh: () =>
|
|
921
|
+
refreshing: isRefreshingFiles,
|
|
922
|
+
onRefresh: () => filesQuery.refetch(),
|
|
1132
923
|
tintColor: colors.primary
|
|
1133
924
|
}),
|
|
1134
925
|
showsVerticalScrollIndicator: false,
|
|
@@ -1141,38 +932,21 @@ const FileManagementScreen = ({
|
|
|
1141
932
|
contentSize
|
|
1142
933
|
} = nativeEvent;
|
|
1143
934
|
const distanceFromBottom = contentSize.height - (contentOffset.y + layoutMeasurement.height);
|
|
1144
|
-
if (distanceFromBottom < 200 && !
|
|
1145
|
-
|
|
935
|
+
if (distanceFromBottom < 200 && !isFetchingMore && hasMoreFiles) {
|
|
936
|
+
filesQuery.fetchNextPage();
|
|
1146
937
|
}
|
|
1147
938
|
},
|
|
1148
939
|
scrollEventThrottle: 250,
|
|
1149
|
-
children:
|
|
1150
|
-
className: "flex-row items-center justify-center py-[16px] gap-[8px]",
|
|
1151
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1152
|
-
size: "small",
|
|
1153
|
-
color: colors.primary
|
|
1154
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1155
|
-
className: "text-[14px] italic",
|
|
1156
|
-
style: {
|
|
1157
|
-
color: colors.textSecondary
|
|
1158
|
-
},
|
|
1159
|
-
children: t('fileManagement.loadingPhotoLayout')
|
|
1160
|
-
})]
|
|
1161
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_JustifiedPhotoGrid.default, {
|
|
940
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_JustifiedPhotoGrid.default, {
|
|
1162
941
|
photos: photos,
|
|
1163
|
-
|
|
1164
|
-
loadPhotoDimensions: loadPhotoDimensions,
|
|
1165
|
-
createJustifiedRows: createJustifiedRows,
|
|
942
|
+
getThumbUrl: thumbSourceFor,
|
|
1166
943
|
renderJustifiedPhotoItem: renderJustifiedPhotoItem,
|
|
1167
944
|
textColor: colors.text,
|
|
1168
945
|
containerWidth: typeof containerWidth === 'number' && containerWidth > 0 ? containerWidth : undefined
|
|
1169
|
-
})
|
|
946
|
+
})
|
|
1170
947
|
});
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
// Inline justified grid removed (moved to components/photogrid/JustifiedPhotoGrid.tsx)
|
|
1174
|
-
|
|
1175
|
-
const renderEmptyState = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
948
|
+
};
|
|
949
|
+
const renderEmptyState = () => hasLoadError ? renderLoadError() : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1176
950
|
className: "items-center py-[40px] px-[24px]",
|
|
1177
951
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
1178
952
|
name: "folder-open-outline",
|
|
@@ -1197,10 +971,7 @@ const FileManagementScreen = ({
|
|
|
1197
971
|
},
|
|
1198
972
|
onPress: handleFileUpload,
|
|
1199
973
|
disabled: uploading || isPickingDocument,
|
|
1200
|
-
children: uploading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1201
|
-
size: "small",
|
|
1202
|
-
color: "#FFFFFF"
|
|
1203
|
-
}) : isPickingDocument ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
974
|
+
children: uploading || isPickingDocument ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1204
975
|
size: "small",
|
|
1205
976
|
color: "#FFFFFF"
|
|
1206
977
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
@@ -1304,7 +1075,7 @@ const FileManagementScreen = ({
|
|
|
1304
1075
|
right: fmHeaderRight,
|
|
1305
1076
|
largeTitle: false
|
|
1306
1077
|
});
|
|
1307
|
-
if (
|
|
1078
|
+
if (isLoadingFiles && !isImageOnlyPicker) {
|
|
1308
1079
|
const GRID_PADDING = 10;
|
|
1309
1080
|
const TILE_GAP = 4;
|
|
1310
1081
|
const GRID_COLUMNS = 3;
|
|
@@ -1403,13 +1174,15 @@ const FileManagementScreen = ({
|
|
|
1403
1174
|
multiSelect: multiSelect,
|
|
1404
1175
|
maxSelection: maxSelection,
|
|
1405
1176
|
allowUpload: allowUpload,
|
|
1406
|
-
refreshing:
|
|
1177
|
+
refreshing: isRefreshingFiles,
|
|
1407
1178
|
uploading: uploading,
|
|
1408
1179
|
isPickingDocument: isPickingDocument,
|
|
1409
1180
|
uploadProgress: uploadProgress,
|
|
1410
|
-
hasMore:
|
|
1411
|
-
loadingMore:
|
|
1412
|
-
loading:
|
|
1181
|
+
hasMore: hasMoreFiles,
|
|
1182
|
+
loadingMore: isFetchingMore,
|
|
1183
|
+
loading: isLoadingFiles,
|
|
1184
|
+
loadError: hasLoadError,
|
|
1185
|
+
onRetry: () => filesQuery.refetch(),
|
|
1413
1186
|
reduceMotion: reduceMotion,
|
|
1414
1187
|
getThumbUrl: thumbSourceFor,
|
|
1415
1188
|
primaryColor: colors.primary,
|
|
@@ -1419,8 +1192,8 @@ const FileManagementScreen = ({
|
|
|
1419
1192
|
,
|
|
1420
1193
|
onPreviewPhoto: file => showFileDetailsModal(file),
|
|
1421
1194
|
onUpload: handleFileUpload,
|
|
1422
|
-
onRefresh: () =>
|
|
1423
|
-
onLoadMore: () =>
|
|
1195
|
+
onRefresh: () => filesQuery.refetch(),
|
|
1196
|
+
onLoadMore: () => filesQuery.fetchNextPage(),
|
|
1424
1197
|
onCancel: () => {
|
|
1425
1198
|
if (onSelect || onConfirmSelection) {
|
|
1426
1199
|
// Legacy callback caller: preserve close/back behaviour.
|
|
@@ -1495,32 +1268,30 @@ const FileManagementScreen = ({
|
|
|
1495
1268
|
textColor: colors.text,
|
|
1496
1269
|
style: screenStyles.viewModeButton,
|
|
1497
1270
|
accessibilityLabel: t('fileManagement.a11y.viewPhotos') || 'Show photos only'
|
|
1498
|
-
}),
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
accessibilityLabel: t('fileManagement.a11y.viewAudio') || 'Show audio only'
|
|
1523
|
-
})]
|
|
1271
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AnimatedButton.AnimatedButton, {
|
|
1272
|
+
isSelected: viewMode === 'videos',
|
|
1273
|
+
onPress: () => setViewMode('videos'),
|
|
1274
|
+
icon: viewMode === 'videos' ? 'video' : 'video-outline',
|
|
1275
|
+
primaryColor: colors.primary,
|
|
1276
|
+
textColor: colors.text,
|
|
1277
|
+
style: screenStyles.viewModeButton,
|
|
1278
|
+
accessibilityLabel: t('fileManagement.a11y.viewVideos') || 'Show videos only'
|
|
1279
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AnimatedButton.AnimatedButton, {
|
|
1280
|
+
isSelected: viewMode === 'documents',
|
|
1281
|
+
onPress: () => setViewMode('documents'),
|
|
1282
|
+
icon: viewMode === 'documents' ? 'file-document' : 'file-document-outline',
|
|
1283
|
+
primaryColor: colors.primary,
|
|
1284
|
+
textColor: colors.text,
|
|
1285
|
+
style: screenStyles.viewModeButton,
|
|
1286
|
+
accessibilityLabel: t('fileManagement.a11y.viewDocuments') || 'Show documents only'
|
|
1287
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AnimatedButton.AnimatedButton, {
|
|
1288
|
+
isSelected: viewMode === 'audio',
|
|
1289
|
+
onPress: () => setViewMode('audio'),
|
|
1290
|
+
icon: viewMode === 'audio' ? 'music-note' : 'music-note-outline',
|
|
1291
|
+
primaryColor: colors.primary,
|
|
1292
|
+
textColor: colors.text,
|
|
1293
|
+
style: screenStyles.viewModeButton,
|
|
1294
|
+
accessibilityLabel: t('fileManagement.a11y.viewAudio') || 'Show audio only'
|
|
1524
1295
|
})]
|
|
1525
1296
|
})
|
|
1526
1297
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
@@ -1553,15 +1324,15 @@ const FileManagementScreen = ({
|
|
|
1553
1324
|
size: 14,
|
|
1554
1325
|
color: colors.textSecondary
|
|
1555
1326
|
})]
|
|
1556
|
-
}), user?.id === targetUserId && (!selectMode ||
|
|
1557
|
-
className:
|
|
1327
|
+
}), user?.id === targetUserId && (!selectMode || allowUploadInSelectMode) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
1328
|
+
className: "h-[44px] w-[44px] rounded-[22px] items-center justify-center",
|
|
1558
1329
|
style: {
|
|
1559
1330
|
backgroundColor: colors.primary
|
|
1560
1331
|
},
|
|
1561
1332
|
onPress: handleFileUpload,
|
|
1562
1333
|
disabled: uploading || isPickingDocument,
|
|
1563
1334
|
accessibilityRole: "button",
|
|
1564
|
-
accessibilityLabel:
|
|
1335
|
+
accessibilityLabel: t('fileManagement.a11y.uploadFile') || 'Upload file',
|
|
1565
1336
|
accessibilityState: {
|
|
1566
1337
|
busy: uploading || isPickingDocument
|
|
1567
1338
|
},
|
|
@@ -1577,17 +1348,6 @@ const FileManagementScreen = ({
|
|
|
1577
1348
|
}) : isPickingDocument ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
1578
1349
|
size: "small",
|
|
1579
1350
|
color: "#FFFFFF"
|
|
1580
|
-
}) : isImageOnlyPicker ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
1581
|
-
className: "flex-row items-center gap-[6px]",
|
|
1582
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
1583
|
-
name: "cloud-upload",
|
|
1584
|
-
size: 18,
|
|
1585
|
-
color: "#FFFFFF"
|
|
1586
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
1587
|
-
className: "text-white text-[14px] font-semibold",
|
|
1588
|
-
numberOfLines: 1,
|
|
1589
|
-
children: t('fileManagement.upload') || 'Upload'
|
|
1590
|
-
})]
|
|
1591
1351
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
1592
1352
|
name: "add",
|
|
1593
1353
|
size: 22,
|
|
@@ -1683,12 +1443,15 @@ const FileManagementScreen = ({
|
|
|
1683
1443
|
filteredFiles: filteredFiles,
|
|
1684
1444
|
searchQuery: searchQuery,
|
|
1685
1445
|
items: groupedFileItems,
|
|
1686
|
-
paging:
|
|
1687
|
-
|
|
1446
|
+
paging: {
|
|
1447
|
+
loadingMore: isFetchingMore,
|
|
1448
|
+
hasMore: hasMoreFiles
|
|
1449
|
+
},
|
|
1450
|
+
refreshing: isRefreshingFiles,
|
|
1688
1451
|
colors: colors,
|
|
1689
1452
|
t: t,
|
|
1690
|
-
onRefresh: () =>
|
|
1691
|
-
onLoadMore: () =>
|
|
1453
|
+
onRefresh: () => filesQuery.refetch(),
|
|
1454
|
+
onLoadMore: () => filesQuery.fetchNextPage(),
|
|
1692
1455
|
onClearSearch: () => setSearchQuery(''),
|
|
1693
1456
|
renderEmptyState: renderEmptyState
|
|
1694
1457
|
}), !selectMode && uploading && /*#__PURE__*/(0, _jsxRuntime.jsx)(_UploadBar.default, {
|