UPDATE: Dynamically change profile picture on UserPage, without requiring page reload
This commit is contained in:
@@ -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 (
|
||||
<div
|
||||
className={`h-screen w-screen ${
|
||||
score > 25000
|
||||
? "bg-black"
|
||||
: score > 10000
|
||||
? "bg-[#0f0024]"
|
||||
: "bg-slate-900"
|
||||
} text-white overflow-hidden relative transition-colors duration-[5s]`}
|
||||
>
|
||||
<div>
|
||||
{stars.map((star, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="absolute w-5 h-5 text-yellow-300"
|
||||
style={{ left: `${star.x}px`, top: `${star.y}px` }}
|
||||
>
|
||||
★
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="absolute flex justify-center items-center h-full z-0 inset-0 bg-[radial-gradient(rgba(255,255,255,0.5)_1px,transparent_1px)] bg-[length:50px_50px]">
|
||||
<div
|
||||
className={`${
|
||||
score > 30000 && "drop-shadow-[0_0_5px_rgb(220,20,60)]"
|
||||
} w-full text-center animate-floating transition-all duration-[5s]`}
|
||||
>
|
||||
<h1 className="text-6xl font-bold mb-4">404</h1>
|
||||
<p className="text-2xl mb-8">Page Not Found</p>
|
||||
<ChromeDinoGame />
|
||||
<Button
|
||||
extraClasses="z-[100]"
|
||||
onClick={() => (window.location.href = "/")}
|
||||
>
|
||||
Go Home
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={`h-screen w-screen ${
|
||||
score > 25000 ? "bg-black" : score > 10000 ? "bg-[#0f0024]" : "bg-slate-900"
|
||||
} text-white overflow-hidden relative transition-colors duration-[5s]`}
|
||||
>
|
||||
<div>
|
||||
{stars.map((star, index) => (
|
||||
<div key={index} className="absolute w-5 h-5 text-yellow-300" style={{ left: `${star.x}px`, top: `${star.y}px` }}>
|
||||
★
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="absolute flex justify-center items-center h-full z-0 inset-0 bg-[radial-gradient(rgba(255,255,255,0.5)_1px,transparent_1px)] bg-[length:50px_50px]">
|
||||
<div
|
||||
className={`${
|
||||
score > 30000 && "drop-shadow-[0_0_5px_rgb(220,20,60)]"
|
||||
} w-full text-center animate-floating transition-all duration-[5s]`}
|
||||
>
|
||||
<h1 className="text-6xl font-bold mb-4">404</h1>
|
||||
<p className="text-2xl mb-8">Page Not Found</p>
|
||||
<ChromeDinoGame />
|
||||
<Button extraClasses="z-[100]" onClick={() => (window.location.href = "/")}>
|
||||
Go Home
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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<UserProfileData>();
|
||||
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 = () => {
|
||||
""
|
||||
)}
|
||||
<img
|
||||
src={`/user/${profileData.username}/profile_picture`}
|
||||
src={userPageVariant === "personal" && profilePicture ? profilePicture : `/user/${profileData.username}/profile_picture`}
|
||||
onError={(e) => {
|
||||
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}`);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -253,7 +269,7 @@ const UserPage: React.FC = () => {
|
||||
onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")}
|
||||
>
|
||||
<button className="text-[var(--follow-text)] whitespace-pre-wrap" onClick={() => navigate(`/user/${username}/following`)}>
|
||||
<button className="text-[var(--follow-text)] whitespace-pre-wrap" onClick={() => handleNavigation(`/user/${username}/following`)}>
|
||||
Following
|
||||
</button>
|
||||
</div>
|
||||
@@ -273,7 +289,7 @@ const UserPage: React.FC = () => {
|
||||
onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")}
|
||||
>
|
||||
<button onClick={() => navigate(`/user/${username}/followedCategories`)}>Categories</button>
|
||||
<button onClick={() => handleNavigation(`/user/${username}/followedCategories`)}>Categories</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user