diff --git a/ui/src/app/app.html b/ui/src/app/app.html
index db035b8..6244667 100644
--- a/ui/src/app/app.html
+++ b/ui/src/app/app.html
@@ -463,20 +463,42 @@
}
@if (entry[1].status === 'error') {
-
+
}
@if (!!entry[1].filename) {
{{ entry[1].title }}
} @else {
- {{entry[1].title}}
- @if (entry[1].msg) {
-
{{entry[1].msg}}
- }
- @if (entry[1].error) {
-
Error: {{entry[1].error}}
- }
+
+ {{entry[1].title}}
+ @if (entry[1].status === 'error' && !isErrorExpanded(entry[0])) {
+
+ Click for details
+
+ }
+
}
+ @if (entry[1].status === 'error' && isErrorExpanded(entry[0])) {
+
+
+
+ @if (entry[1].msg) {
+
Message: {{entry[1].msg}}
+ }
+ @if (entry[1].error) {
+
Error: {{entry[1].error}}
+ }
+
URL: {{entry[1].url}}
+
+
+
+
+ }
@if (entry[1].size) {
diff --git a/ui/src/app/app.ts b/ui/src/app/app.ts
index 0933347..17281c6 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, faSortAmountDown, faSortAmountUp } from '@fortawesome/free-solid-svg-icons';
+import { faTrashAlt, faCheckCircle, faTimesCircle, faRedoAlt, faSun, faMoon, faCheck, faCircleHalfStroke, faDownload, faExternalLinkAlt, faFileImport, faFileExport, faCopy, faClock, faTachometerAlt, faSortAmountDown, faSortAmountUp, 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';
@@ -67,6 +67,7 @@ export class App implements AfterViewInit, OnInit {
metubeVersion: string | null = null;
isAdvancedOpen = false;
sortAscending = false;
+ expandedErrors: Set = new Set();
// Download metrics
activeDownloads = 0;
@@ -103,6 +104,7 @@ export class App implements AfterViewInit, OnInit {
faTachometerAlt = faTachometerAlt;
faSortAmountDown = faSortAmountDown;
faSortAmountUp = faSortAmountUp;
+ faChevronRight = faChevronRight;
subtitleFormats = [
{ id: 'srt', text: 'SRT' },
{ id: 'txt', text: 'TXT (Text only)' },
@@ -722,6 +724,24 @@ export class App implements AfterViewInit, OnInit {
return result;
}
+ 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;
|