Fix bugs in UserAccount

This commit is contained in:
Alex Erdei 2025-04-29 14:09:53 +01:00
parent c7f6906797
commit ab77ae4c02
1 changed files with 189 additions and 101 deletions

View File

@ -1,12 +1,42 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
/* UI */
import TitleBar from "./Titlebar"; import TitleBar from "./Titlebar";
import Profile from "./Profile"; import Profile from "./Profile";
import PhotoViewer from "./PhotoViewer"; import PhotoViewer from "./PhotoViewer";
import HomePage from "./HomePage"; import HomePage from "./HomePage";
import FriendsListPage from "./FriendsListPage"; 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"; import Container from "react-bootstrap/Container";
/* Redux */
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import {
friendsListPageSet,
profileLinkSet,
watchSet,
} from "../features/accountPage/accountPageSlice";
/* Mock-backend helpers */
import { import {
currentUserOffline, currentUserOffline,
currentUserOnline, currentUserOnline,
@ -14,105 +44,163 @@ import {
subscribeUsers, subscribeUsers,
subscribePosts, subscribePosts,
} from "../backend/backend"; } from "../backend/backend";
import {
friendsListPageSet,
profileLinkSet,
watchSet,
} from "../features/accountPage/accountPageSlice";
const UserAccount = (props) => { /* ------------------------------------------------------------------ */
/* Keep Redux in sync with the current pathname (once per navigation) */
/* ------------------------------------------------------------------ */
const RouteStateSync = () => {
const dispatch = useDispatch();
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 profileLink = useSelector((state) => state.accountPage.profileLink);
const currentUser = useSelector((state) => state.currentUser); const currentUser = useSelector((state) => state.currentUser);
const users = useSelector((state) => state.users);
const isFriendsListPage = useSelector(
(state) => state.accountPage.isFriendsListPage
);
const dispatch = useDispatch(); const users = useSelector((state) => state.users);
/* -------------------------------------------------- */
/* Firestore-like subscriptions & online/offline flag */
/* -------------------------------------------------- */
useEffect(() => { useEffect(() => {
const unsubscribeCurrentUser = subscribeCurrentUser(); const unsubCurrentUser = subscribeCurrentUser();
const unsubscribeUsers = subscribeUsers();
const unsubscribePosts = subscribePosts(); const unsubUsers = subscribeUsers();
//We make currentUser online
const unsubPosts = subscribePosts();
/* mark user online */
currentUserOnline(); currentUserOnline();
//We add event listener for the event when the user closes the browser window
const beforeunloadListener = (e) => { /* window closed or refreshed */
//We put the user offline
currentUserOffline(); const beforeUnload = () => currentUserOffline();
};
window.addEventListener("beforeunload", beforeunloadListener); window.addEventListener("beforeunload", beforeUnload);
//we add event listener for the event when the browser window change visibility
const visibilitychangeListener = (e) => { /* tab visibility switch */
if (document.visibilityState === "visible") currentUserOnline();
else currentUserOffline(); const visChange = () =>
}; document.visibilityState === "visible"
document.addEventListener("visibilitychange", visibilitychangeListener); ? currentUserOnline()
: currentUserOffline();
document.addEventListener("visibilitychange", visChange);
/* cleanup */
return () => { return () => {
unsubscribeCurrentUser(); unsubCurrentUser();
unsubscribeUsers();
unsubscribePosts(); unsubUsers();
unsubPosts();
window.removeEventListener("beforeunload", beforeUnload);
document.removeEventListener("visibilitychange", visChange);
}; };
}, []); }, []);
//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) { /* Build unique profile link (.index appended once) */
return <div>...Loading</div>;
/* -------------------------------------------------- */
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 <div>Loading</div>;
} }
/* -------------------------------------------------- */
/* Render */
/* -------------------------------------------------- */
return ( return (
<div className="bg-200 vw-100 main-container overflow-hidden"> <div className='bg-200 vw-100 main-container overflow-hidden'>
<Container className="w-100 p-0" fluid> <Container className='w-100 p-0' fluid>
<BrowserRouter> <Router>
<RouteStateSync />
<TitleBar /> <TitleBar />
<Switch> <Switch>
{/* Friends list ------------------------------------------------ */}
<Route path='/fakebook/friends/list' component={FriendsListPage} />
{/* Single photo ----------------------------------------------- */}
<Route path='/fakebook/photo/:userID/:n' component={PhotoViewer} />
{/* Watch (video feed) ----------------------------------------- */}
<Route <Route
path="/fakebook/friends/list" path='/fakebook/watch'
render={() => { render={(props) => <HomePage {...props} className='pt-5' />}
dispatch(friendsListPageSet(true));
return <FriendsListPage />;
}}
/> />
{/* User profile ----------------------------------------------- */}
<Route path='/fakebook/:userName' component={Profile} />
{/* News-feed root --------------------------------------------- */}
<Route <Route
path={`/fakebook/photo/:userID/:n`} path='/fakebook'
render={() => <PhotoViewer />} exact
/> render={(props) => <HomePage {...props} className='pt-5' />}
<Route
path="/fakebook/watch"
render={() => {
dispatch(friendsListPageSet(false));
dispatch(watchSet(true));
return <HomePage className="pt-5" />;
}}
/>
<Route
path={`/fakebook/:userName`}
render={() => {
if (isFriendsListPage) return <FriendsListPage />;
else {
return <Profile />;
}
}}
/>
<Route
path="/fakebook"
render={() => {
dispatch(friendsListPageSet(false));
dispatch(watchSet(false));
return <HomePage className="pt-5" />;
}}
/> />
</Switch> </Switch>
</BrowserRouter> </Router>
</Container> </Container>
</div> </div>
); );