diff options
| -rw-r--r-- | components/videoPlayer.js | 73 | ||||
| -rw-r--r-- | lib/Artplayer.js | 4 | ||||
| -rw-r--r-- | pages/anime/watch/[...info].js | 41 |
3 files changed, 94 insertions, 24 deletions
diff --git a/components/videoPlayer.js b/components/videoPlayer.js index 0ef5dc4..d437c43 100644 --- a/components/videoPlayer.js +++ b/components/videoPlayer.js @@ -4,21 +4,19 @@ import { useAniList } from "../lib/useAnilist"; export default function VideoPlayer({ data, - seek, - titles, id, progress, session, aniId, stats, + op, + ed, }) { const [url, setUrl] = useState(); const [source, setSource] = useState([]); const [loading, setLoading] = useState(true); const { markProgress } = useAniList(session); - // console.log(progress); - useEffect(() => { async function compiler() { try { @@ -53,6 +51,8 @@ export default function VideoPlayer({ compiler(); }, [data]); + // console.log(skip); + return ( <> {loading ? ( @@ -64,7 +64,6 @@ export default function VideoPlayer({ quality: [source], autoplay: true, screenshot: true, - type: "m3u8", }} style={{ width: "100%", height: "100%", margin: "0 auto 0" }} getInstance={(art) => { @@ -77,7 +76,7 @@ export default function VideoPlayer({ if (percentage >= 0.9) { // use >= instead of > art.currentTime = 0; - console.log("Video restarted from the beginning"); + console.log("Video started from the beginning"); } else { art.currentTime = seekTime; } @@ -99,9 +98,65 @@ export default function VideoPlayer({ } }); - art.on("video:ended", () => { - art.destroy(); - console.log("Video ended"); + art.on("video:timeupdate", function () { + // if (!skip) return; + var currentTime = art.currentTime; + + if ( + op && + currentTime >= op.interval.startTime && + currentTime <= op.interval.endTime + ) { + // Add the layer if it's not already added + if (!art.layers.op) { + art.layers.add({ + name: "op", + html: `<button style="background-color: #fff; color: black; padding: 10px 25px; border: none; border-radius: 4px; cursor: pointer; box-shadow: 2px 2px 5px rgba(0,0,0,0.2); font-family: Karla, sans-serif; font-size: 16px; text-align: center;">Skip Opening</button>`, + tooltip: "Skip", + style: { + position: "absolute", + bottom: "68px", + right: "60px", + }, + click: function (...args) { + art.seek = op.interval.endTime; + }, + }); + } + // Show the layer + art.layers.show = true; + if (art.layers.ed) { + art.layers.ed.style.display = "none"; + } + } else if ( + ed && + currentTime >= ed.interval.startTime && + currentTime <= ed.interval.endTime + ) { + // Add the layer if it's not already added + if (!art.layers.ed) { + art.layers.add({ + name: "ed", + html: `<button style="background-color: #fff; color: black; padding: 10px 25px; border: none; border-radius: 4px; cursor: pointer; box-shadow: 2px 2px 5px rgba(0,0,0,0.2); font-family: Karla, sans-serif; font-size: 16px; text-align: center;">Skip Ending</button>`, + tooltip: "Skip", + style: { + position: "absolute", + bottom: "68px", + right: "60px", + }, + click: function (...args) { + art.seek = ed.interval.endTime; + }, + }); + } + // Show the layer + art.layers.show = true; + if (art.layers.op) { + art.layers.op.style.display = "none"; + } + } else { + art.layers.show = false; + } }); art.on("destroy", async () => { diff --git a/lib/Artplayer.js b/lib/Artplayer.js index 49806ed..ae7b88c 100644 --- a/lib/Artplayer.js +++ b/lib/Artplayer.js @@ -25,17 +25,17 @@ export default function Player({ option, getInstance, ...rest }) { const art = new Artplayer({ ...option, container: artRef.current, + type: "m3u8", customType: { m3u8: playM3u8, }, fullscreen: true, - fullscreenWeb: true, hotkey: true, lock: true, autoOrientation: true, theme: "#f97316", icons: { - state: "</>", + state: "", }, }); diff --git a/pages/anime/watch/[...info].js b/pages/anime/watch/[...info].js index 6c51498..98926d4 100644 --- a/pages/anime/watch/[...info].js +++ b/pages/anime/watch/[...info].js @@ -1,17 +1,14 @@ -import Layout from "../../../components/layout"; -// import { data } from "../../../lib/testData"; -// import { aniData } from "../../../lib/infoData"; import Image from "next/image"; import VideoPlayer from "../../../components/videoPlayer"; import Link from "next/link"; import { closestMatch } from "closest-match"; import Head from "next/head"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import Modal from "../../../components/modal"; import { useNotification } from "../../../lib/useNotify"; -import { signIn, signOut } from "next-auth/react"; +import { signIn } from "next-auth/react"; import { getServerSession } from "next-auth/next"; import { authOptions } from "../../api/auth/[...nextauth]"; @@ -23,7 +20,7 @@ export default function Info({ info, sessions, statusWatch }) { const title = info.aniData.title.romaji || info.aniData.title.english; const data = info.aniData; const fallback = info.epiFallback; - const { Notification: NotificationComponent, show } = useNotification(); + const { Notification: NotificationComponent } = useNotification(); let playingEpisode = data.episodes .filter((item) => item.id == info.id) @@ -60,6 +57,8 @@ export default function Info({ info, sessions, statusWatch }) { .filter((item) => item.id == info.id) .map((item) => item.title); + // console.log(info.skip); + return ( <> <Head> @@ -159,13 +158,13 @@ export default function Info({ info, sessions, statusWatch }) { <VideoPlayer key={info.id} data={info.epiData} - seek={info.seek} - titles={title} id={info.id} progress={parseInt(playingEpisode)} session={sessions} aniId={parseInt(data.id)} stats={statusWatch} + op={info.skip.op} + ed={info.skip.ed} /> </div> <div> @@ -388,7 +387,6 @@ export async function getServerSideProps(context) { const id = info[0]; const aniId = info[1]; - const seek = info[2] || 0; let epiFallback = null; const res = await fetch(`https://api.moopa.my.id/meta/anilist/watch/${id}`); @@ -419,9 +417,13 @@ export async function getServerSideProps(context) { } } - const playingEpisode = aniData.episodes - .filter((item) => item.id == id) - .map((item) => item.number); + const playingEpisode = + aniData.episodes + .filter((item) => item.id == id) + .map((item) => item.number) || + epiFallback.episodes + .filter((item) => item.id == id) + .map((item) => item.number); const response = await fetch("https://graphql.anilist.co/", { method: "POST", @@ -512,14 +514,27 @@ export async function getServerSideProps(context) { statusWatch = "COMPLETED"; } + const res4 = await fetch( + `https://api.aniskip.com/v2/skip-times/${aniData.malId}/${parseInt( + playingEpisode + )}?types[]=ed&types[]=mixed-ed&types[]=mixed-op&types[]=op&types[]=recap&episodeLength=` + ); + const skip = await res4.json(); + + const op = skip.results?.find((item) => item.skipType === "op") || null; + const ed = skip.results?.find((item) => item.skipType === "ed") || null; + return { props: { info: { id, - seek, epiData, aniData, epiFallback, + skip: { + op: op, + ed: ed, + }, }, sessions: session, statusWatch: statusWatch, |