@oxyhq/services 22.12.1 → 22.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/ui/components/FollowButton.js +5 -8
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSurfaceHeader.js +44 -7
- 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/navigation/surfaces.js +8 -3
- package/lib/commonjs/ui/navigation/surfaces.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 +60 -98
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +22 -8
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +10 -7
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/UploadBar.js +19 -11
- package/lib/commonjs/ui/screens/fileManagement/UploadBar.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +42 -9
- 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 +45 -8
- 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/navigation/surfaces.js +7 -1
- package/lib/module/ui/navigation/surfaces.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 +62 -100
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +22 -8
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +10 -7
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/UploadBar.js +20 -12
- package/lib/module/ui/screens/fileManagement/UploadBar.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +43 -10
- 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 +7 -0
- 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/navigation/surfaces.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.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/UploadBar.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +5 -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 +7 -0
- 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/navigation/surfaces.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.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/UploadBar.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +5 -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 +65 -8
- package/src/ui/navigation/__tests__/surfaceNavStack.test.ts +49 -17
- package/src/ui/navigation/surfaceNavStack.ts +15 -11
- package/src/ui/navigation/surfaces.ts +9 -1
- package/src/ui/screens/ChangeAvatarScreen.tsx +46 -39
- package/src/ui/screens/CreateAccountScreen.tsx +128 -166
- package/src/ui/screens/FileManagementScreen.tsx +22 -8
- package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +4 -5
- package/src/ui/screens/fileManagement/UploadBar.tsx +17 -10
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +51 -10
- package/src/ui/types/fileManagement.ts +10 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
-
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { useQueryClient } from '@tanstack/react-query';
|
|
4
4
|
import { toast } from '@oxyhq/bloom';
|
|
5
5
|
import type { AssetUploadInput, FileMetadata } from '@oxyhq/core';
|
|
@@ -58,8 +58,12 @@ 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;
|
|
65
|
+
/** When true, the document picker and pre-upload validation accept images only. */
|
|
66
|
+
imagesOnly?: boolean;
|
|
63
67
|
selectedIds: Set<string>;
|
|
64
68
|
setSelectedIds: React.Dispatch<React.SetStateAction<Set<string>>>;
|
|
65
69
|
t: (key: string, vars?: Record<string, string | number>) => string;
|
|
@@ -94,8 +98,10 @@ export const useFileUploadState = ({
|
|
|
94
98
|
multiSelect,
|
|
95
99
|
afterSelect,
|
|
96
100
|
onSelect,
|
|
101
|
+
onPicked,
|
|
97
102
|
goBack,
|
|
98
103
|
onClose,
|
|
104
|
+
imagesOnly = false,
|
|
99
105
|
selectedIds,
|
|
100
106
|
setSelectedIds,
|
|
101
107
|
t,
|
|
@@ -108,6 +114,23 @@ export const useFileUploadState = ({
|
|
|
108
114
|
|
|
109
115
|
const queryClient = useQueryClient();
|
|
110
116
|
const uploadStartRef = useRef<number | null>(null);
|
|
117
|
+
const postSelectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
118
|
+
const isActiveRef = useRef(true);
|
|
119
|
+
|
|
120
|
+
const clearPostSelectTimer = useCallback(() => {
|
|
121
|
+
if (postSelectTimerRef.current) {
|
|
122
|
+
clearTimeout(postSelectTimerRef.current);
|
|
123
|
+
postSelectTimerRef.current = null;
|
|
124
|
+
}
|
|
125
|
+
}, []);
|
|
126
|
+
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
isActiveRef.current = true;
|
|
129
|
+
return () => {
|
|
130
|
+
isActiveRef.current = false;
|
|
131
|
+
clearPostSelectTimer();
|
|
132
|
+
};
|
|
133
|
+
}, [clearPostSelectTimer]);
|
|
111
134
|
|
|
112
135
|
const endUpload = useCallback(() => {
|
|
113
136
|
const started = uploadStartRef.current;
|
|
@@ -274,6 +297,11 @@ export const useFileUploadState = ({
|
|
|
274
297
|
|
|
275
298
|
const fileType = candidateType(file);
|
|
276
299
|
|
|
300
|
+
if (imagesOnly && !fileType.startsWith('image/')) {
|
|
301
|
+
toast.error(t('fileManagement.toasts.imagesOnlyRequired'));
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
277
305
|
// Generate preview for images - unified approach
|
|
278
306
|
let preview: string | undefined;
|
|
279
307
|
if (fileType.startsWith('image/')) {
|
|
@@ -308,7 +336,7 @@ export const useFileUploadState = ({
|
|
|
308
336
|
// Show preview modal for user to review files before upload
|
|
309
337
|
setPendingFiles(processedFiles);
|
|
310
338
|
setShowUploadPreview(true);
|
|
311
|
-
}, [t]);
|
|
339
|
+
}, [imagesOnly, t]);
|
|
312
340
|
|
|
313
341
|
const handleConfirmUpload = async () => {
|
|
314
342
|
if (pendingFiles.length === 0) return;
|
|
@@ -332,15 +360,26 @@ export const useFileUploadState = ({
|
|
|
332
360
|
// If in selectMode, automatically select the uploaded file(s)
|
|
333
361
|
if (selectMode && uploadedFiles.length > 0) {
|
|
334
362
|
// Defer one tick so the query cache has settled before selecting.
|
|
335
|
-
|
|
363
|
+
clearPostSelectTimer();
|
|
364
|
+
postSelectTimerRef.current = setTimeout(() => {
|
|
365
|
+
postSelectTimerRef.current = null;
|
|
366
|
+
if (!isActiveRef.current) return;
|
|
367
|
+
|
|
336
368
|
const fileToSelect = uploadedFiles[0];
|
|
337
369
|
if (!multiSelect && fileToSelect) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
370
|
+
if (onPicked) {
|
|
371
|
+
// Forward-navigation picker (avatar flow): hand the
|
|
372
|
+
// freshly-uploaded file onward (to the cropper). No
|
|
373
|
+
// dismiss/close — the picker frame stays below.
|
|
374
|
+
onPicked(fileToSelect);
|
|
375
|
+
} else {
|
|
376
|
+
// Single select mode - directly call onSelect callback
|
|
377
|
+
onSelect?.(fileToSelect);
|
|
378
|
+
if (afterSelect === 'back') {
|
|
379
|
+
goBack?.();
|
|
380
|
+
} else if (afterSelect === 'close') {
|
|
381
|
+
onClose?.();
|
|
382
|
+
}
|
|
344
383
|
}
|
|
345
384
|
} else if (multiSelect) {
|
|
346
385
|
// Multi-select mode - add all uploaded files to selection
|
|
@@ -361,6 +400,8 @@ export const useFileUploadState = ({
|
|
|
361
400
|
};
|
|
362
401
|
|
|
363
402
|
const handleCancelUpload = () => {
|
|
403
|
+
clearPostSelectTimer();
|
|
404
|
+
|
|
364
405
|
// Cleanup preview URLs
|
|
365
406
|
for (const pf of pendingFiles) {
|
|
366
407
|
revokePreviewUrl(pf.preview);
|
|
@@ -402,7 +443,7 @@ export const useFileUploadState = ({
|
|
|
402
443
|
// Use expo-document-picker (works on all platforms including web)
|
|
403
444
|
// On web, it uses the native file input and provides File objects directly
|
|
404
445
|
const result = await picker.getDocumentAsync({
|
|
405
|
-
type: '*/*',
|
|
446
|
+
type: imagesOnly ? 'image/*' : '*/*',
|
|
406
447
|
multiple: true,
|
|
407
448
|
copyToCacheDirectory: true,
|
|
408
449
|
});
|
|
@@ -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
|