"use client"; import JSZip from "jszip"; import { useEffect, useState } from "react"; import { z } from "zod"; import { Schema_File } from "~/schema"; import { cn } from "~/utils"; import Icon from "~/components/Icon"; import { Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "~/components/ui/carousel"; import useMediaQuery from "~/hooks/useMediaQuery"; import { CreateDownloadToken } from "./actions"; type Props = { file: z.infer; }; export default function PreviewManga({ file }: Props) { const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const [images, setImages] = useState<{ name: string; blob: string }[]>([]); const [currentImage, setCurrentImage] = useState(1); const [viewSize, setViewSize] = useState<"fit" | "full">("fit"); const [api, setApi] = useState(); const isDesktop = useMediaQuery("(min-width: 768px)"); useEffect(() => { (async () => { try { if (!file.encryptedWebContentLink) { setError("No video to preview"); return; } const token = await CreateDownloadToken(); const manga = await fetch( `/api/download/${file.encryptedId}?token=${token}`, ); const archiveBlob = await manga.blob(); const zipData = await JSZip.loadAsync(archiveBlob); const tempArray: { name: string; blob: string }[] = []; const files = Object.values(zipData.files); for (const file of files) { const f = zipData.file(file.name); if (!f) continue; const blob = await f.async("blob"); const reader = new FileReader(); reader.onload = () => { setImages((prev) => { const exist = prev.find((p) => p.name === file.name); if (exist) return prev; return [ ...prev, { name: file.name, blob: reader.result as string }, ]; }); }; reader.readAsDataURL(blob); } } catch (error) { const e = error as Error; console.error(e); setError(e.message); } finally { setLoading(false); } })(); }, [file]); useEffect(() => { if (!api) return; api.on("select", (embla, e) => { const index = embla.selectedScrollSnap(); setCurrentImage(index + 1); }); }, [api]); return (
{loading ? (

Loading manga content...

) : error ? (
{error}
) : (
{images.map((image, index) => ( {`${image.name} {image.name} ))} {isDesktop ? ( <> ) : null}
{currentImage}/{images.length}
setViewSize(viewSize === "fit" ? "full" : "fit")} >
)}
); }