Upload updates
This commit is contained in:
@@ -15,6 +15,7 @@ import { ConfirmDialog } from "@/components/ConfirmDialog";
|
||||
import { StatusFooter } from "@/components/StatusFooter";
|
||||
import { StatusPill } from "@/components/StatusPill";
|
||||
import { Toasts } from "@/components/Toasts";
|
||||
import { UploadIndicator } from "@/components/UploadIndicator";
|
||||
import { api } from "@/lib/api";
|
||||
import { hasBackend } from "@/lib/backend";
|
||||
import { cn } from "@/lib/cn";
|
||||
@@ -153,6 +154,7 @@ export function AppShell() {
|
||||
<div className="ml-auto flex items-center gap-3">
|
||||
{backend ? (
|
||||
<>
|
||||
<UploadIndicator />
|
||||
<StatusPill status={status} />
|
||||
{user ? (
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { cn } from "@/lib/cn";
|
||||
import { useUploadStatus } from "@/lib/uploadStatus";
|
||||
|
||||
const PHASE_LABELS: Record<string, string> = {
|
||||
md5: "e621 MD5",
|
||||
visual: "Visual similarity",
|
||||
iqdb: "IQDB",
|
||||
};
|
||||
|
||||
/**
|
||||
* Shell-wide progress for the server-side upload pipeline.
|
||||
*
|
||||
* Staged uploads keep processing after the Upload page is closed, so this
|
||||
* pill is the "leave and keep an eye on it" view: it lives in the header on
|
||||
* every page and links back to the board.
|
||||
*/
|
||||
export function UploadIndicator() {
|
||||
const { data: status } = useUploadStatus();
|
||||
if (!status || !status.active) return null;
|
||||
|
||||
const total = Math.max(status.total, status.processed + status.failed);
|
||||
const done = status.processed + status.failed;
|
||||
const percent = total > 0 ? Math.min(100, Math.round((done / total) * 100)) : 0;
|
||||
const broken = status.status === "paused" || status.status === "error";
|
||||
const label =
|
||||
status.status === "paused"
|
||||
? "uploads paused"
|
||||
: status.status === "error"
|
||||
? "uploads failed"
|
||||
: (PHASE_LABELS[status.phase] ?? "processing uploads");
|
||||
const count = total > 0 ? `${done}/${total}` : `${status.outstanding} left`;
|
||||
|
||||
return (
|
||||
<Link
|
||||
to="/upload"
|
||||
title={status.error || "Staged uploads are being processed in the background"}
|
||||
className={cn(
|
||||
"flex items-center gap-2 rounded-md border px-2 py-1 font-mono text-[10px] transition",
|
||||
broken
|
||||
? "border-ctp-red/40 text-ctp-red hover:bg-ctp-red/10"
|
||||
: "border-ctp-surface1 text-ctp-subtext0 hover:bg-ctp-surface0 hover:text-ctp-text",
|
||||
)}
|
||||
>
|
||||
<span className="hidden sm:inline">{label}</span>
|
||||
<span>{count}</span>
|
||||
<span className="h-1 w-12 overflow-hidden rounded-full bg-ctp-surface0">
|
||||
<span
|
||||
className={cn("block h-full", broken ? "bg-ctp-red" : "bg-ctp-teal")}
|
||||
style={{ width: `${percent}%` }}
|
||||
/>
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user