@teamnhz/rn-ui-toolkit 1.1.5 → 1.1.7
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.
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { ActivityIndicator } from "react-native";
|
|
3
|
+
import FastImage from "react-native-fast-image";
|
|
3
4
|
const Image = (props) => {
|
|
4
|
-
const
|
|
5
|
-
return (React.createElement(
|
|
6
|
-
React.createElement(
|
|
7
|
-
|
|
5
|
+
const [isLoading, setIsLoading] = useState(props?.isLoading || false);
|
|
6
|
+
return (React.createElement(React.Fragment, null,
|
|
7
|
+
React.createElement(FastImage, { ...props, resizeMode: props.resizeMode }, isLoading ?
|
|
8
|
+
(React.createElement(ActivityIndicator, { style: { position: "absolute", alignSelf: "center", top: 0, bottom: 0, }, size: props.loaderSize || "small", color: props.loaderColor || "#919191" }))
|
|
9
|
+
: null)));
|
|
8
10
|
};
|
|
9
|
-
const styles = StyleSheet.create({
|
|
10
|
-
container: {
|
|
11
|
-
justifyContent: "center",
|
|
12
|
-
alignItems: "center",
|
|
13
|
-
overflow: "hidden",
|
|
14
|
-
},
|
|
15
|
-
loader: {
|
|
16
|
-
position: "absolute",
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
11
|
export default Image;
|
|
@@ -5,6 +5,14 @@ type Props = {
|
|
|
5
5
|
onSuccess: (data: any) => void;
|
|
6
6
|
visible: boolean;
|
|
7
7
|
onClose: () => void;
|
|
8
|
+
enableCompression?: boolean;
|
|
9
|
+
imageCompressionOptions?: {
|
|
10
|
+
maxWidth?: number;
|
|
11
|
+
quality?: number;
|
|
12
|
+
};
|
|
13
|
+
videoCompressionOptions?: {
|
|
14
|
+
compressionMethod?: "auto" | "manual";
|
|
15
|
+
};
|
|
8
16
|
};
|
|
9
17
|
declare const ImagePicker: React.FC<Props>;
|
|
10
18
|
export default ImagePicker;
|
|
@@ -1,3 +1,162 @@
|
|
|
1
|
+
// // import React, { useCallback } from "react";
|
|
2
|
+
// // import {
|
|
3
|
+
// // View,
|
|
4
|
+
// // Text,
|
|
5
|
+
// // TouchableOpacity,
|
|
6
|
+
// // StyleSheet,
|
|
7
|
+
// // Image,
|
|
8
|
+
// // Alert,
|
|
9
|
+
// // ViewStyle,
|
|
10
|
+
// // TextStyle,
|
|
11
|
+
// // ImageStyle,
|
|
12
|
+
// // } from "react-native";
|
|
13
|
+
// // import { BottomSheet, Dividers } from "../index";
|
|
14
|
+
// // import { launchCamera, launchImageLibrary } from "react-native-image-picker";
|
|
15
|
+
// // import ImageCropPicker from "react-native-image-crop-picker";
|
|
16
|
+
// // import { Colors, Images, Scale, Typography } from "../../styles";
|
|
17
|
+
// // type StyleProps = {
|
|
18
|
+
// // containerStyle?: ViewStyle;
|
|
19
|
+
// // rowStyle?: ViewStyle;
|
|
20
|
+
// // textStyle?: TextStyle;
|
|
21
|
+
// // iconStyle?: ImageStyle;
|
|
22
|
+
// // };
|
|
23
|
+
// // type Props = {
|
|
24
|
+
// // mediaType: "photo" | "video";
|
|
25
|
+
// // isMultiSelect?: boolean;
|
|
26
|
+
// // onSuccess: (data: any) => void;
|
|
27
|
+
// // visible: boolean;
|
|
28
|
+
// // onClose: () => void;
|
|
29
|
+
// // } & StyleProps;
|
|
30
|
+
// // const ImagePicker: React.FC<Props> = ({
|
|
31
|
+
// // mediaType,
|
|
32
|
+
// // isMultiSelect = false,
|
|
33
|
+
// // onSuccess,
|
|
34
|
+
// // visible,
|
|
35
|
+
// // onClose,
|
|
36
|
+
// // containerStyle,
|
|
37
|
+
// // rowStyle,
|
|
38
|
+
// // textStyle,
|
|
39
|
+
// // iconStyle,
|
|
40
|
+
// // }) => {
|
|
41
|
+
// // const onComplete = useCallback(
|
|
42
|
+
// // (data: any) => {
|
|
43
|
+
// // onSuccess(data);
|
|
44
|
+
// // onClose();
|
|
45
|
+
// // },
|
|
46
|
+
// // [onSuccess, onClose]
|
|
47
|
+
// // );
|
|
48
|
+
// // const onCamera = () => {
|
|
49
|
+
// // if (mediaType === "photo") {
|
|
50
|
+
// // if (isMultiSelect) {
|
|
51
|
+
// // ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
52
|
+
// // .then((response) => onComplete([response]))
|
|
53
|
+
// // .catch(() => {});
|
|
54
|
+
// // } else {
|
|
55
|
+
// // ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
56
|
+
// // .then((response) =>
|
|
57
|
+
// // ImageCropPicker.openCropper({
|
|
58
|
+
// // path: response?.path,
|
|
59
|
+
// // width: response?.width,
|
|
60
|
+
// // height: response?.height,
|
|
61
|
+
// // mediaType: "photo",
|
|
62
|
+
// // freeStyleCropEnabled: true,
|
|
63
|
+
// // }).then(onComplete)
|
|
64
|
+
// // )
|
|
65
|
+
// // .catch(() => {});
|
|
66
|
+
// // }
|
|
67
|
+
// // } else {
|
|
68
|
+
// // launchCamera({ mediaType: "video" }, (response) => {
|
|
69
|
+
// // if (response?.assets) {
|
|
70
|
+
// // onComplete({
|
|
71
|
+
// // path: response.assets[0]?.uri,
|
|
72
|
+
// // duration: response.assets[0]?.duration,
|
|
73
|
+
// // });
|
|
74
|
+
// // }
|
|
75
|
+
// // });
|
|
76
|
+
// // }
|
|
77
|
+
// // };
|
|
78
|
+
// // const onGallery = () => {
|
|
79
|
+
// // if (mediaType === "photo") {
|
|
80
|
+
// // if (isMultiSelect) {
|
|
81
|
+
// // ImageCropPicker.openPicker({
|
|
82
|
+
// // mediaType: "photo",
|
|
83
|
+
// // multiple: true,
|
|
84
|
+
// // maxFiles: 5,
|
|
85
|
+
// // })
|
|
86
|
+
// // .then((images) => {
|
|
87
|
+
// // if (images.length > 5) {
|
|
88
|
+
// // Alert.alert(
|
|
89
|
+
// // "Limit Exceeded",
|
|
90
|
+
// // "You can only select up to 5 images."
|
|
91
|
+
// // );
|
|
92
|
+
// // } else {
|
|
93
|
+
// // onComplete(images);
|
|
94
|
+
// // }
|
|
95
|
+
// // })
|
|
96
|
+
// // .catch(() => {});
|
|
97
|
+
// // } else {
|
|
98
|
+
// // ImageCropPicker.openPicker({ mediaType: "photo" })
|
|
99
|
+
// // .then((response) =>
|
|
100
|
+
// // ImageCropPicker.openCropper({
|
|
101
|
+
// // path: response?.path,
|
|
102
|
+
// // width: response?.width,
|
|
103
|
+
// // height: response?.height,
|
|
104
|
+
// // mediaType: "photo",
|
|
105
|
+
// // freeStyleCropEnabled: true,
|
|
106
|
+
// // }).then(onComplete)
|
|
107
|
+
// // )
|
|
108
|
+
// // .catch(() => {});
|
|
109
|
+
// // }
|
|
110
|
+
// // } else {
|
|
111
|
+
// // launchImageLibrary({ mediaType: "video" }, (result) => {
|
|
112
|
+
// // if (result?.assets) {
|
|
113
|
+
// // onComplete({
|
|
114
|
+
// // path: result.assets[0]?.uri,
|
|
115
|
+
// // duration: result.assets[0]?.duration,
|
|
116
|
+
// // });
|
|
117
|
+
// // }
|
|
118
|
+
// // });
|
|
119
|
+
// // }
|
|
120
|
+
// // };
|
|
121
|
+
// // return (
|
|
122
|
+
// // <BottomSheet visible={visible} onClose={onClose} height={230}>
|
|
123
|
+
// // <View style={[styles.container, containerStyle]}>
|
|
124
|
+
// // {/* Camera */}
|
|
125
|
+
// // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onCamera}>
|
|
126
|
+
// // <Image source={Images.video_icon} style={[styles.icon, iconStyle]} />
|
|
127
|
+
// // <Text style={[styles.text, textStyle]}>Camera</Text>
|
|
128
|
+
// // </TouchableOpacity>
|
|
129
|
+
// // <Dividers small />
|
|
130
|
+
// // {/* Gallery */}
|
|
131
|
+
// // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onGallery}>
|
|
132
|
+
// // <Image source={Images.image_icon} style={[styles.icon, iconStyle]} />
|
|
133
|
+
// // <Text style={[styles.text, textStyle]}>Gallery</Text>
|
|
134
|
+
// // </TouchableOpacity>
|
|
135
|
+
// // <Dividers small />
|
|
136
|
+
// // {/* Cancel */}
|
|
137
|
+
// // <TouchableOpacity style={[styles.row, rowStyle]} onPress={onClose}>
|
|
138
|
+
// // <Image source={Images.cancel} style={[styles.icon, iconStyle]} />
|
|
139
|
+
// // <Text style={[styles.text, textStyle]}>Cancel</Text>
|
|
140
|
+
// // </TouchableOpacity>
|
|
141
|
+
// // </View>
|
|
142
|
+
// // </BottomSheet>
|
|
143
|
+
// // );
|
|
144
|
+
// // };
|
|
145
|
+
// // export default ImagePicker;
|
|
146
|
+
// // const styles = StyleSheet.create({
|
|
147
|
+
// // container: { flex: 1, padding: 16 },
|
|
148
|
+
// // row: {
|
|
149
|
+
// // flexDirection: "row",
|
|
150
|
+
// // alignItems: "center",
|
|
151
|
+
// // },
|
|
152
|
+
// // text: { ...Typography.style.standardU(), color: Colors.white },
|
|
153
|
+
// // icon: {
|
|
154
|
+
// // width: Scale.moderateScale(20),
|
|
155
|
+
// // height: Scale.moderateScale(20),
|
|
156
|
+
// // marginRight: 10,
|
|
157
|
+
// // tintColor: Colors.white,
|
|
158
|
+
// // },
|
|
159
|
+
// // });
|
|
1
160
|
// import React, { useCallback } from "react";
|
|
2
161
|
// import {
|
|
3
162
|
// View,
|
|
@@ -6,38 +165,31 @@
|
|
|
6
165
|
// StyleSheet,
|
|
7
166
|
// Image,
|
|
8
167
|
// Alert,
|
|
9
|
-
// ViewStyle,
|
|
10
|
-
// TextStyle,
|
|
11
|
-
// ImageStyle,
|
|
12
168
|
// } from "react-native";
|
|
13
169
|
// import { BottomSheet, Dividers } from "../index";
|
|
14
170
|
// import { launchCamera, launchImageLibrary } from "react-native-image-picker";
|
|
15
171
|
// import ImageCropPicker from "react-native-image-crop-picker";
|
|
16
172
|
// import { Colors, Images, Scale, Typography } from "../../styles";
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
// };
|
|
173
|
+
// // 👇 Import your permission utilities
|
|
174
|
+
// import {
|
|
175
|
+
// cameraPermissions,
|
|
176
|
+
// galleryPermissions,
|
|
177
|
+
// } from "../../utils/permissions"; // ✅ Make sure path is correct
|
|
23
178
|
// type Props = {
|
|
24
179
|
// mediaType: "photo" | "video";
|
|
25
180
|
// isMultiSelect?: boolean;
|
|
26
181
|
// onSuccess: (data: any) => void;
|
|
27
182
|
// visible: boolean;
|
|
28
183
|
// onClose: () => void;
|
|
29
|
-
// }
|
|
184
|
+
// };
|
|
30
185
|
// const ImagePicker: React.FC<Props> = ({
|
|
31
186
|
// mediaType,
|
|
32
187
|
// isMultiSelect = false,
|
|
33
188
|
// onSuccess,
|
|
34
189
|
// visible,
|
|
35
190
|
// onClose,
|
|
36
|
-
// containerStyle,
|
|
37
|
-
// rowStyle,
|
|
38
|
-
// textStyle,
|
|
39
|
-
// iconStyle,
|
|
40
191
|
// }) => {
|
|
192
|
+
// // ✅ Success handler
|
|
41
193
|
// const onComplete = useCallback(
|
|
42
194
|
// (data: any) => {
|
|
43
195
|
// onSuccess(data);
|
|
@@ -45,98 +197,109 @@
|
|
|
45
197
|
// },
|
|
46
198
|
// [onSuccess, onClose]
|
|
47
199
|
// );
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
200
|
+
// // ✅ CAMERA HANDLER with permission check
|
|
201
|
+
// const handleCamera = async () => {
|
|
202
|
+
// await cameraPermissions(async (granted: boolean) => {
|
|
203
|
+
// if (!granted) return; // ❌ Permission denied, handled by your alert
|
|
204
|
+
// if (mediaType === "photo") {
|
|
205
|
+
// if (isMultiSelect) {
|
|
206
|
+
// // single capture, multiple not supported directly from camera
|
|
207
|
+
// ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
208
|
+
// .then((response) => onComplete([response]))
|
|
209
|
+
// .catch(() => {});
|
|
210
|
+
// } else {
|
|
211
|
+
// ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
212
|
+
// .then((response) =>
|
|
213
|
+
// ImageCropPicker.openCropper({
|
|
214
|
+
// path: response?.path,
|
|
215
|
+
// width: response?.width,
|
|
216
|
+
// height: response?.height,
|
|
217
|
+
// mediaType: "photo",
|
|
218
|
+
// freeStyleCropEnabled: true,
|
|
219
|
+
// }).then(onComplete)
|
|
220
|
+
// )
|
|
221
|
+
// .catch(() => {});
|
|
222
|
+
// }
|
|
54
223
|
// } else {
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
// )
|
|
65
|
-
// .catch(() => {});
|
|
224
|
+
// // 🎥 VIDEO CAPTURE
|
|
225
|
+
// launchCamera({ mediaType: "video" }, (response) => {
|
|
226
|
+
// if (response?.assets?.length) {
|
|
227
|
+
// onComplete({
|
|
228
|
+
// path: response.assets[0]?.uri,
|
|
229
|
+
// duration: response.assets[0]?.duration,
|
|
230
|
+
// });
|
|
231
|
+
// }
|
|
232
|
+
// });
|
|
66
233
|
// }
|
|
67
|
-
// }
|
|
68
|
-
// launchCamera({ mediaType: "video" }, (response) => {
|
|
69
|
-
// if (response?.assets) {
|
|
70
|
-
// onComplete({
|
|
71
|
-
// path: response.assets[0]?.uri,
|
|
72
|
-
// duration: response.assets[0]?.duration,
|
|
73
|
-
// });
|
|
74
|
-
// }
|
|
75
|
-
// });
|
|
76
|
-
// }
|
|
234
|
+
// });
|
|
77
235
|
// };
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// Alert.alert(
|
|
89
|
-
// "Limit Exceeded",
|
|
90
|
-
// "You can only select up to 5 images."
|
|
91
|
-
// );
|
|
92
|
-
// } else {
|
|
93
|
-
// onComplete(images);
|
|
94
|
-
// }
|
|
236
|
+
// // ✅ GALLERY HANDLER with permission check
|
|
237
|
+
// const handleGallery = async () => {
|
|
238
|
+
// await galleryPermissions(async (granted: boolean) => {
|
|
239
|
+
// if (!granted) return; // ❌ Permission denied, handled by your alert
|
|
240
|
+
// if (mediaType === "photo") {
|
|
241
|
+
// if (isMultiSelect) {
|
|
242
|
+
// ImageCropPicker.openPicker({
|
|
243
|
+
// mediaType: "photo",
|
|
244
|
+
// multiple: true,
|
|
245
|
+
// maxFiles: 5,
|
|
95
246
|
// })
|
|
96
|
-
//
|
|
247
|
+
// .then((images) => {
|
|
248
|
+
// if (images.length > 5) {
|
|
249
|
+
// Alert.alert(
|
|
250
|
+
// "Limit Exceeded",
|
|
251
|
+
// "You can only select up to 5 images."
|
|
252
|
+
// );
|
|
253
|
+
// } else {
|
|
254
|
+
// onComplete(images);
|
|
255
|
+
// }
|
|
256
|
+
// })
|
|
257
|
+
// .catch(() => {});
|
|
258
|
+
// } else {
|
|
259
|
+
// ImageCropPicker.openPicker({ mediaType: "photo" })
|
|
260
|
+
// .then((response) =>
|
|
261
|
+
// ImageCropPicker.openCropper({
|
|
262
|
+
// path: response?.path,
|
|
263
|
+
// width: response?.width,
|
|
264
|
+
// height: response?.height,
|
|
265
|
+
// mediaType: "photo",
|
|
266
|
+
// freeStyleCropEnabled: true,
|
|
267
|
+
// }).then(onComplete)
|
|
268
|
+
// )
|
|
269
|
+
// .catch(() => {});
|
|
270
|
+
// }
|
|
97
271
|
// } else {
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// )
|
|
108
|
-
// .catch(() => {});
|
|
272
|
+
// // 🎥 VIDEO FROM GALLERY
|
|
273
|
+
// launchImageLibrary({ mediaType: "video" }, (result) => {
|
|
274
|
+
// if (result?.assets?.length) {
|
|
275
|
+
// onComplete({
|
|
276
|
+
// path: result.assets[0]?.uri,
|
|
277
|
+
// duration: result.assets[0]?.duration,
|
|
278
|
+
// });
|
|
279
|
+
// }
|
|
280
|
+
// });
|
|
109
281
|
// }
|
|
110
|
-
// }
|
|
111
|
-
// launchImageLibrary({ mediaType: "video" }, (result) => {
|
|
112
|
-
// if (result?.assets) {
|
|
113
|
-
// onComplete({
|
|
114
|
-
// path: result.assets[0]?.uri,
|
|
115
|
-
// duration: result.assets[0]?.duration,
|
|
116
|
-
// });
|
|
117
|
-
// }
|
|
118
|
-
// });
|
|
119
|
-
// }
|
|
282
|
+
// });
|
|
120
283
|
// };
|
|
121
284
|
// return (
|
|
122
285
|
// <BottomSheet visible={visible} onClose={onClose} height={230}>
|
|
123
|
-
// <View style={
|
|
124
|
-
// {/* Camera */}
|
|
125
|
-
// <TouchableOpacity style={
|
|
126
|
-
// <Image source={Images.video_icon} style={
|
|
127
|
-
// <Text style={
|
|
286
|
+
// <View style={styles.container}>
|
|
287
|
+
// {/* 📸 Camera */}
|
|
288
|
+
// <TouchableOpacity style={styles.row} onPress={handleCamera}>
|
|
289
|
+
// <Image source={Images.video_icon} style={styles.icon} />
|
|
290
|
+
// <Text style={styles.text}>Camera</Text>
|
|
128
291
|
// </TouchableOpacity>
|
|
129
292
|
// <Dividers small />
|
|
130
|
-
// {/* Gallery */}
|
|
131
|
-
// <TouchableOpacity style={
|
|
132
|
-
// <Image source={Images.image_icon} style={
|
|
133
|
-
// <Text style={
|
|
293
|
+
// {/* 🖼️ Gallery */}
|
|
294
|
+
// <TouchableOpacity style={styles.row} onPress={handleGallery}>
|
|
295
|
+
// <Image source={Images.image_icon} style={styles.icon} />
|
|
296
|
+
// <Text style={styles.text}>Gallery</Text>
|
|
134
297
|
// </TouchableOpacity>
|
|
135
298
|
// <Dividers small />
|
|
136
|
-
// {/* Cancel */}
|
|
137
|
-
// <TouchableOpacity style={
|
|
138
|
-
// <Image source={Images.cancel} style={
|
|
139
|
-
// <Text style={
|
|
299
|
+
// {/* ❌ Cancel */}
|
|
300
|
+
// <TouchableOpacity style={styles.row} onPress={onClose}>
|
|
301
|
+
// <Image source={Images.cancel} style={styles.icon} />
|
|
302
|
+
// <Text style={styles.text}>Cancel</Text>
|
|
140
303
|
// </TouchableOpacity>
|
|
141
304
|
// </View>
|
|
142
305
|
// </BottomSheet>
|
|
@@ -162,45 +325,105 @@ import { View, Text, TouchableOpacity, StyleSheet, Image, Alert, } from "react-n
|
|
|
162
325
|
import { BottomSheet, Dividers } from "../index";
|
|
163
326
|
import { launchCamera, launchImageLibrary } from "react-native-image-picker";
|
|
164
327
|
import ImageCropPicker from "react-native-image-crop-picker";
|
|
328
|
+
import { Image as ImageCompressor, Video as VideoCompressor, } from "react-native-compressor";
|
|
329
|
+
import RNFS from "react-native-fs";
|
|
165
330
|
import { Colors, Images, Scale, Typography } from "../../styles";
|
|
166
|
-
//
|
|
167
|
-
import { cameraPermissions, galleryPermissions, } from "../../utils/permissions";
|
|
168
|
-
const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, }) => {
|
|
169
|
-
//
|
|
331
|
+
// Import your permission utilities
|
|
332
|
+
import { cameraPermissions, galleryPermissions, checkMicroPhonePermission, } from "../../utils/permissions";
|
|
333
|
+
const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, enableCompression = true, imageCompressionOptions = { maxWidth: 1080, quality: 0.7 }, videoCompressionOptions = { compressionMethod: "auto" }, }) => {
|
|
334
|
+
// Success handler
|
|
170
335
|
const onComplete = useCallback((data) => {
|
|
171
336
|
onSuccess(data);
|
|
172
337
|
onClose();
|
|
173
338
|
}, [onSuccess, onClose]);
|
|
174
|
-
//
|
|
339
|
+
// Helper: Compress Image
|
|
340
|
+
const compressImage = async (imagePath) => {
|
|
341
|
+
if (!enableCompression)
|
|
342
|
+
return imagePath;
|
|
343
|
+
try {
|
|
344
|
+
const compressedImage = await ImageCompressor.compress(imagePath, {
|
|
345
|
+
maxWidth: imageCompressionOptions.maxWidth,
|
|
346
|
+
quality: imageCompressionOptions.quality,
|
|
347
|
+
});
|
|
348
|
+
// Log compressed size (optional)
|
|
349
|
+
const stats = await RNFS.stat(compressedImage.replace("file://", ""));
|
|
350
|
+
const sizeInMB = stats.size / (1024 * 1024);
|
|
351
|
+
console.log("Compressed Image Size (MB):", sizeInMB);
|
|
352
|
+
return compressedImage;
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
console.error("Image compression error:", error);
|
|
356
|
+
return imagePath; // Return original if compression fails
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
// Helper: Compress Video
|
|
360
|
+
const compressVideo = async (videoUri) => {
|
|
361
|
+
if (!enableCompression)
|
|
362
|
+
return videoUri;
|
|
363
|
+
try {
|
|
364
|
+
const compressedVideo = await VideoCompressor.compress(videoUri, {
|
|
365
|
+
compressionMethod: videoCompressionOptions.compressionMethod,
|
|
366
|
+
});
|
|
367
|
+
// Log compressed size (optional)
|
|
368
|
+
const stats = await RNFS.stat(compressedVideo.replace("file://", ""));
|
|
369
|
+
const sizeInMB = stats.size / (1024 * 1024);
|
|
370
|
+
console.log("Compressed Video Size (MB):", sizeInMB);
|
|
371
|
+
return compressedVideo;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
console.error("Video compression error:", error);
|
|
375
|
+
return videoUri; // Return original if compression fails
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
// CAMERA HANDLER with permission check and compression
|
|
175
379
|
const handleCamera = async () => {
|
|
176
380
|
await cameraPermissions(async (granted) => {
|
|
177
381
|
if (!granted)
|
|
178
|
-
return;
|
|
382
|
+
return;
|
|
179
383
|
if (mediaType === "photo") {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
183
|
-
.then((response) => onComplete([response]))
|
|
184
|
-
.catch(() => { });
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
ImageCropPicker.openCamera({ mediaType: "photo" })
|
|
188
|
-
.then((response) => ImageCropPicker.openCropper({
|
|
189
|
-
path: response?.path,
|
|
190
|
-
width: response?.width,
|
|
191
|
-
height: response?.height,
|
|
384
|
+
try {
|
|
385
|
+
const response = await ImageCropPicker.openCamera({
|
|
192
386
|
mediaType: "photo",
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
387
|
+
});
|
|
388
|
+
if (isMultiSelect) {
|
|
389
|
+
// Single capture for multi-select mode
|
|
390
|
+
const compressedPath = await compressImage(response.path);
|
|
391
|
+
onComplete([{ ...response, path: compressedPath }]);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
// Crop and compress single image
|
|
395
|
+
const cropped = await ImageCropPicker.openCropper({
|
|
396
|
+
path: response?.path,
|
|
397
|
+
width: response?.width,
|
|
398
|
+
height: response?.height,
|
|
399
|
+
mediaType: "photo",
|
|
400
|
+
freeStyleCropEnabled: true,
|
|
401
|
+
});
|
|
402
|
+
const compressedPath = await compressImage(cropped.path);
|
|
403
|
+
onComplete({ ...cropped, path: compressedPath });
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
console.log("Camera cancelled or error:", error);
|
|
196
408
|
}
|
|
197
409
|
}
|
|
198
410
|
else {
|
|
199
|
-
//
|
|
200
|
-
|
|
411
|
+
// VIDEO CAPTURE - check microphone permission first
|
|
412
|
+
const micPermission = await checkMicroPhonePermission();
|
|
413
|
+
if (!micPermission) {
|
|
414
|
+
Alert.alert("Microphone Permission Required", "Please enable microphone access to record videos.");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
launchCamera({
|
|
418
|
+
mediaType: "video",
|
|
419
|
+
durationLimit: 60,
|
|
420
|
+
videoQuality: "high",
|
|
421
|
+
}, async (response) => {
|
|
201
422
|
if (response?.assets?.length) {
|
|
423
|
+
const videoUri = response.assets[0]?.uri;
|
|
424
|
+
const compressedPath = await compressVideo(videoUri);
|
|
202
425
|
onComplete({
|
|
203
|
-
path:
|
|
426
|
+
path: compressedPath,
|
|
204
427
|
duration: response.assets[0]?.duration,
|
|
205
428
|
});
|
|
206
429
|
}
|
|
@@ -208,46 +431,61 @@ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onC
|
|
|
208
431
|
}
|
|
209
432
|
});
|
|
210
433
|
};
|
|
211
|
-
//
|
|
434
|
+
// GALLERY HANDLER with permission check and compression
|
|
212
435
|
const handleGallery = async () => {
|
|
213
436
|
await galleryPermissions(async (granted) => {
|
|
214
437
|
if (!granted)
|
|
215
|
-
return;
|
|
438
|
+
return;
|
|
216
439
|
if (mediaType === "photo") {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
440
|
+
try {
|
|
441
|
+
if (isMultiSelect) {
|
|
442
|
+
const images = await ImageCropPicker.openPicker({
|
|
443
|
+
mediaType: "photo",
|
|
444
|
+
multiple: true,
|
|
445
|
+
maxFiles: 5,
|
|
446
|
+
});
|
|
224
447
|
if (images.length > 5) {
|
|
225
448
|
Alert.alert("Limit Exceeded", "You can only select up to 5 images.");
|
|
449
|
+
return;
|
|
226
450
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
451
|
+
// Compress multiple images
|
|
452
|
+
const compressedImages = await Promise.all(images.map(async (img) => ({
|
|
453
|
+
...img,
|
|
454
|
+
path: await compressImage(img.path),
|
|
455
|
+
})));
|
|
456
|
+
onComplete(compressedImages);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
// Single image with crop
|
|
460
|
+
const response = await ImageCropPicker.openPicker({
|
|
461
|
+
mediaType: "photo",
|
|
462
|
+
});
|
|
463
|
+
const cropped = await ImageCropPicker.openCropper({
|
|
464
|
+
path: response?.path,
|
|
465
|
+
width: response?.width,
|
|
466
|
+
height: response?.height,
|
|
467
|
+
mediaType: "photo",
|
|
468
|
+
freeStyleCropEnabled: true,
|
|
469
|
+
});
|
|
470
|
+
const compressedPath = await compressImage(cropped.path);
|
|
471
|
+
onComplete({ ...cropped, path: compressedPath });
|
|
472
|
+
}
|
|
232
473
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
.then((response) => ImageCropPicker.openCropper({
|
|
236
|
-
path: response?.path,
|
|
237
|
-
width: response?.width,
|
|
238
|
-
height: response?.height,
|
|
239
|
-
mediaType: "photo",
|
|
240
|
-
freeStyleCropEnabled: true,
|
|
241
|
-
}).then(onComplete))
|
|
242
|
-
.catch(() => { });
|
|
474
|
+
catch (error) {
|
|
475
|
+
console.log("Gallery cancelled or error:", error);
|
|
243
476
|
}
|
|
244
477
|
}
|
|
245
478
|
else {
|
|
246
|
-
//
|
|
247
|
-
launchImageLibrary({
|
|
479
|
+
// VIDEO FROM GALLERY
|
|
480
|
+
launchImageLibrary({
|
|
481
|
+
mediaType: "video",
|
|
482
|
+
assetRepresentationMode: "current",
|
|
483
|
+
}, async (result) => {
|
|
248
484
|
if (result?.assets?.length) {
|
|
485
|
+
const videoUri = result.assets[0]?.uri;
|
|
486
|
+
const compressedPath = await compressVideo(videoUri);
|
|
249
487
|
onComplete({
|
|
250
|
-
path:
|
|
488
|
+
path: compressedPath,
|
|
251
489
|
duration: result.assets[0]?.duration,
|
|
252
490
|
});
|
|
253
491
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamnhz/rn-ui-toolkit",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
"react-native-safe-area-context": "^5.6.1",
|
|
32
32
|
"react-native-svg": "^15.12.1",
|
|
33
33
|
"react-native-vector-icons": "^10.3.0",
|
|
34
|
-
"react-native-video-trim": "^3.0.9"
|
|
34
|
+
"react-native-video-trim": "^3.0.9",
|
|
35
|
+
"react-native-compressor": "^1.13.0",
|
|
36
|
+
"react-native-fs": "^2.20.0"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
37
39
|
"@react-native-documents/picker": "^10.1.5",
|