From ec9e0a21afb4f09caaa586e338afb94f60ba8e69 Mon Sep 17 00:00:00 2001 From: Isky Date: Thu, 20 Jun 2024 16:21:45 +0800 Subject: [PATCH] added a close button for ScannedDataBox that will work on both HisoryScreen and QRScannerScreen --- components/ScannedDataBox.tsx | 11 ++++- package-lock.json | 36 +++++++------- screens/HistoryScreen.tsx | 12 ++++- screens/QRScannerScreen.tsx | 89 +++++++++++++++++++---------------- 4 files changed, 88 insertions(+), 60 deletions(-) diff --git a/components/ScannedDataBox.tsx b/components/ScannedDataBox.tsx index ff1d015..6f38ccc 100644 --- a/components/ScannedDataBox.tsx +++ b/components/ScannedDataBox.tsx @@ -6,6 +6,7 @@ import { Ionicons } from '@expo/vector-icons'; interface ScannedDataBoxProps { data: string; dataType: string; + clearScanData: () => void; } interface ScanResult { @@ -14,7 +15,7 @@ interface ScanResult { redirects: number; } -const ScannedDataBox: React.FC = ({ data, dataType }) => { +const ScannedDataBox: React.FC = ({ data, dataType, clearScanData }) => { const [scanResult, setScanResult] = useState(null); useEffect(() => { @@ -71,6 +72,9 @@ const ScannedDataBox: React.FC = ({ data, dataType }) => { return ( + + + {extractedData} @@ -176,6 +180,11 @@ const styles = StyleSheet.create({ color: '#2196F3', marginTop: 5, }, + closeButton: { + position: 'absolute', + top: 10, + right: 10, + }, }); export default ScannedDataBox; diff --git a/package-lock.json b/package-lock.json index 2e00aa1..0d5e68c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4568,9 +4568,9 @@ } }, "node_modules/@react-native-community/cli-server-api/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "dependencies": { "async-limiter": "~1.0.0" } @@ -5374,9 +5374,9 @@ } }, "node_modules/@react-native/dev-middleware/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "dependencies": { "async-limiter": "~1.0.0" } @@ -10686,9 +10686,9 @@ } }, "node_modules/metro/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, @@ -12084,9 +12084,9 @@ } }, "node_modules/react-devtools-core/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, @@ -12308,9 +12308,9 @@ } }, "node_modules/react-native/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "dependencies": { "async-limiter": "~1.0.0" } @@ -14237,9 +14237,9 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, diff --git a/screens/HistoryScreen.tsx b/screens/HistoryScreen.tsx index d4fff4b..d5ef160 100644 --- a/screens/HistoryScreen.tsx +++ b/screens/HistoryScreen.tsx @@ -48,6 +48,11 @@ const HistoryScreen: React.FC = () => { setIsModalVisible(true); }; + const clearSelectedData = () => { + setSelectedData(null); + setSelectedScanResult(null); + }; + return ( @@ -59,7 +64,9 @@ const HistoryScreen: React.FC = () => { {selectedData && ( - + + + )} { } }; + + + // Define the props for QRScannerScreen interface QRScannerScreenProps { clearScanData: () => void; } + + + //-----------------Main------------------// const QRScannerScreen: React.FC = ({ clearScanData }) => { @@ -170,42 +176,45 @@ const QRScannerScreen: React.FC = ({ clearScanData }) => { 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, + }); - -//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.... - 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); + // 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.'); } - } 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... // or else permission for camera is not asked @@ -253,19 +262,19 @@ const QRScannerScreen: React.FC = ({ clearScanData }) => { - + {/* the image icon for opening album/gallery */} - - - + + + + {/* The CONTENT , the popup for the scanned data */} {/* This is called from ../components/ScannedDataBox*/} - {scannedData !== '' && ( - + )} @@ -337,8 +346,10 @@ const styles = StyleSheet.create({ scannedDataBox: { position: 'absolute', top: '10%', + height: '100%', left: '5%', right: '5%', + zIndex: 2, }, welcomeText: { @@ -349,6 +360,4 @@ const styles = StyleSheet.create({ }, }); - - export default QRScannerScreen;