From 399e2fbe7057945ac843ef2a8ab5b364388573c1 Mon Sep 17 00:00:00 2001 From: Administrator Date: Wed, 11 Mar 2026 20:25:13 +0100 Subject: [PATCH] feat: upload progress display, semaphore fix, context menu polish - Status bar shows uploaded/total bytes (e.g. "16 GB / 281 GB") Total is sum of all queue jobs (100GB x 4 hosters = 400GB) - Fix semaphore acquisition order: hoster-first then global prevents jobs waiting on a hoster slot from wasting global semaphore slots, significantly increasing active connection utilization - Context menu: dynamic count on all labels, singular/plural for single selection, user-adjusted grouping with separators Co-Authored-By: Claude Opus 4.6 --- lib/upload-manager.js | 11 +++++++---- renderer/app.js | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/upload-manager.js b/lib/upload-manager.js index 0f16879..203d5ab 100644 --- a/lib/upload-manager.js +++ b/lib/upload-manager.js @@ -239,14 +239,16 @@ class UploadManager extends EventEmitter { maxAttempts }); + // Acquire hoster semaphore first so jobs waiting for a hoster slot + // don't waste global slots (prevents underutilization) + await hosterSemaphore.acquire(signal); + hosterSlotAcquired = true; + if (globalSemaphore) { await globalSemaphore.acquire(signal); globalSlotAcquired = true; } - await hosterSemaphore.acquire(signal); - hosterSlotAcquired = true; - if (settings.timeIntervalSec > 0) { await this._waitForInterval(task.hoster, settings.timeIntervalSec * 1000, signal); } @@ -438,8 +440,9 @@ class UploadManager extends EventEmitter { this.activeJobs.delete(uploadId); this.jobAbortControllers.delete(jobId); cleanupSignals(); - if (hosterSlotAcquired) hosterSemaphore.release(); + // Release in reverse order of acquire (global first, then hoster) if (globalSlotAcquired && globalSemaphore) globalSemaphore.release(); + if (hosterSlotAcquired) hosterSemaphore.release(); } } diff --git a/renderer/app.js b/renderer/app.js index 31f99ee..fd2ba8d 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -1465,7 +1465,8 @@ function updateStatusBar() { document.getElementById('sbState').textContent = stateText; document.getElementById('sbSpeed').textContent = formatSpeed(lastUploadStats.globalSpeedKbs || 0); - document.getElementById('sbTotal').textContent = formatSize(lastUploadStats.totalBytes || 0); + const queueTotalBytes = queueJobs.reduce((sum, j) => sum + (j.bytesTotal || 0), 0); + document.getElementById('sbTotal').textContent = `${formatSize(lastUploadStats.totalBytes || 0)} / ${formatSize(queueTotalBytes)}`; document.getElementById('sbEta').textContent = `ETA ${etaSeconds > 0 ? formatTime(etaSeconds) : '--:--'}`; document.getElementById('sbConnections').textContent = `Aktive Verbindungen ${lastUploadStats.activeJobs || 0}`; document.getElementById('sbQueueCount').textContent = `Gesamt ${counts.total}`;