// Importing necessary hooks from React
import {
useState, // Hook for managing state in functional components
useEffect // Hook for performing side effects in functional components
} from "react";
// Importing components and utilities from React Native
import {
View, // Container component for layout
Text, // Component for displaying text
TextInput, // Component for user input fields
TouchableOpacity, // Component for touchable buttons
ScrollView, // Component for scrollable views
StyleSheet, // Utility for creating styles
Clipboard, // Utility for interacting with the clipboard
} from "react-native";
// Importing Icon component from react-native-vector-icons for displaying icons
import Icon from "react-native-vector-icons/FontAwesome";
const App = () => {
// State variables for managing input fields and password list
const [website, setWebsite] = useState(""); // State for website input
const [username, setUsername] = useState(""); // State for username input
const [password, setPassword] = useState(""); // State for password input
const [passwords, setPasswords] = useState([]); // State for storing list of passwords
const [alertVisible, setAlertVisible] = useState(false); // State for showing alert when text is copied
const [editing, setEditing] = useState(false); // State for tracking if editing mode is active
const [editIndex, setEditIndex] = useState(null); // State for tracking the index of the password being edited
// useEffect hook to initialize the password list when the component mounts
useEffect(() => {
showPasswords();
}, []);
// Function to save or update a password
const savePassword = () => {
// Check if any of the input fields is empty
if (!website || !username || !password) {
alert("Please fill in all fields."); // Show alert if fields are empty
return;
}
if (editing && editIndex !== null) {
// If editing, update the existing password
const updatedPasswords = [...passwords];
updatedPasswords[editIndex] = {
website,
username,
password,
};
setPasswords(updatedPasswords); // Update the password list
setEditing(false); // Exit editing mode
setEditIndex(null); // Clear edit index
} else {
// If not editing, add a new password
const newPassword = {
website,
username,
password,
};
setPasswords([...passwords, newPassword]); // Add new password to the list
}
setWebsite(""); // Reset website input
setUsername(""); // Reset username input
setPassword(""); // Reset password input
};
// Function to enable editing mode for a specific password
const editPassword = (index) => {
setEditing(true); // Enable editing mode
setEditIndex(index); // Set the index of the password being edited
setWebsite(passwords[index].website); // Populate website input with existing value
setUsername(passwords[index].username); // Populate username input with existing value
setPassword(passwords[index].password); // Populate password input with existing value
};
// Function to delete a password by website name
const deletePassword = (website) => {
const updatedPasswords = passwords.filter(
(e) => e.website !== website // Filter out the password with the given website
);
setPasswords(updatedPasswords); // Update the password list
alert(`Successfully deleted ${website}'s password`); // Show success message
};
// Function to reset the password list and input fields
const showPasswords = () => {
setPasswords([]); // Clear the password list
setWebsite(""); // Reset website input
setUsername(""); // Reset username input
setPassword(""); // Reset password input
setEditing(false); // Exit editing mode
setEditIndex(null); // Clear edit index
};
// Function to copy text to the clipboard
const copyText = async (txt) => {
try {
Clipboard.setString(txt); // Copy text to clipboard
setAlertVisible(true); // Show alert
setTimeout(() => {
setAlertVisible(false); // Hide alert after 2 seconds
}, 2000);
} catch (error) {
console.error("Error copying text:", error); // Log error if copying fails
}
};
// Function to mask a password with asterisks
const maskPassword = (pass) => {
let str = "";
for (let index = 0; index < pass.length; index++) {
str += "*";
}
return str;
};
// Function to render the list of saved passwords
const renderPasswordList = () => {
return passwords.map((item, index) => (
<View style={styles.passwordItem} key={index}>
{/* Display website */}
<View style={styles.listItem}>
<Text style={styles.listLabel}>
Website:
</Text>
<Text style={styles.listValue}>
{item.website + " "}
</Text>
<TouchableOpacity
style={styles.copyIcon}
onPress={() => copyText(item.website)}>
<Icon
name="copy"
size={20}
color="#555" />
</TouchableOpacity>
</View>
{/* Display username */}
<View style={styles.listItem}>
<Text style={styles.listLabel}>
Username:
</Text>
<Text style={styles.listValue}>
{item.username + " "}
</Text>
<TouchableOpacity
style={styles.copyIcon}
onPress={() => copyText(item.username)}>
<Icon
name="copy"
size={20}
color="#555" />
</TouchableOpacity>
</View>
{/* Display masked password */}
<View style={styles.listItem}>
<Text style={styles.listLabel}>
Password:
</Text>
<Text style={styles.listValue}>
{maskPassword(item.password)}
</Text>
<TouchableOpacity
style={styles.copyIcon}
onPress={() => copyText(item.password)}>
<Icon
name="copy"
size={20}
color="#555" />
</TouchableOpacity>
</View>
{/* Buttons for editing and deleting */}
<View style={styles.buttonsContainer}>
<TouchableOpacity
style={styles.editButton}
onPress={() => editPassword(index)}>
<Icon
name="edit"
size={20}
color="#fff" />
</TouchableOpacity>
<TouchableOpacity
style={styles.deleteButton}
onPress={() => deletePassword(item.website)}>
<Icon
name="trash"
size={20}
color="white" />
</TouchableOpacity>
</View>
</View>
));
};
// Main component rendering
return (
<ScrollView style={styles.container}>
<View style={styles.content}>
{/* Heading */}
<Text style={styles.heading}>
Password Manager
</Text>
{/* Subheading and alert */}
<Text style={styles.subHeading}>
Your Passwords
{alertVisible && (
<Text id="alert"> (Copied!)</Text>
)}
</Text>
{/* Display message if no passwords are available */}
{passwords.length === 0 ? (
<Text style={styles.noData}>
No Data To Show
</Text>
) : (
<ScrollView horizontal>
<View style={styles.table}>
{renderPasswordList()}
</View>
</ScrollView>
)}
{/* Form for adding or editing passwords */}
<Text style={styles.subHeading}>
{editing
? "Edit Password"
: "Add a Password"}
</Text>
<TextInput
style={styles.input}
placeholder="Website"
value={website}
onChangeText={(text) => setWebsite(text)} />
<TextInput
style={styles.input}
placeholder="Username"
value={username}
onChangeText={(text) => setUsername(text)} />
<TextInput
style={styles.input}
placeholder="Password"
secureTextEntry={true}
value={password}
onChangeText={(text) => setPassword(text)} />
{/* Button to save or update password */}
<TouchableOpacity
style={styles.submitButton}
onPress={savePassword}>
<Text style={styles.submitButtonText}>
{editing
? "Update Password"
: "Add Password"}
</Text>
</TouchableOpacity>
</View>
</ScrollView>
);
};
// Exporting the main App component as the default export
export default App;
// Defining styles for the application using StyleSheet
const styles = StyleSheet.create({
// Style for the main container
container: {
flex: 1, // Take up the full height of the screen
margin: 20, // Add margin around the container
},
// Style for the content inside the container
content: {
margin: 15, // Add margin inside the content
},
// Style for the main heading
heading: {
fontSize: 30, // Large font size
fontWeight: "bold", // Bold text
marginBottom: 15, // Space below the heading
textAlign: "center", // Center align the text
color: "#333", // Dark gray color
},
// Style for subheadings
subHeading: {
fontSize: 23, // Slightly smaller font size than the main heading
fontWeight: "bold", // Bold text
marginBottom: 10, // Space below the subheading
color: "#333", // Dark gray color
},
// Style for the "No Data" message
noData: {
fontSize: 17, // Medium font size
fontStyle: "italic", // Italic text
marginBottom: 20, // Space below the message
color: "#666", // Light gray color
},
// Style for the table containing password items
table: {
flexDirection: "row", // Arrange items in a row
backgroundColor: "white", // White background
borderRadius: 15, // Rounded corners
elevation: 4, // Add shadow for Android
marginBottom: 20, // Space below the table
shadowColor: "grey", // Shadow color for iOS
shadowOffset: { width: 0, height: 0 }, // Shadow offset for iOS
shadowRadius: 5, // Shadow radius for iOS
shadowOpacity: 1, // Shadow opacity for iOS
},
// Style for each password item
passwordItem: {
flexDirection: "column", // Arrange items in a column
alignItems: "center", // Center align items
borderBottomWidth: 1, // Add a bottom border
borderBottomColor: "#ddd", // Light gray border color
padding: 15, // Add padding inside the item
},
// Style for each list item (e.g., website, username, password)
listItem: {
flexDirection: "row", // Arrange items in a row
justifyContent: "space-between", // Space out items evenly
alignItems: "center", // Center align items vertically
marginRight: 10, // Space to the right of the item
marginBottom: 10, // Space below the item
},
// Style for the label in the list item
listLabel: {
fontWeight: "bold", // Bold text
marginBottom: 5, // Space below the label
color: "#333", // Dark gray color
fontSize: 19, // Medium font size
},
// Style for the value in the list item
listValue: {
flex: 1, // Take up available space
fontSize: 18, // Medium font size
color: "#444", // Medium gray color
paddingLeft: 10, // Space to the left of the value
},
// Style for the copy icon in the list item
copyIcon: {
marginRight: 10, // Space to the right of the icon
paddingLeft: 10, // Space to the left of the icon
},
// Style for the delete button
deleteButton: {
backgroundColor: "red", // Red background
borderRadius: 4, // Slightly rounded corners
padding: 5, // Add padding inside the button
marginLeft: 10, // Space to the left of the button
},
// Style for the edit button
editButton: {
backgroundColor: "blue", // Blue background
borderRadius: 4, // Slightly rounded corners
padding: 5, // Add padding inside the button
marginRight: 10, // Space to the right of the button
},
// Style for the container holding the edit and delete buttons
buttonsContainer: {
flexDirection: "row", // Arrange buttons in a row
},
// Style for the input fields
input: {
borderWidth: 2, // Border width
borderColor: "#eee", // Light gray border color
paddingVertical: 10, // Vertical padding inside the input
paddingHorizontal: 15, // Horizontal padding inside the input
marginBottom: 20, // Space below the input
fontSize: 16, // Medium font size
borderRadius: 10, // Rounded corners
backgroundColor: "white", // White background
shadowColor: "grey", // Shadow color for iOS
shadowOffset: { width: 0, height: 0 }, // Shadow offset for iOS
shadowRadius: 10, // Shadow radius for iOS
shadowOpacity: 1, // Shadow opacity for iOS
elevation: 4, // Add shadow for Android
},
// Style for the submit button
submitButton: {
backgroundColor: "green", // Green background
color: "white", // White text color
fontWeight: "bold", // Bold text
borderRadius: 10, // Rounded corners
paddingVertical: 15, // Vertical padding inside the button
paddingHorizontal: 30, // Horizontal padding inside the button
shadowColor: "black", // Shadow color for iOS
shadowOffset: { width: 2, height: 2 }, // Shadow offset for iOS
shadowRadius: 15, // Shadow radius for iOS
shadowOpacity: 1, // Shadow opacity for iOS
elevation: 4, // Add shadow for Android
},
// Style for the text inside the submit button
submitButtonText: {
color: "white", // White text color
textAlign: "center", // Center align the text
fontSize: 18, // Medium font size
},
});