@uploadista/react-native-core 0.0.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/.turbo/turbo-check.log +396 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/package.json +42 -0
- package/src/client/create-uploadista-client.ts +65 -0
- package/src/client/index.ts +4 -0
- package/src/components/CameraUploadButton.tsx +130 -0
- package/src/components/FileUploadButton.tsx +130 -0
- package/src/components/GalleryUploadButton.tsx +199 -0
- package/src/components/UploadList.tsx +214 -0
- package/src/components/UploadProgress.tsx +196 -0
- package/src/components/index.ts +19 -0
- package/src/hooks/index.ts +29 -0
- package/src/hooks/uploadista-context.ts +17 -0
- package/src/hooks/use-camera-upload.ts +38 -0
- package/src/hooks/use-file-upload.ts +40 -0
- package/src/hooks/use-flow-upload.ts +242 -0
- package/src/hooks/use-gallery-upload.ts +65 -0
- package/src/hooks/use-multi-upload.ts +363 -0
- package/src/hooks/use-upload-metrics.ts +82 -0
- package/src/hooks/use-upload.ts +378 -0
- package/src/hooks/use-uploadista-client.ts +23 -0
- package/src/hooks/use-uploadista-context.ts +20 -0
- package/src/index.ts +111 -0
- package/src/types/index.ts +2 -0
- package/src/types/types.ts +359 -0
- package/src/types/upload-input.ts +1 -0
- package/src/utils/fileHelpers.ts +201 -0
- package/src/utils/index.ts +36 -0
- package/src/utils/permissions.ts +177 -0
- package/src/utils/uriHelpers.ts +148 -0
- package/test-compile.ts +5 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import type { UploadistaEvent } from "@uploadista/client-core";
|
|
2
|
+
import type { UploadFile } from "@uploadista/core/types";
|
|
3
|
+
import { UploadEventType } from "@uploadista/core/types";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import type { FilePickResult } from "../types";
|
|
6
|
+
import { useUploadistaContext } from "./use-uploadista-context";
|
|
7
|
+
|
|
8
|
+
export type UploadStatus =
|
|
9
|
+
| "idle"
|
|
10
|
+
| "uploading"
|
|
11
|
+
| "success"
|
|
12
|
+
| "error"
|
|
13
|
+
| "aborted";
|
|
14
|
+
|
|
15
|
+
export interface UploadState {
|
|
16
|
+
status: UploadStatus;
|
|
17
|
+
progress: number;
|
|
18
|
+
bytesUploaded: number;
|
|
19
|
+
totalBytes: number | null;
|
|
20
|
+
error: Error | null;
|
|
21
|
+
result: UploadFile | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface UseUploadOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Upload metadata to attach to the file
|
|
27
|
+
*/
|
|
28
|
+
metadata?: Record<string, string>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether to defer the upload size calculation
|
|
32
|
+
*/
|
|
33
|
+
uploadLengthDeferred?: boolean;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Manual upload size override
|
|
37
|
+
*/
|
|
38
|
+
uploadSize?: number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Called when upload progress updates
|
|
42
|
+
*/
|
|
43
|
+
onProgress?: (
|
|
44
|
+
progress: number,
|
|
45
|
+
bytesUploaded: number,
|
|
46
|
+
totalBytes: number | null,
|
|
47
|
+
) => void;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Called when a chunk completes
|
|
51
|
+
*/
|
|
52
|
+
onChunkComplete?: (
|
|
53
|
+
chunkSize: number,
|
|
54
|
+
bytesAccepted: number,
|
|
55
|
+
bytesTotal: number | null,
|
|
56
|
+
) => void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Called when upload succeeds
|
|
60
|
+
*/
|
|
61
|
+
onSuccess?: (result: UploadFile) => void;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Called when upload fails
|
|
65
|
+
*/
|
|
66
|
+
onError?: (error: Error) => void;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Called when upload is aborted
|
|
70
|
+
*/
|
|
71
|
+
onAbort?: () => void;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Custom retry logic
|
|
75
|
+
*/
|
|
76
|
+
onShouldRetry?: (error: Error, retryAttempt: number) => boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface UseUploadReturn {
|
|
80
|
+
/**
|
|
81
|
+
* Current upload state
|
|
82
|
+
*/
|
|
83
|
+
state: UploadState;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Start uploading a file from a file pick result
|
|
87
|
+
*/
|
|
88
|
+
upload: (file: FilePickResult) => Promise<void>;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Abort the current upload
|
|
92
|
+
*/
|
|
93
|
+
abort: () => void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Reset the upload state to idle
|
|
97
|
+
*/
|
|
98
|
+
reset: () => void;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Retry the last failed upload
|
|
102
|
+
*/
|
|
103
|
+
retry: () => void;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Whether an upload is currently active
|
|
107
|
+
*/
|
|
108
|
+
isUploading: boolean;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether the upload can be retried
|
|
112
|
+
*/
|
|
113
|
+
canRetry: boolean;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const initialState: UploadState = {
|
|
117
|
+
status: "idle",
|
|
118
|
+
progress: 0,
|
|
119
|
+
bytesUploaded: 0,
|
|
120
|
+
totalBytes: null,
|
|
121
|
+
error: null,
|
|
122
|
+
result: null,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* React hook for managing individual file uploads with full state management.
|
|
127
|
+
* Provides upload progress tracking, error handling, abort functionality, and retry logic.
|
|
128
|
+
*
|
|
129
|
+
* Must be used within an UploadistaProvider.
|
|
130
|
+
*
|
|
131
|
+
* @param options - Upload configuration and event handlers
|
|
132
|
+
* @returns Upload state and control methods
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```tsx
|
|
136
|
+
* function MyComponent() {
|
|
137
|
+
* const upload = useUpload({
|
|
138
|
+
* onSuccess: (result) => console.log('Upload complete:', result),
|
|
139
|
+
* onError: (error) => console.error('Upload failed:', error),
|
|
140
|
+
* onProgress: (progress) => console.log('Progress:', progress + '%'),
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* const handlePickFile = async () => {
|
|
144
|
+
* const file = await fileSystemProvider.pickDocument();
|
|
145
|
+
* if (file) {
|
|
146
|
+
* await upload.upload(file);
|
|
147
|
+
* }
|
|
148
|
+
* };
|
|
149
|
+
*
|
|
150
|
+
* return (
|
|
151
|
+
* <View>
|
|
152
|
+
* <Button title="Pick File" onPress={handlePickFile} />
|
|
153
|
+
* {upload.isUploading && <Text>Progress: {upload.state.progress}%</Text>}
|
|
154
|
+
* {upload.state.error && <Text>Error: {upload.state.error.message}</Text>}
|
|
155
|
+
* {upload.canRetry && <Button title="Retry" onPress={upload.retry} />}
|
|
156
|
+
* <Button title="Abort" onPress={upload.abort} disabled={!upload.isUploading} />
|
|
157
|
+
* </View>
|
|
158
|
+
* );
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export function useUpload(options: UseUploadOptions = {}): UseUploadReturn {
|
|
163
|
+
const { client, fileSystemProvider, subscribeToEvents } =
|
|
164
|
+
useUploadistaContext();
|
|
165
|
+
const [state, setState] = useState<UploadState>(initialState);
|
|
166
|
+
const abortControllerRef = useRef<{ abort: () => void } | null>(null);
|
|
167
|
+
const lastFileRef = useRef<FilePickResult | null>(null);
|
|
168
|
+
const currentUploadIdRef = useRef<string | null>(null);
|
|
169
|
+
|
|
170
|
+
const updateState = useCallback((update: Partial<UploadState>) => {
|
|
171
|
+
setState((prev) => ({ ...prev, ...update }));
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
const reset = useCallback(() => {
|
|
175
|
+
if (abortControllerRef.current) {
|
|
176
|
+
abortControllerRef.current.abort();
|
|
177
|
+
abortControllerRef.current = null;
|
|
178
|
+
}
|
|
179
|
+
setState(initialState);
|
|
180
|
+
lastFileRef.current = null;
|
|
181
|
+
currentUploadIdRef.current = null;
|
|
182
|
+
}, []);
|
|
183
|
+
|
|
184
|
+
const abort = useCallback(() => {
|
|
185
|
+
if (abortControllerRef.current) {
|
|
186
|
+
abortControllerRef.current.abort();
|
|
187
|
+
abortControllerRef.current = null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
updateState({
|
|
191
|
+
status: "aborted",
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
options.onAbort?.();
|
|
195
|
+
}, [options, updateState]);
|
|
196
|
+
|
|
197
|
+
const upload = useCallback(
|
|
198
|
+
async (file: FilePickResult) => {
|
|
199
|
+
// Reset any previous state
|
|
200
|
+
setState({
|
|
201
|
+
...initialState,
|
|
202
|
+
status: "uploading",
|
|
203
|
+
totalBytes: file.size,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
lastFileRef.current = file;
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
// Read file content
|
|
210
|
+
const fileContent = await fileSystemProvider.readFile(file.uri);
|
|
211
|
+
|
|
212
|
+
// Create a Blob from the file content
|
|
213
|
+
// Convert ArrayBuffer to Uint8Array for better compatibility
|
|
214
|
+
const data =
|
|
215
|
+
fileContent instanceof ArrayBuffer
|
|
216
|
+
? new Uint8Array(fileContent)
|
|
217
|
+
: fileContent;
|
|
218
|
+
// Note: Using any cast here because React Native Blob accepts BufferSource
|
|
219
|
+
// but TypeScript's lib.dom.d.ts Blob type doesn't include it
|
|
220
|
+
// biome-ignore lint/suspicious/noExplicitAny: React Native Blob accepts BufferSource
|
|
221
|
+
const blob = new Blob([data as any], {
|
|
222
|
+
type: file.mimeType || "application/octet-stream",
|
|
223
|
+
// biome-ignore lint/suspicious/noExplicitAny: BlobPropertyBag type differs by platform
|
|
224
|
+
} as any);
|
|
225
|
+
|
|
226
|
+
// use the Blob (for React Native)
|
|
227
|
+
const uploadInput = blob;
|
|
228
|
+
|
|
229
|
+
// Start the upload using the client
|
|
230
|
+
const uploadPromise = client.upload(uploadInput, {
|
|
231
|
+
metadata: options.metadata,
|
|
232
|
+
uploadLengthDeferred: options.uploadLengthDeferred,
|
|
233
|
+
uploadSize: options.uploadSize,
|
|
234
|
+
|
|
235
|
+
onStart: ({ uploadId }) => {
|
|
236
|
+
currentUploadIdRef.current = uploadId;
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
onProgress: (
|
|
240
|
+
_uploadId: string,
|
|
241
|
+
bytesUploaded: number,
|
|
242
|
+
totalBytes: number | null,
|
|
243
|
+
) => {
|
|
244
|
+
const progress = totalBytes
|
|
245
|
+
? Math.round((bytesUploaded / totalBytes) * 100)
|
|
246
|
+
: 0;
|
|
247
|
+
|
|
248
|
+
updateState({
|
|
249
|
+
progress,
|
|
250
|
+
bytesUploaded,
|
|
251
|
+
totalBytes,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
options.onProgress?.(progress, bytesUploaded, totalBytes);
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
onChunkComplete: (
|
|
258
|
+
chunkSize: number,
|
|
259
|
+
bytesAccepted: number,
|
|
260
|
+
bytesTotal: number | null,
|
|
261
|
+
) => {
|
|
262
|
+
options.onChunkComplete?.(chunkSize, bytesAccepted, bytesTotal);
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
onSuccess: (result: UploadFile) => {
|
|
266
|
+
updateState({
|
|
267
|
+
status: "success",
|
|
268
|
+
result,
|
|
269
|
+
progress: 100,
|
|
270
|
+
bytesUploaded: result.size || 0,
|
|
271
|
+
totalBytes: result.size || null,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
options.onSuccess?.(result);
|
|
275
|
+
abortControllerRef.current = null;
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
onError: (error: Error) => {
|
|
279
|
+
updateState({
|
|
280
|
+
status: "error",
|
|
281
|
+
error,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
options.onError?.(error);
|
|
285
|
+
abortControllerRef.current = null;
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
onShouldRetry: options.onShouldRetry,
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Handle the promise to get the abort controller
|
|
292
|
+
const controller = await uploadPromise;
|
|
293
|
+
abortControllerRef.current = controller;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
updateState({
|
|
296
|
+
status: "error",
|
|
297
|
+
error: error as Error,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
options.onError?.(error as Error);
|
|
301
|
+
abortControllerRef.current = null;
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
[client, fileSystemProvider, options, updateState],
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const retry = useCallback(() => {
|
|
308
|
+
if (
|
|
309
|
+
lastFileRef.current &&
|
|
310
|
+
(state.status === "error" || state.status === "aborted")
|
|
311
|
+
) {
|
|
312
|
+
upload(lastFileRef.current);
|
|
313
|
+
}
|
|
314
|
+
}, [upload, state.status]);
|
|
315
|
+
|
|
316
|
+
// Subscribe to events from context (WebSocket events)
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
const unsubscribe = subscribeToEvents((event: UploadistaEvent) => {
|
|
319
|
+
// Handle upload progress events
|
|
320
|
+
const uploadEvent = event as {
|
|
321
|
+
type: string;
|
|
322
|
+
data?: { id: string; progress: number; total: number };
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
uploadEvent.type === UploadEventType.UPLOAD_PROGRESS &&
|
|
327
|
+
uploadEvent.data
|
|
328
|
+
) {
|
|
329
|
+
const {
|
|
330
|
+
id: uploadId,
|
|
331
|
+
progress: bytesUploaded,
|
|
332
|
+
total: totalBytes,
|
|
333
|
+
} = uploadEvent.data;
|
|
334
|
+
|
|
335
|
+
if (uploadId !== currentUploadIdRef.current) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Update state for this upload
|
|
340
|
+
const progress = totalBytes
|
|
341
|
+
? Math.round((bytesUploaded / totalBytes) * 100)
|
|
342
|
+
: 0;
|
|
343
|
+
|
|
344
|
+
setState((prev) => {
|
|
345
|
+
// Only update if we're currently uploading
|
|
346
|
+
if (prev.status === "uploading") {
|
|
347
|
+
return {
|
|
348
|
+
...prev,
|
|
349
|
+
progress,
|
|
350
|
+
bytesUploaded,
|
|
351
|
+
totalBytes,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
return prev;
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
options.onProgress?.(progress, bytesUploaded, totalBytes);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return unsubscribe;
|
|
362
|
+
}, [subscribeToEvents, options]);
|
|
363
|
+
|
|
364
|
+
const isUploading = state.status === "uploading";
|
|
365
|
+
const canRetry =
|
|
366
|
+
(state.status === "error" || state.status === "aborted") &&
|
|
367
|
+
lastFileRef.current !== null;
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
state,
|
|
371
|
+
upload,
|
|
372
|
+
abort,
|
|
373
|
+
reset,
|
|
374
|
+
retry,
|
|
375
|
+
isUploading,
|
|
376
|
+
canRetry,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
createUploadistaClient,
|
|
3
|
+
UploadistaClientOptions,
|
|
4
|
+
} from "../client";
|
|
5
|
+
|
|
6
|
+
export interface UseUploadistaClientOptions extends UploadistaClientOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Global event handler for all upload and flow events from this client
|
|
9
|
+
*/
|
|
10
|
+
onEvent?: UploadistaClientOptions["onEvent"];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface UseUploadistaClientReturn {
|
|
14
|
+
/**
|
|
15
|
+
* The uploadista client instance
|
|
16
|
+
*/
|
|
17
|
+
client: ReturnType<typeof createUploadistaClient>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Current configuration of the client
|
|
21
|
+
*/
|
|
22
|
+
config: UseUploadistaClientOptions;
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { UploadistaContext } from "./uploadista-context";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook to access the Uploadista client instance
|
|
6
|
+
* Must be used within an UploadistaProvider
|
|
7
|
+
* @throws Error if used outside of UploadistaProvider
|
|
8
|
+
* @returns The Uploadista client and file system provider
|
|
9
|
+
*/
|
|
10
|
+
export function useUploadistaContext() {
|
|
11
|
+
const context = useContext(UploadistaContext);
|
|
12
|
+
|
|
13
|
+
if (!context) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"useUploadistaClient must be used within an UploadistaProvider",
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return context;
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @uploadista/react-native - React Native client for Uploadista
|
|
3
|
+
* Provides mobile-optimized hooks and components for file uploads and flow management
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createUploadistaClient } from '@uploadista/react-native'
|
|
8
|
+
*
|
|
9
|
+
* const client = createUploadistaClient({
|
|
10
|
+
* baseUrl: 'https://api.example.com',
|
|
11
|
+
* storageId: 'my-storage',
|
|
12
|
+
* chunkSize: 1024 * 1024, // 1MB
|
|
13
|
+
* })
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Re-export core types from upload-client-core
|
|
18
|
+
export type {
|
|
19
|
+
Base64Service,
|
|
20
|
+
ConnectionMetrics,
|
|
21
|
+
ConnectionPoolConfig,
|
|
22
|
+
DetailedConnectionMetrics,
|
|
23
|
+
FileReaderService,
|
|
24
|
+
HttpClient,
|
|
25
|
+
IdGenerationService,
|
|
26
|
+
ServiceContainer,
|
|
27
|
+
StorageService,
|
|
28
|
+
} from "@uploadista/client-core";
|
|
29
|
+
|
|
30
|
+
// Export components
|
|
31
|
+
export {
|
|
32
|
+
CameraUploadButton,
|
|
33
|
+
type CameraUploadButtonProps,
|
|
34
|
+
FileUploadButton,
|
|
35
|
+
type FileUploadButtonProps,
|
|
36
|
+
GalleryUploadButton,
|
|
37
|
+
type GalleryUploadButtonProps,
|
|
38
|
+
UploadList,
|
|
39
|
+
type UploadListProps,
|
|
40
|
+
UploadProgress,
|
|
41
|
+
type UploadProgressProps,
|
|
42
|
+
} from "./components";
|
|
43
|
+
// Export hooks
|
|
44
|
+
export {
|
|
45
|
+
UploadistaContext,
|
|
46
|
+
type UploadistaContextType,
|
|
47
|
+
useCameraUpload,
|
|
48
|
+
useFileUpload,
|
|
49
|
+
useFlowUpload,
|
|
50
|
+
useGalleryUpload,
|
|
51
|
+
useMultiUpload,
|
|
52
|
+
useUploadistaContext,
|
|
53
|
+
useUploadMetrics,
|
|
54
|
+
} from "./hooks";
|
|
55
|
+
export type {
|
|
56
|
+
FlowUploadState,
|
|
57
|
+
FlowUploadStatus,
|
|
58
|
+
} from "./hooks/use-flow-upload";
|
|
59
|
+
export type {
|
|
60
|
+
MultiUploadState,
|
|
61
|
+
UploadItemState,
|
|
62
|
+
} from "./hooks/use-multi-upload";
|
|
63
|
+
// Export hook types
|
|
64
|
+
export type { UploadState, UploadStatus } from "./hooks/use-upload";
|
|
65
|
+
|
|
66
|
+
// Export types
|
|
67
|
+
export type {
|
|
68
|
+
CameraOptions,
|
|
69
|
+
FileInfo,
|
|
70
|
+
FilePickResult,
|
|
71
|
+
FileSystemProvider,
|
|
72
|
+
FileSystemProviderConfig,
|
|
73
|
+
PickerOptions,
|
|
74
|
+
ReactNativeUploadInput,
|
|
75
|
+
UploadMetrics,
|
|
76
|
+
UseCameraUploadOptions,
|
|
77
|
+
UseFileUploadOptions,
|
|
78
|
+
UseFlowUploadOptions,
|
|
79
|
+
UseGalleryUploadOptions,
|
|
80
|
+
UseMultiUploadOptions,
|
|
81
|
+
} from "./types";
|
|
82
|
+
// Export utilities
|
|
83
|
+
export {
|
|
84
|
+
formatFileSize,
|
|
85
|
+
getDirectoryFromUri,
|
|
86
|
+
getFileExtension,
|
|
87
|
+
getFileNameFromUri,
|
|
88
|
+
getFileNameWithoutExtension,
|
|
89
|
+
getMimeTypeFromFileName,
|
|
90
|
+
getMimeTypeFromUri,
|
|
91
|
+
getPermissionStatus,
|
|
92
|
+
hasPermissions,
|
|
93
|
+
isContentUri,
|
|
94
|
+
isDocumentFile,
|
|
95
|
+
isFileSizeValid,
|
|
96
|
+
isFileTypeAllowed,
|
|
97
|
+
isFileUri,
|
|
98
|
+
isImageFile,
|
|
99
|
+
isVideoFile,
|
|
100
|
+
normalizeUri,
|
|
101
|
+
openAppSettings,
|
|
102
|
+
PermissionStatus,
|
|
103
|
+
PermissionType,
|
|
104
|
+
pathToUri,
|
|
105
|
+
requestCameraPermission,
|
|
106
|
+
requestPermissions,
|
|
107
|
+
requestPhotoLibraryPermission,
|
|
108
|
+
requestStorageReadPermission,
|
|
109
|
+
requestStorageWritePermission,
|
|
110
|
+
uriToPath,
|
|
111
|
+
} from "./utils";
|