1*dd9570b9SBartosz Kaszubowskiimport { BarCodeScanner, BarCodePoint, BarCodeBounds } from 'expo-barcode-scanner'; 2e331da1dSEvan Baconimport * as ScreenOrientation from 'expo-screen-orientation'; 3e331da1dSEvan Baconimport React from 'react'; 4e331da1dSEvan Baconimport { Button, Platform, StyleSheet, Text, View } from 'react-native'; 5e331da1dSEvan Baconimport * as Svg from 'react-native-svg'; 669185572SBartłomiej Bukowski 769185572SBartłomiej Bukowskiconst BUTTON_COLOR = Platform.OS === 'ios' ? '#fff' : '#666'; 869185572SBartłomiej Bukowski 991d99453SEvan Bacontype State = { 1069185572SBartłomiej Bukowski type: any; 11bd4c8242SŁukasz Kosmaty cornerPoints?: BarCodePoint[]; 1269185572SBartłomiej Bukowski alerting: boolean; 1369185572SBartłomiej Bukowski haveDimensions: boolean; 1469185572SBartłomiej Bukowski canvasHeight?: number; 1569185572SBartłomiej Bukowski canvasWidth?: number; 16bd4c8242SŁukasz Kosmaty boundingBox?: BarCodeBounds; 17bd4c8242SŁukasz Kosmaty cornerPointsString?: string; 18bd4c8242SŁukasz Kosmaty showBoundingBox: boolean; 19bd4c8242SŁukasz Kosmaty showText: boolean; 20bd4c8242SŁukasz Kosmaty data: string; 2169185572SBartłomiej Bukowski}; 2269185572SBartłomiej Bukowski 2391d99453SEvan Baconconst initialState: State = { 2469185572SBartłomiej Bukowski type: BarCodeScanner.Constants.Type.back, 2569185572SBartłomiej Bukowski alerting: false, 2669185572SBartłomiej Bukowski haveDimensions: false, 27bd4c8242SŁukasz Kosmaty showBoundingBox: false, 28bd4c8242SŁukasz Kosmaty data: '', 29bd4c8242SŁukasz Kosmaty showText: false, 3069185572SBartłomiej Bukowski}; 3169185572SBartłomiej Bukowski 3291d99453SEvan Baconfunction reducer(state: State, action: Partial<State>): State { 3391d99453SEvan Bacon return { 3491d99453SEvan Bacon ...state, 3591d99453SEvan Bacon ...action, 36e331da1dSEvan Bacon }; 3769185572SBartłomiej Bukowski} 3869185572SBartłomiej Bukowski 3991d99453SEvan Baconexport default function BarcodeScannerScreen() { 40*dd9570b9SBartosz Kaszubowski const [permission, requestPermission] = BarCodeScanner.usePermissions(); 4169185572SBartłomiej Bukowski 42972c2d8bSCedric van Putten if (!permission) { 43972c2d8bSCedric van Putten return null; 4469185572SBartłomiej Bukowski } 4569185572SBartłomiej Bukowski 46972c2d8bSCedric van Putten if (permission.granted) { 4791d99453SEvan Bacon return <BarcodeScannerExample />; 4891d99453SEvan Bacon } 4991d99453SEvan Bacon 50972c2d8bSCedric van Putten return ( 51972c2d8bSCedric van Putten <View style={[styles.container, { justifyContent: 'center', alignItems: 'center' }]}> 52972c2d8bSCedric van Putten <Text style={{ margin: 16 }}> 53972c2d8bSCedric van Putten You have not granted permission to use the camera on this device! 54972c2d8bSCedric van Putten </Text> 55972c2d8bSCedric van Putten <Button onPress={requestPermission} title="Grant permission" /> 56972c2d8bSCedric van Putten </View> 57972c2d8bSCedric van Putten ); 58972c2d8bSCedric van Putten} 59972c2d8bSCedric van Putten 6091d99453SEvan Baconfunction BarcodeScannerExample() { 6191d99453SEvan Bacon const [state, dispatch] = React.useReducer(reducer, initialState); 6291d99453SEvan Bacon 6391d99453SEvan Bacon let canChangeOrientation = false; 6491d99453SEvan Bacon 6591d99453SEvan Bacon const toggleAlertingAboutResult = () => { 6691d99453SEvan Bacon dispatch({ alerting: !state.alerting }); 6791d99453SEvan Bacon }; 6891d99453SEvan Bacon 6991d99453SEvan Bacon const toggleScreenOrientationState = () => { 7091d99453SEvan Bacon if (canChangeOrientation) { 7191d99453SEvan Bacon ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP); 7291d99453SEvan Bacon } else { 7391d99453SEvan Bacon ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.ALL); 7491d99453SEvan Bacon } 7591d99453SEvan Bacon canChangeOrientation = !canChangeOrientation; 7691d99453SEvan Bacon }; 7791d99453SEvan Bacon 7891d99453SEvan Bacon const setCanvasDimensions = ({ nativeEvent: { layout } }: any) => { 7991d99453SEvan Bacon dispatch({ canvasWidth: layout.width, canvasHeight: layout.height, haveDimensions: true }); 8091d99453SEvan Bacon }; 8191d99453SEvan Bacon 8291d99453SEvan Bacon const toggleType = () => { 8391d99453SEvan Bacon dispatch({ 8491d99453SEvan Bacon type: 8591d99453SEvan Bacon state.type === BarCodeScanner.Constants.Type.back 8691d99453SEvan Bacon ? BarCodeScanner.Constants.Type.front 8791d99453SEvan Bacon : BarCodeScanner.Constants.Type.back, 8891d99453SEvan Bacon }); 8991d99453SEvan Bacon }; 9091d99453SEvan Bacon 9191d99453SEvan Bacon const handleBarCodeScanned = (barCodeEvent: any) => { 9291d99453SEvan Bacon if (state.alerting) { 9391d99453SEvan Bacon requestAnimationFrame(() => { 9491d99453SEvan Bacon alert(JSON.stringify(barCodeEvent)); 9591d99453SEvan Bacon }); 9691d99453SEvan Bacon } 9791d99453SEvan Bacon dispatch({ 9891d99453SEvan Bacon data: barCodeEvent.data, 9991d99453SEvan Bacon cornerPoints: barCodeEvent.cornerPoints, 10091d99453SEvan Bacon boundingBox: barCodeEvent.bounds, 10191d99453SEvan Bacon cornerPointsString: getPointsString(barCodeEvent.cornerPoints), 10291d99453SEvan Bacon }); 10391d99453SEvan Bacon }; 10491d99453SEvan Bacon 10591d99453SEvan Bacon const toggleText = () => dispatch({ showText: !state.showText }); 10691d99453SEvan Bacon 10791d99453SEvan Bacon const toggleBoundingBox = () => dispatch({ showBoundingBox: !state.showBoundingBox }); 10891d99453SEvan Bacon 10991d99453SEvan Bacon const getPointsString = (barCodePoints?: BarCodePoint[]): string | undefined => { 11091d99453SEvan Bacon if (!barCodePoints) { 11191d99453SEvan Bacon return; 11291d99453SEvan Bacon } 11391d99453SEvan Bacon return barCodePoints.map(({ x, y }) => `${Math.round(x)},${Math.round(y)}`).join(' '); 11491d99453SEvan Bacon }; 11591d99453SEvan Bacon 116cf13b9bdSŁukasz Kosmaty const circles = (state.cornerPoints || []).map((point, index) => ( 117cf13b9bdSŁukasz Kosmaty <Svg.Circle 118cf13b9bdSŁukasz Kosmaty cx={point.x} 119cf13b9bdSŁukasz Kosmaty cy={point.y} 120cf13b9bdSŁukasz Kosmaty r={3} 121cf13b9bdSŁukasz Kosmaty strokeWidth={0.5} 122cf13b9bdSŁukasz Kosmaty stroke="#CF4048" 123cf13b9bdSŁukasz Kosmaty fill="#CF4048" 124cf13b9bdSŁukasz Kosmaty key={index} 125cf13b9bdSŁukasz Kosmaty /> 126cf13b9bdSŁukasz Kosmaty )); 12769185572SBartłomiej Bukowski 12869185572SBartłomiej Bukowski return ( 12969185572SBartłomiej Bukowski <View style={styles.container}> 13069185572SBartłomiej Bukowski <BarCodeScanner 13191d99453SEvan Bacon onLayout={setCanvasDimensions} 13291d99453SEvan Bacon onBarCodeScanned={handleBarCodeScanned} 13369185572SBartłomiej Bukowski barCodeTypes={[ 13469185572SBartłomiej Bukowski BarCodeScanner.Constants.BarCodeType.qr, 13569185572SBartłomiej Bukowski BarCodeScanner.Constants.BarCodeType.pdf417, 13669185572SBartłomiej Bukowski BarCodeScanner.Constants.BarCodeType.code128, 1371f9c336aSBartłomiej Bukowski BarCodeScanner.Constants.BarCodeType.code39, 13869185572SBartłomiej Bukowski ]} 13991d99453SEvan Bacon type={state.type} 14069185572SBartłomiej Bukowski style={styles.preview} 14169185572SBartłomiej Bukowski /> 14269185572SBartłomiej Bukowski 14391d99453SEvan Bacon {state.haveDimensions && ( 14491d99453SEvan Bacon <Svg.Svg height={state.canvasHeight} width={state.canvasWidth} style={styles.svg}> 14569185572SBartłomiej Bukowski <Svg.Circle 14691d99453SEvan Bacon cx={state.canvasWidth! / 2} 14791d99453SEvan Bacon cy={state.canvasHeight! / 2} 14869185572SBartłomiej Bukowski r={2} 14969185572SBartłomiej Bukowski strokeWidth={2.5} 15069185572SBartłomiej Bukowski stroke="#e74c3c" 15169185572SBartłomiej Bukowski fill="#f1c40f" 15269185572SBartłomiej Bukowski /> 15391d99453SEvan Bacon {state.showBoundingBox && state.cornerPointsString && ( 154bd4c8242SŁukasz Kosmaty <Svg.Polygon 15591d99453SEvan Bacon points={state.cornerPointsString} 15669185572SBartłomiej Bukowski strokeWidth={2} 157bd4c8242SŁukasz Kosmaty stroke="#582E6E" 15869185572SBartłomiej Bukowski fill="none" 15969185572SBartłomiej Bukowski /> 16069185572SBartłomiej Bukowski )} 16191d99453SEvan Bacon {state.showText && state.boundingBox && ( 162bd4c8242SŁukasz Kosmaty <Svg.Text 163bd4c8242SŁukasz Kosmaty fill="#CF4048" 164bd4c8242SŁukasz Kosmaty stroke="#CF4048" 165bd4c8242SŁukasz Kosmaty fontSize="14" 16691d99453SEvan Bacon x={state.boundingBox.origin.x} 16791d99453SEvan Bacon y={state.boundingBox.origin.y - 8}> 16891d99453SEvan Bacon {state.data} 169bd4c8242SŁukasz Kosmaty </Svg.Text> 170bd4c8242SŁukasz Kosmaty )} 171bd4c8242SŁukasz Kosmaty 17269185572SBartłomiej Bukowski {circles} 1736e2bfc6bSTomasz Sapeta </Svg.Svg> 17469185572SBartłomiej Bukowski )} 17569185572SBartłomiej Bukowski 17669185572SBartłomiej Bukowski <View style={styles.toolbar}> 17791d99453SEvan Bacon <Button color={BUTTON_COLOR} title="Direction" onPress={toggleType} /> 17891d99453SEvan Bacon <Button color={BUTTON_COLOR} title="Orientation" onPress={toggleScreenOrientationState} /> 179972c2d8bSCedric van Putten <Button 180972c2d8bSCedric van Putten title="Bounding box" 181972c2d8bSCedric van Putten onPress={toggleBoundingBox} 182972c2d8bSCedric van Putten color={state.showBoundingBox ? undefined : BUTTON_COLOR} 183972c2d8bSCedric van Putten /> 184972c2d8bSCedric van Putten <Button 185972c2d8bSCedric van Putten title="Text" 186972c2d8bSCedric van Putten onPress={toggleText} 187972c2d8bSCedric van Putten color={state.showText ? undefined : BUTTON_COLOR} 188972c2d8bSCedric van Putten /> 189972c2d8bSCedric van Putten <Button 190972c2d8bSCedric van Putten title="Alerting" 191972c2d8bSCedric van Putten onPress={toggleAlertingAboutResult} 192972c2d8bSCedric van Putten color={state.alerting ? undefined : BUTTON_COLOR} 193972c2d8bSCedric van Putten /> 19469185572SBartłomiej Bukowski </View> 19569185572SBartłomiej Bukowski </View> 19669185572SBartłomiej Bukowski ); 19769185572SBartłomiej Bukowski} 19869185572SBartłomiej Bukowski 19991d99453SEvan BaconBarcodeScannerExample.navigationOptions = { 20091d99453SEvan Bacon title: '<BarCodeScanner />', 201bd4c8242SŁukasz Kosmaty}; 202bd4c8242SŁukasz Kosmaty 20369185572SBartłomiej Bukowskiconst styles = StyleSheet.create({ 20469185572SBartłomiej Bukowski container: { 20569185572SBartłomiej Bukowski flex: 1, 20669185572SBartłomiej Bukowski }, 20769185572SBartłomiej Bukowski preview: { 20869185572SBartłomiej Bukowski ...StyleSheet.absoluteFillObject, 20969185572SBartłomiej Bukowski backgroundColor: 'black', 21069185572SBartłomiej Bukowski }, 21169185572SBartłomiej Bukowski toolbar: { 21269185572SBartłomiej Bukowski position: 'absolute', 21369185572SBartłomiej Bukowski bottom: 0, 21469185572SBartłomiej Bukowski left: 0, 21569185572SBartłomiej Bukowski right: 0, 21669185572SBartłomiej Bukowski paddingVertical: 10, 21769185572SBartłomiej Bukowski paddingHorizontal: 10, 21869185572SBartłomiej Bukowski flexDirection: 'row', 21969185572SBartłomiej Bukowski justifyContent: 'space-between', 22069185572SBartłomiej Bukowski backgroundColor: 'rgba(255,255,255,0.2)', 22169185572SBartłomiej Bukowski }, 22269185572SBartłomiej Bukowski svg: { 22369185572SBartłomiej Bukowski position: 'absolute', 22469185572SBartłomiej Bukowski borderWidth: 2, 22569185572SBartłomiej Bukowski borderColor: 'red', 22669185572SBartłomiej Bukowski }, 22769185572SBartłomiej Bukowski}); 228