diff options
| author | Factiven <[email protected]> | 2023-12-24 13:03:54 +0700 |
|---|---|---|
| committer | Factiven <[email protected]> | 2023-12-24 13:03:54 +0700 |
| commit | 50a0f0240d7fef133eb5acc1bea2b1168b08e9db (patch) | |
| tree | 307e09e505580415a58d64b5fc3580e9235869f1 /components/anime | |
| parent | Update README.md (#104) (diff) | |
| download | moopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.tar.xz moopa-50a0f0240d7fef133eb5acc1bea2b1168b08e9db.zip | |
migrate to typescript
Diffstat (limited to 'components/anime')
| -rw-r--r-- | components/anime/episode.js | 156 | ||||
| -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.js | 22 | ||||
| -rw-r--r-- | components/anime/viewMode/thumbnailOnly.js | 16 | ||||
| -rw-r--r-- | components/anime/viewSelector.js | 20 |
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" |