react-native-timacare 3.3.16 → 3.3.17
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/lib/commonjs/screens/camera/CCCDCameraScreen.js +1 -1
- package/lib/commonjs/screens/camera/CCCDCameraScreen.js.flow +162 -235
- package/lib/commonjs/screens/camera/CCCDCameraScreen.js.map +1 -1
- package/lib/commonjs/screens/toan-trinh-so/OCR.js +1 -1
- package/lib/commonjs/screens/toan-trinh-so/OCR.js.flow +1 -1
- package/lib/module/screens/camera/CCCDCameraScreen.js +1 -1
- package/lib/module/screens/camera/CCCDCameraScreen.js.map +1 -1
- package/lib/module/screens/toan-trinh-so/OCR.js +1 -1
- package/lib/typescript/screens/camera/CCCDCameraScreen.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/screens/camera/CCCDCameraScreen.tsx +162 -235
- package/src/screens/toan-trinh-so/OCR.tsx +1 -1
|
@@ -1,256 +1,200 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck
|
|
2
2
|
import React, { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import {
|
|
4
|
+
ActivityIndicator,
|
|
4
5
|
Alert,
|
|
5
6
|
Dimensions,
|
|
6
|
-
Image,
|
|
7
7
|
Platform,
|
|
8
8
|
StyleSheet,
|
|
9
9
|
TouchableOpacity,
|
|
10
10
|
View,
|
|
11
11
|
} from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
Camera,
|
|
14
|
-
useCameraDevice,
|
|
15
|
-
useCameraFormat,
|
|
16
|
-
useCameraPermission,
|
|
17
|
-
} from 'react-native-vision-camera';
|
|
12
|
+
import { RNCamera } from 'react-native-camera';
|
|
18
13
|
import { IconBackWhite, TakePhotoSvg } from '../../assets/icons';
|
|
19
14
|
import { MText } from '../../components/MText';
|
|
20
|
-
import { useNavigation } from '@react-navigation/native';
|
|
15
|
+
import { useNavigation, useIsFocused } from '@react-navigation/native';
|
|
21
16
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
new Promise((resolve, reject) => {
|
|
30
|
-
Image.getSize(
|
|
31
|
-
uri,
|
|
32
|
-
(width, height) => resolve({ width, height }),
|
|
33
|
-
(err) => reject(err)
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const clamp = (value: number, min: number, max: number) =>
|
|
38
|
-
Math.min(Math.max(value, min), max);
|
|
39
|
-
|
|
40
|
-
const getSnapshotCropRect = ({
|
|
41
|
-
imageWidth,
|
|
42
|
-
imageHeight,
|
|
43
|
-
previewWidth,
|
|
44
|
-
previewHeight,
|
|
45
|
-
frameX,
|
|
46
|
-
frameY,
|
|
47
|
-
frameWidth,
|
|
48
|
-
frameHeight,
|
|
49
|
-
}: {
|
|
50
|
-
imageWidth: number;
|
|
51
|
-
imageHeight: number;
|
|
52
|
-
previewWidth: number;
|
|
53
|
-
previewHeight: number;
|
|
54
|
-
frameX: number;
|
|
55
|
-
frameY: number;
|
|
56
|
-
frameWidth: number;
|
|
57
|
-
frameHeight: number;
|
|
58
|
-
}) => {
|
|
59
|
-
const scaleX = imageWidth / previewWidth;
|
|
60
|
-
const scaleY = imageHeight / previewHeight;
|
|
61
|
-
const originX = clamp(frameX * scaleX, 0, imageWidth);
|
|
62
|
-
const originY = clamp(frameY * scaleY, 0, imageHeight);
|
|
63
|
-
const width = clamp(frameWidth * scaleX, 1, imageWidth - originX);
|
|
64
|
-
const height = clamp(frameHeight * scaleY, 1, imageHeight - originY);
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
originX: Math.round(originX),
|
|
68
|
-
originY: Math.round(originY),
|
|
69
|
-
width: Math.round(width),
|
|
70
|
-
height: Math.round(height),
|
|
71
|
-
};
|
|
72
|
-
};
|
|
17
|
+
import { commonStyles } from '../CommonStyles';
|
|
18
|
+
import {
|
|
19
|
+
request,
|
|
20
|
+
PERMISSIONS,
|
|
21
|
+
RESULTS,
|
|
22
|
+
openSettings,
|
|
23
|
+
} from 'react-native-permissions';
|
|
73
24
|
|
|
74
25
|
export default function CCCDCameraScreen(props) {
|
|
75
26
|
const insets = useSafeAreaInsets();
|
|
76
27
|
const navigation = useNavigation();
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const [
|
|
80
|
-
const
|
|
81
|
-
const [previewLayout, setPreviewLayout] = useState({
|
|
82
|
-
width: screenWidth,
|
|
83
|
-
height: screenHeight,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const format = useCameraFormat(device, [
|
|
87
|
-
{
|
|
88
|
-
photoAspectRatio: previewLayout.height / previewLayout.width,
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
videoAspectRatio: previewLayout.height / previewLayout.width,
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
photoResolution: 'max',
|
|
95
|
-
},
|
|
96
|
-
]);
|
|
97
|
-
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
if (!hasPermission) requestPermission();
|
|
100
|
-
}, [hasPermission, requestPermission]);
|
|
28
|
+
const isFocused = useIsFocused();
|
|
29
|
+
const myCamera = useRef(null);
|
|
30
|
+
const [passPermission, setPassPermission] = useState(false);
|
|
31
|
+
const [shouldRenderCamera, setShouldRenderCamera] = useState(false);
|
|
101
32
|
|
|
102
33
|
const takePicture = async () => {
|
|
103
|
-
if (
|
|
34
|
+
if (myCamera.current == null) return;
|
|
104
35
|
try {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const previewWidth = previewLayout.width;
|
|
118
|
-
const previewHeight = previewLayout.height;
|
|
119
|
-
|
|
120
|
-
const frameWidth = previewWidth * 0.85;
|
|
121
|
-
const frameHeight = frameWidth * 0.63;
|
|
122
|
-
const frameX = (previewWidth - frameWidth) / 2;
|
|
123
|
-
const frameY = (previewHeight - frameHeight) / 2;
|
|
124
|
-
|
|
125
|
-
const cropRect = getSnapshotCropRect({
|
|
126
|
-
imageWidth,
|
|
127
|
-
imageHeight,
|
|
128
|
-
previewWidth,
|
|
129
|
-
previewHeight,
|
|
130
|
-
frameX,
|
|
131
|
-
frameY,
|
|
132
|
-
frameWidth,
|
|
133
|
-
frameHeight,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const result = await RNImageManipulator.manipulate(
|
|
137
|
-
normalized.uri,
|
|
138
|
-
[
|
|
139
|
-
{
|
|
140
|
-
crop: cropRect,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
{ format: 'jpg', compress: 1 }
|
|
144
|
-
);
|
|
145
|
-
setCameraActive(false);
|
|
36
|
+
const options = {
|
|
37
|
+
base64: true,
|
|
38
|
+
pauseAfterCapture: true,
|
|
39
|
+
fixOrientation: false,
|
|
40
|
+
forceUpOrientation: false,
|
|
41
|
+
orientation: RNCamera.Constants.Orientation.portrait,
|
|
42
|
+
quality: 0.9,
|
|
43
|
+
pictureSize: '1280x720',
|
|
44
|
+
};
|
|
45
|
+
const data = await myCamera.current.takePictureAsync(options);
|
|
146
46
|
navigation.goBack();
|
|
147
47
|
if (props.route?.params?.callback) {
|
|
148
|
-
props.route.params.callback(
|
|
48
|
+
props.route.params.callback(data.uri);
|
|
149
49
|
}
|
|
150
50
|
} catch (err) {
|
|
151
51
|
console.error(err);
|
|
152
52
|
}
|
|
153
53
|
};
|
|
154
54
|
|
|
155
|
-
|
|
55
|
+
const requestPermissions = () => {
|
|
56
|
+
request(
|
|
57
|
+
Platform.OS === 'ios'
|
|
58
|
+
? PERMISSIONS.IOS.CAMERA
|
|
59
|
+
: PERMISSIONS.ANDROID.CAMERA
|
|
60
|
+
).then((result) => {
|
|
61
|
+
switch (result) {
|
|
62
|
+
case RESULTS.UNAVAILABLE:
|
|
63
|
+
console.log(
|
|
64
|
+
'This feature is not available (on this device / in this context)'
|
|
65
|
+
);
|
|
66
|
+
Alert.alert(
|
|
67
|
+
'Thông báo',
|
|
68
|
+
'Máy ảnh trên thiết bị không tương thích.\nVui lòng kiểm tra lại thiết bị!',
|
|
69
|
+
[{ text: 'Đồng ý' }]
|
|
70
|
+
);
|
|
71
|
+
break;
|
|
72
|
+
case RESULTS.DENIED:
|
|
73
|
+
console.log(
|
|
74
|
+
'The permission has not been requested / is denied but requestable'
|
|
75
|
+
);
|
|
76
|
+
Alert.alert(
|
|
77
|
+
'Thông báo',
|
|
78
|
+
'Bạn đã từ chối quyền máy ảnh. Vui lòng cấp quyền máy ảnh để tiếp tục!',
|
|
79
|
+
[
|
|
80
|
+
{
|
|
81
|
+
text: 'Đồng ý',
|
|
82
|
+
onPress: () => {
|
|
83
|
+
if (Platform.OS === 'ios') {
|
|
84
|
+
openSettings();
|
|
85
|
+
} else {
|
|
86
|
+
requestPermissions();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
]
|
|
91
|
+
);
|
|
92
|
+
break;
|
|
93
|
+
case RESULTS.LIMITED:
|
|
94
|
+
console.log('The permission is limited: some actions are possible');
|
|
95
|
+
Alert.alert(
|
|
96
|
+
'Thông báo',
|
|
97
|
+
'Quyền máy ảnh bị hạn chế. Vui lòng kiểm tra lại để tiếp tục!',
|
|
98
|
+
[
|
|
99
|
+
{
|
|
100
|
+
text: 'Đồng ý',
|
|
101
|
+
onPress: () => {
|
|
102
|
+
if (Platform.OS === 'ios') {
|
|
103
|
+
openSettings();
|
|
104
|
+
} else {
|
|
105
|
+
requestPermissions();
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
]
|
|
110
|
+
);
|
|
111
|
+
break;
|
|
112
|
+
case RESULTS.GRANTED:
|
|
113
|
+
console.log('The permission is granted');
|
|
114
|
+
setPassPermission(true);
|
|
115
|
+
break;
|
|
116
|
+
case RESULTS.BLOCKED:
|
|
117
|
+
console.log('The permission is denied and not requestable anymore');
|
|
118
|
+
Alert.alert(
|
|
119
|
+
'Thông báo',
|
|
120
|
+
'Bạn đã từ chối quyền máy ảnh. Vui lòng cấp quyền máy ảnh để tiếp tục!',
|
|
121
|
+
[
|
|
122
|
+
{
|
|
123
|
+
text: 'Đồng ý',
|
|
124
|
+
onPress: () => {
|
|
125
|
+
if (Platform.OS === 'ios') {
|
|
126
|
+
openSettings();
|
|
127
|
+
} else {
|
|
128
|
+
openSettings();
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
]
|
|
133
|
+
);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
requestPermissions();
|
|
141
|
+
}, []);
|
|
142
|
+
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
let timeout: NodeJS.Timeout;
|
|
145
|
+
if (isFocused) {
|
|
146
|
+
// Delay mounting camera to give Android time to release the previous one
|
|
147
|
+
timeout = setTimeout(() => {
|
|
148
|
+
setShouldRenderCamera(true);
|
|
149
|
+
}, 500); // thử 300ms–500ms nếu cần
|
|
150
|
+
} else {
|
|
151
|
+
setShouldRenderCamera(false);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return () => clearTimeout(timeout);
|
|
155
|
+
}, [isFocused]);
|
|
156
|
+
|
|
157
|
+
if (!passPermission && !shouldRenderCamera) {
|
|
156
158
|
return (
|
|
157
|
-
<View
|
|
158
|
-
|
|
159
|
-
flex: 1,
|
|
160
|
-
backgroundColor: '#000',
|
|
161
|
-
alignItems: 'center',
|
|
162
|
-
justifyContent: 'center',
|
|
163
|
-
}}
|
|
164
|
-
>
|
|
165
|
-
<MText style={{ color: '#fff' }}>
|
|
166
|
-
Vui lòng cấp quyền truy cập Camera
|
|
167
|
-
</MText>
|
|
159
|
+
<View style={commonStyles.fill}>
|
|
160
|
+
<ActivityIndicator size="large" color="#0000ff" />
|
|
168
161
|
</View>
|
|
169
162
|
);
|
|
170
|
-
|
|
171
|
-
const frameWidth = previewLayout.width * 0.85;
|
|
172
|
-
const frameHeight = frameWidth * 0.63;
|
|
173
|
-
const frameX = (previewLayout.width - frameWidth) / 2;
|
|
174
|
-
const frameY = (previewLayout.height - frameHeight) / 2;
|
|
163
|
+
}
|
|
175
164
|
|
|
176
165
|
return (
|
|
177
166
|
<View
|
|
178
|
-
style={
|
|
179
|
-
|
|
180
|
-
const { width, height } = e.nativeEvent.layout;
|
|
181
|
-
if (width > 0 && height > 0) setPreviewLayout({ width, height });
|
|
182
|
-
}}
|
|
167
|
+
style={{ flex: 1, backgroundColor: 'black' }}
|
|
168
|
+
pointerEvents={'box-none'}
|
|
183
169
|
>
|
|
184
|
-
<
|
|
185
|
-
style={
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
<
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
borderLeftWidth: CORNER_WIDTH,
|
|
211
|
-
borderColor: BORDER_COLOR,
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
|
|
215
|
-
{/* Top Right */}
|
|
216
|
-
<Corner
|
|
217
|
-
style={{
|
|
218
|
-
top: 0,
|
|
219
|
-
right: 0,
|
|
220
|
-
borderTopWidth: CORNER_WIDTH,
|
|
221
|
-
borderRightWidth: CORNER_WIDTH,
|
|
222
|
-
borderColor: BORDER_COLOR,
|
|
223
|
-
}}
|
|
224
|
-
/>
|
|
225
|
-
|
|
226
|
-
{/* Bottom Left */}
|
|
227
|
-
<Corner
|
|
228
|
-
style={{
|
|
229
|
-
bottom: 0,
|
|
230
|
-
left: 0,
|
|
231
|
-
borderBottomWidth: CORNER_WIDTH,
|
|
232
|
-
borderLeftWidth: CORNER_WIDTH,
|
|
233
|
-
borderColor: BORDER_COLOR,
|
|
234
|
-
}}
|
|
235
|
-
/>
|
|
236
|
-
|
|
237
|
-
{/* Bottom Right */}
|
|
238
|
-
<Corner
|
|
239
|
-
style={{
|
|
240
|
-
bottom: 0,
|
|
241
|
-
right: 0,
|
|
242
|
-
borderBottomWidth: CORNER_WIDTH,
|
|
243
|
-
borderRightWidth: CORNER_WIDTH,
|
|
244
|
-
borderColor: BORDER_COLOR,
|
|
245
|
-
}}
|
|
246
|
-
/>
|
|
247
|
-
</View>
|
|
248
|
-
<View
|
|
249
|
-
style={[$darkOverlaySide, { width: frameX, height: frameHeight }]}
|
|
250
|
-
/>
|
|
251
|
-
</View>
|
|
252
|
-
<View style={[$darkOverlayBottom, { height: frameY }]} />
|
|
170
|
+
<View
|
|
171
|
+
style={[
|
|
172
|
+
commonStyles.alignCenter,
|
|
173
|
+
commonStyles.fill,
|
|
174
|
+
commonStyles.justifyCenter,
|
|
175
|
+
{
|
|
176
|
+
position: 'absolute',
|
|
177
|
+
width: Dimensions.get('window').width,
|
|
178
|
+
height: Dimensions.get('window').height,
|
|
179
|
+
},
|
|
180
|
+
]}
|
|
181
|
+
>
|
|
182
|
+
<RNCamera
|
|
183
|
+
ref={myCamera}
|
|
184
|
+
defaultVideoQuality={RNCamera.Constants.VideoQuality['720p']}
|
|
185
|
+
style={{
|
|
186
|
+
width: Dimensions.get('window').width,
|
|
187
|
+
height: 260,
|
|
188
|
+
overflow: 'hidden',
|
|
189
|
+
}}
|
|
190
|
+
maxZoom={1}
|
|
191
|
+
>
|
|
192
|
+
{({ camera, status, recordAudioPermissionStatus }) => {
|
|
193
|
+
if (status !== 'READY') return <ActivityIndicator />;
|
|
194
|
+
}}
|
|
195
|
+
</RNCamera>
|
|
253
196
|
</View>
|
|
197
|
+
|
|
254
198
|
<View style={[$back, { top: insets.top + 16 }]}>
|
|
255
199
|
<TouchableOpacity
|
|
256
200
|
onPress={() => {
|
|
@@ -308,23 +252,6 @@ export default function CCCDCameraScreen(props) {
|
|
|
308
252
|
);
|
|
309
253
|
}
|
|
310
254
|
|
|
311
|
-
const CORNER_SIZE = 20;
|
|
312
|
-
const CORNER_WIDTH = 2;
|
|
313
|
-
const BORDER_COLOR = '#FDFDFD';
|
|
314
|
-
|
|
315
|
-
const Corner = ({ style }: { style: ViewStyle }) => (
|
|
316
|
-
<View
|
|
317
|
-
style={[
|
|
318
|
-
style,
|
|
319
|
-
{
|
|
320
|
-
position: 'absolute',
|
|
321
|
-
width: CORNER_SIZE,
|
|
322
|
-
height: CORNER_SIZE,
|
|
323
|
-
},
|
|
324
|
-
]}
|
|
325
|
-
/>
|
|
326
|
-
);
|
|
327
|
-
|
|
328
255
|
const overlayColor = 'rgba(22, 22, 22, 0.7)';
|
|
329
256
|
const $back: ViewStyle = {
|
|
330
257
|
position: 'absolute',
|
|
@@ -300,7 +300,7 @@ export const OCR = observer(function OCR(props: any) {
|
|
|
300
300
|
fixOrientation: false,
|
|
301
301
|
forceUpOrientation: false,
|
|
302
302
|
orientation: RNCamera.Constants.Orientation.portrait,
|
|
303
|
-
quality: 0.
|
|
303
|
+
quality: 0.9,
|
|
304
304
|
pictureSize: '1280x720',
|
|
305
305
|
};
|
|
306
306
|
const data = await myCamera.current.takePictureAsync(options);
|