Skip to content

Commit

Permalink
splinter watch page into several components
Browse files Browse the repository at this point in the history
  • Loading branch information
sphinxrave committed Dec 29, 2024
1 parent d540af9 commit 5248323
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 86 deletions.
4 changes: 2 additions & 2 deletions packages/react/src/components/chat/LiveChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export function LiveChat({

if (needExtension)
return (
<div className="flex h-full items-center justify-center p-4">
<span className="text-center text-sm">
<div className="flex h-full w-full items-center justify-center p-4 ">
<span className="max-w-40 text-center text-sm">
{t("views.watch.chat.archiveNeedExtension", {
0: (
<Link
Expand Down
7 changes: 5 additions & 2 deletions packages/react/src/components/player/Controlbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function Controlbar({ video, url }: ControlbarProps) {
const [tlOpen, setTlOpen] = useAtom(tlOpenAtom);

return (
<div className="flex flex-col border-t-[1px] border-base">
<div className="">
<HighlightBar video={video} />
<div className="flex shrink-0 items-center gap-0 overflow-x-auto px-4 pb-2 text-base-11 @screen-lg:gap-2">
<Button
Expand All @@ -41,6 +41,9 @@ export function Controlbar({ video, url }: ControlbarProps) {
>
<div className="i-heroicons:arrow-left" />
</Button>
<div className="mx-auto">
{/* Separator - pushes everything to the right */}
</div>
<Button
title={t("views.watch.chat.showTLBtn")}
className="flex @screen-lg:hidden"
Expand Down Expand Up @@ -76,7 +79,7 @@ export function Controlbar({ video, url }: ControlbarProps) {
</Button>
)}
<Button
className="ml-auto whitespace-nowrap"
className="whitespace-nowrap"
variant="ghost"
onClick={() => setTheaterMode((v) => !v)}
>
Expand Down
223 changes: 141 additions & 82 deletions packages/react/src/routes/watch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,107 @@ import { useEffect } from "react";
import { Helmet } from "react-helmet-async";
import { useLocation, useParams } from "react-router-dom";

const TheaterModeChat = ({
currentVideo,
}: {
currentVideo: PlaceholderVideo;
}) => {
const [chatOpen] = useAtom(chatOpenAtom);
const [tlOpen] = useAtom(tlOpenAtom);

if (!currentVideo || (!chatOpen && !tlOpen)) return null;

return (
<div className="hidden min-w-[24rem] @screen-lg:flex">
<ChatCard {...currentVideo} />
</div>
);
};

const VideoContent = ({
currentVideo,
url,
chatPos,
}: {
currentVideo?: PlaceholderVideo;
url: string;
chatPos?: "left" | "right";
}) => {
const [miniPlayer] = useAtom(miniPlayerAtom);
const theaterMode = useAtomValue(theaterModeAtom);

if (miniPlayer || !currentVideo) return null;

return (
<div
className={cn("flex h-full w-full", {
"flex-row-reverse": chatPos === "left",
})}
>
<div className="grow">
<PlayerWrapper id={currentVideo?.id} url={url} />
</div>
{theaterMode && <TheaterModeChat currentVideo={currentVideo} />}
</div>
);
};

const UnderVideoInfo = ({
currentVideo,
channel,
}: {
currentVideo?: PlaceholderVideo;
channel?: Channel;
}) => {
const theaterMode = useAtomValue(theaterModeAtom);

const contentClasses = cn("flex flex-col gap-4", {
"px-4 @screen-lg:px-8 pb-8": theaterMode,
});

return (
<div className={contentClasses}>
{channel && <ChannelCard size="xs" variant="list" {...channel} />}
{currentVideo?.mentions && <Mentions mentions={currentVideo.mentions} />}
{!currentVideo?.link?.includes("twitch") && currentVideo?.description && (
<Description description={currentVideo.description} />
)}
<div className="flex @screen-lg:hidden">
<Recommendations {...currentVideo} />
</div>
</div>
);
};

const VideoAsideLists = ({
currentVideo,
}: {
currentVideo?: PlaceholderVideo;
}) => {
const [chatOpen] = useAtom(chatOpenAtom);
const [tlOpen] = useAtom(tlOpenAtom);
const theaterMode = useAtomValue(theaterModeAtom);
const queue = useAtomValue(queueAtom);

if (theaterMode) return null;

return (
<div className="hidden w-96 shrink-0 flex-col gap-4 @screen-lg:flex">
{!!queue.length && <QueueList currentId={currentVideo?.id} />}
{(currentVideo?.type === "stream" || currentVideo?.status === "live") && (
<div
className={cn("overflow-hidden", {
"h-[80vh] max-h-[80vh]": chatOpen || tlOpen,
})}
>
<ChatCard {...currentVideo} />
</div>
)}
<Recommendations {...currentVideo} />
</div>
);
};

export function Watch() {
const location = useLocation();
const { id } = useParams();
Expand All @@ -42,128 +143,86 @@ export function Watch() {
refetchOnMount: true,
staleTime: 30 * 1000,
placeholderData: () => {
if (location.state?.video && location.state?.video.channel)
return location.state?.video;
if (location.state?.video?.channel) return location.state.video;
},
},
);

const { data: channel } = useChannel(currentVideo?.channel.id ?? "", {
enabled: !!currentVideo,
placeholderData: () => {
if (location.state?.video && location.state?.video.channel)
return location.state?.video.channel;
if (location.state?.video?.channel) return location.state.video.channel;
},
});

const queue = useAtomValue(queueAtom);
const [miniPlayer, setMiniPlayer] = useAtom(miniPlayerAtom);
const theaterMode = useAtomValue(theaterModeAtom);
const [chatOpen, setChatOpen] = useAtom(chatOpenAtom);
const [tlOpen, setTLOpen] = useAtom(tlOpenAtom);
const chatPos = useAtomValue(chatPosAtom);

const smOrMd = !useIsLgAndUp();
const tlOpen = useAtomValue(tlOpenAtom);
const chatOpen = useAtomValue(chatOpenAtom);

const url = idToVideoURL(id!, currentVideo?.link);

const makeHeaderHidden = useSetAtom(headerHiddenAtom);
useEffect(() => {
// hides the holodex default header
if (theaterMode) makeHeaderHidden(true);
return () => makeHeaderHidden(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [theaterMode]);

useEffect(() => {
setMiniPlayer(false);
}, []);

const regularMode = !theaterMode;

const containerClasses = cn(
"mx-auto flex w-full gap-8",
regularMode && " max-w-screen-2xl p-4 pt-2", // padding around the container + a max width for regular mode container.
);

const playerContainerClasses = cn(
"flex w-full flex-col bg-base-3",
theaterMode && "aspect-video @screen-lg:h-dvh", // equal to screen height when theater mode
regularMode && "overflow-hidden rounded-lg",
);

const titleSectionClasses = cn("flex flex-col gap-1", {
"px-4 @screen-lg:px-8 py-4": theaterMode,
});

return (
<>
<Helmet>
<title>{currentVideo?.title}</title>
<meta name="description" content={currentVideo?.description} />
</Helmet>

<div className="flex h-full w-full @container">
<div
className={cn("mx-auto flex w-full gap-8", {
" p-4 pt-2 max-w-screen-2xl": !theaterMode,
})}
>
<div className={cn("flex w-full flex-col gap-4")}>
<div
className={cn("flex w-full flex-col bg-base-3", [
theaterMode
? "aspect-video @screen-lg:h-dvh"
: "overflow-hidden rounded-lg",
])}
>
{!miniPlayer && currentVideo && (
<div
className={cn("flex h-full w-full", {
"flex-row-reverse": chatPos === "left",
})}
>
<div className="grow">
<PlayerWrapper
id={currentVideo?.id}
url={url}
// className="h-full w-full"
// style={{ aspectRatio: theaterMode ? "" : "16 / 9" }}
/>
</div>
{theaterMode && currentVideo && (chatOpen || tlOpen) && (
<div className="hidden min-w-[24rem] @screen-lg:flex">
<ChatCard {...currentVideo} />
</div>
)}
</div>
)}
<div className={containerClasses}>
{/* Container adds padding and width constraint */}
<div className="flex w-full flex-col gap-4">
<div className={playerContainerClasses}>
<VideoContent
currentVideo={currentVideo}
url={url}
chatPos={chatPos}
/>
{currentVideo && <Controlbar video={currentVideo} url={url} />}
</div>
<div
className={cn("flex flex-col gap-1", {
"px-4 @screen-lg:px-8 py-4": theaterMode,
})}
>

<div className={titleSectionClasses}>
<h2 className="text-xl font-bold">{currentVideo?.title}</h2>
{currentVideo && <PlayerStats {...currentVideo} />}
</div>
<div
className={cn("flex flex-col gap-4", {
"px-4 @screen-lg:px-8 pb-8": theaterMode,
})}
>
{channel && <ChannelCard size="xs" variant="list" {...channel} />}
{currentVideo?.mentions && (
<Mentions mentions={currentVideo.mentions} />
)}
{!currentVideo?.link?.includes("twitch") &&
currentVideo?.description && (
<Description description={currentVideo.description} />
)}
<div className="flex @screen-lg:hidden">
<Recommendations {...currentVideo} />
</div>
</div>

<UnderVideoInfo currentVideo={currentVideo} channel={channel} />
</div>
{!theaterMode && (
<div className="hidden w-96 shrink-0 flex-col gap-4 @screen-lg:flex">
{!!queue.length && <QueueList currentId={currentVideo?.id} />}
{(currentVideo?.type === "stream" ||
currentVideo?.status === "live") && (
<div
className={cn("overflow-hidden", {
"h-[80vh] max-h-[80vh]": chatOpen || tlOpen,
})}
>
<ChatCard {...currentVideo} />
</div>
)}
<Recommendations {...currentVideo} />
</div>
)}

<VideoAsideLists currentVideo={currentVideo} />
</div>

{/* Mobile Chat Hover */}
{currentVideo && smOrMd && (
<ChatModal
tlOpen={tlOpen}
Expand Down

0 comments on commit 5248323

Please sign in to comment.