From 1a85c2571690ba592ac5183d5eadaf9846fe532b Mon Sep 17 00:00:00 2001 From: Factiven Date: Mon, 25 Sep 2023 00:44:40 +0700 Subject: Update v4.1.0 (#79) * Update v4.1.0 * Update pages/_app.js --- pages/en/anime/watch/[...info].js | 598 ++++++++++++++++++++++++++------------ 1 file changed, 414 insertions(+), 184 deletions(-) (limited to 'pages/en/anime/watch') diff --git a/pages/en/anime/watch/[...info].js b/pages/en/anime/watch/[...info].js index aa0b672..f5b4fce 100644 --- a/pages/en/anime/watch/[...info].js +++ b/pages/en/anime/watch/[...info].js @@ -1,38 +1,156 @@ +import React, { useEffect, useRef, useState } from "react"; +import PlayerComponent from "@/components/watch/player/playerComponent"; +import { FlagIcon, ShareIcon } from "@heroicons/react/24/solid"; +import Details from "@/components/watch/primary/details"; +import EpisodeLists from "@/components/watch/secondary/episodeLists"; +import { getServerSession } from "next-auth"; +import { useWatchProvider } from "@/lib/hooks/watchPageProvider"; +import { authOptions } from "../../../api/auth/[...nextauth]"; +import { createList, createUser, getEpisode } from "@/prisma/user"; +import Link from "next/link"; +import MobileNav from "@/components/shared/MobileNav"; +import { NewNavbar } from "@/components/shared/NavBar"; +import Modal from "@/components/modal"; +import AniList from "@/components/media/aniList"; +import { signIn } from "next-auth/react"; +import BugReportForm from "@/components/shared/bugReport"; +import Skeleton from "react-loading-skeleton"; import Head from "next/head"; -import { useEffect, useState } from "react"; -import { getServerSession } from "next-auth/next"; -import { authOptions } from "../../../api/auth/[...nextauth]"; +export async function getServerSideProps(context) { + let userData = null; + const session = await getServerSession(context.req, context.res, authOptions); + const accessToken = session?.user?.token || null; + + const query = context?.query; + if (!query) { + return { + notFound: true, + }; + } -import Navigasi from "../../../../components/home/staticNav"; -import PrimarySide from "../../../../components/anime/watch/primarySide"; -import SecondarySide from "../../../../components/anime/watch/secondarySide"; -import { createList, createUser, getEpisode } from "../../../../prisma/user"; + const proxy = process.env.PROXY_URI; + const disqus = process.env.DISQUS_SHORTNAME; -export default function Info({ - sessions, + const [aniId, provider] = query?.info; + const watchId = query?.id; + const epiNumber = query?.num; + const dub = query?.dub; + + const ress = await fetch(`https://graphql.anilist.co`, { + method: "POST", + headers: { + "Content-Type": "application/json", + ...(accessToken && { Authorization: `Bearer ${accessToken}` }), + }, + body: JSON.stringify({ + query: `query ($id: Int) { + Media (id: $id) { + mediaListEntry { + progress + status + customLists + repeat + } + id + idMal + title { + romaji + english + native + } + status + genres + episodes + studios { + edges { + node { + id + name + } + } + } + bannerImage + description + coverImage { + extraLarge + color + } + synonyms + + } + } + `, + variables: { + id: aniId, + }, + }), + }); + const data = await ress.json(); + + try { + if (session) { + await createUser(session.user.name); + await createList(session.user.name, watchId); + const data = await getEpisode(session.user.name, watchId); + userData = JSON.parse( + JSON.stringify(data, (key, value) => { + if (key === "createdDate") { + return String(value); + } + return value; + }) + ); + } + } catch (error) { + console.error(error); + // Handle the error here + } + return { + props: { + sessions: session, + provider: provider || null, + watchId: watchId || null, + epiNumber: epiNumber || null, + dub: dub || null, + userData: userData?.[0] || null, + info: data.data.Media || null, + proxy, + disqus, + }, + }; +} + +export default function Watch({ + info, watchId, - provider, - epiNumber, + disqus, + proxy, dub, - info, userData, - proxy, - disqus, + sessions, + provider, + epiNumber, }) { - const [currentEpisode, setCurrentEpisode] = useState(null); - const [loading, setLoading] = useState(false); - const [artStorage, setArtStorage] = useState(null); + + const [episodeNavigation, setEpisodeNavigation] = useState(null); const [episodesList, setepisodesList] = useState(); - const [mapProviders, setMapProviders] = useState(null); + const [mapEpisode, setMapEpisode] = useState(null); + + const [episodeSource, setEpisodeSource] = useState(null); + + const [open, setOpen] = useState(false); + const [isOpen, setIsOpen] = useState(false); const [onList, setOnList] = useState(false); - const [origin, setOrigin] = useState(null); + + const { theaterMode, setPlayerState, setAutoPlay, setMarked } = + useWatchProvider(); + + const playerRef = useRef(null); useEffect(() => { - setLoading(true); - setOrigin(window.location.origin); async function getInfo() { if (info.mediaListEntry) { setOnList(true); @@ -56,7 +174,7 @@ export default function Info({ }); } - setMapProviders(getMap?.episodes); + setMapEpisode(getMap?.episodes); } if (episodes) { @@ -79,207 +197,319 @@ export default function Info({ const previousEpisode = episodeList?.find( (i) => i.number === parseInt(epiNumber) - 1 ); - setCurrentEpisode({ + setEpisodeNavigation({ prev: previousEpisode, playing: { id: currentEpisode.id, title: playingData?.title, description: playingData?.description, - image: playingData?.image, + img: playingData?.img || playingData?.image, number: currentEpisode.number, }, next: nextEpisode, }); - } else { - setLoading(false); } } setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings"))); // setEpiData(episodes); - setLoading(false); } getInfo(); return () => { - setCurrentEpisode(null); + setEpisodeNavigation(null); }; }, [sessions?.user?.name, epiNumber, dub]); + useEffect(() => { + async function fetchData() { + if (info) { + const autoplay = + localStorage.getItem("autoplay_video") === "true" ? true : false; + setAutoPlay(autoplay); + + const anify = await fetch("/api/v2/source", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + source: + provider === "gogoanime" && !watchId.startsWith("/") + ? "consumet" + : "anify", + providerId: provider, + watchId: watchId, + episode: epiNumber, + id: info.id, + sub: dub ? "dub" : "sub", + }), + }).then((res) => res.json()); + + const skip = await fetch( + `https://api.aniskip.com/v2/skip-times/${info.idMal}/${parseInt( + epiNumber + )}?types[]=ed&types[]=mixed-ed&types[]=mixed-op&types[]=op&types[]=recap&episodeLength=` + ).then((res) => { + if (!res.ok) { + switch (res.status) { + case 404: { + return null; + } + } + } + return res.json(); + }); + + const op = + skip?.results?.find((item) => item.skipType === "op") || null; + const ed = + skip?.results?.find((item) => item.skipType === "ed") || null; + + const episode = { + epiData: anify, + skip: { + op, + ed, + }, + }; + + setEpisodeSource(episode); + } + } + + fetchData(); + return () => { + setEpisodeSource(); + setPlayerState({ + currentTime: 0, + isPlaying: false, + }); + setMarked(0); + }; + }, [provider, watchId, info?.id]); + + const handleShareClick = async () => { + try { + if (navigator.share) { + await navigator.share({ + title: `Watch Now - ${info?.title?.english || info.title.romaji}`, + // text: `Watch [${info?.title?.romaji}] and more on Moopa. Join us for endless anime entertainment"`, + url: window.location.href, + }); + } else { + // Web Share API is not supported, provide a fallback or show a message + alert("Web Share API is not supported in this browser."); + } + } catch (error) { + console.error("Error sharing:", error); + } + }; + + function handleOpen() { + setOpen(true); + document.body.style.overflow = "hidden"; + } + + function handleClose() { + setOpen(false); + document.body.style.overflow = "auto"; + } + return ( <> - {info?.title?.romaji || "Retrieving data..."} + + {episodeNavigation?.playing?.title || + `${info?.title?.romaji} - Episode ${epiNumber}`} + + {/* Write the best SEO for this watch page with data of anime title from info.title.romaji, episode title from episodeNavigation?.playing?.title, description from episodeNavigation?.playing?.description, episode number from epiNumber */} + + {/* Write the best SEO for this homepage */} + + + + + + + + - + handleClose()}> + {!sessions && ( +
+

+ Edit your list +

+ +
+ )} +
+ +
+ + +
+ {theaterMode && ( + + )} +
+
+ {!theaterMode && ( + + )} +
+
+
+
+ + {(episodeNavigation?.playing?.title || + info.title.romaji) ?? + "Loading..."} + +
+

+ {episodeNavigation?.playing?.number ? ( + `Episode ${episodeNavigation?.playing?.number}` + ) : ( + + )} +

+
+
+
+ + +
+
+ {/*
right
*/} +
- -
-
- - +
handleOpen()} + disqus={disqus} + /> +
+
+
+ +
+
-
+
); } - -export async function getServerSideProps(context) { - const session = await getServerSession(context.req, context.res, authOptions); - const accessToken = session?.user?.token || null; - - const query = context.query; - if (!query) { - return { - notFound: true, - }; - } - - const proxy = process.env.PROXY_URI; - const disqus = process.env.DISQUS_SHORTNAME; - - const [aniId, provider] = query.info; - const watchId = query.id; - const epiNumber = query.num; - const dub = query.dub; - - let userData = null; - - const ress = await fetch(`https://graphql.anilist.co`, { - method: "POST", - headers: { - "Content-Type": "application/json", - ...(accessToken && { Authorization: `Bearer ${accessToken}` }), - }, - body: JSON.stringify({ - query: `query ($id: Int) { - Media (id: $id) { - mediaListEntry { - progress - status - customLists - repeat - } - id - idMal - title { - romaji - english - native - } - status - genres - episodes - studios { - edges { - node { - id - name - } - } - } - bannerImage - description - coverImage { - extraLarge - color - } - synonyms - - } - } - `, - variables: { - id: aniId, - }, - }), - }); - const data = await ress.json(); - - try { - if (session) { - await createUser(session.user.name); - await createList(session.user.name, watchId); - const data = await getEpisode(session.user.name, watchId); - userData = JSON.parse( - JSON.stringify(data, (key, value) => { - if (key === "createdDate") { - return String(value); - } - return value; - }) - ); - } - } catch (error) { - console.error(error); - // Handle the error here - } - - return { - props: { - sessions: session, - aniId: aniId || null, - provider: provider || null, - watchId: watchId || null, - epiNumber: epiNumber || null, - dub: dub || null, - userData: userData?.[0] || null, - info: data.data.Media || null, - proxy, - disqus, - }, - }; -} -- cgit v1.2.3