A single-language interface makes the app less usable for part of the audience
and encourages more hardcoded copy as new screens and states are added.
Introducing a shared i18n path with a persisted language preference gives the
UI one consistent way to present text and lowers the risk of partial or
inconsistent localization over time.
The surrounding copy cleanup belongs in the same change because it aligns
existing labels, messages, and settings text with that translation structure
instead of leaving mixed localization approaches in place.
Quality selection during playback:
- Add getAvailableQualities() in streamlink via --json, sorted by fixed order
- Expose playback:get-qualities IPC channel (handlers, preload, type declarations)
- Add quality panel in PlaybackOverlay:
- Button + dropdown
- Keyboard navigation (X: open, arrows: navigate, Enter: confirm, Escape: close)
- Quality change triggers streamlink restart; VOD resumes at current position
- Available in ChannelScreen (Live + VOD) and AppShell global overlay (Live)
- Add QualityIcon
Chapter panel UX improvements:
- Video no longer pauses when chapter panel opens
- PlaybackOverlay is hidden via conditional render instead
- Remove wasPlayingBeforeChapters state (no longer needed)
- X button seeks to video start when no chapters are found, with hint in panel UI
VOD cards and defaults:
- Show view count with eye icon on VOD cards (matching playback overlay style)
- Change default streamBadgeMode from 'language' to 'both'
New PlaybackOverlay component replaces the old hint bar in ChannelScreen.
The overlay sits as a fullscreen layer above the app during playback:
- Auto-hides after 5 s while playing; stays visible when paused;
reactivated by any gamepad key press or mouse movement
- Center play/pause button, channel avatar, title, LIVE badge
- VOD: seek bar with pointer-capture scrubbing, current time / total duration
- Live: pulsing LIVE indicator instead of seek bar
- Double-tap zones left/right (±10 s) with animated skip feedback
- Gamepad hints in the top bar
- New icons: PlayIcon, PauseIcon, StopIcon in Icons.tsx
- New IPC channel `playback:time-update` (~1 Hz) pushes absolute playback
position from main process to renderer; adds PlaybackTimeUpdate type
and onTimeUpdate bridge in preload + t4sd.d.ts
- PlaybackEvent extended with durationSeconds and isLive fields
- ffmpeg-full im Flatpak eingebunden für vollständiges H.264/VAAPI-Decoding
- Trigger-Repeat für L2/R2 deaktiviert, um gestapelte 300s-Seeks zu vermeiden
- fMP4-HLS-Playlists über EXT-X-MAP erkannt
- große fMP4-Seeks nicht mehr per In-Stream-Seek, sondern per Reload einer getrimmten Playlist
- getrimmte Playlists über localhost statt file:// ausgeliefert
- absoluten Playback-Offset eingeführt, damit mehrfaches R2 korrekt weiter vorspult
- B Button ermöglicht, mit der selektierung zurück zum sidemenu zurückzukehren
- Logging Schalter dem Einstellungs Screen hinzugefügt
streamlink.ts — 3 neue mpv-Argumente für VODs
- --demuxer-max-bytes=150M / --demuxer-max-back-bytes=75M — größerer Buffer, verhindert Flush bei Seeks
- --hr-seek=no — Keyframe-only Seeks, zuverlässiger für HLS
mpvController.ts — 2 Änderungen - Relative Seeks jetzt relative+keyframes (statt relative) — konsistent mit seekAbsolute - Neue pollTimePos()-Methode als Fallback wenn observe_property nicht feuert
playbackService.ts — Kerndfix
- playback-restart statt file-loaded für den initialen Resume-Seek — wartet bis der erste Frame dekodiert ist, statt nur auf das Manifest
- Seek-Verify nach 5s — prüft ob der Seek geklappt hat, Retry falls nicht
- Poll-Fallback nach 10s — startet Polling falls time-pos nie über observe_property kommt
- Cleanup in stop() für die neuen Timer/Callbacks
- Kapitel werden via Twitch GQL API geladen
- Kapitelauswahl als Modal-Overlay zentriert dargestellt
- A-Taste pausiert/setzt VOD-Wiedergabe fort (war: Stop)
- Unter "Du folgst" wurde immer der erste Kanal aufgerufen, unabhängig vom ausgewählten Kanal
- Abbrechen der Wiedergabe auch unter "Durchsuchen" und Top-Stream möglich.
- SQLite-Setup: `src/main/store/db.ts` (better-sqlite3, Migration)
- Lokaler VOD-Verlauf (Resume)
- mpv `time-pos`-Observer schreibt alle ~5s in DB
- Auto-Resume: beim VOD-Start Position aus DB lesen → `--start=<s>`
-Resume-Indikator auf VOD-Karte
- Completed-Indikator (dunkles Overlay + Checkmark)