Merge pull request #127 from destruc7i0n/v3

Show more episode info in the page title for a series
This commit is contained in:
mrjvs 2023-01-24 15:04:25 +01:00 committed by GitHub
commit 0ca751f1d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 21 deletions

View File

@ -14,6 +14,7 @@ import { ShowTitleControl } from "./controls/ShowTitleControl";
import { SkipTime } from "./controls/SkipTime"; import { SkipTime } from "./controls/SkipTime";
import { TimeControl } from "./controls/TimeControl"; import { TimeControl } from "./controls/TimeControl";
import { VolumeControl } from "./controls/VolumeControl"; import { VolumeControl } from "./controls/VolumeControl";
import { PageTitleControl } from "./controls/PageTitleControl";
import { VideoPlayerError } from "./parts/VideoPlayerError"; import { VideoPlayerError } from "./parts/VideoPlayerError";
import { VideoPlayerHeader } from "./parts/VideoPlayerHeader"; import { VideoPlayerHeader } from "./parts/VideoPlayerHeader";
import { useVideoPlayerState } from "./VideoContext"; import { useVideoPlayerState } from "./VideoContext";
@ -67,6 +68,7 @@ export function DecoratedVideoPlayer(
return ( return (
<VideoPlayer autoPlay={props.autoPlay}> <VideoPlayer autoPlay={props.autoPlay}>
<PageTitleControl media={props.media} />
<VideoPlayerError media={props.media} onGoBack={props.onGoBack}> <VideoPlayerError media={props.media} onGoBack={props.onGoBack}>
<BackdropControl onBackdropChange={onBackdropChange}> <BackdropControl onBackdropChange={onBackdropChange}>
<div className="absolute inset-0 flex items-center justify-center"> <div className="absolute inset-0 flex items-center justify-center">

View File

@ -0,0 +1,23 @@
import { MWMediaMeta } from "@/backend/metadata/types";
import { Helmet } from "react-helmet";
import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo";
interface PageTitleControlProps {
media?: MWMediaMeta;
}
export function PageTitleControl(props: PageTitleControlProps) {
const { isSeries, humanizedEpisodeId } = useCurrentSeriesEpisodeInfo();
if (!props.media) return null;
const title = isSeries
? `${props.media.title} - ${humanizedEpisodeId}`
: props.media.title;
return (
<Helmet>
<title>{title}</title>
</Helmet>
);
}

View File

@ -1,29 +1,14 @@
import { useMemo } from "react"; import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo";
import { useVideoPlayerState } from "../VideoContext";
export function ShowTitleControl() { export function ShowTitleControl() {
const { videoState } = useVideoPlayerState(); const { isSeries, currentEpisodeInfo, humanizedEpisodeId } =
useCurrentSeriesEpisodeInfo();
const { current, seasons } = videoState.seasonData; if (!isSeries) return null;
const currentSeasonInfo = useMemo(() => {
return seasons?.find((season) => season.id === current?.seasonId);
}, [seasons, current]);
const currentEpisodeInfo = useMemo(() => {
return currentSeasonInfo?.episodes?.find(
(episode) => episode.id === current?.episodeId
);
}, [currentSeasonInfo, current]);
if (!videoState.seasonData.isSeries) return null;
if (!videoState.seasonData.current) return null;
const selectedText = `S${currentSeasonInfo?.number} E${currentEpisodeInfo?.number}`;
return ( return (
<p className="ml-8 select-none space-x-2 text-white"> <p className="ml-8 select-none space-x-2 text-white">
<span>{selectedText}</span> <span>{humanizedEpisodeId}</span>
<span className="opacity-50">{currentEpisodeInfo?.title}</span> <span className="opacity-50">{currentEpisodeInfo?.title}</span>
</p> </p>
); );

View File

@ -0,0 +1,33 @@
import { useMemo } from "react";
import { useVideoPlayerState } from "../VideoContext";
export function useCurrentSeriesEpisodeInfo() {
const { videoState } = useVideoPlayerState();
const { current, seasons } = videoState.seasonData;
const currentSeasonInfo = useMemo(() => {
return seasons?.find((season) => season.id === current?.seasonId);
}, [seasons, current]);
const currentEpisodeInfo = useMemo(() => {
return currentSeasonInfo?.episodes?.find(
(episode) => episode.id === current?.episodeId
);
}, [currentSeasonInfo, current]);
const isSeries = Boolean(
videoState.seasonData.isSeries && videoState.seasonData.current
);
if (!isSeries) return { isSeries: false };
const humanizedEpisodeId = `S${currentSeasonInfo?.number} E${currentEpisodeInfo?.number}`;
return {
isSeries: true,
humanizedEpisodeId,
currentSeasonInfo,
currentEpisodeInfo,
};
}

View File

@ -111,7 +111,6 @@ export function MediaViewPlayer(props: MediaViewPlayerProps) {
return ( return (
<div className="fixed top-0 left-0 h-[100dvh] w-screen"> <div className="fixed top-0 left-0 h-[100dvh] w-screen">
<Helmet> <Helmet>
<title>{props.meta.meta.title}</title>
<html data-full="true" /> <html data-full="true" />
</Helmet> </Helmet>
<DecoratedVideoPlayer media={props.meta.meta} onGoBack={goBack} autoPlay> <DecoratedVideoPlayer media={props.meta.meta} onGoBack={goBack} autoPlay>