feat(webui): quality of life improvements for upload dialog
ci/woodpecker/push/woodpecker Pipeline was successful Details

- when uploading, warn before closing tab
- allow cancelling in progress uploads
- when uploading multiple files, scroll to the current file
feat/users
Tomáš Mládek 2024-04-01 21:17:44 +02:00
parent 669b348160
commit 1f270d6dc7
1 changed files with 32 additions and 6 deletions

View File

@ -21,10 +21,13 @@
let files: File[] = [];
let URLs: string[] = [];
let uploading = false;
let abortController: AbortController | undefined;
let progress: Record<string, number> = {};
let totalProgress: number | undefined;
let filesElement: HTMLDivElement;
$: visible = files.length + URLs.length > 0;
addEmitter.on('files', (ev) => {
@ -40,9 +43,15 @@
uploading = true;
try {
abortController = new AbortController();
const addresses: string[] = [];
for (const file of files) {
for (const [idx, file] of files.entries()) {
filesElement
?.querySelectorAll('.entry')
[idx]?.scrollIntoView({ behavior: 'smooth', block: 'center' });
const address = await api.putBlob(file, {
abortController,
onProgress: (p) => {
progress[file.name] = (p.loaded / p.total) * 100;
totalProgress = Object.values(progress).reduce((a, b) => a + b, 0) / files.length;
@ -50,6 +59,10 @@
timeout: -1
});
addresses.push(address);
if (!uploading) {
break;
}
}
if (addresses.length == 1) {
@ -67,11 +80,16 @@
}
function reset() {
if (!uploading) {
files = [];
URLs = [];
progress = {};
if (uploading) {
const msg = $i18n.t('Are you sure you want to cancel the upload?');
if (!confirm(msg)) return;
}
abortController?.abort();
files = [];
URLs = [];
progress = {};
uploading = false;
}
function onKeydown(event: KeyboardEvent) {
@ -84,14 +102,22 @@
reset();
}
}
function onBeforeUnload(ev: BeforeUnloadEvent) {
if (files.length || uploading) {
ev.preventDefault();
ev.returnValue = true;
}
}
</script>
<svelte:window on:beforeunload={onBeforeUnload} />
<svelte:body on:keydown={onKeydown} />
<!-- svelte-ignore a11y-click-events-have-key-events a11y-no-static-element-interactions -->
<div class="addmodal-container" class:visible class:uploading on:click={reset}>
<div class="addmodal" on:click|stopPropagation>
<div class="files">
<div class="files" bind:this={filesElement}>
{#each files as file}
<div class="entry">
<div class="row">