diff options
| author | Factiven <[email protected]> | 2023-07-16 22:35:39 +0700 |
|---|---|---|
| committer | Factiven <[email protected]> | 2023-07-16 22:35:39 +0700 |
| commit | 1eee181e219dfd993d396ac3169e7aad3dd285eb (patch) | |
| tree | 23fe54e9c3f8810f3ac9ab6b29070b4f0d4b9d20 /pages/en/manga | |
| parent | removed console.log (diff) | |
| download | moopa-1eee181e219dfd993d396ac3169e7aad3dd285eb.tar.xz moopa-1eee181e219dfd993d396ac3169e7aad3dd285eb.zip | |
Update v3.6.4
- Added Manga page with a working tracker for AniList user
- Added schedule component to home page
- Added disqus comment section so you can fight on each other (not recommended)
- Added /id and /en route for english and indonesian subs (id route still work in progress)
Diffstat (limited to 'pages/en/manga')
| -rw-r--r-- | pages/en/manga/[id].js | 172 | ||||
| -rw-r--r-- | pages/en/manga/read/[...params].js | 262 |
2 files changed, 434 insertions, 0 deletions
diff --git a/pages/en/manga/[id].js b/pages/en/manga/[id].js new file mode 100644 index 0000000..5e46599 --- /dev/null +++ b/pages/en/manga/[id].js @@ -0,0 +1,172 @@ +import dotenv from "dotenv"; +import ChapterSelector from "../../../components/manga/chapters"; +import HamburgerMenu from "../../../components/manga/mobile/hamburgerMenu"; +import Navbar from "../../../components/navbar"; +import TopSection from "../../../components/manga/info/topSection"; +import Footer from "../../../components/footer"; +import Head from "next/head"; +import { useEffect, useState } from "react"; +import { setCookie } from "nookies"; +import { getServerSession } from "next-auth"; +import { authOptions } from "../../api/auth/[...nextauth]"; + +export default function Manga({ info, userManga, chapters }) { + const [domainUrl, setDomainUrl] = useState(""); + const [firstEp, setFirstEp] = useState(); + const chaptersData = + info.chapters.data.length === 0 ? chapters : info.chapters.data; + + useEffect(() => { + setDomainUrl(window.location.origin); + }, []); + + return ( + <> + <Head> + <title> + {info + ? `Manga - ${ + info.title.romaji || info.title.english || info.title.native + }` + : "Getting Info..."} + </title> + <meta name="twitter:card" content="summary_large_image" /> + <meta + name="twitter:title" + content={`Moopa - ${info.title.romaji || info.title.english}`} + /> + <meta + name="twitter:description" + content={`${info.description?.slice(0, 180)}...`} + /> + <meta + name="twitter:image" + content={`${domainUrl}/api/og?title=${ + info.title.romaji || info.title.english + }&image=${info.bannerImage || info.coverImage}`} + /> + </Head> + <div className="min-h-screen w-screen flex flex-col items-center relative"> + <HamburgerMenu /> + <Navbar className="absolute top-0 w-full z-40" /> + <div className="flex flex-col w-screen items-center gap-5 md:gap-10 py-10 pt-nav"> + <div className="flex-center w-full relative z-30"> + <TopSection info={info} firstEp={firstEp} setCookie={setCookie} /> + <> + <div className="absolute hidden md:block z-20 bottom-0 h-1/2 w-full bg-secondary" /> + <div className="absolute hidden md:block z-20 top-0 h-1/2 w-full bg-transparent" /> + </> + </div> + <div className="w-[90%] xl:w-[70%] min-h-[35vh] z-40"> + {chaptersData.length > 0 ? ( + <ChapterSelector + chaptersData={chaptersData} + data={info} + setFirstEp={setFirstEp} + setCookie={setCookie} + userManga={userManga} + /> + ) : ( + <p>No Chapter Available :(</p> + )} + </div> + </div> + <Footer /> + </div> + </> + ); +} + +export async function getServerSideProps(context) { + dotenv.config(); + + const session = await getServerSession(context.req, context.res, authOptions); + + const { id } = context.query; + const key = process.env.API_KEY; + const res = await fetch(`https://api.anify.tv/info/${id}?apikey=${key}`); + const data = await res.json(); + + let userManga = null; + + if (session) { + const response = await fetch("https://graphql.anilist.co/", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: ` + query ($username: String, $status: MediaListStatus) { + MediaListCollection(userName: $username, type: MANGA, status: $status, sort: SCORE_DESC) { + user { + id + name + } + lists { + status + name + entries { + id + mediaId + status + progress + score + progressVolumes + media { + id + status + title { + english + romaji + } + episodes + coverImage { + large + } + } + } + } + } + } + `, + variables: { + username: session?.user?.name, + }, + }), + }); + const data = await response.json(); + const user = data?.data?.MediaListCollection; + const userListsCurrent = user?.lists.find((X) => X.status === "CURRENT"); + const matched = userListsCurrent?.entries.find( + (x) => x.mediaId === parseInt(id) + ); + if (matched) { + userManga = matched; + } + } + + if (!data?.chapters) { + return { + notFound: true, + }; + } + + let chapter = null; + + if (data?.chapters?.data.length === 0) { + const res2 = await fetch( + `https://api.anify.tv/chapters/${id}?apikey=${key}` + ); + const data2 = await res2.json(); + chapter = data2; + } + + return { + props: { + info: data, + userManga, + chapters: chapter || null, + }, + }; +} diff --git a/pages/en/manga/read/[...params].js b/pages/en/manga/read/[...params].js new file mode 100644 index 0000000..0c6372d --- /dev/null +++ b/pages/en/manga/read/[...params].js @@ -0,0 +1,262 @@ +import dotenv from "dotenv"; +import { useEffect, useRef, useState } from "react"; +import { LeftBar } from "../../../../components/manga/leftBar"; +import { useRouter } from "next/router"; +import RightBar from "../../../../components/manga/rightBar"; +import FirstPanel from "../../../../components/manga/panels/firstPanel"; +import SecondPanel from "../../../../components/manga/panels/secondPanel"; +import ThirdPanel from "../../../../components/manga/panels/thirdPanel"; +import { getServerSession } from "next-auth"; +import { authOptions } from "../../../api/auth/[...nextauth]"; +import BottomBar from "../../../../components/manga/mobile/bottomBar"; +import TopBar from "../../../../components/manga/mobile/topBar"; +import { ToastContainer } from "react-toastify"; +import Head from "next/head"; +import nookies from "nookies"; +import ShortCutModal from "../../../../components/manga/modals/shortcutModal"; +import ChapterModal from "../../../../components/manga/modals/chapterModal"; + +export default function Read({ data, currentId, sessions }) { + const [info, setInfo] = useState(); + const [chapter, setChapter] = useState([]); + const [layout, setLayout] = useState(1); + + const [visible, setVisible] = useState(true); + const [mobileVisible, setMobileVisible] = useState(true); + const [isKeyOpen, setIsKeyOpen] = useState(false); + const [isChapOpen, setIsChapOpen] = useState(false); + + const [seekPage, setSeekPage] = useState(0); + + const [paddingX, setPaddingX] = useState(208); + const [scaleImg, setScaleImg] = useState(1); + + const [nextChapterId, setNextChapterId] = useState(null); + const [prevChapterId, setPrevChapterId] = useState(null); + + const [currentChapter, setCurrentChapter] = useState(null); + const [currentPage, setCurrentPage] = useState(0); + + const hasRun = useRef(false); + + const router = useRouter(); + + // console.log(cookies); + + useEffect(() => { + hasRun.current = false; + }, [currentId]); + + useEffect(() => { + const get = JSON.parse(localStorage.getItem("manga")); + const chapters = get.manga; + const currentChapter = chapters.chapters?.find((x) => x.id === currentId); + + setCurrentChapter(currentChapter); + setInfo(get.data); + setChapter(chapters); + + if (Array.isArray(chapters?.chapters)) { + const currentIndex = chapters.chapters.findIndex( + (chapter) => chapter.id === currentId + ); + if (currentIndex !== -1) { + const nextChapter = chapters.chapters[currentIndex - 1]; + const prevChapter = chapters.chapters[currentIndex + 1]; + setNextChapterId(nextChapter ? nextChapter.id : null); + setPrevChapterId(prevChapter ? prevChapter.id : null); + } + } + }, [currentId]); + + useEffect(() => { + const handleKeyDown = (event) => { + if (event.key === "ArrowRight" && event.ctrlKey && nextChapterId) { + router.push( + `/en/manga/read/${chapter.providerId}?id=${ + info.id + }&chapterId=${encodeURIComponent(nextChapterId)}` + ); + } else if (event.key === "ArrowLeft" && event.ctrlKey && prevChapterId) { + router.push( + `/en/manga/read/${chapter.providerId}?id=${ + info.id + }&chapterId=${encodeURIComponent(prevChapterId)}` + ); + } + if (event.code === "Slash" && event.ctrlKey) { + setIsKeyOpen(!isKeyOpen); + } + if (event.key === "f" || event.key === "F") { + setVisible(!visible); + } + if (event.code === "ArrowUp" && event.shiftKey) { + setPaddingX(paddingX - 50); + } else if (event.code === "ArrowDown" && event.shiftKey) { + setPaddingX(paddingX + 50); + } + }; + + window.addEventListener("keydown", handleKeyDown); + + return () => { + window.removeEventListener("keydown", handleKeyDown); + }; + }, [nextChapterId, prevChapterId, visible, isKeyOpen, paddingX]); + + return ( + <> + <Head> + <title> + {info + ? `Manga - ${ + info.title.romaji || info.title.english || info.title.native + }` + : "Getting Info..."} + </title> + </Head> + <div className="w-screen flex justify-evenly relative"> + <ToastContainer pauseOnFocusLoss={false} /> + <ShortCutModal isOpen={isKeyOpen} setIsOpen={setIsKeyOpen} /> + <ChapterModal + id={info?.id} + currentId={currentId} + data={chapter} + isOpen={isChapOpen} + setIsOpen={setIsChapOpen} + /> + + {mobileVisible && ( + <> + <TopBar info={info} /> + <BottomBar + id={info?.id} + prevChapter={prevChapterId} + nextChapter={nextChapterId} + currentPage={currentPage} + chapter={chapter} + page={data} + setSeekPage={setSeekPage} + setIsOpen={setIsChapOpen} + /> + </> + )} + {visible && ( + <LeftBar + data={chapter} + page={data} + info={info} + currentId={currentId} + setSeekPage={setSeekPage} + /> + )} + {layout === 1 && ( + <FirstPanel + aniId={info?.id} + data={data} + hasRun={hasRun} + currentId={currentId} + seekPage={seekPage} + setSeekPage={setSeekPage} + visible={visible} + setVisible={setVisible} + chapter={chapter} + nextChapter={nextChapterId} + prevChapter={prevChapterId} + paddingX={paddingX} + session={sessions} + mobileVisible={mobileVisible} + setMobileVisible={setMobileVisible} + setCurrentPage={setCurrentPage} + /> + )} + {layout === 2 && ( + <SecondPanel + aniId={info?.id} + data={data} + hasRun={hasRun} + currentChapter={currentChapter} + currentId={currentId} + seekPage={seekPage} + setSeekPage={setSeekPage} + visible={visible} + setVisible={setVisible} + session={sessions} + /> + )} + {layout === 3 && ( + <ThirdPanel + aniId={info?.id} + data={data} + hasRun={hasRun} + currentId={currentId} + currentChapter={currentChapter} + seekPage={seekPage} + setSeekPage={setSeekPage} + visible={visible} + setVisible={setVisible} + session={sessions} + scaleImg={scaleImg} + setMobileVisible={setMobileVisible} + mobileVisible={mobileVisible} + /> + )} + {visible && ( + <RightBar + id={info?.id} + hasRun={hasRun} + session={sessions} + data={chapter} + currentId={currentId} + currentChapter={currentChapter} + layout={layout} + setLayout={setLayout} + paddingX={paddingX} + setPaddingX={setPaddingX} + setIsKeyOpen={setIsKeyOpen} + scaleImg={scaleImg} + setScaleImg={setScaleImg} + /> + )} + </div> + </> + ); +} + +export async function getServerSideProps(context) { + dotenv.config(); + + const cookies = nookies.get(context); + + const query = context.query; + const providerId = query.params[0]; + const chapterId = query.chapterId; + const mediaId = query.id; + + if (!cookies.manga || cookies.manga !== mediaId) { + return { + redirect: { + destination: `/en/manga/${mediaId}`, + }, + }; + } + + const session = await getServerSession(context.req, context.res, authOptions); + + const key = process.env.API_KEY; + const res = await fetch( + `https://api.anify.tv/pages?providerId=${providerId}&readId=${encodeURIComponent( + chapterId + )}&apikey=${key}` + ); + + const data = await res.json(); + + return { + props: { + data: data, + currentId: chapterId, + sessions: session, + }, + }; +} |