diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8861fe8..ab3d870 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -23,6 +23,7 @@ function App() { const [userId, setUserId] = useState(null); const [isLive, setIsLive] = useState(false); const [isLoading, setIsLoading] = useState(true); + const [profilePicture, setProfilePicture] = useState(null); useEffect(() => { fetch("/api/user/login_status") @@ -53,10 +54,12 @@ function App() { username, userId, isLive, + profilePicture, setIsLoggedIn, setUsername, setUserId, setIsLive, + setProfilePicture, }} > diff --git a/frontend/src/components/Navigation/Sidebar.tsx b/frontend/src/components/Navigation/Sidebar.tsx index 6502847..18b03b8 100644 --- a/frontend/src/components/Navigation/Sidebar.tsx +++ b/frontend/src/components/Navigation/Sidebar.tsx @@ -23,7 +23,7 @@ interface SideBarProps { const Sidebar: React.FC = ({ extraClasses = "" }) => { const { showSideBar, setShowSideBar } = useSidebar(); const navigate = useNavigate(); - const { username, isLoggedIn } = useAuth(); + const { username, isLoggedIn, profilePicture } = useAuth(); const [followedStreamers, setFollowedStreamers] = useState([]); const [followedCategories, setFollowedCategories] = useState([]); const [justToggled, setJustToggled] = useState(false); @@ -92,13 +92,13 @@ const Sidebar: React.FC = ({ extraClasses = "" }) => { {/* Profile Info */}
{ e.currentTarget.src = "/images/pfps/default.png"; e.currentTarget.onerror = null; }} alt="profile picture" - className="w-[3em] h-[3em] rounded-full border-[0.15em] border-purple-500 cursor-pointer" + className="w-[3em] h-[3em] object-cover rounded-full border-[0.15em] border-purple-500 cursor-pointer" onClick={() => navigate(`/user/${username}`)} />
diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index 6d711a8..4aadc9d 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -5,10 +5,12 @@ interface AuthContextType { username: string | null; userId: number | null; isLive: boolean; + profilePicture: string | null; setIsLoggedIn: (value: boolean) => void; setUsername: (value: string | null) => void; setUserId: (value: number | null) => void; setIsLive: (value: boolean) => void; + setProfilePicture: (value: string | null) => void; } export const AuthContext = createContext(undefined); diff --git a/frontend/src/hooks/useContent.ts b/frontend/src/hooks/useContent.ts index 14c6357..8f99efb 100644 --- a/frontend/src/hooks/useContent.ts +++ b/frontend/src/hooks/useContent.ts @@ -77,9 +77,8 @@ export function useFetchContent( throw new Error(`Error fetching data: ${response.status}`); } - const rawData = await response.json(); - let processedData = processor(Array.isArray(rawData) ? rawData : (rawData ? [rawData] : [])); - console.log("processedData", processedData); + const rawData = await response.json(); + let processedData = processor(Array.isArray(rawData) ? rawData : rawData ? [rawData] : []); setData(processedData); setError(null); } catch (err) { diff --git a/frontend/src/pages/NotFoundPage.tsx b/frontend/src/pages/NotFoundPage.tsx index 851324b..df268de 100644 --- a/frontend/src/pages/NotFoundPage.tsx +++ b/frontend/src/pages/NotFoundPage.tsx @@ -4,117 +4,93 @@ import Button from "../components/Input/Button"; import ChromeDinoGame from "react-chrome-dino"; const NotFoundPage: React.FC = () => { - const [stars, setStars] = useState< - { x: number; y: number; xChange: number; yChange: number }[] - >([]); - const starSize = 30; + const [stars, setStars] = useState<{ x: number; y: number; xChange: number; yChange: number }[]>([]); + const starSize = 30; - const [score, setScore] = useState(0); - const [isGameOver, setIsGameOver] = useState(false); + const [score, setScore] = useState(0); + const [isGameOver, setIsGameOver] = useState(false); - useEffect(() => { - console.log("Game over state:", isGameOver); + useEffect(() => { + const loop = setInterval(() => { + if (Math.random() < 0.1) { + const newStar = { + x: score > 20000 ? window.innerWidth + starSize : Math.random() * (window.innerWidth - starSize), + y: score > 20000 ? Math.random() * (window.innerHeight - starSize) : -starSize, + xChange: score * 0.001, + yChange: 5, + }; + setStars((prev) => [...prev, newStar]); + } - const loop = setInterval(() => { - if (Math.random() < 0.1) { - const newStar = { - x: - score > 20000 - ? window.innerWidth + starSize - : Math.random() * (window.innerWidth - starSize), - y: - score > 20000 - ? Math.random() * (window.innerHeight - starSize) - : -starSize, - xChange: score * 0.001, - yChange: 5, - }; - setStars((prev) => [...prev, newStar]); - } + setStars((prev) => { + const newStars = prev.filter((star) => { + if (star.y > window.innerHeight - starSize && star.y < window.innerHeight) { + return false; + } + if (star.y > window.innerHeight) return false; + return true; + }); - setStars((prev) => { - const newStars = prev.filter((star) => { - if ( - star.y > window.innerHeight - starSize && - star.y < window.innerHeight - ) { - return false; - } - if (star.y > window.innerHeight) return false; - return true; - }); + return newStars.map((star) => ({ + x: star.x - star.xChange, + y: star.y + star.yChange, + xChange: score * 0.001, + yChange: star.yChange, + })); + }); - return newStars.map((star) => ({ - x: star.x - star.xChange, - y: star.y + star.yChange, - xChange: score * 0.001, - yChange: star.yChange, - })); - }); + if (isGameOver) { + setScore(score * 0.99); + } + }, 10); - if (isGameOver) { - setScore(score * 0.99); - } - }, 10); + return () => { + clearInterval(loop); + }; + }, [isGameOver, score]); - return () => { - clearInterval(loop); - }; - }, [isGameOver, score]); + useEffect(() => { + const gameMonitor = setInterval(() => { + // Access the Runner instance (which the code stores in Runner.instance_) + const runner = (window as any).Runner?.instance_; + setIsGameOver(runner?.crashed); + if (!runner?.crashed) setScore(runner?.distanceRan); + }, 500); - useEffect(() => { - const gameMonitor = setInterval(() => { - // Access the Runner instance (which the code stores in Runner.instance_) - const runner = (window as any).Runner?.instance_; - setIsGameOver(runner?.crashed); - if (!runner?.crashed) setScore(runner?.distanceRan); - }, 500); + return () => { + clearInterval(gameMonitor); + }; + }, []); - return () => { - clearInterval(gameMonitor); - }; - }, []); - - return ( -
25000 - ? "bg-black" - : score > 10000 - ? "bg-[#0f0024]" - : "bg-slate-900" - } text-white overflow-hidden relative transition-colors duration-[5s]`} - > -
- {stars.map((star, index) => ( -
- ★ -
- ))} -
-
-
30000 && "drop-shadow-[0_0_5px_rgb(220,20,60)]" - } w-full text-center animate-floating transition-all duration-[5s]`} - > -

404

-

Page Not Found

- - -
-
-
- ); + return ( +
25000 ? "bg-black" : score > 10000 ? "bg-[#0f0024]" : "bg-slate-900" + } text-white overflow-hidden relative transition-colors duration-[5s]`} + > +
+ {stars.map((star, index) => ( +
+ ★ +
+ ))} +
+
+
30000 && "drop-shadow-[0_0_5px_rgb(220,20,60)]" + } w-full text-center animate-floating transition-all duration-[5s]`} + > +

404

+

Page Not Found

+ + +
+
+
+ ); }; /* diff --git a/frontend/src/pages/UserPage.tsx b/frontend/src/pages/UserPage.tsx index fcffa20..4bd80dc 100644 --- a/frontend/src/pages/UserPage.tsx +++ b/frontend/src/pages/UserPage.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from "react"; +import React, { useState, useEffect, useCallback, useRef } from "react"; import AuthModal from "../components/Auth/AuthModal"; import { useAuthModal } from "../hooks/useAuthModal"; import { useAuth } from "../context/AuthContext"; @@ -27,7 +27,8 @@ const UserPage: React.FC = () => { const [profileData, setProfileData] = useState(); const { isFollowing, checkFollowStatus, followUser, unfollowUser } = useFollow(); const { showAuthModal, setShowAuthModal } = useAuthModal(); - const { username: loggedInUsername } = useAuth(); + const { username: loggedInUsername, profilePicture, setProfilePicture } = useAuth(); + const initialProfilePicture = useRef(profilePicture); const { username } = useParams(); const { vods } = useVods(`/api/vods/${username}`); const navigate = useNavigate(); @@ -70,7 +71,8 @@ const UserPage: React.FC = () => { if (response.ok) { console.log("Success"); - window.location.reload(); + console.log(URL.createObjectURL(img)) + setProfilePicture(URL.createObjectURL(img)); } } catch (error) { console.log("Failure"); @@ -78,6 +80,21 @@ const UserPage: React.FC = () => { } }; + const handleNavigation = (path: string) => { + if (profilePicture === initialProfilePicture.current) { + // Variable hasn't changed - use React Router navigation + navigate(path); + } else { + // Variable has changed - use full page reload + window.location.href = path; + } + }; + + // Store initial profile picture to know if it changes later + useEffect(() => { + initialProfilePicture.current = profilePicture; + }, []); + // Check if the current user is the currently logged-in user useEffect(() => { if (username === loggedInUsername) setUserPageVariant("personal"); @@ -138,9 +155,8 @@ const UserPage: React.FC = () => { "" )} { - console.log("no error") e.currentTarget.src = "/images/pfps/default.png"; e.currentTarget.onerror = null; }} @@ -216,7 +232,7 @@ const UserPage: React.FC = () => { viewers={currentStream.viewers || 0} thumbnail={currentStream.thumbnail} onItemClick={() => { - navigate(`/${profileData.username}`); + handleNavigation(`/${profileData.username}`); }} />
@@ -253,7 +269,7 @@ const UserPage: React.FC = () => { onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")} onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} > -
@@ -273,7 +289,7 @@ const UserPage: React.FC = () => { onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")} onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} > - +