@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,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission utility functions for React Native uploads
|
|
3
|
+
* Handles camera, gallery, and file access permissions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Permission types
|
|
8
|
+
*/
|
|
9
|
+
export enum PermissionType {
|
|
10
|
+
CAMERA = "CAMERA",
|
|
11
|
+
PHOTO_LIBRARY = "PHOTO_LIBRARY",
|
|
12
|
+
WRITE_STORAGE = "WRITE_STORAGE",
|
|
13
|
+
READ_STORAGE = "READ_STORAGE",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Permission status
|
|
18
|
+
*/
|
|
19
|
+
export enum PermissionStatus {
|
|
20
|
+
GRANTED = "granted",
|
|
21
|
+
DENIED = "denied",
|
|
22
|
+
NOT_DETERMINED = "not_determined",
|
|
23
|
+
RESTRICTED = "restricted",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Request camera permission
|
|
28
|
+
* This is primarily used to check if we should attempt camera operations
|
|
29
|
+
* Actual permission requests are handled by the file system providers
|
|
30
|
+
*
|
|
31
|
+
* @returns Promise resolving to true if permission is granted or already granted
|
|
32
|
+
*/
|
|
33
|
+
export async function requestCameraPermission(): Promise<boolean> {
|
|
34
|
+
try {
|
|
35
|
+
// Permission requests are handled by the file system provider implementations
|
|
36
|
+
// This function serves as a placeholder for app-level permission handling
|
|
37
|
+
console.log(
|
|
38
|
+
"Camera permission requested (handled by file system provider)",
|
|
39
|
+
);
|
|
40
|
+
return true;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error("Failed to request camera permission:", error);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Request photo library permission
|
|
49
|
+
* @returns Promise resolving to true if permission is granted
|
|
50
|
+
*/
|
|
51
|
+
export async function requestPhotoLibraryPermission(): Promise<boolean> {
|
|
52
|
+
try {
|
|
53
|
+
console.log(
|
|
54
|
+
"Photo library permission requested (handled by file system provider)",
|
|
55
|
+
);
|
|
56
|
+
return true;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("Failed to request photo library permission:", error);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Request storage read permission
|
|
65
|
+
* @returns Promise resolving to true if permission is granted
|
|
66
|
+
*/
|
|
67
|
+
export async function requestStorageReadPermission(): Promise<boolean> {
|
|
68
|
+
try {
|
|
69
|
+
console.log(
|
|
70
|
+
"Storage read permission requested (handled by file system provider)",
|
|
71
|
+
);
|
|
72
|
+
return true;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.error("Failed to request storage read permission:", error);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Request storage write permission
|
|
81
|
+
* @returns Promise resolving to true if permission is granted
|
|
82
|
+
*/
|
|
83
|
+
export async function requestStorageWritePermission(): Promise<boolean> {
|
|
84
|
+
try {
|
|
85
|
+
console.log(
|
|
86
|
+
"Storage write permission requested (handled by file system provider)",
|
|
87
|
+
);
|
|
88
|
+
return true;
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error("Failed to request storage write permission:", error);
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Request multiple permissions at once
|
|
97
|
+
* @param permissions - Array of permission types to request
|
|
98
|
+
* @returns Promise resolving to true if all permissions are granted
|
|
99
|
+
*/
|
|
100
|
+
export async function requestPermissions(
|
|
101
|
+
permissions: PermissionType[],
|
|
102
|
+
): Promise<boolean> {
|
|
103
|
+
try {
|
|
104
|
+
const results = await Promise.all(
|
|
105
|
+
permissions.map(async (permission) => {
|
|
106
|
+
switch (permission) {
|
|
107
|
+
case PermissionType.CAMERA:
|
|
108
|
+
return requestCameraPermission();
|
|
109
|
+
case PermissionType.PHOTO_LIBRARY:
|
|
110
|
+
return requestPhotoLibraryPermission();
|
|
111
|
+
case PermissionType.READ_STORAGE:
|
|
112
|
+
return requestStorageReadPermission();
|
|
113
|
+
case PermissionType.WRITE_STORAGE:
|
|
114
|
+
return requestStorageWritePermission();
|
|
115
|
+
default:
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return results.every((result) => result);
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error("Failed to request permissions:", error);
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Check if all required permissions are granted
|
|
130
|
+
* @param permissions - Array of permission types to check
|
|
131
|
+
* @returns Promise resolving to true if all permissions are granted
|
|
132
|
+
*/
|
|
133
|
+
export async function hasPermissions(
|
|
134
|
+
_permissions: PermissionType[],
|
|
135
|
+
): Promise<boolean> {
|
|
136
|
+
try {
|
|
137
|
+
// In React Native, permission checking is typically handled by the platform
|
|
138
|
+
// This is a placeholder that assumes permissions will be handled by the file system provider
|
|
139
|
+
return true;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error("Failed to check permissions:", error);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get permission status
|
|
148
|
+
* @param permission - Permission type to check
|
|
149
|
+
* @returns Promise resolving to permission status
|
|
150
|
+
*/
|
|
151
|
+
export async function getPermissionStatus(
|
|
152
|
+
_permission: PermissionType,
|
|
153
|
+
): Promise<PermissionStatus> {
|
|
154
|
+
try {
|
|
155
|
+
// This is a placeholder implementation
|
|
156
|
+
// Real implementation would use platform-specific APIs
|
|
157
|
+
return PermissionStatus.GRANTED;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error("Failed to get permission status:", error);
|
|
160
|
+
return PermissionStatus.DENIED;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Open app settings to request permissions
|
|
166
|
+
* Guides user to app settings where they can manually enable permissions
|
|
167
|
+
*/
|
|
168
|
+
export function openAppSettings(): void {
|
|
169
|
+
try {
|
|
170
|
+
// This would typically use react-native-app-settings or similar
|
|
171
|
+
console.log(
|
|
172
|
+
"Opening app settings (requires react-native-app-settings or platform implementation)",
|
|
173
|
+
);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error("Failed to open app settings:", error);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URI utility functions for React Native file handling
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Extract file name from URI
|
|
7
|
+
* @param uri - File URI
|
|
8
|
+
* @returns File name extracted from URI
|
|
9
|
+
*/
|
|
10
|
+
export function getFileNameFromUri(uri: string): string {
|
|
11
|
+
try {
|
|
12
|
+
// Handle different URI formats
|
|
13
|
+
if (uri.startsWith("file://")) {
|
|
14
|
+
// File URI format
|
|
15
|
+
const path = uri.replace("file://", "");
|
|
16
|
+
return path.split("/").pop() || "file";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (uri.startsWith("content://")) {
|
|
20
|
+
// Content URI format (Android)
|
|
21
|
+
const parts = uri.split("/");
|
|
22
|
+
return parts[parts.length - 1] || "file";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Assume it's a path or other format
|
|
26
|
+
const parts = uri.split("/");
|
|
27
|
+
return parts[parts.length - 1] || "file";
|
|
28
|
+
} catch {
|
|
29
|
+
return "file";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Convert file path to file URI
|
|
35
|
+
* @param filePath - File path
|
|
36
|
+
* @returns File URI
|
|
37
|
+
*/
|
|
38
|
+
export function pathToUri(filePath: string): string {
|
|
39
|
+
if (filePath.startsWith("file://")) {
|
|
40
|
+
return filePath;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (filePath.startsWith("content://")) {
|
|
44
|
+
return filePath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Convert to file URI
|
|
48
|
+
return `file://${filePath}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Convert file URI to file path
|
|
53
|
+
* @param uri - File URI
|
|
54
|
+
* @returns File path
|
|
55
|
+
*/
|
|
56
|
+
export function uriToPath(uri: string): string {
|
|
57
|
+
if (uri.startsWith("file://")) {
|
|
58
|
+
return uri.replace("file://", "");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (uri.startsWith("content://")) {
|
|
62
|
+
// Content URIs cannot be converted to paths directly
|
|
63
|
+
return uri;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return uri;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get directory from URI
|
|
71
|
+
* @param uri - File URI
|
|
72
|
+
* @returns Directory path
|
|
73
|
+
*/
|
|
74
|
+
export function getDirectoryFromUri(uri: string): string {
|
|
75
|
+
try {
|
|
76
|
+
const path = uriToPath(uri);
|
|
77
|
+
const parts = path.split("/");
|
|
78
|
+
parts.pop(); // Remove file name
|
|
79
|
+
return parts.join("/");
|
|
80
|
+
} catch {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if URI is a content URI (Android specific)
|
|
87
|
+
* @param uri - URI to check
|
|
88
|
+
* @returns True if URI is a content URI
|
|
89
|
+
*/
|
|
90
|
+
export function isContentUri(uri: string): boolean {
|
|
91
|
+
return uri.startsWith("content://");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Check if URI is a file URI
|
|
96
|
+
* @param uri - URI to check
|
|
97
|
+
* @returns True if URI is a file URI
|
|
98
|
+
*/
|
|
99
|
+
export function isFileUri(uri: string): boolean {
|
|
100
|
+
return uri.startsWith("file://");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Normalize URI for cross-platform compatibility
|
|
105
|
+
* @param uri - URI to normalize
|
|
106
|
+
* @returns Normalized URI
|
|
107
|
+
*/
|
|
108
|
+
export function normalizeUri(uri: string): string {
|
|
109
|
+
// Remove duplicate slashes (but keep protocol slashes)
|
|
110
|
+
return uri.replace(/([^:]\/)\/+/g, "$1");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get MIME type hint from URI
|
|
115
|
+
* @param uri - File URI
|
|
116
|
+
* @returns MIME type hint based on file extension
|
|
117
|
+
*/
|
|
118
|
+
export function getMimeTypeFromUri(uri: string): string {
|
|
119
|
+
const fileName = getFileNameFromUri(uri);
|
|
120
|
+
|
|
121
|
+
const mimeTypes: Record<string, string> = {
|
|
122
|
+
// Images
|
|
123
|
+
".jpg": "image/jpeg",
|
|
124
|
+
".jpeg": "image/jpeg",
|
|
125
|
+
".png": "image/png",
|
|
126
|
+
".gif": "image/gif",
|
|
127
|
+
".bmp": "image/bmp",
|
|
128
|
+
".webp": "image/webp",
|
|
129
|
+
|
|
130
|
+
// Videos
|
|
131
|
+
".mp4": "video/mp4",
|
|
132
|
+
".mov": "video/quicktime",
|
|
133
|
+
".avi": "video/x-msvideo",
|
|
134
|
+
|
|
135
|
+
// Audio
|
|
136
|
+
".mp3": "audio/mpeg",
|
|
137
|
+
".wav": "audio/wav",
|
|
138
|
+
".aac": "audio/aac",
|
|
139
|
+
|
|
140
|
+
// Documents
|
|
141
|
+
".pdf": "application/pdf",
|
|
142
|
+
".txt": "text/plain",
|
|
143
|
+
".json": "application/json",
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const ext = fileName.toLowerCase().slice(fileName.lastIndexOf("."));
|
|
147
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
148
|
+
}
|
package/test-compile.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@uploadista/typescript-config/react-library.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": "./",
|
|
5
|
+
"paths": {
|
|
6
|
+
"@/*": ["./src/*"]
|
|
7
|
+
},
|
|
8
|
+
"typeRoots": ["../../node_modules/@types"],
|
|
9
|
+
"types": [],
|
|
10
|
+
"target": "ES2020",
|
|
11
|
+
"lib": ["ES2020", "ES2015.Promise", "ES2015.Iterable", "ES2015.Symbol"],
|
|
12
|
+
"jsx": "react-jsx",
|
|
13
|
+
"module": "ESNext",
|
|
14
|
+
"moduleResolution": "bundler",
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"noUnusedLocals": false,
|
|
17
|
+
"noUnusedParameters": false
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist"]
|
|
21
|
+
}
|