Add QR scanner for walletconnect (#36)

* Add page for scanning qr code

* Refactor code

* Ask for permission to use camera

* Change Qr to QR

* Seperate imports

* QR instead of Qr

---------

Co-authored-by: Adw8 <adwait@deepstacksoft.com>
This commit is contained in:
Adwait Gharpure 2024-03-05 11:42:12 +05:30 committed by GitHub
parent 0a39f7f1ba
commit 21b749d9a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 136 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import SignMessage from './components/SignMessage';
import HomeScreen from './components/HomeScreen';
import SignRequest from './components/SignRequest';
import InvalidPath from './components/InvalidPath';
import QRScanner from './components/QRScanner';
import { StackParamsList } from './types';
@ -58,6 +59,13 @@ const App = (): React.JSX.Element => {
headerBackVisible: false,
}}
/>
<Stack.Screen
name="QRScanner"
component={QRScanner}
options={{
title: 'Connect Wallet',
}}
/>
</Stack.Navigator>
</NavigationContainer>
);

View File

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.laconic.wallet">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name=".MainApplication"

View File

@ -39,3 +39,5 @@ newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
VisionCamera_enableCodeScanner=true

View File

@ -114,6 +114,17 @@ const Accounts = ({
Sign Message
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
navigation.navigate('QRScanner');
}}>
<Text
variant="titleSmall"
style={[styles.hyperlink, { color: theme.colors.primary }]}>
Connect Wallet
</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>

107
components/QRScanner.tsx Normal file
View File

@ -0,0 +1,107 @@
import React, { useEffect, useState } from 'react';
import { Alert, StyleSheet, View, AppState } from 'react-native';
import { Text, Button } from 'react-native-paper';
import {
Camera,
useCameraDevice,
useCameraPermission,
useCodeScanner,
} from 'react-native-vision-camera';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { StackParamsList } from '../types';
const QRScanner = () => {
const navigation =
useNavigation<NativeStackNavigationProp<StackParamsList>>();
const { hasPermission, requestPermission } = useCameraPermission();
const [isActive, setIsActive] = useState(AppState.currentState === 'active');
const device = useCameraDevice('back');
const [isScanning, setScanning] = useState(true);
const codeScanner = useCodeScanner({
codeTypes: ['qr'],
onCodeScanned: codes => {
if (isScanning) {
codes.forEach(code => {
if (code.value) {
Alert.alert(`Scanned: ${code.value}`, undefined, [
{
text: 'OK',
onPress: () => {
navigation.navigate('Laconic');
},
},
]);
setScanning(false);
}
});
}
},
});
useEffect(() => {
const handleAppStateChange = (newState: string) => {
setIsActive(newState === 'active');
};
AppState.addEventListener('change', handleAppStateChange);
if (!hasPermission) {
requestPermission();
}
}, [hasPermission, isActive, requestPermission]);
if (!hasPermission) {
return (
<View style={styles.container}>
<Text>No Camera Permission!</Text>
<Button onPress={() => requestPermission()}>Request Permission</Button>
</View>
);
}
if (!device) {
return (
<View style={styles.container}>
<Text>No Camera Selected!</Text>
</View>
);
}
return (
<View style={styles.container}>
{isActive ? (
<Camera
style={styles.camera}
device={device}
isActive={isActive}
codeScanner={codeScanner}
video={false}
/>
) : (
<Text>No Camera Selected!</Text>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
camera: {
width: 400,
height: 500,
borderRadius: 50,
overflow: 'hidden',
},
});
export default QRScanner;

View File

@ -30,6 +30,7 @@
"react-native-safe-area-context": "^4.9.0",
"react-native-screens": "^3.29.0",
"react-native-vector-icons": "^10.0.3",
"react-native-vision-camera": "^3.9.0",
"text-encoding-polyfill": "^0.6.7"
},
"devDependencies": {

View File

@ -5,6 +5,7 @@ export type StackParamsList = {
| { network: string; address: string; message: string }
| undefined;
InvalidPath: undefined;
QRScanner: undefined;
};
export type Account = {

View File

@ -6604,6 +6604,11 @@ react-native-vector-icons@^10.0.3:
prop-types "^15.7.2"
yargs "^16.1.1"
react-native-vision-camera@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/react-native-vision-camera/-/react-native-vision-camera-3.9.0.tgz#6a96a6cbad53c2db84d671c388b250327681a553"
integrity sha512-q0HejFTS56s5DXWHZhlWLLZMKn/8OXALrqET+FySPIKskwYEdJ5rOV2aDlD6hlo67qCNFGUIMZWGFFc9L2os1g==
react-native@0.73.3:
version "0.73.3"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.3.tgz#aae18b4c6da84294c1f8e1d6446b46c887bf087c"