|
@@ -1,15 +1,16 @@
|
1
|
1
|
// @flow
|
2
|
2
|
|
3
|
3
|
import * as React from 'react';
|
4
|
|
-import {Linking, StyleSheet, View} from "react-native";
|
|
4
|
+import {Linking, Platform, StyleSheet, View} from "react-native";
|
5
|
5
|
import {Button, Text, withTheme} from 'react-native-paper';
|
6
|
|
-import {BarCodeScanner} from "expo-barcode-scanner";
|
7
|
|
-import {Camera} from 'expo-camera';
|
|
6
|
+import {RNCamera} from 'react-native-camera';
|
|
7
|
+import {BarcodeMask} from '@nartc/react-native-barcode-mask';
|
8
|
8
|
import URLHandler from "../../utils/URLHandler";
|
9
|
9
|
import AlertDialog from "../../components/Dialogs/AlertDialog";
|
10
|
10
|
import i18n from 'i18n-js';
|
11
|
11
|
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
|
12
|
12
|
import LoadingConfirmDialog from "../../components/Dialogs/LoadingConfirmDialog";
|
|
13
|
+import {PERMISSIONS, request, RESULTS} from 'react-native-permissions';
|
13
|
14
|
|
14
|
15
|
type Props = {};
|
15
|
16
|
type State = {
|
|
@@ -40,9 +41,14 @@ class ScannerScreen extends React.Component<Props, State> {
|
40
|
41
|
this.requestPermissions();
|
41
|
42
|
}
|
42
|
43
|
|
43
|
|
- requestPermissions = () => Camera.requestPermissionsAsync().then(this.updatePermissionStatus);
|
|
44
|
+ requestPermissions = () => {
|
|
45
|
+ if (Platform.OS === 'android')
|
|
46
|
+ request(PERMISSIONS.ANDROID.CAMERA).then(this.updatePermissionStatus)
|
|
47
|
+ else
|
|
48
|
+ request(PERMISSIONS.IOS.CAMERA).then(this.updatePermissionStatus)
|
|
49
|
+ };
|
44
|
50
|
|
45
|
|
- updatePermissionStatus = ({status}) => this.setState({hasPermission: status === "granted"});
|
|
51
|
+ updatePermissionStatus = (result) => this.setState({hasPermission: result === RESULTS.GRANTED});
|
46
|
52
|
|
47
|
53
|
handleCodeScanned = ({type, data}) => {
|
48
|
54
|
if (!URLHandler.isUrlValid(data))
|
|
@@ -71,36 +77,6 @@ class ScannerScreen extends React.Component<Props, State> {
|
71
|
77
|
</View>
|
72
|
78
|
}
|
73
|
79
|
|
74
|
|
- getOverlay() {
|
75
|
|
- return (
|
76
|
|
- <View style={{flex: 1}}>
|
77
|
|
- <View style={{flex: 1}}>
|
78
|
|
- <View style={{...overlayBackground, top: 0, height: '10%', width: '80%', left: '10%'}}/>
|
79
|
|
- <View style={{...overlayBackground, left: 0, width: '10%', height: '100%'}}/>
|
80
|
|
- <View style={{...overlayBackground, right: 0, width: '10%', height: '100%'}}/>
|
81
|
|
- <View style={{...overlayBackground, bottom: 0, height: '10%', width: '80%', left: '10%'}}/>
|
82
|
|
- </View>
|
83
|
|
-
|
84
|
|
- <View style={styles.overlayTopLeft}>
|
85
|
|
- <View style={{...overlayHorizontalLineStyle, top: 0}}/>
|
86
|
|
- <View style={{...overlayVerticalLineStyle, left: 0}}/>
|
87
|
|
- </View>
|
88
|
|
- <View style={styles.overlayTopRight}>
|
89
|
|
- <View style={{...overlayHorizontalLineStyle, top: 0}}/>
|
90
|
|
- <View style={{...overlayVerticalLineStyle, right: 0}}/>
|
91
|
|
- </View>
|
92
|
|
- <View style={styles.overlayBottomLeft}>
|
93
|
|
- <View style={{...overlayHorizontalLineStyle, bottom: 0}}/>
|
94
|
|
- <View style={{...overlayVerticalLineStyle, left: 0}}/>
|
95
|
|
- </View>
|
96
|
|
- <View style={styles.overlayBottomRight}>
|
97
|
|
- <View style={{...overlayHorizontalLineStyle, bottom: 0}}/>
|
98
|
|
- <View style={{...overlayVerticalLineStyle, right: 0}}/>
|
99
|
|
- </View>
|
100
|
|
- </View>
|
101
|
|
- );
|
102
|
|
- }
|
103
|
|
-
|
104
|
80
|
showHelpDialog = () => {
|
105
|
81
|
this.setState({
|
106
|
82
|
dialogVisible: true,
|
|
@@ -133,19 +109,22 @@ class ScannerScreen extends React.Component<Props, State> {
|
133
|
109
|
|
134
|
110
|
getScanner() {
|
135
|
111
|
return (
|
136
|
|
- <View style={styles.cameraContainer}>
|
137
|
|
- <Camera
|
138
|
|
- onBarCodeScanned={this.state.scanned ? undefined : this.handleCodeScanned}
|
139
|
|
- type={Camera.Constants.Type.back}
|
140
|
|
- barCodeScannerSettings={{
|
141
|
|
- barCodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
|
142
|
|
- }}
|
143
|
|
- style={StyleSheet.absoluteFill}
|
144
|
|
- ratio={'1:1'}
|
145
|
|
- >
|
146
|
|
- {this.getOverlay()}
|
147
|
|
- </Camera>
|
148
|
|
- </View>
|
|
112
|
+ <RNCamera
|
|
113
|
+ onBarCodeRead={this.state.scanned ? undefined : this.handleCodeScanned}
|
|
114
|
+ type={RNCamera.Constants.Type.back}
|
|
115
|
+ barCodeScannerSettings={{
|
|
116
|
+ barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
|
|
117
|
+ }}
|
|
118
|
+ style={StyleSheet.absoluteFill}
|
|
119
|
+ captureAudio={false}
|
|
120
|
+ >
|
|
121
|
+ <BarcodeMask
|
|
122
|
+ backgroundColor={"#000"}
|
|
123
|
+ maskOpacity={0.5}
|
|
124
|
+ animatedLineThickness={1}
|
|
125
|
+ animationDuration={1000}
|
|
126
|
+ />
|
|
127
|
+ </RNCamera>
|
149
|
128
|
);
|
150
|
129
|
}
|
151
|
130
|
|
|
@@ -153,22 +132,20 @@ class ScannerScreen extends React.Component<Props, State> {
|
153
|
132
|
return (
|
154
|
133
|
<View style={{
|
155
|
134
|
...styles.container,
|
156
|
|
- marginBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
|
|
135
|
+ marginBottom: CustomTabBar.TAB_BAR_HEIGHT
|
157
|
136
|
}}>
|
158
|
|
- {this.state.hasPermission
|
159
|
|
- ? this.getScanner()
|
160
|
|
- : this.getPermissionScreen()
|
161
|
|
- }
|
162
|
|
- <View style={{height: 50}}>
|
163
|
|
- <Button
|
164
|
|
- icon="information"
|
165
|
|
- mode="contained"
|
166
|
|
- onPress={this.showHelpDialog}
|
167
|
|
- style={styles.button}
|
168
|
|
- >
|
169
|
|
- {i18n.t("scannerScreen.helpButton")}
|
170
|
|
- </Button>
|
171
|
|
- </View>
|
|
137
|
+ {this.state.hasPermission
|
|
138
|
+ ? this.getScanner()
|
|
139
|
+ : this.getPermissionScreen()
|
|
140
|
+ }
|
|
141
|
+ <Button
|
|
142
|
+ icon="information"
|
|
143
|
+ mode="contained"
|
|
144
|
+ onPress={this.showHelpDialog}
|
|
145
|
+ style={styles.button}
|
|
146
|
+ >
|
|
147
|
+ {i18n.t("scannerScreen.helpButton")}
|
|
148
|
+ </Button>
|
172
|
149
|
<AlertDialog
|
173
|
150
|
visible={this.state.dialogVisible}
|
174
|
151
|
onDismiss={this.onDialogDismiss}
|
|
@@ -185,74 +162,17 @@ class ScannerScreen extends React.Component<Props, State> {
|
185
|
162
|
}
|
186
|
163
|
}
|
187
|
164
|
|
188
|
|
-const borderOffset = '10%';
|
189
|
|
-
|
190
|
|
-const overlayBoxStyle = {
|
191
|
|
- position: 'absolute',
|
192
|
|
- width: 25,
|
193
|
|
- height: 25,
|
194
|
|
-};
|
195
|
|
-
|
196
|
|
-const overlayLineStyle = {
|
197
|
|
- position: 'absolute',
|
198
|
|
- backgroundColor: "#fff",
|
199
|
|
- borderRadius: 2,
|
200
|
|
-};
|
201
|
|
-
|
202
|
|
-const overlayHorizontalLineStyle = {
|
203
|
|
- ...overlayLineStyle,
|
204
|
|
- width: '100%',
|
205
|
|
- height: 5,
|
206
|
|
-};
|
207
|
|
-
|
208
|
|
-const overlayVerticalLineStyle = {
|
209
|
|
- ...overlayLineStyle,
|
210
|
|
- height: '100%',
|
211
|
|
- width: 5,
|
212
|
|
-};
|
213
|
|
-
|
214
|
|
-const overlayBackground = {
|
215
|
|
- backgroundColor: "rgba(0,0,0,0.47)",
|
216
|
|
- position: "absolute",
|
217
|
|
-};
|
218
|
|
-
|
219
|
165
|
const styles = StyleSheet.create({
|
220
|
166
|
container: {
|
221
|
167
|
flex: 1,
|
222
|
168
|
justifyContent: 'center',
|
223
|
169
|
},
|
224
|
|
- cameraContainer: {
|
225
|
|
- marginTop: 'auto',
|
226
|
|
- marginBottom: 'auto',
|
227
|
|
- aspectRatio: 1,
|
228
|
|
- width: '100%',
|
229
|
|
- },
|
230
|
170
|
button: {
|
231
|
171
|
position: 'absolute',
|
232
|
|
- bottom: 5,
|
|
172
|
+ bottom: 20,
|
233
|
173
|
width: '80%',
|
234
|
174
|
left: '10%'
|
235
|
175
|
},
|
236
|
|
- overlayTopLeft: {
|
237
|
|
- ...overlayBoxStyle,
|
238
|
|
- top: borderOffset,
|
239
|
|
- left: borderOffset,
|
240
|
|
- },
|
241
|
|
- overlayTopRight: {
|
242
|
|
- ...overlayBoxStyle,
|
243
|
|
- top: borderOffset,
|
244
|
|
- right: borderOffset,
|
245
|
|
- },
|
246
|
|
- overlayBottomLeft: {
|
247
|
|
- ...overlayBoxStyle,
|
248
|
|
- bottom: borderOffset,
|
249
|
|
- left: borderOffset,
|
250
|
|
- },
|
251
|
|
- overlayBottomRight: {
|
252
|
|
- ...overlayBoxStyle,
|
253
|
|
- bottom: borderOffset,
|
254
|
|
- right: borderOffset,
|
255
|
|
- },
|
256
|
176
|
});
|
257
|
177
|
|
258
|
178
|
export default withTheme(ScannerScreen);
|