@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
|
@@ -14,7 +14,7 @@ import { TextField, TextFieldInput } from '@oxyhq/bloom/text-field';
|
|
|
14
14
|
import { useI18n } from '../hooks/useI18n';
|
|
15
15
|
import { useOxy } from '../context/OxyContext';
|
|
16
16
|
import { useUpdateProfile } from '../hooks/mutations/useAccountMutations';
|
|
17
|
-
import {
|
|
17
|
+
import { getAccountDisplayName } from '@oxyhq/core';
|
|
18
18
|
|
|
19
19
|
const GAP = 12;
|
|
20
20
|
const INNER_GAP = 8;
|
|
@@ -58,7 +58,6 @@ const AnimatedProgressDot: React.FC<{
|
|
|
58
58
|
* - Only when the user presses "Continue" do we invoke onAuthenticated to finish flow & close sheet
|
|
59
59
|
*/
|
|
60
60
|
const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
61
|
-
navigate,
|
|
62
61
|
onAuthenticated,
|
|
63
62
|
theme,
|
|
64
63
|
newUser,
|
|
@@ -67,7 +66,7 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
67
66
|
// the ACTIVE account (the personal user during onboarding, but read through
|
|
68
67
|
// `user` so this stays correct everywhere), with the freshly
|
|
69
68
|
// registered `newUser` as the pre-store-hydration fallback.
|
|
70
|
-
const { user, oxyServices } = useOxy();
|
|
69
|
+
const { user, oxyServices, openAvatarPicker: openChangeAvatarSurface } = useOxy();
|
|
71
70
|
const { t, locale } = useI18n();
|
|
72
71
|
const updateProfileMutation = useUpdateProfile();
|
|
73
72
|
const currentUser = user || newUser; // fallback
|
|
@@ -83,24 +82,19 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
83
82
|
const fadeAnim = useRef(new Animated.Value(1)).current;
|
|
84
83
|
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
85
84
|
const [currentStep, setCurrentStep] = useState(0);
|
|
86
|
-
// Track avatar separately to ensure it updates immediately after selection
|
|
87
|
-
const [selectedAvatarId, setSelectedAvatarId] = useState<string | undefined>(currentUser?.avatar);
|
|
88
85
|
// Name form state for the conditional "set your name" step. Lazy initializers
|
|
89
86
|
// seed from the current user once; no useEffect prop→state sync.
|
|
90
87
|
const [firstName, setFirstName] = useState(() => (currentUser?.name?.first ?? '').trim());
|
|
91
88
|
const [lastName, setLastName] = useState(() => (currentUser?.name?.last ?? '').trim());
|
|
92
89
|
const [savingName, setSavingName] = useState(false);
|
|
93
90
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}, [user?.avatar, newUser?.avatar]);
|
|
102
|
-
|
|
103
|
-
const avatarUri = selectedAvatarId ? oxyServices.getFileDownloadUrl(selectedAvatarId, 'thumb') : undefined;
|
|
91
|
+
// Derived, not mirrored: `openAvatarPicker` writes through the shared avatar
|
|
92
|
+
// path, which updates the active account — including CLEARING it when the
|
|
93
|
+
// user removes their photo, which a "last non-empty value" mirror could not
|
|
94
|
+
// represent.
|
|
95
|
+
const avatarUri = currentUser?.avatar
|
|
96
|
+
? oxyServices.getFileDownloadUrl(currentUser.avatar, 'thumb')
|
|
97
|
+
: undefined;
|
|
104
98
|
|
|
105
99
|
// Steps content. Use the canonical helper so partially-onboarded accounts
|
|
106
100
|
// (publicKey only) still get a friendly greeting instead of a blank one.
|
|
@@ -186,43 +180,19 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
186
180
|
setSavingName(false);
|
|
187
181
|
}
|
|
188
182
|
}, [firstName, lastName, updateProfileMutation, animateToStepCallback, currentStep, t]);
|
|
183
|
+
/**
|
|
184
|
+
* Onboarding uses the SAME avatar flow as everywhere else — the ChangeAvatar
|
|
185
|
+
* surface (source list → crop → upload). It used to run its own
|
|
186
|
+
* pick-a-file-and-set-it path, which bypassed the cropper entirely.
|
|
187
|
+
*/
|
|
189
188
|
const openAvatarPicker = useCallback(() => {
|
|
190
|
-
// Ensure we're on the avatar step
|
|
189
|
+
// Ensure we're on the avatar step, so the wizard shows the new photo
|
|
190
|
+
// when the surface closes.
|
|
191
191
|
if (avatarStepIndex >= 0 && currentStep !== avatarStepIndex) {
|
|
192
192
|
animateToStepCallback(avatarStepIndex);
|
|
193
193
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
selectMode: true,
|
|
197
|
-
multiSelect: false,
|
|
198
|
-
disabledMimeTypes: ['video/', 'audio/', 'application/pdf'],
|
|
199
|
-
afterSelect: 'none', // Don't navigate away - stay on current screen
|
|
200
|
-
onSelect: async (file: any) => {
|
|
201
|
-
if (!file.contentType.startsWith('image/')) {
|
|
202
|
-
toast.error(t('editProfile.toasts.selectImage') || 'Please select an image file');
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
try {
|
|
206
|
-
// Update file visibility to public for avatar
|
|
207
|
-
await updateAvatarVisibility(file.id, oxyServices, 'WelcomeNewUser');
|
|
208
|
-
|
|
209
|
-
// Update the avatar immediately in local state
|
|
210
|
-
setSelectedAvatarId(file.id);
|
|
211
|
-
|
|
212
|
-
// Update user using TanStack Query mutation
|
|
213
|
-
await updateProfileMutation.mutateAsync({ avatar: file.id });
|
|
214
|
-
toast.success(t('editProfile.toasts.avatarUpdated') || 'Avatar updated');
|
|
215
|
-
|
|
216
|
-
// Ensure we stay on the avatar step
|
|
217
|
-
if (avatarStepIndex >= 0 && currentStep !== avatarStepIndex) {
|
|
218
|
-
animateToStepCallback(avatarStepIndex);
|
|
219
|
-
}
|
|
220
|
-
} catch (e: unknown) {
|
|
221
|
-
toast.error((e instanceof Error ? e.message : null) || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar');
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
}, [navigate, updateProfileMutation, oxyServices, currentStep, avatarStepIndex, animateToStepCallback, t]);
|
|
194
|
+
openChangeAvatarSurface();
|
|
195
|
+
}, [openChangeAvatarSurface, currentStep, avatarStepIndex, animateToStepCallback]);
|
|
226
196
|
|
|
227
197
|
const step = steps[currentStep];
|
|
228
198
|
const renderActionButtons = useCallback(() => {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { View, Text, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { Ionicons } from '@expo/vector-icons';
|
|
4
|
+
|
|
5
|
+
export interface FileLibraryErrorProps {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
retryLabel: string;
|
|
9
|
+
onRetry: () => void;
|
|
10
|
+
/** Failure icon tint. */
|
|
11
|
+
iconColor: string;
|
|
12
|
+
titleColor: string;
|
|
13
|
+
descriptionColor: string;
|
|
14
|
+
/** Retry button background (button label/icon are always white). */
|
|
15
|
+
buttonColor: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Terminal load-failure surface for the file library — rendered (INSTEAD of the
|
|
20
|
+
* "no files yet" empty state) when the list query errors with nothing cached, so
|
|
21
|
+
* a failed load never masquerades as an empty library. Pure presentational; the
|
|
22
|
+
* Retry action is wired to the query's `refetch()` by the caller. Themed via
|
|
23
|
+
* color props so it fits both the browse chrome and the dark picker backdrop.
|
|
24
|
+
*/
|
|
25
|
+
const FileLibraryError: React.FC<FileLibraryErrorProps> = ({
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
retryLabel,
|
|
29
|
+
onRetry,
|
|
30
|
+
iconColor,
|
|
31
|
+
titleColor,
|
|
32
|
+
descriptionColor,
|
|
33
|
+
buttonColor,
|
|
34
|
+
}) => (
|
|
35
|
+
<View className="items-center py-[40px] px-[24px]">
|
|
36
|
+
<Ionicons name="cloud-offline-outline" size={64} color={iconColor} />
|
|
37
|
+
<Text className="text-[24px] font-bold mt-[16px] mb-[8px] text-center" style={{ color: titleColor }}>
|
|
38
|
+
{title}
|
|
39
|
+
</Text>
|
|
40
|
+
<Text className="text-[16px] text-center leading-[24px] mb-[32px]" style={{ color: descriptionColor }}>
|
|
41
|
+
{description}
|
|
42
|
+
</Text>
|
|
43
|
+
<TouchableOpacity
|
|
44
|
+
className="flex-row items-center px-[24px] py-[12px] rounded-[24px] gap-[8px]"
|
|
45
|
+
style={{ backgroundColor: buttonColor }}
|
|
46
|
+
onPress={onRetry}
|
|
47
|
+
accessibilityRole="button"
|
|
48
|
+
accessibilityLabel={retryLabel}
|
|
49
|
+
>
|
|
50
|
+
<Ionicons name="refresh" size={20} color="#FFFFFF" />
|
|
51
|
+
<Text className="text-white text-[16px] font-semibold">{retryLabel}</Text>
|
|
52
|
+
</TouchableOpacity>
|
|
53
|
+
</View>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export default FileLibraryError;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
} from 'react-native';
|
|
14
14
|
import { Image as ExpoImage } from 'expo-image';
|
|
15
15
|
import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
|
|
16
|
-
import { BREAKPOINTS } from '@oxyhq/bloom/styles';
|
|
17
16
|
import * as Skeleton from '@oxyhq/bloom/skeleton';
|
|
18
17
|
import type { FileMetadata } from '@oxyhq/core';
|
|
19
18
|
import { computePhotoGridLayout } from './photoGridLayout';
|
|
19
|
+
import FileLibraryError from './FileLibraryError';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Haptic feedback wrapper. `expo-haptics` is an optional dependency — when not
|
|
@@ -130,6 +130,10 @@ export interface PhotoPickerViewProps {
|
|
|
130
130
|
* and container width, not the browse file-manager chrome.
|
|
131
131
|
*/
|
|
132
132
|
loading: boolean;
|
|
133
|
+
/** Terminal load failure (nothing cached) — renders a distinct error state. */
|
|
134
|
+
loadError: boolean;
|
|
135
|
+
/** Retry the failed list load (wired to the query's refetch). */
|
|
136
|
+
onRetry: () => void;
|
|
133
137
|
reduceMotion: boolean;
|
|
134
138
|
getThumbUrl: (file: FileMetadata) => string | undefined;
|
|
135
139
|
primaryColor: string;
|
|
@@ -217,38 +221,54 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: PhotoPickerCe
|
|
|
217
221
|
|
|
218
222
|
const delay = Math.min(enterIndex * STAGGER_PER_CELL_MS, MAX_TOTAL_STAGGER_MS);
|
|
219
223
|
|
|
220
|
-
// Entrance fade, staggered by the cell's grid index.
|
|
224
|
+
// Entrance fade, staggered by the cell's grid index. Started from the wrapper's
|
|
225
|
+
// ref callback (fires on mount) rather than an effect. Reduce-motion pins
|
|
221
226
|
// opacity at 1 and never animates.
|
|
227
|
+
//
|
|
228
|
+
// CRITICAL: `Animated.View` rebuilds its merged ref on every render, so React
|
|
229
|
+
// re-invokes this callback on EVERY commit (not just mount) — and re-running
|
|
230
|
+
// `Animated.timing().start()`/`setValue` each time drives a web re-render that
|
|
231
|
+
// re-fires the ref → "Maximum update depth exceeded" once the grid has cells.
|
|
232
|
+
// The `startedRef` latch makes it genuinely run-once per mount, breaking the
|
|
233
|
+
// loop. (jest/react-test-renderer never exercises the Animated merged-ref path,
|
|
234
|
+
// so this only reproduces in a real browser.)
|
|
222
235
|
const opacity = useRef(new Animated.Value(reduceMotion ? 1 : 0)).current;
|
|
223
|
-
|
|
236
|
+
const startedRef = useRef(false);
|
|
237
|
+
const startEntrance = useCallback((node: unknown) => {
|
|
238
|
+
if (!node) return; // unmount
|
|
239
|
+
if (startedRef.current) return; // ref re-fired on a later commit — already ran
|
|
240
|
+
startedRef.current = true;
|
|
224
241
|
if (reduceMotion) {
|
|
225
242
|
opacity.setValue(1);
|
|
226
243
|
return;
|
|
227
244
|
}
|
|
228
|
-
|
|
245
|
+
opacity.setValue(0);
|
|
246
|
+
Animated.timing(opacity, {
|
|
229
247
|
toValue: 1,
|
|
230
248
|
duration: ENTRANCE_DURATION_MS,
|
|
231
249
|
delay,
|
|
232
250
|
useNativeDriver: Platform.OS !== 'web',
|
|
233
|
-
});
|
|
234
|
-
entrance.start();
|
|
235
|
-
return () => entrance.stop();
|
|
251
|
+
}).start();
|
|
236
252
|
}, [opacity, delay, reduceMotion]);
|
|
237
253
|
|
|
238
|
-
// Selection-ring pulse: a quick scale bump
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
//
|
|
254
|
+
// Selection-ring pulse: a quick scale bump that springs back to rest. The ring
|
|
255
|
+
// renders ONLY while selected, so its own mount IS the "became selected"
|
|
256
|
+
// signal — driven from the ring's ref callback, not an effect. Reduce-motion
|
|
257
|
+
// holds the ring at rest scale. Same run-once latch as the entrance (the ring's
|
|
258
|
+
// `Animated.View` re-fires this ref every commit too) — reset on unmount so a
|
|
259
|
+
// later re-selection pulses again.
|
|
242
260
|
const ringScale = useRef(new Animated.Value(1)).current;
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
if (reduceMotion || !isSelected) {
|
|
248
|
-
ringScale.setValue(1);
|
|
261
|
+
const pulsedRef = useRef(false);
|
|
262
|
+
const startRingPulse = useCallback((node: unknown) => {
|
|
263
|
+
if (!node) {
|
|
264
|
+
pulsedRef.current = false; // ring unmounted (deselected) — arm the next pulse
|
|
249
265
|
return;
|
|
250
266
|
}
|
|
251
|
-
|
|
267
|
+
if (pulsedRef.current) return; // ref re-fired on a later commit — already pulsed
|
|
268
|
+
pulsedRef.current = true;
|
|
269
|
+
ringScale.setValue(1);
|
|
270
|
+
if (reduceMotion) return;
|
|
271
|
+
Animated.sequence([
|
|
252
272
|
Animated.timing(ringScale, {
|
|
253
273
|
toValue: RING_PULSE_PEAK,
|
|
254
274
|
duration: RING_PULSE_UP_MS,
|
|
@@ -260,10 +280,8 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: PhotoPickerCe
|
|
|
260
280
|
tension: RING_SPRING_TENSION,
|
|
261
281
|
useNativeDriver: Platform.OS !== 'web',
|
|
262
282
|
}),
|
|
263
|
-
]);
|
|
264
|
-
|
|
265
|
-
return () => pulse.stop();
|
|
266
|
-
}, [isSelected, ringScale, reduceMotion]);
|
|
283
|
+
]).start();
|
|
284
|
+
}, [ringScale, reduceMotion]);
|
|
267
285
|
|
|
268
286
|
return (
|
|
269
287
|
// The animated wrapper carries the entrance opacity + the layout box as
|
|
@@ -271,6 +289,7 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: PhotoPickerCe
|
|
|
271
289
|
// size/margins are runtime pixels className cannot express. `className`
|
|
272
290
|
// drives the static chrome below (`flex-1` fills this fixed-size box).
|
|
273
291
|
<Animated.View
|
|
292
|
+
ref={startEntrance}
|
|
274
293
|
style={{
|
|
275
294
|
width: size,
|
|
276
295
|
height: size,
|
|
@@ -303,6 +322,7 @@ const PhotoPickerCell = React.memo(function PhotoPickerCell(props: PhotoPickerCe
|
|
|
303
322
|
</View>
|
|
304
323
|
{isSelected && (
|
|
305
324
|
<Animated.View
|
|
325
|
+
ref={startRingPulse}
|
|
306
326
|
pointerEvents="none"
|
|
307
327
|
style={{
|
|
308
328
|
position: 'absolute',
|
|
@@ -346,6 +366,8 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
346
366
|
hasMore,
|
|
347
367
|
loadingMore,
|
|
348
368
|
loading,
|
|
369
|
+
loadError,
|
|
370
|
+
onRetry,
|
|
349
371
|
reduceMotion,
|
|
350
372
|
getThumbUrl,
|
|
351
373
|
primaryColor,
|
|
@@ -376,24 +398,15 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
376
398
|
setGridWidth((prev) => (prev === w ? prev : w));
|
|
377
399
|
}, []);
|
|
378
400
|
|
|
379
|
-
// The
|
|
380
|
-
//
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
// breakpoint in sync with `SHEET_PLACEMENT` in surfaces.ts.
|
|
389
|
-
const isCenteredPanel = windowWidth >= BREAKPOINTS.md;
|
|
390
|
-
const maxPanelHeight = useMemo(
|
|
391
|
-
() => (isCenteredPanel
|
|
392
|
-
? Math.min(Math.round(windowHeight * 0.85), 720)
|
|
393
|
-
: Math.round(windowHeight * 0.9)),
|
|
394
|
-
[isCenteredPanel, windowHeight],
|
|
395
|
-
);
|
|
396
|
-
const rootStyle = useMemo(() => ({ maxHeight: maxPanelHeight }), [maxPanelHeight]);
|
|
401
|
+
// The picker FILLS its panel: the surface morphs the container UP to an
|
|
402
|
+
// explicit large target (`frameSize.heightRatio: 0.9` in `surfaceRegistry`),
|
|
403
|
+
// and this root takes that SAME 0.9-of-viewport height so the grid uses the
|
|
404
|
+
// whole grown card (a `flex: 1` root can't fill — no definite bound propagates
|
|
405
|
+
// through the sheet's flex chain, and the panel is pinned, not measured). The
|
|
406
|
+
// FlatList then scrolls within this fixed height. Keep the 0.9 ratio in sync
|
|
407
|
+
// with the picker's `frameSize` in `surfaceRegistry.ts`.
|
|
408
|
+
const panelHeight = useMemo(() => Math.round(windowHeight * 0.9), [windowHeight]);
|
|
409
|
+
const rootStyle = useMemo(() => ({ height: panelHeight }), [panelHeight]);
|
|
397
410
|
|
|
398
411
|
const effectiveWidth = gridWidth > 0 ? gridWidth : windowWidth;
|
|
399
412
|
const { columns, cellSize, gutter } = useMemo(
|
|
@@ -408,10 +421,10 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
408
421
|
const skeletonTileCount = useMemo(() => {
|
|
409
422
|
const rowHeight = cellSize + gutter;
|
|
410
423
|
if (rowHeight <= 0) return columns * SKELETON_MIN_ROWS;
|
|
411
|
-
const available = Math.max(0,
|
|
424
|
+
const available = Math.max(0, panelHeight - GRID_CONTENT_PADDING_TOP);
|
|
412
425
|
const rows = Math.max(SKELETON_MIN_ROWS, Math.floor(available / rowHeight));
|
|
413
426
|
return rows * columns;
|
|
414
|
-
}, [cellSize, gutter, columns,
|
|
427
|
+
}, [cellSize, gutter, columns, panelHeight]);
|
|
415
428
|
|
|
416
429
|
// Map selectedIds → 1-based selection order for the badge. We freeze a
|
|
417
430
|
// stable order at the time of selection: the order is the insertion
|
|
@@ -547,7 +560,23 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
547
560
|
where Yoga already defaults min-height to 0). */}
|
|
548
561
|
<View className="flex-1 min-h-0 bg-black">
|
|
549
562
|
{/* Photo grid (renders behind the translucent header). */}
|
|
550
|
-
{isEmpty &&
|
|
563
|
+
{isEmpty && loadError ? (
|
|
564
|
+
/* Terminal load failure — a DISTINCT error surface (not the
|
|
565
|
+
empty state), pushed below the translucent header so Cancel
|
|
566
|
+
stays reachable. Retry re-runs the list query. */
|
|
567
|
+
<View className="flex-1 items-center justify-center pt-[60px]">
|
|
568
|
+
<FileLibraryError
|
|
569
|
+
title={t('fileManagement.loadError.title')}
|
|
570
|
+
description={t('fileManagement.loadError.description')}
|
|
571
|
+
retryLabel={t('fileManagement.retry')}
|
|
572
|
+
onRetry={onRetry}
|
|
573
|
+
iconColor="#FF6B6B"
|
|
574
|
+
titleColor="#FFFFFF"
|
|
575
|
+
descriptionColor="rgba(255,255,255,0.7)"
|
|
576
|
+
buttonColor={primaryColor}
|
|
577
|
+
/>
|
|
578
|
+
</View>
|
|
579
|
+
) : isEmpty && loading ? (
|
|
551
580
|
/* Loading skeleton — the picker's OWN shape: shimmer tiles laid
|
|
552
581
|
out with the SAME placement-aware geometry the real grid uses
|
|
553
582
|
(`computePhotoGridLayout(effectiveWidth)`), pushed below the
|