Auf Wunsch: was vom Handy hochgeladen wird, soll auch in Navidrome auftauchen. Die Subsonic-API kennt keinen Upload — also erledigt es die Melo-Cloud selbst. Server (/home/dustin/scripts/melo_cloud.py, nicht versioniert — Backup als melo_cloud.py.bak-20260821-084506): - verknuepfe_navidrome(): Hardlink der Registry-Datei nach /home/dustin/navidrome/music (Bind-Mount des Containers). Gleiche Partition -> kein zusaetzlicher Speicher. Fallback: Kopie. - rescan_navidrome(): Subsonic startScan.view ueber Navidromes AuthProxyHeader (TrustedSources 127.0.0.1) — kein Passwort im Code. Nur zur Beschleunigung, der Watcher findet neue Dateien ohnehin. - upload() verknuepft neue UND bereits bekannte Titel (heilt Bestand). - handle_delete() entfernt die Datei aus Registry + Navidrome, sobald kein Konto sie mehr aktiv hat. Der Registry-EINTRAG bleibt stehen: handle_list haengt die Grabsteine daran (JOIN registry) — ohne ihn erfuehren die anderen Geraete nie von der Loeschung (Zombie-Song). - registry_pfad(): gemeinsame Dateisuche ueber alle Audio-Endungen, mit Rueckfall auf den Navidrome-Ordner. Nebenbei repariert: - Alle 325 Cloud-Dateien lagen nur noch im Navidrome-Ordner, REG war leer: jeder Download antwortete "File missing". Per Hardlink zurueckverknuepft (scripts/melo_cloud_migriere_registry.py). - upload() legte jede Datei als ".mp3" ab, auch m4a/flac. Jetzt echte Endung; _download liefert passenden Content-Type und einen Dateinamen ohne doppelte Endung. App: - MeloCloudService.herunterladen() gibt die geschriebene Datei zurueck und leitet die Endung aus dem Content-Type ab (endungFuer) — sonst landet eine M4A als .mp3 auf dem Handy und Android ordnet sie falsch ein. - loeschBremseGreift(): der Abgleich reicht keine Loeschwelle mehr zum Server durch (>10 Titel UND >1/3 des Serverbestands). Ohne die Bremse haette eine nicht eingehaengte Speicherkarte die Sammlung auf allen Geraeten geloescht. 276 Tests gruen (1 uebersprungen), flutter analyze ohne Befund, plus ein Durchlauf gegen den echten Server (scripts/test_melo_cloud_navidrome.py): Upload -> Registry + Navidrome (ein Hardlink) -> Navidrome liest ein -> Loeschen entfernt beides, Grabstein bleibt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FpPu4nuKjKKeX1RpdDeX81
34 KiB
Changelog
Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert. Format angelehnt an Keep a Changelog.
[Unreleased]
📚 Hochgeladene Titel landen jetzt auch in Navidrome (2026-08-21)
- 🎵 Was sich ändert: Was du vom Handy hochlädst, taucht ab sofort auch in der Navidrome-Bibliothek auf — also im Browser und in jeder anderen Musik-App, die auf den Server zugreift. Vorher blieb es in der Melo-Cloud liegen und war nur in Melo sichtbar. 🔧 Wie: Die Melo-Cloud hängt die hochgeladene Datei zusätzlich in Navidromes Musikordner (als Hardlink — dieselbe Datei unter zwei Namen, also kein zusätzlicher Speicherplatz) und stößt einen Scan an. Navidrome hat den Titel binnen Sekunden. Löschst du ihn, verschwindet er auch aus Navidrome — aber nur, wenn ihn kein anderes Konto mehr hat. ⚠️ Zu wissen: Navidrome hat eine gemeinsame Bibliothek. Was ein Konto hochlädt, sehen dort alle Navidrome-Nutzer. In Melo bleibt die Trennung pro Konto bestehen.
- 🩹 Nebenbei repariert: Downloads vom Server gingen gar nicht. Die 325 Titel der Melo-Cloud lagen nur noch im Navidrome-Ordner — der Ablageordner der Cloud war leer. Jeder Download antwortete deshalb mit „File missing". Alle Dateien sind zurückverknüpft, Downloads gehen wieder.
- 🏷️ Nebenbei repariert: falsche Dateiendungen. Hochgeladene Dateien
wurden immer als
.mp3abgelegt, auch M4A und FLAC; heruntergeladene bekamen den NamenLied.m4a.m4a. Jetzt zählt der echte Dateityp — auf dem Server wie auf dem Handy (wichtig, damit Android den Titel richtig einordnet). - 🛑 Neu: Sicherheitsbremse gegen Massenlöschung. Der Bibliotheks-Scan markiert jeden Titel als gelöscht, dessen Datei er nicht findet. Ist die Speicherkarte einmal nicht eingehängt oder die Berechtigung entzogen, betrifft das die halbe Sammlung — und ohne Bremse hätte der Abgleich sie am Server und damit auf allen Geräten gelöscht. Melo hält jetzt an, wenn mehr als 10 Titel und mehr als ein Drittel des Serverbestands auf einmal verschwinden sollen, und sagt warum. Einzelne Löschungen laufen unverändert durch.
- 🔧 Details für Technikinteressierte:
melo_cloud.py:verknuepfe_navidrome()(Hardlink, Fallback Kopie),loese_navidrome(),rescan_navidrome()(SubsonicstartScan.viewüber NavidromesAuthProxyHeader— kein Passwort im Code),registry_pfad()als gemeinsame Dateisuche über alle Audio-Endungen.handle_delete()räumt die Datei ab, sobald kein Konto sie mehr aktiv hat — der Registry-Eintrag bleibt aber stehen, sonst verlöre/listden Grabstein und andere Geräte bekämen den Titel als Zombie zurück.- Neu:
scripts/melo_cloud_migriere_registry.py(einmalige Rückverknüpfung) undscripts/test_melo_cloud_navidrome.py(Durchlauf-Test). - App:
MeloCloudService.herunterladen()gibt die geschriebene Datei zurück und leitet die Endung aus dem Inhaltstyp ab (endungFuer);loeschBremseGreift()insync_service.dart.
- ✅ Getestet: 276 Tests grün (9 neue) plus ein Durchlauf gegen den echten Server: Upload → Registry + Navidrome (ein Hardlink) → Navidrome liest ein → Löschen entfernt beides, Grabstein bleibt.
🔊 Lokale Lieder spielen wieder + Abgleich zwischen Handy und Server (2026-08-21)
-
▶️ Behoben: Musik vom Handy war nicht abspielbar. Titel, die auf dem Gerät liegen, tauchten zwar in der Bibliothek auf, beim Antippen kam aber nur „Wiedergabe fehlgeschlagen: (0) Source error" oder „Loading interrupted". 🐛 Die Ursache: Sobald ein Musikserver eingerichtet war, hat Melo jeden Titel beim Server nachgefragt — auch die vom Handy. Als „Song-Nummer" schickte die App dabei den Dateipfad (
file:///storage/…). Der Server kennt so etwas natürlich nicht und antwortete mit einer Fehlermeldung. Diese Fehlermeldung reichte Melo dann als „Musikdatei" an den Player weiter — daher der Fehler. Schlimmer noch: die Fehlermeldung wurde als.mp3im Zwischenspeicher abgelegt, wodurch der Titel dauerhaft kaputt blieb. 🔧 Was jetzt anders ist: Melo unterscheidet sauber zwischen Titeln vom Gerät und Titeln vom Server. Für eine Datei auf dem Handy geht keine einzige Anfrage mehr ins Netz — sie wird direkt abgespielt. -
⚡ Behoben: Wiedergabe startete gar nicht mehr. Beim Antippen eines Liedes lud Melo vorher die gesamte Warteschlange vom Server herunter, bevor der erste Ton kam — bei hunderten Titeln also nie. Tippte man noch einmal, brach der laufende Ladevorgang ab („Loading interrupted"). 🔧 Jetzt startet der Titel sofort; das Zwischenspeichern für später läuft im Hintergrund und nur für das Lied, das gerade läuft.
-
💾 Behoben: der Offline-Zwischenspeicher wurde nie wiedergefunden. Als Ablage-Schlüssel diente die komplette Stream-Adresse — die enthält aber ein Zufallsmerkmal, das Melo bei jedem App-Start neu erzeugt. Derselbe Titel bekam also jedes Mal einen anderen Schlüssel: der Zwischenspeicher wuchs nur noch und half nie. Jetzt zählt die Song-Nummer, und offline gespeicherte Server-Titel laufen wirklich ohne Netz.
-
🧹 Zwischenspeicher kann sich nicht mehr vergiften: Es wird erst in eine
.part-Datei geschrieben und nur dann als Musik übernommen, wenn der Server wirklich Audio geliefert hat. Abgebrochene Downloads hinterlassen keine halben Dateien mehr. -
☁️ Neu: Abgleich zwischen Handy, Server und Web. Unter Einstellungen → Geräte-Abgleich hält Melo alles auf demselben Stand:
- ⬇️ Titel vom Server landen als richtige Datei auf dem Handy und sind danach offline verfügbar.
- ⬆️ Eigene Dateien vom Handy gehen zum Server — auch von anderen Geräten aus abrufbar.
- 🗑️ Löschungen wirken in beide Richtungen: was hier verschwindet, taucht auf den anderen Geräten nicht wieder auf, und umgekehrt.
- ❤️ Favoriten und 🕐 Wiedergaben werden mitgemeldet.
- 🔄 Das passiert automatisch beim App-Start und beim Zurückkehren in
die App (höchstens alle 15 Minuten, damit es keinen Akku frisst). Der
Knopf für „jetzt sofort" ist trotzdem da.
⚠️ Ehrlich gesagt: Der Abgleich läuft über die Melo-Cloud
(
cloud.baka-net.de), nicht über Navidrome. Grund: Navidrome bietet schlicht keine Möglichkeit, Dateien hochzuladen — die Subsonic-Schnittstelle kennt keinen Upload. Navidrome bleibt die Streaming-Bibliothek, die Melo-Cloud ist der gemeinsame Speicher. Dafür ist eine Anmeldung beim Baka-Konto nötig (Tab Online → YouTube). Einzelne Datei: max. 50 MB.
-
🏷️ Behoben: Korrigierte Titelangaben gingen beim Scannen verloren. Wer Titel, Künstler oder Album von Hand richtiggestellt hatte, bekam beim nächsten Bibliotheks-Scan wieder die falschen Angaben aus der Datei. Die Markierung „von Hand bearbeitet" wurde nirgends gesetzt und nirgends beachtet. Jetzt schon — in beiden Scans (Handy und Ordner).
-
🔧 Details für Technikinteressierte:
MeloAudioHandler.loadPlaylistbaut die Warteschlange ohne Netzzugriff; neue reine FunktionennavidromeIdOf,songIdOf,nutztServerCache,quelleFuer.- Server-Titel tragen ihre Server-Nummer in
MediaItem.extras['navidromeId']statt sie aus der Abspiel-Adresse zu raten. NavidromeService.ladeInCache()ersetztstreamAndCacheToLocal():.part-Datei + Prüfung des Inhaltstyps (istAudioAntwort) + stabiler Schlüssel (cacheSchluessel); der HTTP-Client wird geschlossen.- Neu:
services/melo_cloud_service.dart,services/sync_service.dartmit der reinen PlanungsfunktionplaneSync(). - Datenbank auf Version 8: neue Spalte
songs.cloud_idverbindet einen Titel auf dem Gerät mit seinem Gegenstück am Server. database.g.dartwar veraltet und musste neu erzeugt werden — dadurch ließ sich das Projekt vorher gar nicht übersetzen.
-
✅ Getestet: 267 Tests grün (78 neue),
flutter analyzeohne Befund. -
⚠️ Offen: Ein bestehender Widget-Test (
song_detail_sheet_test.dart) bleibt beim Öffnen des Detail-Fensters hängen und blockierte den gesamten Testlauf. Er ist vorerst als übersprungen markiert; sein Zweck wird jetzt vonmetadaten_uebernahme_test.dartohne Widgets abgedeckt.
🔎 Melo merkt selbst, wenn neue Musik da ist (2026-08-20)
- 📂 Neue Dateien auf dem Handy: Kommst du in die App zurück, sieht Melo nach, ob sich der Musikbestand geändert hat — und liest neue Titel von allein ein. Musik per Kabel überspielt oder anderswo heruntergeladen? Sie ist einfach da, ohne dass du "Musik scannen" antippen musst. 🔧 Wie sparsam das ist: Melo vergleicht nur die Anzahl der Dateien und prüft höchstens alle 5 Minuten. Der eigentliche Scan läuft nur, wenn die Zahl abweicht — sonst passiert gar nichts. ⚠️ Grenze, ehrlich gesagt: Werden genauso viele Titel gelöscht wie hinzukommen, bleibt die Zahl gleich und Melo merkt es nicht. Dafür gibt es weiterhin den Knopf zum Scannen von Hand.
- 🌐 Neues auf dem Musikserver: Im Tab Online → Server erscheint ein Hinweis, wenn auf Navidrome Alben dazugekommen sind ("3 neue Alben auf dem Server"). Ein Tipp auf Verstanden und der Hinweis ist weg — dieselben Alben melden sich nicht noch einmal. 🔧 Beim allerersten Mal meldet Melo bewusst nichts: sonst wäre deine ganze Sammlung auf einmal "neu". Melo merkt sich still den Stand und meldet ab dann nur noch, was wirklich dazukommt. Der Hinweis kostet keinen zusätzlichen Serveraufruf — er nutzt die Alben, die ohnehin geladen werden.
- 🔧 Details:
- Neu:
library/auto_scan.dart(6 Tests),services/server_neuheiten.dart(5 Tests),MeloDb.countSongs()(1 Test),countAndroidMediaStoreSongs(). HomeShellhört jetzt auf den App-Lebenszyklus (resumed).
- Neu:
- ✅ Getestet: 189 Tests grün (12 neue),
flutter analyzeohne Befund.
⬇️ YouTube-Downloader mit Baka-Anmeldung (2026-08-20)
- 🎬 Musik von YouTube holen: Im Tab Online → YouTube eine Adresse einfügen, auf Herunterladen tippen — fertig. Der Titel landet danach automatisch in Meine Musik.
- 🔑 Warum eine Anmeldung nötig ist: Das Herunterladen erledigt der Baka-Server (yt.baka-net.de), und der nimmt nur Anfragen von angemeldeten Konten an. Deshalb gibt es im YouTube-Bereich einen Anmelde-Knopf für dein Baka-Konto. Die Anmeldung wird verschlüsselt auf dem Gerät gespeichert und gilt auch nach dem Neustart. Läuft sie ab, sagt Melo das im Klartext ("Anmeldung abgelaufen — bitte neu anmelden") statt eine Fehlernummer zu zeigen.
- 📂 Wo die Musik landet: In
Music/Melo— dem öffentlichen Musikordner. Das ist wichtig: Melo liest seine Bibliothek auf Android über den MediaStore. Eine Datei, die nur in einem App-Ordner läge, wäre beim nächsten Scan wieder verschwunden. Nebeneffekt: die Musik ist auch in anderen Apps da. - 🧹 Keine Bruchstücke: Der Download geht erst in einen Zwischenordner. Erst wenn die Datei vollständig da ist, wandert sie in den Musikordner. Bricht etwas ab, wird die halbe Datei gelöscht statt als kaputter Titel in der Bibliothek zu landen.
- 🎤 Künstler: Steht der Titel als "Künstler - Lied" da, wird der Künstler übernommen. Steht da nichts dergleichen, bleibt das Feld leer — geraten wird nicht.
- 🔧 Details:
- Neu:
services/baka_auth.dart(6 Tests),services/yt_download_service.dart(8 Tests),services/media_store.dart(2 Tests) und die native BrückeMediaStoreBridge.kt(MediaStore ab Android 10, Dateisystem + Scanner davor). WRITE_EXTERNAL_STORAGE(nur bis Android 9) im Manifest ergänzt.- Der Online-Tab hat jetzt die Unterreiter YouTube · Server (3 Tests);
SubTabsliegt dafür inshared/sub_tabs.dart. - ⚠️ Der Anmelde-Server meldet Fehler mit Status 200 und Text im Rumpf — der Code prüft deshalb den Inhalt, nicht nur den Statuscode.
- Neu:
- ✅ Getestet: 177 Tests grün (19 neue),
flutter analyzeohne Befund, Release-APK baut (22,8 MB). ⚠️ Ehrlich dazugesagt: Der Weg über den echten Proxy und das Schreiben in den Musikordner sind noch nicht auf dem Handy ausprobiert — das geht nur auf dem Gerät. Alles davor ist mit Tests abgedeckt.
🧭 Neue Tab-Struktur nach deinen Referenzbildern (2026-08-20)
- 🔀 Untere Leiste wie auf deinem Bild: Die Reihenfolge ist jetzt Meine Musik · Online · Suchen · Favoriten. Der frühere Reiter "Download" heißt jetzt Online (Musiknoten-Symbol) — dort kommt als Nächstes der YouTube-Downloader dazu.
- 🗂️ Unterreiter in "Meine Musik": Über der Liste sitzen jetzt Songs · Künstler · Alben als Pillen — genau wie in der Referenz. Der aktive Reiter ist hell, die anderen sind nur Text. Wichtig: Ein Unterreiter wechselt nur den Inhalt und öffnet keinen neuen Bildschirm — Suchfeld und Schnellzugriffe bleiben stehen.
- 🧹 Aufgeräumt: Die Schnellzugriff-Kacheln "Künstler" und "Alben" sind weg, weil sie jetzt Unterreiter sind. Übrig bleiben — wie in der Referenz — Favoriten · Wiedergabelisten · Zuletzt.
- 🔧 Details:
MyMusicScreenist jetzt zustandsbehaftet (_subTab), neues_SubTabs-Widget; die dadurch totenArtistsScreen/AlbumsScreen-Hüllen wurden entfernt (ArtistListScreen/AlbumListScreenbleiben und werden direkt eingebettet). - ✅ Getestet: 158 Tests grün (4 neue),
flutter analyzeohne Befund.
🎼 Songtext, Warteschlange, Sperrbildschirm-Cover und gleiche Lautstärke (2026-08-20)
- 📝 Automatischer Songtext: Beim Scan wird der Songtext aus dem Tag der Datei mitgelesen und in der Wiedergabe sofort angezeigt — ohne Server und ohne Internet. Nur wenn die Datei keinen Text enthält, wird der Navidrome-Server gefragt. 🐛 Nebenbei gefixt: Der Songtext-Knopf hat bisher die Datei-Adresse statt der Song-ID weitergegeben, dadurch kam vom Server nie ein Text zurück.
- ➕ Warteschlange ohne Nebenwirkungen: Im ⋮-Menü einer Songzeile gibt es jetzt "Als Nächstes spielen" und "Zur Warteschlange hinzufügen" — beides ändert nichts an Favoriten oder Wiedergabelisten und unterbricht die laufende Wiedergabe nicht. Umgekehrt entfernt das ✕ in der Warteschlange den Titel weiterhin nur dort — er bleibt Favorit und bleibt in jeder Wiedergabeliste.
- 🖼️ Sperrbildschirm zeigt dasselbe Bild wie die App: Läuft ein Titel, bekommt der Sperrbildschirm jetzt das Kategorie-Cover (sofern die Einstellung "Gleiche Kategorie = gleiches Coverbild" an ist) statt eines abweichenden Bildes. Auch Wiedergabelisten zeigen jetzt dieses Cover.
- 🔉 Gleiche Lautstärke (ReplayGain): Neuer Schalter unter Einstellungen → Ton (standardmäßig an). Melo liest den ReplayGain-Tag der Datei und senkt laute Titel ab, damit alles gleich laut wirkt. ⚠️ Ehrlich dazugesagt: Verstärken kann ein Player nicht über 100 % hinaus — angeglichen wird deshalb immer nach unten. Und es funktioniert nur bei Dateien, die den Tag mitbringen (typisch FLAC/OGG und mit ReplayGain versehene MP3s). Dateien ohne Tag bleiben unverändert.
- 🔧 Details:
- DB-Schema 6: neue Spalten
lyricsundgain_db. - Neu:
player/replay_gain.dart(7 Tests),playNextIndex+addToQueue/playNextim Audio-Handler (3 Tests), Cover-Vorgabe insongToMediaItem(3 Tests).
- DB-Schema 6: neue Spalten
- ✅ Getestet: 154 Tests grün,
flutter analyzeohne Befund.
🎚️ Equalizer, Dolby Atmos und automatische Wiedergabe (2026-08-20)
- ✅ Was: Die Einstellungen haben einen neuen Bereich Ton mit Equalizer, Dolby Atmos und der automatischen Wiedergabe bei Kopfhörern.
- 🎛️ Equalizer (echt, nicht nachgebaut): Neuer Bildschirm mit den Klangprofilen deines Geräts (Normal, Rock, Pop …), den Frequenzbändern als senkrechte Regler mit Beschriftung (60Hz … 14.0kHz) und den beiden Drehreglern Bass und Immersives Audio — wie auf deinem Bild. Zum Regeln senkrecht über den Drehregler wischen. Alle Werte werden gespeichert und nach dem Neustart wiederhergestellt.
- 🔊 Wie das technisch geht: Neue native Android-Brücke
(
AudioEffectsBridge.kt) aufandroid.media.audiofx— Equalizer, BassBoost und Virtualizer hängen an der Audio-Session des Players. Da just_audio die Session-ID erst beim Abspielen meldet, verbindet sich die App bei jedem Wechsel automatisch neu. Bietet ein Gerät einen Effekt nicht an, wird er ausgegraut statt die App abstürzen zu lassen. - 🎬 Dolby Atmos: Öffnet die Klangeffekte des Systems — auf deinem POCO ist das die Dolby-Atmos-Seite. Eine App kann Dolby Atmos nicht selbst steuern; der System-Weg ist der einzige, der wirklich funktioniert. Bietet ein Gerät die Seite nicht an, sagt Melo das.
- 🎧 Automatische Wiedergabe: Neuer Schalter — sobald Kopfhörer verbunden werden (Klinke oder Bluetooth), spielt Melo weiter. Eine bereits laufende Wiedergabe wird nie unterbrochen, und ohne Warteschlange passiert nichts.
- 🔧 Details:
- Neu:
player/audio_effects.dart(6 Tests, u. a. Grenzwerte und Wiederherstellen),player/headphone_autoplay.dart(6 Tests),settings/equalizer_screen.dartinkl. selbst gezeichnetem Drehregler. MODIFY_AUDIO_SETTINGSim Manifest ergänzt (nötig für die Effekte).MainActivity.ktregistriert die Brücke und gibt die Effekte beim Beenden wieder frei.
- Neu:
- ✅ Getestet: 141 Tests grün,
flutter analyzeohne Befund.
🏷️ Kategorien, Metadaten-Ansicht und Expertenmodus (2026-08-20)
- ✅ Was: Jeder Song kann jetzt mehreren Kategorien angehören. Sie stehen in der Songzeile hinter dem Künstler ("Neoni | Trap cool · Chill") — genau wie in deinem Entwurf.
- 📥 Woher sie kommen: Beim Scan aus dem Genre-Tag der Datei. Mehrere
Werte in einem Tag werden automatisch getrennt (
;,|/), doppelte fallen weg. Über ⋮ → Metadaten → Bearbeiten kannst du Kategorien selbst hinzufügen oder entfernen; bereits vergebene Kategorien werden als Vorschläge angeboten. - 🔒 Von Hand schlägt Automatik: Sobald du die Kategorien eines Songs selbst änderst, überschreibt ein späterer Scan sie nicht mehr.
- 🖼️ Gleiche Kategorie = gleiches Coverbild: Neue Einstellung unter Einstellungen → Darstellung (standardmäßig an, jederzeit abschaltbar). Ist sie an, zeigen alle Songs einer Kategorie das Bild der ersten Kategorie; hat die Kategorie kein Bild, bleibt das eigene Cover. Im Metadaten-Fenster ist die bildgebende Kategorie mit einem Bild-Symbol markiert.
- 🔬 Expertenmodus: Im Metadaten-Fenster ausklappbar — Titel, Künstler, Album, Dauer, Wiedergaben, Hinzugefügt-Datum, Herkunft der Kategorien, Format, Dateigröße und Pfad.
- 🔧 Details:
- DB-Schema 4: neue Tabelle
song_categories(Song ↔ Kategorie mit Reihenfolge) und Spaltecategories_edited. Bestehende Bibliotheken werden automatisch migriert. - Neu:
library/categories.dart(reine Logik: Tag zerlegen, Cover je Kategorie ermitteln — 12 Tests),library/category_service.dart(hält Kategorien + Cover-Zuordnung einmal zentral, 3 Tests),library/song_detail_sheet.dart,settings/app_settings.dart. - Beide Scanner (Android-MediaStore und Ordner-Scan) schreiben die Kategorien mit.
- Das Drei-Punkte-Menü der Songzeile ersetzt den bisherigen Playlist-Knopf und enthält "Metadaten" und "Zu Wiedergabeliste hinzufügen".
- DB-Schema 4: neue Tabelle
- ✅ Getestet: 129 Tests grün,
flutter analyzeohne Befund.
🎨 Neue Melo-Oberfläche: 4 Tabs + Sortierung (2026-08-20)
- ✅ Was: Die App hat jetzt die von dir gewünschte Struktur mit 4 Tabs: Meine Musik · Suche · Favoriten · Download. "Meine Musik" ist der neue Startbildschirm — ohne Topbar, wie du es wolltest.
- 🎵 Meine Musik: Oben eine Kopfzeile mit Einstellungs-Icon (links), Suchfeld (Mitte) und ?-Icon für die Musikerkennung (rechts, kommt später). Darunter Schnellzugriff-Karten (Favoriten · Wiedergabelisten · Zuletzt · Künstler · Alben), dann Shuffle-Wiedergabe + Sortieren, dann die komplette Liederliste.
- ↕️ Sortieren (neu!): Über das Symbol rechts neben "Shuffle-Wiedergabe" kannst du wählen zwischen Zuletzt hinzugefügt, Name (A–Z–#) und Wie oft abgespielt — jeweils auf- oder absteigend. Die Wahl wird gespeichert und überlebt einen Neustart. Bei "Name" stehen Buchstaben vorne und Ziffern/Sonderzeichen hinten unter "#"; Umlaute sortieren richtig ein (Ärger steht bei A, nicht hinter Z).
- ❤️ Favoriten-Tab: eigener Tab mit Shuffle-Wiedergabe und genau derselben Sortierung — mit eigener, getrennt gespeicherter Einstellung.
- ⬇️ Download-Tab: durchsucht den verbundenen Navidrome-Server (Alben/Künstler); abgespielte Titel werden weiterhin automatisch lokal zwischengespeichert.
- 🔢 "Wie oft abgespielt" zählt jetzt wirklich: Neue Spalte
playCountin der Datenbank (Schema 3, bestehende Bibliotheken werden automatisch migriert). Gezählt wird beim Start eines Titels — nicht sekündlich, solange er läuft. - 🎨 Farben: Schwarz auf #0B0B10 und Melo-Rot #c0392b (vorher ein helleres Rot).
- 🔧 Details:
- Neu:
library/song_sort.dart(reine Sortier-Logik, 11 Tests),shared/sort_store.dart(Speichern der Wahl, 4 Tests),shared/sortable_song_list.dart(Shuffle + Sortier-Menü),library/my_music_screen.dart,library/favorites_screen.dart,downloads/downloads_screen.dart. - Der alte
library_screen.dart(Tabs Alle/Künstler/Alben/Server) ist entfallen — seine Inhalte leben jetzt in "Meine Musik" (Alle), als eigene Bildschirme (Künstler/Alben) und im Download-Tab (Server). - Musik hinzufügen und Erneut scannen saßen in der entfernten Topbar und stehen jetzt in den Einstellungen → Bibliothek (zusätzlich weiterhin im leeren Zustand von "Meine Musik").
- Der Mini-Player ist jetzt auf allen Tabs sichtbar (vorher war der Player ein eigener Tab).
- Neu:
- 🐛 Nebenbei gefixt: Das Sortier-Menü ist scrollbar — auf niedrigen Bildschirmen bzw. im Querformat war der "Übernehmen"-Knopf sonst nicht erreichbar. Schnellzugriff-Karten liefen um 2 Pixel über.
- ✅ Getestet: 107 Tests grün,
flutter analyzeohne Befund.
🔎 Login-Dialog zeigt jetzt die echte Server-Fehlermeldung (2026-08-20)
- ✅ Was: Schlägt der Navidrome-Login fehl, zeigt der Dialog jetzt die Original-Meldung des Servers (z. B. „Wrong username or password") statt nur „Login fehlgeschlagen". So ist sofort klar, ob das Passwort falsch ist oder ein Netzwerkproblem vorliegt.
- 🔧 Details:
NavidromeService.letzterLoginFehlerhält die Server-Meldung des letzten abgelehnten Logins fest (wird bei jedem Ping zurückgesetzt).- Das Fehler-Log enthält jetzt die Passwort-Länge (
pwLen=…, nie das Passwort selbst) — ein Tippfehler wird so im Log sofort sichtbar (Melo…!hat 11 Zeichen).
- 🐛 Hintergrund (tiefe Debug-Runde): Server-seitig ist alles nachweislich
korrekt — Subsonic-API (
/rest/*) läuft trotz SSO-Umbau ohne Forward-Auth, DB-Passwort für „Baka" stimmt, und die exakte App-Token-Logik (Base64-Salt + md5) wurde 8/8-mal erfolgreich gegen den Live-Server reproduziert. Die Ablehnungen kommen von einem falschen Passwort-Wert auf dem Gerät; die neue Fehlermeldung macht genau das künftig direkt sichtbar.
🔎 Login-Diagnose: Passwort-Sichtbarkeit + Trim (2026-08-20)
- 🐛 „Login fehlgeschlagen" trotz korrekter Zugangsdaten: Systematische Analyse (App-Code, App-Logs, Caddy/Navidrome-Logs, 1:1-Nachbau des App-Requests inkl. Salt/Token) hat bewiesen: App-Code, Server, User „Baka" und Passwort sind korrekt — der Fehler lag im auf dem Gerät verwendeten Credential-Wert (der ältere Build mit dem Ping-Fehlalarm persistierte ungültige Zugangsdaten; verdeckte Tippfehler im Passwortfeld blieben unsichtbar).
- 🔧 Passwort-Anzeigen-Umschalter (Auge-Icon) im Navidrome-Login — Tippfehler werden sichtbar.
- 🔧 URL + Passwort werden getrimmt (randständige Leerzeichen aus Autofill / Tastatur entfernt).
- 🔧 Default-User im Login ist jetzt „Baka" (vorher „Dustin") — verhindert versehentlichen Login mit falschem User.
- ℹ️ Ein erfolgreicher Login überschreibt die alten (ungültigen) gespeicherten Zugangsdaten — der Ping-Fix aus dieser Version stellt sicher, dass künftig nur noch gültige Credentials gespeichert werden.
🔒 Datenschutz: Log-Bereinigung vor Server-Upload (2026-08-20)
- ✅ Was: Diagnose-Logs werden jetzt zentral bereinigt, bevor sie an
logs.baka-net.degehen. Der lokaledebugPrintbleibt vollständig. - 🔧 Details:
- Freitext-Scrubber für
message+stackTrace: maskiert sensiblekey=value-Fragmente (user=,pw=,password=,token=,secret=,url=), Datei-Pfade (<path>), nackte URLs (<url>),Bearer-Token, JWTs (<jwt>) und lange Hex-IDs (<hex>). stackTracewird auf max. 8 Zeilen gekürzt.deviceModelsendet nur noch die grobe Plattform (android/ios) statt Hersteller+Modell (war ein Geräte-Fingerprint) —device_info_plusim Logger entfernt.
- Freitext-Scrubber für
- 🐛 Fix (Quelle): Der Navidrome-Login in
settings_screenloggte Benutzername + Server-URL im Klartext (Login: url=… user=…). Diese Aufrufe senden jetzt nur noch den neutralen Status inkl.pwLeer-Flag. - 🧪 Tests: neue Suite
test/logger_service_test.dart(9 Tests) — 79/79 grün,flutter analyzeohne Issues. - ℹ️ Offen: Opt-in/Einwilligung für den Diagnose-Versand bleibt ein separater Folgeschritt (braucht UI).
🐛 Server-Bibliothek lädt + Tab abgeschnitten (2026-08-20)
- 🐛 Server-Bibliothek lud nicht ("Erneut versuchen"): Ursache war, dass
der Code das Subsonic-
status-Feld ignorierte. Navidrome liefert auch bei falschem Passwort HTTP 200 mitstatus:"failed"—ping()meldete dadurch fälschlich „Login ok", undgetAlben/getArtistsbehandelten die Fehlerantwort still als „leer".- 🔧
ping()prüft jetzt den Body (status) — kein Fehlalarm mehr beim Login. - 🔧
getAlben/getArtistswerfen beistatus:"failed"eineNavidromeExceptionmit Server-Meldung statt still[]zurückzugeben. - 🔧 Der Server-Tab zeigt die echte Server-Fehlermeldung (z. B. „Wrong username or password") statt nur „Keine Alben geladen".
- 🔧 Album-Abruf nutzt jetzt den ID3-Endpoint
getAlbumList2(konsistent zugetArtists) — der alte Folder-EndpointgetAlbumListliefert bei tag-organisierten Libraries leer.
- 🔧
- 🐛 Tab „🌐 Server" war abgeschnitten (nur „Serve" sichtbar): Die 4 festen
Tabs waren zu eng.
labelPaddingverkleinert (engere Abstände) — Schriftgröße unverändert. - 🧪 Neue Tests:
test/navidrome_parse_test.dart(5). 84/84 grün, analyze sauber.
🔧 Log-Upload System - Fixes (2026-08-19)
- ✅ ERROR-Level Logging: Fehler werden SOFORT zum Server hochgeladen (async/await Fixed)
- ✅ Navidrome-Service Error Logging: Alle API-Fehler (ping, getAlben, getSongs, getFavorites, getArtists, getArtistSongs, getLyrics, scrobble, getBookmarks, getPlaylists, getPlaylistSongs) werden jetzt mit
logger.error()zum Server geloggt (statt nur debugPrint) - ✅ Login-Fehler Detail-Logging: Fehler enthalten URL, User, Exception-Typ und StackTrace
- ✅ HTTP-Error bei Stream: Stream-Fehler mit HTTP-Statuscode werden auch geloggt
- ✅ Payload-Format: Logs senden als
{"logs": [...]}Array zum Server
🎉 RELEASE BUILD v3: Phase 2 + Login + Auto-Bugreport System!
Build Date: 2026-08-19 21:30
APK (Release/Universal): app-release.apk (22.3 MB) — Mit Auto-Logger + Login-Improvements!
APK (ARM64-Specific): app-arm64-v8a-release.apk (21 MB) — Optimal für POCO X7 Pro
Tests: 70/70 ✅
Build Status: ✅ SUCCESS
Neue Features in dieser Build:
- ✨ Login-Verbesserungen: Auto-URL + User-Buttons + Gast-Modus
- 📊 Auto-Bugreport System: Logger sendet Fehler sofort + andere Logs gesammelt zum Server
- Device-Info (Model + OS) + Timestamp + Stack-Traces
- Integration in Navidrome-Service für Login-Fehler-Diagnose
- 📝 Alle Phase-2-Features (Sync, Caching, Player, Controls)
- 🔒 Secure Credential-Speicherung
- 🎵 Enhanced MiniPlayer mit Skip-Buttons
Phase 2 (Part 1-8 Completed — MILESTONE!)
- 🗄️ Auto-Caching: Lieder werden automatisch beim Streamen lokal gespeichert!
- Cache-First-Logik: Existierende Dateien lokal spielen
- Fallback: Vom Server streamen wenn kein Cache
- Cache-Speicher-Status in Settings (MB/KB/B) mit Clear-Button
- 🗄️ CacheManager: MD5-Hash-basierte Cache-Verwaltung (getCacheSize, clearCache)
- 📴 Offline-Mode: Toggle in Settings aktiviert Offline-Betrieb (nur gecachte Lieder spielen)
- 🎤 Artist-Browse: Toggle in Navidrome-Tab zwischen Albums ↔ Künstler, Tap lädt alle Songs des Künstlers
- 🌟 Favoriten-Sync: Button in Settings lädt Server-Favoriten und importiert sie lokal
- 📊 History-Sync: Wiedergabe-Position vom Server laden + alle 5s zum Server senden (Subsonic-Bookmarks)
- 📋 Playlisten-Sync: Button in Settings lädt alle Server-Playlisten (mit 🌐 Präfix zur Unterscheidung)
- 🔒 Lock-Screen Controls: Notification mit Play/Pause/Skip-Buttons auf Android Lock Screen
- 🎵 Enhanced MiniPlayer: Now-Playing Widget auf allen Tabs mit Skip-Buttons + Progress-Bar
- Infrastructure für Multi-Device Sync vorbereitet
Added
- 🌐 Musikserver-Tab in Bibliothek: Zeige Alben vom Navidrome-Server, tippe um Album abzuspielen
- 📝 Lyrics-Anzeige: Lyrics-Button im Now-Playing Screen, Bottom-Sheet mit Song-Lyrics vom Server
- 🔀 Shuffle & Repeat Modi: Shuffle-Button (aktiv = rot), Repeat-Cycle (Off → All → One), beide im Player
- 🌐 Navidrome-Integration (Musikserver-Verbindung): Settings-Tab bietet Login/Logout für Subsonic-API-kompatible Server
- Navidrome-Service mit sichere Credential-Speicherung (Secure Storage + SharedPreferences)
- Server-Album-Browser: Lädt Alben vom Server, zeigt Songcount, tippe um Album in Queue zu laden
- Server-APIs erweitert: getArtists(), getArtistSongs(), setFavorite(), getFavorites(), getLyrics() (Phase 2 vorbereitet)
- Dependencies für Navidrome hinzugefügt: http, crypto, shared_preferences, flutter_secure_storage
Known Limitations (Phase 2)
- Server-Favoriten-Sync: APIs vorhanden, UI-Integration in Phase 2
- Artist-Browse: APIs vorhanden, UI in Phase 2
- Server-Caching: Musik wird nicht lokal für Offline gecacht (Phase 2)
- Lyrics-Sync: Keine Timed-Synchronisation (Phase 2+)
[1.0.0-alpha]
Added
- Playlisten-Tab: Favoriten-Kurzeinstieg oben, Liste aller Playlisten mit Songanzahl, Erstellen-Dialog (FAB), Löschen mit Bestätigung
- 🎵➕ Songs per Bottom-Sheet zu Playlisten hinzufügen (neuer Button in der Songliste, neben dem Favoriten-Herz)
- Playlist-Detailansicht: Songs per Drag & Drop umsortieren, einzeln entfernen, Antippen spielt die Playlist ab dieser Stelle
- Datenbank: Playlisten, Favoriten und Wiedergabe-Historie Tabellen (Drift, Schema v2)
- PlaylistService für Playlisten- und Favoriten-Verwaltung
- ❤️ Favoriten-Herz in der Songliste (ausgefüllt/leer)
- ❤️ Favoriten-Herz auch im Now-Playing-Screen (aktueller Song)
- Bibliothek: Künstler- und Alben-Tabs neben "Alle" — Songs werden clientseitig aus der bestehenden Songliste gruppiert (alphabetisch sortiert, fehlender Künstler/Album → "Unbekannt" / "Unbekanntes Album"); Antippen öffnet die Songliste des jeweiligen Künstlers/Albums, Alben zeigen zusätzlich das Cover
- Warteschlangen-Ansicht (Queue-Button in der Now-Playing-AppBar): zeigt die aktuelle Wiedergabeliste, hebt den laufenden Titel hervor, per Antippen direkt zu einem Titel springen, Titel entfernen oder per Drag & Drop umsortieren — ohne Änderungen am Audio-Handler (Queue wird clientseitig neu berechnet und neu geladen)
- Wiedergabeposition wird alle 5 Sekunden gespeichert und beim erneuten Abspielen eines Songs automatisch fortgesetzt (kein Resume bei den letzten 3 Sekunden eines Songs, um ein sofortiges Ende zu vermeiden)
- Settings-Tab: Bibliotheks-Statistik (Song-Anzahl + Gesamtspieldauer), Musik-Berechtigung mit Link in die Systemeinstellungen, kurzer "Über Melo"-Abschnitt — bewusst ohne Platzhalter für Profil/Cloud-Sync/ Geräte-Verwaltung, da es dafür noch kein Account-/Cloud-System gibt (Phase 2)
Damit ist das komplette 5-Tab-MVP fertig: Player / Bibliothek / Playlisten / Suche / Settings — inklusive Playlisten, Favoriten, Warteschlangen-Verwaltung, Künstler-/Alben-Browsing und automatischem Fortsetzen der Wiedergabeposition.
Changed
- Now-Playing-Screen läuft jetzt als eigener Tab statt als gepushter Screen (kein Schließen-Button mehr in der AppBar)
- MediaItem trägt jetzt die Song-UUID mit (
extras['songId']), nicht mehr nur die Datei-URI - Finales 5-Tab-Layout: Player / Bibliothek / Playlisten / Suche / Settings (Playlisten und Settings vorerst als Platzhalter)
- "Zuletzt hinzugefügt" aus der alten Startseite ist jetzt Teil der Bibliothek (horizontale Leiste oben)
- MiniPlayer wird auf dem Player-Tab ausgeblendet (dort läuft schon die volle Ansicht)
Fixed
- 🐛 Der APK-Build funktioniert jetzt überhaupt. Drei Dinge waren nötig:
compileSdk = 37undkotlin.jvm.target.validation.mode=warningexistierten bisher nur lokal auf dem Server und fehlten im Repo — ohne sie bricht der Build ab, weilpermission_handlerSDK 37 verlangt. Zusätzlich hebt ein Gradle- Workaround jetzt Plugin-Module mit zu altemcompileSdkauf 36 an:on_audio_query_androidkompiliert gegen SDK 33, seine AndroidX-Abhängigkeiten verlangen aber mindestens 34 (16 Metadaten-Konflikte).
Removed
- Alte Startseite (
home_screen.dart) entfernt — Funktionalität in die Bibliothek verschoben
Known Issues
- Genre-Browsing fehlt noch: die
Songs-Tabelle hat keine Genre-Spalte und keiner der Scanner (scan_service.dart, android_scan.dart) liest Genre- Metadaten aus den Dateien aus. Das ursprünglich geplante dritte Bibliotheks- Tab "Genres" ist deshalb nicht umgesetzt — braucht eine Schema-Migration plus Metadaten-Extraktion im Scanner (eigene Aufgabe, außerhalb dieses Tasks)