feat(downloads): M5 — Download Center frontend

- api.ts: download types + methods (profiles, enqueue, list/manage, file url, share,
  usage, index, admin storage/quota)
- format.ts: formatBytes / formatSpeed
- i18n: en/hu/de downloads.json (trilingual)
- Downloads nav module (Download icon, active-count badge, hidden for demo) placed after
  Messages; urlState page + App render + Header title
- DownloadButton: self-contained per-card/player affordance (demo-hidden, reflects the
  per-user download index: downloaded / in-queue), opens the preset dialog
- DownloadDialog: preset picker + optional display name -> enqueue + 'View' toast
- ProfileEditor: manage built-in + custom formats (full spec form incl. SponsorBlock)
- DownloadCenter: Queue / Library / Shared / (admin) System tabs, live progress via
  useLiveQuery, usage bar, pause/resume/cancel/delete, save-to-device, rename, share,
  admin storage dashboard + per-user quota editor
- wired DownloadButton into VideoCard + PlayerModal
- lib/nav.ts: decoupled navigator so the download toast can jump to the page

tsc + vite build clean. Verified in a headless authed browser: page + tabs render, Library
shows a real download with usage bar + actions, no console errors.
This commit is contained in:
npeter83 2026-07-03 01:52:58 +02:00
parent 51158ad9cf
commit 7d1ed24fea
17 changed files with 1551 additions and 1 deletions

View file

@ -0,0 +1,136 @@
{
"navLabel": "Downloads",
"button": {
"label": "Herunterladen",
"queued": "In Warteschlange",
"downloaded": "Heruntergeladen"
},
"dialog": {
"title": "Video herunterladen",
"profile": "Format",
"nameLabel": "Dateiname (optional)",
"namePlaceholder": "Leer lassen, um den Videotitel zu verwenden",
"submit": "Zu Downloads hinzufügen",
"added": "Zu Downloads hinzugefügt",
"view": "Öffnen",
"manage": "Formate verwalten"
},
"page": {
"title": "Downloads",
"subtitle": "Videos auf den Server laden und dann auf dein Gerät speichern.",
"addUrl": "YouTube-Link oder Video-ID einfügen…",
"add": "Hinzufügen",
"manage": "Formate verwalten"
},
"tabs": {
"queue": "Warteschlange",
"done": "Bibliothek",
"shared": "Mit mir geteilt",
"system": "System"
},
"status": {
"queued": "Wartet",
"running": "Lädt",
"paused": "Pausiert",
"done": "Fertig",
"error": "Fehlgeschlagen",
"canceled": "Abgebrochen",
"expired": "Abgelaufen"
},
"actions": {
"pause": "Pause",
"resume": "Fortsetzen",
"cancel": "Abbrechen",
"delete": "Entfernen",
"retry": "Erneut",
"download": "Auf mein Gerät speichern",
"rename": "Umbenennen",
"share": "Teilen"
},
"empty": {
"queue": "Die Warteschlange ist leer.",
"done": "Noch keine Downloads.",
"shared": "Es wurde nichts mit dir geteilt.",
"admin": "Auf dieser Instanz gibt es noch keine Downloads."
},
"usage": {
"title": "Dein Speicher",
"items": "{{used}} / {{max}} Elemente",
"unlimited": "Unbegrenzt"
},
"rename": {
"title": "Download umbenennen",
"label": "Anzeigename",
"hint": "Ändert nur den angezeigten und beim Speichern verwendeten Namen — die gespeicherte Datei behält ihren Namen.",
"save": "Speichern"
},
"share": {
"title": "Download teilen",
"label": "E-Mail des Empfängers",
"placeholder": "user@example.com",
"submit": "Teilen",
"done": "Geteilt mit {{email}}"
},
"confirm": {
"cancelTitle": "Download abbrechen?",
"cancelBody": "Dies stoppt den Download und entfernt ihn aus deiner Warteschlange.",
"deleteTitle": "Download entfernen?",
"deleteBody": "Dies entfernt ihn aus deiner Liste. Die Datei kann bis zum Ablauf für andere Nutzer im Cache bleiben."
},
"profiles": {
"manage": "Formate verwalten",
"title": "Download-Formate",
"builtin": "Integriert",
"yours": "Deine Formate",
"new": "Neues Format",
"name": "Name",
"namePlaceholder": "Mein Format",
"mode": "Inhalt",
"modeAv": "Video + Audio",
"modeV": "Nur Video",
"modeA": "Nur Audio",
"quality": "Max. Qualität",
"best": "Beste",
"container": "Container",
"audioFormat": "Audioformat",
"vcodec": "Video-Codec",
"any": "Beliebig",
"embedSubs": "Untertitel einbetten",
"embedChapters": "Kapitel einbetten",
"embedThumbnail": "Vorschaubild einbetten",
"sponsorblock": "Sponsor-Segmente überspringen (SponsorBlock)",
"save": "Speichern",
"create": "Erstellen",
"delete": "Löschen",
"deleteConfirm": "Das Format „{{name}}“ löschen?"
},
"admin": {
"storageTitle": "Speicher",
"readyFiles": "Fertige Dateien",
"totalSize": "Gesamtgröße",
"cap": "Cache-Limit",
"noCap": "kein Limit",
"perUser": "Speicher pro Nutzer",
"user": "Nutzer",
"footprint": "Belegung",
"editQuota": "Kontingent bearbeiten",
"quotaTitle": "Download-Kontingent — {{email}}",
"maxBytes": "Speicherlimit (GB)",
"maxJobs": "Max. Downloads",
"maxConcurrent": "Max. gleichzeitig",
"unlimited": "Unbegrenzt (Speicherlimit umgehen)",
"reset": "Auf Standard zurücksetzen",
"save": "Speichern",
"custom": "individuell",
"default": "Standard"
},
"cols": {
"title": "Titel",
"channel": "Kanal",
"format": "Format",
"size": "Größe",
"status": "Status",
"added": "Hinzugefügt",
"user": "Nutzer"
}
}