aboutsummaryrefslogtreecommitdiff
path: root/components/anime
diff options
context:
space:
mode:
authorFactiven <[email protected]>2023-12-24 13:03:54 +0700
committerFactiven <[email protected]>2023-12-24 13:03:54 +0700
commit50a0f0240d7fef133eb5acc1bea2b1168b08e9db (patch)
tree307e09e505580415a58d64b5fc3580e9235869f1 /components/anime
parentUpdate README.md (#104) (diff)
downloadmoopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.tar.xz
moopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.zip
migrate to typescript
Diffstat (limited to 'components/anime')
-rw-r--r--components/anime/episode.js156
-rw-r--r--components/anime/mobile/reused/infoChip.tsx (renamed from components/anime/mobile/reused/infoChip.js)23
-rw-r--r--components/anime/mobile/topSection.tsx (renamed from components/anime/mobile/topSection.js)325
-rw-r--r--components/anime/viewMode/thumbnailDetail.js22
-rw-r--r--components/anime/viewMode/thumbnailOnly.js16
-rw-r--r--components/anime/viewSelector.js20
6 files changed, 300 insertions, 262 deletions
diff --git a/components/anime/episode.js b/components/anime/episode.js
index 3650944..f35df10 100644
--- a/components/anime/episode.js
+++ b/components/anime/episode.js
@@ -6,29 +6,45 @@ import ThumbnailDetail from "./viewMode/thumbnailDetail";
import ListMode from "./viewMode/listMode";
import { toast } from "sonner";
-function allProvider(response, setMapProviders, setProviderId) {
- const getMap = response.find((i) => i?.map === true);
- let allProvider = response;
+const ITEMS_PER_PAGE = 13;
+const DEFAULT_VIEW = 3;
- if (getMap) {
- allProvider = response.filter((i) => {
+const fetchEpisodes = async (info, isDub, refresh = false) => {
+ const response = await fetch(
+ `/api/v2/episode/${info.id}?releasing=${
+ info.status === "RELEASING" ? "true" : "false"
+ }${isDub ? "&dub=true" : ""}${refresh ? "&refresh=true" : ""}`
+ ).then((res) => res.json());
+
+ const providers = filterProviders(response);
+
+ return providers;
+};
+
+const filterProviders = (response) => {
+ const providersWithMap = response.find((i) => i?.map === true);
+ let providers = response;
+
+ if (providersWithMap) {
+ providers = response.filter((i) => {
if (i?.providerId === "gogoanime" && i?.map !== true) {
return null;
}
return i;
});
- setMapProviders(getMap?.episodes);
}
- if (allProvider.length > 0) {
- const defaultProvider = allProvider.find(
+ return providers;
+};
+
+const setDefaultProvider = (providers, setProviderId) => {
+ if (providers.length > 0) {
+ const defaultProvider = providers.find(
(x) => x.providerId === "gogoanime" || x.providerId === "9anime"
);
- setProviderId(defaultProvider?.providerId || allProvider[0].providerId); // set to first provider id
+ setProviderId(defaultProvider?.providerId || providers[0].providerId);
}
-
- return allProvider;
-}
+};
export default function AnimeEpisode({
info,
@@ -48,20 +64,13 @@ export default function AnimeEpisode({
const [isDub, setIsDub] = useState(false);
const [providers, setProviders] = useState(null);
- const [mapProviders, setMapProviders] = useState(null);
useEffect(() => {
setLoading(true);
const fetchData = async () => {
- const response = await fetch(
- `/api/v2/episode/${info.id}?releasing=${
- info.status === "RELEASING" ? "true" : "false"
- }${isDub ? "&dub=true" : ""}`
- ).then((res) => res.json());
-
- const providers = allProvider(response, setMapProviders, setProviderId);
-
- setView(Number(localStorage.getItem("view")) || 3);
+ const providers = await fetchEpisodes(info, isDub);
+ setDefaultProvider(providers, setProviderId);
+ setView(Number(localStorage.getItem("view")) || DEFAULT_VIEW);
setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings")));
setProviders(providers);
setLoading(false);
@@ -71,20 +80,16 @@ export default function AnimeEpisode({
return () => {
setCurrentPage(1);
setProviders(null);
- setMapProviders(null);
};
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [info.id, isDub]);
+ }, [info.id, isDub]); // eslint-disable-next-line react-hooks/exhaustive-deps
const episodes =
- providers
- ?.find((provider) => provider.providerId === providerId)
- ?.episodes?.slice(0, mapProviders?.length) || [];
+ providers?.find((provider) => provider.providerId === providerId)
+ ?.episodes || [];
const lastEpisodeIndex = currentPage * itemsPerPage;
const firstEpisodeIndex = lastEpisodeIndex - itemsPerPage;
- let currentEpisodes = episodes.slice(firstEpisodeIndex, lastEpisodeIndex);
+ let currentEpisodes = episodes?.slice(firstEpisodeIndex, lastEpisodeIndex);
const totalPages = Math.ceil(episodes.length / itemsPerPage);
@@ -98,9 +103,10 @@ export default function AnimeEpisode({
useEffect(() => {
if (
- !mapProviders ||
- mapProviders?.every(
+ !currentEpisodes ||
+ currentEpisodes?.every(
(item) =>
+ // item?.img?.includes("null") ||
item?.img?.includes("https://s4.anilist.co/") ||
item?.image?.includes("https://s4.anilist.co/") ||
item?.img === null
@@ -173,67 +179,13 @@ export default function AnimeEpisode({
setLoading(true);
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(async () => {
- const res = await fetch(
- `/api/v2/episode/${info.id}?releasing=${
- info.status === "RELEASING" ? "true" : "false"
- }${isDub ? "&dub=true" : ""}&refresh=true`
- );
- if (!res.ok) {
- const json = await res.json();
- if (res.status === 429) {
- toast.error(json.error);
- const resp = await fetch(
- `/api/v2/episode/${info.id}?releasing=${
- info.status === "RELEASING" ? "true" : "false"
- }${isDub ? "&dub=true" : ""}`
- ).then((res) => res.json());
-
- if (resp) {
- const providers = allProvider(
- resp,
- setMapProviders,
- setProviderId
- );
- setProviders(providers);
- }
- } else {
- toast.error("Something went wrong");
- setProviders([]);
- }
- setLoading(false);
- } else {
- const remainingRequests = res.headers.get("X-RateLimit-Remaining");
- toast.success("Remaining requests " + remainingRequests);
-
- const data = await res.json();
- const getMap = data.find((i) => i?.map === true) || data[0];
- let allProvider = data;
-
- if (getMap) {
- allProvider = data.filter((i) => {
- if (i?.providerId === "gogoanime" && i?.map !== true) {
- return null;
- }
- return i;
- });
- setMapProviders(getMap?.episodes);
- }
-
- if (allProvider.length > 0) {
- const defaultProvider = allProvider.find(
- (x) => x.providerId === "gogoanime" || x.providerId === "9anime"
- );
- setProviderId(
- defaultProvider?.providerId || allProvider[0].providerId
- ); // set to first provider id
- }
-
- setView(Number(localStorage.getItem("view")) || 3);
- setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings")));
- setProviders(allProvider);
- setLoading(false);
- }
- }, 1000);
+ const providers = await fetchEpisodes(info, isDub, true);
+ setDefaultProvider(providers, setProviderId);
+ setView(Number(localStorage.getItem("view")) || DEFAULT_VIEW);
+ setArtStorage(JSON.parse(localStorage.getItem("artplayer_settings")));
+ setProviders(providers);
+ setLoading(false);
+ }, 5000);
} catch (err) {
console.log(err);
toast.error("Something went wrong");
@@ -257,7 +209,7 @@ export default function AnimeEpisode({
onClick={() => {
handleRefresh();
setProviders(null);
- setMapProviders(null);
+ // setMapProviders(null);
}}
className="relative flex flex-col items-center w-5 h-5 group"
>
@@ -376,7 +328,7 @@ export default function AnimeEpisode({
view={view}
setView={setView}
episode={currentEpisodes}
- map={mapProviders}
+ // map={mapProviders}
/>
</div>
</div>
@@ -395,9 +347,9 @@ export default function AnimeEpisode({
{Array.isArray(providers) ? (
providers.length > 0 ? (
currentEpisodes.map((episode, index) => {
- const mapData = mapProviders?.find(
- (i) => i.number === episode.number
- );
+ // const mapData = mapProviders?.find(
+ // (i) => i.number === episode.number
+ // );
return (
<Fragment key={index}>
@@ -406,7 +358,7 @@ export default function AnimeEpisode({
key={index}
index={index}
info={info}
- image={mapData?.img || mapData?.image}
+ // image={mapData?.img || mapData?.image}
providerId={providerId}
episode={episode}
artStorage={artStorage}
@@ -417,9 +369,9 @@ export default function AnimeEpisode({
{view === 2 && (
<ThumbnailDetail
key={index}
- image={mapData?.img || mapData?.image}
- title={mapData?.title}
- description={mapData?.description}
+ // image={mapData?.img || mapData?.image}
+ // title={mapData?.title}
+ // description={mapData?.description}
index={index}
epi={episode}
provider={providerId}
diff --git a/components/anime/mobile/reused/infoChip.js b/components/anime/mobile/reused/infoChip.tsx
index 41def85..80ebf83 100644
--- a/components/anime/mobile/reused/infoChip.js
+++ b/components/anime/mobile/reused/infoChip.tsx
@@ -1,7 +1,20 @@
-import React from "react";
-import { getFormat } from "../../../../utils/getFormat";
+import React, { CSSProperties, FC } from "react";
+import { getFormat } from "@/utils/getFormat";
-export default function InfoChip({ info, color, className }) {
+interface Info {
+ episodes?: number;
+ averageScore?: number;
+ format?: string;
+ status?: string;
+}
+
+interface InfoChipProps {
+ info: Info;
+ color: any;
+ className: string;
+}
+
+const InfoChip: FC<InfoChipProps> = ({ info, color, className }) => {
return (
<div
className={`flex-wrap w-full justify-start md:pt-1 gap-4 ${className}`}
@@ -40,4 +53,6 @@ export default function InfoChip({ info, color, className }) {
)}
</div>
);
-}
+};
+
+export default InfoChip;
diff --git a/components/anime/mobile/topSection.js b/components/anime/mobile/topSection.tsx
index 6780da5..2d28c66 100644
--- a/components/anime/mobile/topSection.js
+++ b/components/anime/mobile/topSection.tsx
@@ -11,26 +11,36 @@ import { convertSecondsToTime } from "@/utils/getTimes";
import Link from "next/link";
import InfoChip from "./reused/infoChip";
import Description from "./reused/description";
-import { NewNavbar } from "@/components/shared/NavBar";
+import Skeleton from "react-loading-skeleton";
+import { AniListInfoTypes } from "types/info/AnilistInfoTypes";
+
+type DetailTopProps = {
+ info?: AniListInfoTypes | null;
+ statuses?: any;
+ handleOpen: () => void;
+ watchUrl: string | undefined;
+ progress?: number;
+ color?: string | null;
+};
export default function DetailTop({
info,
- statuses,
+ statuses = undefined,
handleOpen,
watchUrl,
progress,
color,
-}) {
+}: DetailTopProps) {
const router = useRouter();
const [readMore, setReadMore] = useState(false);
const [showAll, setShowAll] = useState(false);
- const isAnime = info.type === "ANIME";
+ const isAnime = info?.type === "ANIME";
useEffect(() => {
setReadMore(false);
- }, [info.id]);
+ }, [info?.id]);
const handleShareClick = async () => {
try {
@@ -51,78 +61,150 @@ export default function DetailTop({
return (
<div className="gap-6 w-full px-3 pt-4 md:pt-10 flex flex-col items-center justify-center">
- <NewNavbar info={info} />
-
{/* MAIN */}
<div className="flex flex-col md:flex-row w-full items-center md:items-end gap-5 pt-12">
<div className="shrink-0 w-[180px] h-[250px] rounded overflow-hidden">
- <img
- src={info?.coverImage?.extraLarge || info?.coverImage}
- alt="poster anime"
- width={300}
- height={300}
- className="w-full h-full object-cover"
- />
+ {info ? (
+ <img
+ src={
+ info?.coverImage?.extraLarge?.toString() ??
+ info?.coverImage?.toString()
+ }
+ alt="poster anime"
+ width={300}
+ height={300}
+ className="w-full h-full object-cover"
+ />
+ ) : (
+ <Skeleton className="h-full" />
+ )}
</div>
<div className="flex flex-col gap-4 items-center md:items-start justify-end w-full">
- <div className="flex flex-col gap-1 text-center md:text-start">
+ <div className="flex flex-col gap-1 text-center md:text-start w-full">
<h3 className="font-karla text-lg capitalize leading-none">
{info?.season?.toLowerCase() || getMonth(info?.startDate?.month)}{" "}
- {info.seasonYear || info?.startDate?.year}
+ {info?.seasonYear || info?.startDate?.year}
+ {!info && <Skeleton height={14} width={140} />}
</h3>
<h1 className="font-outfit font-extrabold text-2xl md:text-4xl line-clamp-2 text-white">
{info?.title?.romaji || info?.title?.english}
+ {!info && <Skeleton height={35} width={340} className="" />}
</h1>
<h2 className="font-karla line-clamp-1 text-sm md:text-lg md:pb-2 font-light text-white/70">
- {info.title?.english}
+ {info?.title?.english}
</h2>
- <InfoChip info={info} color={color} className="hidden md:flex" />
- {info?.description && (
- <Description
- info={info}
- readMore={readMore}
- setReadMore={setReadMore}
- className="md:block hidden"
- />
+ {info && (
+ <InfoChip info={info} color={color} className="hidden md:flex" />
+ )}
+ {info ? (
+ info?.description && (
+ <Description
+ info={info}
+ readMore={readMore}
+ setReadMore={setReadMore}
+ className="md:block hidden"
+ />
+ )
+ ) : (
+ <div className="w-full md:px-0 md:block hidden">
+ <Skeleton className="h-[80px] w-[700px]" />
+ </div>
)}
</div>
</div>
</div>
<div className="hidden md:flex gap-5 items-center justify-start w-full">
- <button
- type="button"
- onClick={() => router.push(watchUrl)}
- className={`${
- !watchUrl ? "opacity-30 pointer-events-none" : ""
- } w-[180px] flex-center text-lg font-karla font-semibold gap-2 border-black border-opacity-10 text-black rounded-full py-1 px-4 bg-white hover:opacity-80`}
- >
- {isAnime ? (
- <PlayIcon className="w-5 h-5" />
- ) : (
- <BookOpenIcon className="w-5 h-5" />
- )}
- {progress > 0 ? (
- statuses?.value === "COMPLETED" ? (
- isAnime ? (
- "Rewatch"
+ {info ? (
+ <button
+ type="button"
+ onClick={() => router.push(watchUrl ?? "#")}
+ className={`${
+ !watchUrl ? "opacity-30 pointer-events-none" : ""
+ } w-[180px] flex-center text-lg font-karla font-semibold gap-2 border-black border-opacity-10 text-black rounded-full py-1 px-4 bg-white hover:opacity-80`}
+ >
+ {isAnime ? (
+ <PlayIcon className="w-5 h-5" />
+ ) : (
+ <BookOpenIcon className="w-5 h-5" />
+ )}
+ {progress && progress > 0 ? (
+ statuses?.value === "COMPLETED" ? (
+ isAnime ? (
+ "Rewatch"
+ ) : (
+ "Reread"
+ )
+ ) : !watchUrl && info?.nextAiringEpisode ? (
+ <span>
+ {convertSecondsToTime(info.nextAiringEpisode.timeUntilAiring)}{" "}
+ </span>
) : (
- "Reread"
+ "Continue"
)
- ) : !watchUrl && info?.nextAiringEpisode ? (
- <span>
- {convertSecondsToTime(info.nextAiringEpisode.timeUntilAiring)}{" "}
- </span>
+ ) : isAnime ? (
+ "Watch Now"
) : (
- "Continue"
- )
- ) : isAnime ? (
- "Watch Now"
+ "Read Now"
+ )}
+ </button>
+ ) : (
+ <div className="h-10 w-[180px] bg-secondary flex-center text-lg font-karla font-semibold gap-2 border-black border-opacity-10 text-black rounded-full" />
+ )}
+ <div className="flex gap-2">
+ {info ? (
+ <button
+ type="button"
+ className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
+ onClick={() => handleOpen()}
+ >
+ <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
+ Add to List
+ </span>
+ <PlusIcon className="w-5 h-5" />
+ </button>
) : (
- "Read Now"
+ <div className="w-10 h-10 bg-secondary rounded-full" />
)}
- </button>
- <div className="flex gap-2">
+ {info ? (
+ <button
+ type="button"
+ className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
+ onClick={handleShareClick}
+ >
+ <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
+ Share {isAnime ? "Anime" : "Manga"}
+ </span>
+ <ShareIcon className="w-5 h-5" />
+ </button>
+ ) : (
+ <div className="w-10 h-10 bg-secondary rounded-full" />
+ )}
+ {info ? (
+ <a
+ target="_blank"
+ rel="noopener noreferrer"
+ href={`https://anilist.co/${info.type.toLowerCase()}/${info.id}`}
+ className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
+ >
+ <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
+ See on AniList
+ </span>
+ <Image
+ src="/svg/anilist-icon.svg"
+ alt="anilist_icon"
+ width={20}
+ height={20}
+ />
+ </a>
+ ) : (
+ <div className="w-10 h-10 bg-secondary rounded-full" />
+ )}
+ </div>
+ </div>
+
+ <div className="md:hidden flex gap-2 items-center justify-center w-[90%]">
+ {info ? (
<button
type="button"
className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
@@ -133,6 +215,46 @@ export default function DetailTop({
</span>
<PlusIcon className="w-5 h-5" />
</button>
+ ) : (
+ <div className="w-10 h-10 bg-secondary rounded-full" />
+ )}
+ {info ? (
+ <button
+ type="button"
+ onClick={() => router.push(watchUrl ?? "#")}
+ className={`${
+ !watchUrl ? "opacity-30 pointer-events-none" : ""
+ } flex items-center text-lg font-karla font-semibold gap-1 border-black border-opacity-10 text-black rounded-full py-2 px-4 bg-white`}
+ >
+ {isAnime ? (
+ <PlayIcon className="w-5 h-5" />
+ ) : (
+ <BookOpenIcon className="w-5 h-5" />
+ )}
+ {progress && progress > 0 ? (
+ statuses?.value === "COMPLETED" ? (
+ isAnime ? (
+ "Rewatch"
+ ) : (
+ "Reread"
+ )
+ ) : !watchUrl && info?.nextAiringEpisode ? (
+ <span>
+ {convertSecondsToTime(info.nextAiringEpisode.timeUntilAiring)}{" "}
+ </span>
+ ) : (
+ "Continue"
+ )
+ ) : isAnime ? (
+ "Watch Now"
+ ) : (
+ "Read Now"
+ )}
+ </button>
+ ) : (
+ <div className="h-10 w-32 bg-secondary flex-center text-lg font-karla font-semibold gap-2 border-black border-opacity-10 text-black rounded-full" />
+ )}
+ {info ? (
<button
type="button"
className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
@@ -143,81 +265,12 @@ export default function DetailTop({
</span>
<ShareIcon className="w-5 h-5" />
</button>
- <a
- target="_blank"
- rel="noopener noreferrer"
- href={`https://anilist.co/${info.type.toLowerCase()}/${info.id}`}
- className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
- >
- <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
- See on AniList
- </span>
- <Image
- src="/svg/anilist-icon.svg"
- alt="anilist_icon"
- width={20}
- height={20}
- />
- </a>
- </div>
+ ) : (
+ <div className="w-10 h-10 bg-secondary rounded-full" />
+ )}
</div>
- <div className="md:hidden flex gap-2 items-center justify-center w-[90%]">
- <button
- type="button"
- className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
- onClick={() => handleOpen()}
- >
- <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
- Add to List
- </span>
- <PlusIcon className="w-5 h-5" />
- </button>
- <button
- type="button"
- onClick={() => router.push(watchUrl)}
- className={`${
- !watchUrl ? "opacity-30 pointer-events-none" : ""
- } flex items-center text-lg font-karla font-semibold gap-1 border-black border-opacity-10 text-black rounded-full py-2 px-4 bg-white`}
- >
- {isAnime ? (
- <PlayIcon className="w-5 h-5" />
- ) : (
- <BookOpenIcon className="w-5 h-5" />
- )}
- {progress > 0 ? (
- statuses?.value === "COMPLETED" ? (
- isAnime ? (
- "Rewatch"
- ) : (
- "Reread"
- )
- ) : !watchUrl && info?.nextAiringEpisode ? (
- <span>
- {convertSecondsToTime(info.nextAiringEpisode.timeUntilAiring)}{" "}
- </span>
- ) : (
- "Continue"
- )
- ) : isAnime ? (
- "Watch Now"
- ) : (
- "Read Now"
- )}
- </button>
- <button
- type="button"
- className="flex-center group relative w-10 h-10 bg-secondary rounded-full"
- onClick={handleShareClick}
- >
- <span className="absolute pointer-events-none z-40 opacity-0 -translate-y-8 group-hover:-translate-y-10 group-hover:opacity-100 font-karla shadow-tersier shadow-md whitespace-nowrap bg-secondary px-2 py-1 rounded transition-all duration-200 ease-out">
- Share {isAnime ? "Anime" : "Manga"}
- </span>
- <ShareIcon className="w-5 h-5" />
- </button>
- </div>
-
- {info.nextAiringEpisode?.timeUntilAiring && (
+ {info && info.nextAiringEpisode?.timeUntilAiring && (
<p className="md:hidden">
Episode {info.nextAiringEpisode.episode} in{" "}
<span className="font-bold">
@@ -226,7 +279,7 @@ export default function DetailTop({
</p>
)}
- {info?.description && (
+ {info && info?.description && (
<Description
info={info}
readMore={readMore}
@@ -235,13 +288,15 @@ export default function DetailTop({
/>
)}
- <InfoChip
- info={info}
- color={color}
- className={`${readMore ? "flex" : "hidden"} md:hidden`}
- />
+ {info && (
+ <InfoChip
+ info={info}
+ color={color}
+ className={`${readMore ? "flex" : "hidden"} md:hidden`}
+ />
+ )}
- {info?.relations?.edges?.length > 0 && (
+ {info && info?.relations?.edges?.length > 0 && (
<div className="w-screen md:w-full">
<div className="flex justify-between items-center p-3 md:p-0">
{info?.relations?.edges?.length > 0 && (
@@ -288,7 +343,7 @@ export default function DetailTop({
<div className="w-[90px] bg-image rounded-l-md shrink-0">
<Image
src={rel.coverImage.extraLarge}
- alt={rel.id}
+ alt={rel.id.toString()}
height={500}
width={500}
className="object-cover h-full w-full shrink-0 rounded-l-md"
@@ -314,7 +369,7 @@ export default function DetailTop({
);
}
-function getMonth(month) {
+function getMonth(month: number | undefined) {
if (!month) return "";
const formattedMonth = new Date(0, month).toLocaleString("default", {
month: "long",
diff --git a/components/anime/viewMode/thumbnailDetail.js b/components/anime/viewMode/thumbnailDetail.js
index d8cbfcc..f955fec 100644
--- a/components/anime/viewMode/thumbnailDetail.js
+++ b/components/anime/viewMode/thumbnailDetail.js
@@ -1,3 +1,4 @@
+import { parseImageProxy } from "@/utils/imageUtils";
import Image from "next/image";
import Link from "next/link";
@@ -5,7 +6,7 @@ export default function ThumbnailDetail({
index,
epi,
info,
- image,
+ // image,
title,
description,
provider,
@@ -18,10 +19,10 @@ export default function ThumbnailDetail({
let prog = (time / duration) * 100;
if (prog > 90) prog = 100;
- const parsedImage = image
- ? image?.includes("null")
+ const parsedImage = epi?.img
+ ? epi?.img?.includes("null")
? info.coverImage?.extraLarge
- : image
+ : epi?.img
: info.coverImage?.extraLarge || null;
return (
@@ -36,7 +37,12 @@ export default function ThumbnailDetail({
<div className="relative">
{parsedImage && (
<Image
- src={parsedImage || ""}
+ src={
+ parseImageProxy(
+ parsedImage,
+ provider === "animepahe" ? "https://animepahe.ru" : undefined
+ ) || ""
+ }
alt={`Episode ${epi?.number} Thumbnail`}
width={520}
height={236}
@@ -74,11 +80,11 @@ export default function ThumbnailDetail({
className={`w-[70%] h-full select-none p-4 flex flex-col justify-center gap-3`}
>
<h1 className="font-karla font-bold text-base lg:text-lg xl:text-xl italic line-clamp-1">
- {title || `Episode ${epi?.number || 0}`}
+ {epi?.title || `Episode ${epi?.number || 0}`}
</h1>
- {description && (
+ {epi?.description && (
<p className="line-clamp-2 text-xs lg:text-md xl:text-lg italic font-outfit font-extralight">
- {description}
+ {epi?.description}
</p>
)}
</div>
diff --git a/components/anime/viewMode/thumbnailOnly.js b/components/anime/viewMode/thumbnailOnly.js
index c7fe674..06a92f5 100644
--- a/components/anime/viewMode/thumbnailOnly.js
+++ b/components/anime/viewMode/thumbnailOnly.js
@@ -1,9 +1,10 @@
import Image from "next/image";
import Link from "next/link";
+import { parseImageProxy } from "../../../utils/imageUtils";
export default function ThumbnailOnly({
info,
- image,
+ // image,
providerId,
episode,
artStorage,
@@ -15,10 +16,10 @@ export default function ThumbnailOnly({
let prog = (time / duration) * 100;
if (prog > 90) prog = 100;
- const parsedImage = image
- ? image?.includes("null")
+ const parsedImage = episode?.img
+ ? episode?.img?.includes("null")
? info.coverImage?.extraLarge
- : image
+ : episode?.img
: info.coverImage?.extraLarge || null;
return (
<Link
@@ -45,7 +46,12 @@ export default function ThumbnailOnly({
{/* <div className="absolute inset-0 bg-black z-30 opacity-20" /> */}
{parsedImage && (
<Image
- src={parsedImage || ""}
+ src={
+ parseImageProxy(
+ parsedImage,
+ providerId === "animepahe" ? "https://animepahe.ru" : undefined
+ ) || ""
+ }
alt={`Episode ${episode?.number} Thumbnail`}
width={500}
height={500}
diff --git a/components/anime/viewSelector.js b/components/anime/viewSelector.js
index baa13b2..c2ca327 100644
--- a/components/anime/viewSelector.js
+++ b/components/anime/viewSelector.js
@@ -4,13 +4,14 @@ export default function ViewSelector({ view, setView, episode, map }) {
<div
className={
episode?.length > 0
- ? map?.every(
+ ? episode?.every(
(item) =>
item?.img === null ||
+ item?.img?.includes("null") ||
item?.img?.includes("https://s4.anilist.co/") ||
item?.image?.includes("https://s4.anilist.co/") ||
item.title === null
- ) || !map
+ ) || !episode
? "pointer-events-none"
: "cursor-pointer"
: "pointer-events-none"
@@ -32,13 +33,14 @@ export default function ViewSelector({ view, setView, episode, map }) {
height="20"
className={`${
episode?.length > 0
- ? map?.every(
+ ? episode?.every(
(item) =>
item?.img === null ||
+ item?.img?.includes("null") ||
item?.img?.includes("https://s4.anilist.co/") ||
item?.image?.includes("https://s4.anilist.co/") ||
item.title === null
- ) || !map
+ ) || !episode
? "fill-[#1c1c22]"
: view === 1
? "fill-action"
@@ -52,13 +54,14 @@ export default function ViewSelector({ view, setView, episode, map }) {
<div
className={
episode?.length > 0
- ? map?.every(
+ ? episode?.every(
(item) =>
item?.img === null ||
+ item?.img?.includes("null") ||
item?.img?.includes("https://s4.anilist.co/") ||
item?.image?.includes("https://s4.anilist.co/") ||
item.title === null
- ) || !map
+ ) || !episode
? "pointer-events-none"
: "cursor-pointer"
: "pointer-events-none"
@@ -75,13 +78,14 @@ export default function ViewSelector({ view, setView, episode, map }) {
fill="none"
className={`${
episode?.length > 0
- ? map?.every(
+ ? episode?.every(
(item) =>
item?.img === null ||
+ item?.img?.includes("null") ||
item?.img?.includes("https://s4.anilist.co/") ||
item?.image?.includes("https://s4.anilist.co/") ||
item.title === null
- ) || !map
+ ) || !episode
? "fill-[#1c1c22]"
: view === 2
? "fill-action"