import React, { useState, useEffect, createContext, useContext } from 'react'; import { Text, View, StyleSheet, ActivityIndicator, TouchableOpacity, FlatList } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { CameraView, Camera } from 'expo-camera'; // The icons used in the navigation bar import { Ionicons } from '@expo/vector-icons'; // Import Axios for HTTP requests for the VT API call import axios from 'axios'; // Create a Context for QR code data const QRCodeContext = createContext(null); const Tab = createBottomTabNavigator(); // Component for QR Scanner Screen const QRScannerScreen: React.FC = () => { const { qrCodes, setQrCodes } = useContext(QRCodeContext); // Access context const [hasPermission, setHasPermission] = useState(null); // State for camera permission const [scanned, setScanned] = useState(false); // State for scanned status const [showSplash, setShowSplash] = useState(true); // State for splash screen const [scannedData, setScannedData] = useState(''); // State for scanned data const [scanResult, setScanResult] = useState(null); // State for VirusTotal scan result useEffect(() => { const initializeApp = async () => { const { status } = await Camera.requestCameraPermissionsAsync(); // Request camera permissions setHasPermission(status === 'granted'); // Set permission status setShowSplash(false); // Hide splash screen }; initializeApp(); // Initialize app }, []); // Function to handle barcode scanned event const handleQRCodeSanned = async ({ type, data }: { type: string; data: string }) => { setScanned(true);// Mark as scanned // Determine the type of data (URL, text, or just numbers) let dataType; if (/^(http|https):\/\//.test(data)) { dataType = 'URL'; } else if (/^[0-9]+$/.test(data)) { dataType = 'Numbers'; } else { dataType = 'Text'; } // Construct the scanned data with the data type let newScannedData = `Type: ${dataType}\nData: ${data}`; // Initialize with type and data try { const scanId = await scanWithVirusTotal(data); // Send data to VirusTotal and get scan ID const positive = await getScanResult(scanId); // Get scan result and extract positive score newScannedData += `\nScore: ${positive}`; // Append positive score to newScannedData } catch (error) { console.error('Error handling barcode scan:', error); // Handle error } setScannedData(newScannedData); // Save scanned data setQrCodes([...qrCodes, newScannedData]); // Add scanned data to history }; // Function to send data to VirusTotal and get the scan ID const scanWithVirusTotal = async (data: any) => { const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e'; // 4/min , 500/day const url = 'https://www.virustotal.com/vtapi/v2/url/scan'; const params = { apikey: apiKey, url: data }; // The axios to handle URL stuff try { const response = await axios.post(url, null, { params }); return response.data.scan_id; // Return scanID } catch (error) { console.error('Error scanning with VirusTotal:', error); throw error; } }; // Get the full list of scanned result based on scanID from // response above, Only want response.data.positive const getScanResult = async (scanId: Int32Array) => { const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e'; const url = 'https://www.virustotal.com/vtapi/v2/url/report'; const params = { apikey: apiKey, resource: scanId }; // The axios to handle URL stuff try { const response = await axios.get(url, { params }); return response.data.positives; // Reture the value of positive: } catch (error) { console.error('Error getting scan result:', error); throw error; } }; if (showSplash) { return ( ); } if (hasPermission === null) { return Requesting for camera permission; } if (hasPermission === false) { return No access to camera; } return ( {/* Header banner */} SafeQR {/* Welcome message */} Welcome to SafeQR code Scanner {/* Camera view container */} {/* Display scanned data */} {scannedData !== '' && ( {scannedData} {scanResult && {JSON.stringify(scanResult)}} )} ); }; // Component for History Screen function HistoryScreen() { const { qrCodes } = useContext(QRCodeContext); return ( History Screen ( {item} )} keyExtractor={(item, index) => index.toString()} // Key extractor for FlatList /> ); } // Component for Settings Screen function SettingsScreen() { const { setQrCodes } = useContext(QRCodeContext); // Access context const clearHistory = () => {setQrCodes([]);}; // To clear History return ( Settings Screen Clear History ); } // Component for Profile Screen function ProfileScreen() { return ( Profile Screen ); } // Custom Tab Bar Component const CustomTabBar = ({ state, descriptors, navigation }) => { return ( {state.routes.map((route, index) => { const { options } = descriptors[route.key]; const label = options.tabBarLabel !== undefined ? options.tabBarLabel : options.title !== undefined ? options.title : route.name; const isFocused = state.index === index; const onPress = () => { const event = navigation.emit({ type: 'tabPress', target: route.key, }); if (!isFocused && !event.defaultPrevented) { navigation.navigate(route.name); } }; const onLongPress = () => { navigation.emit({ type: 'tabLongPress', target: route.key, }); }; // Set different icons for each tab const iconName = route.name === 'QR Scanner' ? 'camera' : route.name === 'History' ? 'time' : route.name === 'Settings' ? 'settings' : 'person'; return ( {label} ); })} {navigation.navigate('QR Scanner');}}> ); }; // Main App component with bottom tab navigation export default function App() { const [qrCodes, setQrCodes] = useState([]); // State to hold QR codes return ( }> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f8f0fc', padding: 20, }, banner:{}, headerText:{}, splashContainer: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#f8f0fc", }, scanText: { textAlign: "center", fontSize: 24, fontWeight: "bold", color: "#ff69b4", marginVertical: 10, }, instructionText: { textAlign: "center", fontSize: 16, color: "#000", marginBottom: 20, }, cameraContainer: { flex: 1, alignItems: "center", justifyContent: "center", borderRadius: 10, overflow: "hidden", }, camera: { width: '100%', height: '100%', }, button: { backgroundColor: '#333', paddingHorizontal: 20, paddingVertical: 10, borderRadius: 30, alignItems: 'center', justifyContent: 'center', marginVertical: 10, }, buttonText: { color: 'white', fontSize: 16, }, dataBox: { marginVertical: 10, padding: 10, backgroundColor: "#fff", borderRadius: 5, alignItems: "center", justifyContent: "center", }, dataText: { fontSize: 16, color: "#000", }, welcomeText: { textAlign: "center", fontSize: 20, marginVertical: 10, color: "black", }, tabBar: { position: 'absolute', bottom: 20, left: 20, right: 20, height: 70, borderRadius: 35, backgroundColor: '#fff', flexDirection: 'row', justifyContent: 'space-around', alignItems: 'center', shadowColor: '#000', shadowOpacity: 0.1, shadowOffset: { width: 0, height: 2 }, shadowRadius: 10, elevation: 5, }, tabButton: { flex: 1, justifyContent: 'center', alignItems: 'center', }, floatingButton: { position: 'absolute', bottom: 30, left: '50%', // Position from the left marginLeft: -30, // Half of the button width to center it width: 60, height: 60, borderRadius: 30, backgroundColor: '#673ab7', justifyContent: 'center', alignItems: 'center', shadowColor: '#000', shadowOpacity: 0.1, shadowOffset: { width: 0, height: 2 }, shadowRadius: 5, elevation: 3, }, });