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;
}