Compare commits

...
2 Commits
Author SHA1 Message Date
LeviM0323 b771a989f1 Mobile lab 5 2026-10-30 16:32:34 -04:00
LeviM0323 8d9ed344d6 Device Sync 2026-10-30 16:29:35 -04:00
18 changed files with 10551 additions and 7 deletions

No files matched your search

-7
View File
@@ -22,13 +22,6 @@ node_modules/
dist/ dist/
coverage/ coverage/
# Python
__pycache__/
*.py[cod]
.venv/
venv/
.pytest_cache/
# Java and Android build output # Java and Android build output
.gradle/ .gradle/
build/ build/
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Exercise 1</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<h1>Exercise 1</h1>
<script>
d3.select("body")
.append("svg")
.attr("width", 110)
.attr("height", 200)
.append("rect")
.attr("x", 10)
.attr("width", 100)
.attr("height", 200)
.attr("fill", "blue");
d3.select("body")
.append("svg")
.attr("width", 220)
.attr("height", 200)
.style("margin-left", "50px")
.append("rect")
.attr("x", 120)
.attr("width", 100)
.attr("height", 200)
.attr("fill", "green");
</script>
</body>
</html>
@@ -0,0 +1,13 @@
> Why do I have a folder named ".expo" in my project?
The ".expo" folder is created when an Expo project is started using "expo start" command.
> What do the files contain?
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
- "settings.json": contains the server configuration that is used to serve the application manifest.
> Should I commit the ".expo" folder?
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
@@ -0,0 +1,3 @@
{
"devices": []
}
@@ -0,0 +1,309 @@
import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect } from "react";
import { View, TextInput, Text, Button, Alert, StyleSheet } from "react-native";
import { db, firestore, auth } from "./FirebaseConfig";
import {
createUserWithEmailAndPassword,
signOut,
signInWithEmailAndPassword,
onAuthStateChanged,
} from "firebase/auth";
import { ref, set, onValue } from "firebase/database";
import { doc, setDoc, onSnapshot } from "firebase/firestore";
export default function App() {
const [registrationEmail, setRegistrationEmail] = useState("");
const [registrationPassword, setRegistrationPassword] = useState("");
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const [loggedIn, setLoggedIn] = useState(false);
const [databaseData, setDatabaseData] = useState("");
const [user, setUser] = useState(null);
// Monitor authentication state
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
setLoggedIn(!!currentUser);
});
return () => unsubscribe();
}, []);
const registerWithFirebase = () => {
if (registrationEmail.length < 4) {
Alert.alert("Please enter an email address.");
return;
}
if (registrationPassword.length < 4) {
Alert.alert("Please enter a password.");
return;
}
createUserWithEmailAndPassword(
auth,
registrationEmail,
registrationPassword
)
.then((userCredential) => {
Alert.alert("User registered successfully!");
setRegistrationEmail("");
setRegistrationPassword("");
})
.catch((error) => {
console.log("Registration error:", error);
if (error.code === "auth/weak-password") {
Alert.alert("The password is too weak.");
} else if (error.code === "auth/email-already-in-use") {
Alert.alert("This email is already registered.");
} else {
Alert.alert(error.message);
}
});
};
const loginWithFirebase = () => {
if (loginEmail.length < 4) {
Alert.alert("Please enter an email address.");
return;
}
if (loginPassword.length < 4) {
Alert.alert("Please enter a password.");
return;
}
signInWithEmailAndPassword(auth, loginEmail, loginPassword)
.then((userCredential) => {
Alert.alert("User logged in successfully!");
setLoginEmail("");
setLoginPassword("");
})
.catch((error) => {
console.log("Login error:", error);
if (error.code === "auth/wrong-password") {
Alert.alert("Wrong password.");
} else if (error.code === "auth/user-not-found") {
Alert.alert("User not found.");
} else {
Alert.alert(error.message);
}
});
};
const signoutWithFirebase = () => {
signOut(auth)
.then(() => {
Alert.alert("User was logged out!");
setDatabaseData("");
})
.catch((error) => {
Alert.alert("Error signing out:", error.message);
});
};
const saveDataWithFirebase = () => {
if (!user) {
Alert.alert("Please log in first.");
return;
}
const userID = user.uid;
// Save to Realtime DB
set(ref(db, "users/" + userID), {
text: databaseData,
timestamp: Date.now(),
})
.then(() => {
console.log("Data saved to Realtime DB");
})
.catch((error) => {
console.log("Realtime DB error:", error);
});
// Save to Firestore
setDoc(
doc(firestore, "users", userID),
{
text: databaseData,
timestamp: Date.now(),
},
{ merge: true }
)
.then(() => {
Alert.alert("Data saved successfully!");
})
.catch((error) => {
Alert.alert("Error saving data");
console.log("Firestore error:", error);
});
};
const retrieveDataWithFirebase = () => {
if (!user) {
Alert.alert("Please log in first.");
return;
}
const userID = user.uid;
const dbRef = ref(db, "users/" + userID);
// Using Realtime DB
onValue(dbRef, (snapshot) => {
if (snapshot.exists()) {
const data = snapshot.val();
setDatabaseData(data.text || "");
Alert.alert("Data retrieved from Realtime DB");
} else {
Alert.alert("No data found");
}
});
// Uncomment for Firestore
/*
const unsubscribe = onSnapshot(doc(firestore, "users", userID), (doc) => {
if (doc.exists()) {
const data = doc.data();
setDatabaseData(data.text || "");
Alert.alert("Data retrieved from Firestore");
} else {
Alert.alert("No data found in Firestore");
}
});
*/
};
return (
<View style={styles.form}>
<StatusBar style="auto" />
{!loggedIn ? (
<View>
<View style={styles.section}>
<Text style={styles.label}>Lab 5 - l_mclean215318</Text>
<Text style={styles.label}>Register with Firebase</Text>
<TextInput
style={styles.textInput}
onChangeText={setRegistrationEmail}
value={registrationEmail}
autoCapitalize="none"
autoCorrect={false}
autoCompleteType="email"
keyboardType="email-address"
placeholder="Email"
/>
<TextInput
style={styles.textInput}
onChangeText={setRegistrationPassword}
value={registrationPassword}
autoCapitalize="none"
autoCorrect={false}
autoCompleteType="password"
placeholder="Password"
secureTextEntry={true}
/>
<Button title="Register" onPress={registerWithFirebase} />
</View>
<View style={styles.section}>
<Text style={styles.label}>Sign In with Firebase</Text>
<TextInput
style={styles.textInput}
onChangeText={setLoginEmail}
value={loginEmail}
autoCapitalize="none"
autoCorrect={false}
autoCompleteType="email"
keyboardType="email-address"
placeholder="Email"
/>
<TextInput
style={styles.textInput}
onChangeText={setLoginPassword}
value={loginPassword}
autoCapitalize="none"
autoCorrect={false}
autoCompleteType="password"
placeholder="Password"
secureTextEntry={true}
/>
<Button title="Login" onPress={loginWithFirebase} />
</View>
</View>
) : (
<View>
<Text style={styles.welcome}>Welcome, {user?.email}</Text>
<TextInput
style={styles.textArea}
multiline={true}
numberOfLines={4}
onChangeText={setDatabaseData}
value={databaseData}
placeholder="Enter your data here..."
/>
<View style={styles.buttonContainer}>
<Button title="Save Data" onPress={saveDataWithFirebase} />
<Button title="Load Data" onPress={retrieveDataWithFirebase} />
</View>
<View style={styles.signOutButton}>
<Button
title="Sign Out"
onPress={signoutWithFirebase}
color="#ff4444"
/>
</View>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
form: {
flex: 1,
margin: 30,
marginTop: 60,
},
section: {
marginBottom: 30,
},
label: {
fontSize: 18,
marginBottom: 15,
textAlign: "center",
fontWeight: "bold",
},
welcome: {
fontSize: 18,
marginBottom: 20,
textAlign: "center",
fontWeight: "bold",
},
textInput: {
borderColor: "#ccc",
borderWidth: 1,
marginBottom: 15,
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 5,
},
textArea: {
borderColor: "#ccc",
borderWidth: 1,
marginBottom: 15,
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 5,
height: 100,
textAlignVertical: "top",
},
buttonContainer: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 20,
},
signOutButton: {
marginTop: 20,
},
});
@@ -0,0 +1,21 @@
import { initializeApp } from "firebase/app";
import { getDatabase } from "firebase/database";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
// Your Firebase config
const firebaseConfig = {
apiKey: "AIzaSyBfvjd5heEO3nS59rQSqY3Vsr36Pv2V3RU",
authDomain: "week6-fb-db.firebaseapp.com",
databaseURL: "https://week6-fb-db-default-rtdb.firebaseio.com",
projectId: "week6-fb-db",
storageBucket: "week6-fb-db.firebasestorage.app",
messagingSenderId: "854313991657",
appId: "1:854313991657:web:42859a9b1c0bd06f391f78",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getDatabase(app);
export const auth = getAuth(app);
export const firestore = getFirestore(app);
@@ -0,0 +1,29 @@
{
"expo": {
"name": "firebase-DB",
"slug": "firebase-DB",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash-icon.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"edgeToEdgeEnabled": true
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,23 @@
{
"name": "firebase-db",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.24.0",
"expo": "~54.0.12",
"expo-status-bar": "~3.0.8",
"firebase": "^12.3.0",
"react": "19.1.0",
"react-native": "0.81.4"
},
"private": true,
"devDependencies": {
"@expo/cli": "^54.0.10"
}
}