2021-08-06 15:39:54 +02:00
|
|
|
import React, { useCallback } from 'react'
|
2021-08-02 15:08:55 +02:00
|
|
|
import { useRouteMatch, useHistory } from 'react-router-dom'
|
2021-08-02 15:15:24 +02:00
|
|
|
import { Helmet } from 'react-helmet';
|
2021-07-14 00:31:37 +02:00
|
|
|
import { Title } from '../components/Title'
|
|
|
|
import { Card } from '../components/Card'
|
|
|
|
import { useMovie } from '../hooks/useMovie'
|
|
|
|
import { VideoElement } from '../components/VideoElement'
|
2021-07-15 00:09:42 +02:00
|
|
|
import { EpisodeSelector } from '../components/EpisodeSelector'
|
2021-07-20 12:20:56 +02:00
|
|
|
import { getStreamUrl } from '../lib/index'
|
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
import './Movie.css'
|
2021-07-14 00:31:37 +02:00
|
|
|
|
|
|
|
export function MovieView(props) {
|
2021-08-02 15:08:55 +02:00
|
|
|
const baseRouteMatch = useRouteMatch('/:type/:source/:title/:slug');
|
|
|
|
const showRouteMatch = useRouteMatch('/:type/:source/:title/:slug/season/:season/episode/:episode');
|
|
|
|
const history = useHistory();
|
2021-08-06 15:39:54 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
const { streamUrl, streamData, setStreamUrl } = useMovie();
|
2021-08-06 15:39:54 +02:00
|
|
|
const [ seasonList, setSeasonList ] = React.useState([]);
|
|
|
|
const [ episodeLists, setEpisodeList ] = React.useState([]);
|
|
|
|
const [ loading, setLoading ] = React.useState(false);
|
2021-08-02 15:08:55 +02:00
|
|
|
const [ selectedSeason, setSelectedSeason ] = React.useState("1");
|
|
|
|
|
|
|
|
const season = showRouteMatch?.params.season || "1";
|
|
|
|
const episode = showRouteMatch?.params.episode || "1";
|
2021-07-15 00:09:42 +02:00
|
|
|
|
2021-08-06 15:39:54 +02:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
function setEpisode({ season, episode }) {
|
2021-08-06 17:54:09 +02:00
|
|
|
history.replace(`${baseRouteMatch.url}/season/${season}/episode/${episode}`);
|
2021-08-06 15:39:54 +02:00
|
|
|
}
|
|
|
|
|
2021-08-02 15:08:55 +02:00
|
|
|
React.useEffect(() => {
|
|
|
|
if (streamData.type === "show" && !showRouteMatch) history.replace(`${baseRouteMatch.url}/season/1/episode/1`);
|
|
|
|
}, [streamData, showRouteMatch, history, baseRouteMatch.url]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (streamData.type === "show" && showRouteMatch) setSelectedSeason(showRouteMatch.params.season.toString());
|
2021-08-06 15:39:54 +02:00
|
|
|
}, [showRouteMatch, streamData]);
|
2021-08-02 15:08:55 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
React.useEffect(() => {
|
|
|
|
let cancel = false;
|
2021-08-06 17:54:09 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
if (streamData.type !== "show") return () => {
|
|
|
|
cancel = true;
|
|
|
|
};
|
2021-08-06 17:54:09 +02:00
|
|
|
|
2021-08-02 15:08:55 +02:00
|
|
|
if (!episode) {
|
2021-07-15 00:09:42 +02:00
|
|
|
setLoading(false);
|
|
|
|
setStreamUrl('');
|
|
|
|
return;
|
|
|
|
}
|
2021-08-06 17:54:09 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
setLoading(true);
|
|
|
|
|
2021-08-02 15:08:55 +02:00
|
|
|
getStreamUrl(streamData.slug, streamData.type, streamData.source, season, episode)
|
2021-07-15 00:09:42 +02:00
|
|
|
.then(({url}) => {
|
|
|
|
if (cancel) return;
|
|
|
|
setStreamUrl(url)
|
|
|
|
setLoading(false);
|
|
|
|
})
|
2021-08-06 17:54:09 +02:00
|
|
|
.catch((e) => {
|
2021-07-15 00:09:42 +02:00
|
|
|
if (cancel) return;
|
|
|
|
console.error(e)
|
|
|
|
})
|
2021-08-06 15:39:54 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
return () => {
|
|
|
|
cancel = true;
|
2021-07-15 21:04:47 +02:00
|
|
|
}
|
2021-08-02 15:08:55 +02:00
|
|
|
}, [episode, streamData, setStreamUrl, season]);
|
|
|
|
|
2021-08-06 15:39:54 +02:00
|
|
|
React.useEffect(() => {
|
|
|
|
// Cache streamData continue watching on home page
|
|
|
|
let movieCache = JSON.parse(localStorage.getItem("movie-cache") || "{}");
|
|
|
|
|
|
|
|
if(!movieCache[streamData.source]) movieCache[streamData.source] = {}
|
|
|
|
movieCache[streamData.source][streamData.slug] = {
|
|
|
|
cachedAt: Date.now()
|
|
|
|
}
|
|
|
|
|
|
|
|
localStorage.setItem("movie-cache", JSON.stringify(movieCache));
|
2021-08-06 17:54:09 +02:00
|
|
|
}, [streamData])
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
2021-08-06 15:39:54 +02:00
|
|
|
if (streamData.type === "show") {
|
|
|
|
setSeasonList(streamData.seasons);
|
2021-08-06 17:54:09 +02:00
|
|
|
setSelectedSeason(selectedSeason)
|
|
|
|
setEpisodeList(streamData.episodes[selectedSeason]);
|
2021-08-06 15:39:54 +02:00
|
|
|
}
|
2021-08-06 17:54:09 +02:00
|
|
|
}, [streamData, selectedSeason])
|
2021-07-14 00:31:37 +02:00
|
|
|
|
2021-07-15 20:34:25 +02:00
|
|
|
const setProgress = (evt) => {
|
|
|
|
let ls = JSON.parse(localStorage.getItem("video-progress") || "{}")
|
|
|
|
|
2021-08-06 17:54:09 +02:00
|
|
|
if (!ls[streamData.source])
|
|
|
|
ls[streamData.source] = {}
|
|
|
|
if (!ls[streamData.source][streamData.type])
|
|
|
|
ls[streamData.source][streamData.type] = {}
|
|
|
|
if (!ls[streamData.source][streamData.type][streamData.slug])
|
2021-07-21 12:29:18 +02:00
|
|
|
ls[streamData.source][streamData.type][streamData.slug] = {}
|
2021-07-15 20:34:25 +02:00
|
|
|
|
|
|
|
// Store real data
|
2021-08-06 17:54:09 +02:00
|
|
|
let key = streamData.type === "show" ? `${season}-${episode}` : "full"
|
2021-07-21 12:29:18 +02:00
|
|
|
ls[streamData.source][streamData.type][streamData.slug][key] = {
|
2021-07-15 20:34:25 +02:00
|
|
|
currentlyAt: Math.floor(evt.currentTarget.currentTime),
|
2021-07-15 21:04:47 +02:00
|
|
|
totalDuration: Math.floor(evt.currentTarget.duration),
|
2021-08-06 15:39:54 +02:00
|
|
|
updatedAt: Date.now(),
|
|
|
|
meta: streamData
|
2021-07-15 20:34:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(streamData.type === "show") {
|
2021-07-21 12:29:18 +02:00
|
|
|
ls[streamData.source][streamData.type][streamData.slug][key].show = {
|
2021-07-15 20:34:25 +02:00
|
|
|
season,
|
2021-08-06 17:54:09 +02:00
|
|
|
episode
|
2021-07-15 20:34:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
localStorage.setItem("video-progress", JSON.stringify(ls))
|
|
|
|
}
|
|
|
|
|
2021-07-14 00:31:37 +02:00
|
|
|
return (
|
2021-07-15 00:09:42 +02:00
|
|
|
<div className={`cardView showType-${streamData.type}`}>
|
2021-08-02 15:15:24 +02:00
|
|
|
<Helmet>
|
2021-08-02 15:22:13 +02:00
|
|
|
<title>{streamData.title}{streamData.type === 'show' ? ` | S${season}E${episode}` : ''} | movie-web</title>
|
2021-08-02 15:15:24 +02:00
|
|
|
</Helmet>
|
|
|
|
|
2021-07-14 00:31:37 +02:00
|
|
|
<Card fullWidth>
|
|
|
|
<Title accent="Return to home" accentLink="search">
|
2021-07-15 00:09:42 +02:00
|
|
|
{streamData.title}
|
2021-07-14 00:31:37 +02:00
|
|
|
</Title>
|
2021-07-15 00:09:42 +02:00
|
|
|
{streamData.type === "show" ? <Title size="small">
|
2021-08-02 15:08:55 +02:00
|
|
|
Season {season}: Episode {episode}
|
2021-07-15 00:09:42 +02:00
|
|
|
</Title> : undefined}
|
2021-08-06 17:54:09 +02:00
|
|
|
|
2021-07-15 20:34:25 +02:00
|
|
|
<VideoElement streamUrl={streamUrl} loading={loading} setProgress={setProgress} />
|
2021-08-06 17:54:09 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
{streamData.type === "show" ?
|
|
|
|
<EpisodeSelector
|
2021-08-02 15:08:55 +02:00
|
|
|
setSelectedSeason={setSelectedSeason}
|
|
|
|
selectedSeason={selectedSeason}
|
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
setEpisode={setEpisode}
|
2021-08-02 15:08:55 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
seasons={seasonList}
|
|
|
|
episodes={episodeLists}
|
2021-08-02 15:08:55 +02:00
|
|
|
|
2021-07-15 00:09:42 +02:00
|
|
|
currentSeason={season}
|
|
|
|
currentEpisode={episode}
|
2021-08-02 15:08:55 +02:00
|
|
|
|
2021-08-06 17:54:09 +02:00
|
|
|
streamData={streamData}
|
2021-07-15 00:09:42 +02:00
|
|
|
/>
|
|
|
|
: ''}
|
2021-07-14 00:31:37 +02:00
|
|
|
</Card>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|