diff --git a/.env.development b/.env.development index 04bf676..265055a 100644 --- a/.env.development +++ b/.env.development @@ -1 +1 @@ -BASE_URL=http://192.168.1.30:8080 \ No newline at end of file +BASE_URL=https://localhost:8443 \ No newline at end of file diff --git a/App.tsx b/App.tsx index 7aa504c..05f7589 100644 --- a/App.tsx +++ b/App.tsx @@ -1,10 +1,12 @@ import React, { useState } from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; +import { createDrawerNavigator } from '@react-navigation/drawer'; // Import Drawer Navigator import { Provider } from 'react-redux'; import QRScannerScreen from './screens/QRScannerScreen'; import HistoryScreen from './screens/HistoryScreen'; -import SettingsScreen from './screens/SettingsScreen'; +import EmailScreen from './screens/EmailScreen'; // Import the Email screen +import SettingsScreen from './screens/SettingsScreen'; // Import the Settings screen import { QRCodeContext } from './types'; import CustomTabBar from './components/CustomTabBar'; import store from './store'; @@ -19,6 +21,7 @@ enableScreens(); Amplify.configure(config); const Tab = createBottomTabNavigator(); +const Drawer = createDrawerNavigator(); // Create Drawer Navigator const App: React.FC = () => { const [scannedData, setScannedData] = useState(''); @@ -39,7 +42,7 @@ const App: React.FC = () => { {(props) => } - + @@ -47,4 +50,4 @@ const App: React.FC = () => { ); }; -export default withAuthenticator(App); \ No newline at end of file +export default withAuthenticator(App); diff --git a/api/qrCodeAPI.tsx b/api/qrCodeAPI.tsx index 550730e..2a19784 100644 --- a/api/qrCodeAPI.tsx +++ b/api/qrCodeAPI.tsx @@ -1,7 +1,7 @@ import axios from 'axios'; import Constants from 'expo-constants'; -const { API_BASE_URL } = Constants.expoConfig.extra; -//const API_BASE_URL = 'http://192.168.1.30:8080/v1/qrcodetypes'; +//const { API_BASE_URL } = Constants.expoConfig.extra; +const API_BASE_URL = 'https://localhost:8443'; const API_URL_DETECT = "/v1/qrcodetypes/detect"; const API_URL_VERIFY_URL = "/v1/qrcodetypes/verifyURL" diff --git a/components/CustomTabBar.tsx b/components/CustomTabBar.tsx index 576eeda..febad38 100644 --- a/components/CustomTabBar.tsx +++ b/components/CustomTabBar.tsx @@ -1,23 +1,23 @@ import React from 'react'; import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; -import { Ionicons } from '@expo/vector-icons'; - +import { Ionicons, MaterialIcons } from '@expo/vector-icons'; // Define custom props for CustomTabBar interface CustomTabBarProps extends BottomTabBarProps { clearScanData: () => void; } - // Custom tab bar component with typings -const CustomTabBar: React.FC = ({ state, descriptors, navigation, clearScanData }) => { +const CustomTabBar: React.FC = ({ state, descriptors, navigation, clearScanData }) => { return ( {state.routes.map((route, index) => { const { options } = descriptors[route.key]; const label = - options.tabBarLabel !== undefined + route.name === 'Email' + ? 'Gmail' + : options.tabBarLabel !== undefined ? options.tabBarLabel : options.title !== undefined ? options.title @@ -25,13 +25,13 @@ const CustomTabBar: React.FC = ({ state, descriptors, naviga const isFocused = state.index === index; - // Event handler for tab press - const onPress = () => { - const event = navigation.emit({ - type: 'tabPress', - target: route.key, - canPreventDefault: true - }); + // Event handler for tab press + const onPress = () => { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }); if (!isFocused && !event.defaultPrevented) { navigation.navigate(route.name); @@ -53,7 +53,9 @@ const CustomTabBar: React.FC = ({ state, descriptors, naviga }); }; - const iconName = route.name === 'QRScanner' ? 'camera' : route.name === 'History' ? 'time' : 'settings'; + // Define the icon for each tab + const iconName = + route.name === 'QRScanner' ? 'camera' : route.name === 'History' ? 'time' : 'settings'; return ( = ({ state, descriptors, naviga onLongPress={onLongPress} style={styles.tabButton} > - + {route.name === 'Email' ? ( + + ) : ( + + )} {/* Check if label is a string before rendering */} {typeof label === 'string' ? ( @@ -77,13 +83,15 @@ const CustomTabBar: React.FC = ({ state, descriptors, naviga ); })} - { - clearScanData(); - navigation.reset({ - index: 0, - routes: [{ name: 'QRScanner' }], - }); - }}> + { + clearScanData(); + navigation.reset({ + index: 0, + routes: [{ name: 'QRScanner' }], + }); + }} + > diff --git a/package-lock.json b/package-lock.json index b5de7b7..71ef542 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,9 @@ "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-community/netinfo": "11.3.1", "@react-navigation/bottom-tabs": "^6.5.20", + "@react-navigation/drawer": "^6.7.2", "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.4.1", "@reduxjs/toolkit": "^2.2.6", "aws-amplify": "^6.4.2", "axios": "^1.7.2", @@ -31,6 +33,7 @@ "react": "18.2.0", "react-native": "^0.74.3", "react-native-dotenv": "^3.4.11", + "react-native-gesture-handler": "^2.17.1", "react-native-get-random-values": "^1.11.0", "react-native-qrcode-svg": "^6.3.1", "react-native-safe-area-context": "^4.10.4", @@ -3665,6 +3668,17 @@ "node": ">=6.9.0" } }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@expo/bunyan": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.0.tgz", @@ -7324,10 +7338,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@react-navigation/drawer": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.7.2.tgz", + "integrity": "sha512-o4g2zgTZa2+oLd+8V33etrSM38KIqu8S/zCBTsdsHUoQyVE7JNRiv3Qgq/jMvEb8PZCqWmm7jHItcgzrBuwyOQ==", + "dependencies": { + "@react-navigation/elements": "^1.3.31", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-reanimated": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@react-navigation/elements": { - "version": "1.3.30", - "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.30.tgz", - "integrity": "sha512-plhc8UvCZs0UkV+sI+3bisIyn78wz9O/BiWZXpounu72k/R/Sj5PuZYFJ1fi6psvriUveMCGh4LeZckAZu2qiQ==", + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.31.tgz", + "integrity": "sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ==", "peerDependencies": { "@react-navigation/native": "^6.0.0", "react": "*", @@ -7369,6 +7402,24 @@ "nanoid": "^3.1.23" } }, + "node_modules/@react-navigation/stack": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.4.1.tgz", + "integrity": "sha512-upMEHOKMtuMu4c9gmoPlO/JqI6mDlSqwXg1aXKOTQLXAF8H5koOLRfrmi7AkdiE9A7lDXWUAZoGuD9O88cYvDQ==", + "dependencies": { + "@react-navigation/elements": "^1.3.31", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@reduxjs/toolkit": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", @@ -8720,6 +8771,11 @@ "integrity": "sha512-SMWlRBukG9KV8ZNjwemp2AzDibp/czIAeKKTw09nCPbWxVskIxactCJCGOp4y6I1hCMY7T7UGfySvBLXNeUbEw==", "license": "MIT" }, + "node_modules/@types/hammerjs": { + "version": "2.0.45", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.45.tgz", + "integrity": "sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ==" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -12186,6 +12242,14 @@ "node": ">=8" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/hosted-git-info": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", @@ -16260,6 +16324,21 @@ "@babel/runtime": "^7.20.6" } }, + "node_modules/react-native-gesture-handler": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.17.1.tgz", + "integrity": "sha512-pWfniN6NuVKUq40KACuD3NCMe+bWNQCpD3cmxL6aLSCTwPKYmf7l4Lp0/E/almpjvxhybJZtFLU0w4tmxnIKaA==", + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-get-random-values": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz", @@ -16286,6 +16365,27 @@ "react-native-svg": ">=13.2.0" } }, + "node_modules/react-native-reanimated": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.14.0.tgz", + "integrity": "sha512-TAxLtCfRyC/nOLeWoX/8MhdIF+Fi1e1NbLhIgEm5Kv9/gioAwSNaqLUYxjIClU1RaLwSTE8iaiHNVhTU4TS9DA==", + "peer": true, + "dependencies": { + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-safe-area-context": { "version": "4.10.8", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.10.8.tgz", diff --git a/package.json b/package.json index 8a3bdbd..36068f7 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,9 @@ "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-community/netinfo": "11.3.1", "@react-navigation/bottom-tabs": "^6.5.20", + "@react-navigation/drawer": "^6.7.2", "@react-navigation/native": "^6.1.17", + "@react-navigation/stack": "^6.4.1", "@reduxjs/toolkit": "^2.2.6", "aws-amplify": "^6.4.2", "axios": "^1.7.2", @@ -34,6 +36,7 @@ "react": "18.2.0", "react-native": "^0.74.3", "react-native-dotenv": "^3.4.11", + "react-native-gesture-handler": "^2.17.1", "react-native-get-random-values": "^1.11.0", "react-native-qrcode-svg": "^6.3.1", "react-native-safe-area-context": "^4.10.4", diff --git a/screens/EmailScreen.tsx b/screens/EmailScreen.tsx new file mode 100644 index 0000000..b885bd1 --- /dev/null +++ b/screens/EmailScreen.tsx @@ -0,0 +1,28 @@ +// EmailScreen.tsx +import React from 'react'; +import { View, Text, StyleSheet } from 'react-native'; + +const EmailScreen: React.FC = () => { + return ( + + Email Screen T^T + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#f8f0fc', + padding: 20, + justifyContent: 'center', + alignItems: 'center', + }, + header: { + fontSize: 24, + fontWeight: 'bold', + color: '#ff69b4', + }, +}); + +export default EmailScreen; diff --git a/screens/QRScannerScreen.tsx b/screens/QRScannerScreen.tsx index 4ee5417..3987793 100644 --- a/screens/QRScannerScreen.tsx +++ b/screens/QRScannerScreen.tsx @@ -53,6 +53,16 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat console.log("Scan data cleared"); }; + useEffect(() => { + navigation.setOptions({ + headerRight: () => ( + navigation.navigate('Settings')}> + + + ), + }); + }, [navigation]); + // Handle QR Code Payload const handlePayload = async (payload: string) => { setScanned(true); @@ -180,9 +190,7 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat return ( - - SafeQR v0.89 - + SafeQR v0.89 Welcome to SafeQR code Scanner @@ -230,14 +238,12 @@ const styles = StyleSheet.create({ backgroundColor: '#f8f0fc', padding: 20, }, - banner: { - alignItems: 'center', - marginBottom: 20, - }, headerText: { fontSize: 24, fontWeight: 'bold', color: '#ff69b4', + textAlign: 'center', + marginBottom: 20, }, splashContainer: { flex: 1, diff --git a/screens/SettingsScreen.tsx b/screens/SettingsScreen.tsx index 4cec05f..82923e6 100644 --- a/screens/SettingsScreen.tsx +++ b/screens/SettingsScreen.tsx @@ -1,200 +1,142 @@ -import { View, Text, StyleSheet, TouchableOpacity, Linking, 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 { Buffer } from 'buffer'; +import React from 'react'; +import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; +import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; +import { Ionicons, MaterialIcons } from '@expo/vector-icons'; - -function SignOutButton() { - const { signOut } = useAuthenticator(); - return