From 44eb8c758a3706c58718fdc0c7748ebcecccd106 Mon Sep 17 00:00:00 2001 From: xpltd Date: Thu, 19 Mar 2026 04:13:17 -0500 Subject: [PATCH] Clear button, toolbar row, admin format defaults, cyberpunk background MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Queue toolbar: - Filter tabs (All/Active/Completed/Failed) and action buttons (Download All/Clear) share one row — filters left, actions right - Download All moved from DownloadTable to DownloadQueue toolbar - Clear button: muted style → red border on hover → 'Sure?' red confirm state → executes on second click, auto-resets after 3s - Clear removes all completed and failed jobs (leaves active untouched) Admin format defaults: - Settings tab has Video/Audio default format dropdowns - Stored in settings_overrides (same as welcome_message) - Public config returns default_video_format and default_audio_format - UrlInput resolves Auto format against admin defaults — if admin sets audio default to MP3, 'Auto' chip shows 'Auto (.mp3)' and downloads convert accordingly Cyberpunk animated background: - Diagonal crossing lines (blue 45° + orange -45°) drift slowly (60s cycle) - Subtle radial gradient pulse (8s breathing effect) - Layered on top of the existing grid pattern - All CSS-only, no JS — zero performance cost - Only active on cyberpunk theme (scoped to [data-theme=cyberpunk]) --- backend/app/routers/system.py | 2 + frontend/src/api/types.ts | 2 + frontend/src/components/AdminPanel.vue | 72 +++++++++- frontend/src/components/DownloadQueue.vue | 153 ++++++++++++++++++++-- frontend/src/components/DownloadTable.vue | 49 ------- frontend/src/components/UrlInput.vue | 24 +++- frontend/src/tests/stores/config.test.ts | 2 + frontend/src/themes/cyberpunk.css | 47 +++++++ 8 files changed, 288 insertions(+), 63 deletions(-) diff --git a/backend/app/routers/system.py b/backend/app/routers/system.py index d2db471..cf6a5b9 100644 --- a/backend/app/routers/system.py +++ b/backend/app/routers/system.py @@ -32,4 +32,6 @@ async def public_config(request: Request) -> dict: ), "purge_enabled": config.purge.enabled, "max_concurrent_downloads": config.downloads.max_concurrent, + "default_video_format": overrides.get("default_video_format", "auto"), + "default_audio_format": overrides.get("default_audio_format", "auto"), } diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index 90dd81c..f681f77 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -73,6 +73,8 @@ export interface PublicConfig { welcome_message: string purge_enabled: boolean max_concurrent_downloads: number + default_video_format: string + default_audio_format: string } export interface HealthStatus { diff --git a/frontend/src/components/AdminPanel.vue b/frontend/src/components/AdminPanel.vue index 4f3587c..9e492b3 100644 --- a/frontend/src/components/AdminPanel.vue +++ b/frontend/src/components/AdminPanel.vue @@ -16,6 +16,8 @@ const loadingJobs = ref>(new Set()) // Settings state const welcomeMessage = ref('') +const defaultVideoFormat = ref('auto') +const defaultAudioFormat = ref('auto') const settingsSaved = ref(false) function formatBytes(bytes: number): string { @@ -34,6 +36,8 @@ async function switchTab(tab: typeof activeTab.value) { try { const config = await api.getPublicConfig() welcomeMessage.value = config.welcome_message + defaultVideoFormat.value = config.default_video_format || 'auto' + defaultAudioFormat.value = config.default_audio_format || 'auto' } catch { // Keep current value } @@ -42,7 +46,11 @@ async function switchTab(tab: typeof activeTab.value) { async function saveSettings() { settingsSaved.value = false - const ok = await store.updateSettings({ welcome_message: welcomeMessage.value }) + const ok = await store.updateSettings({ + welcome_message: welcomeMessage.value, + default_video_format: defaultVideoFormat.value, + default_audio_format: defaultAudioFormat.value, + }) if (ok) { settingsSaved.value = true setTimeout(() => { settingsSaved.value = false }, 3000) @@ -204,6 +212,33 @@ function formatFilesize(bytes: number | null): string { placeholder="Enter a welcome message…" > + +
+ +

When "Auto" is selected, files are converted to these formats instead of the native container.

+
+
+ Video + +
+
+ Audio + +
+
+
+