# 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 analyze` → *No issues found*. `flutter test` → *328 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 > (K1–K5) sowie G1–G10. 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. > > **Nachtrag 2026-08-24:** Die **P2-Liste** ist ebenfalls abgearbeitet > (Hero-Übergang, Wischgesten, Künstlerseite mit Alben, Reduced Motion > app-weit, Querformat/Tablet, Alphabet-Sprung, Mehrfachauswahl). > > **Nachtrag 2026-08-24 (zweiter):** Auch die **P3-Liste** ist abgearbeitet — > Cover-Farbe im Player, Teilen-Intent, Android Auto. Bei V2 (eigene Schrift) > hat Dustin entschieden, bei der System-Schrift zu bleiben und stattdessen > die Typografie zu schärfen; das ist umgesetzt. > > Offen bleibt damit **K4** in seiner > korrigierten Fassung (Album-Detailansicht **lokal**, mit Tracknummer und > Schema-Erweiterung — die Server-Seite davon ist mit G2 erledigt). > > **Nachtrag 2026-08-25 (UX-Simulation):** Ergänzend zu diesem Code-Review > ist die App per Multi-Agent-Simulation als normaler Nutzer durchgegangen > worden — 7 Flows (Erststart, Bibliothek, Download, Suche, Favoriten, > Player, Einstellungen), 39 Funde. Details im CHANGELOG. Kurzfassung: > Mehrfachauswahl lief nur in zwei von vier Songlisten-Kontexten, der > Baka-Login blieb bei Fehlern bis zu 15s stumm, mehrere destruktive > Aktionen (Cache leeren, Navidrome-Abmelden) hatten keine Rückfrage — alles > behoben. Bewusst nicht angefasst: `ServerFavoriteButton` bleibt wie hier > unter G3 beschrieben lokal-only; das ist keine neue Erkenntnis, sondern > dieselbe offene Baustelle. > > **Nachtrag 2026-08-25 (zweiter, UX-Simulation Teil 3):** Auch die zuerst > zurückgestellten Kleinigkeiten sind erledigt — Abbrechen-Knopf für > YouTube-Downloads, Hintergrund-Punkt am inaktiven Download-Unterreiter, > Versionsnummer unter "Über Melo" (neue Abhängigkeit `package_info_plus`) > und ein Mini-Player, der beim Wischen sichtbar mitführt und zusätzlich > zum Schwung die Strecke auswertet. `ServerFavoriteButton`/G3 bleibt > weiterhin bewusst offen. --- ## 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-Achse~~ → **korrigiert: 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 `navidromeId` — **kein** `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" 6. Alben-Achse: `groupByAlbum`, vierter Unterreiter, Album-Screen *(K4, ~1 Tag)* 7. Suche umbauen: nach Typ gruppiert, Server einbeziehen, letzte Suchen *(G1, ~1,5 Tage)* 8. Server-Bereich aus "Download" lösen → eigener Tab "Online" mit Album-Detail *(G2, ~1,5 Tage)* 9. Offline-Download pro Album/Playlist + Cache-Grenze mit LRU *(G4, ~1,5 Tage)* 10. "Läuft gerade"-Markierung in allen Listen *(G5, ~3 h)* ### P2 — Politur, die man sofort sieht 11. `Colors.redAccent` → `MeloTheme.red`, Emoji → Material-Icons, "Settings" → "Einstellungen" *(G6, G7, P1 — zusammen ~3 h)* 12. Hero-Übergang + Wischgesten am Mini-Player *(P2, P3, ~4 h)* 13. Synchronisierter Songtext (LRC) *(G8, ~1 Tag)* 14. Künstler- und Kategorieliste visuell aufwerten *(P4, ~4 h)* 15. Reduced-Motion + Querformat *(P5, P6, ~4 h)* ### P3 — danach 16. Cover-Farbe im Player *(V1)* 17. Eigene Schrift *(V2)* 18. YouTube-Share-Intent *(V3)* 19. 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._