@uploadista/react-native-core 0.0.20-beta.2 → 0.0.20-beta.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/dist/index.d.mts +192 -53
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/hooks/index.ts +1 -1
- package/src/index.ts +7 -3
- package/src/hooks/use-flow-upload.ts +0 -223
package/src/hooks/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export {
|
|
|
6
6
|
export { useCameraUpload } from "./use-camera-upload";
|
|
7
7
|
export { useFileUpload } from "./use-file-upload";
|
|
8
8
|
// Flow hooks
|
|
9
|
+
// useFlow is the primary hook for flow operations (replaces useFlowUpload)
|
|
9
10
|
export type {
|
|
10
11
|
FlowInputMetadata,
|
|
11
12
|
FlowUploadState,
|
|
@@ -15,7 +16,6 @@ export type {
|
|
|
15
16
|
UseFlowReturn,
|
|
16
17
|
} from "./use-flow";
|
|
17
18
|
export { useFlow } from "./use-flow";
|
|
18
|
-
export { useFlowUpload } from "./use-flow-upload";
|
|
19
19
|
export { useGalleryUpload } from "./use-gallery-upload";
|
|
20
20
|
// Multi-upload hooks
|
|
21
21
|
export type {
|
package/src/index.ts
CHANGED
|
@@ -46,21 +46,26 @@ export {
|
|
|
46
46
|
useFlowManagerContext,
|
|
47
47
|
} from "./contexts/flow-manager-context";
|
|
48
48
|
// Export hooks
|
|
49
|
+
// useFlow is the primary hook for flow operations (replaces useFlowUpload)
|
|
49
50
|
export {
|
|
50
51
|
UploadistaContext,
|
|
51
52
|
type UploadistaContextType,
|
|
52
53
|
useCameraUpload,
|
|
53
54
|
useFileUpload,
|
|
54
|
-
|
|
55
|
+
useFlow,
|
|
55
56
|
useGalleryUpload,
|
|
56
57
|
useMultiUpload,
|
|
57
58
|
useUploadistaContext,
|
|
58
59
|
useUploadMetrics,
|
|
59
60
|
} from "./hooks";
|
|
60
61
|
export type {
|
|
62
|
+
FlowInputMetadata,
|
|
61
63
|
FlowUploadState,
|
|
62
64
|
FlowUploadStatus,
|
|
63
|
-
|
|
65
|
+
InputExecutionState,
|
|
66
|
+
UseFlowOptions,
|
|
67
|
+
UseFlowReturn,
|
|
68
|
+
} from "./hooks/use-flow";
|
|
64
69
|
export type {
|
|
65
70
|
MultiUploadState,
|
|
66
71
|
UploadItemState,
|
|
@@ -80,7 +85,6 @@ export type {
|
|
|
80
85
|
UploadMetrics,
|
|
81
86
|
UseCameraUploadOptions,
|
|
82
87
|
UseFileUploadOptions,
|
|
83
|
-
UseFlowUploadOptions,
|
|
84
88
|
UseGalleryUploadOptions,
|
|
85
89
|
UseMultiUploadOptions,
|
|
86
90
|
} from "./types";
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FlowManager,
|
|
3
|
-
FlowUploadState,
|
|
4
|
-
FlowUploadStatus,
|
|
5
|
-
} from "@uploadista/client-core";
|
|
6
|
-
import type { TypedOutput } from "@uploadista/core/flow";
|
|
7
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
8
|
-
import { useFlowManagerContext } from "../contexts/flow-manager-context";
|
|
9
|
-
import type { FilePickResult, UseFlowUploadOptions } from "../types";
|
|
10
|
-
import { createBlobFromBuffer } from "../types/platform-types";
|
|
11
|
-
import { useUploadistaContext } from "./use-uploadista-context";
|
|
12
|
-
|
|
13
|
-
// Re-export types from core for convenience
|
|
14
|
-
export type { FlowUploadState, FlowUploadStatus };
|
|
15
|
-
|
|
16
|
-
const initialState: FlowUploadState = {
|
|
17
|
-
status: "idle",
|
|
18
|
-
progress: 0,
|
|
19
|
-
bytesUploaded: 0,
|
|
20
|
-
totalBytes: null,
|
|
21
|
-
error: null,
|
|
22
|
-
jobId: null,
|
|
23
|
-
flowStarted: false,
|
|
24
|
-
currentNodeName: null,
|
|
25
|
-
currentNodeType: null,
|
|
26
|
-
flowOutputs: null,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Hook for uploading files through a flow pipeline with full state management.
|
|
31
|
-
* Provides upload progress tracking, flow execution monitoring, error handling, and abort functionality.
|
|
32
|
-
*
|
|
33
|
-
* Must be used within FlowManagerProvider (which must be within UploadistaProvider).
|
|
34
|
-
* Flow events are automatically routed by the provider to the appropriate manager.
|
|
35
|
-
*
|
|
36
|
-
* @param options - Flow upload configuration
|
|
37
|
-
* @returns Flow upload state and control methods
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```tsx
|
|
41
|
-
* function MyComponent() {
|
|
42
|
-
* const flowUpload = useFlowUpload({
|
|
43
|
-
* flowId: 'image-processing-flow',
|
|
44
|
-
* storageId: 'my-storage',
|
|
45
|
-
* onSuccess: (result) => console.log('Flow complete:', result),
|
|
46
|
-
* onError: (error) => console.error('Flow failed:', error),
|
|
47
|
-
* onProgress: (progress) => console.log('Progress:', progress + '%'),
|
|
48
|
-
* });
|
|
49
|
-
*
|
|
50
|
-
* const handlePickFile = async () => {
|
|
51
|
-
* const file = await fileSystemProvider.pickDocument();
|
|
52
|
-
* if (file) {
|
|
53
|
-
* await flowUpload.upload(file);
|
|
54
|
-
* }
|
|
55
|
-
* };
|
|
56
|
-
*
|
|
57
|
-
* return (
|
|
58
|
-
* <View>
|
|
59
|
-
* <Button title="Pick File" onPress={handlePickFile} />
|
|
60
|
-
* {flowUpload.isUploading && <Text>Progress: {flowUpload.state.progress}%</Text>}
|
|
61
|
-
* {flowUpload.state.jobId && <Text>Job ID: {flowUpload.state.jobId}</Text>}
|
|
62
|
-
* {flowUpload.state.error && <Text>Error: {flowUpload.state.error.message}</Text>}
|
|
63
|
-
* <Button title="Abort" onPress={flowUpload.abort} disabled={!flowUpload.isActive} />
|
|
64
|
-
* </View>
|
|
65
|
-
* );
|
|
66
|
-
* }
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
export function useFlowUpload(options: UseFlowUploadOptions) {
|
|
70
|
-
const { getManager, releaseManager } = useFlowManagerContext();
|
|
71
|
-
const { fileSystemProvider } = useUploadistaContext();
|
|
72
|
-
const [state, setState] = useState<FlowUploadState>(initialState);
|
|
73
|
-
const managerRef = useRef<FlowManager<unknown> | null>(null);
|
|
74
|
-
const lastFileRef = useRef<FilePickResult | null>(null);
|
|
75
|
-
|
|
76
|
-
// Store callbacks in refs so they can be updated without recreating the manager
|
|
77
|
-
const callbacksRef = useRef(options);
|
|
78
|
-
|
|
79
|
-
// Update refs on every render to capture latest callbacks
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
callbacksRef.current = options;
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Get or create manager from context when component mounts
|
|
85
|
-
// Manager lifecycle is now handled by FlowManagerProvider
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
const flowId = options.flowId;
|
|
88
|
-
|
|
89
|
-
// Create stable callback wrappers that call the latest callbacks via refs
|
|
90
|
-
const stableCallbacks = {
|
|
91
|
-
onStateChange: setState,
|
|
92
|
-
onProgress: (
|
|
93
|
-
_uploadId: string,
|
|
94
|
-
bytesUploaded: number,
|
|
95
|
-
totalBytes: number | null,
|
|
96
|
-
) => {
|
|
97
|
-
if (callbacksRef.current.onProgress) {
|
|
98
|
-
const progress = totalBytes
|
|
99
|
-
? Math.round((bytesUploaded / totalBytes) * 100)
|
|
100
|
-
: 0;
|
|
101
|
-
callbacksRef.current.onProgress(progress, bytesUploaded, totalBytes);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
onChunkComplete: (
|
|
105
|
-
chunkSize: number,
|
|
106
|
-
bytesAccepted: number,
|
|
107
|
-
bytesTotal: number | null,
|
|
108
|
-
) => {
|
|
109
|
-
callbacksRef.current.onChunkComplete?.(
|
|
110
|
-
chunkSize,
|
|
111
|
-
bytesAccepted,
|
|
112
|
-
bytesTotal,
|
|
113
|
-
);
|
|
114
|
-
},
|
|
115
|
-
onFlowComplete: (outputs: TypedOutput[]) => {
|
|
116
|
-
callbacksRef.current.onFlowComplete?.(outputs);
|
|
117
|
-
},
|
|
118
|
-
onSuccess: (outputs: TypedOutput[]) => {
|
|
119
|
-
callbacksRef.current.onSuccess?.(outputs);
|
|
120
|
-
},
|
|
121
|
-
onError: (error: Error) => {
|
|
122
|
-
callbacksRef.current.onError?.(error);
|
|
123
|
-
},
|
|
124
|
-
onAbort: () => {
|
|
125
|
-
// onAbort is not exposed in the public API
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// Get manager from context (creates if doesn't exist, increments ref count)
|
|
130
|
-
managerRef.current = getManager(flowId, stableCallbacks, {
|
|
131
|
-
flowConfig: {
|
|
132
|
-
flowId: options.flowId,
|
|
133
|
-
storageId: options.storageId,
|
|
134
|
-
outputNodeId: options.outputNodeId,
|
|
135
|
-
metadata: options.metadata as Record<string, string> | undefined,
|
|
136
|
-
},
|
|
137
|
-
onChunkComplete: options.onChunkComplete,
|
|
138
|
-
onSuccess: options.onSuccess,
|
|
139
|
-
onError: options.onError,
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// Release manager when component unmounts or flowId changes
|
|
143
|
-
return () => {
|
|
144
|
-
releaseManager(flowId);
|
|
145
|
-
managerRef.current = null;
|
|
146
|
-
};
|
|
147
|
-
}, [
|
|
148
|
-
options.flowId,
|
|
149
|
-
options.storageId,
|
|
150
|
-
options.outputNodeId,
|
|
151
|
-
getManager,
|
|
152
|
-
releaseManager,
|
|
153
|
-
]);
|
|
154
|
-
|
|
155
|
-
const upload = useCallback(
|
|
156
|
-
async (file: FilePickResult) => {
|
|
157
|
-
// Handle cancelled picker
|
|
158
|
-
if (file.status === "cancelled") {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Handle picker error
|
|
163
|
-
if (file.status === "error") {
|
|
164
|
-
options.onError?.(file.error);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
lastFileRef.current = file;
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
// Read file content
|
|
172
|
-
const fileContent = await fileSystemProvider.readFile(file.data.uri);
|
|
173
|
-
|
|
174
|
-
// Create a Blob from the file content using platform-aware utility
|
|
175
|
-
// Handles differences between React Native and browser Blob APIs
|
|
176
|
-
const blob = createBlobFromBuffer(fileContent, {
|
|
177
|
-
type: file.data.mimeType || "application/octet-stream",
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// Start the upload using the manager
|
|
181
|
-
await managerRef.current?.upload(blob);
|
|
182
|
-
} catch (error) {
|
|
183
|
-
options.onError?.(error as Error);
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
[fileSystemProvider, options],
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
const reset = useCallback(() => {
|
|
190
|
-
managerRef.current?.reset();
|
|
191
|
-
lastFileRef.current = null;
|
|
192
|
-
}, []);
|
|
193
|
-
|
|
194
|
-
const abort = useCallback(() => {
|
|
195
|
-
managerRef.current?.abort();
|
|
196
|
-
}, []);
|
|
197
|
-
|
|
198
|
-
const retry = useCallback(() => {
|
|
199
|
-
if (
|
|
200
|
-
lastFileRef.current &&
|
|
201
|
-
(state.status === "error" || state.status === "aborted")
|
|
202
|
-
) {
|
|
203
|
-
upload(lastFileRef.current);
|
|
204
|
-
}
|
|
205
|
-
}, [upload, state.status]);
|
|
206
|
-
|
|
207
|
-
// Derive computed values from state (reactive to state changes)
|
|
208
|
-
const isActive =
|
|
209
|
-
state.status === "uploading" || state.status === "processing";
|
|
210
|
-
const canRetry =
|
|
211
|
-
(state.status === "error" || state.status === "aborted") &&
|
|
212
|
-
lastFileRef.current !== null;
|
|
213
|
-
|
|
214
|
-
return {
|
|
215
|
-
state,
|
|
216
|
-
upload,
|
|
217
|
-
abort,
|
|
218
|
-
reset,
|
|
219
|
-
retry,
|
|
220
|
-
isActive,
|
|
221
|
-
canRetry,
|
|
222
|
-
};
|
|
223
|
-
}
|