forked from cerc-io/laconic-wallet
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:
parent
0a39f7f1ba
commit
21b749d9a4
8
App.tsx
8
App.tsx
@ -7,6 +7,7 @@ import SignMessage from './components/SignMessage';
|
|||||||
import HomeScreen from './components/HomeScreen';
|
import HomeScreen from './components/HomeScreen';
|
||||||
import SignRequest from './components/SignRequest';
|
import SignRequest from './components/SignRequest';
|
||||||
import InvalidPath from './components/InvalidPath';
|
import InvalidPath from './components/InvalidPath';
|
||||||
|
import QRScanner from './components/QRScanner';
|
||||||
|
|
||||||
import { StackParamsList } from './types';
|
import { StackParamsList } from './types';
|
||||||
|
|
||||||
@ -58,6 +59,13 @@ const App = (): React.JSX.Element => {
|
|||||||
headerBackVisible: false,
|
headerBackVisible: false,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="QRScanner"
|
||||||
|
component={QRScanner}
|
||||||
|
options={{
|
||||||
|
title: 'Connect Wallet',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.laconic.wallet">
|
<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.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
|
@ -39,3 +39,5 @@ newArchEnabled=false
|
|||||||
# Use this property to enable or disable the Hermes JS engine.
|
# Use this property to enable or disable the Hermes JS engine.
|
||||||
# If set to false, you will be using JSC instead.
|
# If set to false, you will be using JSC instead.
|
||||||
hermesEnabled=true
|
hermesEnabled=true
|
||||||
|
|
||||||
|
VisionCamera_enableCodeScanner=true
|
||||||
|
@ -114,6 +114,17 @@ const Accounts = ({
|
|||||||
Sign Message
|
Sign Message
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
navigation.navigate('QRScanner');
|
||||||
|
}}>
|
||||||
|
<Text
|
||||||
|
variant="titleSmall"
|
||||||
|
style={[styles.hyperlink, { color: theme.colors.primary }]}>
|
||||||
|
Connect Wallet
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
107
components/QRScanner.tsx
Normal file
107
components/QRScanner.tsx
Normal 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;
|
@ -30,6 +30,7 @@
|
|||||||
"react-native-safe-area-context": "^4.9.0",
|
"react-native-safe-area-context": "^4.9.0",
|
||||||
"react-native-screens": "^3.29.0",
|
"react-native-screens": "^3.29.0",
|
||||||
"react-native-vector-icons": "^10.0.3",
|
"react-native-vector-icons": "^10.0.3",
|
||||||
|
"react-native-vision-camera": "^3.9.0",
|
||||||
"text-encoding-polyfill": "^0.6.7"
|
"text-encoding-polyfill": "^0.6.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
1
types.ts
1
types.ts
@ -5,6 +5,7 @@ export type StackParamsList = {
|
|||||||
| { network: string; address: string; message: string }
|
| { network: string; address: string; message: string }
|
||||||
| undefined;
|
| undefined;
|
||||||
InvalidPath: undefined;
|
InvalidPath: undefined;
|
||||||
|
QRScanner: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Account = {
|
export type Account = {
|
||||||
|
@ -6604,6 +6604,11 @@ react-native-vector-icons@^10.0.3:
|
|||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
yargs "^16.1.1"
|
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:
|
react-native@0.73.3:
|
||||||
version "0.73.3"
|
version "0.73.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.3.tgz#aae18b4c6da84294c1f8e1d6446b46c887bf087c"
|
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.3.tgz#aae18b4c6da84294c1f8e1d6446b46c887bf087c"
|
||||||
|
Loading…
Reference in New Issue
Block a user