From ab77ae4c02515d5c61213c3d237baf6f161cdf01 Mon Sep 17 00:00:00 2001 From: Alex Erdei Date: Tue, 29 Apr 2025 14:09:53 +0100 Subject: [PATCH] Fix bugs in UserAccount --- src/components/UserAccount.jsx | 290 +++++++++++++++++++++------------ 1 file changed, 189 insertions(+), 101 deletions(-) diff --git a/src/components/UserAccount.jsx b/src/components/UserAccount.jsx index d31a805..e05ea03 100644 --- a/src/components/UserAccount.jsx +++ b/src/components/UserAccount.jsx @@ -1,121 +1,209 @@ import React, { useEffect } from "react"; + +/* UI */ + import TitleBar from "./Titlebar"; + import Profile from "./Profile"; + import PhotoViewer from "./PhotoViewer"; + import HomePage from "./HomePage"; + import FriendsListPage from "./FriendsListPage"; -import { BrowserRouter, Switch, Route } from "react-router-dom"; + +/* Router */ + +import { + BrowserRouter as Router, + Switch, + Route, + useLocation, +} from "react-router-dom"; + +/* Layout */ + import Container from "react-bootstrap/Container"; + +/* Redux */ + import { useDispatch, useSelector } from "react-redux"; + import { - currentUserOffline, - currentUserOnline, - subscribeCurrentUser, - subscribeUsers, - subscribePosts, -} from "../backend/backend"; -import { - friendsListPageSet, - profileLinkSet, - watchSet, + friendsListPageSet, + profileLinkSet, + watchSet, } from "../features/accountPage/accountPageSlice"; -const UserAccount = (props) => { - const profileLink = useSelector((state) => state.accountPage.profileLink); +/* Mock-backend helpers */ - const currentUser = useSelector((state) => state.currentUser); - const users = useSelector((state) => state.users); - const isFriendsListPage = useSelector( - (state) => state.accountPage.isFriendsListPage - ); +import { + currentUserOffline, + currentUserOnline, + subscribeCurrentUser, + subscribeUsers, + subscribePosts, +} from "../backend/backend"; - const dispatch = useDispatch(); +/* ------------------------------------------------------------------ */ - useEffect(() => { - const unsubscribeCurrentUser = subscribeCurrentUser(); - const unsubscribeUsers = subscribeUsers(); - const unsubscribePosts = subscribePosts(); - //We make currentUser online - currentUserOnline(); - //We add event listener for the event when the user closes the browser window - const beforeunloadListener = (e) => { - //We put the user offline - currentUserOffline(); - }; - window.addEventListener("beforeunload", beforeunloadListener); - //we add event listener for the event when the browser window change visibility - const visibilitychangeListener = (e) => { - if (document.visibilityState === "visible") currentUserOnline(); - else currentUserOffline(); - }; - document.addEventListener("visibilitychange", visibilitychangeListener); - return () => { - unsubscribeCurrentUser(); - unsubscribeUsers(); - unsubscribePosts(); - }; - }, []); +/* Keep Redux in sync with the current pathname (once per navigation) */ - //We add the index of user to the profileLink if there are more users with the exact same userName - const addIndexToProfileLink = () => { - if (currentUser && currentUser.index && currentUser.index > 0) { - return `${profileLink}.${currentUser.index}`; - } else return profileLink; - }; - const newProfileLink = addIndexToProfileLink(); - useEffect(() => dispatch(profileLinkSet(newProfileLink)), [dispatch, newProfileLink]); +/* ------------------------------------------------------------------ */ - if (users.length === 0 || !currentUser) { - return
...Loading
; - } +const RouteStateSync = () => { + const dispatch = useDispatch(); - return ( -
- - - - - { - dispatch(friendsListPageSet(true)); - return ; - }} - /> - } - /> - { - dispatch(friendsListPageSet(false)); - dispatch(watchSet(true)); - return ; - }} - /> - { - if (isFriendsListPage) return ; - else { - return ; - } - }} - /> - { - dispatch(friendsListPageSet(false)); - dispatch(watchSet(false)); - return ; - }} - /> - - - -
- ); + const location = useLocation(); + + useEffect(() => { + const { pathname } = location; + + /* friends list page */ + + dispatch(friendsListPageSet(pathname.startsWith("/fakebook/friends/list"))); + + /* watch page (videos feed) */ + + dispatch(watchSet(pathname.startsWith("/fakebook/watch"))); + }, [location, dispatch]); + + return null; // renders nothing +}; + +/* ------------------------------------------------------------------ */ + +const UserAccount = () => { + const dispatch = useDispatch(); + + /* Redux selectors */ + + const profileLink = useSelector((state) => state.accountPage.profileLink); + + const currentUser = useSelector((state) => state.currentUser); + + const users = useSelector((state) => state.users); + + /* -------------------------------------------------- */ + + /* Firestore-like subscriptions & online/offline flag */ + + /* -------------------------------------------------- */ + + useEffect(() => { + const unsubCurrentUser = subscribeCurrentUser(); + + const unsubUsers = subscribeUsers(); + + const unsubPosts = subscribePosts(); + + /* mark user online */ + + currentUserOnline(); + + /* window closed or refreshed */ + + const beforeUnload = () => currentUserOffline(); + + window.addEventListener("beforeunload", beforeUnload); + + /* tab visibility switch */ + + const visChange = () => + document.visibilityState === "visible" + ? currentUserOnline() + : currentUserOffline(); + + document.addEventListener("visibilitychange", visChange); + + /* cleanup */ + + return () => { + unsubCurrentUser(); + + unsubUsers(); + + unsubPosts(); + + window.removeEventListener("beforeunload", beforeUnload); + + document.removeEventListener("visibilitychange", visChange); + }; + }, []); + + /* -------------------------------------------------- */ + + /* Build unique profile link (.index appended once) */ + + /* -------------------------------------------------- */ + + useEffect(() => { + if (!currentUser) return; + + /* remove any existing trailing ".number" */ + + const base = profileLink.replace(/\.\d+$/, ""); + + const newLink = + currentUser.index && currentUser.index > 0 + ? `${base}.${currentUser.index}` + : base; + + dispatch(profileLinkSet(newLink)); + }, [currentUser, profileLink, dispatch]); + + /* Loading guard */ + + if (!currentUser || users.length === 0) { + return
…Loading
; + } + + /* -------------------------------------------------- */ + + /* Render */ + + /* -------------------------------------------------- */ + + return ( +
+ + + + + + + + {/* Friends list ------------------------------------------------ */} + + + + {/* Single photo ----------------------------------------------- */} + + + + {/* Watch (video feed) ----------------------------------------- */} + + } + /> + + {/* User profile ----------------------------------------------- */} + + + + {/* News-feed root --------------------------------------------- */} + + } + /> + + + +
+ ); }; export default UserAccount;