fix(frontend): shared mark on its own line in trash rows, undo ignores the trailing click, trash segment has a key
This commit is contained in:
1 parent
580927da0a
commit
c9c088ed73
3 files changed
+29
-5
No files matched your search
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
const PAGE = 30;
|
const PAGE = 30;
|
||||||
const UNDO_MS = 12_000;
|
const UNDO_MS = 12_000;
|
||||||
|
const UNDO_GUARD_MS = 600;
|
||||||
|
|
||||||
let summary = $state<StorageSummary | null>(null);
|
let summary = $state<StorageSummary | null>(null);
|
||||||
let files = $state<StorageFile[]>([]);
|
let files = $state<StorageFile[]>([]);
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
const selected = new SvelteSet<number>();
|
const selected = new SvelteSet<number>();
|
||||||
let token = 0;
|
let token = 0;
|
||||||
let undoTimer: ReturnType<typeof setTimeout> | undefined;
|
let undoTimer: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
let undoShownAt = 0;
|
||||||
|
|
||||||
const heaviest = $derived(files[0]?.file_size ?? 0);
|
const heaviest = $derived(files[0]?.file_size ?? 0);
|
||||||
const chosen = $derived(files.filter((file) => selected.has(file.media_id)));
|
const chosen = $derived(files.filter((file) => selected.has(file.media_id)));
|
||||||
@@ -151,6 +153,7 @@
|
|||||||
hideUndo();
|
hideUndo();
|
||||||
if (outcome.files > 0) {
|
if (outcome.files > 0) {
|
||||||
undo = { files: trashed, outcome };
|
undo = { files: trashed, outcome };
|
||||||
|
undoShownAt = Date.now();
|
||||||
undoTimer = setTimeout(hideUndo, UNDO_MS);
|
undoTimer = setTimeout(hideUndo, UNDO_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +188,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function restoreLast() {
|
async function restoreLast() {
|
||||||
if (undo === null) {
|
if (undo === null || Date.now() - undoShownAt < UNDO_GUARD_MS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const restored = undo;
|
const restored = undo;
|
||||||
@@ -290,9 +293,13 @@
|
|||||||
<Icon name="delete" size="1.375rem" />
|
<Icon name="delete" size="1.375rem" />
|
||||||
<span class="label">Корзина</span>
|
<span class="label">Корзина</span>
|
||||||
<span class="value">
|
<span class="value">
|
||||||
{summary.trash_files > 0
|
{#if summary.trash_files > 0}
|
||||||
? `${filesLabel(summary.trash_files)} · ${formatBytes(summary.trash_bytes)}`
|
<span class="swatch"></span>
|
||||||
: "пусто"}
|
{filesLabel(summary.trash_files)}
|
||||||
|
· {formatBytes(summary.trash_bytes)}
|
||||||
|
{:else}
|
||||||
|
пусто
|
||||||
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<Icon name="next" size="1.125rem" />
|
<Icon name="next" size="1.125rem" />
|
||||||
</button>
|
</button>
|
||||||
@@ -581,10 +588,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.375rem;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
font-variant-numeric: tabular-nums;
|
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 {
|
&:focus-visible {
|
||||||
outline: 2px solid var(--color-primary);
|
outline: 2px solid var(--color-primary);
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
lead?: string;
|
lead?: string;
|
||||||
menu: Snippet;
|
menu: Snippet;
|
||||||
mime: string | null;
|
mime: string | null;
|
||||||
|
note?: string;
|
||||||
onopen: () => void;
|
onopen: () => void;
|
||||||
ontoggle: () => void;
|
ontoggle: () => void;
|
||||||
refetchable: boolean;
|
refetchable: boolean;
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
lead,
|
lead,
|
||||||
sub,
|
sub,
|
||||||
tail,
|
tail,
|
||||||
|
note,
|
||||||
size,
|
size,
|
||||||
weight,
|
weight,
|
||||||
refetchable,
|
refetchable,
|
||||||
@@ -76,6 +78,9 @@
|
|||||||
<span class="rigid">{` · ${tail}`}</span>
|
<span class="rigid">{` · ${tail}`}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
{#if note}
|
||||||
|
<span class="note">{note}</span>
|
||||||
|
{/if}
|
||||||
{#if !refetchable}
|
{#if !refetchable}
|
||||||
<span class="gone">Не скачать заново</span>
|
<span class="gone">Не скачать заново</span>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -211,6 +216,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sub,
|
.sub,
|
||||||
|
.note,
|
||||||
.gone {
|
.gone {
|
||||||
margin-top: 0.125rem;
|
margin-top: 0.125rem;
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
|
|||||||
@@ -178,6 +178,7 @@
|
|||||||
kind={item.kind}
|
kind={item.kind}
|
||||||
lead={purgeLabel(item.purge_at)}
|
lead={purgeLabel(item.purge_at)}
|
||||||
mime={item.mime}
|
mime={item.mime}
|
||||||
|
note={item.refs > 1 ? messagesLabel(item.refs) : undefined}
|
||||||
onopen={() => open(index)}
|
onopen={() => open(index)}
|
||||||
ontoggle={() => toggle(item.storage_key)}
|
ontoggle={() => toggle(item.storage_key)}
|
||||||
refetchable={item.refetchable}
|
refetchable={item.refetchable}
|
||||||
@@ -185,7 +186,6 @@
|
|||||||
size={item.file_size}
|
size={item.file_size}
|
||||||
src={trashedUrl(item.storage_key)}
|
src={trashedUrl(item.storage_key)}
|
||||||
sub={chatTitle(item.chat_id)}
|
sub={chatTitle(item.chat_id)}
|
||||||
tail={item.refs > 1 ? messagesLabel(item.refs) : undefined}
|
|
||||||
weight={heaviest > 0 ? (item.file_size ?? 0) / heaviest : 0}
|
weight={heaviest > 0 ? (item.file_size ?? 0) / heaviest : 0}
|
||||||
>
|
>
|
||||||
{#snippet menu()}
|
{#snippet menu()}
|
||||||
|
|||||||
Reference in new issue
Block a user