ReCommit: Removed header for all screens. Updated QRScanner Screen UI to be responsive to screen size

This commit is contained in:
2024-08-07 12:07:17 +08:00
parent 7cb5cbbe34
commit f893f3285a
10 changed files with 140 additions and 104 deletions

14
App.tsx
View File

@@ -30,16 +30,22 @@ const App: React.FC = () => {
<Provider store={store}>
<QRCodeContext.Provider value={{ scannedData, setScannedData }}>
<NavigationContainer>
<Tab.Navigator
initialRouteName="QRScanner"
tabBar={(props) => <CustomTabBar {...props} clearScanData={clearScanData} />}
>
<Tab.Navigator
initialRouteName="QRScanner"
tabBar={(props) => <CustomTabBar {...props} clearScanData={clearScanData} />}
screenOptions={{ headerShown: false }} // turn of header for all screens
>
<Tab.Screen name="History" component={HistoryScreen} />
<Tab.Screen name="QRScanner">
{(props) => <QRScannerScreen {...props} clearScanData={clearScanData} />}
</Tab.Screen>
<Tab.Screen name="Email" component={EmailScreen} />
</Tab.Navigator>
</NavigationContainer>
</QRCodeContext.Provider>
</Provider>

BIN
assets/SafeQR_Logo 1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -76,7 +76,7 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ qrCodeId, clearScanData
}
};
const getRedirectIcon = () => {
const getSheildIcon = () => {
if (redirects === 0) {
return <Ionicons name="shield-checkmark" size={screenWidth * 0.045} color="#44c167" />;
} else if (redirects <= 2) {
@@ -99,19 +99,24 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ qrCodeId, clearScanData
};
return (
<View style={styles.dataBox}>
<TouchableOpacity style={styles.closeButton} onPress={clearScanData}>
<Ionicons name="close-circle-outline" size={screenWidth * 0.05} color="#ff69b4" />
</TouchableOpacity>
{/* The Top Scan Icon with payload, truncated */}
<View style={[styles.row, styles.shadowBox]}>
<Image source={require('../assets/ScanIcon3.png')} style={styles.scan_icon} />
<Text style={styles.payload} onPress={() => setIsContentModalVisible(true)}>
{truncateContent(contents, 30)} {/* Truncated content further */}
{truncateContent(contents, 30)}
</Text>
</View>
<View style={styles.mainContent}>
{/* Display QR Code , timestamp and Description */}
<View style={styles.qrSection}>
<QRCode value={contents || 'No Data'} size={screenWidth * 0.2} backgroundColor="transparent" />
</View>
@@ -123,11 +128,12 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ qrCodeId, clearScanData
</View>
</View>
{/* The Main Result in appropriate color */}
<Text style={[styles.resultText, { color: getResultColor() }]}>
Result: {getResultText()}
</Text>
{/* Change the UI based on Type */}
{type === 'URL' && (
<>
<View style={styles.displayCheck}>
@@ -140,33 +146,21 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ qrCodeId, clearScanData
<>
<SimpleLineIcons name="shield" size={screenWidth * 0.045} color="#ff0000" />
<Text style={styles.moreInfoButtonText}>Not Secure</Text>
</>
)}
</View>
<TouchableOpacity style={styles.moreInfoButton} onPress={() => setIsRedirectModalVisible(true)}>
{getRedirectIcon()}
{getSheildIcon()}
<Text style={styles.moreInfoButtonText}>Redirects</Text>
<Ionicons name="chevron-forward" size={screenWidth * 0.045} color="#ff69b4" />
</TouchableOpacity>
</>
)}
{type === 'SMS' && (
<>
<Text style={styles.moreInfoButtonText}>Recipient Phone Number: {details.phone || 'Undefined'}</Text>
<Text style={styles.moreInfoButtonText}>Message Content: {details.message || 'Undefined'}</Text>
</>
)}
{type === 'TEXT' && (
<TouchableOpacity style={[styles.contentBox, styles.shadowBox]} onPress={() => setIsContentModalVisible(true)}>
<Text style={styles.moreInfoButtonText}>
Content: {truncateContent(contents, 30)} {/* Truncated content further */}
</Text>
</TouchableOpacity>
)}
<TouchableOpacity style={styles.moreInfoButton} onPress={() => setIsModalVisible(true)}>
<TouchableOpacity style={styles.moreInfoButton} onPress={() => setIsModalVisible(true)}>
<Ionicons name="shield-checkmark" size={screenWidth * 0.045} color="#ff69b4" />
<Text style={styles.moreInfoButtonText}>Security Headers</Text>
<Ionicons name="chevron-forward" size={screenWidth * 0.045} color="#ff69b4" />
@@ -210,6 +204,32 @@ const ScannedDataBox: React.FC<ScannedDataBoxProps> = ({ qrCodeId, clearScanData
</View>
</Modal>
</>
)}
{type === 'SMS' && (
<>
<Text style={styles.moreInfoButton}>Recipient Phone Number: {details.phone || 'Undefined'}</Text>
<Text style={styles.moreInfoButton}>Message Content: {details.message || 'Undefined'}</Text>
</>
)}
{type === 'TEXT' && (
<TouchableOpacity style={styles.moreInfoButton} onPress={() => setIsContentModalVisible(true)}>
<Text >
Content: {truncateContent(contents, 30)} {/* Truncated content further */}
</Text>
<Ionicons name="chevron-forward" size={screenWidth * 0.045} color="#ff69b4" />
</TouchableOpacity>
)}
<Modal
visible={isContentModalVisible}
transparent={true}
@@ -288,7 +308,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: screenWidth * 0.0125,
padding: screenWidth * 0.0525,
},
qrSection: {
flex: 1,
@@ -306,7 +326,7 @@ const styles = StyleSheet.create({
timestampText: {
fontSize: screenWidth * 0.0275,
fontSize: screenWidth * 0.03,
color: '#000',
marginBottom: screenWidth * 0.01875,
},

View File

@@ -6,25 +6,23 @@ import HistoryScreen from '../screens/HistoryScreen';
import SettingsScreen from '../screens/SettingsScreen';
import CustomTabBar from '../components/CustomTabBar';
// Create a bottom tab navigator
const Tab = createBottomTabNavigator();
// Main navigation component
const AppNavigator = () => {
return (
// Wrap the navigator in a NavigationContainer to manage the navigation tree
<NavigationContainer>
{/* Define the tab navigator with custom tab bar and initial route */}
<Tab.Navigator initialRouteName="QR Scanner" tabBar={props => <CustomTabBar {...props} />}>
{/* Define each tab with a name and corresponding component */}
<Tab.Navigator
initialRouteName="QRScanner"
tabBar={props => <CustomTabBar clearScanData={function (): void {
throw new Error('Function not implemented.');
} } {...props} />}
>
<Tab.Screen name="History" component={HistoryScreen} />
<Tab.Screen name="QR Scanner" component={QRScannerScreen} />
<Tab.Screen name="QRScanner" component={QRScannerScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
};
export default AppNavigator;
export default AppNavigator;

7
package-lock.json generated
View File

@@ -42,7 +42,8 @@
"react-native-svg": "15.2.0",
"react-native-webview": "^13.8.6",
"react-redux": "^9.1.2",
"redux": "^5.0.1"
"redux": "^5.0.1",
"safeqr": "file:"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@@ -16952,6 +16953,10 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safeqr": {
"resolved": "",
"link": true
},
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",

View File

@@ -46,7 +46,8 @@
"react-native-svg": "15.2.0",
"react-native-webview": "^13.8.6",
"react-redux": "^9.1.2",
"redux": "^5.0.1"
"redux": "^5.0.1",
"safeqr": "file:"
},
"devDependencies": {
"@babel/core": "^7.20.0",

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Modal, TouchableWithoutFeedback } from 'react-native';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Modal, Image, Dimensions } from 'react-native';
import { Camera, CameraView, scanFromURLAsync } from 'expo-camera';
import { Ionicons } from '@expo/vector-icons';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
@@ -7,10 +7,11 @@ import * as ImagePicker from 'expo-image-picker';
import ScannedDataBox from '../components/ScannedDataBox';
import { useDispatch } from 'react-redux';
import { AppDispatch } from '../store';
import { addQRCode } from '../reducers/qrCodesReducer';
import { scanQRCode, getUserInfo } from '../api/qrCodeAPI';
import SettingsScreen from './SettingsScreen';
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanData }) => {
const navigation = useNavigation(); // Navigation hook
const dispatch = useDispatch<AppDispatch>(); // Use dispatch for Redux actions
@@ -141,8 +142,9 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat
return (
<View style={styles.container}>
<Text style={styles.headerText}>SafeQR</Text>
<Text style={styles.welcomeText}>Welcome to SafeQR code Scanner</Text>
<Text style={styles.titleText}>Welcome to</Text>
<Image source={require('../assets/SafeQR_Logo 1.png')} style={styles.logo} />
<Text style={styles.welcomeText}>Please point the camera at the QR Code</Text>
<View style={styles.cameraContainer}>
{cameraVisible && (
@@ -155,27 +157,26 @@ const QRScannerScreen: React.FC<{ clearScanData: () => void }> = ({ clearScanDat
)}
<TouchableOpacity onPress={toggleTorch} style={styles.flashButton}>
<Ionicons name="flashlight" size={24} color="#fff" />
<Ionicons name="flashlight" size={screenWidth * 0.06} color="#fff" />
</TouchableOpacity>
<TouchableOpacity onPress={readQRFromImage} style={styles.galleryButton}>
<Ionicons name="image" size={24} color="#fff" />
<Ionicons name="image" size={screenWidth * 0.06} color="#fff" />
</TouchableOpacity>
</View>
{/* Scanned Data Box */}
{isScannedDataBoxVisible && (
<View style={styles.scannedDataBoxPopup}>
<ScannedDataBox
qrCodeId={qrCodeId}
clearScanData={() => setIsScannedDataBoxVisible(false)}
/>
</View>
)}
<View style={styles.scannedDataBoxPopup}>
<ScannedDataBox
qrCodeId={qrCodeId}
clearScanData={() => setIsScannedDataBoxVisible(false)}
/>
</View>
)}
{/* Settings Icon */}
<TouchableOpacity onPress={() => setIsSettingsModalVisible(true)} style={styles.settingsButton}>
<Ionicons name="settings" size={24} color="#000" />
<Ionicons name="settings" size={screenWidth * 0.06} color="#000" />
</TouchableOpacity>
{/* Settings Modal */}
@@ -205,12 +206,36 @@ const styles = StyleSheet.create({
backgroundColor: '#f8f0fc',
padding: 20,
},
headerText: {
fontSize: 24,
fontWeight: 'bold',
color: '#ff69b4',
titleText: {
textAlign: 'center',
marginBottom: 20,
fontSize: 20,
marginTop: screenHeight * 0.05,
color: 'black',
},
logo: {
alignSelf: 'center',
width: screenWidth * 0.5,
height: screenWidth * 0.2,
resizeMode: 'contain',
marginVertical: 10,
},
welcomeText: {
textAlign: 'center',
fontSize: 20,
marginVertical: 10,
color: 'black',
},
cameraContainer: {
height: '60%',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 10,
overflow: 'hidden',
},
settingsButton: {
position: 'absolute',
top: screenHeight * 0.05,
right: 20,
},
splashContainer: {
flex: 1,
@@ -220,38 +245,31 @@ const styles = StyleSheet.create({
height: '100%',
width: '100%',
},
cameraContainer: {
height: '60%',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 10,
overflow: 'hidden',
},
camera: {
width: '100%',
height: '100%',
},
flashButton: {
position: 'absolute',
bottom: 20,
left: 100,
width: 50,
height: 50,
bottom: screenHeight * 0.025,
left: screenWidth * 0.2,
width: screenWidth * 0.125,
height: screenWidth * 0.125,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
borderRadius: 25,
borderRadius: screenWidth * 0.0625,
},
galleryButton: {
position: 'absolute',
bottom: 20,
right: 100,
width: 50,
height: 50,
bottom: screenHeight * 0.025,
right: screenWidth * 0.2,
width: screenWidth * 0.125,
height: screenWidth * 0.125,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000',
borderRadius: 25,
borderRadius: screenWidth * 0.0625,
},
scannedDataBoxPopup: {
position: 'absolute',
@@ -259,51 +277,39 @@ const styles = StyleSheet.create({
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,
marginVertical: 10,
color: 'black',
},
settingsButton: {
position: 'absolute',
top: 40,
right: 20,
zIndex: 2,
backgroundColor: 'white',
borderRadius: screenWidth * 0.025,
padding: screenWidth * 0.025,
elevation: 5,
},
settingsModal: {
backgroundColor: 'rgba(0, 0, 0, 0.5)', // Semi-transparent background
},
settingsModalContainer: {
flex: 2,
justifyContent: 'center', // Center the modal vertically
flex: 1,
justifyContent: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
settingsModalContent: {
settingsModalContent: {
width: '100%',
height: '80%', // Increase the height to make the modal taller
height: '80%',
backgroundColor: 'white',
padding: 20,
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
padding: screenWidth * 0.05,
borderTopLeftRadius: screenWidth * 0.025,
borderTopRightRadius: screenWidth * 0.025,
alignItems: 'center',
},
closeButton: {
marginTop: 10,
padding: 10,
marginTop: screenHeight * 0.01,
padding: screenWidth * 0.025,
backgroundColor: '#ff69b4',
borderRadius: 5,
borderRadius: screenWidth * 0.0125,
},
closeButtonText: {
color: 'white',
fontWeight: 'bold',
}
},
});
export default QRScannerScreen;
export default QRScannerScreen;

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB