motorinc-gallery-picker-pro 1.0.0
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/README.md +236 -0
- package/android/build.gradle +22 -0
- package/android/src/main/AndroidManifest.xml +10 -0
- package/android/src/main/java/com/gallerypicker/imagepicker/ImagePickerModule.java +1968 -0
- package/android/src/main/java/com/gallerypicker/imagepicker/ImagePickerPackage.java +24 -0
- package/index.d.ts +129 -0
- package/index.js +18 -0
- package/ios/ImagePickerModule.h +8 -0
- package/ios/ImagePickerModule.m +876 -0
- package/motorinc-gallery-picker-pro.podspec +21 -0
- package/package.json +63 -0
- package/react-native.config.js +13 -0
- package/src/components/ImageCropper.tsx +433 -0
- package/src/components/MainPhotoGallery.tsx +2639 -0
- package/src/components/PhotoAssetImage.tsx +121 -0
- package/src/modules/ImagePickerModule.ts +117 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, {useState, useEffect} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Image,
|
|
4
|
+
ImageProps,
|
|
5
|
+
ActivityIndicator,
|
|
6
|
+
View,
|
|
7
|
+
StyleSheet,
|
|
8
|
+
Dimensions,
|
|
9
|
+
} from 'react-native';
|
|
10
|
+
import ImagePickerModule from '../modules/ImagePickerModule';
|
|
11
|
+
const {width: screenWidth} = Dimensions.get('window');
|
|
12
|
+
|
|
13
|
+
interface PhotoAssetImageProps extends Omit<ImageProps, 'source'> {
|
|
14
|
+
uri: string;
|
|
15
|
+
width?: number;
|
|
16
|
+
height?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const PhotoAssetImage: React.FC<PhotoAssetImageProps> = ({
|
|
20
|
+
uri,
|
|
21
|
+
width = screenWidth,
|
|
22
|
+
height = screenWidth,
|
|
23
|
+
style,
|
|
24
|
+
...props
|
|
25
|
+
}) => {
|
|
26
|
+
const [imageUri, setImageUri] = useState<string | null>(null);
|
|
27
|
+
const [loading, setLoading] = useState(true);
|
|
28
|
+
const [error, setError] = useState(false);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const loadImage = async () => {
|
|
32
|
+
if (uri.startsWith('ph://')) {
|
|
33
|
+
// iOS placeholder URI - need to get actual image
|
|
34
|
+
const assetId = uri.replace('ph://', '');
|
|
35
|
+
try {
|
|
36
|
+
setLoading(true);
|
|
37
|
+
const actualUri = await ImagePickerModule.getImageForAsset(
|
|
38
|
+
assetId,
|
|
39
|
+
width,
|
|
40
|
+
height,
|
|
41
|
+
);
|
|
42
|
+
setImageUri(actualUri);
|
|
43
|
+
setError(false);
|
|
44
|
+
} catch (err) {
|
|
45
|
+
console.error('Failed to load image for asset:', assetId, err);
|
|
46
|
+
setError(true);
|
|
47
|
+
} finally {
|
|
48
|
+
setLoading(false);
|
|
49
|
+
}
|
|
50
|
+
} else if (uri.startsWith('android://')) {
|
|
51
|
+
// Android placeholder URI - need to get actual image
|
|
52
|
+
const assetId = uri.replace('android://', '');
|
|
53
|
+
try {
|
|
54
|
+
setLoading(true);
|
|
55
|
+
const actualUri = await ImagePickerModule.getImageForAsset(
|
|
56
|
+
assetId,
|
|
57
|
+
width,
|
|
58
|
+
height,
|
|
59
|
+
);
|
|
60
|
+
setImageUri(actualUri);
|
|
61
|
+
setError(false);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error('Failed to load image for asset:', assetId, err);
|
|
64
|
+
setError(true);
|
|
65
|
+
} finally {
|
|
66
|
+
setLoading(false);
|
|
67
|
+
}
|
|
68
|
+
} else if (uri.startsWith('content://')) {
|
|
69
|
+
// Android content URI - can be used directly by React Native Image
|
|
70
|
+
setImageUri(uri);
|
|
71
|
+
setLoading(false);
|
|
72
|
+
setError(false);
|
|
73
|
+
} else {
|
|
74
|
+
// Regular file URI, use directly
|
|
75
|
+
setImageUri(uri);
|
|
76
|
+
setLoading(false);
|
|
77
|
+
setError(false);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
loadImage();
|
|
82
|
+
}, [uri, width, height]);
|
|
83
|
+
|
|
84
|
+
if (loading) {
|
|
85
|
+
return (
|
|
86
|
+
<View style={[styles.loadingContainer, style]}>
|
|
87
|
+
<ActivityIndicator size="small" color="#f4f4f4" />
|
|
88
|
+
</View>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (error || !imageUri) {
|
|
93
|
+
return (
|
|
94
|
+
<View style={[styles.errorContainer, style]}>
|
|
95
|
+
{/* Empty placeholder for failed images */}
|
|
96
|
+
</View>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Image
|
|
102
|
+
{...props}
|
|
103
|
+
source={{uri: imageUri}}
|
|
104
|
+
style={style}
|
|
105
|
+
onError={() => setError(true)}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const styles = StyleSheet.create({
|
|
111
|
+
loadingContainer: {
|
|
112
|
+
justifyContent: 'center',
|
|
113
|
+
alignItems: 'center',
|
|
114
|
+
backgroundColor: '#000',
|
|
115
|
+
},
|
|
116
|
+
errorContainer: {
|
|
117
|
+
backgroundColor: '#000',
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export default PhotoAssetImage;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const LINKING_ERROR =
|
|
4
|
+
'The package \'ImagePickerModule\' doesn\'t seem to be linked. Make sure: \n\n' +
|
|
5
|
+
Platform.select({ ios: "- You have run 'cd ios && pod install'\n", default: '' }) +
|
|
6
|
+
'- You rebuilt the app after installing the package\n' +
|
|
7
|
+
'- You are not using Expo Go\n';
|
|
8
|
+
|
|
9
|
+
interface ImagePickerModuleInterface {
|
|
10
|
+
openCamera(options: ImagePickerOptions): Promise<ImagePickerResult>;
|
|
11
|
+
openGallery(options: ImagePickerOptions): Promise<ImagePickerResult>;
|
|
12
|
+
requestCameraPermission(): Promise<boolean>;
|
|
13
|
+
requestGalleryPermission(): Promise<boolean>;
|
|
14
|
+
getPhotoLibraryPermissionStatus(): Promise<PermissionStatus>;
|
|
15
|
+
fetchPhotoLibraryAssets(options: GalleryFetchOptions): Promise<GalleryResult>;
|
|
16
|
+
getImageForAsset(assetId: string, targetWidth?: number, targetHeight?: number): Promise<string>;
|
|
17
|
+
openPhotoLibraryLimitedPicker(): Promise<boolean>;
|
|
18
|
+
openPhotoLibraryLimitedSettings(): Promise<boolean>;
|
|
19
|
+
setLimitedAccessMode(limited: boolean): Promise<boolean>;
|
|
20
|
+
managePhotoSelection(): Promise<boolean>;
|
|
21
|
+
openMultiSelectGallery(options: MultiSelectOptions): Promise<MultiSelectResult>;
|
|
22
|
+
debugPermissionsAndMediaStore(): Promise<any>;
|
|
23
|
+
testVideoQuery(): Promise<any>;
|
|
24
|
+
simpleVideoTest(): Promise<any>;
|
|
25
|
+
testSystemVideoPicker(): Promise<any>;
|
|
26
|
+
getVideoBase64(videoUri: string): Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface MultiSelectOptions {
|
|
30
|
+
maxSelectionLimit?: number;
|
|
31
|
+
quality?: number;
|
|
32
|
+
maxWidth?: number;
|
|
33
|
+
maxHeight?: number;
|
|
34
|
+
includeBase64?: boolean;
|
|
35
|
+
mediaType?: MediaType;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ImagePickerOptions {
|
|
39
|
+
quality?: number;
|
|
40
|
+
maxWidth?: number;
|
|
41
|
+
maxHeight?: number;
|
|
42
|
+
allowsEditing?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ImagePickerResult {
|
|
46
|
+
success: boolean;
|
|
47
|
+
uri?: string;
|
|
48
|
+
fileName?: string;
|
|
49
|
+
fileSize?: number;
|
|
50
|
+
width?: number;
|
|
51
|
+
height?: number;
|
|
52
|
+
type?: string;
|
|
53
|
+
error?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type PermissionStatus =
|
|
57
|
+
| 'authorized'
|
|
58
|
+
| 'limited'
|
|
59
|
+
| 'denied'
|
|
60
|
+
| 'restricted'
|
|
61
|
+
| 'not_determined';
|
|
62
|
+
|
|
63
|
+
export type MediaType = 'photo' | 'video' | 'mixed';
|
|
64
|
+
|
|
65
|
+
export interface GalleryFetchOptions {
|
|
66
|
+
limit?: number;
|
|
67
|
+
offset?: number;
|
|
68
|
+
mediaType?: MediaType;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface PhotoAsset {
|
|
72
|
+
uri: string;
|
|
73
|
+
id: string;
|
|
74
|
+
filename?: string;
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
creationDate: number;
|
|
78
|
+
mediaType?: 'image' | 'video';
|
|
79
|
+
duration?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface GalleryResult {
|
|
83
|
+
assets: PhotoAsset[];
|
|
84
|
+
hasMore: boolean;
|
|
85
|
+
totalCount: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface SelectedImage {
|
|
89
|
+
uri: string;
|
|
90
|
+
fileName: string;
|
|
91
|
+
fileSize: number;
|
|
92
|
+
width: number;
|
|
93
|
+
height: number;
|
|
94
|
+
type: string;
|
|
95
|
+
id: string;
|
|
96
|
+
base64?: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface MultiSelectResult {
|
|
100
|
+
success: boolean;
|
|
101
|
+
images?: SelectedImage[];
|
|
102
|
+
count?: number;
|
|
103
|
+
error?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const ImagePickerModule = NativeModules.ImagePickerModule
|
|
107
|
+
? NativeModules.ImagePickerModule
|
|
108
|
+
: new Proxy(
|
|
109
|
+
{},
|
|
110
|
+
{
|
|
111
|
+
get() {
|
|
112
|
+
throw new Error(LINKING_ERROR);
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
) as ImagePickerModuleInterface;
|
|
116
|
+
|
|
117
|
+
export default ImagePickerModule;
|