import { IconPatch } from "components/buttons/IconPatch"; import { Icons } from "components/Icon"; import { Navigation } from "components/layout/Navigation"; import { Paper } from "components/layout/Paper"; import { LoadingSeasons, Seasons } from "components/layout/Seasons"; import { SkeletonVideoPlayer, VideoPlayer } from "components/media/VideoPlayer"; import { ArrowLink } from "components/text/ArrowLink"; import { DotList } from "components/text/DotList"; import { Title } from "components/text/Title"; import { useLoading } from "hooks/useLoading"; import { usePortableMedia } from "hooks/usePortableMedia"; import { MWPortableMedia, getStream, MWMediaStream, MWMedia, convertPortableToMedia, getProviderFromId, MWMediaProvider, MWMediaType, } from "providers"; import { ReactElement, useEffect, useState } from "react"; import { useHistory } from "react-router-dom"; import { getIfBookmarkedFromPortable, useBookmarkContext, } from "state/bookmark"; import { getWatchedFromPortable, useWatchedContext } from "state/watched"; import { NotFoundChecks } from "./notfound/NotFoundChecks"; interface StyledMediaViewProps { media: MWMedia; stream: MWMediaStream; } function StyledMediaView(props: StyledMediaViewProps) { const watchedStore = useWatchedContext(); const startAtTime: number | undefined = getWatchedFromPortable( watchedStore.watched.items, props.media )?.progress; function updateProgress(e: Event) { if (!props.media) return; const el: HTMLVideoElement = e.currentTarget as HTMLVideoElement; if (el.currentTime <= 30) { return; // Don't update stored progress if less than 30s into the video } watchedStore.updateProgress(props.media, el.currentTime, el.duration); } return ( updateProgress(e)} startAt={startAtTime} /> ); } interface StyledMediaFooterProps { media: MWMedia; provider: MWMediaProvider; } function StyledMediaFooter(props: StyledMediaFooterProps) { const { setItemBookmark, getFilteredBookmarks } = useBookmarkContext(); const isBookmarked = getIfBookmarkedFromPortable( getFilteredBookmarks(), props.media ); return (
{props.media.title}
setItemBookmark(props.media, !isBookmarked)} clickable />
{props.media.mediaType !== MWMediaType.MOVIE ? ( ) : null}
); } function LoadingMediaFooter(props: { error?: boolean }) { return (
{props.error ? (

Your url may be invalid

) : ( )}
); } function MediaViewContent(props: { portable: MWPortableMedia }) { const mediaPortable = props.portable; const [streamUrl, setStreamUrl] = useState(); const [media, setMedia] = useState(); const [fetchMedia, loadingPortable, errorPortable] = useLoading( (portable: MWPortableMedia) => convertPortableToMedia(portable) ); const [fetchStream, loadingStream, errorStream] = useLoading( (portable: MWPortableMedia) => getStream(portable) ); useEffect(() => { (async () => { if (mediaPortable) { setMedia(await fetchMedia(mediaPortable)); } })(); }, [mediaPortable, setMedia, fetchMedia]); useEffect(() => { (async () => { if (mediaPortable) { setStreamUrl(await fetchStream(mediaPortable)); } })(); }, [mediaPortable, setStreamUrl, fetchStream]); let playerContent: ReactElement | null = null; if (loadingStream) playerContent = ; else if (errorStream) playerContent = ; else if (media && streamUrl) playerContent = ; let footerContent: ReactElement | null = null; if (loadingPortable) footerContent = ; else if (errorPortable) footerContent = ; else if (mediaPortable && media) footerContent = ( ); return ( <> {playerContent} {footerContent} ); } export function MediaView() { const mediaPortable: MWPortableMedia | undefined = usePortableMedia(); const reactHistory = useHistory(); return (
reactHistory.action !== "POP" ? reactHistory.goBack() : reactHistory.push("/") } direction="left" linkText="Go back" />
); }