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:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user