FEAT: Sidebar update to include followed streamers & categories;

FEAT: Sidebar now alters page width on open/close (DynamicPageContent);
FIX: Properly disallow shortcut keys when typing in an input field;
This commit is contained in:
Chris-1010
2025-02-18 00:47:24 +00:00
parent 902c745065
commit fde7c70b54
14 changed files with 311 additions and 172 deletions

View File

@@ -1,8 +1,8 @@
import React, { useEffect } from "react";
import Navbar from "../components/Navigation/Navbar";
import { useNavigate } from "react-router-dom";
import ListRow from "../components/Layout/ListRow";
import { useCategories } from "../context/ContentContext";
import DynamicPageContent from "../components/Layout/DynamicPageContent";
const AllCategoriesPage: React.FC = () => {
const { categories, setCategories } = useCategories();
@@ -51,11 +51,10 @@ const AllCategoriesPage: React.FC = () => {
};
return (
<div
<DynamicPageContent
className="min-h-screen bg-gradient-radial from-[#ff00f1] via-[#0400ff] to-[#ff0000]"
style={{ backgroundImage: "url(/images/background-pattern.svg)" }}
>
<Navbar />
<ListRow
type="category"
title="All Categories"
@@ -64,7 +63,7 @@ const AllCategoriesPage: React.FC = () => {
extraClasses="text-center"
wrap={true}
/>
</div>
</DynamicPageContent>
);
};

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import Navbar from "../components/Navigation/Navbar";
import ListRow from "../components/Layout/ListRow";
import { useNavigate } from "react-router-dom";
import DynamicPageContent from "../components/Layout/DynamicPageContent";
interface StreamData {
type: "stream";
@@ -66,12 +66,10 @@ const CategoryPage: React.FC = () => {
}
return (
<div
<DynamicPageContent
className="min-h-screen bg-gradient-radial from-[#ff00f1] via-[#0400ff] to-[#ff0000]"
style={{ backgroundImage: "url(/images/background-pattern.svg)" }}
>
<Navbar />
<div className="pt-8">
<ListRow
type="stream"
@@ -89,7 +87,7 @@ const CategoryPage: React.FC = () => {
No live streams found in this category
</div>
)}
</div>
</DynamicPageContent>
);
};

View File

@@ -1,9 +1,9 @@
import React from "react";
import Navbar from "../components/Navigation/Navbar";
import ListRow from "../components/Layout/ListRow";
import { useNavigate } from "react-router-dom";
import { useStreams, useCategories } from "../context/ContentContext";
import Button from "../components/Input/Button";
import DynamicPageContent from "../components/Layout/DynamicPageContent";
interface HomePageProps {
variant?: "default" | "personalised";
@@ -23,13 +23,11 @@ const HomePage: React.FC<HomePageProps> = ({ variant = "default" }) => {
};
return (
<div
id="home-page"
className="animate-moving_bg h-full"
<DynamicPageContent
navbarVariant="home"
className="h-full min-h-screen animate-moving_bg"
style={{ backgroundImage: "url(/images/background-pattern.svg)" }}
>
<Navbar variant="home" />
{/* If Personalised_HomePage, display Streams recommended for the logged-in user. Else, live streams with the most viewers. */}
<ListRow
type="stream"
@@ -77,7 +75,7 @@ const HomePage: React.FC<HomePageProps> = ({ variant = "default" }) => {
Show More . . .
</Button>
</ListRow>
</div>
</DynamicPageContent>
);
};

View File

@@ -8,6 +8,7 @@ import ListItem from "../components/Layout/ListItem";
import { useFollow } from "../hooks/useFollow";
import { useNavigate } from "react-router-dom";
import Button from "../components/Input/Button";
import DynamicPageContent from "../components/Layout/DynamicPageContent";
interface UserProfileData {
id: number;
@@ -108,14 +109,14 @@ const UserPage: React.FC = () => {
);
}
return (
<div
<DynamicPageContent
className={`min-h-screen ${
profileData.isLive
? "bg-gradient-radial from-[#ff00f1] via-[#0400ff] to-[#2efd2d]"
: bgColors[userPageVariant]
} text-white flex flex-col`}
>
<Navbar />
<div className="flex justify-evenly justify-self-center items-center h-full px-4 py-8">
<div className="grid grid-cols-3 w-full gap-8">
{/* Profile Section - Left Third */}
@@ -241,7 +242,7 @@ const UserPage: React.FC = () => {
</div>
</div>
{showAuthModal && <AuthModal onClose={() => setShowAuthModal(false)} />}
</div>
</DynamicPageContent>
);
};

View File

@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import Navbar from "../components/Navigation/Navbar";
import { ToggleButton } from "../components/Input/Button";
import ChatPanel from "../components/Video/ChatPanel";
import { useNavigate, useParams } from "react-router-dom";
@@ -10,6 +9,8 @@ import VideoPlayer from "../components/Video/VideoPlayer";
import { SocketProvider } from "../context/SocketContext";
import AuthModal from "../components/Auth/AuthModal";
import CheckoutForm, { Return } from "../components/Checkout/CheckoutForm";
import DynamicPageContent from "../components/Layout/DynamicPageContent";
import { useSidebar } from "../context/SidebarContext";
interface VideoPageProps {
streamerId: number;
@@ -28,7 +29,7 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
const [streamData, setStreamData] = useState<StreamDataProps>();
const [viewerCount, setViewerCount] = useState(0);
const [isChatOpen, setIsChatOpen] = useState(true);
const [isInputFocused, setIsInputFocused] = useState(false);
const { showSideBar } = useSidebar();
const { isFollowing, checkFollowStatus, followUser, unfollowUser } =
useFollow();
const { showAuthModal, setShowAuthModal } = useAuthModal();
@@ -80,7 +81,7 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
// Keyboard shortcut to toggle chat
useEffect(() => {
const handleKeyPress = (e: KeyboardEvent) => {
if (e.key === "c" && !isInputFocused) {
if (e.key === "c" && document.activeElement == document.body) {
setIsChatOpen((prev) => !prev);
}
};
@@ -90,7 +91,7 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
return () => {
document.removeEventListener("keydown", handleKeyPress);
};
}, [isInputFocused]);
}, []);
const toggleChat = () => {
setIsChatOpen((prev) => !prev);
@@ -111,34 +112,39 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
return (
<SocketProvider>
<div id="videoPage" className="w-full">
<Navbar />
{/* Toggle Button for Chat */}
<ToggleButton
onClick={toggleChat}
toggled={isChatOpen}
extraClasses="group cursor-pointer absolute top-[70px] right-[20px] text-[1rem] flex items-center flex-nowrap"
>
{isChatOpen ? "Hide Chat" : "Show Chat"}
<small className="absolute right-0 left-0 -bottom-0 group-hover:-bottom-5 opacity-0 group-hover:opacity-100 text-white transition-all">
Press C
</small>
</ToggleButton>
<DynamicPageContent className="w-full min-h-screen">
<div
id="container"
className={`grid ${isChatOpen ? "w-[100vw]" : "w-[125vw]"
} grid-rows-[auto_1fr] bg-gray-900 h-full grid-cols-[auto_25vw] transition-all`}
className={`bg-gray-900 h-full grid ${
isChatOpen
? showSideBar
? "w-[85vw] duration-[1s]"
: "w-[100vw] duration-[0.5s]"
: showSideBar
? "w-[110vw] duration-[1s]"
: "w-[125vw] duration-[0.5s]"
} grid-rows-[auto_1fr] grid-cols-[auto_25vw] transition-all ease-in-out`}
>
<div className="relative">
<VideoPlayer />
</div>
<ToggleButton
onClick={toggleChat}
toggled={isChatOpen}
extraClasses="group cursor-pointer absolute top-[70px] right-[20px] text-[1rem] flex items-center flex-nowrap"
>
{isChatOpen ? "Hide Chat" : "Show Chat"}
<small className="absolute right-0 left-0 -bottom-0 group-hover:-bottom-5 opacity-0 group-hover:opacity-100 text-white transition-all">
Press C
</small>
</ToggleButton>
<ChatPanel
streamId={streamerId}
onViewerCountChange={(count: number) => setViewerCount(count)}
onInputFocus={setIsInputFocused}
/>
{/* Stream Data */}
@@ -244,7 +250,7 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
<AuthModal onClose={() => setShowAuthModal(false)} />
)}
</div>
</div>
</DynamicPageContent>
</SocketProvider>
);
};