From 0104add945fe3745cd61ded6da68d8036a9c6bb6 Mon Sep 17 00:00:00 2001 From: ddmoney420 Date: Sat, 28 Feb 2026 22:11:35 -0700 Subject: [PATCH] feat: expandable error details with copy-to-clipboard (closes #143) Co-Authored-By: Claude Opus 4.6 --- ui/src/app/app.html | 38 ++++++++++++++++++++++++++++++-------- ui/src/app/app.ts | 22 +++++++++++++++++++++- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/ui/src/app/app.html b/ui/src/app/app.html index 8e7741e..6043083 100644 --- a/ui/src/app/app.html +++ b/ui/src/app/app.html @@ -456,20 +456,42 @@ } @if (download.value.status === 'error') { - + } @if (!!download.value.filename) { {{ download.value.title }} } @else { - {{download.value.title}} - @if (download.value.msg) { -
{{download.value.msg}}
- } - @if (download.value.error) { -
Error: {{download.value.error}}
- } + + {{download.value.title}} + @if (download.value.status === 'error' && !isErrorExpanded(download.key)) { + + Click for details + + } + }
+ @if (download.value.status === 'error' && isErrorExpanded(download.key)) { +
+
+
+ @if (download.value.msg) { +
Message: {{download.value.msg}}
+ } + @if (download.value.error) { +
Error: {{download.value.error}}
+ } +
URL: {{download.value.url}}
+
+ +
+
+ } @if (download.value.size) { diff --git a/ui/src/app/app.ts b/ui/src/app/app.ts index e56fd2b..7738c65 100644 --- a/ui/src/app/app.ts +++ b/ui/src/app/app.ts @@ -6,7 +6,7 @@ import { FormsModule } from '@angular/forms'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NgSelectModule } from '@ng-select/ng-select'; -import { faTrashAlt, faCheckCircle, faTimesCircle, faRedoAlt, faSun, faMoon, faCheck, faCircleHalfStroke, faDownload, faExternalLinkAlt, faFileImport, faFileExport, faCopy, faClock, faTachometerAlt } from '@fortawesome/free-solid-svg-icons'; +import { faTrashAlt, faCheckCircle, faTimesCircle, faRedoAlt, faSun, faMoon, faCheck, faCircleHalfStroke, faDownload, faExternalLinkAlt, faFileImport, faFileExport, faCopy, faClock, faTachometerAlt, faChevronRight } from '@fortawesome/free-solid-svg-icons'; import { faGithub } from '@fortawesome/free-brands-svg-icons'; import { CookieService } from 'ngx-cookie-service'; import { DownloadsService } from './services/downloads.service'; @@ -66,6 +66,7 @@ export class App implements AfterViewInit, OnInit { ytDlpVersion: string | null = null; metubeVersion: string | null = null; isAdvancedOpen = false; + expandedErrors: Set = new Set(); // Download metrics activeDownloads = 0; @@ -100,6 +101,7 @@ export class App implements AfterViewInit, OnInit { faGithub = faGithub; faClock = faClock; faTachometerAlt = faTachometerAlt; + faChevronRight = faChevronRight; subtitleFormats = [ { id: 'srt', text: 'SRT' }, { id: 'txt', text: 'TXT (Text only)' }, @@ -699,6 +701,24 @@ export class App implements AfterViewInit, OnInit { this.isAdvancedOpen = !this.isAdvancedOpen; } + toggleErrorDetail(id: string) { + if (this.expandedErrors.has(id)) this.expandedErrors.delete(id); + else this.expandedErrors.add(id); + } + + copyErrorMessage(download: Download) { + const parts: string[] = []; + if (download.title) parts.push(`Title: ${download.title}`); + if (download.url) parts.push(`URL: ${download.url}`); + if (download.msg) parts.push(`Message: ${download.msg}`); + if (download.error) parts.push(`Error: ${download.error}`); + navigator.clipboard.writeText(parts.join('\n')).catch(() => {}); + } + + isErrorExpanded(id: string): boolean { + return this.expandedErrors.has(id); + } + private updateMetrics() { this.activeDownloads = Array.from(this.downloads.queue.values()).filter(d => d.status === 'downloading' || d.status === 'preparing').length; this.queuedDownloads = Array.from(this.downloads.queue.values()).filter(d => d.status === 'pending').length;