-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/main' into bugfix/require-pin
- Loading branch information
Showing
48 changed files
with
2,179 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import React, { useEffect } from 'react' | ||
import { Image } from 'react-native' | ||
import Animated, { | ||
useSharedValue, | ||
useAnimatedStyle, | ||
withRepeat, | ||
withTiming, | ||
} from 'react-native-reanimated' | ||
import Box from './Box' | ||
|
||
const SCANNER_SIZE = 300 | ||
const SCANNER_LINE_HEIGHT = 43 | ||
const SCAN_DURATION = 2000 | ||
const BORDER_SEGMENT_SIZE = 40 | ||
export const CameraScannerLayout = () => { | ||
const linePosition = useSharedValue<number>(-SCANNER_LINE_HEIGHT) | ||
const animatedStyle = useAnimatedStyle(() => ({ | ||
transform: [{ translateY: linePosition.value }], | ||
})) | ||
|
||
useEffect(() => { | ||
linePosition.value = withRepeat( | ||
withTiming(SCANNER_SIZE, { | ||
duration: SCAN_DURATION, | ||
}), | ||
-1, | ||
) | ||
}, [linePosition]) | ||
|
||
return ( | ||
<Box | ||
position="absolute" | ||
top={0} | ||
left={0} | ||
right={0} | ||
bottom={0} | ||
justifyContent="center" | ||
alignItems="center" | ||
opacity={0.5} | ||
backgroundColor="primaryBackground" | ||
> | ||
<Box | ||
position="relative" | ||
width={SCANNER_SIZE} | ||
height={SCANNER_SIZE} | ||
justifyContent="space-between" | ||
alignItems="center" | ||
overflow="hidden" | ||
> | ||
{/* top left */} | ||
<Box | ||
position="absolute" | ||
borderColor="hntBlue" | ||
width={BORDER_SEGMENT_SIZE} | ||
height={BORDER_SEGMENT_SIZE} | ||
borderTopWidth={4} | ||
borderLeftWidth={4} | ||
top={0} | ||
left={0} | ||
/> | ||
{/* top right */} | ||
<Box | ||
position="absolute" | ||
borderColor="hntBlue" | ||
width={BORDER_SEGMENT_SIZE} | ||
height={BORDER_SEGMENT_SIZE} | ||
borderTopWidth={4} | ||
borderRightWidth={4} | ||
top={0} | ||
right={0} | ||
/> | ||
{/* bottom left */} | ||
<Box | ||
position="absolute" | ||
borderColor="hntBlue" | ||
width={BORDER_SEGMENT_SIZE} | ||
height={BORDER_SEGMENT_SIZE} | ||
borderBottomWidth={4} | ||
borderLeftWidth={4} | ||
bottom={0} | ||
left={0} | ||
/> | ||
{/* bottom right */} | ||
<Box | ||
position="absolute" | ||
borderColor="hntBlue" | ||
width={BORDER_SEGMENT_SIZE} | ||
height={BORDER_SEGMENT_SIZE} | ||
borderBottomWidth={4} | ||
borderRightWidth={4} | ||
bottom={0} | ||
right={0} | ||
/> | ||
{/* animated scanner line */} | ||
<Animated.View style={animatedStyle}> | ||
<Image source={require('../assets/images/scannerLine.png')} /> | ||
</Animated.View> | ||
</Box> | ||
</Box> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* eslint-disable no-console */ | ||
import React, { useEffect, useState } from 'react' | ||
import { BarcodeScanningResult, Camera, CameraView } from 'expo-camera' | ||
import { Linking, Platform, StyleSheet } from 'react-native' | ||
import { useNavigation } from '@react-navigation/native' | ||
import { useAsync } from 'react-async-hook' | ||
import { useTranslation } from 'react-i18next' | ||
import useAlert from '@hooks/useAlert' | ||
import { CameraScannerLayout } from './CameraScannerLayout' | ||
import Box from './Box' | ||
import BackScreen from './BackScreen' | ||
import ProgressBar from './ProgressBar' | ||
import Text from './Text' | ||
|
||
type Props = { | ||
progress: number | ||
onBarCodeScanned: (data: string) => void | ||
} | ||
const DynamicQrScanner = ({ onBarCodeScanned, progress }: Props) => { | ||
const [hasPermission, setHasPermission] = useState<boolean>() | ||
const navigation = useNavigation() | ||
const { showOKCancelAlert } = useAlert() | ||
const { t } = useTranslation() | ||
|
||
useEffect(() => { | ||
Camera.requestCameraPermissionsAsync().then( | ||
({ status }: { status: string }) => { | ||
setHasPermission(status === 'granted') | ||
}, | ||
) | ||
}, []) | ||
|
||
useAsync(async () => { | ||
if (hasPermission !== false) return | ||
|
||
// if permission is not granted, show alert to open settings | ||
const decision = await showOKCancelAlert({ | ||
title: t('qrScanner.deniedAlert.title'), | ||
message: t('qrScanner.deniedAlert.message'), | ||
ok: t('qrScanner.deniedAlert.ok'), | ||
}) | ||
|
||
// if user clicks ok, open settings | ||
if (decision) { | ||
if (Platform.OS === 'ios') { | ||
Linking.openURL('app-settings:') | ||
} else { | ||
Linking.openSettings() | ||
} | ||
} | ||
|
||
// if user clicks cancel, go back to the previous screen | ||
if (decision === false) { | ||
navigation.goBack() | ||
} | ||
}, [hasPermission, navigation, showOKCancelAlert]) | ||
|
||
const handleBarCodeScanned = (result: BarcodeScanningResult) => { | ||
onBarCodeScanned(result.data) | ||
} | ||
|
||
return ( | ||
<BackScreen padding="none"> | ||
{/* if permission is not granted, show a black screen and notice alert modal */} | ||
{hasPermission !== true && <Box />} | ||
|
||
{hasPermission === true && ( | ||
<Box flex={1}> | ||
<CameraView | ||
onBarcodeScanned={handleBarCodeScanned} | ||
barcodeScannerSettings={{ barcodeTypes: ['qr'] }} | ||
style={StyleSheet.absoluteFillObject} | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
ratio="16:9" | ||
/> | ||
<CameraScannerLayout /> | ||
|
||
<Box position="absolute" bottom="20%" width="70%" alignSelf="center"> | ||
<ProgressBar progress={progress} /> | ||
</Box> | ||
|
||
<Box | ||
position="absolute" | ||
bottom="10%" | ||
alignSelf="center" | ||
paddingHorizontal="s" | ||
> | ||
<Text variant="subtitle3" marginTop="xxxl" textAlign="center"> | ||
{t('keystone.payment.scanTxQrcodeScreenSubtitle3')} | ||
</Text> | ||
</Box> | ||
</Box> | ||
)} | ||
</BackScreen> | ||
) | ||
} | ||
export default DynamicQrScanner |
Oops, something went wrong.