diff --git a/tests/test_downloads_tab_workflow_route.mjs b/tests/test_downloads_tab_workflow_route.mjs index 5fcdab4..090eee5 100644 --- a/tests/test_downloads_tab_workflow_route.mjs +++ b/tests/test_downloads_tab_workflow_route.mjs @@ -3020,6 +3020,44 @@ test('native Xet progress bar uses live network bytes against the known final fi }).percent, 20); }); +test('download progress presentation combines display and logical size labels', () => { + const getDownloadProgressPresentation = eval( + `(${extractMethod(renderFormatMethodsSource, 'getDownloadProgressPresentation')})` + ); + const dialog = { + getDownloadDisplayProgress: () => ({ + percent: 42.5, + downloaded: 100, + totalSize: 250, + isTransfer: true, + isFinalizing: false, + }), + formatBytes: value => `${value} B`, + formatDownloadProgressMeta: () => 'meta', + formatDownloadPercent: value => `${value}%`, + }; + + assert.deepEqual( + getDownloadProgressPresentation.call(dialog, { + downloaded: 80, + total_size: 200, + }, { unknownTotal: 'Unknown' }), + { + percent: 42.5, + downloaded: 100, + totalSize: 250, + isTransfer: true, + isFinalizing: false, + percentLabel: '42.5%', + downloadedText: '100 B', + totalText: '250 B', + progressMeta: 'meta', + logicalDownloadedText: '80 B', + logicalTotalText: '200 B', + } + ); +}); + test('base model alias resolves FLUX KREA as Flux.1 Krea', () => { const { normalizeBaseModelToken, @@ -4025,6 +4063,9 @@ test('downloads tab shows active downloads from all workflow tabs', () => { test('downloads tab renders workflow label for active downloads', () => { const renderQueueDownloadsHtml = eval(`(${extractMethod(queueMethodsSource, 'renderQueueDownloadsHtml')})`); + const getDownloadProgressPresentation = eval( + `(${extractMethod(renderFormatMethodsSource, 'getDownloadProgressPresentation')})` + ); const dialog = { escapeHtml(value) { return String(value).replace(/[&<>\"]/g, char => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[char])); @@ -4049,6 +4090,9 @@ test('downloads tab renders workflow label for active downloads', () => { isFinalizing: false, }; }, + getDownloadProgressPresentation(progress, options) { + return getDownloadProgressPresentation.call(this, progress, options); + }, formatDownloadProgressMeta() { return ''; }, diff --git a/web/resolver/actions/queue_methods.js b/web/resolver/actions/queue_methods.js index 31b7dee..6ebbc0f 100644 --- a/web/resolver/actions/queue_methods.js +++ b/web/resolver/actions/queue_methods.js @@ -1144,8 +1144,16 @@ export const queueMethods = { const progress = typeof this.applyPendingDownloadStatus === 'function' ? this.applyPendingDownloadStatus(info, info.lastProgress || {}) : (info.lastProgress || {}); - const displayProgress = this.getDownloadDisplayProgress(progress); - const percent = displayProgress.percent; + const presentation = this.getDownloadProgressPresentation(progress); + const { + percent, + downloadedText: downloaded, + totalText: total, + progressMeta, + percentLabel, + logicalDownloadedText: logicalDownloaded, + logicalTotalText: logicalTotal, + } = presentation; const filename = progress.filename || info.filename || info.missing?.download_source?.filename @@ -1153,22 +1161,16 @@ export const queueMethods = { || 'model'; const category = this.getCategoryDisplayName?.(info.category || info.missing?.category || '') || info.category || ''; const nodeLabel = info.missing?.subgraph_name || info.missing?.node_type || (info.missing?.subgraph_id ? 'Subgraph' : 'Node'); - const downloaded = this.formatBytes(displayProgress.downloaded); - const total = displayProgress.totalSize ? this.formatBytes(displayProgress.totalSize) : ''; - const progressMeta = this.formatDownloadProgressMeta?.(progress) || ''; const status = progress.status || info.lastStatus || 'starting'; const backend = String(progress.download_backend || info.downloadBackend || '').toLowerCase(); const isAria2 = backend === 'aria2'; const isPaused = status === 'paused'; - const percentLabel = this.formatDownloadPercent?.(percent) ?? String(Math.round(percent)); const statusLabel = status === 'downloading' - ? (displayProgress.isFinalizing ? 'Finalizing' : `${percentLabel}%`) + ? (presentation.isFinalizing ? 'Finalizing' : `${percentLabel}%`) : (status === 'starting' ? 'Starting' : (isPaused ? 'Paused' : status.replace(/_/g, ' '))); - const logicalDownloaded = this.formatBytes(progress.downloaded || 0); - const logicalTotal = progress.total_size ? this.formatBytes(progress.total_size) : ''; - const sizeText = displayProgress.isFinalizing && logicalTotal + const sizeText = presentation.isFinalizing && logicalTotal ? `Finalizing file: ${logicalDownloaded} / ${logicalTotal}` - : (total ? `${downloaded} / ${total}` : downloaded); + : (presentation.totalSize ? `${downloaded} / ${total}` : downloaded); const targetPath = progress.directory || info.downloadDirectory || info.downloadPath || ''; const targetLabel = targetPath ? targetPath.split(/[/\\]/).filter(Boolean).pop() || targetPath : ''; const workflowLabel = this.getDownloadWorkflowLabel?.(info) || 'Unknown workflow'; diff --git a/web/resolver/actions/resolve_download_methods.js b/web/resolver/actions/resolve_download_methods.js index 32fb8ae..026f309 100644 --- a/web/resolver/actions/resolve_download_methods.js +++ b/web/resolver/actions/resolve_download_methods.js @@ -1127,17 +1127,19 @@ export const resolveDownloadMethods = { const backend = String(progress.download_backend || snapshot.downloadBackend || snapshot.download_backend || '').toLowerCase(); const isAria2 = backend === 'aria2'; const isPaused = status === 'paused'; - const displayProgress = this.getDownloadDisplayProgress(progress); - const percent = displayProgress.percent; - const downloaded = this.formatBytes(displayProgress.downloaded); - const total = this.formatBytes(displayProgress.totalSize); - const progressMeta = this.formatDownloadProgressMeta(progress); - const percentLabel = this.formatDownloadPercent?.(percent) ?? String(Math.round(percent)); - const logicalDownloaded = this.formatBytes(progress.downloaded || 0); - const logicalTotal = progress.total_size ? this.formatBytes(progress.total_size) : 'Unknown'; - const leftText = displayProgress.isFinalizing + const presentation = this.getDownloadProgressPresentation(progress, { unknownTotal: 'Unknown' }); + const { + percent, + downloadedText: downloaded, + totalText: total, + progressMeta, + percentLabel, + logicalDownloadedText: logicalDownloaded, + logicalTotalText: logicalTotal, + } = presentation; + const leftText = presentation.isFinalizing ? `Finalizing file: ${logicalDownloaded} / ${logicalTotal}` - : (displayProgress.totalSize + : (presentation.totalSize ? `${downloaded} / ${total} (${percentLabel}%)${isPaused ? ' - Paused' : ''}` : 'Connecting...'); let actionClass = canCancel ? 'cancel-download-btn mr-btn mr-btn-danger mr-btn-sm' : ''; diff --git a/web/resolver/utils/render_format_methods.js b/web/resolver/utils/render_format_methods.js index 6ec1bbe..a2bbd98 100644 --- a/web/resolver/utils/render_format_methods.js +++ b/web/resolver/utils/render_format_methods.js @@ -340,6 +340,23 @@ export const renderFormatMethods = { }; }, + getDownloadProgressPresentation(progress = {}, { unknownTotal = '' } = {}) { + const displayProgress = this.getDownloadDisplayProgress(progress); + const percent = displayProgress.percent; + + return { + ...displayProgress, + percentLabel: this.formatDownloadPercent?.(percent) ?? String(Math.round(percent)), + downloadedText: this.formatBytes(displayProgress.downloaded), + totalText: this.formatBytes(displayProgress.totalSize), + progressMeta: this.formatDownloadProgressMeta(progress), + logicalDownloadedText: this.formatBytes(progress.downloaded || 0), + logicalTotalText: progress.total_size + ? this.formatBytes(progress.total_size) + : unknownTotal, + }; + }, + getDownloadEtaText(progress = {}) { const backend = String(progress.download_backend || '').toLowerCase(); const totalSize = Number(progress.total_size) || 0;