Firebase Optimization #93

Merged
LAX18 merged 3 commits from npease-data-minimization into main 2024-04-21 08:58:49 -09:00
8 changed files with 191 additions and 98 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ function Home() {
onValue(ref(database, `users/${authUser.uid}`), (userData) => {
userData = userData.val();
if (userData) {
setUser(userData);
setUser({...userData});
} else {
window.location.href = "/onboarding";
}
+5 -2
View File
@@ -5,7 +5,7 @@ import { useState, useEffect } from "react";
// Firebase Imports
import { auth, database } from "../../../firebase-config";
import { ref, onValue, set, onDisconnect } from "firebase/database";
import { ref, onValue, set, onDisconnect, get, onChildAdded, onChildRemoved } from "firebase/database";
import { useAuthState } from "react-firebase-hooks/auth"
// Component Imports
@@ -90,13 +90,16 @@ function Chat() {
uid: user.uid,
})*/
onValue(ref(database, `/rooms/${path}`), (roomData) => {
// Room Object Load
get(ref(database, `/rooms/${path}`)).then((roomData) => {
roomData = roomData.val();
setChatRoomObj(roomData)
if (!doneLoading) {
setDoneLoading(true)
}
})
}
}, [user]);
+8 -7
View File
@@ -5,7 +5,7 @@ import { useState, useEffect } from "react";
// Firebase Imports
import { auth, database } from "../../../firebase-config";
import { ref, onValue, set, onDisconnect } from "firebase/database";
import { ref, onValue, set, onDisconnect, get, onChildAdded, onChildRemoved} from "firebase/database";
import { useAuthState } from "react-firebase-hooks/auth"
// Component Imports
@@ -94,12 +94,13 @@ function Chat() {
uid: user.uid,
})*/
onValue(ref(database, `/dms/${path}`), (roomData) => {
roomData = roomData.val();
setChatRoomObj(roomData)
if (!doneLoading) {
setDoneLoading(true)
}
// Room Object Load
get(ref(database, `/dms/${path}`)).then((roomData) => {
roomData = roomData.val();
setChatRoomObj(roomData)
if (!doneLoading) {
setDoneLoading(true)
}
})
}
}, [user]);
@@ -2,7 +2,7 @@
import { Form, useForm } from "react-hook-form";
// Firebase Imports
import { ref, set } from "firebase/database";
import { ref, set, onChildAdded, onChildRemoved } from "firebase/database";
import { database } from "../../../../firebase-config";
// Component Imports
@@ -11,6 +11,11 @@ import { Chat, SystemMessage } from "../datatypes";
// Icons
import SendIcon from '@mui/icons-material/Send';
// Notification
import { createNotification } from "../notifications/notifications";
import { useEffect, useState } from "react";
/**
* Chat Room Component
* @prop {JSON} roomObj - Room Object
@@ -18,31 +23,61 @@ import SendIcon from '@mui/icons-material/Send';
* @returns {Object} - Chat Room Component
*/
export function DMRoom({ roomObj, user }) {
const [chatRoomObj, setChatRoomObj] = useState(roomObj);
const [chats, setChats] = useState(null);
var { register, control, reset, handleSubmit } = useForm();
// Message updater
var chatsArr = [];
var messages = roomObj.chats;
for (var message in messages) {
if (messages[message].isSystem) {
chatsArr.push(
<SystemMessage
chatObj={messages[message]}
key={messages[message].timestamp}
/>
);
} else {
chatsArr.push(
<Chat
chatObj={messages[message]}
user={user}
path={"/dms/" + roomObj.room}
key={messages[message].timestamp}
/>
);
// Listeners for DMs
useEffect(() => {
var path = roomObj.UIDs[0] < roomObj.UIDs[1] ? roomObj.UIDs[0] + "-" + roomObj.UIDs[1] : roomObj.UIDs[1] + "-" + roomObj.UIDs[0];
onChildAdded(ref(database, `/dms/${path}/chats`), (newDM) => {
if (chatRoomObj) {
var newDMRoomObj = chatRoomObj
if (newDMRoomObj) {
if (!newDMRoomObj.chats) {
newDMRoomObj.chats = {}
}
newDMRoomObj.chats[newDM.key] = newDM.val()
setChatRoomObj({...newDMRoomObj})
}
}
});
onChildRemoved(ref(database, `/dms/${path}/chats`), (removed) => {
if (chatRoomObj) {
var newDMRoomObj = chatRoomObj
var deleted = removed.val()
delete newDMRoomObj.chats[`${deleted.timestamp}-${deleted.user}`]
setChatRoomObj({...newDMRoomObj})
}
});
}, [])
useEffect(() => {
// Message updater
var chatsArr = [];
var messages = chatRoomObj.chats;
for (var message in messages) {
if (messages[message].isSystem) {
chatsArr.push(
<SystemMessage
chatObj={messages[message]}
key={messages[message].timestamp}
/>
);
} else {
chatsArr.push(
<Chat
chatObj={messages[message]}
user={user}
path={"/dms/" + chatRoomObj.room}
key={messages[message].timestamp}
/>
);
}
}
}
var chats = chatsArr.reverse();
setChats(chatsArr.reverse())
}, [chatRoomObj])
/**
* Send Message in Chatroom
@@ -50,6 +85,21 @@ export function DMRoom({ roomObj, user }) {
* @returns {void}
*/
function sendMessage(data) {
// Other UID
var otherUID = chatRoomObj.initUID == user.uid ? chatRoomObj.targetUID : chatRoomObj.initUID;
// Send other user notification if not in room
if (chatRoomObj.users && chatRoomObj.users.online) {
if (!(otherUID in chatRoomObj.users.online)) {
createNotification(
"New Message",
`${user.username} sent you a message.`,
"dm",
user.uid,
otherUID
);
}
}
var messageFilterBypass = [undefined, null, "", " ", ' ', '\'']
reset();
if (!messageFilterBypass.includes(data.message)) {
@@ -63,7 +113,7 @@ export function DMRoom({ roomObj, user }) {
set(
ref(
database,
`/dms/${roomObj.room}/chats/${new Date().getTime()}-${user.username}`
`/dms/${chatRoomObj.room}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
@@ -23,6 +23,7 @@ import CloseIcon from '@mui/icons-material/Close';
*/
function closeChat(chatRoomObj, user) {
remove(ref(database, `/rooms/${chatRoomObj.path}/${chatRoomObj.name}-${chatRoomObj.timestamp}/users/online/${user.uid}`))
}
/**
@@ -17,28 +17,38 @@ import { ref, set, remove } from "firebase/database";
* @returns {Notification} - Notification Component
*/
function Notification({data}) {
/**
* Removes Notification
* @returns {void}
*/
function removeNotification() {
remove(ref(database, `/users/${data.ruser}/notifications/${data.suser}-${data.action}`))
}
/**
* Determines Action
*/
function onClick() {
if (data.action === "dm") {
var order = data.suser > data.ruser ? data.ruser + "-" + data.suser : data.suser + "-" + data.ruser;
window.location.href = "/dm?dm=" + order;
removeNotification()
}
}
return (
<div className="hover:bg-[#C0C0C0] rounded-lg">
<div className="hover:bg-[#C0C0C0] rounded-lg cursor-pointer" >
<div className="float-right top-0 cursor-pointer p-2 text-[24px] text-slate-500">
<div onClick={() => {removeNotification(data.id)}}><CloseIcon/></div>
<div onClick={() => {removeNotification()}}><CloseIcon/></div>
</div>
<div className="p-3 text-left">
{data.title}<br/>
<div className="p-3 text-left" onClick={() => {onClick()}}>
<span className="font-bold">{data.title}</span><br/>
{data.byline}<br/>
</div>
</div>
)
}
/**
* Removes Notification
* @param {String} ruser - Receiving user UID (User Whose Notifications are being removed)
* @param {String} dataID - Notification ID
* @returns {void}
*/
function removeNotification(ruser, dataID) {
remove(ref(database, `/user/${ruser}/notifications/${dataID}`))
}
/**
* Creates New Notification
@@ -49,16 +59,18 @@ function removeNotification(ruser, dataID) {
* @param {String} ruser - Receiving user UID
* @returns {void}
*/
function createNotification(title, byline, action, suser, ruser) {
export function createNotification(title, byline, action, suser, ruser) {
var timestamp = new Date().getTime();
var payload = {
title: title,
byline: byline,
action: action,
suser: suser,
ruser: ruser
ruser: ruser,
id: suser + "-" + action,
timestamp: timestamp
};
set(ref(database, `/user/${ruser}/notifications/${timestamp}-${suser}`), payload);
set(ref(database, `/users/${ruser}/notifications/${suser}-${action}`), payload);
}
/**
@@ -69,14 +81,13 @@ function createNotification(title, byline, action, suser, ruser) {
*/
export function NotificationPanel({user}) {
var notificationsMap = []
if (user.notification) {
for (var notificationPackage in user.notification) {
notificationsMap.push(<Notification data={user.notification[notificationPackage]}/>)
if (user.notifications) {
for (var notificationPackage in user.notifications) {
notificationsMap.push(<Notification data={user.notifications[notificationPackage]}/>)
}
} else {
notificationsMap = null
}
var isNotifications = true
} else {
var isNotifications = false
}
return (
<Popover className="relative">
@@ -88,8 +99,8 @@ export function NotificationPanel({user}) {
<Popover.Panel className="absolute z-10 bg-white mt-[4px] rounded-xl ml-3 shadow-2xl w-64 md:right-[0px] max-md:right-[-300%]">
<div className="grid grid-cols-1">
{isNotifications && notificationsMap}
{!isNotifications &&
{notificationsMap}
{!notificationsMap &&
<div className="h-[64px] flex flex-col justify-center items-center">
<NotificationsPausedIcon/> All caught up!
</div>
+54 -27
View File
@@ -2,7 +2,7 @@
import { Form, useForm } from "react-hook-form";
// Firebase Imports
import { ref, set } from "firebase/database";
import { ref, set, onChildAdded, onChildRemoved } from "firebase/database";
import { database } from "../../../../firebase-config";
// Component Imports
@@ -10,6 +10,7 @@ import { Chat, SystemMessage } from "../datatypes";
// Icons
import SendIcon from '@mui/icons-material/Send';
import { useState,useEffect } from "react";
/**
* Chat Room Component
@@ -18,32 +19,60 @@ import SendIcon from '@mui/icons-material/Send';
* @returns {Object} - Chat Room Component
*/
export function ChatRoom({ roomObj, user }) {
const [chatRoomObj, setChatRoomObj] = useState(roomObj);
const [chats, setChats] = useState(null);
var { register, control, reset, handleSubmit } = useForm();
// Listeners for Chats
useEffect(() => {
var path = chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp;
onChildAdded(ref(database, `/rooms/${path}/chats`), (newChat) => {
var newChatRoomObj = chatRoomObj
if (newChatRoomObj) {
if (!newChatRoomObj.chats) {
newChatRoomObj.chats = {}
}
newChatRoomObj.chats[newChat.key] = newChat.val()
setChatRoomObj({...newChatRoomObj})
}
// Message updater
var chatsArr = [];
var messages = roomObj.chats;
for (var message in messages) {
if (messages[message].isSystem) {
chatsArr.push(
<SystemMessage
chatObj={messages[message]}
key={messages[message].timestamp}
/>
);
} else {
chatsArr.push(
<Chat
chatObj={messages[message]}
user={user}
path={"/rooms/" +roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp}
key={messages[message].timestamp}
/>
);
});
onChildRemoved(ref(database, `/rooms/${path}/chats`), (removed) => {
if (chatRoomObj) {
var newChatRoomObj = chatRoomObj
var deleted = removed.val()
delete newChatRoomObj.chats[`${deleted.timestamp}-${deleted.user}`]
setChatRoomObj({...newChatRoomObj})
}
});
}, [])
useEffect(() => {
// Message updater
var chatsArr = [];
var messages = chatRoomObj.chats;
for (var message in messages) {
if (messages[message].isSystem) {
chatsArr.push(
<SystemMessage
chatObj={messages[message]}
key={messages[message].timestamp}
/>
);
} else {
chatsArr.push(
<Chat
chatObj={messages[message]}
user={user}
path={"/rooms/" + chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp}
key={messages[message].timestamp}
/>
);
}
}
}
var chats = chatsArr.reverse();
setChats(chatsArr.reverse())
}, [chatRoomObj])
/**
* Send Message in Chatroom
* @param {JSON} data - Message data to send (from form)
@@ -63,9 +92,7 @@ export function ChatRoom({ roomObj, user }) {
set(
ref(
database,
`/rooms/${
roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp
}/chats/${new Date().getTime()}-${user.username}`
`/rooms/${chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
+12 -12
View File
@@ -1,23 +1,23 @@
import { Member } from "../datatypes"
import { database } from "../../../../firebase-config"
import {ref, get, set} from "firebase/database"
import {ref, get, onValue} from "firebase/database"
import { useState, useEffect } from "react"
export function Sidebar({user, chatRoomObj}) {
const [profileData, setProfileData] = useState(null)
// Active users list
if (
chatRoomObj.hasOwnProperty("users") &&
chatRoomObj.users.hasOwnProperty("online")
) {
var activeUsers = [];
var activeUsersJSON = chatRoomObj.users.online;
const [profileData, setProfileData] = useState(null)
const [chatroomOnline, setChatroomOnline] = useState(null)
var path = chatRoomObj.UIDs[0] < chatRoomObj.UIDs[1] ? chatRoomObj.UIDs[0] + "-" + chatRoomObj.UIDs[1] : chatRoomObj.UIDs[1] + "-" + chatRoomObj.UIDs[0];
var activeUsers = []
onValue(ref(database, `/dms/${path}/users/online`), (snapshot) => {
if (snapshot.exists()) {
var activeUsersJSON = snapshot.val();
for (var activeUser in activeUsersJSON)
activeUsers.push(<Member memberObj={activeUsersJSON[activeUser]} />);
var chatroomOnline = activeUsers
activeUsers.push(<Member memberObj={activeUsersJSON[activeUser]} key={activeUser} />);
}
})
useEffect(() => {
if (user) {
@@ -49,7 +49,7 @@ export function Sidebar({user, chatRoomObj}) {
</div>
<div className="bg-white rounded-lg m-2 shadow-2xl">
<div>In The Chat</div>
{chatroomOnline}
{activeUsers}
</div>
</div>
</div>