Nós iremos fazer o tempo do episódio. Iremos então na pasta “service” criar um arquivo chamado “episodesService.ts”.
Nós iremos primeiro criar um “WatchTimeParams”, que vai receber apenas o id e os segundos do episódio
import api from './api'
interface watchTimeParams {
episodeId: number;
seconds: number;
}
Nós iremos então criar um service e o primeiro método, que será o método de pegar os segundos assistidos daquele episódio pelo usuário
const watchEpisodeService = {
getWatchTime: async (episodeId: number) => {},
};
export default watchEpisodeService;
Agora, iremos fazer de fato o método, ele é praticamente igual aos outros, só mudando basicamente a sua url
const watchEpisodeService = {
getWatchTime: async (episodeId: number) => {
const token = sessionStorage.getItem("onebitflix-token");
const res = await api
.get(`/episodes/${episiodeId}/watchTime`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.catch((error) => {
console.log(error.response.data.message);
return error.response;
});
return res;
},
};
Agora, iremos aproveitar para fazer o método de set, pois nós precisamos enviar para o backend o tempo assistido pelo usuário.
setWatchTime: async ({ episodeId, seconds }: watchTimeParams) => {
const token = sessionStorage.getItem("onebitflix-token");
const res = await api
.post(
`/episodes/${episodeId}/watchTime`,
{ seconds },
{
headers: {
Authorization: `Bearer ${token}`,
},
}
)
.catch((error) => {
console.log(error.response.data.message);
return error.response;
});
return res;
},
Agora, nós vamos poder ir no arquivo de episódio, onde temos o player. Nós vamos começar fazendo dois states, um para pegar o time do episódio e outro para setar.
const router = useRouter();
const episodeOrder = parseFloat(router.query.id?.toString() || "");
const courseId = router.query.courseid?.toString() || "";
const [course, setCourse] = useState<CourseType>();
const [getEpisodeTime, setGetEpisodeTime] = useState(0);
const [episodeTime, setEpisodeTime] = useState(0);
Agora, nós iremos fazer um handle para pegarmos esse tempo do backend, faremos ele acima da função “getCourse”, assim como todos os outros métodos que vamos criar.
const handleGetEpisodeTime = async () => {
const res = await watchEpisodeService.getWatchTime();
};
Agora, nós iremos em “episodeList” para colocarmos um parâmetro no push, que será o id do episódio, pois precisamos dele como parâmetro do “getWatchTime”
Vamos adicionar outro parâmetro com um “&” e o parâmetro.
const handleEpisodePlayer = () => {
router.push(`/courses/episode/${episode.order - 1}?courseid=${course.id}&episodeid=${episode.id}`);
};
Agora nós iremos pegar o “episodeId” que nem fizemos com o “episodeOrder”
const episodeOrder = parseFloat(router.query.id?.toString() || "");
const episodeId = parseFloat(router.query.episodeid?.toString() || "");
Vamos também colocar esse parâmetro nos handle de passar e votar episódio, fazendo a mesma coisa que fizemos no order, somar e subtrair.
const handleLastEpisode = () => {
router.push(`/courses/episode/${episodeOrder - 1}?courseid=${course.id}&episodeid=${episodeId - 1}`);
};
const handleNextEpisode = () => {
router.push(`/courses/episode/${episodeOrder + 1}?courseid=${course.id}&episodeid=${episodeId + 1}`);
};
Agora iremos passar esse episodeId como parâmetro para o “getWatchTime”
const handleGetEpisodeTime = async () => {
const res = await watchEpisodeService.getWatchTime(episodeId);
};
Vamos então verificar se o “data” não é nulo, se não for, iremos setar o “getEpisodeTime”, e se for, ele vai começar como 0, já que é o valor do “getEpisodeTime”
const handleGetEpisodeTime = async () => {
const res = await watchEpisodeService.getWatchTime(parseFloat(episodeId));
if (res.data !== null) {
setGetEpisodeTime(res.data.seconds);
}
};
Agora colocaremos um “useEffect” com o router na depêndencia, pois dessa forma nós iremos chamar o método quando o a rota mudar.
useEffect(() => {
handleGetEpisodeTime();
}, [router]);
Agora faremos uma coisa nova, nós iremos pegar a referência do player, essa referência vai fazer com que a gente possa usar alguns elementos do player, como o método de mover o time do episódio. Vamos deixar abaixo do “getEpisodeTime” e “episodeTime
const playerRef = useRef<ReactPlayer>(null);
Agora iremos criar um handle abaixo do useEffect que iremos chamar de “handlePlayerTime”, que vai setar o valor inicial do video.
{typeof window == "undefined" ? null : (
<ReactPlayer
className={styles.player}
url={`${
process.env.NEXT_PUBLIC_BASEURL
}/episodes/stream?videoUrl=${
course.episodes[episodeOrder].videoUrl
}&token=${sessionStorage.getItem("onebitflix-token")}`}
controls
ref={playerRef}
onStart={handlePlayerTime}
/>
)}
Agora iremos colocar duas novas informações dentro do player: “ref” que vamos colocar o “useRef” que criamos e “onStart” que será o “handlePlayerTime”
<ReactPlayer
className={styles.player}
url={`${process.env.NEXT_PUBLIC_BASEURL}/episodes/stream?videoUrl=${videoUrl}&token=${token}`}
controls
ref={playerRef}
onStart={handlePlayerTime}
/>
Nós ainda não podemos testar por que não conseguimos colocar um valor inicial, então vamos criar a função que vai setar o valor inicial de acordo com o que for assistido.
const handleSetEpisodeTime = async () => {
await watchEpisodeService.setWatchTime({
episodeId: episodeId,
seconds: Math.round(episodeTime),
});
};
Agora, nós iremos dar os sets nos segundos do vídeo com um “onProgress”
{typeof window == "undefined" ? null : (
<ReactPlayer
className={styles.player}
url={`${
process.env.NEXT_PUBLIC_BASEURL
}/episodes/stream?videoUrl=${
course.episodes[episodeOrder].videoUrl
}&token=${sessionStorage.getItem("onebitflix-token")}`}
controls
ref={playerRef}
onStart={handlePlayerTime}
onProgress={(progress) => {
setEpisodeTime(progress.playedSeconds);
}}
/>
)}
Nós iremos agora criar um “useState” para sabermos quando a pessoa der play no vídeo, pois nós só começaremos a chamar o “handleSet” quando a pessoa der play. Nós vamos colocar esse “useState” abaixo do “playerRef”
const [isReady, setIsReady] = useState(false);
Nós vamos setar o “isReady” para true, no “handlePlayerTime”, pois esse handle só é chamado quando o vídeo é iniciado.
const handlePlayerTime = () => {
playerRef.current?.seekTo(getEpisodeTime);
setIsReady(true);
};
Agora, nós iremos começar a chamada do nosso “handleSet”. Vamos verificar se o “isReady” é verdadeiro, então vamos colocar um “setTimeOut”, que vai chamar essa função a cada 3 segundos. Vamos colocar esse if abaixo do “handlePlayerTime”
if (isReady === true) {
setTimeout(() => {
handleSetEpisodeTime();
}, 1000 * 3);
}