ReCommit: Removed header for all screens. Updated QRScanner Screen UI to be responsive to screen size
This commit is contained in:
14
App.tsx
14
App.tsx
@@ -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
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 |
BIN
assets/icon.png
BIN
assets/icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 57 KiB |
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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
7
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
BIN
temp/Sample QR/To Whatsapp.png
Normal file
BIN
temp/Sample QR/To Whatsapp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Reference in New Issue
Block a user