feat(frontend): a finished action answers on the button that was pressed instead of a toast

This commit is contained in:
hh committed 2026-10-19 06:07:54 +00:00
1 parent e228d999dd
commit bca0b34636
15 files changed
+179 -73

No files matched your search

@@ -1,4 +1,5 @@
<script lang="ts">
import { SvelteSet } from "svelte/reactivity";
import {
deleteShare,
listShares,
@@ -11,6 +12,7 @@
import ShareLinkField from "#lib/components/shares/ShareLinkField.svelte";
import ContextMenu from "#lib/components/ui/ContextMenu.svelte";
import ContextMenuItem from "#lib/components/ui/ContextMenuItem.svelte";
import CopyItem from "#lib/components/ui/CopyItem.svelte";
import EmptyState from "#lib/components/ui/EmptyState.svelte";
import Icon from "#lib/components/ui/Icon.svelte";
import Spinner from "#lib/components/ui/Spinner.svelte";
@@ -19,6 +21,7 @@
import { formatDownloads, formatExpiry } from "#lib/format/shares.js";
import { t } from "#lib/i18n/locale.svelte.js";
import { accounts } from "#lib/stores/accounts.svelte.js";
import { createFlash } from "#lib/stores/flash.svelte.js";
import { shareUi } from "#lib/stores/shares.svelte.js";
import { toasts } from "#lib/stores/toasts.svelte.js";
import { ui } from "#lib/stores/ui.svelte.js";
@@ -31,10 +34,14 @@
let filter = $state<Filter>("active");
let expanded = $state<number | null>(null);
let token = 0;
const kept = new SvelteSet<number>();
const done = createFlash<number>();
const visible = $derived(
filter === "active"
? items.filter((item) => shareState(item) === "active")
? items.filter(
(item) => kept.has(item.id) || shareState(item) === "active"
)
: items
);
const activeCount = $derived(
@@ -50,6 +57,7 @@
const rows = await listShares(activeOnly);
if (current === token) {
items = rows;
kept.clear();
}
} catch {
if (current === token) {
@@ -79,15 +87,11 @@
ui.closePanel();
}
async function copy(share: FileShare) {
await navigator.clipboard.writeText(shareUrl(share));
toasts.success(t("shares.copied"));
}
async function revoke(share: FileShare) {
try {
replace(await revokeShare(share.id));
toasts.success(t("shares.revokedToast"));
kept.add(share.id);
done.show(share.id);
} catch {
toasts.error(t("shares.revokeFailed"));
}
@@ -96,7 +100,7 @@
async function reissue(share: FileShare) {
try {
replace(await reissueShare(share.id));
toasts.success(t("shares.reissued"));
done.show(share.id);
} catch {
toasts.error(t("shares.reissueFailed"));
}
@@ -205,9 +209,12 @@
</button>
{/snippet}
{#snippet menu()}
<ContextMenuItem icon="copy" onselect={() => copy(share)}>
{t("shares.copy")}
</ContextMenuItem>
<CopyItem
done={t("shares.copied")}
icon="copy"
label={t("shares.copy")}
text={() => shareUrl(share)}
/>
{#if share.message_id !== null || share.peer_id !== null}
<ContextMenuItem icon="reply" onselect={() => jump(share)}>
{t("ui.jumpToMessage")}
@@ -247,7 +254,14 @@
<Icon name="reply" size="1rem" />{t("shares.toMessage")}
</button>
{/if}
{#if state === "active"}
{#if done.current === share.id}
<span class="done">
<Icon name="check" size="1rem" />
{state === "active"
? t("shares.reissued")
: t("shares.accessRevoked")}
</span>
{:else if state === "active"}
<button
class="pill danger"
onclick={() => revoke(share)}
@@ -461,6 +475,18 @@
}
}
.done {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.3125rem 0;
border: 1px solid transparent;
font-size: 0.8125rem;
color: var(--color-text-green);
}
.footnote {
margin: 0;
padding: 0 1rem 1rem;