UPDATE/REFACTOR: Change how VODs are accessed & loaded;
FIX: `isLive` -> `streamerIsLive`; FIX: `Sidebar` profile pictures;
This commit is contained in:
@@ -151,7 +151,7 @@ const VodListItem: React.FC<VodListItemProps> = ({
|
||||
<div className="flex justify-evenly items-stretch rounded-b-lg">
|
||||
<a
|
||||
className="flex justify-around w-full h-full bg-black/50 hover:bg-black/80 p-2 mx-1 font-semibold rounded-full border border-transparent hover:border-white"
|
||||
href={`/vods/${username}/${vod_id}.mp4`}
|
||||
href={`/vod/${username}/${vod_id}.mp4`}
|
||||
download={`${username}_vod_${vod_id}.mp4`}
|
||||
>
|
||||
<DownloadIcon />
|
||||
|
||||
@@ -17,7 +17,7 @@ interface ListRowProps {
|
||||
description?: string;
|
||||
items: ItemType[];
|
||||
wrap?: boolean;
|
||||
onItemClick: (itemName: string) => void;
|
||||
onItemClick: (itemName: string, username?: string) => void;
|
||||
titleClickable?: boolean;
|
||||
extraClasses?: string;
|
||||
itemExtraClasses?: string;
|
||||
@@ -185,8 +185,8 @@ const ListRow = forwardRef<ListRowRef, ListRowProps>((props, ref) => {
|
||||
category_name={item.category_name}
|
||||
length={item.length}
|
||||
views={item.views}
|
||||
thumbnail={item.thumbnail}
|
||||
onItemClick={() => handleVodClick(item)}
|
||||
thumbnail={`/vods/${item.username}/${item.vod_id}.png`}
|
||||
onItemClick={() => onItemClick(item.username, item.vod_id.toString())}
|
||||
extraClasses={itemExtraClasses}
|
||||
variant={variant}
|
||||
/>
|
||||
|
||||
@@ -120,7 +120,7 @@ const Sidebar: React.FC<SideBarProps> = ({ extraClasses = "" }) => {
|
||||
</div>
|
||||
<div id="streamers-followed" className="flex flex-col flex-grow items-center">
|
||||
<h2 className="border-b-2 border-t-2 w-[125%] text-2xl cursor-default mb-5">Streamers</h2>
|
||||
<div className="flex flex-col flex-grow justify-evenly w-full">
|
||||
<div className="flex flex-col flex-grow justify-start w-full">
|
||||
{followedStreamers.map((streamer) => (
|
||||
<div
|
||||
key={`${sidebarId.current}-streamer-${streamer.username}`}
|
||||
@@ -131,6 +131,10 @@ const Sidebar: React.FC<SideBarProps> = ({ extraClasses = "" }) => {
|
||||
>
|
||||
<img
|
||||
src={`/user/${streamer.username}/profile_picture`}
|
||||
onError={(e) => {
|
||||
e.currentTarget.src = "/images/pfps/default.png";
|
||||
e.currentTarget.onerror = null;
|
||||
}}
|
||||
alt={`${streamer.username}'s Profile`}
|
||||
className="w-10 h-10 rounded-full object-cover"
|
||||
/>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ChatProvider } from "../../context/ChatContext";
|
||||
const StreamerRoute: React.FC = () => {
|
||||
const { streamerName } = useParams();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [isLive, setIsLive] = useState<boolean>(false);
|
||||
const [streamerIsLive, setStreamerIsLive] = useState<boolean>(false);
|
||||
const [streamId, setStreamId] = useState<number>(0);
|
||||
const navigate = useNavigate();
|
||||
|
||||
@@ -16,11 +16,11 @@ const StreamerRoute: React.FC = () => {
|
||||
try {
|
||||
const response = await fetch(`/api/user/${streamerName}/status`);
|
||||
const data = await response.json();
|
||||
setIsLive(Boolean(data.is_live));
|
||||
setStreamerIsLive(Boolean(data.is_live));
|
||||
setStreamId(data.user_id);
|
||||
} catch (error) {
|
||||
console.error("Error checking stream status:", error);
|
||||
setIsLive(false);
|
||||
setStreamerIsLive(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ const StreamerRoute: React.FC = () => {
|
||||
|
||||
if (isLoading) return <LoadingScreen />;
|
||||
|
||||
if (isLive) {
|
||||
if (streamerIsLive) {
|
||||
return (
|
||||
<ChatProvider>
|
||||
<VideoPage streamerId={streamId} />
|
||||
|
||||
@@ -10,18 +10,6 @@ interface VodsDashboardProps {
|
||||
const VodsDashboard: React.FC<VodsDashboardProps> = ({ vods }) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleVodClick = (vodId: string) => {
|
||||
if (vods.length > 0) {
|
||||
navigate(`/stream/${vods[0].username}/vods/${vodId}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure each VOD has a hardcoded thumbnail path
|
||||
const thumbnails = vods.map((vod) => ({
|
||||
...vod,
|
||||
thumbnail: `/vods/${vod.username}/${vod.vod_id}.png`,
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Past Broadcasts</h2>
|
||||
@@ -34,9 +22,9 @@ const VodsDashboard: React.FC<VodsDashboardProps> = ({ vods }) => {
|
||||
<ListRow
|
||||
type="vod"
|
||||
variant="vodDashboard"
|
||||
items={thumbnails} // Use modified VODs with hardcoded thumbnail
|
||||
items={vods}
|
||||
wrap={false}
|
||||
onItemClick={handleVodClick}
|
||||
onItemClick={(username, vodId) => navigate(`/vods/${username}/${vodId}`) }
|
||||
extraClasses="bg-black/50"
|
||||
itemExtraClasses="w-[20vw]"
|
||||
/>
|
||||
|
||||
@@ -6,7 +6,6 @@ import Button from "../components/Input/Button";
|
||||
import DynamicPageContent from "../components/Layout/DynamicPageContent";
|
||||
import LoadingScreen from "../components/Layout/LoadingScreen";
|
||||
import Footer from "../components/Layout/Footer";
|
||||
import { useAuth } from "../context/AuthContext";
|
||||
|
||||
const HomePage: React.FC = () => {
|
||||
const { streams, isLoading: isLoadingStreams } = useStreams();
|
||||
@@ -14,16 +13,8 @@ const HomePage: React.FC = () => {
|
||||
const { vods, isLoading: isLoadingVods } = useVods();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
|
||||
if (isLoadingStreams || isLoadingCategories || isLoadingVods) return <LoadingScreen>Loading Content...</LoadingScreen>;
|
||||
|
||||
const thumbnails = vods.map((vod) => ({
|
||||
...vod,
|
||||
thumbnail: `/vods/${vod.username}/${vod.vod_id}.png`,
|
||||
video: `/vods/${vod.username}/${vod.vod_id}.mp4`,
|
||||
}));
|
||||
|
||||
return (
|
||||
<DynamicPageContent navbarVariant="home" className="relative min-h-screen animate-moving_bg" contentClassName="pb-[12vh]">
|
||||
{/* Streams Section */}
|
||||
@@ -60,9 +51,9 @@ const HomePage: React.FC = () => {
|
||||
type="vod"
|
||||
title="Recent VODs"
|
||||
description="Watch the latest recorded streams!"
|
||||
items={thumbnails}
|
||||
items={vods}
|
||||
wrap={false}
|
||||
onItemClick={() => null}
|
||||
onItemClick={(username, vodId) => navigate(`/vods/${username}/${vodId}`) }
|
||||
extraClasses="bg-black/50"
|
||||
itemExtraClasses="w-[20vw]"
|
||||
/>
|
||||
|
||||
@@ -36,13 +36,6 @@ const UserPage: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { streams } = useStreams(`/api/streams/${username}/data`);
|
||||
const currentStream = streams[0];
|
||||
console.log(vods)
|
||||
|
||||
const thumbnails = vods.map((vod) => ({
|
||||
...vod,
|
||||
thumbnail: `/vods/${vod.username}/${vod.vod_id}.png`,
|
||||
}));
|
||||
|
||||
|
||||
const fetchProfileData = useCallback(async () => {
|
||||
try {
|
||||
@@ -80,7 +73,7 @@ const UserPage: React.FC = () => {
|
||||
|
||||
if (response.ok) {
|
||||
console.log("Success");
|
||||
console.log(URL.createObjectURL(img))
|
||||
console.log(URL.createObjectURL(img));
|
||||
setProfilePicture(URL.createObjectURL(img));
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -130,7 +123,7 @@ const UserPage: React.FC = () => {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setProfileData(prev => prev ? { ...prev, bio: editedBio } : undefined);
|
||||
setProfileData((prev) => (prev ? { ...prev, bio: editedBio } : undefined));
|
||||
setIsEditingBio(false);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -166,7 +159,8 @@ const UserPage: React.FC = () => {
|
||||
{/* Profile Picture */}
|
||||
<div
|
||||
className={`relative -top-[40px] sm:-top-[90px] w-[16vw] h-[16vw] sm:w-[20vw] sm:h-[20vw] max-w-[10em] max-h-[10em]
|
||||
rounded-full flex-shrink-0 border-4 ${profileData.isLive ? "border-[#ff0000]" : "border-[var(--user-pfp-border)]"
|
||||
rounded-full flex-shrink-0 border-4 ${
|
||||
profileData.isLive ? "border-[#ff0000]" : "border-[var(--user-pfp-border)]"
|
||||
} inset-0 z-20`}
|
||||
style={{ boxShadow: "var(--user-pfp-border-shadow)" }}
|
||||
>
|
||||
@@ -189,7 +183,7 @@ const UserPage: React.FC = () => {
|
||||
}}
|
||||
alt={`${profileData.username}'s profile`}
|
||||
className="sm:w-full h-full object-cover rounded-full group-hover:brightness-50 relative z-0 transition-all"
|
||||
style={{ backgroundColor: 'white' }}
|
||||
style={{ backgroundColor: "white" }}
|
||||
/>
|
||||
|
||||
{/* If current user is the profile user then allow profile picture swap */}
|
||||
@@ -283,10 +277,7 @@ const UserPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{/* Content Section */}
|
||||
<div
|
||||
id="content"
|
||||
className="col-span-2 bg-[var(--user-contentBox)] rounded-lg p-6 flex flex-col items-center w-full"
|
||||
>
|
||||
<div id="content" className="col-span-2 bg-[var(--user-contentBox)] rounded-lg p-6 flex flex-col items-center w-full">
|
||||
{/* Stream */}
|
||||
{currentStream && (
|
||||
<div className="mb-8 max-w-[500px] w-full">
|
||||
@@ -295,7 +286,7 @@ const UserPage: React.FC = () => {
|
||||
font-black mb-4 rounded-full text-center"
|
||||
>
|
||||
Currently Live!
|
||||
</h2>
|
||||
</h2>
|
||||
<StreamListItem
|
||||
id={profileData.id}
|
||||
title={currentStream.title || ""}
|
||||
@@ -312,14 +303,11 @@ const UserPage: React.FC = () => {
|
||||
{/* VODs */}
|
||||
{vods.length > 0 && (
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold mb-4"></h2>
|
||||
<ListRow
|
||||
type="vod"
|
||||
title={`Past Broadcasts (${vods.length})`}
|
||||
items={thumbnails}
|
||||
onItemClick={(vod) => {
|
||||
console.log("VOD Clicked:", vod);
|
||||
}}
|
||||
items={vods}
|
||||
onItemClick={(user, vodId) => handleNavigation(`/vods/${user}/${vodId}`)}
|
||||
extraClasses="w-fit max-w-[40vw] py-0 mt-0"
|
||||
amountForScroll={2}
|
||||
itemExtraClasses="w-[15vw]"
|
||||
@@ -342,14 +330,12 @@ 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 pointer-events-none">
|
||||
Following
|
||||
</button>
|
||||
<button className="text-[var(--follow-text)] whitespace-pre-wrap pointer-events-none">Following</button>
|
||||
</div>
|
||||
<div
|
||||
className="bg-[var(--user-follow-bg)] rounded-[1em] hover:scale-105 transition-all ease-in-out duration-300
|
||||
flex items-center justify-center w-full p-4 content-start cursor-pointer"
|
||||
onClick={() => handleNavigation(`/user/${username}/vods`)}
|
||||
onClick={() => handleNavigation(`/vods/${username}`)}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--follow-shadow)")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user