Files
Melo/.ui-design/reviews/melo_vollwertigkeit_20260823.md
T
Hermes (Server)andClaude Opus 5 0d76d8cc58 Album-Ansicht, mitlaufender Songtext, Cover-Cache, Server-Favoriten
Die letzten vier Punkte aus dem Review-Bericht.

G2 — Server-Bereich: Ein Tipp auf ein Album spielte sofort alles ab;
hineinsehen ging nicht. Jetzt Album- und Kuenstler-Ansicht mit Cover,
Kuenstler, Titelzahl, Gesamtdauer, "Abspielen"/"Zufaellig" und der
Titelliste; Antippen startet an dieser Stelle. Dazu "Mehr Alben laden" —
die Liste hoerte bei 50 auf, ohne dass etwas darauf hinwies.
NICHT umgesetzt: den Server-Bereich aus dem Download-Tab loesen (das
widerspricht Commit 34d6d8e, "Auf Wunsch von Dustin") und eine
Server-Suche (die Suche bleibt ausdruecklich rein lokal).

G8 — Songtext: Traegt der Text Zeitmarken, laeuft er mit; die aktive Zeile
ist hervorgehoben, Antippen springt an die Stelle. Ohne Zeitmarken bleibt
es eine Textwand — die App schaut nach, statt zu raten.

G10 — Cover bleiben liegen. Eigener Ordner, einmal geholt. Der Schluessel
haengt an der Album-Kennung, nicht an der Adresse: die traegt bei jedem
App-Start ein neues Token, und der Ordner waere sonst gewachsen, ohne je
einen Treffer zu liefern. Keine neue Abhaengigkeit.

G3 — Das Herz ist bei Server-Titeln nicht mehr ausgegraut, sondern
favorisiert am Server (star/unstar) — dort, wo der Favoriten-Abgleich sie
auch wieder abholt. Offen bleibt der schwere Teil: Wiedergabezaehler,
Historie und Kategorien braeuchten fuer Server-Titel eine Zeile in der
Bibliothek.

Aus dem Code-Review nachgebessert (sieben Punkte): das Herz behielt beim
Titelwechsel seinen Zustand; recycelte Listenzeilen zeigten kurz das Cover
der vorherigen; der neue Songtext bekam bei Server-Titeln die
Abspiel-Adresse statt der Server-Kennung und fand deshalb nie einen Text;
ein einmal fehlgeschlagenes Cover blieb die ganze Sitzung grau; "Server
nicht erreichbar" sah aus wie "Album hat keine Titel", womit der
Wiederholen-Knopf unerreichbar war; die Kuenstler-Ansicht waere immer leer
geblieben, weil getArtist die Titel gar nicht mitliefert; und zwei
gleichzeitige Cover-Abrufe konnten ein zerschnittenes Bild hinterlassen.

Selbst gefunden: das Haekchen "schon geladen" fragte pro Zeile die Platte
ab, bei jedem Positionswechsel neu. Jetzt einmal je Bildschirm.

457 Tests gruen (vorher 433), flutter analyze ohne Befund, Release-APK
gebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
2026-08-23 21:53:31 +02:00

20 KiB
Raw Blame History

Design- & Feature-Review: Melo vs. Apple Music / Spotify

Review-ID: melo_vollwertigkeit_20260823 Datum: 2026-08-23 Umfang: gesamte App (lib/, 56 Dateien, 14.721 Zeilen), Android-Manifest, Referenz-Bilder Fokus: Visual · Usability · Funktionsumfang · Code Werkzeuge: ui-ux-pro-max (design-system + flutter stack + pro-rules), ui-design:design-review

Verifizierter Ist-Zustand: flutter analyzeNo issues found. flutter test328 bestanden, 1 übersprungen (der bekannte Hänger aus BACKLOG.md).


Summary

Melo ist technisch überdurchschnittlich sauber: echtes Design-Token-System, WCAG-geprüfte Textfarben, Tombstone-fähiges Schema ab Tag 1, hohe Testabdeckung, deutschsprachige Erklär-Kommentare an genau den Stellen, wo früher Bugs saßen. Das ist deutlich besser als der Durchschnitt eines Hobby-Projekts.

Als vollwertige Musik-App im Sinne von Apple Music ist sie es aber noch nicht. Es fehlen nicht Details, sondern drei tragende Säulen: die Album-Detailansicht (siehe die Korrektur unter K4), echtes Offline-Management und Cover-Art für Server-Titel. Dazu kommen zwei stille Fehler, die man der App nicht ansieht: der Offline-Schalter tut nichts, und ohne POST_NOTIFICATIONS erscheint auf Android 13+ keine Wiedergabe-Benachrichtigung.

Gefundene Punkte: 26 → 5 kritisch · 10 groß · 7 klein · 4 Vorschläge

Stand 2026-08-23, nach der Umsetzung. Erledigt: alle fünf P0-Punkte (K1K5) sowie G1G10. Details im CHANGELOG.

Zwei Teilforderungen aus G2 sind bewusst nicht umgesetzt: den Server-Bereich aus dem Download-Tab zu lösen widerspricht Commit 34d6d8e („Auf Wunsch von Dustin"), und eine Server-Suche widerspricht der Vorgabe, dass die Suche rein lokal bleibt.

Aus G3 bleibt der schwere Teil offen: Wiedergabezähler, Historie und Kategorien für reine Server-Titel bräuchten eine Zeile in der Bibliothek.

Offen sind damit noch die P2- und P3-Listen unten sowie K4 in seiner korrigierten Fassung (Album-Detailansicht lokal, mit Tracknummer und Schema-Erweiterung — die Server-Seite davon ist mit G2 erledigt).


Kritische Punkte (P0)

K1 — Offline-Modus ist ein toter Schalter

Ort: lib/services/offline_mode.dart · lib/settings/settings_screen.dart:190 Kategorie: Usability / Korrektheit

OfflineMode speichert ein Bool in den SharedPreferences und ruft notifyListeners(). Das war's. Verifiziert per Volltextsuche: kein einziger Leser außerhalb von main.dart (Registrierung) und dem Settings-Schalter selbst. MeloAudioHandler, NavidromeService und SyncService fragen ihn nie ab.

Wirkung: Der Nutzer schaltet "Nur gecachte Lieder abspielen" ein, die App streamt trotzdem und verbraucht Mobilfunkdaten. Ein Versprechen, das die UI gibt und der Code bricht.

Empfehlung: OfflineMode in loadPlaylist auslesen. Ist er an, nur Titel mit Cache-Treffer oder lokalem Pfad in die Queue nehmen und die übersprungenen sichtbar machen ("3 Titel übersprungen — nicht offline verfügbar").


K2 — Keine POST_NOTIFICATIONS-Berechtigung

Ort: android/app/src/main/AndroidManifest.xml Kategorie: Plattform

Verifiziert im gemergten Manifest (build/app/intermediates/merged_manifests/release/.../AndroidManifest.xml): POST_NOTIFICATIONS ist nicht dabei. targetSdk folgt Flutter (≥ 33).

Wirkung: Auf Android 13+ zeigt das System die Media-Notification erst nach erteilter Laufzeit-Berechtigung. Ohne sie fehlt die zentrale Bedienfläche einer Musik-App im Alltag. Der Vordergrunddienst läuft, aber unsichtbar.

Empfehlung: Permission ins Manifest, beim ersten Start der Wiedergabe abfragen (permission_handler ist bereits als Abhängigkeit da).


K3 — Server-Titel haben nie ein Coverbild

Ort: lib/shared/cover.dart:38 · lib/downloads/downloads_screen.dart:309 Kategorie: Visual

CoverImage rendert ausschließlich artUri.scheme == 'file'. Für alles andere kommt der Noten-Platzhalter. Navidrome-Titel bekommen in _playAlbum/_playArtist gar kein artUri mitgegeben — obwohl NavidromeService.coverUrl (Zeile 265) existiert und SubsonicAlbum.coverId geparst wird.

Wirkung: Jeder Server-Titel ist in Liste, Mini-Player, Vollbild-Player, Notification und Sperrbildschirm ein graues Notensymbol. Das ist der augenfälligste Unterschied zu Apple Music — dort trägt das Cover die gesamte visuelle Identität.

Empfehlung: CoverImage um Image.network für http/https erweitern (mit cacheWidth, Fehler-Fallback auf den Platzhalter), und in beiden _play*-Methoden artUri: _nav.coverUrl(s.coverId) setzen. Bild-Cache lokal ablegen, damit es offline bleibt.


K4 — Alben fehlen als Browse-Achsekorrigiert: Album-Detailansicht fehlt

Ort: lib/library/category_list.dart:12 · lib/library/categories.dart:26 Kategorie: Funktionsumfang

Korrektur vom 2026-08-23 (nach der P0-Runde). Die ursprüngliche Fassung dieses Punktes war falsch. Sie behauptete, die Alben-Achse sei „verlorengegangen". Sie wurde bewusst ersetzt: category_list.dart dokumentiert das im Klassenkommentar, und kategorienAusTags setzt den Album-Namen beim Scan als erste Kategorie jedes Titels. Der Reiter „Kategorie" ist der Alben-Reiter — nur allgemeiner, weil ein Titel mehreren Kategorien angehören darf. Der Fehler entstand, weil nur song_grouping.dart und my_music_screen.dart gelesen wurden.

Was wirklich fehlt, ist nicht die Achse, sondern die Ansicht eines Albums als Album:

  1. Kein Album-Kopf. _KategorieLiederScreen ist eine AppBar über einer Titelliste. Es fehlen großes Cover, Künstler, Jahr, Titelzahl, Gesamtdauer und ein „Abspielen / Zufällig"-Paar. Bei Apple Music trägt genau dieser Kopf die Identität eines Albums.
  2. Falsche Reihenfolge. Innerhalb einer Kategorie wird nach Titel sortiert. Ein Album gehört in Tracknummer-Reihenfolge — sonst beginnt jedes Konzeptalbum mit dem Lied, das alphabetisch vorn steht.
  3. Die Tracknummer wird gar nicht gelesen. Verifiziert: weder Songs noch der Scan kennen trackNumber. Punkt 2 braucht also zuerst eine Schema-Erweiterung plus Auslesen des Tags.
  4. Kein Weg vom Künstler zu seinen Alben. _ArtistSongsScreen zeigt alle Titel flach.

Empfehlung (ersetzt die alte): Keinen vierten Reiter bauen — der würde denselben Bestand doppelt zeigen. Stattdessen _KategorieLiederScreen zu einem richtigen Detail-Screen ausbauen und die Tracknummer nachrüsten. Der Aufwand liegt damit nicht bei „ein Reiter wie der Künstler-Reiter", sondern bei Schema-Migration + Scan + Screen.


K5 — Warteschlange neu ordnen startet die Wiedergabe neu

Ort: lib/player/queue_screen.dart:87,103 · lib/player/audio_handler.dart:169 Kategorie: Usability / Korrektheit

Der Kommentar im Code ist ehrlich: der Handler bietet keine Live-Mutation, also ruft jedes Entfernen und jedes Verschieben loadPlaylist() auf. Das führt _player.setAudioSources(...) + play() + seek() aus.

Drei Folgen:

  1. Hörbarer Aussetzer bei jeder Queue-Änderung — bei Apple Music passiert das lautlos.
  2. loadPlaylist setzt _lastCountedIndex = null (Zeile 173) → der laufende Titel wird erneut als Wiedergabe gezählt. Die Sortierung "Wie oft abgespielt" wird durch Queue-Bedienung verfälscht.
  3. Bei Server-Titeln werden alle Cache-Treffer neu ermittelt (await in der Schleife).

Empfehlung: removeQueueItem/insertQueueItem auf _player.removeAudioSourceAt / moveAudioSource abbilden. just_audio kann das ohne Neuaufbau.


Große Punkte (P1)

G1 — Suche findet nur lokale Titel, nur flach

Ort: lib/library/search_screen.dart (59 Zeilen) db.searchSongs() per LIKE über Titel/Künstler/Album. Kein Server (search3.view wird nirgends aufgerufen), keine Playlisten, keine Kategorien, keine Gruppierung der Treffer nach Typ, keine letzten Suchen, keine Vorschläge, kein Entprellen. Apple Music gruppiert Ergebnisse in Titel/Alben/Künstler/Playlists und zeigt bei leerem Feld die Historie. Der ganze Tab ist heute ein Textfeld über einer Liste.

G2 — Navidrome ist im Download-Tab versteckt

Ort: lib/downloads/downloads_screen.dart:56 Der komplette Server-Browser ist ein Unterreiter von "Download". Ein Nutzer, der seine Server-Bibliothek hören will, sucht sie nicht unter "Download". Im Referenz-Screenshot hieß der Tab noch "Online" — treffender.

Dazu: Tippen auf ein Album spielt sofort ab. Es gibt keinen Album-Screen, keine Titelliste, keine Möglichkeit, einen einzelnen Server-Titel zu wählen. Nur 50 Alben, kein Nachladen, keine Server-Suche.

G3 — Server-Titel sind Bürger zweiter Klasse

Ort: lib/library/song_media.dart vs. lib/downloads/downloads_screen.dart:309 Ein MediaItem vom Server trägt nur navidromeIdkein songId. Damit gilt für Server-Titel: kein Favorit, keine Playlist-Zuordnung, kein lokaler Wiedergabezähler, keine Kategorie, kein Cover, kein Eintrag in der Historie.

Konkreter Fehler daraus: now_playing_screen.dart:45 gibt FavoriteButton(songId: item.extras?['songId'] ?? '') — bei Server-Titeln also den leeren String. FavoriteButton prüft nicht darauf, toggleFavorite('') legt eine Favoriten-Zeile mit leerer ID an. Das Herz füllt sich, in der Favoritenliste (INNER JOIN auf songs) taucht nichts auf. Falsche Rückmeldung an den Nutzer.

G4 — Kein gezielter Offline-Download

Ort: lib/services/cache_manager.dart · lib/player/audio_handler.dart:203 Gecacht wird nur, was zufällig abgespielt wurde. Es gibt kein "Album offline verfügbar machen", keine Anzeige, welche Titel offline sind, kein Verwalten pro Titel. CacheManager hat außerdem keine Größenbegrenzung und keine Verdrängung — nur "alles löschen". Der Cache wächst unbegrenzt. Alle Dateien werden .mp3 benannt, unabhängig vom tatsächlichen Codec (Navidrome liefert oft Opus/FLAC).

G5 — Kein "läuft gerade"-Zustand in der Liste

Ort: lib/library/song_list.dart:157 Die Referenz-UI zeigt den laufenden Titel farbig hervorgehoben mit animierten Balken. Melos SongList hat keinerlei Bezug zum mediaItem-Stream. Der Nutzer scrollt durch die Liste und sieht nicht, wo er gerade ist.

G6 — Zwei verschiedene Rot-Töne

Ort: 10 Vorkommen von Colors.redAccent (#FF5252), meist in settings_screen.dart und downloads_screen.dart Die Marke ist MeloTheme.red = #C0392B (gedecktes Ziegelrot). Colors.redAccent ist ein grelles Signalrot. Beide stehen im selben Screen nebeneinander. Insgesamt 58 hartcodierte Colors.*-Werte außerhalb des Themes, 18 davon allein in den Einstellungen — die sind visuell der schwächste Screen der App.

G7 — Emoji als Icon

Ort: downloads_screen.dart:234,247 (📀 Alben / 🎤 Künstler), settings_screen.dart:190 (📴 Offline-Modus), now_playing_screen.dart:362 (📝 Songtext) Verstößt gegen die erste Regel der Pre-Delivery-Checkliste von ui-ux-pro-max: Emoji rendern je nach Hersteller-Font unterschiedlich, lassen sich nicht einfärben, folgen keinem Design-Token und sind für Screenreader Unsinn. Material-Icons sind vorhanden (Icons.album, Icons.mic, Icons.cloud_off, Icons.lyrics).

G8 — Songtext ist ein statischer Textblock

Ort: lib/player/now_playing_screen.dart:309 Der Text wird als eine Wand angezeigt. Kein Zeilen-Sync (LRC), kein Mitlaufen, kein Antippen zum Springen. Navidromes getLyricsBySongId liefert synchronisierte Texte. Das ist bei Apple Music eine der meistgenutzten Funktionen.


G9 — Nach stop() merkt sich die App keine Positionen mehr (bei der P0-Umsetzung gefunden)

Ort: lib/player/audio_handler.dart:258 (stop) Kategorie: Korrektheit · Status: nicht behoben, außerhalb des P0-Auftrags

stop() ruft _positionRecordTimer.cancel(). Der Timer ist Timer.periodic und wird nur einmal im Konstruktor angelegt — einmal abgebrochen, kommt er für den Rest der App-Sitzung nicht zurück.

stop() löst nicht nur der Nutzer aus: das System ruft es beim Wegwischen der Benachrichtigung und über die Stop-Aktion auf. Danach speichert die App keine Wiedergabepositionen mehr und scrobbelt nicht mehr zum Server — bis zum Neustart, und ohne jeden Hinweis. „Fortsetzen an alter Stelle" hört damit still auf zu funktionieren.

Empfehlung: Den Timer in stop() nicht abbrechen, sondern in der Callback prüfen (if (!_player.playing) return; steht bereits drin — der Abbruch ist also gar nicht nötig). Abbrechen gehört allein in dispose().

Vorbestehend, nicht durch die P0-Änderungen entstanden: der alte QueueScreen rief in derselben Lage ebenfalls handler.stop() auf.


G10 — Server-Cover haben keinen dauerhaften Zwischenspeicher (Folge der K3-Umsetzung)

Ort: lib/shared/cover.dart:55 Kategorie: Performance · Status: offen, bewusst nicht in P0

Image.network legt nur im Arbeitsspeicher ab (Flutters ImageCache, ~100 MB, beim Beenden weg). Beim nächsten Kaltstart fragt jede sichtbare Zeile ihr Cover erneut beim Server an. Außerdem laufen diese Anfragen auch im Offline-Modus — sie schlagen dann fehl und fallen auf den Platzhalter zurück, kosten aber Versuche.

Ein dauerhafter Cache bräuchte entweder cached_network_image als neue Abhängigkeit oder eine Erweiterung des vorhandenen CacheManager auf Bilder. Beides ist eine Entscheidung, keine Fehlerbehebung — deshalb nicht im P0-Fix. Der Unterschied zu vorher bleibt trotzdem groß: bisher gab es überhaupt kein Server-Cover.


Kleine Punkte (P2)

# Punkt Ort
P1 AppBar der Einstellungen heißt "Settings" — einziges englisches Wort in einer deutschen App settings_screen.dart:65
P2 Kein Hero-Übergang Mini-Player → Vollbild (0 Treffer in lib/). Der Wechsel springt, statt das Cover wandern zu lassen mini_player.dart:70
P3 Kein Wischen am Mini-Player (nach unten = schließen, seitlich = nächster Titel) mini_player.dart
P4 Künstlerliste ist eine nackte ListTile-Liste ohne Bilder; kein Album-Zwischenschritt artist_list.dart:31
P5 Keine Reduced-Motion-Unterstützung (0 Treffer für disableAnimations), obwohl MeloMotion sauber getokent ist theme.dart:41
P6 Keine Querformat-/Tablet-Anpassung (LayoutBuilder nur in cover.dart, MediaQuery.size nur im Equalizer) app-weit
P7 Kein Alphabet-Schnellscroller und keine Mehrfachauswahl in langen Listen song_list.dart

Vorschläge (P3)

  • V1 — Farbe aus dem Cover ziehen. Apple Music und Spotify färben den Player nach dem Albumcover. In Flutter mit PaletteGenerator + Verlauf hinter dem Cover. Größter optischer Sprung pro Zeile Code.
  • V2 — Eigene Schrift. Die App nutzt System-Roboto. Die ui-ux-pro-max-Abfrage für "music entertainment" schlägt Righteous/Poppins vor; für Schwarz/Rot passt eher eine kräftige Grotesk (Outfit, Sora) für Überschriften bei Roboto/Inter im Fließtext.
  • V3 — YouTube-Share-Intent. Aktuell muss man die URL kopieren und einfügen. Ein ACTION_SEND-Intent-Filter im Manifest macht "Teilen → Melo" möglich. Sehr kleine Änderung, spürbarer Alltagsgewinn.
  • V4 — Android Auto / Assistant. Der MediaBrowserService ist im Manifest deklariert, aber MeloAudioHandler überschreibt getChildren/getMediaItem nicht — Browsen im Auto funktioniert also nicht. Kein Widget, keine Wear-Unterstützung.

Was gut ist (nicht ändern)

  • Design-Token-System (theme.dart): MeloSpace, MeloRadius, MeloMotion mit begründeten Werten. Die Textfarben sind nicht geschätzt, sondern per theme_kontrast_test.dart gegen 4,5:1 nachgerechnet. Das machen wenige.
  • Haarlinie statt Schatten auf Schwarz — richtige Entscheidung für OLED, deckt sich mit der "Dark Mode (OLED)"-Empfehlung des Style-Katalogs.
  • Datenmodell: UUID + updatedAtMs + deleted-Tombstone ab Schema 1, 9 saubere Migrationen. Sync war von Anfang an mitgedacht statt nachgerüstet.
  • Reine Funktionen ausgelagert (shouldResumeAt, playNextIndex, reorderQueue, planeSync, newPlayingIndex) — deshalb 328 Tests ohne Emulator.
  • Kommentare erklären das Warum, oft mit dem konkreten Bug, der dahinterstand (navidromeIdOf, cacheSchluessel, loadPlaylist). Genau die Stellen aus ui-referenz/bugs/ sind so dokumentiert.
  • Tooltips überall an Icon-Buttons → in Flutter automatisch Semantics-Label.

Priorisierter Plan

P0 — bevor irgendetwas Neues gebaut wird

  1. POST_NOTIFICATIONS ins Manifest + Laufzeit-Abfrage (K2, ~1 h)
  2. Offline-Modus wirklich verdrahten oder den Schalter entfernen (K1, ~3 h)
  3. CoverImage für http + artUri bei Server-Titeln setzen (K3, ~3 h)
  4. Queue ohne Neuladen mutieren, Doppelzählung beenden (K5, ~4 h)
  5. Leere songId in FavoriteButton abfangen (G3-Teil, ~30 min)

P1 — das macht sie "vollwertig"

  1. Alben-Achse: groupByAlbum, vierter Unterreiter, Album-Screen (K4, ~1 Tag)
  2. Suche umbauen: nach Typ gruppiert, Server einbeziehen, letzte Suchen (G1, ~1,5 Tage)
  3. Server-Bereich aus "Download" lösen → eigener Tab "Online" mit Album-Detail (G2, ~1,5 Tage)
  4. Offline-Download pro Album/Playlist + Cache-Grenze mit LRU (G4, ~1,5 Tage)
  5. "Läuft gerade"-Markierung in allen Listen (G5, ~3 h)

P2 — Politur, die man sofort sieht

  1. Colors.redAccentMeloTheme.red, Emoji → Material-Icons, "Settings" → "Einstellungen" (G6, G7, P1 — zusammen ~3 h)
  2. Hero-Übergang + Wischgesten am Mini-Player (P2, P3, ~4 h)
  3. Synchronisierter Songtext (LRC) (G8, ~1 Tag)
  4. Künstler- und Kategorieliste visuell aufwerten (P4, ~4 h)
  5. Reduced-Motion + Querformat (P5, P6, ~4 h)

P3 — danach

  1. Cover-Farbe im Player (V1)
  2. Eigene Schrift (V2)
  3. YouTube-Share-Intent (V3)
  4. Android Auto: getChildren implementieren (V4)

Feature-Matrix gegen Apple Music

Bereich Apple Music Melo Bewertung
Wiedergabe, Hintergrund, Sperrbildschirm da (Notification-Permission fehlt → K2)
Warteschlange ansehen/umordnen schwach — Neuladen bei jeder Änderung
Als Nächstes / Ans Ende da
Shuffle & Repeat da
Sleep-Timer da (Melo besser als Apple Music)
Equalizer ⚠️ nur System 5-Band + Bass + Virtualizer besser als Apple Music
Lautstärke-Angleich ReplayGain da
Fortsetzen an alter Stelle lokal + Server-Bookmark da
Favoriten da, aber nicht für Server-Titel
Playlisten anlegen/ordnen da
Alben durchsuchen fehlt
Künstler-Seite mit Alben ⚠️ nackte Titelliste schwach
Suche typgruppiert, serverweit ⚠️ lokal, flach schwach
Songtext zeilensynchron ⚠️ statischer Block schwach
Offline verfügbar machen gezielt ⚠️ nur Zufalls-Cache schwach
Cover-Art ⚠️ nur lokale Dateien schwach
Geräte-Sync der Bibliothek iCloud Melo-Cloud + Tombstones da
Scrobble / Wiedergabestatistik lokal + Subsonic da
Musikerkennung (Shazam) ACRCloud da
YouTube-Import Alleinstellung
Kategorien / eigene Tags Alleinstellung
Empfehlungen, Radio, Charts fehlt (bewusst? Melo hat keinen Katalog)
Teilen fehlt
Homescreen-Widget fehlt
Android Auto fehlt (Service da, Browsing nicht)
Cast / Sonos fehlt
Crossfade / Gapless fehlt

Zählung: 13 × da · 7 × schwach · 8 × fehlt · 3 × besser als Apple Music


Erzeugt mit ui-ux-pro-max 2.13.0 (design-system, --stack flutter, pro-rules) und ui-design:design-review. Alle Code-Stellen im Repo verifiziert, flutter analyze und flutter test zum Review-Zeitpunkt ausgeführt.