From 7f7f686ef858436e85b531033081d1b945f5a4ef Mon Sep 17 00:00:00 2001 From: Isky Date: Sat, 3 Aug 2024 23:07:41 +0800 Subject: [PATCH] Recommit, without build falire (native_modules.gradle' line: 401, finished with non-zero exit value 1) --- .env.development | 2 +- api/qrCodeAPI.tsx | 91 ++++++++------- components/ScannedDataBox.tsx | 192 ++++++++++++++++++++----------- screens/HistoryScreen.tsx | 139 ++++++++++------------ screens/QRScannerScreen.tsx | 211 +++++++++++++++------------------- screens/SettingsScreen.tsx | 106 +++++++++++------ 6 files changed, 404 insertions(+), 337 deletions(-) diff --git a/.env.development b/.env.development index 34fe0a0..f8cda80 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,2 @@ NODE_ENV=development -BASE_URL=http://192.168.1.30:8080 \ No newline at end of file +BASE_URL=http://192.168.10.247:8080 \ No newline at end of file diff --git a/api/qrCodeAPI.tsx b/api/qrCodeAPI.tsx index 07e27a4..2681514 100644 --- a/api/qrCodeAPI.tsx +++ b/api/qrCodeAPI.tsx @@ -2,18 +2,22 @@ import axios from 'axios'; import Constants from 'expo-constants'; const { API_BASE_URL, ENVIRONMENT } = Constants.expoConfig.extra; import { fetchAuthSession, getCurrentUser } from 'aws-amplify/auth'; -//const API_BASE_URL = 'https://localhost:8443'; -const API_URL_DETECT = "/v1/qrcodetypes/detect"; -const API_URL_VERIFY_URL = "/v1/qrcodetypes/verifyURL" -const API_URL_VIRUS_TOTAL_CHECK = "/v1/qrcodetypes/virusTotalCheck" -const API_URL_CHECK_REDIRECTS = "/v1/qrcodetypes/checkRedirects" -const API_URL_GET_HISTORIES = "/v1/user/getScannedHistories" -const API_URL_DELETE_SCANNED_HISTORY = "/v1/user/deleteScannedHistories" -const API_URL_GET_BOOKMARKS = "/v1/user/getBookmarks" -const API_URL_SET_BOOKMARK = "/v1/user/setBookmark" -const API_URL_DELETE_BOOKMARK = "/v1/user/deleteBookmark" -const API_URL_GET_SCANNED_GMAILS = "/v1/gmail/getEmails" + +const API_URL_SCAN = "/v1/qrcodetypes/scan"; +const API_URL_GET_QR_DETAILS = "/v1/qrcodetypes/getQRDetails"; + + +const API_URL_GET_HISTORIES = "/v1/user/getScannedHistories"; +const API_URL_DELETE_SCANNED_HISTORY = "/v1/user/deleteScannedHistories"; +const API_URL_DELETE_ALL_HISTORIES = "/v1/user/deleteAllScannedHistories"; +const API_URL_GET_BOOKMARKS = "/v1/user/getBookmarks"; +const API_URL_SET_BOOKMARK = "/v1/user/setBookmark"; +const API_URL_DELETE_BOOKMARK = "/v1/user/deleteBookmark"; + + +const API_URL_GET_SCANNED_GMAILS = "/v1/gmail/getEmails"; +const API_URL_GET_USER = "/v1/user/getUser"; // New endpoint // Create an Axios instance const apiClient = axios.create({ @@ -36,6 +40,9 @@ apiClient.interceptors.request.use( } } + // Log the X-USER-ID header + console.log('X-USER-ID:', config.headers['X-USER-ID']); + return config; }, (error) => { @@ -47,22 +54,17 @@ apiClient.interceptors.request.use( export const apiRequest = async (config) => { try { console.log("ENVIRONMENT:", ENVIRONMENT); - console.log(`API Call - ${config.method.toUpperCase()}:`, config.url, config.data || ''); console.log(config); const response = await apiClient(config); console.log('API Response:', response.data); - return response.data; } catch (error) { if (error.response) { - // The request was made and the server responded with a status code that falls out of the range of 2xx console.error('API Error - Response:', error.response.data); } else if (error.request) { - // The request was made but no response was received console.error('API Error - No Response:', error.request); } else { - // Something happened in setting up the request that triggered an Error console.error('API Error - General:', error.message); } throw error; @@ -81,37 +83,29 @@ const fetchUserId = async () => { return currentUser.userId; }; -export const detectQRCodeType = async (data) => { +// Function to handle /scan request +export const scanQRCode = async (data) => { return apiRequest({ method: 'post', - url: `${API_BASE_URL}${API_URL_DETECT}`, + url: `${API_BASE_URL}${API_URL_SCAN}`, data: { data } }); }; -export const verifyURL = async (data) => { +// Function to get QR code details +export const getQRCodeDetails = async (qrCodeId: string) => { return apiRequest({ - method: 'post', - url: `${API_BASE_URL}${API_URL_VERIFY_URL}`, - data: { data } + method: 'get', + url: `${API_BASE_URL}${API_URL_GET_QR_DETAILS}`, + headers: { 'QR-ID': qrCodeId }, }); }; -export const virusTotalCheck = async (data) => { - return apiRequest({ - method: 'post', - url: `${API_BASE_URL}${API_URL_VIRUS_TOTAL_CHECK}`, - data: { data } - }); -}; -export const checkRedirects = async (data) => { - return apiRequest({ - method: 'post', - url: `${API_BASE_URL}${API_URL_CHECK_REDIRECTS}`, - data: { data } - }); -}; + + +//----------- + // GET User's Scanned Histories export const getScannedHistories = async () => { return apiRequest({ @@ -119,7 +113,8 @@ export const getScannedHistories = async () => { url: `${API_BASE_URL}${API_URL_GET_HISTORIES}` }); }; -// GET All User's Bookmark + +// GET All User's Bookmarks export const getAllUserBookmarks = async () => { return apiRequest({ method: 'get', @@ -132,7 +127,7 @@ export const setBookmark = async (qrCodeId: string) => { return apiRequest({ method: 'post', url: `${API_BASE_URL}${API_URL_SET_BOOKMARK}`, - data: { "qrCodeId": qrCodeId } + data: { qrCodeId } }); }; @@ -141,7 +136,7 @@ export const deleteBookmark = async (qrCodeId: string) => { return apiRequest({ method: 'put', url: `${API_BASE_URL}${API_URL_DELETE_BOOKMARK}`, - data: { "qrCodeId": qrCodeId } + data: { qrCodeId } }); }; @@ -150,7 +145,15 @@ export const deleteScannedHistory = async (qrCodeId: string) => { return apiRequest({ method: 'put', url: `${API_BASE_URL}${API_URL_DELETE_SCANNED_HISTORY}`, - data: { "qrCodeId": qrCodeId } + data: { qrCodeId } + }); +}; + +// Function to delete all scanned histories +export const deleteAllScannedHistories = async () => { + return apiRequest({ + method: 'put', + url: `${API_BASE_URL}${API_URL_DELETE_ALL_HISTORIES}`, }); }; @@ -160,4 +163,12 @@ export const getScannedGmails = async () => { method: 'get', url: `${API_BASE_URL}${API_URL_GET_SCANNED_GMAILS}` }); +}; + +// Get user information +export const getUserInfo = async () => { + return apiRequest({ + method: 'get', + url: `${API_BASE_URL}${API_URL_GET_USER}`, + }); }; \ No newline at end of file diff --git a/components/ScannedDataBox.tsx b/components/ScannedDataBox.tsx index afcd238..1618179 100644 --- a/components/ScannedDataBox.tsx +++ b/components/ScannedDataBox.tsx @@ -1,40 +1,78 @@ import React, { useEffect, useState } from 'react'; -import { View, Text, StyleSheet, Image, TouchableOpacity, Modal } from 'react-native'; +import { View, Text, StyleSheet, Image, TouchableOpacity, Modal, ActivityIndicator, Alert } from 'react-native'; import QRCode from 'react-native-qrcode-svg'; import { Ionicons } from '@expo/vector-icons'; -import * as Sharing from 'expo-sharing'; -import { WebView } from 'react-native-webview'; +//import * as Sharing from 'expo-sharing'; +//import * as Clipboard from 'expo-clipboard'; // >.< +import { getQRCodeDetails } from '../api/qrCodeAPI'; +import SecureWebView from '../components/SecureWebView'; // Import the SecureWebView component // Define Props for ScannedDataBox component interface ScannedDataBoxProps { - data: string; - dataType: string; + qrCodeId: string; clearScanData: () => void; - scanResult: { - secureConnection: boolean; - virusTotalCheck: boolean; - redirects: number; - }; } -const ScannedDataBox: React.FC = ({ data, dataType, clearScanData, scanResult }) => { +const ScannedDataBox: React.FC = ({ qrCodeId, clearScanData }) => { const [isModalVisible, setIsModalVisible] = useState(false); + const [qrDetails, setQrDetails] = useState(null); const [isWebViewVisible, setIsWebViewVisible] = useState(false); - console.log("ScannedDataBox -> Data", data); - console.log("DataType", dataType); + const [webViewUrl, setWebViewUrl] = useState(''); useEffect(() => { - console.log("Scan result set:", scanResult); - }, [data]); + const fetchQRDetails = async () => { + try { + const details = await getQRCodeDetails(qrCodeId); + setQrDetails(details.qrcode); + console.log('details for scannedDataBOX:', details); + } catch (error) { + console.error('Error fetching QR details:', error); + } + }; + + if (qrCodeId) { + fetchQRDetails(); + } + }, [qrCodeId]); + + if (!qrDetails) { + return ( + + + + ); + } + + // Clipboard Button KIV...cause it broke everything...... +/* const copyToClipboard = async () => { + try { + const contents = qrDetails.data?.contents || 'Undefined'; + await Clipboard.setStringAsync(contents); + Alert.alert('Copied to Clipboard', 'The QR code content has been copied to your clipboard.'); + } catch (error) { + console.error('Error copying to clipboard:', error); + } + }; + */ + + // Handle cases where data might be undefined + const data = qrDetails.data || {}; + const details = qrDetails.details || {}; + const type = data.info?.type || 'Undefined'; + const contents = data.contents || 'Undefined'; + const secureConnection = details.hstsHeader?.includes('HSTS Header') ? '✔️' : '✘'; + const redirects = details.redirect || 0; + const securityHeaders = details.hstsHeader || ['No Headers']; + const redirectChain = details.redirectChain || ['No Redirects']; // Determine the result text based on scan result const getResultText = () => { - if (!scanResult.secureConnection && !scanResult.virusTotalCheck) { + if (secureConnection === '✘' || redirects > 0) { return 'DANGEROUS'; - } else if (scanResult.redirects > 0) { - return 'WARNING'; - } else { + } else if (secureConnection === '✔️' && redirects === 0) { return 'SAFE'; + } else { + return 'WARNING'; } }; @@ -52,15 +90,9 @@ const ScannedDataBox: React.FC = ({ data, dataType, clearSc } }; - const shareQRCodeData = async () => { - try { - await Sharing.shareAsync(data); - } catch (error) { - console.error('Error sharing QR code data:', error); - } - }; - - const openWebView = () => { + // Open the WebView for the URL + const openWebView = (url: string) => { + setWebViewUrl(url); setIsWebViewVisible(true); }; @@ -70,45 +102,66 @@ const ScannedDataBox: React.FC = ({ data, dataType, clearSc - + {/* Display scanned data */} - {data} + {contents} - {new Date().toLocaleString()} + {data.createdAt ? new Date(data.createdAt).toLocaleString() : 'Invalid Date'} - + Result: {getResultText()} - + {/* Display data type */} - Type: {dataType} + Type: {type} {'\n'} - + {/* Display scan checks */} - Checks - Secure Connection: {scanResult.secureConnection ? '✔️' : '✘'} - Virus Total Check: {scanResult.virusTotalCheck ? '✔️' : '✘'} - Redirects: {scanResult.redirects} - + {type === 'URL' && ( + <> + Checks + Secure Connection: {secureConnection} + Redirects: {redirects} + Alert.alert('Redirect Chain', redirectChain.join('\n'))}> + Show all redirects + + + )} + + {type === 'SMS' && ( + <> + Recipient Phone Number: {details.phone || 'Undefined'} + Message Content: {details.message || 'Undefined'} + + )} + + {type === 'TEXT' && ( + <> + Content: {contents} + + )} + {/* Action buttons */} - - - Share - - - - Open + + + Copy + {type === 'URL' && ( + openWebView(contents)}> + + Open + + )} - + {/* More information button */} More Information setIsModalVisible(true)}> @@ -116,7 +169,7 @@ const ScannedDataBox: React.FC = ({ data, dataType, clearSc Security Headers - + {/* Modal for security headers */} = ({ data, dataType, clearSc Security Headers - Name: Strict-Transport-Security - Value: max-age=31536000; includeSubDomains - Name: X-Frame-Options - Value: DENY - Name: X-Content-Type-Options - Value: nosniff - Name: Content-Security-Policy - Value: default-src 'self' + {securityHeaders.map((header, index) => ( + {header} + ))} setIsModalVisible(false)}> Close + + {/* SecureWebView Modal */} = ({ data, dataType, clearSc > - true} - /> + setIsWebViewVisible(false)}> Close @@ -303,13 +346,28 @@ const styles = StyleSheet.create({ fontSize: 12, color: '#fff', }, + loadingContainer: { + justifyContent: 'center', + alignItems: 'center', + }, + showAllButton: { + backgroundColor: '#2196F3', + borderRadius: 7.5, + padding: 5, + marginTop: 5, + }, + showAllButtonText: { + color: '#fff', + fontSize: 12, + textAlign: 'center', + }, webViewContainer: { width: '100%', height: '80%', backgroundColor: 'white', borderRadius: 7.5, overflow: 'hidden' - }, + } }); -export default ScannedDataBox; +export default ScannedDataBox; \ No newline at end of file diff --git a/screens/HistoryScreen.tsx b/screens/HistoryScreen.tsx index 5dea21b..abce2da 100644 --- a/screens/HistoryScreen.tsx +++ b/screens/HistoryScreen.tsx @@ -1,5 +1,5 @@ -import React, { useCallback, useState, useEffect, useRef } from 'react'; -import { View, Text, StyleSheet, FlatList, TouchableOpacity, Image, BackHandler, Modal } from 'react-native'; +import React, { useCallback, useState, useEffect } from 'react'; +import { View, Text, StyleSheet, FlatList, TouchableOpacity, Image, Modal, ActivityIndicator } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; import ScannedDataBox from '../components/ScannedDataBox'; import { Ionicons } from '@expo/vector-icons'; @@ -20,6 +20,9 @@ const HistoryScreen: React.FC = () => { const [historiesLoading, setHistoriesLoading] = useState(false); const [historiesError, setHistoriesError] = useState(null); + const [selectedQrCodeId, setSelectedQrCodeId] = useState(null); + + const fetchHistories = useCallback(async () => { if (!userAttributes?.sub) return; @@ -27,8 +30,6 @@ const HistoryScreen: React.FC = () => { setHistoriesLoading(true); const historiesData = await getScannedHistories(); dispatch(setScannedHistories(historiesData)); - - setHistoriesLoading(false); } catch (error: any) { setHistoriesError(error.message); } finally { @@ -50,43 +51,17 @@ const HistoryScreen: React.FC = () => { }, [dispatch, userAttributes]); - const [selectedData, setSelectedData] = useState(null); - const [selectedScanResult, setSelectedScanResult] = useState(null); - const [selectedType, setSelectedType] = useState(null); - - useEffect(() => { - const backAction = () => { - if (selectedData) { - setSelectedData(null); - setSelectedScanResult(null); - setSelectedType(null); - return true; - } - return false; - }; - - const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction); - - return () => backHandler.remove(); - }, [selectedData]); - const filteredQrCodes = showBookmarks ? histories.filter(qr => qr.bookmarked) : histories; const handleItemPress = (item: QRCodeType) => { - // setSelectedData(item.data); - // setSelectedScanResult(item.scanResult); - // setSelectedType(item.type); - //setSelectedData(item.contents); - setSelectedType(item.data.type); - console.log('Selected QR code data:', item); - // console.log('Selected QR code type:', item.type); + setSelectedQrCodeId(item.data.id || null); }; const clearSelectedData = () => { - setSelectedData(null); - setSelectedScanResult(null); - setSelectedType(null); + setSelectedQrCodeId(null); }; + + return ( @@ -99,51 +74,57 @@ const HistoryScreen: React.FC = () => { Bookmarks - {/* Display scanned data details */} - {selectedData && ( - - - + + {/* Loading Indicator */} + {historiesLoading && } + + {/* Display message when there are no histories or bookmarks */} + {!historiesLoading && filteredQrCodes.length === 0 && ( + + {showBookmarks ? 'No bookmarks available' : 'No history available'} + )} + + {/* Display scanned data details */} + {selectedQrCodeId && ( + + + +)} + {/* List of QR codes */} { - // console.log('Rendering QR code item:', item); - return ( - - - handleItemPress(item)} style={styles.itemContent}> - - - {item.data.contents} - - - {new Date(item.data.createdAt).toLocaleDateString('en-GB', { - day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'})} - - - - dispatch(toggleBookmark({ userId: userAttributes.sub, qrCode: item}))}> - - - { - setQrCodeToDelete(item.data.id); - setIsModalVisible(true); - }}> - - - + renderItem={({ item }) => ( + + + handleItemPress(item)} style={styles.itemContent}> + + + {item.data.contents} + + + {new Date(item.data.createdAt).toLocaleDateString('en-GB', { + day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'})} + - ); - }} - keyExtractor={(item, index) => { - //console.log(item, index); - - return index.toString(); - }} + + dispatch(toggleBookmark({ userId: userAttributes.sub, qrCode: item}))}> + + + { + setQrCodeToDelete(item.data.id); + setIsModalVisible(true); + }}> + + + + + )} + keyExtractor={(item, index) => index.toString()} contentContainerStyle={styles.flatListContent} /> + {/* Modal for delete confirmation */} void }> = ({ clearScanData }) => { - const navigation = useNavigation(); // call Navigation bar + const navigation = useNavigation(); // Navigation hook const dispatch = useDispatch(); // Use dispatch for Redux actions - const [showSplash, setShowSplash] = useState(true); // call splash screen - const qrCodeContext = useContext(QRCodeContext); // From ./types.ts - const { qrCodes, setQrCodes } = qrCodeContext || { qrCodes: [], setQrCodes: () => {} }; - + // State variables + const [showSplash, setShowSplash] = useState(true); // State for splash screen visibility const [hasPermission, setHasPermission] = useState(null); const [scanned, setScanned] = useState(false); - const [scannedData, setScannedData] = useState(''); // State for QR scanned Data - const [dataType, setDataType] = useState(''); // State for data type + const [qrCodeId, setQRCodeId] = useState(null); // State for QR code ID const [enableTorch, setEnableTorch] = useState(false); // State for torch const [cameraVisible, setCameraVisible] = useState(true); // State to control camera visibility - - // State to control the visibility of the modal - const [isSettingsModalVisible, setIsSettingsModalVisible] = useState(false); - - // Add state variables for scan results - const [secureConnection, setSecureConnection] = useState(null); - const [virusTotalCheck, setVirusTotalCheck] = useState(null); - const [redirects, setRedirects] = useState(null); + const [isScannedDataBoxVisible, setIsScannedDataBoxVisible] = useState(false); // State for ScannedDataBox modal visibility + const [isSettingsModalVisible, setIsSettingsModalVisible] = useState(false); // State for modal visibility // Request Camera Permission and initialize the app useEffect(() => { @@ -43,79 +32,71 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat setHasPermission(status === 'granted'); setShowSplash(false); console.log("Camera permissions initialized"); + + // Fetch and log user information + fetchUserInformation(); }; initializeApp(); }, []); + // Focus effect to enable camera and clear data on focus + useFocusEffect( + useCallback(() => { + setCameraVisible(true); + clearScanDataInternal(); + console.log("Screen focused, scan data cleared and camera enabled"); + + return () => { + setCameraVisible(false); + console.log("Screen unfocused, camera disabled"); + }; + }, [navigation]) + ); + // Clear Scan Data const clearScanDataInternal = () => { - setScannedData(''); setScanned(false); - setDataType(''); + setQRCodeId(null); console.log("Scan data cleared"); }; + // Handle scanning of payload (QR code data) and get the QR-ID const handlePayload = async (payload: string) => { setScanned(true); - console.log("Scanning Completed. Payload is:", 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 = { - data: payload, - type, - scanResult: { - secureConnection: secureConnectionResult.isSecure, - virusTotalCheck: !secureConnectionResult.isMalicious, - redirects: redirectResult.redirects - }, - bookmarked: false // by default - }; - - setScannedData(payload); - console.log("Payload received:", payload); - console.log("Type received from server:", type); - setDataType(type); - dispatch(addQRCode(qrCode)); // Dispatch action to save QR code data - console.log("QR code data added to history"); - }; - - const sendToAPIServer = async (payload: string): Promise => { - console.log('Sending QR code data to backend:', payload); + console.info("Decoded QR Code, Payload is: ", payload); try { - const response = await axios.post('http://192.168.1.30:8080/v1/qrcodetypes/scan', { - data: payload, - }, { - headers: { - 'Content-Type': 'application/json', - }, - }); - console.log('Response from backend:', response.data); - return response.data; + const response = await scanQRCode(payload); + const qrCodeId = response.qrcode.data.id; + // Store the QR code ID for later use + setQRCodeId(qrCodeId); + setIsScannedDataBoxVisible(true); // Show ScannedDataBox modal + + // Optionally, show a message or perform another action + console.log("QR code scanned successfully, ID:", qrCodeId); } catch (error) { - console.error('Error detecting QR code type:', error); - return 'UNKNOWN'; + console.error("Error scanning QR code:", error); } }; + // Fetch and log user information + const fetchUserInformation = async () => { + try { + const userInfo = await getUserInfo(); + console.log('User Info:', userInfo); + } catch (error) { + console.error('Error fetching user information:', error); + } + }; + + // Toggle torch (flashlight) on/off const toggleTorch = () => { setEnableTorch((prev) => !prev); console.log("Torch toggled:", enableTorch ? "off" : "on"); }; - const handleTestScan = () => { - handlePayload('TEST123'); - console.log("Test scan executed"); - }; - + // Read QR from image const readQRFromImage = async () => { clearScanDataInternal(); console.log("Reading QR code from image"); @@ -133,30 +114,15 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat handlePayload(scannedResult[0].data); console.log('QR code data from image:', scannedResult[0].data); } else { - setScannedData("No QR Code Found"); console.log("No QR code found in the selected image"); - Alert.alert('No QR code found in the selected image.'); } } catch (error) { console.error('Error scanning QR code from image:', error); - Alert.alert('Failed to scan QR code from image.'); } } }; - useFocusEffect( - useCallback(() => { - setCameraVisible(true); - clearScanDataInternal(); - console.log("Screen focused, scan data cleared and camera enabled"); - - return () => { - setCameraVisible(false); - console.log("Screen unfocused, camera disabled"); - }; - }, [navigation]) - ); - + // Conditional rendering based on state if (showSplash) { return ( @@ -175,7 +141,7 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat return ( - SafeQR v0.89 + SafeQR Welcome to SafeQR code Scanner @@ -196,20 +162,16 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat - {scannedData !== '' && ( - - - - )} + {/* Scanned Data Box */} + {isScannedDataBoxVisible && ( + + setIsScannedDataBoxVisible(false)} + /> + +)} + {/* Settings Icon */} setIsSettingsModalVisible(true)} style={styles.settingsButton}> @@ -222,9 +184,10 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat transparent={true} visible={isSettingsModalVisible} onRequestClose={() => setIsSettingsModalVisible(false)} + style={styles.settingsModal} > - - + + setIsSettingsModalVisible(false)} style={styles.closeButton}> Close @@ -290,13 +253,18 @@ const styles = StyleSheet.create({ backgroundColor: '#000', borderRadius: 25, }, - scannedDataBox: { + scannedDataBoxPopup: { position: 'absolute', top: '10%', left: '5%', right: '5%', zIndex: 2, + backgroundColor: 'white', // Optional: Set a background color if needed + borderRadius: 10, // Optional: Add rounded corners + padding: 10, // Optional: Add padding around the content + elevation: 5, // Optional: Add elevation for shadow effect }, + welcomeText: { textAlign: 'center', fontSize: 20, @@ -309,21 +277,23 @@ const styles = StyleSheet.create({ right: 20, zIndex: 2, }, - modalContainer: { - flex: 1, - justifyContent: 'center', - height: '90%', - alignItems: 'center', + settingsModal: { + backgroundColor: 'rgba(0, 0, 0, 0.5)', // Semi-transparent background + }, + settingsModalContainer: { + flex: 2, + justifyContent: 'center', // Center the modal vertically backgroundColor: 'rgba(0, 0, 0, 0.5)', }, - modalContent: { - width: '100%', // Adjust the width to cover more space - height: '90%', // Adjust the height to cover more space + settingsModalContent: { + width: '100%', + height: '80%', // Increase the height to make the modal taller backgroundColor: 'white', - padding: 20, // Reduce the padding - borderRadius: 10, + padding: 20, + borderTopLeftRadius: 10, + borderTopRightRadius: 10, alignItems: 'center', - }, + }, closeButton: { marginTop: 10, padding: 10, @@ -333,6 +303,7 @@ const styles = StyleSheet.create({ closeButtonText: { color: 'white', fontWeight: 'bold', - }, + } }); -export default QRScannerScreen; + +export default QRScannerScreen; \ No newline at end of file diff --git a/screens/SettingsScreen.tsx b/screens/SettingsScreen.tsx index f3963cf..0e001ff 100644 --- a/screens/SettingsScreen.tsx +++ b/screens/SettingsScreen.tsx @@ -1,16 +1,16 @@ -import { View, Text, StyleSheet, TouchableOpacity, Linking, Button } from 'react-native'; +import React, { useEffect, useState } from 'react'; +import { View, Text, StyleSheet, TouchableOpacity, Linking, Alert, Button } from 'react-native'; import { useAuthenticator } from '@aws-amplify/ui-react-native'; import useFetchUserAttributes from '../hooks/useFetchUserAttributes'; import { fetchAuthSession, getCurrentUser, signInWithRedirect } from 'aws-amplify/auth'; -import { useEffect, useState } from 'react'; +import { deleteAllScannedHistories } from '../api/qrCodeAPI'; // Import the API function import { Buffer } from 'buffer'; -import { createDrawerNavigator } from '@react-navigation/drawer'; - function SignOutButton() { const { signOut } = useAuthenticator(); return