diff --git a/frontend/src/lib/components/disk/StoragePanel.svelte b/frontend/src/lib/components/disk/StoragePanel.svelte index 8a7c1d8..b576e4a 100644 --- a/frontend/src/lib/components/disk/StoragePanel.svelte +++ b/frontend/src/lib/components/disk/StoragePanel.svelte @@ -37,6 +37,7 @@ const PAGE = 30; const UNDO_MS = 12_000; + const UNDO_GUARD_MS = 600; let summary = $state(null); let files = $state([]); @@ -54,6 +55,7 @@ const selected = new SvelteSet(); let token = 0; let undoTimer: ReturnType | undefined; + let undoShownAt = 0; const heaviest = $derived(files[0]?.file_size ?? 0); const chosen = $derived(files.filter((file) => selected.has(file.media_id))); @@ -151,6 +153,7 @@ hideUndo(); if (outcome.files > 0) { undo = { files: trashed, outcome }; + undoShownAt = Date.now(); undoTimer = setTimeout(hideUndo, UNDO_MS); } } @@ -185,7 +188,7 @@ } async function restoreLast() { - if (undo === null) { + if (undo === null || Date.now() - undoShownAt < UNDO_GUARD_MS) { return; } const restored = undo; @@ -290,9 +293,13 @@ Корзина - {summary.trash_files > 0 - ? `${filesLabel(summary.trash_files)} · ${formatBytes(summary.trash_bytes)}` - : "пусто"} + {#if summary.trash_files > 0} + + {filesLabel(summary.trash_files)} + · {formatBytes(summary.trash_bytes)} + {:else} + пусто + {/if} @@ -581,10 +588,21 @@ } .value { + display: flex; + gap: 0.375rem; + align-items: center; + font-size: 0.8125rem; font-variant-numeric: tabular-nums; } + .swatch { + width: 0.5rem; + height: 0.5rem; + border-radius: 50%; + background-color: rgba(var(--color-text-secondary-rgb), 0.35); + } + &:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; diff --git a/frontend/src/lib/components/disk/StorageRow.svelte b/frontend/src/lib/components/disk/StorageRow.svelte index cadf2c2..2b2d0e8 100644 --- a/frontend/src/lib/components/disk/StorageRow.svelte +++ b/frontend/src/lib/components/disk/StorageRow.svelte @@ -12,6 +12,7 @@ lead?: string; menu: Snippet; mime: string | null; + note?: string; onopen: () => void; ontoggle: () => void; refetchable: boolean; @@ -31,6 +32,7 @@ lead, sub, tail, + note, size, weight, refetchable, @@ -76,6 +78,9 @@ {` · ${tail}`} {/if} + {#if note} + {note} + {/if} {#if !refetchable} Не скачать заново {/if} @@ -211,6 +216,7 @@ } .sub, + .note, .gone { margin-top: 0.125rem; font-size: 0.8125rem; diff --git a/frontend/src/lib/components/disk/TrashPanel.svelte b/frontend/src/lib/components/disk/TrashPanel.svelte index 395b858..57f481c 100644 --- a/frontend/src/lib/components/disk/TrashPanel.svelte +++ b/frontend/src/lib/components/disk/TrashPanel.svelte @@ -178,6 +178,7 @@ kind={item.kind} lead={purgeLabel(item.purge_at)} mime={item.mime} + note={item.refs > 1 ? messagesLabel(item.refs) : undefined} onopen={() => open(index)} ontoggle={() => toggle(item.storage_key)} refetchable={item.refetchable} @@ -185,7 +186,6 @@ size={item.file_size} src={trashedUrl(item.storage_key)} sub={chatTitle(item.chat_id)} - tail={item.refs > 1 ? messagesLabel(item.refs) : undefined} weight={heaviest > 0 ? (item.file_size ?? 0) / heaviest : 0} > {#snippet menu()}