Merge branch 'refactoring' of https://github.com/safeqr/SafeQR_Front_End_Mobile into refactoring
This commit is contained in:
13
App.tsx
13
App.tsx
@@ -1,11 +1,13 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
import QRScannerScreen from './screens/QRScannerScreen';
|
import QRScannerScreen from './screens/QRScannerScreen';
|
||||||
import HistoryScreen from './screens/HistoryScreen';
|
import HistoryScreen from './screens/HistoryScreen';
|
||||||
import SettingsScreen from './screens/SettingsScreen';
|
import SettingsScreen from './screens/SettingsScreen';
|
||||||
import { QRCodeContext } from './types';
|
import { QRCodeContext } from './types';
|
||||||
import CustomTabBar from './components/CustomTabBar';
|
import CustomTabBar from './components/CustomTabBar';
|
||||||
|
import store from './store';
|
||||||
|
|
||||||
import { withAuthenticator } from '@aws-amplify/ui-react-native';
|
import { withAuthenticator } from '@aws-amplify/ui-react-native';
|
||||||
import { Amplify } from 'aws-amplify';
|
import { Amplify } from 'aws-amplify';
|
||||||
@@ -19,7 +21,6 @@ Amplify.configure(config);
|
|||||||
const Tab = createBottomTabNavigator();
|
const Tab = createBottomTabNavigator();
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [qrCodes, setQrCodes] = useState<{ data: string, bookmarked: boolean, scanResult: { secureConnection: boolean, virusTotalCheck: boolean, redirects: number } }[]>([]);
|
|
||||||
const [scannedData, setScannedData] = useState<string>('');
|
const [scannedData, setScannedData] = useState<string>('');
|
||||||
|
|
||||||
const clearScanData = () => {
|
const clearScanData = () => {
|
||||||
@@ -27,22 +28,22 @@ const App: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QRCodeContext.Provider value={{ qrCodes, setQrCodes }}>
|
<Provider store={store}>
|
||||||
|
<QRCodeContext.Provider value={{ scannedData, setScannedData }}>
|
||||||
<NavigationContainer>
|
<NavigationContainer>
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
initialRouteName="QRScanner"
|
initialRouteName="QRScanner"
|
||||||
tabBar={props => <CustomTabBar {...props} clearScanData={clearScanData} />}
|
tabBar={(props) => <CustomTabBar {...props} clearScanData={clearScanData} />}
|
||||||
>
|
>
|
||||||
<Tab.Screen name="History" component={HistoryScreen} />
|
<Tab.Screen name="History" component={HistoryScreen} />
|
||||||
<Tab.Screen name="QRScanner">
|
<Tab.Screen name="QRScanner">
|
||||||
{(props) => <QRScannerScreen clearScanData={function (): void {
|
{(props) => <QRScannerScreen {...props} clearScanData={clearScanData} />}
|
||||||
throw new Error('Function not implemented.');
|
|
||||||
} } {...props} />}
|
|
||||||
</Tab.Screen>
|
</Tab.Screen>
|
||||||
<Tab.Screen name="Settings" component={SettingsScreen} />
|
<Tab.Screen name="Settings" component={SettingsScreen} />
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</QRCodeContext.Provider>
|
</QRCodeContext.Provider>
|
||||||
|
</Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
6
actions/qrCodeActions.ts
Normal file
6
actions/qrCodeActions.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
import { QRCode } from '../types';
|
||||||
|
|
||||||
|
export const addQRCode = createAction<QRCode>('qrCodes/addQRCode');
|
||||||
|
export const toggleBookmark = createAction<number>('qrCodes/toggleBookmark');
|
||||||
|
export const deleteQRCode = createAction<number | null>('qrCodes/deleteQRCode');
|
||||||
31
api/qrCodeAPI.tsx
Normal file
31
api/qrCodeAPI.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const API_BASE_URL = 'http://192.168.10.247:8080/v1/api/qrcodetypes';
|
||||||
|
|
||||||
|
export const detectQRCodeType = async (data: string) => {
|
||||||
|
console.log('API Call - Detect QR Code Type:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/detect`, { data });
|
||||||
|
console.log('API Response - QR Code Type:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verifyURL = async (data: string) => {
|
||||||
|
console.log('API Call - Verify URL:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/verifyURL`, { data });
|
||||||
|
console.log('API Response - Verify URL:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const virusTotalCheck = async (data: string) => {
|
||||||
|
console.log('API Call - Virus Total Check:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/virusTotalCheck`, { data });
|
||||||
|
console.log('API Response - Virus Total Check:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkRedirects = async (data: string) => {
|
||||||
|
console.log('API Call - Check Redirects:', data);
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/checkRedirects`, { data });
|
||||||
|
console.log('API Response - Check Redirects:', response.data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
@@ -2,43 +2,33 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import { View, Text, StyleSheet, Image, TouchableOpacity, Modal } from 'react-native';
|
import { View, Text, StyleSheet, Image, TouchableOpacity, Modal } from 'react-native';
|
||||||
import QRCode from 'react-native-qrcode-svg';
|
import QRCode from 'react-native-qrcode-svg';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import * as Sharing from 'expo-sharing';
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
|
||||||
// Define Props for ScannedDataBox component
|
// Define Props for ScannedDataBox component
|
||||||
interface ScannedDataBoxProps {
|
interface ScannedDataBoxProps {
|
||||||
data: string;
|
data: string;
|
||||||
dataType: string;
|
dataType: string;
|
||||||
clearScanData: () => void;
|
clearScanData: () => void;
|
||||||
}
|
scanResult: {
|
||||||
|
|
||||||
// Define ScanResult interface
|
|
||||||
interface ScanResult {
|
|
||||||
secureConnection: boolean;
|
secureConnection: boolean;
|
||||||
virusTotalCheck: boolean;
|
virusTotalCheck: boolean;
|
||||||
redirects: number;
|
redirects: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData }) => {
|
const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearScanData, scanResult }) => {
|
||||||
const [scanResult, setScanResult] = useState<ScanResult | null>(null);
|
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [isWebViewVisible, setIsWebViewVisible] = useState(false);
|
||||||
|
console.log("ScannedDataBox -> Data", data);
|
||||||
|
console.log("DataType", dataType);
|
||||||
|
|
||||||
console.log("ScannedDataBox -> Data:", data);
|
|
||||||
console.log("DataType:", dataType);
|
|
||||||
|
|
||||||
// Set scan result based on data
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setScanResult({
|
|
||||||
secureConnection: data.includes('https'), // Example logic
|
|
||||||
virusTotalCheck: !data.includes('danger'), // Example logic
|
|
||||||
redirects: data.includes('redirect') ? 1 : 0, // Example logic
|
|
||||||
});
|
|
||||||
console.log("Scan result set:", scanResult);
|
console.log("Scan result set:", scanResult);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
// Determine the result text based on scan result
|
// Determine the result text based on scan result
|
||||||
const getResultText = () => {
|
const getResultText = () => {
|
||||||
if (!scanResult) {
|
|
||||||
return 'UNKNOWN';
|
|
||||||
}
|
|
||||||
if (!scanResult.secureConnection && !scanResult.virusTotalCheck) {
|
if (!scanResult.secureConnection && !scanResult.virusTotalCheck) {
|
||||||
return 'DANGEROUS';
|
return 'DANGEROUS';
|
||||||
} else if (scanResult.redirects > 0) {
|
} else if (scanResult.redirects > 0) {
|
||||||
@@ -62,6 +52,18 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const shareQRCodeData = async () => {
|
||||||
|
try {
|
||||||
|
await Sharing.shareAsync(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error sharing QR code data:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const openWebView = () => {
|
||||||
|
setIsWebViewVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.dataBox}>
|
<View style={styles.dataBox}>
|
||||||
{/* Close button */}
|
{/* Close button */}
|
||||||
@@ -90,17 +92,17 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
|
|
||||||
{/* Display scan checks */}
|
{/* Display scan checks */}
|
||||||
<Text style={styles.checksText}>Checks</Text>
|
<Text style={styles.checksText}>Checks</Text>
|
||||||
<Text style={styles.checksText}>Secure Connection: {scanResult?.secureConnection ? '✔️' : '✘'}</Text>
|
<Text style={styles.checksText}>Secure Connection: {scanResult.secureConnection ? '✔️' : '✘'}</Text>
|
||||||
<Text style={styles.checksText}>Virus Total Check: {scanResult?.virusTotalCheck ? '✔️' : '✘'}</Text>
|
<Text style={styles.checksText}>Virus Total Check: {scanResult.virusTotalCheck ? '✔️' : '✘'}</Text>
|
||||||
<Text style={styles.checksText}>Redirects: {scanResult ? scanResult.redirects : 'N/A'}</Text>
|
<Text style={styles.checksText}>Redirects: {scanResult.redirects}</Text>
|
||||||
|
|
||||||
{/* Action buttons */}
|
{/* Action buttons */}
|
||||||
<View style={styles.iconContainer}>
|
<View style={styles.iconContainer}>
|
||||||
<TouchableOpacity style={styles.iconButton}>
|
<TouchableOpacity style={styles.iconButton} onPress={shareQRCodeData}>
|
||||||
<Ionicons name="share-social" size={18} color="#2196F3" />
|
<Ionicons name="share-social" size={18} color="#2196F3" />
|
||||||
<Text style={styles.iconText}>Share</Text>
|
<Text style={styles.iconText}>Share</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.iconButton}>
|
<TouchableOpacity style={styles.iconButton} onPress={openWebView}>
|
||||||
<Ionicons name="open" size={18} color="#2196F3" />
|
<Ionicons name="open" size={18} color="#2196F3" />
|
||||||
<Text style={styles.iconText}>Open</Text>
|
<Text style={styles.iconText}>Open</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -139,6 +141,28 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ data, dataType, clearSc
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal
|
||||||
|
visible={isWebViewVisible}
|
||||||
|
transparent={true}
|
||||||
|
animationType="slide"
|
||||||
|
onRequestClose={() => setIsWebViewVisible(false)}
|
||||||
|
>
|
||||||
|
<View style={styles.modalContainer}>
|
||||||
|
<View style={styles.webViewContainer}>
|
||||||
|
<WebView
|
||||||
|
source={{ uri: data }}
|
||||||
|
javaScriptEnabled={false}
|
||||||
|
domStorageEnabled={false}
|
||||||
|
allowFileAccess={false}
|
||||||
|
originWhitelist={['*']}
|
||||||
|
onShouldStartLoadWithRequest={(request) => true}
|
||||||
|
/>
|
||||||
|
<TouchableOpacity style={styles.closeModalButton} onPress={() => setIsWebViewVisible(false)}>
|
||||||
|
<Text style={styles.closeModalButtonText}>Close</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -279,6 +303,13 @@ const styles = StyleSheet.create({
|
|||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
},
|
},
|
||||||
|
webViewContainer: {
|
||||||
|
width: '100%',
|
||||||
|
height: '80%',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
borderRadius: 7.5,
|
||||||
|
overflow: 'hidden'
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default ScannedDataBox;
|
export default ScannedDataBox;
|
||||||
|
|||||||
21
components/SecureWebView.tsx
Normal file
21
components/SecureWebView.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { WebView } from 'react-native-webview';
|
||||||
|
|
||||||
|
// Define the SecureWebView component
|
||||||
|
const SecureWebView = ({ url }) => {
|
||||||
|
return (
|
||||||
|
<WebView
|
||||||
|
source={{ uri: url }} // Load the URL passed as a prop
|
||||||
|
javaScriptEnabled={false} // Disable JavaScript for security
|
||||||
|
domStorageEnabled={false} // Disable DOM storage for security
|
||||||
|
allowFileAccess={false} // Disable file access within the WebView for security
|
||||||
|
originWhitelist={['*']} // Allow all origins to be loaded in the WebView
|
||||||
|
onShouldStartLoadWithRequest={(request) => {
|
||||||
|
// Implement additional URL filtering logic here if needed
|
||||||
|
return true; // Return true to allow the URL to be loaded
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecureWebView;
|
||||||
112
package-lock.json
generated
112
package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"@react-native-community/netinfo": "11.3.1",
|
"@react-native-community/netinfo": "11.3.1",
|
||||||
"@react-navigation/bottom-tabs": "^6.5.20",
|
"@react-navigation/bottom-tabs": "^6.5.20",
|
||||||
"@react-navigation/native": "^6.1.17",
|
"@react-navigation/native": "^6.1.17",
|
||||||
|
"@reduxjs/toolkit": "^2.2.6",
|
||||||
"aws-amplify": "^6.3.8",
|
"aws-amplify": "^6.3.8",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"expo": "~51.0.17",
|
"expo": "~51.0.17",
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"expo-dev-client": "~4.0.19",
|
"expo-dev-client": "~4.0.19",
|
||||||
"expo-image-manipulator": "^12.0.5",
|
"expo-image-manipulator": "^12.0.5",
|
||||||
"expo-image-picker": "~15.0.7",
|
"expo-image-picker": "~15.0.7",
|
||||||
|
"expo-sharing": "~12.0.1",
|
||||||
"expo-status-bar": "~1.12.1",
|
"expo-status-bar": "~1.12.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "^0.74.3",
|
"react-native": "^0.74.3",
|
||||||
@@ -30,7 +32,10 @@
|
|||||||
"react-native-qrcode-svg": "^6.3.1",
|
"react-native-qrcode-svg": "^6.3.1",
|
||||||
"react-native-safe-area-context": "4.10.1",
|
"react-native-safe-area-context": "4.10.1",
|
||||||
"react-native-screens": "3.31.1",
|
"react-native-screens": "3.31.1",
|
||||||
"react-native-svg": "15.2.0"
|
"react-native-svg": "15.2.0",
|
||||||
|
"react-native-webview": "^13.10.4",
|
||||||
|
"react-redux": "^9.1.2",
|
||||||
|
"redux": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
@@ -7351,6 +7356,29 @@
|
|||||||
"nanoid": "^3.1.23"
|
"nanoid": "^3.1.23"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@reduxjs/toolkit": {
|
||||||
|
"version": "2.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz",
|
||||||
|
"integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==",
|
||||||
|
"dependencies": {
|
||||||
|
"immer": "^10.0.3",
|
||||||
|
"redux": "^5.0.1",
|
||||||
|
"redux-thunk": "^3.1.0",
|
||||||
|
"reselect": "^5.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.9.0 || ^17.0.0 || ^18",
|
||||||
|
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@rnx-kit/chromium-edge-launcher": {
|
"node_modules/@rnx-kit/chromium-edge-launcher": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz",
|
||||||
@@ -8747,6 +8775,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
|
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/use-sync-external-store": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
|
||||||
|
},
|
||||||
"node_modules/@types/uuid": {
|
"node_modules/@types/uuid": {
|
||||||
"version": "9.0.8",
|
"version": "9.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
|
||||||
@@ -11438,6 +11471,14 @@
|
|||||||
"invariant": "^2.2.4"
|
"invariant": "^2.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-sharing": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-wBT+WeXwapj/9NWuLJO01vi9bdlchYu/Q/xD8slL/Ls4vVYku8CPqzkTtDFcjLrjtlJqyeHsdQXwKLvORmBIew==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-status-bar": {
|
"node_modules/expo-status-bar": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz",
|
||||||
@@ -12257,10 +12298,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/immer": {
|
"node_modules/immer": {
|
||||||
"version": "9.0.6",
|
"version": "10.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
|
||||||
"integrity": "sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ==",
|
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/immer"
|
"url": "https://opencollective.com/immer"
|
||||||
@@ -16259,6 +16299,27 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-webview": {
|
||||||
|
"version": "13.10.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.10.4.tgz",
|
||||||
|
"integrity": "sha512-kRn70M7vyBS3IDaX2KqyF66ovUkrBS6LiHOgrEmRdZFO0i3hYY0wldEv1fJuKvgQIPMfo7GtGAjozFrk2vQdBw==",
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": "2.0.0",
|
||||||
|
"invariant": "2.2.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-native-webview/node_modules/escape-string-regexp": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-svg-transformer": {
|
"node_modules/react-native-svg-transformer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-svg-transformer/-/react-native-svg-transformer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-svg-transformer/-/react-native-svg-transformer-1.4.0.tgz",
|
||||||
@@ -16373,6 +16434,28 @@
|
|||||||
"async-limiter": "~1.0.0"
|
"async-limiter": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-redux": {
|
||||||
|
"version": "9.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
|
||||||
|
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/use-sync-external-store": "^0.0.3",
|
||||||
|
"use-sync-external-store": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^18.2.25",
|
||||||
|
"react": "^18.0",
|
||||||
|
"redux": "^5.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"redux": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.14.2",
|
"version": "0.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||||
@@ -16436,6 +16519,19 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/redux": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
|
||||||
|
},
|
||||||
|
"node_modules/redux-thunk": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"redux": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/regenerate": {
|
"node_modules/regenerate": {
|
||||||
"version": "1.4.2",
|
"version": "1.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||||
@@ -16569,6 +16665,11 @@
|
|||||||
"path-parse": "^1.0.5"
|
"path-parse": "^1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/reselect": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.8",
|
"version": "1.22.8",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||||
@@ -18428,7 +18529,6 @@
|
|||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||||
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||||
"license": "MIT",
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@react-navigation/bottom-tabs": "^6.5.20",
|
"@react-navigation/bottom-tabs": "^6.5.20",
|
||||||
"@react-navigation/native": "^6.1.17",
|
"@react-navigation/native": "^6.1.17",
|
||||||
"aws-amplify": "^6.3.8",
|
"aws-amplify": "^6.3.8",
|
||||||
|
"@reduxjs/toolkit": "^2.2.6",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"expo": "~51.0.17",
|
"expo": "~51.0.17",
|
||||||
"expo-camera": "~15.0.13",
|
"expo-camera": "~15.0.13",
|
||||||
@@ -28,10 +29,14 @@
|
|||||||
"react-native": "^0.74.3",
|
"react-native": "^0.74.3",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"react-native-qrcode-svg": "^6.3.1",
|
"react-native-qrcode-svg": "^6.3.1",
|
||||||
"react-native-safe-area-context": "4.10.1",
|
"react-native-safe-area-context": "^4.10.4",
|
||||||
"react-native-screens": "3.31.1",
|
"react-native-screens": "3.31.1",
|
||||||
"react-native-svg": "15.2.0",
|
"react-native-svg": "15.2.0",
|
||||||
"expo-dev-client": "~4.0.19"
|
"expo-dev-client": "~4.0.19",
|
||||||
|
"react-native-webview": "^13.10.4",
|
||||||
|
"react-redux": "^9.1.2",
|
||||||
|
"redux": "^5.0.1",
|
||||||
|
"expo-sharing": "~12.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
|
|||||||
30
reducers/qrCodesReducer.ts
Normal file
30
reducers/qrCodesReducer.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
import { QRCode } from '../types';
|
||||||
|
|
||||||
|
const qrCodesSlice = createSlice({
|
||||||
|
name: 'qrCodes',
|
||||||
|
initialState: [] as QRCode[],
|
||||||
|
reducers: {
|
||||||
|
addQRCode(state, action: PayloadAction<QRCode>) {
|
||||||
|
state.push(action.payload);
|
||||||
|
console.log('Added QR code to state:', action.payload);
|
||||||
|
},
|
||||||
|
toggleBookmark(state, action: PayloadAction<number>) {
|
||||||
|
const index = state.length - 1 - action.payload;
|
||||||
|
if (state[index]) {
|
||||||
|
state[index].bookmarked = !state[index].bookmarked;
|
||||||
|
console.log('Toggled bookmark for QR code at index:', index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteQRCode(state, action: PayloadAction<number | null>) {
|
||||||
|
const index = state.length - 1 - (action.payload as number);
|
||||||
|
if (state[index]) {
|
||||||
|
console.log('Deleting QR code at index:', index);
|
||||||
|
state.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { addQRCode, toggleBookmark, deleteQRCode } = qrCodesSlice.actions;
|
||||||
|
export default qrCodesSlice.reducer;
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
import React, { useContext, useState, useEffect } from 'react';
|
import React, { useContext, useState, useEffect } from 'react';
|
||||||
import { View, Text, StyleSheet, FlatList, TouchableOpacity, Image, BackHandler, Modal } from 'react-native';
|
import { View, Text, StyleSheet, FlatList, TouchableOpacity, Image, BackHandler, Modal } from 'react-native';
|
||||||
import { QRCodeContext, QRCode } from '../types'; // Import QRCode type
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import ScannedDataBox from '../components/ScannedDataBox';
|
import ScannedDataBox from '../components/ScannedDataBox';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import { RootState } from '../store';
|
||||||
|
import { QRCode } from '../types';
|
||||||
|
import { toggleBookmark, deleteQRCode } from '../actions/qrCodeActions';
|
||||||
|
|
||||||
const HistoryScreen: React.FC = () => {
|
const HistoryScreen: React.FC = () => {
|
||||||
const qrCodeContext = useContext(QRCodeContext);
|
const dispatch = useDispatch();
|
||||||
|
const qrCodes = useSelector((state: RootState) => state.qrCodes);
|
||||||
const qrCodes = qrCodeContext?.qrCodes || [];
|
|
||||||
const setQrCodes = qrCodeContext?.setQrCodes || (() => {});
|
|
||||||
|
|
||||||
const [selectedData, setSelectedData] = useState<string | null>(null);
|
const [selectedData, setSelectedData] = useState<string | null>(null);
|
||||||
const [selectedScanResult, setSelectedScanResult] = useState<any | null>(null);
|
const [selectedScanResult, setSelectedScanResult] = useState<any | null>(null);
|
||||||
const [selectedType, setSelectedType] = useState<string | null>(null); // Add state for selectedType
|
const [selectedType, setSelectedType] = useState<string | null>(null);
|
||||||
const [showBookmarks, setShowBookmarks] = useState<boolean>(false);
|
const [showBookmarks, setShowBookmarks] = useState<boolean>(false);
|
||||||
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
|
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
|
||||||
const [indexToDelete, setIndexToDelete] = useState<number | null>(null);
|
const [indexToDelete, setIndexToDelete] = useState<number | null>(null);
|
||||||
@@ -28,42 +29,17 @@ const HistoryScreen: React.FC = () => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const backHandler = BackHandler.addEventListener(
|
const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
|
||||||
'hardwareBackPress',
|
|
||||||
backAction
|
|
||||||
);
|
|
||||||
|
|
||||||
return () => backHandler.remove();
|
return () => backHandler.remove();
|
||||||
}, [selectedData]);
|
}, [selectedData]);
|
||||||
|
|
||||||
const toggleBookmark = (index: number) => {
|
const filteredQrCodes = showBookmarks ? qrCodes.filter(qr => qr.bookmarked) : qrCodes.slice().reverse();
|
||||||
setQrCodes((prev: QRCode[]) => {
|
|
||||||
const originalIndex = prev.length - 1 - index; // Compute the original index
|
|
||||||
const newQrCodes = [...prev];
|
|
||||||
newQrCodes[originalIndex].bookmarked = !newQrCodes[originalIndex].bookmarked;
|
|
||||||
console.log('Toggled bookmark for QR code at index:', originalIndex);
|
|
||||||
return newQrCodes;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteQRCode = () => {
|
const handleItemPress = (item: QRCode) => {
|
||||||
if (indexToDelete !== null) {
|
|
||||||
setQrCodes((prev: QRCode[]) => {
|
|
||||||
const originalIndex = prev.length - 1 - indexToDelete; // Compute the original index
|
|
||||||
console.log('Deleting QR code at index:', originalIndex);
|
|
||||||
return prev.filter((_, i) => i !== originalIndex);
|
|
||||||
});
|
|
||||||
setIndexToDelete(null);
|
|
||||||
setIsModalVisible(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const filteredQrCodes = (showBookmarks ? qrCodes.filter(qr => qr.bookmarked) : qrCodes.slice().reverse());
|
|
||||||
|
|
||||||
const handleItemPress = (item: any) => {
|
|
||||||
setSelectedData(item.data);
|
setSelectedData(item.data);
|
||||||
setSelectedScanResult(item.scanResult);
|
setSelectedScanResult(item.scanResult);
|
||||||
setSelectedType(item.type); // Set the selected type
|
setSelectedType(item.type);
|
||||||
console.log('Selected QR code data:', item.data);
|
console.log('Selected QR code data:', item.data);
|
||||||
console.log('Selected QR code type:', item.type);
|
console.log('Selected QR code type:', item.type);
|
||||||
};
|
};
|
||||||
@@ -77,23 +53,17 @@ const HistoryScreen: React.FC = () => {
|
|||||||
const clearSelectedData = () => {
|
const clearSelectedData = () => {
|
||||||
setSelectedData(null);
|
setSelectedData(null);
|
||||||
setSelectedScanResult(null);
|
setSelectedScanResult(null);
|
||||||
setSelectedType(null); // Clear the selected type
|
setSelectedType(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{/* Header for toggling between History and Bookmarks */}
|
{/* Header for toggling between History and Bookmarks */}
|
||||||
<View style={styles.headerContainer}>
|
<View style={styles.headerContainer}>
|
||||||
<TouchableOpacity onPress={() => {
|
<TouchableOpacity onPress={() => { setShowBookmarks(false); clearSelectedData(); }}>
|
||||||
setShowBookmarks(false);
|
|
||||||
clearSelectedData();
|
|
||||||
}}>
|
|
||||||
<Text style={!showBookmarks ? styles.headerTextActive : styles.headerTextInactive}>History</Text>
|
<Text style={!showBookmarks ? styles.headerTextActive : styles.headerTextInactive}>History</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => {
|
<TouchableOpacity onPress={() => { setShowBookmarks(true); clearSelectedData(); }}>
|
||||||
setShowBookmarks(true);
|
|
||||||
clearSelectedData();
|
|
||||||
}}>
|
|
||||||
<Text style={showBookmarks ? styles.headerTextActive : styles.headerTextInactive}>Bookmarks</Text>
|
<Text style={showBookmarks ? styles.headerTextActive : styles.headerTextInactive}>Bookmarks</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
@@ -121,7 +91,7 @@ const HistoryScreen: React.FC = () => {
|
|||||||
})}</Text>
|
})}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.itemRight}>
|
<View style={styles.itemRight}>
|
||||||
<TouchableOpacity onPress={() => toggleBookmark(index)}>
|
<TouchableOpacity onPress={() => dispatch(toggleBookmark(index))}>
|
||||||
<Ionicons name={item.bookmarked ? "bookmark" : "bookmark-outline"} size={24} color={item.bookmarked ? "#2196F3" : "#ff69b4"} />
|
<Ionicons name={item.bookmarked ? "bookmark" : "bookmark-outline"} size={24} color={item.bookmarked ? "#2196F3" : "#ff69b4"} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={() => confirmDelete(index)}>
|
<TouchableOpacity onPress={() => confirmDelete(index)}>
|
||||||
@@ -146,7 +116,7 @@ const HistoryScreen: React.FC = () => {
|
|||||||
<Text style={styles.modalTitle}>Are you sure?</Text>
|
<Text style={styles.modalTitle}>Are you sure?</Text>
|
||||||
<Text style={styles.modalText}>If bookmarked, this will be removed from both History and Bookmarks.</Text>
|
<Text style={styles.modalText}>If bookmarked, this will be removed from both History and Bookmarks.</Text>
|
||||||
<View style={styles.modalButtons}>
|
<View style={styles.modalButtons}>
|
||||||
<TouchableOpacity style={styles.modalButton} onPress={deleteQRCode}>
|
<TouchableOpacity style={styles.modalButton} onPress={() => dispatch(deleteQRCode(indexToDelete))}>
|
||||||
<Text style={styles.modalButtonText}>Yes, Delete</Text>
|
<Text style={styles.modalButtonText}>Yes, Delete</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.modalButton} onPress={() => setIsModalVisible(false)}>
|
<TouchableOpacity style={styles.modalButton} onPress={() => setIsModalVisible(false)}>
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ import { Ionicons } from '@expo/vector-icons'; // For icons
|
|||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import * as ImagePicker from 'expo-image-picker';
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
import ScannedDataBox from '../components/ScannedDataBox';
|
import ScannedDataBox from '../components/ScannedDataBox';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { addQRCode } from '../actions/qrCodeActions'; // Assuming you have actions defined for Redux
|
||||||
|
import { detectQRCodeType, verifyURL, checkRedirects } from '../api/qrCodeAPI'; // Import utility functions
|
||||||
|
|
||||||
// Main Function
|
// Main Function
|
||||||
const QRScannerScreen: React.FC = () => {
|
const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanData }) => {
|
||||||
const navigation = useNavigation(); // call Navigation bar
|
const navigation = useNavigation(); // call Navigation bar
|
||||||
const [showSplash, setShowSplash] = useState<boolean>(true); // call splash screen
|
const dispatch = useDispatch(); // Use dispatch for Redux actions
|
||||||
|
|
||||||
|
const [showSplash, setShowSplash] = useState<boolean>(true); // call splash screen
|
||||||
const qrCodeContext = useContext(QRCodeContext); // From ./types.ts
|
const qrCodeContext = useContext(QRCodeContext); // From ./types.ts
|
||||||
const { qrCodes, setQrCodes } = qrCodeContext || { qrCodes: [], setQrCodes: () => {} };
|
const { qrCodes, setQrCodes } = qrCodeContext || { qrCodes: [], setQrCodes: () => {} };
|
||||||
|
|
||||||
@@ -22,6 +26,11 @@ const QRScannerScreen: React.FC = () => {
|
|||||||
const [dataType, setDataType] = useState<string>(''); // State for data type
|
const [dataType, setDataType] = useState<string>(''); // State for data type
|
||||||
const [enableTorch, setEnableTorch] = useState<boolean>(false); // State for torch
|
const [enableTorch, setEnableTorch] = useState<boolean>(false); // State for torch
|
||||||
|
|
||||||
|
// Add state variables for scan results
|
||||||
|
const [secureConnection, setSecureConnection] = useState<boolean | null>(null);
|
||||||
|
const [virusTotalCheck, setVirusTotalCheck] = useState<boolean | null>(null);
|
||||||
|
const [redirects, setRedirects] = useState<number | null>(null);
|
||||||
|
|
||||||
// Request Camera Permission and initialize the app
|
// Request Camera Permission and initialize the app
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeApp = async () => {
|
const initializeApp = async () => {
|
||||||
@@ -46,23 +55,31 @@ const QRScannerScreen: React.FC = () => {
|
|||||||
const handlePayload = async (payload: string) => {
|
const handlePayload = async (payload: string) => {
|
||||||
setScanned(true);
|
setScanned(true);
|
||||||
console.log("Scanning Completed. Payload is:", payload);
|
console.log("Scanning Completed. Payload is:", payload);
|
||||||
const type = await sendToAPIServer(payload);
|
|
||||||
|
const type = await detectQRCodeType(payload);
|
||||||
|
const secureConnectionResult = await verifyURL(payload);
|
||||||
|
const redirectResult = await checkRedirects(payload);
|
||||||
|
|
||||||
|
setSecureConnection(secureConnectionResult.isSecure);
|
||||||
|
setVirusTotalCheck(!secureConnectionResult.isMalicious); // Assuming you have virusTotalCheck logic integrated here
|
||||||
|
setRedirects(redirectResult.redirects);
|
||||||
|
|
||||||
const qrCode = {
|
const qrCode = {
|
||||||
data: payload,
|
data: payload,
|
||||||
type,
|
type,
|
||||||
scanResult: {
|
scanResult: {
|
||||||
secureConnection: true, // Placeholder, replace with actual logic
|
secureConnection: secureConnectionResult.isSecure,
|
||||||
virusTotalCheck: true, // Placeholder, replace with actual logic
|
virusTotalCheck: !secureConnectionResult.isMalicious,
|
||||||
redirects: 0 // Placeholder, replace with actual logic
|
redirects: redirectResult.redirects
|
||||||
}
|
},
|
||||||
|
bookmarked: false // by default
|
||||||
};
|
};
|
||||||
|
|
||||||
setScannedData(payload);
|
setScannedData(payload);
|
||||||
console.log("Payload received:", payload);
|
console.log("Payload received:", payload);
|
||||||
console.log("Type received from server:", type);
|
console.log("Type received from server:", type);
|
||||||
setDataType(type);
|
setDataType(type);
|
||||||
setQrCodes([...qrCodes, qrCode]);
|
dispatch(addQRCode(qrCode)); // Dispatch action to save QR code data
|
||||||
console.log("QR code data added to history");
|
console.log("QR code data added to history");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,7 +198,16 @@ const QRScannerScreen: React.FC = () => {
|
|||||||
|
|
||||||
{scannedData !== '' && (
|
{scannedData !== '' && (
|
||||||
<View style={styles.scannedDataBox}>
|
<View style={styles.scannedDataBox}>
|
||||||
<ScannedDataBox data={scannedData} dataType={dataType} clearScanData={clearScanDataInternal} />
|
<ScannedDataBox
|
||||||
|
data={scannedData}
|
||||||
|
dataType={dataType}
|
||||||
|
clearScanData={clearScanDataInternal}
|
||||||
|
scanResult={{
|
||||||
|
secureConnection,
|
||||||
|
virusTotalCheck,
|
||||||
|
redirects
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
11
store.ts
Normal file
11
store.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
|
import qrCodesReducer from './reducers/qrCodesReducer';
|
||||||
|
|
||||||
|
const store = configureStore({
|
||||||
|
reducer: {
|
||||||
|
qrCodes: qrCodesReducer,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
export default store;
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "expo/tsconfig.base",
|
"compilerOptions": {},
|
||||||
"compilerOptions": {
|
"extends": "expo/tsconfig.base"
|
||||||
"strict": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
14
types.ts
14
types.ts
@@ -1,7 +1,8 @@
|
|||||||
import { createContext } from "react";
|
import { createContext } from 'react';
|
||||||
|
|
||||||
export interface QRCode {
|
export interface QRCode {
|
||||||
data: string;
|
data: string;
|
||||||
|
type: string;
|
||||||
bookmarked: boolean;
|
bookmarked: boolean;
|
||||||
scanResult: {
|
scanResult: {
|
||||||
secureConnection: boolean;
|
secureConnection: boolean;
|
||||||
@@ -10,12 +11,7 @@ export interface QRCode {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QRCodeContextProps {
|
export const QRCodeContext = createContext<{
|
||||||
qrCodes: QRCode[];
|
qrCodes: QRCode[];
|
||||||
setQrCodes: (codes: QRCode[]) => void;
|
setQrCodes: React.Dispatch<React.SetStateAction<QRCode[]>>;
|
||||||
setCurrentScannedData?: (data: string) => void;
|
} | null>(null);
|
||||||
toggleBookmark?: (index: number) => void;
|
|
||||||
deleteQRCode?: (index: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const QRCodeContext = createContext<QRCodeContextProps | null>(null);
|
|
||||||
Reference in New Issue
Block a user