From 9452a8d8feb0aa87fbc17ec9b99661f6c6ade8d0 Mon Sep 17 00:00:00 2001 From: wukko Date: Thu, 22 May 2025 23:17:13 +0600 Subject: [PATCH] web/ProcessingQueueItem: timeout the download button --- .../queue/ProcessingQueueItem.svelte | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/web/src/components/queue/ProcessingQueueItem.svelte b/web/src/components/queue/ProcessingQueueItem.svelte index f1cae700..42f888df 100644 --- a/web/src/components/queue/ProcessingQueueItem.svelte +++ b/web/src/components/queue/ProcessingQueueItem.svelte @@ -39,6 +39,7 @@ let { id, info }: Props = $props(); let retrying = $state(false); + let downloading = $state(false); const retry = async (info: CobaltQueueItem) => { if (info.canRetry && info.originalRequest) { @@ -51,13 +52,28 @@ } }; - const download = (file: File) => + const download = (file: File) => { + downloading = true; + downloadFile({ file: new File([file], info.filename, { type: info.mimeType, }), }); + setTimeout(() => { + /* + fake timeout to prevent download button spam, + because there's no real way to await the real + saving process via object url (blob), which + takes some time on some devices depending on file size. + if you know of a way to do it in + lib/download.ts -> openFile(), please make a PR! + */ + downloading = false; + }, 3000) + }; + type StatusText = { info: CobaltQueueItem; currentTasks: CobaltCurrentTasks; @@ -202,8 +218,14 @@ class="button action-button" aria-label={$t("button.download")} onclick={() => download(info.resultFile)} + disabled={downloading} + class:downloading > - + {#if !downloading} + + {:else} + + {/if} {/if} @@ -221,6 +243,7 @@ class="button action-button" aria-label={$t(`button.${info.state === "done" ? "delete" : "remove"}`)} onclick={() => removeItem(id)} + disabled={downloading} > @@ -324,11 +347,6 @@ margin-right: 0; } - .status-spinner :global(svg) { - animation: spinner 0.7s infinite linear; - will-change: transform; - } - .file-actions { gap: 4px; } @@ -382,6 +400,7 @@ padding: 8px; height: auto; box-shadow: none; + transition: opacity 0.2s; } .action-button :global(svg) { @@ -390,6 +409,17 @@ stroke-width: 1.5px; } + .action-button:disabled { + cursor: progress; + opacity: 0.5; + } + + .status-spinner :global(svg), + .action-button.downloading :global(svg) { + animation: spinner 0.7s infinite linear; + will-change: transform; + } + .processing-item:first-child { padding-top: 0; }