WIP: Moves camera setting to Settings screen

This commit is contained in:
Aaron Louie 2020-09-04 17:50:50 -04:00
parent ede1783ed9
commit 3eef273701
6 changed files with 83 additions and 54 deletions

40
App.tsx
View File

@ -6,17 +6,17 @@ import {BarCodeEvent, BarCodeScanner, PermissionResponse} from 'expo-barcode-sca
import * as firebase from 'firebase'; import * as firebase from 'firebase';
import 'firebase/firestore'; import 'firebase/firestore';
import React, {ReactElement, useCallback, useEffect, useState} from 'react'; import React, {ReactElement, useCallback, useEffect, useState} from 'react';
import {AppRegistry, SafeAreaView, View, YellowBox} from 'react-native'; import {AppRegistry, SafeAreaView, Text, View, YellowBox} from 'react-native';
import { import {
Appbar, Appbar,
Button, Button,
DefaultTheme, DefaultTheme,
HelperText, HelperText,
Provider as PaperProvider, Provider as PaperProvider, RadioButton,
Snackbar, Snackbar,
Subheading, Subheading,
TextInput, TextInput,
Title Title,
} from 'react-native-paper'; } from 'react-native-paper';
import {expo as appExpo} from './app.json'; import {expo as appExpo} from './app.json';
import {CancelButton} from './components/Common'; import {CancelButton} from './components/Common';
@ -24,7 +24,7 @@ import {BarCodeDisplay, PrintButton, PrintingMessage} from './components/Print';
import {IdNumberInput, InputIdButton, ScanButton, Scanner} from './components/Scan'; import {IdNumberInput, InputIdButton, ScanButton, Scanner} from './components/Scan';
import {colors, styles} from './components/Styles'; import {colors, styles} from './components/Styles';
import {BarcodeScannerAppState} from './models/BarcodeScannerAppState'; import {BarcodeScannerAppState} from './models/BarcodeScannerAppState';
import {ElementProps, StateProps} from './models/ElementProps'; import {CameraType, ElementProps, StateProps} from './models/ElementProps';
import {Sample} from './models/Sample'; import {Sample} from './models/Sample';
const firebaseConfig = { const firebaseConfig = {
@ -44,6 +44,7 @@ if (firebase.apps.length === 0) {
YellowBox.ignoreWarnings([ YellowBox.ignoreWarnings([
'Setting a timer for a long period of time', // Ignore Firebase timer warnings 'Setting a timer for a long period of time', // Ignore Firebase timer warnings
'Remote debugger is in a background tab', // Ignore Firebase timer warnings
]); ]);
const db = firebase.firestore(); const db = firebase.firestore();
@ -62,6 +63,7 @@ export default function Main() {
const [locationStr, setLocationStr] = useState<string>('4321'); const [locationStr, setLocationStr] = useState<string>('4321');
const [errorMessage, setErrorMessage] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string>('');
const [samples, setSamples] = useState<Sample[]>([]); const [samples, setSamples] = useState<Sample[]>([]);
const [cameraType, setCameraType] = useState<CameraType>('back');
useEffect(() => { useEffect(() => {
BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => { BarCodeScanner.requestPermissionsAsync().then((value: PermissionResponse) => {
@ -110,6 +112,7 @@ export default function Main() {
// Manually-entered ID numbers will be exactly 9 digits long. // Manually-entered ID numbers will be exactly 9 digits long.
const barCodeString = e.data; const barCodeString = e.data;
const pattern = /^[\d]{14}$|^[\d]{9}$/; const pattern = /^[\d]{14}$|^[\d]{9}$/;
console.log('barCodeString', barCodeString);
if (pattern.test(barCodeString)) { if (pattern.test(barCodeString)) {
const cardId = e.data.slice(0, 9); const cardId = e.data.slice(0, 9);
const newSampleDate = new Date(); const newSampleDate = new Date();
@ -168,13 +171,38 @@ export default function Main() {
function SettingsScreen(props: ElementProps): ReactElement { function SettingsScreen(props: ElementProps): ReactElement {
const [inputStr, setInputStr] = useState<string>(locationStr); const [inputStr, setInputStr] = useState<string>(locationStr);
const pattern = /^[\d]{4}$/; const pattern = /^[\d]{4}$/;
const hasErrors = () => { const hasErrors = () => {
return !pattern.test(inputStr); return !pattern.test(inputStr);
}; };
return <View style={styles.settings}> return <View style={styles.settings}>
<Title style={styles.headingInverse}>Settings</Title> <View style={{marginBottom: 10}}>
<Subheading style={{color: DefaultTheme.colors.text}}>Which camera to scan bar codes with?</Subheading>
<RadioButton.Group
onValueChange={value => setCameraType(value as CameraType)}
value={cameraType as string}
>
<View style={styles.row}>
<Text>Front</Text>
<RadioButton
value="front"
color={colors.primary}
uncheckedColor={colors.accent}
/>
</View>
<View style={styles.row}>
<Text>Back</Text>
<RadioButton
value="back"
color={colors.primary}
uncheckedColor={colors.accent}
/>
</View>
</RadioButton.Group>
</View>
<View style={{marginBottom: 10}}> <View style={{marginBottom: 10}}>
<Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}> <Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}>
Please do NOT change this unless you know what you are doing. Entering an incorrect location number may Please do NOT change this unless you know what you are doing. Entering an incorrect location number may
@ -264,11 +292,13 @@ export default function Main() {
return <Scanner return <Scanner
onScanned={handleBarCodeScanned} onScanned={handleBarCodeScanned}
onCancel={_home} onCancel={_home}
cameraType={cameraType}
/>; />;
case BarcodeScannerAppState.INPUT: case BarcodeScannerAppState.INPUT:
return <IdNumberInput return <IdNumberInput
onScanned={handleBarCodeScanned} onScanned={handleBarCodeScanned}
onCancel={_home} onCancel={_home}
cameraType={undefined}
/>; />;
case BarcodeScannerAppState.SETTINGS: case BarcodeScannerAppState.SETTINGS:
return <SettingsScreen/>; return <SettingsScreen/>;

View File

@ -4,7 +4,7 @@
"name": "uva-covid19-testing-kiosk", "name": "uva-covid19-testing-kiosk",
"slug": "uva-covid19-testing-kiosk", "slug": "uva-covid19-testing-kiosk",
"version": "1.0.0", "version": "1.0.0",
"orientation": "portrait", "orientation": "landscape",
"icon": "./assets/icon.png", "icon": "./assets/icon.png",
"splash": { "splash": {
"image": "./assets/splash.png", "image": "./assets/splash.png",
@ -19,7 +19,8 @@
], ],
"ios": { "ios": {
"supportsTablet": true, "supportsTablet": true,
"bundleIdentifier": "com.sartography.uvacovid19testingkiosk" "bundleIdentifier": "com.sartography.uvacovid19testingkiosk",
"requireFullScreen": true
}, },
"web": { "web": {
"favicon": "./assets/favicon.png" "favicon": "./assets/favicon.png"
@ -34,4 +35,4 @@
"package": "com.sartography.uvacovid19testingkiosk" "package": "com.sartography.uvacovid19testingkiosk"
} }
} }
} }

View File

@ -5,52 +5,32 @@ import {Button, DefaultTheme, HelperText, Subheading, TextInput, Title} from 're
import {ButtonProps, ScannerProps} from '../models/ElementProps'; import {ButtonProps, ScannerProps} from '../models/ElementProps';
import {colors, styles} from './Styles'; import {colors, styles} from './Styles';
declare type CameraType = number | 'front' | 'back' | undefined;
export const Scanner = (props: ScannerProps): ReactElement => { export const Scanner = (props: ScannerProps): ReactElement => {
const [componentKey, setComponentKey] = useState<number>(0); return <View style={styles.container}>
const [cameraType, setCameraType] = useState<CameraType>('back'); <View style={styles.container}>
<BarCodeScanner
const _toggleCameraType = () => { type={props.cameraType}
setCameraType(cameraType === 'front' ? 'back' : 'front'); onBarCodeScanned={props.onScanned}
setComponentKey(componentKey + 1); style={styles.fullScreen}
} />
</View>
const ScanCamera = (): ReactElement => { <View style={styles.centerMiddle}>
return <View style={styles.container}> <View style={styles.captureBox}/>
<View style={styles.container}> </View>
<BarCodeScanner <Text style={styles.subtitle}>
type={cameraType} Hold your ID card up, with the barcode facing the camera. Keep the card in the green box.
onBarCodeScanned={props.onScanned} </Text>
style={styles.fullScreen} <View style={styles.centerMiddle}>
/> <Button
</View> mode="text"
<View style={styles.centerMiddle}> color={colors.primary}
<View style={styles.captureBox}/> icon="cancel"
</View> onPress={props.onCancel}
<Text style={styles.subtitle}> style={styles.btnWhite}
Hold your ID card up, with the barcode facing the camera. Keep the card in the green box. >Cancel</Button>
</Text> </View>
<View style={styles.centerMiddle}> </View>;
<Button
mode="contained"
color={colors.primary}
icon="camera-switch"
onPress={_toggleCameraType}
style={{marginVertical: 10}}
>Switch Camera</Button>
<Button
mode="text"
color={colors.primary}
icon="cancel"
onPress={props.onCancel}
style={styles.btnWhite}
>Cancel</Button>
</View>
</View>;
}
return <ScanCamera key={componentKey}/>;
}; };
export const ScanButton = (props: ButtonProps): ReactElement => { export const ScanButton = (props: ButtonProps): ReactElement => {
@ -70,6 +50,7 @@ export const InputIdButton = (props: ButtonProps): ReactElement => {
mode="text" mode="text"
color={colors.onBackground} color={colors.onBackground}
onPress={props.onClicked} onPress={props.onClicked}
style={{marginTop: 30}}
>Enter ID Number Manually</Button>; >Enter ID Number Manually</Button>;
}; };
@ -85,7 +66,7 @@ export const IdNumberInput = (props: ScannerProps): ReactElement => {
} }
return <View style={styles.settings}> return <View style={styles.settings}>
<Title style={styles.headingInverse}>Settings</Title> <Title style={styles.headingInverse}>Manual ID # Entry</Title>
<View style={{marginBottom: 10}}> <View style={{marginBottom: 10}}>
<Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}> <Subheading style={{color: DefaultTheme.colors.text, marginBottom: 60}}>
Please double check that you have entered the number correctly. Entering an incorrect ID number will prevent Please double check that you have entered the number correctly. Entering an incorrect ID number will prevent

View File

@ -1,6 +1,9 @@
import {BarCodeScannedCallback} from 'expo-barcode-scanner'; import {BarCodeScannedCallback} from 'expo-barcode-scanner';
import {BarcodeScannerAppState} from './BarcodeScannerAppState'; import {BarcodeScannerAppState} from './BarcodeScannerAppState';
export declare type CameraType = number | 'front' | 'back' | undefined;
export declare type CheckedStatus ='checked' | 'unchecked' | undefined;
export interface ElementProps { export interface ElementProps {
title?: string; title?: string;
} }
@ -23,6 +26,7 @@ export interface ButtonProps extends ElementProps {
export interface ScannerProps extends ElementProps { export interface ScannerProps extends ElementProps {
onScanned: BarCodeScannedCallback; onScanned: BarCodeScannedCallback;
onCancel: () => void; onCancel: () => void;
cameraType: CameraType;
} }
export interface PrintingProps extends BarCodeProps { export interface PrintingProps extends BarCodeProps {

View File

@ -12,6 +12,7 @@
"expo": "~38.0.8", "expo": "~38.0.8",
"expo-barcode-scanner": "~8.2.1", "expo-barcode-scanner": "~8.2.1",
"expo-print": "~9.0.1", "expo-print": "~9.0.1",
"expo-screen-orientation": "~1.1.1",
"expo-splash-screen": "^0.5.0", "expo-splash-screen": "^0.5.0",
"expo-status-bar": "^1.0.2", "expo-status-bar": "^1.0.2",
"expo-updates": "~0.2.10", "expo-updates": "~0.2.10",

View File

@ -4334,6 +4334,13 @@ expo-print@~9.0.1:
resolved "https://registry.yarnpkg.com/expo-print/-/expo-print-9.0.2.tgz#1138bbc0dc94799962980cdc9c09475ba4943d4d" resolved "https://registry.yarnpkg.com/expo-print/-/expo-print-9.0.2.tgz#1138bbc0dc94799962980cdc9c09475ba4943d4d"
integrity sha512-Jk8Q4QOdkCGY4zqr+omLMnsX5FPQYz6Ug2TfUeAixwPfJuNuGUPPvWiQhucxV4idS0C1nHh4HAXj+S27zDZwig== integrity sha512-Jk8Q4QOdkCGY4zqr+omLMnsX5FPQYz6Ug2TfUeAixwPfJuNuGUPPvWiQhucxV4idS0C1nHh4HAXj+S27zDZwig==
expo-screen-orientation@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/expo-screen-orientation/-/expo-screen-orientation-1.1.1.tgz#515776e534530efdb716e56ec0c47cf8fb9de82f"
integrity sha512-o3RhmidIhVK4lXHVActnO2iD0ZrZKxzWuRrJaTSpRsvRjCabeE74xkpZWPGcEcXhAxEwMaAAizHO8rlJDdrVzw==
dependencies:
fbjs "1.0.0"
expo-splash-screen@^0.5.0: expo-splash-screen@^0.5.0:
version "0.5.0" version "0.5.0"
resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.5.0.tgz#cad0eb77a3eade2c7101d169b8655e7ee8053c2f" resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.5.0.tgz#cad0eb77a3eade2c7101d169b8655e7ee8053c2f"
@ -7589,7 +7596,12 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qrcode@^1.3.2: qrcode-svg@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/qrcode-svg/-/qrcode-svg-1.1.0.tgz#2087549843dc5d0a3f8e8aa046cd9bcf23708cc3"
integrity sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==
qrcode@^1.3.2, qrcode@^1.4.4:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"
integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==