@oxyhq/services 22.12.0 → 22.12.2
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/FollowButton.js +5 -8
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSurfaceHeader.js +2 -2
- package/lib/commonjs/ui/hooks/useSurfaceHeader.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaceNavStack.js +8 -7
- package/lib/commonjs/ui/navigation/surfaceNavStack.js.map +1 -1
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js +48 -42
- package/lib/commonjs/ui/screens/ChangeAvatarScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js +55 -98
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +32 -13
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +35 -41
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +14 -6
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +5 -8
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/hooks/useSurfaceHeader.js +2 -2
- package/lib/module/ui/hooks/useSurfaceHeader.js.map +1 -1
- package/lib/module/ui/navigation/surfaceNavStack.js +8 -7
- package/lib/module/ui/navigation/surfaceNavStack.js.map +1 -1
- package/lib/module/ui/screens/ChangeAvatarScreen.js +48 -42
- package/lib/module/ui/screens/ChangeAvatarScreen.js.map +1 -1
- package/lib/module/ui/screens/CreateAccountScreen.js +58 -101
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +32 -13
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +35 -41
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +14 -6
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSurfaceHeader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts +7 -4
- package/lib/typescript/commonjs/ui/navigation/surfaceNavStack.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts +9 -5
- package/lib/typescript/commonjs/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts +1 -1
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +3 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/fileManagement.d.ts +10 -0
- package/lib/typescript/commonjs/ui/types/fileManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSurfaceHeader.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts +7 -4
- package/lib/typescript/module/ui/navigation/surfaceNavStack.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts +9 -5
- package/lib/typescript/module/ui/screens/ChangeAvatarScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts +1 -1
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +3 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/fileManagement.d.ts +10 -0
- package/lib/typescript/module/ui/types/fileManagement.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ui/components/FollowButton.tsx +5 -8
- package/src/ui/hooks/useSurfaceHeader.ts +2 -17
- package/src/ui/navigation/__tests__/surfaceNavStack.test.ts +49 -17
- package/src/ui/navigation/surfaceNavStack.ts +15 -11
- package/src/ui/screens/ChangeAvatarScreen.tsx +46 -39
- package/src/ui/screens/CreateAccountScreen.tsx +123 -167
- package/src/ui/screens/FileManagementScreen.tsx +28 -12
- package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +35 -44
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +16 -6
- package/src/ui/types/fileManagement.ts +10 -0
|
@@ -74,26 +74,22 @@ const hapticSelection = async (): Promise<void> => {
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
* The picker renders inside a Bloom `<Dialog>` in NAV-HEADER mode
|
|
78
|
-
* narrow, centered card on `md+`). The Dialog
|
|
79
|
-
* (Cancel / "Choose Photo" / Upload, wired by
|
|
80
|
-
* `useSurfaceHeader`)
|
|
81
|
-
* the Dialog
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* content; the grid's `pt-[24px]` (fade + 4dp breathing room) clears it. The
|
|
92
|
-
* `GRID_CONTENT_PADDING_TOP` constant MUST stay in sync with that class.
|
|
77
|
+
* The picker renders inside a Bloom `<Dialog>` in NAV-HEADER mode with
|
|
78
|
+
* `tone: 'onImage'` (bottom-sheet on narrow, centered card on `md+`). The Dialog
|
|
79
|
+
* owns the shared gradient nav bar (Cancel / "Choose Photo" / Upload, wired by
|
|
80
|
+
* `FileManagementScreen` through `useSurfaceHeader`). Because the tone is
|
|
81
|
+
* `'onImage'`, the Dialog inserts NO nav-bar spacer above this content
|
|
82
|
+
* (`DialogNavBarSpacer` collapses to nothing), so the black photo grid slides UP
|
|
83
|
+
* under the floating translucent bar and reads EDGE-TO-EDGE — the Apple/Google
|
|
84
|
+
* Photos immersive picker. The grid therefore takes the FULL `frameSize` height
|
|
85
|
+
* and carries no top padding; only the pull-to-refresh spinner is offset so it
|
|
86
|
+
* lands below the floating bar.
|
|
87
|
+
*
|
|
88
|
+
* `FLOATING_NAV_BAR_HEIGHT` mirrors Bloom's `DIALOG_NAV_BAR_HEIGHT` (not exported
|
|
89
|
+
* from `@oxyhq/bloom/dialog`) — the height of the floating bar the refresh spinner
|
|
90
|
+
* must clear.
|
|
93
91
|
*/
|
|
94
|
-
const
|
|
95
|
-
const HEADER_GRADIENT_FADE = 20;
|
|
96
|
-
const GRID_CONTENT_PADDING_TOP = HEADER_GRADIENT_FADE + 4; // 24 — matches `pt-[24px]`
|
|
92
|
+
const FLOATING_NAV_BAR_HEIGHT = 52;
|
|
97
93
|
|
|
98
94
|
/**
|
|
99
95
|
* Props for the dedicated photo picker view. Used by FileManagementScreen
|
|
@@ -383,18 +379,15 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
383
379
|
|
|
384
380
|
// The picker FILLS its panel: the surface morphs the container UP to an
|
|
385
381
|
// explicit large target (`frameSize.heightRatio: 0.9` in `surfaceRegistry`),
|
|
386
|
-
// and this root takes that SAME 0.9-of-viewport height
|
|
387
|
-
// nav-bar spacer
|
|
388
|
-
//
|
|
389
|
-
// `maxHeightRatio: 0.9` cap
|
|
390
|
-
//
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
const panelHeight = useMemo(
|
|
395
|
-
() => Math.round(windowHeight * 0.9) - DIALOG_NAV_BAR_SPACER,
|
|
396
|
-
[windowHeight],
|
|
397
|
-
);
|
|
382
|
+
// and this root takes that SAME 0.9-of-viewport height. Under `tone:'onImage'`
|
|
383
|
+
// the Dialog inserts NO nav-bar spacer, so the grid uses the FULL morph target
|
|
384
|
+
// (no `-52`) and slides up under the floating bar, edge-to-edge, within the
|
|
385
|
+
// panel's `maxHeightRatio: 0.9` cap. A `flex: 1` root can't fill (no definite
|
|
386
|
+
// bound propagates through the sheet's flex chain at rest, where the panel is
|
|
387
|
+
// height:auto), so the fixed height is required; the FlatList scrolls within
|
|
388
|
+
// it. Keep the 0.9 ratio in sync with the picker's `frameSize` in
|
|
389
|
+
// `surfaceRegistry.ts`.
|
|
390
|
+
const panelHeight = useMemo(() => Math.round(windowHeight * 0.9), [windowHeight]);
|
|
398
391
|
const rootStyle = useMemo(() => ({ height: panelHeight }), [panelHeight]);
|
|
399
392
|
|
|
400
393
|
const effectiveWidth = gridWidth > 0 ? gridWidth : windowWidth;
|
|
@@ -410,7 +403,7 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
410
403
|
const skeletonTileCount = useMemo(() => {
|
|
411
404
|
const rowHeight = cellSize + gutter;
|
|
412
405
|
if (rowHeight <= 0) return columns * SKELETON_MIN_ROWS;
|
|
413
|
-
const available = Math.max(0, panelHeight -
|
|
406
|
+
const available = Math.max(0, panelHeight - FLOATING_NAV_BAR_HEIGHT);
|
|
414
407
|
const rows = Math.max(SKELETON_MIN_ROWS, Math.floor(available / rowHeight));
|
|
415
408
|
return rows * columns;
|
|
416
409
|
}, [cellSize, gutter, columns, panelHeight]);
|
|
@@ -531,9 +524,9 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
531
524
|
clears that fade). */}
|
|
532
525
|
{isEmpty && loadError ? (
|
|
533
526
|
/* Terminal load failure — a DISTINCT error surface (not the
|
|
534
|
-
empty state),
|
|
535
|
-
|
|
536
|
-
<View className="flex-1 items-center justify-center
|
|
527
|
+
empty state), centered in the immersive frame. Retry re-runs
|
|
528
|
+
the list query. */
|
|
529
|
+
<View className="flex-1 items-center justify-center">
|
|
537
530
|
<FileLibraryError
|
|
538
531
|
title={t('fileManagement.loadError.title')}
|
|
539
532
|
description={t('fileManagement.loadError.description')}
|
|
@@ -548,13 +541,11 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
548
541
|
) : isEmpty && loading ? (
|
|
549
542
|
/* Loading skeleton — the picker's OWN shape: shimmer tiles laid
|
|
550
543
|
out with the SAME placement-aware geometry the real grid uses
|
|
551
|
-
(`computePhotoGridLayout(effectiveWidth)`),
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
construction). */
|
|
544
|
+
(`computePhotoGridLayout(effectiveWidth)`), edge-to-edge under
|
|
545
|
+
the floating bar. `flexWrap` breaks rows exactly at `columns`
|
|
546
|
+
because the last tile in each row carries no right margin (a
|
|
547
|
+
full row + gutters fits the measured width by construction). */
|
|
556
548
|
<View
|
|
557
|
-
className="pt-[24px]"
|
|
558
549
|
style={{ flexDirection: 'row', flexWrap: 'wrap' }}
|
|
559
550
|
pointerEvents="none"
|
|
560
551
|
accessibilityElementsHidden
|
|
@@ -575,7 +566,7 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
575
566
|
))}
|
|
576
567
|
</View>
|
|
577
568
|
) : isEmpty ? (
|
|
578
|
-
<View className="flex-1 items-center justify-center px-space-32
|
|
569
|
+
<View className="flex-1 items-center justify-center px-space-32">
|
|
579
570
|
<View className="opacity-30 mb-space-16">
|
|
580
571
|
<MaterialCommunityIcons name="image-outline" size={64} color="#FFFFFF" />
|
|
581
572
|
</View>
|
|
@@ -616,7 +607,7 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
616
607
|
keyExtractor={keyExtractor}
|
|
617
608
|
numColumns={columns}
|
|
618
609
|
className="flex-1 min-h-0"
|
|
619
|
-
contentContainerClassName="
|
|
610
|
+
contentContainerClassName="pb-space-24"
|
|
620
611
|
showsVerticalScrollIndicator={false}
|
|
621
612
|
refreshControl={
|
|
622
613
|
<RefreshControl
|
|
@@ -624,7 +615,7 @@ const PhotoPickerView: React.FC<PhotoPickerViewProps> = ({
|
|
|
624
615
|
onRefresh={onRefresh}
|
|
625
616
|
tintColor="#FFFFFF"
|
|
626
617
|
colors={[primaryColor]}
|
|
627
|
-
progressViewOffset={
|
|
618
|
+
progressViewOffset={FLOATING_NAV_BAR_HEIGHT}
|
|
628
619
|
/>
|
|
629
620
|
}
|
|
630
621
|
onEndReached={handleEndReached}
|
|
@@ -58,6 +58,8 @@ export interface UseFileUploadStateParams {
|
|
|
58
58
|
multiSelect: boolean;
|
|
59
59
|
afterSelect: 'close' | 'back' | 'none';
|
|
60
60
|
onSelect?: (file: FileMetadata) => void;
|
|
61
|
+
/** Forward-navigation picker: see {@link FileManagementScreenProps.onPicked}. */
|
|
62
|
+
onPicked?: (file: FileMetadata) => void;
|
|
61
63
|
goBack?: () => void;
|
|
62
64
|
onClose?: () => void;
|
|
63
65
|
selectedIds: Set<string>;
|
|
@@ -94,6 +96,7 @@ export const useFileUploadState = ({
|
|
|
94
96
|
multiSelect,
|
|
95
97
|
afterSelect,
|
|
96
98
|
onSelect,
|
|
99
|
+
onPicked,
|
|
97
100
|
goBack,
|
|
98
101
|
onClose,
|
|
99
102
|
selectedIds,
|
|
@@ -335,12 +338,19 @@ export const useFileUploadState = ({
|
|
|
335
338
|
setTimeout(() => {
|
|
336
339
|
const fileToSelect = uploadedFiles[0];
|
|
337
340
|
if (!multiSelect && fileToSelect) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
if (onPicked) {
|
|
342
|
+
// Forward-navigation picker (avatar flow): hand the
|
|
343
|
+
// freshly-uploaded file onward (to the cropper). No
|
|
344
|
+
// dismiss/close — the picker frame stays below.
|
|
345
|
+
onPicked(fileToSelect);
|
|
346
|
+
} else {
|
|
347
|
+
// Single select mode - directly call onSelect callback
|
|
348
|
+
onSelect?.(fileToSelect);
|
|
349
|
+
if (afterSelect === 'back') {
|
|
350
|
+
goBack?.();
|
|
351
|
+
} else if (afterSelect === 'close') {
|
|
352
|
+
onClose?.();
|
|
353
|
+
}
|
|
344
354
|
}
|
|
345
355
|
} else if (multiSelect) {
|
|
346
356
|
// Multi-select mode - add all uploaded files to selection
|
|
@@ -14,6 +14,16 @@ export interface FileManagementScreenProps extends BaseScreenProps {
|
|
|
14
14
|
multiSelect?: boolean;
|
|
15
15
|
// Callback when a file is selected (single select mode)
|
|
16
16
|
onSelect?: (file: FileMetadata) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Forward-navigation picker: called with the picked file in single-select
|
|
19
|
+
* mode when the picker is one FRAME of a larger in-surface flow. Unlike
|
|
20
|
+
* {@link onSelect}, the caller is expected to NAVIGATE the surface onward
|
|
21
|
+
* (e.g. the avatar flow pushes the cropper on top of this picker) — so on
|
|
22
|
+
* select the picker neither dismisses nor closes the session, and its
|
|
23
|
+
* Cancel/back pops THIS frame (returning to the frame that opened the picker)
|
|
24
|
+
* rather than closing. Takes precedence over `onSelect`/`dismiss` when set.
|
|
25
|
+
*/
|
|
26
|
+
onPicked?: (file: FileMetadata) => void;
|
|
17
27
|
// Callback when confirm pressed in multi-select mode
|
|
18
28
|
onConfirmSelection?: OnConfirmFileSelection;
|
|
19
29
|
// Initial selected file IDs for multi-select
|