"use client"; import { useState, useTransition } from "react"; import { ImageIcon, Loader2, CheckCircle2 } from "lucide-react"; import { previewRegenThumbnails, regenerateThumbnails } from "@/app/actions/maintenance"; type State = | { kind: "idle" } | { kind: "scanning" } | { kind: "preview"; total: number; missing: number; staleNames: number } | { kind: "running" } | { kind: "done"; regenerated: number; renamed: number; skipped: number; errors: number }; export function RegenThumbnailsButton() { const [state, setState] = useState({ kind: "idle" }); const [pending, start] = useTransition(); const scan = () => { setState({ kind: "scanning" }); start(async () => { const r = await previewRegenThumbnails(); setState({ kind: "preview", total: r.total, missing: r.missing, staleNames: r.staleNames }); }); }; const run = (force: boolean) => { if (state.kind !== "preview") return; const count = force ? state.total : state.missing + state.staleNames; const verb = force ? "Re-encode" : "Regenerate missing + rename stale"; if (!confirm(`${verb} for ${count} thumbnail${count === 1 ? "" : "s"}? Reads each cover from library/ when it needs encoding and renames legacy files in place when possible. Cannot be undone.`)) return; setState({ kind: "running" }); start(async () => { const r = await regenerateThumbnails({ force }); setState({ kind: "done", ...r }); }); }; return (
Regenerate Thumbnails
Rebuild the grid-preview WebP files in data/thumbs/ from the originals in library/, and rename legacy <sha>.webp files to the new <CODE>-<sha>.webp format. Use this if your thumbs folder was wiped, restored from an incomplete backup, or you upgraded to the code-prefix naming.
{state.kind === "preview" && (
{state.missing} missing on disk {" · "} {state.staleNames} with legacy filename {" · "}of {state.total} total
)} {state.kind === "done" && (
Encoded {state.regenerated} · renamed {state.renamed} · skipped {state.skipped} {state.errors > 0 && · {state.errors} error{state.errors === 1 ? "" : "s"}}
)}
{state.kind === "idle" && ( )} {(state.kind === "scanning" || state.kind === "running") && ( {state.kind === "scanning" ? "Scanning…" : "Regenerating…"} )} {state.kind === "preview" && ( <> {(state.missing > 0 || state.staleNames > 0) && ( )} )} {state.kind === "done" && ( )}
); }