added a close button for ScannedDataBox that will work on both HisoryScreen and QRScannerScreen
This commit is contained in:
@@ -6,6 +6,7 @@ import { Ionicons } from '@expo/vector-icons';
|
|||||||
interface ScannedDataBoxProps {
|
interface ScannedDataBoxProps {
|
||||||
data: string;
|
data: string;
|
||||||
dataType: string;
|
dataType: string;
|
||||||
|
clearScanData: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ScanResult {
|
interface ScanResult {
|
||||||
@@ -14,7 +15,7 @@ interface ScanResult {
|
|||||||
redirects: number;
|
redirects: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType }) => {
|
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData }) => {
|
||||||
const [scanResult, setScanResult] = useState<ScanResult | null>(null);
|
const [scanResult, setScanResult] = useState<ScanResult | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -71,6 +72,9 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.dataBox}>
|
<View style={styles.dataBox}>
|
||||||
|
<TouchableOpacity style={styles.closeButton} onPress={clearScanData}>
|
||||||
|
<Ionicons name="close-circle-outline" size={24} color="#ff69b4" />
|
||||||
|
</TouchableOpacity>
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<Image source={require('../assets/ScanIcon3.png')} style={styles.scan_icon} />
|
<Image source={require('../assets/ScanIcon3.png')} style={styles.scan_icon} />
|
||||||
<Text style={styles.payload}>{extractedData}</Text>
|
<Text style={styles.payload}>{extractedData}</Text>
|
||||||
@@ -176,6 +180,11 @@ const styles = StyleSheet.create({
|
|||||||
color: '#2196F3',
|
color: '#2196F3',
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
},
|
},
|
||||||
|
closeButton: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 10,
|
||||||
|
right: 10,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ScannedDataBox;
|
export default ScannedDataBox;
|
||||||
|
|||||||
36
package-lock.json
generated
36
package-lock.json
generated
@@ -4568,9 +4568,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-native-community/cli-server-api/node_modules/ws": {
|
"node_modules/@react-native-community/cli-server-api/node_modules/ws": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
|
||||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
"integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
@@ -5374,9 +5374,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-native/dev-middleware/node_modules/ws": {
|
"node_modules/@react-native/dev-middleware/node_modules/ws": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
|
||||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
"integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
@@ -10686,9 +10686,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/metro/node_modules/ws": {
|
"node_modules/metro/node_modules/ws": {
|
||||||
"version": "7.5.9",
|
"version": "7.5.10",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
@@ -12084,9 +12084,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-devtools-core/node_modules/ws": {
|
"node_modules/react-devtools-core/node_modules/ws": {
|
||||||
"version": "7.5.9",
|
"version": "7.5.10",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3.0"
|
"node": ">=8.3.0"
|
||||||
},
|
},
|
||||||
@@ -12308,9 +12308,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native/node_modules/ws": {
|
"node_modules/react-native/node_modules/ws": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
|
||||||
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
|
"integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
@@ -14237,9 +14237,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.17.0",
|
"version": "8.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||||
"integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==",
|
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ const HistoryScreen: React.FC = () => {
|
|||||||
setIsModalVisible(true);
|
setIsModalVisible(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clearSelectedData = () => {
|
||||||
|
setSelectedData(null);
|
||||||
|
setSelectedScanResult(null);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.headerContainer}>
|
<View style={styles.headerContainer}>
|
||||||
@@ -59,7 +64,9 @@ const HistoryScreen: React.FC = () => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
{selectedData && (
|
{selectedData && (
|
||||||
<ScannedDataBox data={selectedData} scanResult={selectedScanResult} dataType="URL" />
|
<View style={styles.scannedDataBoxContainer}>
|
||||||
|
<ScannedDataBox data={selectedData} scanResult={selectedScanResult} dataType="URL" clearScanData={clearSelectedData} />
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
<FlatList
|
<FlatList
|
||||||
data={filteredQrCodes}
|
data={filteredQrCodes}
|
||||||
@@ -211,6 +218,9 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: '#000',
|
color: '#000',
|
||||||
},
|
},
|
||||||
|
scannedDataBoxContainer: {
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default HistoryScreen;
|
export default HistoryScreen;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useContext } from 'react';
|
import React, { useState, useEffect, useContext } from 'react';
|
||||||
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Button, Alert, Image } from 'react-native';
|
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, Image, BackHandler } from 'react-native';
|
||||||
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
|
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
|
||||||
import { QRCodeContext } from '../types';
|
import { QRCodeContext } from '../types';
|
||||||
import axios from 'axios'; // For URL calls
|
import axios from 'axios'; // For URL calls
|
||||||
@@ -64,11 +64,17 @@ const getVirusTotalResults = async (scanId: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Define the props for QRScannerScreen
|
// Define the props for QRScannerScreen
|
||||||
interface QRScannerScreenProps {
|
interface QRScannerScreenProps {
|
||||||
clearScanData: () => void;
|
clearScanData: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------Main------------------//
|
//-----------------Main------------------//
|
||||||
const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
||||||
|
|
||||||
@@ -170,42 +176,45 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
|||||||
handleQRCodeScanned({ type: 'TEST', data: 'TEST123' });
|
handleQRCodeScanned({ type: 'TEST', data: '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 () => {
|
||||||
|
clearScanDataInternal();
|
||||||
|
const result = await ImagePicker.launchImageLibraryAsync({
|
||||||
|
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
||||||
|
allowsEditing: false, // Don't ask user to crop images
|
||||||
|
quality: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// if (result && result.assets[0].uri) { // KIV this....
|
||||||
//https://medium.com/@funti009/create-a-mobile-qr-scanner-that-scans-via-camera-and-image-in-the-gallery-react-native-expo-ee7098a265d7
|
if (result && result.assets && result.assets.length > 0 && result.assets[0].uri) { // this is to unsure the uri is not empty
|
||||||
// Refactored to use Camera.scanFromURLAsync instead
|
try {
|
||||||
// Function to handle QR code scanning from the image picker
|
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 handleImagePicker = async () => {
|
const dataNeeded = scannedResult[0].data;
|
||||||
clearScanDataInternal();
|
handleQRCodeScanned({ type: 'QR_CODE', data: dataNeeded });
|
||||||
const result = await ImagePicker.launchImageLibraryAsync({
|
} else {
|
||||||
mediaTypes: ImagePicker.MediaTypeOptions.Images,
|
setScannedData("No QR Code Found");
|
||||||
allowsEditing: false, // Don't ask user to crop images
|
setTimeout(() => setScannedData(""), 4000);
|
||||||
quality: 1,
|
}
|
||||||
});
|
} catch (error) {
|
||||||
|
console.error('Error scanning QR code from image:', error);
|
||||||
|
Alert.alert('Failed to scan QR code from image.');
|
||||||
//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
|
|
||||||
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 });
|
|
||||||
} else {
|
|
||||||
setScannedData("No QR Code Found");
|
|
||||||
setTimeout(() => setScannedData(""), 4000);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('Error scanning QR code from image:', error);
|
|
||||||
Alert.alert('Failed to scan QR code from image.');
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
// Add back button handler to clear scanned data
|
||||||
|
useEffect(() => {
|
||||||
|
const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||||
|
clearScanDataInternal();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => backHandler.remove();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// For Splash, for some reason need to be near the end of the function...
|
// For Splash, for some reason need to be near the end of the function...
|
||||||
// or else permission for camera is not asked
|
// or else permission for camera is not asked
|
||||||
@@ -253,19 +262,19 @@ const QRScannerScreen: React.FC<QRScannerScreenProps> = ({ clearScanData }) => {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={handleTestScan} style={styles.testButton}>
|
<TouchableOpacity onPress={handleTestScan} style={styles.testButton}>
|
||||||
<Ionicons name="bug" size={24} color="#fff" />
|
<Ionicons name="bug" size={24} color="#fff" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
{/* the image icon for opening album/gallery */}
|
{/* the image icon for opening album/gallery */}
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity onPress={handleImagePicker} style={styles.galleryButton}>
|
<TouchableOpacity onPress={handleImagePicker} style={styles.galleryButton}>
|
||||||
<Ionicons name="image" size={24} color="#fff" />
|
<Ionicons name="image" size={24} color="#fff" />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* The CONTENT , the popup for the scanned data */}
|
{/* The CONTENT , the popup for the scanned data */}
|
||||||
{/* This is called from ../components/ScannedDataBox*/}
|
{/* This is called from ../components/ScannedDataBox*/}
|
||||||
</View>
|
|
||||||
{scannedData !== '' && (
|
{scannedData !== '' && (
|
||||||
<View style={styles.scannedDataBox}>
|
<View style={styles.scannedDataBox}>
|
||||||
<ScannedDataBox data={scannedData} scanResult={scanResult} dataType={dataType} />
|
<ScannedDataBox data={scannedData} scanResult={scanResult} dataType={dataType} clearScanData={clearScanDataInternal} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -337,8 +346,10 @@ const styles = StyleSheet.create({
|
|||||||
scannedDataBox: {
|
scannedDataBox: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '10%',
|
top: '10%',
|
||||||
|
height: '100%',
|
||||||
left: '5%',
|
left: '5%',
|
||||||
right: '5%',
|
right: '5%',
|
||||||
|
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
},
|
},
|
||||||
welcomeText: {
|
welcomeText: {
|
||||||
@@ -349,6 +360,4 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default QRScannerScreen;
|
export default QRScannerScreen;
|
||||||
|
|||||||
Reference in New Issue
Block a user