This commit is contained in:
EvanLin3141
2025-02-27 15:50:02 +00:00
7 changed files with 64 additions and 58 deletions

View File

@@ -30,7 +30,7 @@ const DynamicPageContent: React.FC<DynamicPageContentProps> = ({
id="content" id="content"
className={`min-w-[850px] ${ className={`min-w-[850px] ${
showSideBar ? "w-[85vw] translate-x-[15vw]" : "w-[100vw]" showSideBar ? "w-[85vw] translate-x-[15vw]" : "w-[100vw]"
} items-start pb-[12vh] transition-all duration-[500ms] ease-in-out ${contentClassName}`} } items-start transition-all duration-[500ms] ease-in-out ${contentClassName}`}
> >
{children} {children}
</div> </div>

View File

@@ -25,6 +25,7 @@ const Navbar: React.FC<NavbarProps> = ({ variant = "default" }) => {
const { showAuthModal, setShowAuthModal } = useAuthModal(); const { showAuthModal, setShowAuthModal } = useAuthModal();
const { showSideBar } = useSidebar(); const { showSideBar } = useSidebar();
const { showQuickSettings, setShowQuickSettings } = useQuickSettings(); const { showQuickSettings, setShowQuickSettings } = useQuickSettings();
const [justToggled, setJustToggled] = React.useState(false);
const handleLogout = () => { const handleLogout = () => {
console.log("Logging out..."); console.log("Logging out...");
@@ -38,6 +39,8 @@ const Navbar: React.FC<NavbarProps> = ({ variant = "default" }) => {
const handleQuickSettings = () => { const handleQuickSettings = () => {
setShowQuickSettings(!showQuickSettings); setShowQuickSettings(!showQuickSettings);
setJustToggled(true);
setTimeout(() => setJustToggled(false), 750);
}; };
// Keyboard shortcut to toggle sidebar // Keyboard shortcut to toggle sidebar
@@ -65,43 +68,43 @@ const Navbar: React.FC<NavbarProps> = ({ variant = "default" }) => {
> >
{isLoggedIn && window.innerWidth > 900 && <Sidebar />} {isLoggedIn && window.innerWidth > 900 && <Sidebar />}
<Logo variant={variant} /> <Logo variant={variant} />
{/* Login / Logout Button */} {/* Login / Logout Button */}
<Button <Button
extraClasses={`absolute top-[2vh] ${ extraClasses={`absolute top-[2vh] ${
showSideBar showSideBar
? "left-[16vw] duration-[0.5s]" ? "left-[16vw] duration-[0.5s]"
: "left-[20px] duration-[1s]" : "left-[20px] duration-[1s]"
} text-[1rem] flex items-center flex-nowrap z-[99]`} } text-[1rem] flex items-center flex-nowrap z-[99]`}
onClick={() => (isLoggedIn ? handleLogout() : setShowAuthModal(true))} onClick={() => (isLoggedIn ? handleLogout() : setShowAuthModal(true))}
> >
{isLoggedIn ? ( {isLoggedIn ? (
<> <>
<LogOutIcon className="h-15 w-15 mr-1" /> <LogOutIcon className="h-15 w-15 mr-1" />
Logout Logout
</> </>
) : ( ) : (
<> <>
<LogInIcon className="h-15 w-15 mr-1" /> <LogInIcon className="h-15 w-15 mr-1" />
Login / Register Login / Register
</> </>
)} )}
</Button> </Button>
{/* Quick Settings Sidebar */} {/* Quick Settings Sidebar */}
<ToggleButton <ToggleButton
extraClasses={`absolute group text-[1rem] top-[2vh] ${ extraClasses={`absolute group text-[1rem] top-[2vh] ${
showQuickSettings ? "right-[21vw]" : "right-[20px]" showQuickSettings ? "right-[21vw]" : "right-[20px]"
} cursor-pointer`} } cursor-pointer`}
onClick={() => handleQuickSettings()} onClick={() => handleQuickSettings()}
toggled={showQuickSettings} toggled={showQuickSettings}
> >
<SettingsIcon className="h-[2vw] w-[2vw]" /> <SettingsIcon className="h-[2vw] w-[2vw]" />
{showQuickSettings && ( {!showQuickSettings && !justToggled && (
<small className="absolute flex items-center top-0 mr-4 right-0 h-full w-full my-auto group-hover:right-full opacity-0 group-hover:opacity-100 text-white transition-all delay-200"> <small className="absolute flex items-center top-0 mr-4 right-0 h-full w-full my-auto group-hover:right-full opacity-0 group-hover:opacity-100 text-white transition-all delay-200">
Press Q Press Q
</small> </small>
)} )}
</ToggleButton> </ToggleButton>
<QuickSettings /> <QuickSettings />
{variant != "no-searchbar" && <SearchBar />} {variant != "no-searchbar" && <SearchBar />}

View File

@@ -25,6 +25,7 @@ const Sidebar: React.FC<SideBarProps> = ({ extraClasses = "" }) => {
const { username, isLoggedIn } = useAuth(); const { username, isLoggedIn } = useAuth();
const [followedStreamers, setFollowedStreamers] = useState<Streamer[]>([]); const [followedStreamers, setFollowedStreamers] = useState<Streamer[]>([]);
const [followedCategories, setFollowedCategories] = useState<Category[]>([]); const [followedCategories, setFollowedCategories] = useState<Category[]>([]);
const [justToggled, setJustToggled] = useState(false);
// Fetch followed streamers // Fetch followed streamers
useEffect(() => { useEffect(() => {
@@ -46,6 +47,8 @@ const Sidebar: React.FC<SideBarProps> = ({ extraClasses = "" }) => {
const handleSideBar = () => { const handleSideBar = () => {
setShowSideBar(!showSideBar); setShowSideBar(!showSideBar);
setJustToggled(true);
setTimeout(() => setJustToggled(false), 750);
}; };
// Keyboard shortcut to toggle sidebar // Keyboard shortcut to toggle sidebar
@@ -98,7 +101,7 @@ const Sidebar: React.FC<SideBarProps> = ({ extraClasses = "" }) => {
> >
<SidebarIcon className="h-[2vw] w-[2vw]" /> <SidebarIcon className="h-[2vw] w-[2vw]" />
{showSideBar && ( {!showSideBar && !justToggled && (
<small className="absolute flex items-center top-0 ml-4 left-0 h-full w-full my-auto group-hover:left-full opacity-0 group-hover:opacity-100 text-white transition-all delay-200"> <small className="absolute flex items-center top-0 ml-4 left-0 h-full w-full my-auto group-hover:left-full opacity-0 group-hover:opacity-100 text-white transition-all delay-200">
Press S Press S
</small> </small>

View File

@@ -30,6 +30,7 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
const [messages, setMessages] = useState<ChatMessage[]>([]); const [messages, setMessages] = useState<ChatMessage[]>([]);
const [inputMessage, setInputMessage] = useState(""); const [inputMessage, setInputMessage] = useState("");
const chatContainerRef = useRef<HTMLDivElement>(null); const chatContainerRef = useRef<HTMLDivElement>(null);
const [justToggled, setJustToggled] = useState(false);
// Join chat room when component mounts // Join chat room when component mounts
useEffect(() => { useEffect(() => {
@@ -114,6 +115,8 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
const toggleChat = () => { const toggleChat = () => {
setShowChat(!showChat); setShowChat(!showChat);
setJustToggled(true);
setTimeout(() => setJustToggled(false), 750);
}; };
const sendChat = () => { const sendChat = () => {
@@ -147,11 +150,11 @@ const ChatPanel: React.FC<ChatPanelProps> = ({
{/* Toggle Button for Chat */} {/* Toggle Button for Chat */}
<button <button
onClick={toggleChat} onClick={toggleChat}
className={`group cursor-pointer p-2 hover:bg-gray-800 rounded-md absolute top-[1vh] left-[1vw] ${showChat ? "" : "delay-[0.75s] -translate-x-[3.3vw]"} text-[1rem] text-purple-500 flex items-center flex-nowrap z-[50] duration-[0.3s] transition-all`} className={`group cursor-pointer p-2 hover:bg-gray-800 rounded-md absolute top-[1vh] left-[1vw] ${showChat ? "" : "delay-[0.75s] -translate-x-[4vw]"} text-[1rem] text-purple-500 flex items-center flex-nowrap z-[20] duration-[0.3s] transition-all`}
> >
{showChat ? <ArrowRightFromLineIcon /> : <ArrowLeftFromLineIcon />} {showChat ? <ArrowRightFromLineIcon /> : <ArrowLeftFromLineIcon />}
<small className={`absolute ${showChat ? "right-0 group-hover:-right-[4vw]" : "left-0 group-hover:-left-[4vw]"} p-1 rounded-md group-hover:bg-white/10 w-fit opacity-0 group-hover:opacity-100 text-white transition-all`}> <small className={`absolute ${showChat ? justToggled ? "left-0 group-hover:-left-[4vw] group-hover:bg-white/10" : "right-0 group-hover:-right-[5vw] group-hover:bg-red-500/80" : justToggled ? "right-0 group-hover:-right-[5vw] group-hover:bg-red-500/80" : "left-0 group-hover:-left-[4vw] group-hover:bg-white/10"} p-1 rounded-md w-fit opacity-0 group-hover:opacity-100 text-white transition-all`}>
Press C Press C
</small> </small>
</button> </button>

View File

@@ -87,7 +87,7 @@ const AllCategoriesPage: React.FC = () => {
type="category" type="category"
title="All Categories" title="All Categories"
items={categories} items={categories}
onClick={handleCategoryClick} onItemClick={handleCategoryClick}
extraClasses="bg-[var(--recommend)] text-center" extraClasses="bg-[var(--recommend)] text-center"
itemExtraClasses="w-[20vw]" itemExtraClasses="w-[20vw]"
wrap={true} wrap={true}

View File

@@ -10,6 +10,7 @@ import { SocketProvider } from "../context/SocketContext";
import { useAuthModal } from "../hooks/useAuthModal"; import { useAuthModal } from "../hooks/useAuthModal";
import { useFollow } from "../hooks/useFollow"; import { useFollow } from "../hooks/useFollow";
import { useChat } from "../context/ChatContext"; import { useChat } from "../context/ChatContext";
import { StreamType } from "../types/StreamType";
// Lazy load the CheckoutForm component // Lazy load the CheckoutForm component
const CheckoutForm = lazy(() => import("../components/Checkout/CheckoutForm")); const CheckoutForm = lazy(() => import("../components/Checkout/CheckoutForm"));
@@ -18,17 +19,10 @@ interface VideoPageProps {
streamerId: number; streamerId: number;
} }
interface StreamDataProps {
streamTitle: string;
streamerName: string;
startTime: string;
categoryName: string;
}
const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => { const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
const { isLoggedIn } = useAuth(); const { isLoggedIn } = useAuth();
const { streamerName } = useParams<{ streamerName: string }>(); const { streamerName } = useParams<{ streamerName: string }>();
const [streamData, setStreamData] = useState<StreamDataProps>(); const [streamData, setStreamData] = useState<StreamType>();
const [viewerCount, setViewerCount] = useState(0); const [viewerCount, setViewerCount] = useState(0);
const { showSideBar } = useSidebar(); const { showSideBar } = useSidebar();
const { isFollowing, checkFollowStatus, followUser, unfollowUser } = const { isFollowing, checkFollowStatus, followUser, unfollowUser } =
@@ -66,11 +60,14 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
res res
.json() .json()
.then((data) => { .then((data) => {
const transformedData: StreamDataProps = { const transformedData: StreamType = {
streamerName: data.username, type: "stream",
streamTitle: data.title, id: data.stream_id,
username: data.username,
title: data.title,
startTime: data.start_time, startTime: data.start_time,
categoryName: data.category_name, streamCategory: data.category_name,
viewers: data.viewers,
}; };
setStreamData(transformedData); setStreamData(transformedData);
@@ -134,7 +131,6 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
fetch(`/api/user/subscription/${streamerName}/expiration`) fetch(`/api/user/subscription/${streamerName}/expiration`)
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
console.log(streamData?.streamerName, data.remaining_time);
if (data.remaining_time > 0) { if (data.remaining_time > 0) {
setIsSubscribed(true); setIsSubscribed(true);
} }
@@ -183,17 +179,17 @@ const VideoPage: React.FC<VideoPageProps> = ({ streamerId }) => {
className="text-white font-bold hover:underline mt-[0.5em]" className="text-white font-bold hover:underline mt-[0.5em]"
onClick={() => navigate(`/user/${streamerName}`)} onClick={() => navigate(`/user/${streamerName}`)}
> >
{streamData ? streamData.streamerName : "Loading..."} {streamerName}
</button> </button>
</div> </div>
{/* Stream Title */} {/* Stream Title */}
<div className="flex flex-col items-start flex-grow"> <div className="flex flex-col items-start flex-grow">
<h2 className="text-[0.75em] lg:text-[0.85em] xl:text-[1em] font-bold"> <h2 className="text-[0.75em] lg:text-[0.85em] xl:text-[1em] font-bold">
{streamData ? streamData.streamTitle : "Loading..."} {streamData ? streamData.title : "Loading..."}
</h2> </h2>
<span className="text-[0.75em] lg:text-[0.85em] xl:text-[1em] text-gray-400"> <span className="text-[0.75em] lg:text-[0.85em] xl:text-[1em] text-gray-400">
{streamData ? streamData.categoryName : "Loading..."} {streamData ? streamData.streamCategory : "Loading..."}
</span> </span>
</div> </div>

View File

@@ -5,5 +5,6 @@ export interface StreamType {
username: string; username: string;
streamCategory: string; streamCategory: string;
viewers: number; viewers: number;
startTime?: string;
thumbnail?: string; thumbnail?: string;
} }