aboutsummaryrefslogtreecommitdiff
path: root/components/manga/panels
diff options
context:
space:
mode:
authorFactiven <[email protected]>2023-07-16 22:35:39 +0700
committerFactiven <[email protected]>2023-07-16 22:35:39 +0700
commit1eee181e219dfd993d396ac3169e7aad3dd285eb (patch)
tree23fe54e9c3f8810f3ac9ab6b29070b4f0d4b9d20 /components/manga/panels
parentremoved console.log (diff)
downloadmoopa-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 'components/manga/panels')
-rw-r--r--components/manga/panels/firstPanel.js200
-rw-r--r--components/manga/panels/secondPanel.js191
-rw-r--r--components/manga/panels/thirdPanel.js171
3 files changed, 562 insertions, 0 deletions
diff --git a/components/manga/panels/firstPanel.js b/components/manga/panels/firstPanel.js
new file mode 100644
index 0000000..29484be
--- /dev/null
+++ b/components/manga/panels/firstPanel.js
@@ -0,0 +1,200 @@
+import { useEffect, useRef, useState } from "react";
+import {
+ ArrowsPointingOutIcon,
+ ArrowsPointingInIcon,
+ ChevronLeftIcon,
+ ChevronRightIcon,
+} from "@heroicons/react/24/outline";
+import Image from "next/image";
+import { useRouter } from "next/router";
+import { useAniList } from "../../../lib/anilist/useAnilist";
+
+export default function FirstPanel({
+ aniId,
+ data,
+ hasRun,
+ currentId,
+ seekPage,
+ setSeekPage,
+ visible,
+ setVisible,
+ chapter,
+ nextChapter,
+ prevChapter,
+ paddingX,
+ session,
+ mobileVisible,
+ setMobileVisible,
+ setCurrentPage,
+}) {
+ const { markProgress } = useAniList(session);
+ const [currentImageIndex, setCurrentImageIndex] = useState(0);
+ const imageRefs = useRef([]);
+ const scrollContainerRef = useRef();
+
+ const router = useRouter();
+
+ useEffect(() => {
+ const handleScroll = () => {
+ const scrollTop = scrollContainerRef.current.scrollTop;
+ let index = 0;
+
+ for (let i = 0; i < imageRefs.current.length; i++) {
+ const img = imageRefs.current[i];
+ if (
+ scrollTop >= img?.offsetTop - scrollContainerRef.current.offsetTop &&
+ scrollTop <
+ img.offsetTop -
+ scrollContainerRef.current.offsetTop +
+ img.offsetHeight
+ ) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index === data.length - 3 && !hasRun.current) {
+ if (session) {
+ const currentChapter = chapter.chapters?.find(
+ (x) => x.id === currentId
+ );
+ if (currentChapter) {
+ markProgress(aniId, currentChapter.number);
+ console.log("marking progress");
+ }
+ }
+ hasRun.current = true;
+ }
+
+ setCurrentPage(index + 1);
+ setCurrentImageIndex(index);
+ setSeekPage(index);
+ };
+
+ scrollContainerRef?.current?.addEventListener("scroll", handleScroll, {
+ passive: true,
+ });
+
+ return () => {
+ if (scrollContainerRef.current) {
+ scrollContainerRef.current.removeEventListener("scroll", handleScroll, {
+ passive: true,
+ });
+ }
+ };
+ }, [data, session, chapter]);
+
+ useEffect(() => {
+ if (scrollContainerRef.current && seekPage !== currentImageIndex) {
+ const targetImageRef = imageRefs.current[seekPage];
+ if (targetImageRef) {
+ scrollContainerRef.current.scrollTo({
+ top: targetImageRef.offsetTop - scrollContainerRef.current.offsetTop,
+ behavior: "smooth",
+ });
+ }
+ }
+ }, [seekPage, currentImageIndex]);
+
+ useEffect(() => {
+ if (scrollContainerRef.current) {
+ scrollContainerRef.current.scrollTo(0, 0);
+ }
+ }, [currentId]);
+
+ useEffect(() => {
+ if (typeof window !== "undefined") {
+ const root = window.document.documentElement;
+ root.style.setProperty("--dynamic-padding", `${paddingX}px`);
+ }
+ }, [paddingX]);
+
+ return (
+ <section className="flex-grow flex flex-col items-center relative">
+ <div
+ // style={{ paddingLeft: paddingX, paddingRight: paddingX }}
+ className="longPanel h-screen w-full overflow-y-scroll lg:scrollbar-thin scrollbar-thumb-txt scrollbar-thumb-rounded-sm"
+ ref={scrollContainerRef}
+ >
+ {data && Array.isArray(data) && data?.length > 0 ? (
+ data.map((i, index) => (
+ <div
+ key={i.url}
+ className="w-screen lg:h-auto lg:w-full"
+ ref={(el) => (imageRefs.current[index] = el)}
+ >
+ <Image
+ src={`https://img.moopa.live/image-proxy?url=${encodeURIComponent(
+ i.url
+ )}&headers=${encodeURIComponent(
+ JSON.stringify({ Referer: i.headers.Referer })
+ )}`}
+ alt={i.index}
+ width={500}
+ height={500}
+ onClick={() => setMobileVisible(!mobileVisible)}
+ className="w-screen lg:w-full h-auto bg-[#bbb]"
+ />
+ </div>
+ ))
+ ) : (
+ <div className="w-full flex-center h-full">
+ {data.error || "Not found"} :(
+ </div>
+ )}
+ </div>
+ <div className="absolute hidden lg:flex bottom-5 left-5 gap-5">
+ <span className="flex bg-secondary p-2 rounded-sm">
+ {visible ? (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingOutIcon className="w-5 h-5" />
+ </button>
+ ) : (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingInIcon className="w-5 h-5" />
+ </button>
+ )}
+ </span>
+ <div className="flex gap-2">
+ <button
+ type="button"
+ className={`flex-center rounded-sm p-2 ${
+ prevChapter
+ ? "bg-secondary"
+ : "pointer-events-none bg-[#18181A] text-[#424245]"
+ }`}
+ onClick={() =>
+ router.push(
+ `/en/manga/read/${
+ chapter.providerId
+ }?id=${aniId}&chapterId=${encodeURIComponent(prevChapter)}`
+ )
+ }
+ >
+ <ChevronLeftIcon className="w-5 h-5" />
+ </button>
+ <button
+ type="button"
+ className={`flex-center rounded-sm p-2 ${
+ nextChapter
+ ? "bg-secondary"
+ : "pointer-events-none bg-[#18181A] text-[#424245]"
+ }`}
+ onClick={() =>
+ router.push(
+ `/en/manga/read/${
+ chapter.providerId
+ }?id=${aniId}&chapterId=${encodeURIComponent(nextChapter)}`
+ )
+ }
+ >
+ <ChevronRightIcon className="w-5 h-5" />
+ </button>
+ </div>
+ </div>
+ <span className="hidden lg:flex bg-secondary p-2 rounded-sm absolute bottom-5 right-5">{`Page ${
+ currentImageIndex + 1
+ }/${data.length}`}</span>
+ </section>
+ );
+}
diff --git a/components/manga/panels/secondPanel.js b/components/manga/panels/secondPanel.js
new file mode 100644
index 0000000..6048fb4
--- /dev/null
+++ b/components/manga/panels/secondPanel.js
@@ -0,0 +1,191 @@
+import { useEffect, useRef, useState } from "react";
+import Image from "next/image";
+import {
+ ArrowsPointingOutIcon,
+ ArrowsPointingInIcon,
+} from "@heroicons/react/24/outline";
+import { useAniList } from "../../../lib/anilist/useAnilist";
+
+export default function SecondPanel({
+ aniId,
+ data,
+ hasRun,
+ currentChapter,
+ currentId,
+ seekPage,
+ setSeekPage,
+ visible,
+ setVisible,
+ session,
+}) {
+ const [index, setIndex] = useState(0);
+ const [image, setImage] = useState(null);
+
+ const { markProgress } = useAniList(session);
+
+ useEffect(() => {
+ setIndex(0);
+ setSeekPage(0);
+ }, [data, currentId]);
+
+ const seekToIndex = (newIndex) => {
+ if (newIndex >= 0 && newIndex < data.length) {
+ // if newIndex is odd, decrease it by 1 to show the previous page
+ if (newIndex % 2 !== 0) {
+ newIndex = newIndex - 1;
+ }
+ setIndex(newIndex);
+ setSeekPage(newIndex);
+ }
+ };
+
+ useEffect(() => {
+ seekToIndex(seekPage);
+ }, [seekPage]);
+
+ useEffect(() => {
+ if (data && Array.isArray(data) && data?.length > 0) {
+ setImage([...data].reverse()); // Create a copy of data before reversing
+ }
+ }, [data]);
+
+ useEffect(() => {
+ const handleKeyDown = (event) => {
+ if (event.key === "ArrowRight") {
+ if (index > 0) {
+ setIndex(index - 2);
+ setSeekPage(index - 2);
+ }
+ } else if (event.key === "ArrowLeft") {
+ if (index < image.length - 2) {
+ setIndex(index + 2);
+ setSeekPage(index + 2);
+ }
+
+ if (index + 1 >= image.length - 4 && !hasRun.current) {
+ let chapterNumber = currentChapter?.number;
+ if (chapterNumber % 1 !== 0) {
+ // If it's a decimal, round it
+ chapterNumber = Math.round(chapterNumber);
+ }
+
+ markProgress(aniId, chapterNumber);
+ hasRun.current = true;
+ }
+ }
+ };
+
+ window.addEventListener("keydown", handleKeyDown);
+
+ return () => {
+ window.removeEventListener("keydown", handleKeyDown);
+ };
+ }, [index, image]);
+
+ const handleNext = () => {
+ if (index < image.length - 2) {
+ setIndex(index + 2);
+ setSeekPage(index + 2);
+ }
+
+ if (index + 1 >= image.length - 4 && !hasRun.current) {
+ console.log("marking progress");
+ let chapterNumber = currentChapter?.number;
+ if (chapterNumber % 1 !== 0) {
+ // If it's a decimal, round it
+ chapterNumber = Math.round(chapterNumber);
+ }
+
+ markProgress(aniId, chapterNumber);
+ hasRun.current = true;
+ }
+ };
+
+ const handlePrev = () => {
+ if (index > 0) {
+ setIndex(index - 2);
+ setSeekPage(index - 2);
+ }
+ };
+ return (
+ <div className="flex-grow h-screen">
+ <div className="flex items-center w-full relative group">
+ {image && Array.isArray(image) && image?.length > 0 ? (
+ <>
+ <div
+ className={`flex w-full ${
+ image[image.length - index - 2]?.url
+ ? "justify-between"
+ : "justify-center"
+ }`}
+ >
+ {image[image.length - index - 2]?.url && (
+ <Image
+ key={image[image.length - index - 2]?.url}
+ width={500}
+ height={500}
+ className="w-1/2 h-screen object-contain"
+ src={`https://img.moopa.live/image-proxy?url=${encodeURIComponent(
+ image[image.length - index - 2]?.url
+ )}&headers=${encodeURIComponent(
+ JSON.stringify({
+ Referer: image[image.length - index - 2]?.headers.Referer,
+ })
+ )}`}
+ alt="Manga Page"
+ />
+ )}
+ <Image
+ key={image[image.length - index - 1]?.url}
+ width={500}
+ height={500}
+ className="w-1/2 h-screen object-contain"
+ src={`https://img.moopa.live/image-proxy?url=${encodeURIComponent(
+ image[image.length - index - 1]?.url
+ )}&headers=${encodeURIComponent(
+ JSON.stringify({
+ Referer: image[image.length - index - 1]?.headers.Referer,
+ })
+ )}`}
+ alt="Manga Page"
+ />
+ </div>
+ <div className="absolute w-full hidden group-hover:flex justify-between mt-4">
+ <button
+ className="px-4 py-2 bg-secondary text-white rounded-r"
+ onClick={handleNext}
+ >
+ Next
+ </button>
+ <button
+ className="px-4 py-2 bg-secondary text-white rounded-l"
+ onClick={handlePrev}
+ >
+ Previous
+ </button>
+ </div>
+ </>
+ ) : (
+ <div className="w-full flex-center h-full">
+ {data.error || "Not found"} :(
+ </div>
+ )}
+ <span className="absolute hidden group-hover:flex bottom-5 left-5 bg-secondary p-2">
+ {visible ? (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingOutIcon className="w-5 h-5" />
+ </button>
+ ) : (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingInIcon className="w-5 h-5" />
+ </button>
+ )}
+ </span>
+ <span className="absolute hidden group-hover:flex bottom-5 right-5 bg-secondary p-2">
+ Page {index + 1}
+ {index + 2 > data.length ? "" : `-${index + 2}`}/{data.length}
+ </span>
+ </div>
+ </div>
+ );
+}
diff --git a/components/manga/panels/thirdPanel.js b/components/manga/panels/thirdPanel.js
new file mode 100644
index 0000000..7dff76b
--- /dev/null
+++ b/components/manga/panels/thirdPanel.js
@@ -0,0 +1,171 @@
+import { useEffect, useRef, useState } from "react";
+import Image from "next/image";
+import {
+ ArrowsPointingOutIcon,
+ ArrowsPointingInIcon,
+} from "@heroicons/react/24/outline";
+import { useAniList } from "../../../lib/anilist/useAnilist";
+
+export default function ThirdPanel({
+ aniId,
+ data,
+ hasRun,
+ currentId,
+ currentChapter,
+ seekPage,
+ setSeekPage,
+ visible,
+ setVisible,
+ session,
+ scaleImg,
+ setMobileVisible,
+ mobileVisible,
+}) {
+ const [index, setIndex] = useState(0);
+ const [image, setImage] = useState(null);
+ const { markProgress } = useAniList(session);
+
+ useEffect(() => {
+ setIndex(0);
+ setSeekPage(0);
+ }, [data, currentId]);
+
+ const seekToIndex = (newIndex) => {
+ if (newIndex >= 0 && newIndex < data.length) {
+ setIndex(newIndex);
+ setSeekPage(newIndex);
+ }
+ };
+
+ useEffect(() => {
+ seekToIndex(seekPage);
+ }, [seekPage]);
+
+ useEffect(() => {
+ if (data && Array.isArray(data) && data?.length > 0) {
+ setImage([...data].reverse()); // Create a copy of data before reversing
+ }
+ }, [data]);
+
+ useEffect(() => {
+ const handleKeyDown = (event) => {
+ if (event.key === "ArrowRight") {
+ if (index > 0) {
+ setIndex(index - 1);
+ setSeekPage(index - 1);
+ }
+ } else if (event.key === "ArrowLeft") {
+ if (index < image.length - 1) {
+ setIndex(index + 1);
+ setSeekPage(index + 1);
+ }
+ if (index + 1 >= image.length - 2 && !hasRun.current) {
+ let chapterNumber = currentChapter?.number;
+ if (chapterNumber % 1 !== 0) {
+ // If it's a decimal, round it
+ chapterNumber = Math.round(chapterNumber);
+ }
+
+ markProgress(aniId, chapterNumber);
+ hasRun.current = true;
+ }
+ }
+ };
+
+ window.addEventListener("keydown", handleKeyDown);
+
+ return () => {
+ window.removeEventListener("keydown", handleKeyDown);
+ };
+ }, [index, image]);
+
+ const handleNext = () => {
+ if (index < image.length - 1) {
+ setIndex(index + 1);
+ setSeekPage(index + 1);
+ }
+ if (index + 1 >= image.length - 2 && !hasRun.current) {
+ let chapterNumber = currentChapter?.number;
+ if (chapterNumber % 1 !== 0) {
+ // If it's a decimal, round it
+ chapterNumber = Math.round(chapterNumber);
+ }
+
+ markProgress(aniId, chapterNumber);
+ hasRun.current = true;
+ }
+ };
+
+ const handlePrev = () => {
+ if (index > 0) {
+ setIndex(index - 1);
+ setSeekPage(index - 1);
+ }
+ };
+
+ return (
+ <div className="flex-grow h-screen">
+ <div className="flex items-center w-full relative group">
+ {image && Array.isArray(image) && image?.length > 0 ? (
+ <>
+ <div
+ className={`flex w-full justify-center items-center lg:scrollbar-thin scrollbar-thumb-txt scrollbar-thumb-rounded-sm overflow-x-hidden`}
+ >
+ <Image
+ key={image[image.length - index - 1]?.url}
+ width={500}
+ height={500}
+ className="w-full h-screen object-contain"
+ onClick={() => setMobileVisible(!mobileVisible)}
+ src={`https://img.moopa.live/image-proxy?url=${encodeURIComponent(
+ image[image.length - index - 1]?.url
+ )}&headers=${encodeURIComponent(
+ JSON.stringify({
+ Referer: image[image.length - index - 1]?.headers.Referer,
+ })
+ )}`}
+ alt="Manga Page"
+ style={{
+ transform: `scale(${scaleImg})`,
+ transformOrigin: "top",
+ }}
+ />
+ </div>
+ <div className="absolute w-full hidden group-hover:flex justify-between mt-4">
+ <button
+ className="px-4 py-2 bg-secondary text-white rounded-r"
+ onClick={handleNext}
+ >
+ Next
+ </button>
+ <button
+ className="px-4 py-2 bg-secondary text-white rounded-l"
+ onClick={handlePrev}
+ >
+ Previous
+ </button>
+ </div>
+ </>
+ ) : (
+ <div className="w-full flex-center h-full">
+ {data.error || "Not found"} :(
+ </div>
+ )}
+ <span className="absolute hidden group-hover:flex bottom-5 left-5 bg-secondary p-2">
+ {visible ? (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingOutIcon className="w-5 h-5" />
+ </button>
+ ) : (
+ <button type="button" onClick={() => setVisible(!visible)}>
+ <ArrowsPointingInIcon className="w-5 h-5" />
+ </button>
+ )}
+ </span>
+ <span className="absolute hidden group-hover:flex bottom-5 right-5 bg-secondary p-2">
+ Page {index + 1}/{data.length}
+ </span>
+ </div>
+ </div>
+ );
+}