feat: add upload progress bar (#20)

This commit is contained in:
pluja
2023-11-21 17:20:32 +01:00
parent 4e7e135ca4
commit 7dc703c335
4 changed files with 60 additions and 20 deletions

View File

@@ -1,6 +1,7 @@
<script> <script>
import { validateURL, CLIENT_API_HOST } from '$lib/utils.js'; import { validateURL, CLIENT_API_HOST } from '$lib/utils.js';
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import { uploadProgress } from '$lib/stores';
import toast from 'svelte-french-toast'; import toast from 'svelte-french-toast';
@@ -10,7 +11,7 @@
let language = 'auto'; let language = 'auto';
let sourceUrl = ''; let sourceUrl = '';
let fileInput; let fileInput;
let device = (env.PUBLIC_WHISHPER_PROFILE == "gpu") ? 'cuda' : 'cpu'; let device = env.PUBLIC_WHISHPER_PROFILE == 'gpu' ? 'cuda' : 'cpu';
let languages = [ let languages = [
'auto', 'auto',
@@ -83,14 +84,44 @@
formData.append('file', fileInput.files[0]); formData.append('file', fileInput.files[0]);
} }
const res = await fetch(`${CLIENT_API_HOST}/api/transcriptions`, { return new Promise((resolve, reject) => {
method: 'POST', const xhr = new XMLHttpRequest();
body: formData
// Set up progress event listener
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentCompleted = Math.round((event.loaded * 100) / event.total);
uploadProgress.set(percentCompleted);
}
});
// Set up load event listener
xhr.addEventListener('load', () => {
if (xhr.status === 200) {
resolve(xhr.response);
toast.success('Success!');
} else {
reject(xhr.statusText);
toast.error('Upload failed');
}
uploadProgress.set(0); // Reset progress after completion
});
// Set up error event listener
xhr.addEventListener('error', () => {
reject(xhr.statusText);
toast.error('An error occurred during upload');
uploadProgress.set(0); // Reset progress on error
});
xhr.open('POST', `${CLIENT_API_HOST}/api/transcriptions`);
xhr.send(formData);
}); });
// Set file and sourceUrl to empty // Set file and sourceUrl to empty
sourceUrl = ''; sourceUrl = '';
fileInput.value = ''; fileInput.value = '';
uploadProgress.set(0);
toast.success('Success!'); toast.success('Success!');
} }
@@ -182,7 +213,7 @@
<span class="label-text">Device</span> <span class="label-text">Device</span>
</label> </label>
<select name="device" bind:value={device} class="select select-bordered"> <select name="device" bind:value={device} class="select select-bordered">
{#if env.PUBLIC_WHISHPER_PROFILE == "gpu" } {#if env.PUBLIC_WHISHPER_PROFILE == 'gpu'}
<option selected value="cuda">GPU</option> <option selected value="cuda">GPU</option>
<option value="cpu">CPU</option> <option value="cpu">CPU</option>
{:else} {:else}
@@ -199,7 +230,7 @@
>Start</button >Start</button
> >
</form> </form>
<form method="dialog" class="modal-backdrop"> <form method="dialog" class="modal-backdrop">
<button>close</button> <button>close</button>
</form> </form>
</dialog> </dialog>

View File

@@ -15,7 +15,6 @@
.then(data => { .then(data => {
if (data) { if (data) {
availableLanguages = data; availableLanguages = data;
console.log(availableLanguages)
// Languages fetched successfully, stop trying // Languages fetched successfully, stop trying
clearInterval(fetchLanguagesInterval); clearInterval(fetchLanguagesInterval);
} }
@@ -56,7 +55,7 @@
<!-- Language picker --> <!-- Language picker -->
<div class="w-full max-w-xs form-control"> <div class="w-full max-w-xs form-control">
<label for="target-lan" class="label"> <label for="target-lan" class="label">
<span class="label-text">Target language</span> <span class="label-text">Target languages for {tr.result.language}</span>
</label> </label>
<select bind:value={targetLanguage} name="target-lan" class="select select-bordered"> <select bind:value={targetLanguage} name="target-lan" class="select select-bordered">
<option disabled selected>Pick one</option> <option disabled selected>Pick one</option>

View File

@@ -13,6 +13,9 @@ export const downloadTranscription = writable(null);
export const editorHistory = writable([]); export const editorHistory = writable([]);
// Upload progress and status
export const uploadProgress = writable(0);
// editor settings // editor settings
export let editorSettings = writable({ export let editorSettings = writable({
autosave: false, autosave: false,

View File

@@ -1,6 +1,6 @@
<script> <script>
import { Toaster } from 'svelte-french-toast'; import { Toaster } from 'svelte-french-toast';
import { transcriptions } from '$lib/stores'; import { transcriptions, uploadProgress } from '$lib/stores';
import { browser, dev } from '$app/environment'; import { browser, dev } from '$app/environment';
import { CLIENT_WS_HOST } from '$lib/utils'; import { CLIENT_WS_HOST } from '$lib/utils';
import { onMount, onDestroy } from 'svelte'; import { onMount, onDestroy } from 'svelte';
@@ -89,21 +89,28 @@
<ModalTranscriptionForm /> <ModalTranscriptionForm />
<header> <header>
<h1 class="flex items-center justify-center space-x-4 font-bold text-4xl mt-8"> <h1 class="flex items-center justify-center mt-8 space-x-4 text-4xl font-bold">
<span> <span>
<img class="w-20 h-20" src="/logo.svg" alt="Logo: a cloud whispering" /> <img class="w-20 h-20" src="/logo.svg" alt="Logo: a cloud whispering" />
</span> </span>
<span> Whishper </span> <span> Whishper </span>
</h1> </h1>
<h2 class="text-md text-center opacity-70 font-mono">{data.randomSentence}</h2> <h2 class="font-mono text-center text-md opacity-70">{data.randomSentence}</h2>
</header> </header>
<main class="card w-4/6 bg-neutral text-neutral-content mx-auto mt-4 mb-8"> <main class="w-4/6 mx-auto mt-4 mb-8 card bg-neutral text-neutral-content">
<button {#if $uploadProgress > 0}
class="btn btn-primary mx-auto max-w-md mt-8 btn-md" <div class="flex flex-col items-center justify-center px-4 pt-4 my-4">
onclick="modalNewTranscription.showModal()">✨ new transcription</button <progress class="w-full mx-2 progress progress-success" value="{$uploadProgress}" max="100"></progress>
> <span>Uploading...</span>
<div class="card-body items-center text-center mb-0"> </div>
{:else}
<button
class="max-w-md mx-auto mt-8 btn btn-primary btn-md"
onclick="modalNewTranscription.showModal()">✨ new transcription</button
>
{/if}
<div class="items-center mb-0 text-center card-body">
{#if $transcriptions.length > 0} {#if $transcriptions.length > 0}
{#each $transcriptions as tr (tr.id)} {#each $transcriptions as tr (tr.id)}
{#if tr.status == 2} {#if tr.status == 2}
@@ -120,7 +127,7 @@
{/if} {/if}
{/each} {/each}
{:else} {:else}
<p class="text-center font-bold text-2xl">🔮 No transcriptions yet 🔮</p> <p class="text-2xl font-bold text-center">🔮 No transcriptions yet 🔮</p>
{/if} {/if}
</div> </div>
</main> </main>