From c68fcaddd19dc66eeb019ae3aec34b0be8966d6b Mon Sep 17 00:00:00 2001 From: tjelite1986 Date: Sun, 16 Aug 2026 12:56:29 +0200 Subject: [PATCH] feat: show the queued format in the Downloading table (closes #551) With the format picked per download rather than left on one setting, the Downloading list gave no way to tell which item was queued as what until it landed in Completed. The new column labels the format exactly as the form does, reusing the same option lists, and falls back to the raw value uppercased for a record queued before an option existed. Co-Authored-By: Claude Opus 5 (1M context) --- ui/src/app/app.html | 2 ++ ui/src/app/app.spec.ts | 41 +++++++++++++++++++++++++++++++++++++++++ ui/src/app/app.ts | 16 ++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/ui/src/app/app.html b/ui/src/app/app.html index c6e436c..c425a3e 100644 --- a/ui/src/app/app.html +++ b/ui/src/app/app.html @@ -693,6 +693,7 @@ Video + Format Speed ETA @@ -726,6 +727,7 @@ } + {{ formatLabel(download.value) }} {{ download.value.speed | speed }} {{ download.value.eta | eta }} diff --git a/ui/src/app/app.spec.ts b/ui/src/app/app.spec.ts index fb529e8..9ba4546 100644 --- a/ui/src/app/app.spec.ts +++ b/ui/src/app/app.spec.ts @@ -6,6 +6,7 @@ import { DownloadsService } from './services/downloads.service'; import { SubscriptionsService } from './services/subscriptions.service'; import { ToastService } from './services/toast.service'; import { CookieService } from 'ngx-cookie-service'; +import { Download } from './interfaces'; class DownloadsServiceStub { loading = false; @@ -229,6 +230,46 @@ describe('App', () => { expect(root.textContent).toContain('starts in'); }); + it('shows the queued format in the Downloading table', () => { + downloads.queue.set('https://example.com/v', { + id: 'v1', + title: 'Some Video', + url: 'https://example.com/v', + download_type: 'audio', + quality: 'best', + format: 'flac', + folder: '', + custom_name_prefix: '', + playlist_item_limit: 0, + status: 'downloading', + msg: '', + percent: 10, + speed: 0, + eta: 0, + filename: '', + checked: false, + }); + downloads.queueChanged.next(); + + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const row = (fixture.nativeElement as HTMLElement).querySelector('tbody tr'); + expect(row?.textContent).toContain('FLAC'); + }); + + it('labels formats the way the form does, and copes with an unknown one', () => { + const app = TestBed.createComponent(App).componentInstance; + const base = { format: '' } as Download; + + expect(app.formatLabel({ ...base, format: 'any' })).toBe('Auto'); + expect(app.formatLabel({ ...base, format: 'mp4' })).toBe('MP4'); + expect(app.formatLabel({ ...base, format: 'srt' })).toBe('SRT'); + // A format from a record older than the option list still reads sensibly. + expect(app.formatLabel({ ...base, format: 'mkv' })).toBe('MKV'); + expect(app.formatLabel(base)).toBe('-'); + }); + it('includes titleRegex in subscribe payload', () => { const fixture = TestBed.createComponent(App); const app = fixture.componentInstance; diff --git a/ui/src/app/app.ts b/ui/src/app/app.ts index d88cc9d..f0f08b0 100644 --- a/ui/src/app/app.ts +++ b/ui/src/app/app.ts @@ -909,6 +909,22 @@ export class App implements AfterViewInit, OnInit, OnDestroy { return type.charAt(0).toUpperCase() + type.slice(1); } + // The format the download was queued with, labelled the way the form labels + // it, so a queued item can be told apart while it is still downloading. + formatLabel(download: Download): string { + const format = (download.format || '').trim(); + if (!format) { + return '-'; + } + const options: Option[] = [ + ...this.videoFormats, + ...this.audioFormats, + ...this.captionFormats, + ...this.thumbnailFormats, + ]; + return options.find(o => o.id === format)?.text ?? format.toUpperCase(); + } + formatCodecLabel(download: Download): string { if (download.download_type !== 'video') { const format = (download.format || '').toUpperCase();