Add cancel button to filesystem upload queue

This commit is contained in:
2024-06-13 20:08:10 +02:00
parent 1e0a692ca0
commit a5873148d4
3 changed files with 60 additions and 24 deletions

View File

@@ -12,7 +12,7 @@
import { fs_path_url } from "../FilesystemUtil" import { fs_path_url } from "../FilesystemUtil"
// code and an error message // code and an error message
export const upload_file = async (file, path, on_progress, on_success, on_error) => { export const upload_file = (file, path, on_progress, on_success, on_error) => {
// Check the file size limit. For free accounts it's 20 GB // Check the file size limit. For free accounts it's 20 GB
if (window.user.subscription.file_size_limit === 0) { if (window.user.subscription.file_size_limit === 0) {
window.user.subscription.file_size_limit = 20e9 window.user.subscription.file_size_limit = 20e9
@@ -70,4 +70,6 @@ export const upload_file = async (file, path, on_progress, on_success, on_error)
}; };
xhr.send(file); xhr.send(file);
return xhr
} }

View File

@@ -3,21 +3,22 @@ import { createEventDispatcher } from "svelte";
import { fade } from "svelte/transition"; import { fade } from "svelte/transition";
import { upload_file } from "./UploadFunc"; import { upload_file } from "./UploadFunc";
import ProgressBar from "../../util/ProgressBar.svelte"; import ProgressBar from "../../util/ProgressBar.svelte";
import Button from "../../layout/Button.svelte"
let dispatch = createEventDispatcher() let dispatch = createEventDispatcher()
export let job = { export let job = {
file: null, file: null,
name: "", name: "",
id: "",
status: "", status: "",
} }
export let total = 0 export let total = 0
export let loaded = 0 export let loaded = 0
let error_code = "" let error_code = ""
let error_message = "" let error_message = ""
let xhr = null
export const start = () => { export const start = () => {
upload_file( xhr = upload_file(
job.file, job.file,
job.path, job.path,
(prog_loaded, prog_total) => { (prog_loaded, prog_total) => {
@@ -29,37 +30,66 @@ export const start = () => {
dispatch("finished") dispatch("finished")
}, },
(code, message) => { (code, message) => {
if (job.status === "finished") {
return
}
console.log("Upload error", code, message) console.log("Upload error", code, message)
error_code = code error_code = code
error_message = message error_message = message
job.status = "error" job.status = "error"
// Wait with reporting so the user can read the error message // We don't send the finished signal so the user can read the error
setTimeout(() => dispatch("finished"), 60000) // messsage and manually dismiss it through the cancel button
}, },
) )
job.status = "uploading" job.status = "uploading"
} }
const cancel = () => {
job.status = "finished"
if (xhr && xhr.abort) {
xhr.abort()
}
xhr = null
dispatch("finished")
}
</script> </script>
<div class="upload_progress" transition:fade={{duration: 200}} class:error={job.status === "error"}> <div class="prog" transition:fade={{duration: 200}} class:error={job.status === "error"}>
<div class="bar">
{job.file.name}<br/> {job.file.name}<br/>
{#if error_code !== ""} {#if error_code !== ""}
{error_message}<br/> {error_message}<br/>
{error_code}<br/> {error_code}<br/>
{/if} {/if}
<ProgressBar total={total} used={loaded}/> <ProgressBar total={total} used={loaded}/>
</div>
<div class="cancel">
<Button icon="cancel" click={cancel}/>
</div>
</div> </div>
<style> <style>
.upload_progress { .prog {
display: block; display: flex;
flex-direction: row;
}
.bar {
flex: 1 1 auto;
padding: 2px 4px 1px 4px; padding: 2px 4px 1px 4px;
margin: 4px; margin: 4px;
border-radius: 4px; border-radius: 4px;
} }
.cancel {
flex: 0 0 auto;
display: flex;
justify-content: center;
align-items: center; /* Stop stretching the button */
}
.error { .error {
background: var(--danger_color); background: var(--danger_color);
color: var(--highlight_text_color); color: var(--highlight_text_color);

View File

@@ -80,6 +80,15 @@ let active_uploads = 0
let state = "idle" let state = "idle"
const start_upload = async () => { const start_upload = async () => {
// Count the number of active uploads so we can know how many new uploads we
// can start
active_uploads = upload_queue.reduce((acc, val) => {
if (val.status === "uploading") {
acc++
}
return acc
}, 0)
for (let i = 0; i < upload_queue.length && active_uploads < 3; i++) { for (let i = 0; i < upload_queue.length && active_uploads < 3; i++) {
if (upload_queue[i]) { if (upload_queue[i]) {
if (upload_queue[i].status === "queued") { if (upload_queue[i].status === "queued") {
@@ -92,17 +101,12 @@ const start_upload = async () => {
if (active_uploads === 0) { if (active_uploads === 0) {
state = "finished" state = "finished"
dispatch("uploads_finished")
let file_ids = [] // Empty the queue to free any references to lingering components
upload_queue.forEach(job => {
if (job.status === "finished" && job.id !== "") {
file_ids.push(job.id)
}
})
dispatch("uploads_finished", file_ids)
upload_queue = [] upload_queue = []
// In ten seconds we close the popup
setTimeout(() => { setTimeout(() => {
if (state === "finished") { if (state === "finished") {
visible = false visible = false
@@ -114,7 +118,7 @@ const start_upload = async () => {
} }
const finish_upload = (e) => { const finish_upload = (e) => {
active_uploads-- // Update the queue so the status updates are properly rendered
upload_queue = upload_queue upload_queue = upload_queue
start_upload() start_upload()
} }