From 549d19e16f7c1d7551832427274e46dfde3b82c2 Mon Sep 17 00:00:00 2001 From: Cooper Ransom Date: Wed, 20 Mar 2024 14:55:09 -0400 Subject: [PATCH 1/5] Add auto next episode --- public/config.js | 8 +++ .../player/atoms/NextEpisodeButton.tsx | 55 ++++++++++++++----- 2 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 public/config.js diff --git a/public/config.js b/public/config.js new file mode 100644 index 00000000..7eb8a8bc --- /dev/null +++ b/public/config.js @@ -0,0 +1,8 @@ +window.CONFIG = { + VITE_BACKEND_URL: "https://backend.sudo-flix.lol/", + VITE_CORS_PROXY_URL: "https://sudo-proxy1.sudo-flix.lol%2Chttps//sudo-proxy2.sudo-flix.lol,https://sudo-proxy3.sudo-flix.lol,https://sudo-proxy4.sudo-flix.lol,https://sudo-proxy5.sudo-flix.lol", + VITE_DMCA_EMAIL: "sudo-flix@proton.me", + VITE_GA_ID: "G-3VB2TNCW2V", + VITE_NORMAL_ROUTER: true, + VITE_TMDB_READ_API_KEY: "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhZTljNGE2ZDE1ZDFiODZiNzdlMWQyYmI5ZGY0MzdmYyIsInN1YiI6IjY1YjNmMWI0NTk0Yzk0MDE2MzNkZDBjNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.kAX7TkbKuJkNty6IsjcCLnoENFicVZn6d6DkLQsy3p8", +}; diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx index 3d760900..ce608750 100644 --- a/src/components/player/atoms/NextEpisodeButton.tsx +++ b/src/components/player/atoms/NextEpisodeButton.tsx @@ -1,5 +1,5 @@ import classNames from "classnames"; -import React, { useCallback } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Icon, Icons } from "@/components/Icon"; @@ -54,12 +54,30 @@ export function NextEpisodeButton(props: { const setShouldStartFromBeginning = usePlayerStore( (s) => s.setShouldStartFromBeginning, ); + const [countdown, setCountdown] = useState(15); let show = false; if (showingState === "always") show = true; else if (showingState === "hover" && props.controlsShowing) show = true; if (isHidden || status !== "playing" || duration === 0) show = false; + useEffect(() => { + // Initialize intervalId with 0, which is a safe value to clear if not reassigned. + let intervalId: number = 0; + if (show && countdown > 0) { + intervalId = window.setInterval(() => { + setCountdown((currentCountdown) => currentCountdown - 1); + }, 1000); + } else { + window.clearInterval(intervalId); // No need for casting here. + if (!show) { + setCountdown(15); // Reset countdown when not showing. + } + } + // Cleanup function to clear the interval when the component unmounts or the dependencies change. + return () => window.clearInterval(intervalId); + }, [show, countdown]); + const animation = showingState === "hover" ? "slide-up" : "fade"; let bottom = "bottom-[calc(6rem+env(safe-area-inset-bottom))]"; if (showingState === "always") @@ -99,23 +117,30 @@ export function NextEpisodeButton(props: { >
- - + {countdown > 0 && show && ( +
+ {t("player.nextEpisode.nextIn", { seconds: countdown })} +
+ )} +
+ + +
); From 7e8c8d7983605a259cb3dc81de3c9b914e31cc6a Mon Sep 17 00:00:00 2001 From: Cooper Ransom Date: Thu, 21 Mar 2024 10:35:00 -0400 Subject: [PATCH 2/5] Fix issue with next episode --- public/config.js | 8 ---- src/assets/locales/en.json | 3 +- .../player/atoms/NextEpisodeButton.tsx | 44 +++++++++++-------- 3 files changed, 28 insertions(+), 27 deletions(-) delete mode 100644 public/config.js diff --git a/public/config.js b/public/config.js deleted file mode 100644 index 7eb8a8bc..00000000 --- a/public/config.js +++ /dev/null @@ -1,8 +0,0 @@ -window.CONFIG = { - VITE_BACKEND_URL: "https://backend.sudo-flix.lol/", - VITE_CORS_PROXY_URL: "https://sudo-proxy1.sudo-flix.lol%2Chttps//sudo-proxy2.sudo-flix.lol,https://sudo-proxy3.sudo-flix.lol,https://sudo-proxy4.sudo-flix.lol,https://sudo-proxy5.sudo-flix.lol", - VITE_DMCA_EMAIL: "sudo-flix@proton.me", - VITE_GA_ID: "G-3VB2TNCW2V", - VITE_NORMAL_ROUTER: true, - VITE_TMDB_READ_API_KEY: "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhZTljNGE2ZDE1ZDFiODZiNzdlMWQyYmI5ZGY0MzdmYyIsInN1YiI6IjY1YjNmMWI0NTk0Yzk0MDE2MzNkZDBjNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.kAX7TkbKuJkNty6IsjcCLnoENFicVZn6d6DkLQsy3p8", -}; diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index a9db3c83..afbcd54c 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -395,7 +395,8 @@ }, "nextEpisode": { "replay": "Replay", - "next": "Next episode" + "next": "Next episode", + "nextIn": "Next episode in {{seconds}}" }, "playbackError": { "badge": "Playback error", diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx index ce608750..921d86c0 100644 --- a/src/components/player/atoms/NextEpisodeButton.tsx +++ b/src/components/player/atoms/NextEpisodeButton.tsx @@ -61,23 +61,6 @@ export function NextEpisodeButton(props: { else if (showingState === "hover" && props.controlsShowing) show = true; if (isHidden || status !== "playing" || duration === 0) show = false; - useEffect(() => { - // Initialize intervalId with 0, which is a safe value to clear if not reassigned. - let intervalId: number = 0; - if (show && countdown > 0) { - intervalId = window.setInterval(() => { - setCountdown((currentCountdown) => currentCountdown - 1); - }, 1000); - } else { - window.clearInterval(intervalId); // No need for casting here. - if (!show) { - setCountdown(15); // Reset countdown when not showing. - } - } - // Cleanup function to clear the interval when the component unmounts or the dependencies change. - return () => window.clearInterval(intervalId); - }, [show, countdown]); - const animation = showingState === "hover" ? "slide-up" : "fade"; let bottom = "bottom-[calc(6rem+env(safe-area-inset-bottom))]"; if (showingState === "always") @@ -106,6 +89,29 @@ export function NextEpisodeButton(props: { props.onChange?.(metaCopy); }, [setDirectMeta, meta, props, setShouldStartFromBeginning]); + useEffect(() => { + let intervalId: number = 0; + if (show && countdown > 0) { + intervalId = window.setInterval(() => { + setCountdown((currentCountdown) => { + // When countdown reaches 1, load the next episode on the next tick + if (currentCountdown === 1) { + // Ensure this runs only once by setting countdown to a non-positive number + setCountdown(-1); + loadNextEpisode(); + } + return currentCountdown - 1; + }); + }, 1000); + } else { + window.clearInterval(intervalId); + if (!show) { + setCountdown(15); // Reset countdown when not showing. + } + } + return () => window.clearInterval(intervalId); + }, [show, countdown, loadNextEpisode]); + if (!meta?.episode || !nextEp) return null; if (metaType !== "show") return null; @@ -138,7 +144,9 @@ export function NextEpisodeButton(props: { className="bg-buttons-primary hover:bg-buttons-primaryHover text-buttons-primaryText flex justify-center items-center" > - {t("player.nextEpisode.next")} + {countdown > 0 && show + ? `${t("player.nextEpisode.nextIn", { seconds: countdown })}` + : t("player.nextEpisode.next")} From 7c80e8c783fc7dcf8a2845c9240eff8bd997d981 Mon Sep 17 00:00:00 2001 From: Cooper Ransom Date: Thu, 21 Mar 2024 11:41:53 -0400 Subject: [PATCH 3/5] Fix issue with next episode vol. 2 --- .../player/atoms/NextEpisodeButton.tsx | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx index 921d86c0..95140e77 100644 --- a/src/components/player/atoms/NextEpisodeButton.tsx +++ b/src/components/player/atoms/NextEpisodeButton.tsx @@ -90,27 +90,31 @@ export function NextEpisodeButton(props: { }, [setDirectMeta, meta, props, setShouldStartFromBeginning]); useEffect(() => { - let intervalId: number = 0; - if (show && countdown > 0) { - intervalId = window.setInterval(() => { - setCountdown((currentCountdown) => { - // When countdown reaches 1, load the next episode on the next tick - if (currentCountdown === 1) { - // Ensure this runs only once by setting countdown to a non-positive number - setCountdown(-1); - loadNextEpisode(); - } - return currentCountdown - 1; - }); - }, 1000); - } else { - window.clearInterval(intervalId); - if (!show) { - setCountdown(15); // Reset countdown when not showing. - } + // Only start the countdown if the button is supposed to show. + if (!show) { + return; } + + // Initialize the countdown only once when the condition to show the button is met. + setCountdown(15); // Reset to 15 seconds whenever the conditions to show the button are met. + + const intervalId = window.setInterval(() => { + setCountdown((currentCountdown) => { + const newCountdown = currentCountdown - 1; + // When countdown reaches 0, load the next episode. + if (newCountdown <= 0) { + loadNextEpisode(); + // Stop the countdown by clearing the interval. + window.clearInterval(intervalId); + return 0; // Optionally reset the countdown or keep it at 0. + } + return newCountdown; + }); + }, 1000); + + // Cleanup function to clear the interval when the component unmounts or the dependencies change. return () => window.clearInterval(intervalId); - }, [show, countdown, loadNextEpisode]); + }, [show, loadNextEpisode]); // Removed countdown from dependencies to prevent resetting it unnecessarily. if (!meta?.episode || !nextEp) return null; if (metaType !== "show") return null; From 80bfa3b27d642754e4c85a79fda3e30ecfbc1457 Mon Sep 17 00:00:00 2001 From: Cooper Ransom Date: Thu, 21 Mar 2024 11:53:27 -0400 Subject: [PATCH 4/5] Fix issue with next episode vol. 3 --- .../player/atoms/NextEpisodeButton.tsx | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx index 95140e77..df7fbff7 100644 --- a/src/components/player/atoms/NextEpisodeButton.tsx +++ b/src/components/player/atoms/NextEpisodeButton.tsx @@ -19,6 +19,11 @@ function shouldShowNextEpisodeButton( return "none"; } +function shouldStartCountdown(time: number, duration: number): boolean { + const secondsFromEnd = duration - time; + return secondsFromEnd <= 30 || time / duration >= 0.93; +} + function Button(props: { className: string; onClick?: () => void; @@ -90,31 +95,30 @@ export function NextEpisodeButton(props: { }, [setDirectMeta, meta, props, setShouldStartFromBeginning]); useEffect(() => { - // Only start the countdown if the button is supposed to show. - if (!show) { - return; + // Check if we should start the countdown to automatically go to the next episode. + const startCountdown = shouldStartCountdown(time, duration); + + if (startCountdown && countdown === 15) { + const intervalId = window.setInterval(() => { + setCountdown((currentCountdown) => { + if (currentCountdown <= 1) { + loadNextEpisode(); // Load next episode when countdown reaches 0. + window.clearInterval(intervalId); // Clear the interval. + return 0; + } + return currentCountdown - 1; + }); + }, 1000); + + // Cleanup function to clear the interval when the component unmounts or the dependencies change. + return () => window.clearInterval(intervalId); } - - // Initialize the countdown only once when the condition to show the button is met. - setCountdown(15); // Reset to 15 seconds whenever the conditions to show the button are met. - - const intervalId = window.setInterval(() => { - setCountdown((currentCountdown) => { - const newCountdown = currentCountdown - 1; - // When countdown reaches 0, load the next episode. - if (newCountdown <= 0) { - loadNextEpisode(); - // Stop the countdown by clearing the interval. - window.clearInterval(intervalId); - return 0; // Optionally reset the countdown or keep it at 0. - } - return newCountdown; - }); - }, 1000); - - // Cleanup function to clear the interval when the component unmounts or the dependencies change. - return () => window.clearInterval(intervalId); - }, [show, loadNextEpisode]); // Removed countdown from dependencies to prevent resetting it unnecessarily. + if (!startCountdown) { + // Reset countdown when conditions are not met. + setCountdown(15); + } + // Removed countdown from the dependencies to prevent resetting it unnecessarily. + }, [time, duration, countdown, loadNextEpisode]); if (!meta?.episode || !nextEp) return null; if (metaType !== "show") return null; @@ -149,7 +153,7 @@ export function NextEpisodeButton(props: { > {countdown > 0 && show - ? `${t("player.nextEpisode.nextIn", { seconds: countdown })}` + ? t("player.nextEpisode.nextIn", { seconds: countdown }) : t("player.nextEpisode.next")} From a945fcc4c5cabb28279db4a7d23bf052d97ed057 Mon Sep 17 00:00:00 2001 From: Cooper Ransom Date: Thu, 21 Mar 2024 12:06:06 -0400 Subject: [PATCH 5/5] Fix issue with next episode vol. 4 --- src/assets/locales/en.json | 4 +- .../player/atoms/NextEpisodeButton.tsx | 53 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index afbcd54c..5257cec9 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -395,8 +395,8 @@ }, "nextEpisode": { "replay": "Replay", - "next": "Next episode", - "nextIn": "Next episode in {{seconds}}" + "nextIn": "Next episode in {{seconds}}", + "next": "Next Episode" }, "playbackError": { "badge": "Playback error", diff --git a/src/components/player/atoms/NextEpisodeButton.tsx b/src/components/player/atoms/NextEpisodeButton.tsx index df7fbff7..9e5e5a5d 100644 --- a/src/components/player/atoms/NextEpisodeButton.tsx +++ b/src/components/player/atoms/NextEpisodeButton.tsx @@ -95,30 +95,41 @@ export function NextEpisodeButton(props: { }, [setDirectMeta, meta, props, setShouldStartFromBeginning]); useEffect(() => { - // Check if we should start the countdown to automatically go to the next episode. - const startCountdown = shouldStartCountdown(time, duration); + // Function to calculate the initial countdown value based on current time and duration. + const calculateCountdown = () => { + const secondsFromEnd = duration - time; + if (secondsFromEnd <= 30) { + return Math.max(secondsFromEnd, 0); // Ensure countdown doesn't go below 0. + } + return 15; // Default countdown start value if within the last 30 seconds. + }; - if (startCountdown && countdown === 15) { - const intervalId = window.setInterval(() => { - setCountdown((currentCountdown) => { - if (currentCountdown <= 1) { - loadNextEpisode(); // Load next episode when countdown reaches 0. - window.clearInterval(intervalId); // Clear the interval. - return 0; - } - return currentCountdown - 1; - }); + // Update countdown based on current playback time. + const updateCountdown = () => { + if (status === "playing") { + const newCountdown = calculateCountdown(); + setCountdown(newCountdown); + } + }; + + // Call updateCountdown initially and whenever relevant dependencies change. + updateCountdown(); + + // Set up an interval to update the countdown every second if the video is playing. + let intervalId: number | null = null; + if (status === "playing") { + intervalId = window.setInterval(() => { + updateCountdown(); }, 1000); + } - // Cleanup function to clear the interval when the component unmounts or the dependencies change. - return () => window.clearInterval(intervalId); - } - if (!startCountdown) { - // Reset countdown when conditions are not met. - setCountdown(15); - } - // Removed countdown from the dependencies to prevent resetting it unnecessarily. - }, [time, duration, countdown, loadNextEpisode]); + // Cleanup function to clear the interval when the component unmounts or dependencies change. + return () => { + if (intervalId) { + clearInterval(intervalId); + } + }; + }, [time, duration, status]); // Depend on time, duration, and status to re-evaluate when they change. if (!meta?.episode || !nextEp) return null; if (metaType !== "show") return null;