aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/videoPlayer.js73
-rw-r--r--lib/Artplayer.js4
-rw-r--r--pages/anime/watch/[...info].js41
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,