aboutsummaryrefslogtreecommitdiff
path: root/src/app/anime/components/episode_buttons.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/anime/components/episode_buttons.jsx')
-rw-r--r--src/app/anime/components/episode_buttons.jsx205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/app/anime/components/episode_buttons.jsx b/src/app/anime/components/episode_buttons.jsx
new file mode 100644
index 0000000..013dee1
--- /dev/null
+++ b/src/app/anime/components/episode_buttons.jsx
@@ -0,0 +1,205 @@
+"use client";
+import { useState, useEffect } from "react";
+import { MediaPlayer, MediaProvider } from "@vidstack/react";
+import "@vidstack/react/player/styles/default/theme.css";
+import "@vidstack/react/player/styles/default/layouts/video.css";
+import {
+ defaultLayoutIcons,
+ DefaultVideoLayout,
+} from "@vidstack/react/player/layouts/default";
+
+import styles from "../styles/buttons.module.css";
+import { video_url } from "../data-fetch/request";
+import { preFetchVideoLinks } from "./cacher";
+import { storeLocal } from "./storeHistory";
+
+const EpisodesButtons = ({ data: data }) => {
+ const [videoLink, setVideoLink] = useState(null);
+ const [buttonGroups, setButtonGroups] = useState(null);
+ const [videoLoading, setVideoLoading] = useState(null);
+
+ useEffect(() => {
+ setButtonGroups(createButtonGroups(0, 50));
+ }, []);
+
+ const groups = createGroups(data.episodes, 50);
+
+ /**
+ * Retrieves the video URL for a given episode ID.
+ * This function handles the initializing, changing URL, and hiding the video player.
+ * @param {string} epID - The episode ID.
+ */
+ async function getVideoURL(epID) {
+ setVideoLoading(true);
+ const data = await video_url(epID);
+ setVideoLink(data.sources[data.sources.length - 2].url);
+ setVideoLoading(false);
+ }
+
+ /**
+ * Creates button groups for a range of episodes.
+ * @param {number} start - The starting index of episodes.
+ * @param {number} end - The ending index of episodes.
+ * @returns {JSX.Element} - Button groups JSX element.
+ */
+ function createButtonGroups(start, end) {
+ try {
+ const buttons = document.getElementsByClassName("episode-button");
+ for (let i = 0; i < buttons.length; i++) {
+ buttons[i].style.backgroundColor = "#1f1f1fd2";
+ }
+ } catch (error) {
+ console.error(
+ "ERROR: This error is expected. This is done in order to reset the background color of the buttons. I can't think of a better way than this....so yeah.",
+ error.message
+ );
+ }
+
+ return (
+ <div className={styles.animeButtonContainer}>
+ {data.episodes &&
+ data.episodes.slice(start, end).map((item, index) => (
+ <button
+ className={styles.dramaButton + " episode-button"}
+ key={index}
+ onClick={(event) => {
+ event.target.style.backgroundColor =
+ "var(--soft-purple)";
+ getVideoURL(item.id);
+ store_to_local(
+ data.title,
+ data.image,
+ item.number,
+ data.id
+ );
+ }}
+ >
+ {item.number}
+ </button>
+ ))}
+ </div>
+ );
+ }
+
+ /**
+ * Handles the change event of the select element.
+ * @param {Event} event - The change event object.
+ */
+ function handleSelectChange(event) {
+ const selectedIndex = event.target.selectedIndex;
+ const selectedGroup = groups[selectedIndex];
+ if (selectedGroup) {
+ setButtonGroups(
+ createButtonGroups(
+ selectedGroup[0].number - 1,
+ selectedGroup[selectedGroup.length - 1].number
+ )
+ );
+ preFetchVideoLinks(
+ data.episodes.slice(
+ selectedGroup[0].number - 1,
+ selectedGroup[selectedGroup.length - 1].number
+ )
+ );
+ }
+ }
+
+ return (
+ <main className={styles.Main}>
+ {data.episodes && (
+ <select
+ onChange={(event) => handleSelectChange(event)}
+ className={styles.SelectClass}
+ >
+ {groups &&
+ groups.map((item, index) => (
+ <option key={index}>
+ {item[0].number} -{" "}
+ {item[item.length - 1].number}
+ </option>
+ ))}
+ </select>
+ )}
+ {buttonGroups}
+ {videoLoading && (
+ <p style={{ margin: "0.5rem 0 0 0" }}>Loading...</p>
+ )}
+ {videoLink && (
+ <div className={styles.videoPopUp} id="popup">
+ <div className={styles.video}>
+ <MediaPlayer
+ title="dramaPlayer"
+ src={videoLink}
+ aspectRatio="16/9"
+ load="eager"
+ className={styles.VideoPlayer}
+ playsInline
+ id="videoPlayer"
+ volume={0.8}
+ >
+ <MediaProvider />
+ <DefaultVideoLayout icons={defaultLayoutIcons} />
+ </MediaPlayer>
+ <button
+ className={styles.closeButton}
+ onClick={() => {
+ setVideoLink("");
+ }}
+ >
+ Close
+ </button>
+ </div>
+ </div>
+ )}
+ </main>
+ );
+};
+
+/**
+ * Divides an array into groups of a specified size.
+ * @param {Array} array - The array to be divided.
+ * @param {number} size - The size of each group.
+ * @returns {Array} - An array containing groups of elements.
+ */
+function createGroups(array, size) {
+ const groups = [];
+ for (let i = 0; i < array.length; i += size) {
+ groups.push(array.slice(i, i + size));
+ }
+ return groups;
+}
+
+/**
+ * Stores watch history to local storage.
+ * @param {string} name - The name of the episode.
+ * @param {string} image - The image URL of the episode.
+ * @param {number} episode - The episode number.
+ * @param {string} id - The ID of the episode.
+ */
+function store_to_local(name, image, episode, id) {
+ const currentDate = new Date();
+
+ try {
+ let newData = {
+ name: name,
+ image: image,
+ episode: episode,
+ id: id,
+ type: "anime",
+ date: `${currentDate.getDate()}-${String(
+ currentDate.getMonth() + 1
+ ).padStart(2, "0")}`,
+ time: `${currentDate.getHours()}:${String(
+ currentDate.getMinutes()
+ ).padStart(2, "0")}`,
+ };
+ storeLocal(newData);
+ } catch (error) {
+ console.error(
+ "Some error occurred during the process of saving your watch history to local storage. Please try again or contact us on GitHub if this issue persists.",
+ error.message
+ );
+ }
+}
+
+export default EpisodesButtons; \ No newline at end of file