diff --git a/frontend/src/components/prompts/UploadFiles.vue b/frontend/src/components/prompts/UploadFiles.vue index f7e5baf0..3e382472 100644 --- a/frontend/src/components/prompts/UploadFiles.vue +++ b/frontend/src/components/prompts/UploadFiles.vue @@ -93,15 +93,14 @@ const sentPercent = computed(() => ); const sentMbytes = computed(() => byteToMbyte(uploadStore.sentBytes)); - const totalMbytes = computed(() => byteToMbyte(uploadStore.totalBytes)); - const speedMbytes = computed(() => byteToMbyte(speed.value)); let lastSpeedUpdate: number = 0; let recentSpeeds: number[] = []; const calculateSpeed = (sentBytes: number, oldSentBytes: number) => { + // Reset the state when the uploads batch is complete if (sentBytes === 0) { lastSpeedUpdate = 0; recentSpeeds = []; @@ -124,12 +123,13 @@ const calculateSpeed = (sentBytes: number, oldSentBytes: number) => { const recentSpeedsAverage = recentSpeeds.reduce((acc, curr) => acc + curr) / recentSpeeds.length; + // Use the current speed for the first update to avoid smoothing lag if (recentSpeeds.length === 1) { - speed.value = recentSpeedsAverage; - } else { - speed.value = recentSpeedsAverage * 0.2 + speed.value * 0.8; + speed.value = currentSpeed; } + speed.value = recentSpeedsAverage * 0.2 + speed.value * 0.8; + lastSpeedUpdate = Date.now(); calculateEta(); @@ -151,10 +151,11 @@ const calculateEta = () => { watch(sentBytes, calculateSpeed); watch(totalBytes, (totalBytes, oldTotalBytes) => { - if (oldTotalBytes > 0) { + if (oldTotalBytes !== 0) { return; } + // Mark the start time of a new upload batch lastSpeedUpdate = Date.now(); }); diff --git a/frontend/src/stores/upload.ts b/frontend/src/stores/upload.ts index 1eb7ec4c..1349ecfe 100644 --- a/frontend/src/stores/upload.ts +++ b/frontend/src/stores/upload.ts @@ -32,33 +32,6 @@ export const useUploadStore = defineStore("upload", () => { // ACTIONS // - const reset = () => { - if (progressInterval !== null) { - clearInterval(progressInterval); - progressInterval = null; - } - - allUploads.value = []; - activeUploads.value = new Set(); - lastUpload.value = -1; - totalBytes.value = 0; - sentBytes.value = 0; - }; - - const nextUpload = (): Upload => { - lastUpload.value++; - - const upload = allUploads.value[lastUpload.value]; - activeUploads.value.add(upload); - - return upload; - }; - - const hasActiveUploads = () => activeUploads.value.size > 0; - - const hasPendingUploads = () => - allUploads.value.length > lastUpload.value + 1; - const upload = ( path: string, name: string, @@ -79,6 +52,7 @@ export const useUploadStore = defineStore("upload", () => { type, totalBytes: file?.size ?? 0, sentBytes: 0, + // Stores rapidly changing sent bytes value without causing component re-renders rawProgress: markRaw({ sentBytes: 0, }), @@ -90,14 +64,14 @@ export const useUploadStore = defineStore("upload", () => { processUploads(); }; - const finishUpload = (upload: Upload) => { - sentBytes.value += upload.totalBytes - upload.sentBytes; - upload.sentBytes = upload.totalBytes; - upload.file = null; + // + // PRIVATE FUNCTIONS + // - activeUploads.value.delete(upload); - processUploads(); - }; + const hasActiveUploads = () => activeUploads.value.size > 0; + + const hasPendingUploads = () => + allUploads.value.length > lastUpload.value + 1; const isActiveUploadsOnLimit = () => activeUploads.value.size < UPLOADS_LIMIT; @@ -112,6 +86,7 @@ export const useUploadStore = defineStore("upload", () => { if (isActiveUploadsOnLimit() && hasPendingUploads()) { if (!hasActiveUploads()) { + // Update the state in a fixed time interval progressInterval = window.setInterval(syncState, 1000); } @@ -133,6 +108,24 @@ export const useUploadStore = defineStore("upload", () => { } }; + const nextUpload = (): Upload => { + lastUpload.value++; + + const upload = allUploads.value[lastUpload.value]; + activeUploads.value.add(upload); + + return upload; + }; + + const finishUpload = (upload: Upload) => { + sentBytes.value += upload.totalBytes - upload.sentBytes; + upload.sentBytes = upload.totalBytes; + upload.file = null; + + activeUploads.value.delete(upload); + processUploads(); + }; + const syncState = () => { for (const upload of activeUploads.value) { sentBytes.value += upload.rawProgress.sentBytes - upload.sentBytes; @@ -140,18 +133,26 @@ export const useUploadStore = defineStore("upload", () => { } }; + const reset = () => { + if (progressInterval !== null) { + clearInterval(progressInterval); + progressInterval = null; + } + + allUploads.value = []; + activeUploads.value = new Set(); + lastUpload.value = -1; + totalBytes.value = 0; + sentBytes.value = 0; + }; + return { // STATE - allUploads, activeUploads, - lastUpload, totalBytes, sentBytes, // ACTIONS - reset, upload, - finishUpload, - processUploads, }; }); diff --git a/frontend/src/views/Layout.vue b/frontend/src/views/Layout.vue index 597a680e..5a91bee5 100644 --- a/frontend/src/views/Layout.vue +++ b/frontend/src/views/Layout.vue @@ -1,7 +1,11 @@