# Changelog All notable changes to NovaSonic are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Versioning: two-part `MAJOR.MINOR` — each release bumps the minor (features and fixes together). Die Android-App zählt eigenständig weiter (mehrere APKs pro Release). Welche das waren, steht in einer **Android:**-Zeile direkt unter der Release-Überschrift — die Einträge darunter beschreiben nur noch, *was* sich geändert hat, nicht in welchem APK. --- ## Platform Parity Matrix | Feature | Web (PWA) | Android | |----------------------------------|:---------:|:-------:| | Music playback (Navidrome) | ✅ | ✅ | | Seek bar / scrubbing | ✅ | ✅ | | Queue management | ✅ | ✅ | | Warteschlange bearbeiten (ziehen/löschen) | ✅ | ✅ | | Shuffle / Repeat | ✅ | ✅ | | Radio mode (similar songs) | ✅ | ✅ | | Now Playing overlay | ✅ | ✅ | | Dominant color background | ✅ | ✅ | | Cover art scale animation | ❌ | ✅ | | Synced lyrics (LRCLIB) | ✅ | ✅ | | Lyrics-Mitlaufen (umschaltbar) | ✅ | ✅ | | Star / favorite song | ✅ | ✅ | | Multi-artist navigation | ✅ | ✅ | | Album detail page | ✅ | ✅ | | Artist page (Navidrome) | ✅ | ✅ | | Artist page (Deezer fallback) | ✅ | ✅ | | Global search source | Deezer | Deezer | | Same-name artist disambiguation | ✅ | ✅ | | Artist fan count shown | ✅ | ✅ | | 30s preview control bar | ✅ | ✅ | | Concert events (Ticketmaster) | ✅ | ✅ | | Genre browsing | ✅ | ✅ | | Global search | ✅ | ✅ | | Playlist browsing | ✅ | ✅ | | Playlist create/edit | ✅ | ✅ | | Playlist cover upload | ✅ | ✅ | | Besitzer geteilter Playlists | ✅ | ✅ | | Künstler folgen / Album merken | ✅ | ✅ | | Neu von deinen Künstlern | ✅ | ✅ | | Konzerte deiner Künstler | ✅ | ✅ | | Spotify / YouTube importer | ✅ | ✅ | | Musik-Duell (Anzeigetafel) | ✅ | ✅ | | Wiedergabe fortsetzen | ✅ | ✅ | | Teilen per Link | ✅ | ✅ | | Album → Künstler (Deezer-Suche) | ✅ | ✅ | | Playlist aus Import anlegen | ✅ | ✅ | | Song von Festplatte löschen | ✅ | ✅ | | Metadata editor (tags + cover) | ✅ | ❌ | | Song delete (from disk) | ✅ | ❌ | | Import notification | ✅ | ✅ | | Import notification → nav | ✅ | ✅ | | ABS (Audiobookshelf) playback | ✅ | ✅ | | ABS chapter navigation | ✅ | ✅ | | ABS sleep timer | ✅ | ✅ | | ABS playback speed | ✅ | ✅ | | ABS library search | ✅ | ✅ | | ABS book descriptions (HTML) | ✅ | ✅ | | Media notification | ✅ | ✅ | | ABS notification (modern style) | ❌ | ✅ | | Android Auto | — | ✅ | | Offline download (albums/playlists) | ❌ | ✅ | | Downloads nur über WLAN | — | ✅ | | Offline download (single songs) | ❌ | ✅ | | Offline playback | ❌ | ✅ | | Offline detail / manage downloads | ❌ | ✅ | | Player bar on all screens | ✅ | ✅ | | Timestamped play-log (own scrobble) | ✅ | ✅ | | Listening statistics view | ✅ | ✅ | | Stats cover art (artist/album) | ✅ | ✅ | | Musik-Match (Head-to-Head) | ✅ | ✅ | | Yearly Wrapped | 🔜 | 🔜 | | Romaji / Japanese sort | ✅ | ❌ | | Settings (Navidrome, ABS, etc.) | ✅ | ✅ | --- ## [3.3] — 2026-10-13 **Android:** 1.26 (versionCode 29) → 1.27 (versionCode 30). ### Fixed - **Now-Playing passte sich der Anzeige nicht an (Android)** — gemeldet auf einem aufgeklappten Fold: die Ansicht wirkte überdimensional. Ursache war, dass die Seite überhaupt keine Breitengrenze hatte: das Cover war `fillMaxWidth()` mal `aspectRatio(1f)`. Auf einem Handy sind das knappe 360 dp und passt; aufgeklappt sind es über 800 dp, und ein quadratisches Bild dieser Größe schob Titel, Fortschrittsbalken und Knopfreihe aus dem Bild. Die Web-Ansicht deckelt dasselbe seit immer bei 480 px (`.np-inner`), Android jetzt auch. - **Das Cover nimmt das Kleinste aus drei Maßen:** verfügbare Breite, Höhe abzüglich dessen was der Rest der Seite braucht, und 400 dp als Obergrenze. Auf einem hohen Handy gewinnt wie bisher die Breite — dort ändert sich nichts. - **Breitengrenzen** für Titelblock, Fortschritt und Knöpfe (480 dp) sowie für Liedtext und Warteschlange (560 dp). Ohne sie standen Schließen-Knopf und Menü ganz außen und die Reiter einsam in der Mitte, und eine Textzeile lief über die ganze Tischbreite. - **Höhe statt Breite als Maß.** Bei einer fast quadratischen Anzeige sagt die Breite nichts mehr darüber, ob ein quadratisches Bild hineinpasst. - **Kurze Anzeigen: Knopfreihe war abgeschnitten (Android)** — auf dem Frontdisplay eines Flip, im Querformat und auf kleinen Handys reichte die Höhe nicht, und die Spalte wurde einfach beschnitten. Jetzt schrumpfen auf kurzen Anzeigen Abstände, Reiter und Abspielknopf, und wenn es dann noch nicht reicht, **lässt sich die Player-Seite rollen**. Beides in einem Aufbau: der Inhalt ist mindestens so hoch wie die Seite — passt er, wird er zentriert; passt er nicht, wächst er darüber hinaus und der Rollbereich hat etwas zu rollen. Die Wischgeste zum Schließen bleibt erhalten, weil ein Rollbereich ohne Weg die Geste nicht verbraucht. - Entschieden wird nach **Maßen, nicht nach Gerätenamen**: `kurz` unter 560 dp Höhe, `schmal` unter 356 dp Breite (oder kurz). Damit greift es auf Fold zugeklappt, Flip-Frontdisplay, Tablet, Querformat und geteiltem Bildschirm gleichermaßen. - **Auf einem gewöhnlichen Handy ändert sich nichts.** Die Schwellen liegen bewusst außerhalb dessen, was Handys im Hochformat messen (360–448 dp breit, 700 dp und mehr hoch): dort ist weiterhin die Breite das engste Maß, das Cover also exakt so groß wie bisher, der Aufbau oben beginnend mit 28 dp Abstand und die Kopfzeile unverändert. Senkrecht zentriert wird nur, wenn eine der neuen Grenzen wirklich greift. Der Rollbereich liegt auf jeder Anzeige darunter, hat aber bei passendem Inhalt den Weg null und verhält sich wie keiner. ## [3.2] — 2026-10-01 **Android:** 1.25 (versionCode 28) → 1.26 (versionCode 29). ### Added - **Lyrics: Mitlaufen ein- und ausschalten (Web + Android)** — im Lyrics-Reiter sitzt jetzt ein kleiner Schalter *Mitlaufen / Folgt*. Aus heißt: der Text bleibt stehen, man scrollt selbst. An heißt: der Text springt mit und hält die laufende Zeile bei 40 % Höhe. - **Vorgabe ist AUS.** Wer mitliest, blättert auch mal zurück oder vor — und genau dann sprang der Text bisher bei jeder neuen Zeile unter dem Finger weg. - **Nur bei synchronen Texten sichtbar.** Ohne Zeitstempel gibt es nichts mitzuführen; bei reinem Text erscheint der Schalter nicht. - Hervorgehoben wird die laufende Zeile **immer**, auch bei ausgeschaltetem Mitlaufen — man will ja sehen, wo man ist. Einschalten richtet sofort aus, statt bis zur nächsten Zeile zu warten. - Gespeichert wird pro Gerät (`ns_lyrics_folgen` im Web, `lyrics_autoscroll` in den Android- Einstellungen). Der Android-Schlüssel wird **einzeln** geschrieben: würde ihn das Speichern im Einstellungsbildschirm mitschreiben, setzte es ihn jedes Mal auf die Vorgabe zurück, weil dieser Bildschirm das Feld gar nicht führt. ### Fixed - **Mischen war nicht zufällig (Web)** — `liste.sort(() => Math.random() - 0.5)` ist keine Mischung: ein Vergleicher, der bei derselben Paarung mal so und mal anders antwortet, ist für eine Sortierung ungültig, und das Ergebnis ist messbar verzerrt. Gemessen (V8, 3000 Durchläufe) blieb der erste Titel drei- bis fünfmal zu oft vorn — bei 10 Titeln in 18,8 % der Fälle statt 10 %, bei 100 in 3,1 % statt 1 %, bei 2000 in 0,23 % statt 0,05 %. Die Grobordnung sah dabei gemischt aus, weshalb es lange nicht auffiel; bevorzugt wurden trotzdem immer dieselben Titel. Ersetzt durch Fisher-Yates in `src/player/queueMath.js` (`mischeListe`), verwendet an allen vier Stellen: Warteschlange starten, Mischen umschalten und die beiden Genre-Knöpfe. - **Der letzte Titel lief mehrfach wieder los (Web/PWA)** — am Ende der Warteschlange ohne Repeat steht nichts mehr an, trotzdem spielte der letzte Titel bei jedem Zurückholen der Seite erneut. Ursache: ein beendetes `