Toast action results and confirm destructive actions in one dialog

Inline banners and per-row status text reported action results all over
the app; they are replaced by a small toast stack (bottom-right, Level 3
floating well styling) that only speaks for actions: successes fade,
errors stay until dismissed, and form-field validation stays inline.

Destructive actions no longer use bespoke inline confirm steps (the
library detail's Confirm delete button) or fire immediately (duplicate
copies/items, delete page selections, temp cleanup, upload discard, job
cancellation): they all go through one promise-based confirm dialog
(confirmAction) with a danger variant, Escape/backdrop to cancel.
This commit is contained in:
2026-09-17 22:19:54 -05:00
parent 1053e3ee55
commit e97c3b9da0
21 changed files with 430 additions and 287 deletions
@@ -19,6 +19,7 @@ import {
type OptimizeOptions,
} from "./types";
import { useOptimizer } from "./useOptimizer";
import { toast } from "@/store/toasts";
const DIMENSION_CHOICES: { value: number | null; label: string }[] = [
{ value: null, label: "Keep original" },
@@ -248,12 +249,17 @@ export function OptimizeModal({
if (result?.storageKey) void deleteStoredFile(result.storageKey);
setApplied(true);
setApplyError(null);
toast.ok(`${item.j_id} optimized.`);
void queryClient.invalidateQueries({ queryKey: ["file", item.j_id] });
void queryClient.invalidateQueries({ queryKey: ["files"] });
void queryClient.invalidateQueries({ queryKey: ["storage"] });
void queryClient.invalidateQueries({ queryKey: ["duplicates-md5"] });
},
onError: (err) => setApplyError(errorMessage(err)),
onError: (err) => {
const message = errorMessage(err);
setApplyError(message);
toast.error(message);
},
});
const originalSize = item.size;