Criação do método de tempo do episódio

  1. Nós iremos fazer o tempo do episódio. Iremos então na pasta “service” criar um arquivo chamado “episodesService.ts”.

  2. 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;
    }
    
  3. 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;
    
  4. 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;
      },
    };
    
  5. 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;
      },
    
  6. 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);
    
  7. 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();
      };
    
  8. 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”

    1. 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}`);
        };
      
    2. 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() || "");
      
    3. 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}`);
        };
      
  9. Agora iremos passar esse episodeId como parâmetro para o “getWatchTime”

    	const handleGetEpisodeTime = async () => {
        const res = await watchEpisodeService.getWatchTime(episodeId);
      };
    
  10. 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);
        }
      };
    
  11. 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]);
    
  12. 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);
    
  13. 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}
                />
              )}
    
  14. 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}
              />
    
  15. 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.

    1. Nós iremos criar um handle, que vai ter o método de set, passando um “Math.round” no episode time, pois do jeito que iremos pegar,ele vai vir quebrado “16.7673920...”. Vamos colocar esse handle logo abaixo do “handleGet”
    	const handleSetEpisodeTime = async () => {
        await watchEpisodeService.setWatchTime({
          episodeId: episodeId,
          seconds: Math.round(episodeTime),
        });
      };
    
  16. 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);
                  }}
                />
              )}
    
  17. 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);
    
  18. 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);
      };
    
  19. 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);
      }