@teamnhz/rn-ui-toolkit 1.1.8 → 1.1.9

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,259 +1,3 @@
1
- // import React, { useCallback } from "react";
2
- // import {
3
- // View,
4
- // Text,
5
- // TouchableOpacity,
6
- // StyleSheet,
7
- // Image,
8
- // Alert,
9
- // } from "react-native";
10
- // import { BottomSheet, Dividers } from "../index";
11
- // import { launchCamera, launchImageLibrary } from "react-native-image-picker";
12
- // import ImageCropPicker from "react-native-image-crop-picker";
13
- // import {
14
- // Image as ImageCompressor,
15
- // Video as VideoCompressor,
16
- // } from "react-native-compressor";
17
- // import RNFS from "react-native-fs";
18
- // import { Colors, Images, Scale, Typography } from "../../styles";
19
- // // Import your permission utilities
20
- // import {
21
- // cameraPermissions,
22
- // galleryPermissions,
23
- // checkMicroPhonePermission,
24
- // } from "../../utils/permissions";
25
- // type Props = {
26
- // mediaType: "photo" | "video";
27
- // isMultiSelect?: boolean;
28
- // onSuccess: (data: any) => void;
29
- // visible: boolean;
30
- // onClose: () => void;
31
- // // Compression options
32
- // enableCompression?: boolean;
33
- // imageCompressionOptions?: {
34
- // maxWidth?: number;
35
- // quality?: number;
36
- // };
37
- // videoCompressionOptions?: {
38
- // compressionMethod?: "auto" | "manual";
39
- // };
40
- // };
41
- // const ImagePicker: React.FC<Props> = ({
42
- // mediaType,
43
- // isMultiSelect = false,
44
- // onSuccess,
45
- // visible,
46
- // onClose,
47
- // enableCompression = true,
48
- // imageCompressionOptions = { maxWidth: 1080, quality: 0.7 },
49
- // videoCompressionOptions = { compressionMethod: "auto" },
50
- // }) => {
51
- // // Success handler
52
- // const onComplete = useCallback(
53
- // (data: any) => {
54
- // onSuccess(data);
55
- // onClose();
56
- // },
57
- // [onSuccess, onClose]
58
- // );
59
- // // Helper: Compress Image
60
- // const compressImage = async (imagePath: string) => {
61
- // if (!enableCompression) return imagePath;
62
- // try {
63
- // const compressedImage = await ImageCompressor.compress(imagePath, {
64
- // maxWidth: imageCompressionOptions.maxWidth,
65
- // quality: imageCompressionOptions.quality,
66
- // });
67
- // // Log compressed size (optional)
68
- // const stats = await RNFS.stat(compressedImage.replace("file://", ""));
69
- // const sizeInMB = stats.size / (1024 * 1024);
70
- // console.log("Compressed Image Size (MB):", sizeInMB);
71
- // return compressedImage;
72
- // } catch (error) {
73
- // console.error("Image compression error:", error);
74
- // return imagePath; // Return original if compression fails
75
- // }
76
- // };
77
- // // Helper: Compress Video
78
- // const compressVideo = async (videoUri: string) => {
79
- // if (!enableCompression) return videoUri;
80
- // try {
81
- // const compressedVideo = await VideoCompressor.compress(videoUri, {
82
- // compressionMethod: videoCompressionOptions.compressionMethod,
83
- // });
84
- // // Log compressed size (optional)
85
- // const stats = await RNFS.stat(compressedVideo.replace("file://", ""));
86
- // const sizeInMB = stats.size / (1024 * 1024);
87
- // console.log("Compressed Video Size (MB):", sizeInMB);
88
- // return compressedVideo;
89
- // } catch (error) {
90
- // console.error("Video compression error:", error);
91
- // return videoUri; // Return original if compression fails
92
- // }
93
- // };
94
- // // CAMERA HANDLER with permission check and compression
95
- // const handleCamera = async () => {
96
- // await cameraPermissions(async (granted: boolean) => {
97
- // if (!granted) return;
98
- // if (mediaType === "photo") {
99
- // try {
100
- // const response = await ImageCropPicker.openCamera({
101
- // mediaType: "photo",
102
- // });
103
- // if (isMultiSelect) {
104
- // // Single capture for multi-select mode
105
- // const compressedPath = await compressImage(response.path);
106
- // onComplete([{ ...response, path: compressedPath }]);
107
- // } else {
108
- // // Crop and compress single image
109
- // const cropped = await ImageCropPicker.openCropper({
110
- // path: response?.path,
111
- // width: response?.width,
112
- // height: response?.height,
113
- // mediaType: "photo",
114
- // freeStyleCropEnabled: true,
115
- // });
116
- // const compressedPath = await compressImage(cropped.path);
117
- // onComplete({ ...cropped, path: compressedPath });
118
- // }
119
- // } catch (error) {
120
- // console.log("Camera cancelled or error:", error);
121
- // }
122
- // } else {
123
- // // VIDEO CAPTURE - check microphone permission first
124
- // const micPermission = await checkMicroPhonePermission();
125
- // if (!micPermission) {
126
- // Alert.alert(
127
- // "Microphone Permission Required",
128
- // "Please enable microphone access to record videos."
129
- // );
130
- // return;
131
- // }
132
- // launchCamera(
133
- // {
134
- // mediaType: "video",
135
- // durationLimit: 60,
136
- // videoQuality: "high",
137
- // },
138
- // async (response) => {
139
- // if (response?.assets?.length) {
140
- // const videoUri = response.assets[0]?.uri;
141
- // const compressedPath = await compressVideo(videoUri);
142
- // onComplete({
143
- // path: compressedPath,
144
- // duration: response.assets[0]?.duration,
145
- // });
146
- // }
147
- // }
148
- // );
149
- // }
150
- // });
151
- // };
152
- // // GALLERY HANDLER with permission check and compression
153
- // const handleGallery = async () => {
154
- // await galleryPermissions(async (granted: boolean) => {
155
- // if (!granted) return;
156
- // if (mediaType === "photo") {
157
- // try {
158
- // if (isMultiSelect) {
159
- // const images = await ImageCropPicker.openPicker({
160
- // mediaType: "photo",
161
- // multiple: true,
162
- // maxFiles: 5,
163
- // });
164
- // if (images.length > 5) {
165
- // Alert.alert(
166
- // "Limit Exceeded",
167
- // "You can only select up to 5 images."
168
- // );
169
- // return;
170
- // }
171
- // // Compress multiple images
172
- // const compressedImages = await Promise.all(
173
- // images.map(async (img) => ({
174
- // ...img,
175
- // path: await compressImage(img.path),
176
- // }))
177
- // );
178
- // onComplete(compressedImages);
179
- // } else {
180
- // // Single image with crop
181
- // const response = await ImageCropPicker.openPicker({
182
- // mediaType: "photo",
183
- // });
184
- // const cropped = await ImageCropPicker.openCropper({
185
- // path: response?.path,
186
- // width: response?.width,
187
- // height: response?.height,
188
- // mediaType: "photo",
189
- // freeStyleCropEnabled: true,
190
- // });
191
- // const compressedPath = await compressImage(cropped.path);
192
- // onComplete({ ...cropped, path: compressedPath });
193
- // }
194
- // } catch (error) {
195
- // console.log("Gallery cancelled or error:", error);
196
- // }
197
- // } else {
198
- // // VIDEO FROM GALLERY
199
- // launchImageLibrary(
200
- // {
201
- // mediaType: "video",
202
- // assetRepresentationMode: "current",
203
- // },
204
- // async (result) => {
205
- // if (result?.assets?.length) {
206
- // const videoUri = result.assets[0]?.uri;
207
- // const compressedPath = await compressVideo(videoUri);
208
- // onComplete({
209
- // path: compressedPath,
210
- // duration: result.assets[0]?.duration,
211
- // });
212
- // }
213
- // }
214
- // );
215
- // }
216
- // });
217
- // };
218
- // return (
219
- // <BottomSheet visible={visible} onClose={onClose} height={230}>
220
- // <View style={styles.container}>
221
- // {/* Camera */}
222
- // <TouchableOpacity style={styles.row} onPress={handleCamera}>
223
- // <Image source={Images.video_icon} style={styles.icon} />
224
- // <Text style={styles.text}>Camera</Text>
225
- // </TouchableOpacity>
226
- // <Dividers small />
227
- // {/* Gallery */}
228
- // <TouchableOpacity style={styles.row} onPress={handleGallery}>
229
- // <Image source={Images.image_icon} style={styles.icon} />
230
- // <Text style={styles.text}>Gallery</Text>
231
- // </TouchableOpacity>
232
- // <Dividers small />
233
- // {/* Cancel */}
234
- // <TouchableOpacity style={styles.row} onPress={onClose}>
235
- // <Image source={Images.cancel} style={styles.icon} />
236
- // <Text style={styles.text}>Cancel</Text>
237
- // </TouchableOpacity>
238
- // </View>
239
- // </BottomSheet>
240
- // );
241
- // };
242
- // export default ImagePicker;
243
- // const styles = StyleSheet.create({
244
- // container: { flex: 1, padding: 16 },
245
- // row: {
246
- // flexDirection: "row",
247
- // alignItems: "center",
248
- // },
249
- // text: { ...Typography.style.standardU(), color: Colors.white },
250
- // icon: {
251
- // width: Scale.moderateScale(20),
252
- // height: Scale.moderateScale(20),
253
- // marginRight: 10,
254
- // tintColor: Colors.white,
255
- // },
256
- // });
257
1
  import React from "react";
258
2
  import { View, Text, TouchableOpacity, StyleSheet, Image, } from "react-native";
259
3
  import { BottomSheet, Dividers } from "../index";
@@ -262,16 +6,35 @@ import ImageCropPicker from "react-native-image-crop-picker";
262
6
  import { Image as ImageCompressor, Video as VideoCompressor, } from "react-native-compressor";
263
7
  import { Colors, Images, Scale, Typography } from "../../styles";
264
8
  import { cameraPermissions, galleryPermissions, checkMicroPhonePermission, } from "../../utils/permissions";
9
+ // NORMALIZE FINAL RESPONSE
10
+ const buildResponse = (raw, compressedPath) => {
11
+ return {
12
+ path: compressedPath || raw?.path || raw?.uri?.replace("file://", ""),
13
+ originalPath: raw?.path?.replace("file://", "") ||
14
+ raw?.uri?.replace("file://", "") ||
15
+ "",
16
+ fileName: raw?.fileName || "",
17
+ type: raw?.type || "",
18
+ duration: raw?.duration || undefined,
19
+ };
20
+ };
265
21
  const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onClose, enableCompression = true, }) => {
266
- // Close modal + start loader in parent
267
- const sendRawAndClose = (rawData) => {
22
+ // SEND RAW (loading true) TO PARENT
23
+ const sendRaw = (raw) => {
268
24
  onClose();
269
- onSuccess({ loading: true, data: rawData });
25
+ onSuccess({
26
+ loading: true,
27
+ data: buildResponse(raw),
28
+ });
270
29
  };
271
- // After compression finished
272
- const sendFinalCompressed = (compressed) => {
273
- onSuccess({ loading: false, data: compressed });
30
+ // SEND FINAL COMPRESSED
31
+ const sendFinal = (raw, compressedPath) => {
32
+ onSuccess({
33
+ loading: false,
34
+ data: buildResponse(raw, compressedPath),
35
+ });
274
36
  };
37
+ // IMAGE COMPRESSOR
275
38
  const compressImage = async (path) => {
276
39
  try {
277
40
  const compressed = await ImageCompressor.compress(path, {
@@ -280,10 +43,11 @@ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onC
280
43
  });
281
44
  return compressed;
282
45
  }
283
- catch (e) {
46
+ catch {
284
47
  return path;
285
48
  }
286
49
  };
50
+ // VIDEO COMPRESSOR
287
51
  const compressVideo = async (uri) => {
288
52
  try {
289
53
  const compressed = await VideoCompressor.compress(uri, {
@@ -291,84 +55,73 @@ const ImagePicker = ({ mediaType, isMultiSelect = false, onSuccess, visible, onC
291
55
  });
292
56
  return compressed;
293
57
  }
294
- catch (e) {
58
+ catch {
295
59
  return uri;
296
60
  }
297
61
  };
298
- // ---------- CAMERA ----------
62
+ // ------------------ CAMERA ------------------
299
63
  const handleCamera = async () => {
300
64
  await cameraPermissions(async (granted) => {
301
65
  if (!granted)
302
66
  return;
303
67
  if (mediaType === "photo") {
304
68
  try {
305
- const picked = await ImageCropPicker.openCamera({
306
- mediaType: "photo",
307
- });
308
- sendRawAndClose(picked); // CLOSE MODAL + START LOADER
309
- setTimeout(async () => {
310
- const compressedPath = await compressImage(picked.path);
311
- sendFinalCompressed({ ...picked, path: compressedPath });
312
- }, 10);
69
+ const picked = await ImageCropPicker.openCamera({ mediaType: "photo" });
70
+ sendRaw(picked);
71
+ const compressed = enableCompression
72
+ ? await compressImage(picked.path)
73
+ : picked.path;
74
+ sendFinal(picked, compressed);
313
75
  }
314
- catch (err) {
315
- console.log(err);
76
+ catch (e) {
77
+ console.log(e);
316
78
  }
317
79
  }
318
80
  else {
319
- // VIDEO
320
81
  const mic = await checkMicroPhonePermission();
321
82
  if (!mic)
322
83
  return;
323
- launchCamera({ mediaType: "video", durationLimit: 60, videoQuality: "high" }, (res) => {
84
+ launchCamera({ mediaType: "video", durationLimit: 60, videoQuality: "high" }, async (res) => {
324
85
  if (!res?.assets?.length)
325
86
  return;
326
87
  const raw = res.assets[0];
327
- sendRawAndClose(raw);
328
- setTimeout(async () => {
329
- const compressed = await compressVideo(raw.uri);
330
- sendFinalCompressed({
331
- path: compressed,
332
- duration: raw.duration,
333
- });
334
- }, 10);
88
+ sendRaw(raw);
89
+ const compressed = enableCompression
90
+ ? await compressVideo(raw.uri)
91
+ : raw.uri;
92
+ sendFinal(raw, compressed);
335
93
  });
336
94
  }
337
95
  });
338
96
  };
339
- // ---------- GALLERY ----------
97
+ // ------------------ GALLERY ------------------
340
98
  const handleGallery = async () => {
341
99
  await galleryPermissions(async (granted) => {
342
100
  if (!granted)
343
101
  return;
344
102
  if (mediaType === "photo") {
345
103
  try {
346
- const picked = await ImageCropPicker.openPicker({
347
- mediaType: "photo",
348
- });
349
- sendRawAndClose(picked);
350
- setTimeout(async () => {
351
- const compressed = await compressImage(picked.path);
352
- sendFinalCompressed({ ...picked, path: compressed });
353
- }, 10);
104
+ const picked = await ImageCropPicker.openPicker({ mediaType: "photo" });
105
+ sendRaw(picked);
106
+ const compressed = enableCompression
107
+ ? await compressImage(picked.path)
108
+ : picked.path;
109
+ sendFinal(picked, compressed);
354
110
  }
355
111
  catch (e) {
356
112
  console.log(e);
357
113
  }
358
114
  }
359
115
  else {
360
- launchImageLibrary({ mediaType: "video" }, (res) => {
116
+ launchImageLibrary({ mediaType: "video" }, async (res) => {
361
117
  if (!res?.assets?.length)
362
118
  return;
363
119
  const raw = res.assets[0];
364
- sendRawAndClose(raw);
365
- setTimeout(async () => {
366
- const compressed = await compressVideo(raw.uri);
367
- sendFinalCompressed({
368
- path: compressed,
369
- duration: raw.duration,
370
- });
371
- }, 10);
120
+ sendRaw(raw);
121
+ const compressed = enableCompression
122
+ ? await compressVideo(raw.uri)
123
+ : raw.uri;
124
+ sendFinal(raw, compressed);
372
125
  });
373
126
  }
374
127
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamnhz/rn-ui-toolkit",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [