@oxyhq/services 22.10.0 → 22.11.1
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 +71 -39
- 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 +71 -40
- 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 +11 -7
- 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 +73 -44
- 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
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { useCallback, useRef, useState } from 'react';
|
|
3
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
3
4
|
import { toast } from '@oxyhq/bloom';
|
|
4
5
|
import type { AssetUploadInput, FileMetadata } from '@oxyhq/core';
|
|
5
|
-
import { useFileStore } from '../../../stores/fileStore';
|
|
6
6
|
import type { useUploadFile } from '../../../hooks/mutations/useAccountMutations';
|
|
7
|
+
import { queryKeys } from '../../../hooks/queries/queryKeys';
|
|
8
|
+
import {
|
|
9
|
+
prependFileToCache,
|
|
10
|
+
removeFileFromCache,
|
|
11
|
+
replaceFileInCache,
|
|
12
|
+
} from '../../../hooks/queries/useFileQueries';
|
|
7
13
|
import { convertDocumentPickerAssetToFile, formatFileSize } from '../../../utils/fileManagement';
|
|
8
14
|
import {
|
|
9
15
|
createPendingUploadFile,
|
|
@@ -17,6 +23,15 @@ import {
|
|
|
17
23
|
loadDocumentPicker,
|
|
18
24
|
} from '../shared';
|
|
19
25
|
|
|
26
|
+
/** Aggregate progress across a multi-file upload. */
|
|
27
|
+
export interface FileUploadAggregateProgress {
|
|
28
|
+
current: number;
|
|
29
|
+
total: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Minimum time the "Uploading…" indicator stays visible (anti-flash). */
|
|
33
|
+
const MIN_BANNER_MS = 600;
|
|
34
|
+
|
|
20
35
|
function revokePreviewUrl(preview: string | undefined): void {
|
|
21
36
|
if (preview?.startsWith('blob:')) {
|
|
22
37
|
URL.revokeObjectURL(preview);
|
|
@@ -47,7 +62,6 @@ export interface UseFileUploadStateParams {
|
|
|
47
62
|
onClose?: () => void;
|
|
48
63
|
selectedIds: Set<string>;
|
|
49
64
|
setSelectedIds: React.Dispatch<React.SetStateAction<Set<string>>>;
|
|
50
|
-
loadFiles: (mode?: 'initial' | 'refresh' | 'silent' | 'more') => Promise<void> | void;
|
|
51
65
|
t: (key: string, vars?: Record<string, string | number>) => string;
|
|
52
66
|
}
|
|
53
67
|
|
|
@@ -56,6 +70,10 @@ export interface UseFileUploadStateResult {
|
|
|
56
70
|
isPickingDocument: boolean;
|
|
57
71
|
pendingFiles: PendingUploadFile[];
|
|
58
72
|
showUploadPreview: boolean;
|
|
73
|
+
/** Whether an upload is in flight (drives the "Uploading…" banner). */
|
|
74
|
+
uploading: boolean;
|
|
75
|
+
/** Aggregate progress across the current upload, or null. */
|
|
76
|
+
uploadProgress: FileUploadAggregateProgress | null;
|
|
59
77
|
handleFileUpload: () => Promise<void>;
|
|
60
78
|
handleConfirmUpload: () => Promise<void>;
|
|
61
79
|
handleCancelUpload: () => void;
|
|
@@ -80,25 +98,23 @@ export const useFileUploadState = ({
|
|
|
80
98
|
onClose,
|
|
81
99
|
selectedIds,
|
|
82
100
|
setSelectedIds,
|
|
83
|
-
loadFiles,
|
|
84
101
|
t,
|
|
85
102
|
}: UseFileUploadStateParams): UseFileUploadStateResult => {
|
|
86
103
|
const [isPickingDocument, setIsPickingDocument] = useState(false);
|
|
87
104
|
const [pendingFiles, setPendingFiles] = useState<PendingUploadFile[]>([]);
|
|
88
105
|
const [showUploadPreview, setShowUploadPreview] = useState(false);
|
|
106
|
+
const [uploading, setUploading] = useState(false);
|
|
107
|
+
const [uploadProgress, setUploadProgress] = useState<FileUploadAggregateProgress | null>(null);
|
|
89
108
|
|
|
109
|
+
const queryClient = useQueryClient();
|
|
90
110
|
const uploadStartRef = useRef<number | null>(null);
|
|
91
|
-
const MIN_BANNER_MS = 600;
|
|
92
|
-
|
|
93
|
-
const storeSetUploading = useFileStore(s => s.setUploading);
|
|
94
|
-
const storeSetUploadProgress = useFileStore(s => s.setUploadProgress);
|
|
95
111
|
|
|
96
112
|
const endUpload = useCallback(() => {
|
|
97
113
|
const started = uploadStartRef.current;
|
|
98
114
|
const elapsed = started ? Date.now() - started : MIN_BANNER_MS;
|
|
99
115
|
const remaining = elapsed < MIN_BANNER_MS ? MIN_BANNER_MS - elapsed : 0;
|
|
100
116
|
setTimeout(() => {
|
|
101
|
-
|
|
117
|
+
setUploading(false);
|
|
102
118
|
uploadStartRef.current = null;
|
|
103
119
|
}, remaining);
|
|
104
120
|
}, []);
|
|
@@ -108,7 +124,7 @@ export const useFileUploadState = ({
|
|
|
108
124
|
if (!targetUserId) return []; // Guard clause to ensure userId is defined
|
|
109
125
|
const uploadedFiles: FileMetadata[] = [];
|
|
110
126
|
try {
|
|
111
|
-
|
|
127
|
+
setUploadProgress({ current: 0, total: selectedFiles.length });
|
|
112
128
|
const maxSize = 50 * 1024 * 1024; // 50MB
|
|
113
129
|
const oversizedFiles = selectedFiles.filter(file => candidateSize(file) > maxSize);
|
|
114
130
|
if (oversizedFiles.length > 0) {
|
|
@@ -120,20 +136,16 @@ export const useFileUploadState = ({
|
|
|
120
136
|
let failureCount = 0;
|
|
121
137
|
const errors: string[] = [];
|
|
122
138
|
for (let i = 0; i < selectedFiles.length; i++) {
|
|
123
|
-
|
|
139
|
+
setUploadProgress({ current: i + 1, total: selectedFiles.length });
|
|
124
140
|
const raw = selectedFiles[i];
|
|
125
141
|
const fileName = candidateName(raw, `file-${i + 1}`);
|
|
126
142
|
const fileSize = candidateSize(raw);
|
|
127
143
|
const fileType = candidateType(raw);
|
|
128
|
-
const optimisticId = `temp-${Date.now()}-${i}-${Math.random().toString(36).
|
|
144
|
+
const optimisticId = `temp-${Date.now()}-${i}-${Math.random().toString(36).slice(2, 11)}`; // Unique ID per file
|
|
129
145
|
|
|
130
146
|
try {
|
|
131
147
|
// Validate file before upload
|
|
132
148
|
if (!raw || !fileName || fileSize <= 0) {
|
|
133
|
-
const errorMsg = `Invalid file: ${fileName}`;
|
|
134
|
-
if (__DEV__) {
|
|
135
|
-
console.error('Upload validation failed:', { file: raw, error: errorMsg });
|
|
136
|
-
}
|
|
137
149
|
failureCount++;
|
|
138
150
|
errors.push(`${fileName}: Invalid file (missing name or size)`);
|
|
139
151
|
continue;
|
|
@@ -158,7 +170,7 @@ export const useFileUploadState = ({
|
|
|
158
170
|
metadata: optimisticMetadata,
|
|
159
171
|
variants: [],
|
|
160
172
|
};
|
|
161
|
-
|
|
173
|
+
prependFileToCache(queryClient, targetUserId, optimisticFile);
|
|
162
174
|
|
|
163
175
|
// Use the mutation hook with authentication handling
|
|
164
176
|
const result = await uploadFileMutation.mutateAsync({
|
|
@@ -179,41 +191,26 @@ export const useFileUploadState = ({
|
|
|
179
191
|
metadata: f.metadata || {},
|
|
180
192
|
variants: f.variants || [],
|
|
181
193
|
};
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
useFileStore.getState().addFile(merged, { prepend: true });
|
|
194
|
+
// Swap the optimistic temp entry for the persisted record.
|
|
195
|
+
replaceFileInCache(queryClient, targetUserId, optimisticId, merged);
|
|
185
196
|
uploadedFiles.push(merged);
|
|
186
197
|
successCount++;
|
|
187
198
|
} else {
|
|
188
199
|
// Upload succeeded but the API returned no file payload,
|
|
189
200
|
// so we cannot build a real entry. Drop the optimistic
|
|
190
201
|
// placeholder instead of stranding a `temp-…` id (which
|
|
191
|
-
// would leak into asset URLs); the
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
if (__DEV__) {
|
|
195
|
-
console.warn('Upload completed but no file data returned:', { fileName, result });
|
|
196
|
-
}
|
|
202
|
+
// would leak into asset URLs); the reconcile invalidation
|
|
203
|
+
// below re-fetches the persisted record.
|
|
204
|
+
removeFileFromCache(queryClient, targetUserId, optimisticId);
|
|
197
205
|
// Still count as success if upload didn't throw
|
|
198
206
|
successCount++;
|
|
199
207
|
}
|
|
200
208
|
} catch (error: unknown) {
|
|
201
209
|
failureCount++;
|
|
202
210
|
const errorMessage = getErrorMessage(error) || 'Upload failed';
|
|
203
|
-
|
|
204
|
-
errors.push(fullError);
|
|
205
|
-
if (__DEV__) {
|
|
206
|
-
console.error('File upload failed:', {
|
|
207
|
-
fileName,
|
|
208
|
-
fileSize,
|
|
209
|
-
fileType,
|
|
210
|
-
error: errorMessage,
|
|
211
|
-
stack: (error instanceof Error) ? error.stack : undefined
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
211
|
+
errors.push(`${fileName}: ${errorMessage}`);
|
|
215
212
|
// Remove optimistic file on error (use the same optimisticId from above)
|
|
216
|
-
|
|
213
|
+
removeFileFromCache(queryClient, targetUserId, optimisticId);
|
|
217
214
|
}
|
|
218
215
|
}
|
|
219
216
|
|
|
@@ -228,12 +225,15 @@ export const useFileUploadState = ({
|
|
|
228
225
|
: '';
|
|
229
226
|
toast.error(`${t('fileManagement.toasts.uploadFailed', { count: failureCount })}${errorDetails}`);
|
|
230
227
|
}
|
|
231
|
-
//
|
|
232
|
-
|
|
228
|
+
// Reconcile against the server (picks up generated variants / metadata)
|
|
229
|
+
// — replaces the old silent-reload timer.
|
|
230
|
+
if (successCount > 0) {
|
|
231
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.files.list(targetUserId) });
|
|
232
|
+
}
|
|
233
233
|
} catch (error: unknown) {
|
|
234
234
|
toast.error(getErrorMessage(error) || t('fileManagement.toasts.uploadError'));
|
|
235
235
|
} finally {
|
|
236
|
-
|
|
236
|
+
setUploadProgress(null);
|
|
237
237
|
}
|
|
238
238
|
return uploadedFiles;
|
|
239
239
|
};
|
|
@@ -245,35 +245,23 @@ export const useFileUploadState = ({
|
|
|
245
245
|
for (const file of selectedFiles) {
|
|
246
246
|
// Validate file has required properties
|
|
247
247
|
if (!file) {
|
|
248
|
-
if (__DEV__) {
|
|
249
|
-
console.error('Invalid file: file is null or undefined');
|
|
250
|
-
}
|
|
251
248
|
toast.error(t('fileManagement.toasts.invalidFileMissing'));
|
|
252
249
|
continue;
|
|
253
250
|
}
|
|
254
251
|
|
|
255
252
|
const name = candidateName(file, '');
|
|
256
253
|
if (!name) {
|
|
257
|
-
if (__DEV__) {
|
|
258
|
-
console.error('Invalid file: missing or invalid name property', file);
|
|
259
|
-
}
|
|
260
254
|
toast.error(t('fileManagement.toasts.invalidFileName'));
|
|
261
255
|
continue;
|
|
262
256
|
}
|
|
263
257
|
|
|
264
258
|
const size = (file as { size?: number }).size;
|
|
265
259
|
if (size === undefined || size === null || Number.isNaN(size)) {
|
|
266
|
-
if (__DEV__) {
|
|
267
|
-
console.error('Invalid file: missing or invalid size property', file);
|
|
268
|
-
}
|
|
269
260
|
toast.error(t('fileManagement.toasts.invalidFileSize', { name }));
|
|
270
261
|
continue;
|
|
271
262
|
}
|
|
272
263
|
|
|
273
264
|
if (size <= 0) {
|
|
274
|
-
if (__DEV__) {
|
|
275
|
-
console.error('Invalid file: file size is zero or negative', file);
|
|
276
|
-
}
|
|
277
265
|
toast.error(t('fileManagement.toasts.fileEmpty', { name }));
|
|
278
266
|
continue;
|
|
279
267
|
}
|
|
@@ -303,11 +291,8 @@ export const useFileUploadState = ({
|
|
|
303
291
|
(typeof Blob !== 'undefined' && file instanceof Blob)) {
|
|
304
292
|
preview = URL.createObjectURL(file as Blob);
|
|
305
293
|
}
|
|
306
|
-
} catch
|
|
307
|
-
|
|
308
|
-
console.warn('Failed to create preview URL:', error);
|
|
309
|
-
}
|
|
310
|
-
// Preview is optional, continue without it
|
|
294
|
+
} catch {
|
|
295
|
+
// Preview is optional — continue without it.
|
|
311
296
|
}
|
|
312
297
|
}
|
|
313
298
|
}
|
|
@@ -330,23 +315,23 @@ export const useFileUploadState = ({
|
|
|
330
315
|
|
|
331
316
|
setShowUploadPreview(false);
|
|
332
317
|
uploadStartRef.current = Date.now();
|
|
333
|
-
|
|
334
|
-
|
|
318
|
+
setUploading(true);
|
|
319
|
+
setUploadProgress(null);
|
|
335
320
|
|
|
336
321
|
try {
|
|
337
322
|
const filesToUpload = pendingFiles.map(pf => pf.file);
|
|
338
|
-
|
|
323
|
+
setUploadProgress({ current: 0, total: filesToUpload.length });
|
|
339
324
|
const uploadedFiles = await processFileUploads(filesToUpload);
|
|
340
325
|
|
|
341
326
|
// Cleanup preview URLs
|
|
342
|
-
|
|
327
|
+
for (const pf of pendingFiles) {
|
|
343
328
|
revokePreviewUrl(pf.preview);
|
|
344
|
-
}
|
|
329
|
+
}
|
|
345
330
|
setPendingFiles([]);
|
|
346
331
|
|
|
347
332
|
// If in selectMode, automatically select the uploaded file(s)
|
|
348
333
|
if (selectMode && uploadedFiles.length > 0) {
|
|
349
|
-
//
|
|
334
|
+
// Defer one tick so the query cache has settled before selecting.
|
|
350
335
|
setTimeout(() => {
|
|
351
336
|
const fileToSelect = uploadedFiles[0];
|
|
352
337
|
if (!multiSelect && fileToSelect) {
|
|
@@ -359,11 +344,11 @@ export const useFileUploadState = ({
|
|
|
359
344
|
}
|
|
360
345
|
} else if (multiSelect) {
|
|
361
346
|
// Multi-select mode - add all uploaded files to selection
|
|
362
|
-
|
|
347
|
+
for (const file of uploadedFiles) {
|
|
363
348
|
if (!selectedIds.has(file.id)) {
|
|
364
349
|
setSelectedIds(prev => new Set(prev).add(file.id));
|
|
365
350
|
}
|
|
366
|
-
}
|
|
351
|
+
}
|
|
367
352
|
}
|
|
368
353
|
}, 500);
|
|
369
354
|
}
|
|
@@ -377,9 +362,9 @@ export const useFileUploadState = ({
|
|
|
377
362
|
|
|
378
363
|
const handleCancelUpload = () => {
|
|
379
364
|
// Cleanup preview URLs
|
|
380
|
-
|
|
365
|
+
for (const pf of pendingFiles) {
|
|
381
366
|
revokePreviewUrl(pf.preview);
|
|
382
|
-
}
|
|
367
|
+
}
|
|
383
368
|
setPendingFiles([]);
|
|
384
369
|
setShowUploadPreview(false);
|
|
385
370
|
};
|
|
@@ -487,9 +472,6 @@ export const useFileUploadState = ({
|
|
|
487
472
|
toast.error(t('fileManagement.toasts.noFilesProcessed'));
|
|
488
473
|
}
|
|
489
474
|
} catch (error: unknown) {
|
|
490
|
-
if (__DEV__) {
|
|
491
|
-
console.error('File upload error:', error);
|
|
492
|
-
}
|
|
493
475
|
if (getErrorMessage(error)?.includes('expo-document-picker') || getErrorMessage(error)?.includes('Different document picking in progress')) {
|
|
494
476
|
if (getErrorMessage(error)?.includes('Different document picking in progress')) {
|
|
495
477
|
toast.error(t('fileManagement.toasts.waitForSelection'));
|
|
@@ -509,6 +491,8 @@ export const useFileUploadState = ({
|
|
|
509
491
|
isPickingDocument,
|
|
510
492
|
pendingFiles,
|
|
511
493
|
showUploadPreview,
|
|
494
|
+
uploading,
|
|
495
|
+
uploadProgress,
|
|
512
496
|
handleFileUpload,
|
|
513
497
|
handleConfirmUpload,
|
|
514
498
|
handleCancelUpload,
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { useFollowStore } from './followStore';
|
|
2
|
-
import { useFileStore } from './fileStore';
|
|
3
2
|
|
|
4
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Drop session-scoped Zustand slices so the next user/account never inherits
|
|
5
|
+
* stale UI state.
|
|
6
|
+
*
|
|
7
|
+
* The file library is NOT reset here: it lives in React Query keyed by owner id
|
|
8
|
+
* (`queryKeys.files.list(ownerId)`), so switching accounts naturally shows the
|
|
9
|
+
* new owner's files and the old owner's cache is garbage-collected on its own.
|
|
10
|
+
*/
|
|
5
11
|
export function resetSessionScopedStores(): void {
|
|
6
12
|
useFollowStore.getState().resetFollowState();
|
|
7
|
-
useFileStore.getState().reset();
|
|
8
13
|
}
|
|
@@ -13,6 +13,8 @@ export interface BaseScreenProps {
|
|
|
13
13
|
// Navigation props
|
|
14
14
|
navigate?: (screen: RouteName, props?: Record<string, unknown>) => void;
|
|
15
15
|
goBack?: () => void;
|
|
16
|
+
/** Whether the host surface can navigate back — a deeper frame OR a prior step. */
|
|
17
|
+
canGoBack?: () => boolean;
|
|
16
18
|
onClose?: () => void;
|
|
17
19
|
onAuthenticated?: (payload?: unknown) => void;
|
|
18
20
|
/**
|
|
@@ -60,9 +60,18 @@ export async function updateProfileWithAvatar(
|
|
|
60
60
|
// Update authStore so frontend components see the changes immediately
|
|
61
61
|
useAuthStore.getState().setUser(data);
|
|
62
62
|
|
|
63
|
-
// If avatar was updated, refresh accountStore with cache-busted URL
|
|
63
|
+
// If avatar was updated, refresh accountStore with a cache-busted URL. An
|
|
64
|
+
// EMPTY avatar is a removal: clear both fields so the switcher falls back to
|
|
65
|
+
// initials instead of pointing at a download URL for the empty file id.
|
|
64
66
|
if (typeof updates.avatar === 'string' && activeSessionId) {
|
|
65
|
-
|
|
67
|
+
if (updates.avatar) {
|
|
68
|
+
refreshAvatarInStore(activeSessionId, updates.avatar, oxyServices);
|
|
69
|
+
} else {
|
|
70
|
+
useAccountStore.getState().updateAccount(activeSessionId, {
|
|
71
|
+
avatar: undefined,
|
|
72
|
+
avatarUrl: undefined,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
// Invalidate all related queries to refresh everywhere
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { Ionicons } from '@expo/vector-icons';
|
|
2
|
-
import type { AssetUploadInput,
|
|
2
|
+
import type { AssetUploadInput, RNFileDescriptor } from '@oxyhq/core';
|
|
3
3
|
import type { ComponentProps } from 'react';
|
|
4
4
|
import { Platform } from 'react-native';
|
|
5
|
-
import { toast } from '@oxyhq/bloom';
|
|
6
|
-
import type { RouteName } from '../navigation/routes';
|
|
7
|
-
import { updateAvatarVisibility } from '@oxyhq/core';
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
7
|
* Extended File interface that includes a `uri` property for mobile preview support.
|
|
@@ -155,100 +152,3 @@ export async function uploadFileRaw(
|
|
|
155
152
|
) {
|
|
156
153
|
return await oxyServices.uploadRawFile(file, visibility);
|
|
157
154
|
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Configuration for creating an avatar picker handler
|
|
161
|
-
*/
|
|
162
|
-
export interface AvatarPickerConfig {
|
|
163
|
-
/** Navigation function from BaseScreenProps */
|
|
164
|
-
navigate?: (screen: RouteName, props?: Record<string, unknown>) => void;
|
|
165
|
-
/** OxyServices instance */
|
|
166
|
-
// biome-ignore lint/suspicious/noExplicitAny: OxyServices type cannot be fully resolved due to mixin composition pattern
|
|
167
|
-
oxyServices: any;
|
|
168
|
-
/** TanStack Query mutation for updating profile */
|
|
169
|
-
updateProfileMutation: {
|
|
170
|
-
mutateAsync: (updates: { avatar: string }) => Promise<unknown>;
|
|
171
|
-
};
|
|
172
|
-
/** Callback to update local avatar state */
|
|
173
|
-
onAvatarSelected?: (fileId: string) => void;
|
|
174
|
-
/** i18n translation function */
|
|
175
|
-
t: (key: string) => string | undefined;
|
|
176
|
-
/** Optional context name for logging (e.g., 'AccountSettings', 'WelcomeNewUser') */
|
|
177
|
-
contextName?: string;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Creates a reusable avatar picker handler function.
|
|
182
|
-
*
|
|
183
|
-
* This function navigates to the FileManagement screen and handles:
|
|
184
|
-
* - Image file validation
|
|
185
|
-
* - File visibility update to public
|
|
186
|
-
* - Profile avatar update via mutation
|
|
187
|
-
* - Success/error toast notifications
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```tsx
|
|
191
|
-
* const openAvatarPicker = createAvatarPickerHandler({
|
|
192
|
-
* navigate,
|
|
193
|
-
* oxyServices,
|
|
194
|
-
* updateProfileMutation,
|
|
195
|
-
* onAvatarSelected: setAvatarFileId,
|
|
196
|
-
* t,
|
|
197
|
-
* contextName: 'AccountSettings'
|
|
198
|
-
* });
|
|
199
|
-
*
|
|
200
|
-
* <TouchableOpacity onPress={openAvatarPicker}>
|
|
201
|
-
* <Text>Change Avatar</Text>
|
|
202
|
-
* </TouchableOpacity>
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
export function createAvatarPickerHandler(config: AvatarPickerConfig): () => void {
|
|
206
|
-
const {
|
|
207
|
-
navigate,
|
|
208
|
-
oxyServices,
|
|
209
|
-
updateProfileMutation,
|
|
210
|
-
onAvatarSelected,
|
|
211
|
-
t,
|
|
212
|
-
contextName = 'AvatarPicker'
|
|
213
|
-
} = config;
|
|
214
|
-
|
|
215
|
-
return () => {
|
|
216
|
-
if (!navigate) {
|
|
217
|
-
console.warn(`[${contextName}] navigate function is not available`);
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
navigate('FileManagement', {
|
|
222
|
-
selectMode: true,
|
|
223
|
-
multiSelect: false,
|
|
224
|
-
disabledMimeTypes: ['video/', 'audio/', 'application/pdf'],
|
|
225
|
-
afterSelect: 'none', // Don't navigate away - stay on current screen
|
|
226
|
-
onSelect: async (file: FileMetadata) => {
|
|
227
|
-
if (!file.contentType.startsWith('image/')) {
|
|
228
|
-
toast.error(t('editProfile.toasts.selectImage'));
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
try {
|
|
233
|
-
// Update file visibility to public for avatar
|
|
234
|
-
await updateAvatarVisibility(file.id, oxyServices, contextName);
|
|
235
|
-
|
|
236
|
-
// Update local state if callback provided
|
|
237
|
-
if (onAvatarSelected) {
|
|
238
|
-
onAvatarSelected(file.id);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Update user using TanStack Query mutation
|
|
242
|
-
await updateProfileMutation.mutateAsync({ avatar: file.id });
|
|
243
|
-
|
|
244
|
-
toast.success(t('editProfile.toasts.avatarUpdated'));
|
|
245
|
-
} catch (e: unknown) {
|
|
246
|
-
toast.error(
|
|
247
|
-
e instanceof Error ? e.message : t('editProfile.toasts.updateAvatarFailed'),
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.useUploading = exports.useUploadAggregateProgress = exports.useFiles = exports.useFileStore = exports.useDeleting = void 0;
|
|
7
|
-
var _zustand = require("zustand");
|
|
8
|
-
// Shallow compare two file metadata objects by keys/values
|
|
9
|
-
function shallowEqualFile(a, b) {
|
|
10
|
-
if (a === b) return true;
|
|
11
|
-
if (!a || !b) return false;
|
|
12
|
-
const aKeys = Object.keys(a);
|
|
13
|
-
const bKeys = Object.keys(b);
|
|
14
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
15
|
-
for (const k of aKeys) {
|
|
16
|
-
// treat metadata/variants shallowly by reference
|
|
17
|
-
if (a[k] !== b[k]) return false;
|
|
18
|
-
}
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Basic upload progress type for aggregate tracking
|
|
23
|
-
|
|
24
|
-
const initialState = {
|
|
25
|
-
files: {},
|
|
26
|
-
order: [],
|
|
27
|
-
uploading: false,
|
|
28
|
-
deleting: null,
|
|
29
|
-
uploadProgress: null
|
|
30
|
-
};
|
|
31
|
-
const useFileStore = exports.useFileStore = (0, _zustand.create)((set, get) => ({
|
|
32
|
-
...initialState,
|
|
33
|
-
setFiles: (files, opts) => set(state => {
|
|
34
|
-
const merge = opts?.merge !== false; // default true
|
|
35
|
-
if (!merge) {
|
|
36
|
-
const map = {};
|
|
37
|
-
const order = [];
|
|
38
|
-
files.forEach(f => {
|
|
39
|
-
map[f.id] = f;
|
|
40
|
-
order.push(f.id);
|
|
41
|
-
});
|
|
42
|
-
// detect if identical to avoid redundant updates
|
|
43
|
-
const sameOrder = order.length === state.order.length && order.every((id, i) => id === state.order[i]);
|
|
44
|
-
let sameFiles = sameOrder;
|
|
45
|
-
if (sameOrder) {
|
|
46
|
-
sameFiles = order.every(id => state.files[id] && shallowEqualFile(state.files[id], map[id]));
|
|
47
|
-
}
|
|
48
|
-
if (sameOrder && sameFiles) return state;
|
|
49
|
-
return {
|
|
50
|
-
files: map,
|
|
51
|
-
order
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const newFiles = {
|
|
55
|
-
...state.files
|
|
56
|
-
};
|
|
57
|
-
const newOrder = [...state.order];
|
|
58
|
-
let changed = false;
|
|
59
|
-
files.forEach(f => {
|
|
60
|
-
const prev = state.files[f.id];
|
|
61
|
-
const merged = {
|
|
62
|
-
...(prev || {}),
|
|
63
|
-
...f
|
|
64
|
-
};
|
|
65
|
-
if (!prev || !shallowEqualFile(prev, merged)) {
|
|
66
|
-
newFiles[f.id] = merged;
|
|
67
|
-
changed = true;
|
|
68
|
-
}
|
|
69
|
-
if (!newOrder.includes(f.id)) {
|
|
70
|
-
newOrder.unshift(f.id);
|
|
71
|
-
changed = true;
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
if (!changed) return state;
|
|
75
|
-
return {
|
|
76
|
-
files: newFiles,
|
|
77
|
-
order: newOrder
|
|
78
|
-
};
|
|
79
|
-
}),
|
|
80
|
-
addFile: (file, opts) => set(state => {
|
|
81
|
-
const prepend = opts?.prepend !== false; // default true
|
|
82
|
-
if (state.files[file.id]) {
|
|
83
|
-
if (shallowEqualFile(state.files[file.id], file)) return state;
|
|
84
|
-
return {
|
|
85
|
-
files: {
|
|
86
|
-
...state.files,
|
|
87
|
-
[file.id]: file
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
files: {
|
|
93
|
-
...state.files,
|
|
94
|
-
[file.id]: file
|
|
95
|
-
},
|
|
96
|
-
order: prepend ? [file.id, ...state.order] : [...state.order, file.id]
|
|
97
|
-
};
|
|
98
|
-
}),
|
|
99
|
-
updateFile: (id, patch) => set(state => {
|
|
100
|
-
const existing = state.files[id];
|
|
101
|
-
if (!existing) return state;
|
|
102
|
-
const updated = {
|
|
103
|
-
...existing,
|
|
104
|
-
...patch
|
|
105
|
-
};
|
|
106
|
-
if (shallowEqualFile(existing, updated)) return state;
|
|
107
|
-
return {
|
|
108
|
-
files: {
|
|
109
|
-
...state.files,
|
|
110
|
-
[id]: updated
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
}),
|
|
114
|
-
removeFile: id => set(state => {
|
|
115
|
-
if (!state.files[id]) return state;
|
|
116
|
-
const {
|
|
117
|
-
[id]: _removed,
|
|
118
|
-
...rest
|
|
119
|
-
} = state.files;
|
|
120
|
-
const newOrder = state.order.filter(fid => fid !== id);
|
|
121
|
-
return {
|
|
122
|
-
files: rest,
|
|
123
|
-
order: newOrder
|
|
124
|
-
};
|
|
125
|
-
}),
|
|
126
|
-
setUploading: val => set({
|
|
127
|
-
uploading: val
|
|
128
|
-
}),
|
|
129
|
-
setDeleting: id => set({
|
|
130
|
-
deleting: id
|
|
131
|
-
}),
|
|
132
|
-
setUploadProgress: p => set({
|
|
133
|
-
uploadProgress: p
|
|
134
|
-
}),
|
|
135
|
-
reset: () => set(initialState)
|
|
136
|
-
}));
|
|
137
|
-
|
|
138
|
-
// selectors
|
|
139
|
-
const useFiles = () => {
|
|
140
|
-
const files = useFileStore(s => s.files);
|
|
141
|
-
const order = useFileStore(s => s.order);
|
|
142
|
-
// Return stable array when contents unchanged
|
|
143
|
-
const out = order.map(id => files[id]);
|
|
144
|
-
return out;
|
|
145
|
-
};
|
|
146
|
-
exports.useFiles = useFiles;
|
|
147
|
-
const useUploading = () => useFileStore(s => s.uploading);
|
|
148
|
-
exports.useUploading = useUploading;
|
|
149
|
-
const useUploadAggregateProgress = () => useFileStore(s => s.uploadProgress);
|
|
150
|
-
exports.useUploadAggregateProgress = useUploadAggregateProgress;
|
|
151
|
-
const useDeleting = () => useFileStore(s => s.deleting);
|
|
152
|
-
exports.useDeleting = useDeleting;
|
|
153
|
-
//# sourceMappingURL=fileStore.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_zustand","require","shallowEqualFile","a","b","aKeys","Object","keys","bKeys","length","k","initialState","files","order","uploading","deleting","uploadProgress","useFileStore","exports","create","set","get","setFiles","opts","state","merge","map","forEach","f","id","push","sameOrder","every","i","sameFiles","newFiles","newOrder","changed","prev","merged","includes","unshift","addFile","file","prepend","updateFile","patch","existing","updated","removeFile","_removed","rest","filter","fid","setUploading","val","setDeleting","setUploadProgress","p","reset","useFiles","s","out","useUploading","useUploadAggregateProgress","useDeleting"],"sourceRoot":"../../../../src","sources":["ui/stores/fileStore.ts"],"mappings":"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","ignoreList":[]}
|