Camera QR

This commit is contained in:
KoalaSat 2023-02-25 20:45:27 +01:00
parent f8cfae8f7a
commit e3a8fd0031
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
14 changed files with 151 additions and 3 deletions

View File

@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nostros">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- required for react-native-share base64 sharing -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

View File

@ -1,4 +1,12 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin', 'react-native-paper/babel'],
plugins: [
[
'react-native-reanimated/plugin',
{
globals: ['__scanCodes'],
},
],
'react-native-paper/babel',
],
}

View File

@ -12,8 +12,13 @@
"privateKeysSnackbarTitle": "Wichtig!",
"privateKeysSnackbarDescription": "Verwahre den privaten Schlüssel an einem sicheren Ort. Geht der Schlüssel verloren, kann er nicht wiederhergestellt werden. Das Konto kann nie wieder benutzt werden."
},
"qrReaderPage": {
"emptyTitle": "Permissions not granted",
"emptyDescription": "Grant camera permissions to Nostros to start scanning QR codes"
},
"homeNavigator": {
"Group": "",
"QrReader": "",
"ProfileCreate": "Profil anlegen",
"ProfileConnect": "",
"ProfileLoad": "",

View File

@ -18,6 +18,7 @@
"Group": "",
"ProfileLoad": "",
"Landing": "",
"QrReader": "",
"Contacts": "Contacts",
"Conversation": "Conversation",
"Repost": "Repost note",
@ -46,6 +47,10 @@
"foundContacts": "{{contactsCount}} contacts found",
"storing": "Event {{lastEventId}} stored on database."
},
"qrReaderPage": {
"emptyTitle": "Permissions not granted",
"emptyDescription": "Grant camera permissions to Nostros to start scanning QR codes"
},
"sendPage": {
"isContact": "Following",
"isNotContact": "Not following",

View File

@ -12,8 +12,13 @@
"privateKeysSnackbarTitle": "Muy importante.",
"privateKeysSnackbarDescription": "Guarda tu clave privada en un lugar seguro, si la pierdes no podrás volver a acceder con ella ni recuperar tu cuenta."
},
"qrReaderPage": {
"emptyTitle": "Permisos no concedidos",
"emptyDescription": "Concede permisos a Nostros para acceder a tu camara y empezar a escanear códigos QR"
},
"homeNavigator": {
"Group": "",
"QrReader": "",
"ProfileCreate": "Crear perfil",
"ProfileConnect": "",
"ProfileLoad": "",

View File

@ -12,8 +12,13 @@
"privateKeysSnackbarTitle": "Très important.",
"privateKeysSnackbarDescription": "Conservez votre clé privée dans un endroit sûr. Si vous la perdez, vous ne pourrez plus avoir accès ni récupérer votre compte."
},
"qrReaderPage": {
"emptyTitle": "Permissions not granted",
"emptyDescription": "Grant camera permissions to Nostros to start scanning QR codes"
},
"homeNavigator": {
"Group": "",
"QrReader": "",
"ProfileCreate": "Create profile",
"ProfileConnect": "",
"ProfileLoad": "",

View File

@ -12,8 +12,13 @@
"privateKeysSnackbarTitle": "Важно",
"privateKeysSnackbarDescription": "Keep your private key in a safe place, if you lose it you will not be able to access it again or recover your account."
},
"qrReaderPage": {
"emptyTitle": "Permissions not granted",
"emptyDescription": "Grant camera permissions to Nostros to start scanning QR codes"
},
"homeNavigator": {
"Group": "",
"QrReader": "",
"ProfileCreate": "Create profile",
"ProfileConnect": "",
"ProfileLoad": "",

View File

@ -12,8 +12,13 @@
"privateKeysSnackbarTitle": "注意",
"privateKeysSnackbarDescription": "请妥善保管您的私钥。如果遗失,您将无法访问或恢复您的账号。"
},
"qrReaderPage": {
"emptyTitle": "Permissions not granted",
"emptyDescription": "Grant camera permissions to Nostros to start scanning QR codes"
},
"homeNavigator": {
"Group": "",
"QrReader": "",
"ProfileCreate": "创建用户",
"ProfileConnect": "",
"Contacts": "联系人",

View File

@ -260,6 +260,7 @@ export const ConfigPage: React.FC = () => {
label={t('configPage.defaultZapAmount') ?? ''}
onChangeText={setZapAmount}
value={zapAmount}
keyboardType='numeric'
/>
<Button
mode='contained'

View File

@ -11,6 +11,7 @@ import ProfileCreatePage from '../../Pages/ProfileCreatePage'
import { DrawerNavigationProp } from '@react-navigation/drawer'
import RelaysPage from '../RelaysPage'
import ConfigPage from '../ConfigPage'
import QrReaderPage from '../QrReaderPage'
export const HomeNavigator: React.FC = () => {
const theme = useTheme()
@ -109,6 +110,7 @@ export const HomeNavigator: React.FC = () => {
<Stack.Screen name='About' component={AboutPage} />
<Stack.Screen name='Relays' component={RelaysPage} />
<Stack.Screen name='Config' component={ConfigPage} />
<Stack.Screen name='QrReader' component={QrReaderPage} />
</Stack.Group>
</Stack.Navigator>
<RBSheet

View File

@ -158,6 +158,13 @@ export const ProfileConnectPage: React.FC = () => {
forceTextInputFocus={false}
/>
}
left={
<TextInput.Icon
icon='qrcode'
onPress={() => navigate('QrReader')}
forceTextInputFocus={false}
/>
}
/>
)}
<Button

View File

@ -0,0 +1,88 @@
import * as React from 'react'
import { StyleSheet, View } from 'react-native'
import { Camera, useCameraDevices } from 'react-native-vision-camera'
import { useScanBarcodes, BarcodeFormat } from 'vision-camera-code-scanner'
import { Text, useTheme } from 'react-native-paper'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { useTranslation } from 'react-i18next'
export const QrReaderPage: React.FC = () => {
const theme = useTheme()
const { t } = useTranslation('common')
const [hasPermission, setHasPermission] = React.useState(false)
const devices = useCameraDevices()
const device = devices.back
const [frameProcessor, barcodes] = useScanBarcodes([BarcodeFormat.QR_CODE], {
checkInverted: true,
})
React.useEffect(() => {
console.log(barcodes)
}, [barcodes])
React.useEffect(() => {
;(async () => {
const status = await Camera.requestCameraPermission()
setHasPermission(status === 'authorized')
})()
}, [])
const NoPermissionsComponent = React.useMemo(
() => (
<View style={styles.blank}>
<MaterialCommunityIcons
name='camera-off-outline'
size={64}
style={styles.center}
color={theme.colors.onPrimaryContainer}
/>
<Text variant='headlineSmall' style={styles.center}>
{t('qrReaderPage.emptyTitle')}
</Text>
<Text variant='bodyMedium' style={styles.center}>
{t('qrReaderPage.emptyDescription')}
</Text>
</View>
),
[],
)
return device != null && hasPermission ? (
<>
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
frameProcessor={frameProcessor}
frameProcessorFps={5}
/>
{barcodes.map((barcode, idx) => (
<Text key={idx} style={styles.barcodeTextURL}>
{barcode.displayValue}
</Text>
))}
</>
) : (
NoPermissionsComponent
)
}
const styles = StyleSheet.create({
barcodeTextURL: {
fontSize: 20,
color: 'white',
fontWeight: 'bold',
},
center: {
alignContent: 'center',
textAlign: 'center',
},
blank: {
justifyContent: 'space-between',
height: 170,
marginTop: 91,
},
})
export default QrReaderPage

View File

@ -60,13 +60,15 @@
"react-native-tab-view": "^3.3.4",
"react-native-vector-icons": "^9.2.0",
"react-native-version-number": "^0.3.6",
"react-native-vision-camera": "^2.15.4",
"react-native-webp-format": "^1.1.2",
"readable-stream": "^4.3.0",
"safe-buffer": "^5.2.1",
"sqlstring": "^2.3.3",
"stream": "^0.0.2",
"text-encoding-polyfill": "^0.6.7",
"uuid": "^9.0.0"
"uuid": "^9.0.0",
"vision-camera-code-scanner": "^0.2.0"
},
"devDependencies": {
"@babel/core": "^7.20.2",

View File

@ -7228,6 +7228,11 @@ react-native-version-number@^0.3.6:
resolved "https://registry.yarnpkg.com/react-native-version-number/-/react-native-version-number-0.3.6.tgz#dd8b1435fc217df0a166d7e4a61fdc993f3e7437"
integrity sha512-TdyXiK90NiwmSbmAUlUBOV6WI1QGoqtvZZzI5zQY4fKl67B3ZrZn/h+Wy/OYIKKFMfePSiyfeIs8LtHGOZ/NgA==
react-native-vision-camera@^2.15.4:
version "2.15.4"
resolved "https://registry.yarnpkg.com/react-native-vision-camera/-/react-native-vision-camera-2.15.4.tgz#821f0505fc8c63b87c1ae4697d2bb4f670333576"
integrity sha512-SJXSWH1pu4V3Kj4UuX/vSgOxc9d5wb5+nHqBHd+5iUtVyVLEp0F6Jbbaha7tDoU+kUBwonhlwr2o8oV6NZ7Ibg==
react-native-webp-format@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/react-native-webp-format/-/react-native-webp-format-1.1.2.tgz#22b14f544191e9a5411c920b9874e532a6ea6c89"
@ -8469,6 +8474,11 @@ vary@~1.1.2:
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
vision-camera-code-scanner@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/vision-camera-code-scanner/-/vision-camera-code-scanner-0.2.0.tgz#8adc0694319a17f6a95f6dfacc02ab7ac29b4742"
integrity sha512-H5hVkXfbIcGdg9YlhuS8Y/xDX5e32Vo6eK5FyDQsE9AGVjlqEHMmSLHZg7BX8UUm4ADmiAZc8wzc4n8TUqGr0g==
vlq@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468"