@teamnhz/rn-ui-toolkit 1.2.1 โ 1.2.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.
|
@@ -7,25 +7,38 @@ import { Image as ImageCompressor, Video as VideoCompressor, } from "react-nativ
|
|
|
7
7
|
import { cameraPermissions, galleryPermissions, checkMicroPhonePermission, } from "../../utils/permissions";
|
|
8
8
|
import { Colors, Images, Scale, Typography } from "../../styles";
|
|
9
9
|
//--------------------------------------
|
|
10
|
-
// ๐ฆ FORMAT
|
|
10
|
+
// ๐ฆ FORMAT PATH (always file:// format)
|
|
11
11
|
//--------------------------------------
|
|
12
12
|
const normalizePath = (p) => {
|
|
13
13
|
if (!p)
|
|
14
14
|
return "";
|
|
15
15
|
return p.startsWith("file://") ? p : `file://${p}`;
|
|
16
16
|
};
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
const resetInternalState = () => {
|
|
18
|
+
try {
|
|
19
|
+
ImageCropPicker.clean().catch(() => { });
|
|
20
|
+
ImageCropPicker.cleanSingle && ImageCropPicker.cleanSingle().catch(() => { });
|
|
21
|
+
}
|
|
22
|
+
catch { }
|
|
23
|
+
// ๐งน If you stored something in ref or state in future
|
|
24
|
+
// you can reset here too.
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
//--------------------------------------
|
|
27
|
+
// ๐ฆ FINAL RESPONSE FORMAT
|
|
28
|
+
//--------------------------------------
|
|
29
|
+
const buildResponse = (raw, compressed) => ({
|
|
30
|
+
path: normalizePath(compressed || raw?.path || raw?.uri),
|
|
31
|
+
originalPath: normalizePath(raw?.path || raw?.uri),
|
|
32
|
+
fileName: raw?.fileName || "",
|
|
33
|
+
type: raw?.type || "",
|
|
34
|
+
duration: raw?.duration || undefined,
|
|
35
|
+
});
|
|
36
|
+
//--------------------------------------
|
|
37
|
+
// ๐ฆ MAIN COMPONENT
|
|
38
|
+
//--------------------------------------
|
|
39
|
+
const ImagePicker = ({ mediaType, visible, onSuccess, onClose, enableCompression = true, }) => {
|
|
27
40
|
//--------------------------------------
|
|
28
|
-
//
|
|
41
|
+
// SEND RAW (loader ON)
|
|
29
42
|
//--------------------------------------
|
|
30
43
|
const sendRaw = (raw) => {
|
|
31
44
|
onSuccess({
|
|
@@ -34,16 +47,17 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
34
47
|
});
|
|
35
48
|
};
|
|
36
49
|
//--------------------------------------
|
|
37
|
-
//
|
|
50
|
+
// SEND FINAL (loader OFF)
|
|
38
51
|
//--------------------------------------
|
|
39
|
-
const sendFinal = (raw,
|
|
52
|
+
const sendFinal = (raw, compressed) => {
|
|
40
53
|
onSuccess({
|
|
41
54
|
loading: false,
|
|
42
|
-
data: buildResponse(raw,
|
|
55
|
+
data: buildResponse(raw, compressed),
|
|
43
56
|
});
|
|
57
|
+
resetInternalState();
|
|
44
58
|
};
|
|
45
59
|
//--------------------------------------
|
|
46
|
-
//
|
|
60
|
+
// COMPRESS IMAGE
|
|
47
61
|
//--------------------------------------
|
|
48
62
|
const compressImage = async (path) => {
|
|
49
63
|
try {
|
|
@@ -57,7 +71,7 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
57
71
|
}
|
|
58
72
|
};
|
|
59
73
|
//--------------------------------------
|
|
60
|
-
//
|
|
74
|
+
// COMPRESS VIDEO
|
|
61
75
|
//--------------------------------------
|
|
62
76
|
const compressVideo = async (uri) => {
|
|
63
77
|
try {
|
|
@@ -70,13 +84,14 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
70
84
|
}
|
|
71
85
|
};
|
|
72
86
|
//--------------------------------------
|
|
73
|
-
//
|
|
87
|
+
// CAMERA HANDLER
|
|
74
88
|
//--------------------------------------
|
|
75
89
|
const handleCamera = async () => {
|
|
90
|
+
onClose(); // ๐ฅ CLOSE FIRST (best UX)
|
|
76
91
|
await cameraPermissions(async (granted) => {
|
|
77
92
|
if (!granted)
|
|
78
93
|
return;
|
|
79
|
-
// PHOTO
|
|
94
|
+
// PHOTO
|
|
80
95
|
if (mediaType === "photo") {
|
|
81
96
|
try {
|
|
82
97
|
const img = await ImageCropPicker.openCamera({
|
|
@@ -90,10 +105,10 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
90
105
|
sendFinal(img, compressed);
|
|
91
106
|
}
|
|
92
107
|
catch (e) {
|
|
93
|
-
console.log("Camera Photo Error", e);
|
|
108
|
+
console.log("Camera Photo Error:", e);
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
|
-
// VIDEO
|
|
111
|
+
// VIDEO
|
|
97
112
|
else {
|
|
98
113
|
const mic = await checkMicroPhonePermission();
|
|
99
114
|
if (!mic)
|
|
@@ -112,13 +127,14 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
112
127
|
});
|
|
113
128
|
};
|
|
114
129
|
//--------------------------------------
|
|
115
|
-
//
|
|
130
|
+
// GALLERY HANDLER
|
|
116
131
|
//--------------------------------------
|
|
117
132
|
const handleGallery = async () => {
|
|
133
|
+
onClose(); // ๐ฅ CLOSE IMMEDIATELY
|
|
118
134
|
await galleryPermissions(async (granted) => {
|
|
119
135
|
if (!granted)
|
|
120
136
|
return;
|
|
121
|
-
// PHOTO
|
|
137
|
+
// PHOTO (Crop Picker)
|
|
122
138
|
if (mediaType === "photo") {
|
|
123
139
|
try {
|
|
124
140
|
const img = await ImageCropPicker.openPicker({
|
|
@@ -132,10 +148,10 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
132
148
|
sendFinal(img, compressed);
|
|
133
149
|
}
|
|
134
150
|
catch (e) {
|
|
135
|
-
console.log("Gallery Photo Error", e);
|
|
151
|
+
console.log("Gallery Photo Error:", e);
|
|
136
152
|
}
|
|
137
153
|
}
|
|
138
|
-
// VIDEO
|
|
154
|
+
// VIDEO
|
|
139
155
|
else {
|
|
140
156
|
launchImageLibrary({ mediaType: "video" }, async (res) => {
|
|
141
157
|
const raw = res?.assets?.[0];
|
|
@@ -151,6 +167,8 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
151
167
|
});
|
|
152
168
|
};
|
|
153
169
|
//--------------------------------------
|
|
170
|
+
// RETURN UI
|
|
171
|
+
//--------------------------------------
|
|
154
172
|
return (React.createElement(BottomSheet, { visible: visible, onClose: onClose, height: 230 },
|
|
155
173
|
React.createElement(View, { style: styles.container },
|
|
156
174
|
React.createElement(TouchableOpacity, { style: styles.row, onPress: handleCamera },
|
|
@@ -166,10 +184,23 @@ const ImagePicker = ({ mediaType, onSuccess, visible, onClose, enableCompression
|
|
|
166
184
|
React.createElement(Text, { style: styles.text }, "Cancel")))));
|
|
167
185
|
};
|
|
168
186
|
export default ImagePicker;
|
|
187
|
+
//--------------------------------------
|
|
188
|
+
// STYLES
|
|
189
|
+
//--------------------------------------
|
|
169
190
|
const styles = StyleSheet.create({
|
|
170
191
|
container: { flex: 1, padding: 16 },
|
|
171
|
-
row: {
|
|
172
|
-
|
|
192
|
+
row: {
|
|
193
|
+
flexDirection: "row",
|
|
194
|
+
alignItems: "center",
|
|
195
|
+
justifyContent: "center",
|
|
196
|
+
paddingVertical: 14,
|
|
197
|
+
},
|
|
198
|
+
text: {
|
|
199
|
+
...Typography.style.standardU(),
|
|
200
|
+
color: Colors.white,
|
|
201
|
+
marginLeft: 10,
|
|
202
|
+
textAlign: "center",
|
|
203
|
+
},
|
|
173
204
|
icon: {
|
|
174
205
|
width: Scale.moderateScale(20),
|
|
175
206
|
height: Scale.moderateScale(20),
|