From 7954432add1848449e44d7937277b81b1ee0024b Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Wed, 17 Apr 2024 22:06:24 -0400 Subject: [PATCH 1/8] Add Global User Online Status --- frontend-next/src/app/user/page.js | 8 +++++--- frontend-next/src/components/app/datatypes.js | 3 ++- frontend-next/src/components/app/friends/friends.js | 3 ++- frontend-next/src/components/app/header.js | 11 ++++++++++- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/frontend-next/src/app/user/page.js b/frontend-next/src/app/user/page.js index 52a7a25..3f724f8 100644 --- a/frontend-next/src/app/user/page.js +++ b/frontend-next/src/app/user/page.js @@ -8,7 +8,6 @@ import { useAuthState } from "react-firebase-hooks/auth" // Refactored Component Imports - // Data Structure Imports import { ProfileRoom } from "../../components/app/profile/ProfileRoom"; import { ProfileEdit } from "../../components/app/profile/ProfileEdit"; @@ -20,6 +19,9 @@ import { Header } from "../../components/app/header"; // Friend Import import { addFriend } from "../../components/app/friends/friends"; +// Icons +import CircleIcon from '@mui/icons-material/Circle'; + /** * User Profile Page * @returns {Object} - User Profile Page @@ -128,8 +130,8 @@ function UserProfile() { style={{maxWidth: "350px", maxHeight: "450px"}} className="relative mx-auto rounded-2xl overflow-hidden" /> -
- {profileData.firstName} {profileData.lastName} +
+ {profileData.lastOnline == true && }{profileData.firstName} {profileData.lastName}
@{profileData.username}
{profileData.bio}
diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index e03dfff..c55b64a 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -3,6 +3,7 @@ import { useEffect, useState } from "react"; // Icons import PersonIcon from '@mui/icons-material/Person'; +import CircleIcon from '@mui/icons-material/Circle'; // Colors for Messages const userColors = [ @@ -149,7 +150,7 @@ export function Member({ memberObj }) { return (
- {memberObj.username} + {memberObj.lastOnline == true && }{memberObj.username}
); diff --git a/frontend-next/src/components/app/friends/friends.js b/frontend-next/src/components/app/friends/friends.js index 467a2ff..30493b9 100644 --- a/frontend-next/src/components/app/friends/friends.js +++ b/frontend-next/src/components/app/friends/friends.js @@ -12,6 +12,7 @@ import { openDM } from './dm'; // Icons import CheckIcon from '@mui/icons-material/Check'; import CloseIcon from '@mui/icons-material/Close'; +import CircleIcon from '@mui/icons-material/Circle'; /** * Send a friend request to a user @@ -41,7 +42,7 @@ export function Friend({user,friendObj}) {
-
{friendObj.firstName} {friendObj.lastName}
+
{friendObj.lastOnline == true && }{friendObj.firstName} {friendObj.lastName}
@{friendObj.username}
diff --git a/frontend-next/src/components/app/header.js b/frontend-next/src/components/app/header.js index aa860c8..bb9dfea 100644 --- a/frontend-next/src/components/app/header.js +++ b/frontend-next/src/components/app/header.js @@ -3,7 +3,7 @@ import Link from "next/link" // Firebase Imports import { database } from "../../../firebase-config"; -import { ref, set, remove } from "firebase/database"; +import { ref, set, remove, onDisconnect, serverTimestamp } from "firebase/database"; // Component Imports import { NotificationPanel } from "./notifications/notifications"; @@ -88,6 +88,15 @@ export function Header({mainTab,chatRoomObj,user,sidebarControl}) { } } + + // Sets User Online / Offline + // Stored in header for easy code maintenance and retains user online/offline throughout app + // Makes user online + set(ref(database, `/users/${user.uid}/lastOnline`), true) + + // Makes user offline (with last time online) + onDisconnect(ref(database, `/users/${user.uid}/lastOnline`)).set(serverTimestamp()) + return (
From 5b161ad232504dac841458890148c58ec0224797 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Wed, 17 Apr 2024 22:18:20 -0400 Subject: [PATCH 2/8] Add Profile Menu Option to Appear Offline --- frontend-next/src/components/app/header.js | 4 +++- .../src/components/app/profile/ProfilePanel.js | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frontend-next/src/components/app/header.js b/frontend-next/src/components/app/header.js index bb9dfea..467f89d 100644 --- a/frontend-next/src/components/app/header.js +++ b/frontend-next/src/components/app/header.js @@ -92,7 +92,9 @@ export function Header({mainTab,chatRoomObj,user,sidebarControl}) { // Sets User Online / Offline // Stored in header for easy code maintenance and retains user online/offline throughout app // Makes user online - set(ref(database, `/users/${user.uid}/lastOnline`), true) + if (user.invisibleStatus == false) { + set(ref(database, `/users/${user.uid}/lastOnline`), true) + } // Makes user offline (with last time online) onDisconnect(ref(database, `/users/${user.uid}/lastOnline`)).set(serverTimestamp()) diff --git a/frontend-next/src/components/app/profile/ProfilePanel.js b/frontend-next/src/components/app/profile/ProfilePanel.js index 0b3dcb3..387025d 100644 --- a/frontend-next/src/components/app/profile/ProfilePanel.js +++ b/frontend-next/src/components/app/profile/ProfilePanel.js @@ -3,8 +3,9 @@ import { Popover } from "@headlessui/react"; import Link from "next/link" // Firebase Imports -import { auth } from "../../../../firebase-config"; +import { auth, database } from "../../../../firebase-config"; import { signOut } from "firebase/auth"; +import {update, ref, serverTimestamp} from "firebase/database"; /** * Logs out from Firebase Authentication @@ -43,6 +44,18 @@ export function ProfilePanel({user}) { > View Profile +
{ + // Toggle Invisible Status + update(ref(database, `/users/${user.uid}`), { + invisibleStatus: user.invisibleStatus? !user.invisibleStatus: true, + lastOnline: user.invisibleStatus? true: serverTimestamp() + } + ); + }} + > + {user.invisibleStatus ? "Go Online" : "Go Invisible"} +
Date: Wed, 17 Apr 2024 22:27:25 -0400 Subject: [PATCH 3/8] Simple Fix for Blank Messages --- frontend-next/src/components/app/page/chat.js | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/frontend-next/src/components/app/page/chat.js b/frontend-next/src/components/app/page/chat.js index 1af3db9..b7cd438 100644 --- a/frontend-next/src/components/app/page/chat.js +++ b/frontend-next/src/components/app/page/chat.js @@ -48,23 +48,25 @@ export function ChatRoom({ roomObj, user }) { * @returns {void} */ function sendMessage(data) { - reset(); - var payload = { - body: data.message, - user: user.username, - uid: user.uid, - isSystem: false, - timestamp: new Date().getTime(), - }; - set( - ref( - database, - `/rooms/${ - roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp - }/chats/${new Date().getTime()}-${user.username}` - ), - payload - ); + if (data.message) { + reset(); + var payload = { + body: data.message, + user: user.username, + uid: user.uid, + isSystem: false, + timestamp: new Date().getTime(), + }; + set( + ref( + database, + `/rooms/${ + roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp + }/chats/${new Date().getTime()}-${user.username}` + ), + payload + ); + } } if (!chats) return
No Chats
; From c3d55c94d1bc9646005f4daf1edc455b4836b739 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Wed, 17 Apr 2024 22:46:55 -0400 Subject: [PATCH 4/8] Add Profanity Filter --- frontend-next/package-lock.json | 17 +++++++++++++++++ frontend-next/package.json | 1 + frontend-next/src/components/app/datatypes.js | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/frontend-next/package-lock.json b/frontend-next/package-lock.json index d3182f5..69d6d5a 100644 --- a/frontend-next/package-lock.json +++ b/frontend-next/package-lock.json @@ -16,6 +16,7 @@ "@headlessui/react": "^1.7.18", "@mui/icons-material": "^5.15.14", "@mui/material": "^5.15.14", + "bad-words": "^3.0.4", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", @@ -2893,6 +2894,22 @@ "npm": ">=6" } }, + "node_modules/bad-words": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bad-words/-/bad-words-3.0.4.tgz", + "integrity": "sha512-v/Q9uRPH4+yzDVLL4vR1+S9KoFgOEUl5s4axd6NIAq8SV2mradgi4E8lma/Y0cw1ltVdvyegCQQKffCPRCp8fg==", + "dependencies": { + "badwords-list": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/badwords-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz", + "integrity": "sha512-oWhaSG67e+HQj3OGHQt2ucP+vAPm1wTbdp2aDHeuh4xlGXBdWwzZ//pfu6swf5gZ8iX0b7JgmSo8BhgybbqszA==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", diff --git a/frontend-next/package.json b/frontend-next/package.json index 3c73bf5..82be4fc 100644 --- a/frontend-next/package.json +++ b/frontend-next/package.json @@ -17,6 +17,7 @@ "@headlessui/react": "^1.7.18", "@mui/icons-material": "^5.15.14", "@mui/material": "^5.15.14", + "bad-words": "^3.0.4", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index e03dfff..cfa3d48 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -1,5 +1,7 @@ import Link from "next/link" import { useEffect, useState } from "react"; +const Filter = require('bad-words') +const filter = new Filter(); // Icons import PersonIcon from '@mui/icons-material/Person'; @@ -97,6 +99,8 @@ const generateColor = (user_str) => { */ export function Chat({ chatObj }) { var message = RMF(chatObj.body) + if (message) + message = filter.clean(message) return (
From 32a5f5b05795b5b7b23c5e1a4271f349679b9d06 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Thu, 18 Apr 2024 00:01:17 -0400 Subject: [PATCH 5/8] Add Image Detection to RMF (Rich Message Formatting) --- frontend-next/src/components/app/datatypes.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index e03dfff..8a66b05 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -36,19 +36,27 @@ let dateOptions = { * @returns {String} - Formatted Message (IN HTML) */ function RMF(message) { + var IMG_END = [".jpg", ".jpeg", ".png", ".gif", ".webp"] var URLREGEX = /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; var URLmatch = message.match(URLREGEX); + var newMessage = [] if (URLmatch) { for (var i = 0; i < URLmatch.length; i++) { - var link = ( - {message.split(URLmatch[i])[0]} - {URLmatch[i]} - {message.split(URLmatch[i])[1]} - ) - message = link + if (IMG_END.includes(URLmatch[i].slice(-4)) || IMG_END.includes(URLmatch[i].slice(-5))) { + // Its a photo + newMessage.push(()) + } else { + console.log(message) + newMessage.push(( + {URLmatch.length == 1 && message.split(URLmatch[i])[0]} + {URLmatch[i]} + {(i == URLmatch.length || URLmatch.length == 1) && message.split(URLmatch[i])[1]} + )) + } + } } - return message + return newMessage } /** * Grabs Window Size From de99e26ca208d800c606bde64cd278dbb145633a Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Thu, 18 Apr 2024 12:47:02 -0400 Subject: [PATCH 6/8] Properly Integrate Images, RMF and Profane filters --- frontend-next/src/components/app/datatypes.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index dbb8b10..72a28fc 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -42,7 +42,7 @@ function RMF(message) { var IMG_END = [".jpg", ".jpeg", ".png", ".gif", ".webp"] var URLREGEX = /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; var URLmatch = message.match(URLREGEX); - var newMessage = [] + var newMessage = URLmatch ? [] : message if (URLmatch) { for (var i = 0; i < URLmatch.length; i++) { if (IMG_END.includes(URLmatch[i].slice(-4)) || IMG_END.includes(URLmatch[i].slice(-5))) { @@ -107,9 +107,10 @@ const generateColor = (user_str) => { * @returns {Object} - Chat Message Component */ export function Chat({ chatObj }) { - var message = RMF(chatObj.body) - if (message) - message = filter.clean(message) + if (chatObj.body) { + var message = filter.clean(chatObj.body) + message = RMF(message) + } return (
From 9ee81aa487bf6f54c67af6c6fa4f2577b07d8b95 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Thu, 18 Apr 2024 12:59:12 -0400 Subject: [PATCH 7/8] Profile Picture Sizing Corrected on Sidebar --- frontend-next/src/components/app/friends/dm.js | 10 ++++++---- frontend-next/src/components/app/friends/friends.js | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frontend-next/src/components/app/friends/dm.js b/frontend-next/src/components/app/friends/dm.js index 6e2e92d..44071c1 100644 --- a/frontend-next/src/components/app/friends/dm.js +++ b/frontend-next/src/components/app/friends/dm.js @@ -44,10 +44,12 @@ export function DM({user,friendObj}) {
{openDM(user,friendObj.uid)}}> -
-
-
{friendObj.firstName} {friendObj.lastName}
-
@{friendObj.username}
+
+
+
+
{friendObj.lastOnline == true && }{friendObj.firstName} {friendObj.lastName}
+
@{friendObj.username}
+
diff --git a/frontend-next/src/components/app/friends/friends.js b/frontend-next/src/components/app/friends/friends.js index 30493b9..1d1f774 100644 --- a/frontend-next/src/components/app/friends/friends.js +++ b/frontend-next/src/components/app/friends/friends.js @@ -40,10 +40,12 @@ export function Friend({user,friendObj}) {
-
-
-
{friendObj.lastOnline == true && }{friendObj.firstName} {friendObj.lastName}
-
@{friendObj.username}
+
+
+
+
{friendObj.lastOnline == true && }{friendObj.firstName} {friendObj.lastName}
+
@{friendObj.username}
+
From d1a9116b34e9c2d5cfa77913b78b70d20329cb87 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Thu, 18 Apr 2024 13:01:41 -0400 Subject: [PATCH 8/8] Fix Profile Picture Scaling on Different Screen Sizes --- frontend-next/src/app/user/page.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend-next/src/app/user/page.js b/frontend-next/src/app/user/page.js index 3f724f8..eb84533 100644 --- a/frontend-next/src/app/user/page.js +++ b/frontend-next/src/app/user/page.js @@ -127,8 +127,7 @@ function UserProfile() {
{profileData.lastOnline == true && }{profileData.firstName} {profileData.lastName}