Commit Graph
20 Commits
Author SHA1 Message Date
Hermes (Server)andClaude Opus 5 bb800adb61 Datenschutz: Fehlerberichte nur mit Zustimmung senden (Opt-in)
Uebertragung eines Befunds aus dem Security-Audit der alten Melo-App
(21.08.2026) in die neue Codebasis.

Ausgangslage hier war eine ANDERE als dort: LoggerService lud jeden Fehler
unbedingt zu logs.baka-net.de hoch, es gab ueberhaupt keinen Schalter. In
der alten App existierte er zwar, wirkte aber nicht ueber einen Neustart
hinaus.

Neu:
- Schalter "Fehlerberichte senden" in den Einstellungen unter Datenschutz,
  Standard AUS. Ohne ausdrueckliche Zustimmung verlaesst kein Bericht das
  Geraet - auch nicht beim allerersten Start und auch nicht im Zeitfenster
  zwischen logger.init() und settings.init().
- Sperre an der einzigen Stelle, durch die jeder Upload laeuft. Lokales
  debugPrint bleibt, aber nichts verlaesst das Geraet; der Puffer wird
  geleert, damit er nicht unbegrenzt waechst.
- Die Entscheidung ueberlebt den Neustart: AppSettings speichert sie und
  reicht sie an den Logger durch, UND LoggerService liest sie beim Start
  zusaetzlich selbst.
- LoggerService bekam einen injizierbaren http.Client (Muster wie BakaAuth),
  damit sich belegen laesst, dass ohne Zustimmung KEIN Request rausgeht.

Auswirkung auf bestehende Installationen: Wer bisher unfreiwillig Berichte
gesendet hat, sendet ab diesem Update keine mehr, bis er zustimmt. Das ist
gewollt - die Zustimmung wurde nie eingeholt.

Nicht uebernommen: der zweite Befund (Logout liess Zugangsdaten zurueck)
trifft hier nicht zu. BakaAuth.abmelden() loescht genau die Schluessel, die
anmelden() schreibt, und Navidrome hat mit loescheZugangsdaten() ein
eigenes, vollstaendiges Trennen.

Auf main (34d6d8e) rebast. settings_screen.dart hat sich sauber automatisch
zusammengefuehrt - die Umbenennungen und MeloTheme-Farben der UI-Politur
bleiben erhalten, der Datenschutz-Abschnitt fuegt sich ein. Im CHANGELOG
kollidierten beide Seiten am Kopf; beide Eintraege wurden behalten.

Tests: 340 gruen (main allein: 328), 12 neue in
test/settings/diagnose_opt_out_test.dart. Fuenf tragende Stellen per
Mutationsprobe geprueft. flutter analyze: keine Befunde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbuWT267W8rFDsaavANuEn
2026-08-21 15:23:03 +02:00
Hermes (Server)andClaude Opus 5 bc861f6087 UI-Politur: Kontrast, Abstaende, Typografie, Bewegung
Kein Redesign — Schwarz/Rot, 4 Tabs und Lieder/Kategorie bleiben. Grundlage
sind die Design-Skills: ui-ux-pro-max (Barrierefreiheit, Touch, Typografie,
Bewegung), ui-design/mobile-android (Material 3) und die Token-Disziplin
aus Hue.

Behobene Maengel (messbar, nicht Geschmack):
- Text in Colors.white38 an 17 Stellen = 3,4:1 Kontrast, WCAG verlangt
  4,5:1. Ersetzt durch drei benannte Stufen (text1 15,9:1 / text2 8,8:1 /
  text3 4,9:1). theme_kontrast_test.dart rechnet die Verhaeltnisse bei
  jedem Lauf nach, statt sie zu behaupten.
- SubTabs waren ~38 dp hoch (Material 3 verlangt 48), ohne Ripple und ohne
  Uebergang. Jetzt 48 dp, InkWell, AnimatedContainer, und die Auswahl wird
  Vorlesehilfen als Zustand gemeldet (Semantics.selected).
- mini_player.dart: Expanded UM eine feste Hoehe herum — zwei
  widerspruechliche Angaben. Entschaerft.
- Emoji in Bedienelementen der Einstellungen (jeweils neben einem echten
  Icon) entfernt.

Neu in shared/theme.dart: MeloSpace (8er-Raster), MeloRadius, MeloMotion,
Farbrollen text1/2/3 + border + hairline, minTouchTarget, vollstaendiges
textTheme (7 Stufen) und Themes fuer Listen, Sheets, Snackbars,
Fortschritt, Trenner.

318 Tests gruen (23 neue, 1 uebersprungen), flutter analyze ohne Befund.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpPu4nuKjKKeX1RpdDeX81
2026-08-21 12:40:25 +02:00
Hermes (Server)andClaude Opus 5 9fa027fca1 Fix: Lokale Wiedergabe + neuer Geraete-Abgleich (Handy <-> Server)
BUG 1 — Lieder vom Handy waren nicht abspielbar
("Wiedergabe fehlgeschlagen: (0) Source error" / "Loading interrupted")

Wurzel-Ursache: MeloAudioHandler.loadPlaylist hat jeden Warteschlangen-
Eintrag durch NavidromeService.streamAndCacheToLocal(item.id) geschickt,
sobald Zugangsdaten existierten. item.id ist aber NIE eine Navidrome-Song-ID
— lokal ist es file:///storage/..., beim Server die fertige Stream-Adresse.
Der Server bekam also 'file:///...' als Song-ID, antwortete mit einem Fehler,
und diese Fehlerantwort wurde an just_audio weitergereicht (Source error) —
bzw. als .mp3 in den Cache geschrieben, wodurch der Titel dauerhaft kaputt
blieb.

Zweite Ursache: die Schleife lud die GANZE Warteschlange seriell vorab
herunter (30s Timeout je Titel), bevor setAudioSources lief. Bei hunderten
Titeln startete die Wiedergabe deshalb nie; ein zweiter Tipp brach den
laufenden Ladevorgang ab ("Loading interrupted").

Fix:
- Server-Titel tragen ihre ID in MediaItem.extras['navidromeId'] statt sie
  aus der Abspiel-Adresse zu raten. Neue reine Funktionen navidromeIdOf,
  songIdOf, nutztServerCache, quelleFuer.
- loadPlaylist baut die Quellen ohne Netzzugriff; Caching des laufenden
  Titels im Hintergrund (unawaited).
- Resume/Scrobble nur noch mit der jeweils passenden ID (Server bzw. lokal).
- ladeInCache() ersetzt streamAndCacheToLocal(): .part-Datei, Pruefung des
  Inhaltstyps (istAudioAntwort), stabiler Cache-Schluessel ueber die
  Song-ID statt der Stream-Adresse (die trug Token+Salt und war je Sitzung
  anders — der Cache war nie wiederauffindbar), Client wird geschlossen.

BUG 2 — kein Abgleich zwischen Handy und Server

Neu: services/melo_cloud_service.dart + services/sync_service.dart gegen
cloud.baka-net.de (Bearer-JWT ueber BakaAuth). Server-Titel herunterladen
(offline verfuegbar), eigene Dateien hochladen, Loeschungen in beide
Richtungen (Tombstones), Favoriten und Wiedergabe-Verlauf. Automatisch beim
App-Start und bei Rueckkehr in die App (max. alle 15 Min), plus Knopf unter
Einstellungen -> Geraete-Abgleich. Reine Planungsfunktion planeSync().

Bewusst NICHT ueber Navidrome: die Subsonic-API kennt keinen Upload-
Endpunkt. Navidrome bleibt die Streaming-Bibliothek, die Melo-Cloud ist der
gemeinsame Speicher.

DB-Schema 8: songs.cloud_id verbindet Geraet und Server.

Nebenbei behoben (blockierte Build bzw. Tests):
- database.g.dart war veraltet — das Projekt liess sich nicht uebersetzen.
- metadataEdited wurde nirgends gesetzt/beachtet: von Hand korrigierte
  Metadaten wurden vom naechsten Scan ueberschrieben. Jetzt in beiden
  Scans respektiert; metadatenUebernahme() setzt die Markierung.
- song_detail_sheet_test.dart haengt beim Oeffnen des Modal-Sheets und
  blockierte den gesamten Testlauf — vorerst uebersprungen (TODO im Code);
  der Zweck wird von metadaten_uebernahme_test.dart abgedeckt.

Enthaelt ausserdem die bis dahin nicht committete Arbeit der Vorsitzung
(Musikerkennung/ACRCloud, MusicBrainz-Metadaten, MediaStore-Datentraeger).

267 Tests gruen (1 uebersprungen), flutter analyze ohne Befund.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpPu4nuKjKKeX1RpdDeX81
2026-08-21 08:32:32 +02:00
dustinandClaude Opus 5 4ebd0a8dd4 Songtext aus Datei-Tags, Warteschlangen-Aktionen, Kategorie-Cover im
Sperrbildschirm und ReplayGain

- DB-Schema 6: lyrics + gain_db
- Songtext bevorzugt lokalen Tag, Server nur als Rueckfall; Song-ID-Bug
  beim Lyrics-Aufruf behoben
- "Als Naechstes spielen" / "Zur Warteschlange hinzufuegen" ohne Eingriff
  in Favoriten oder Wiedergabelisten
- songToMediaItem nimmt eine Cover-Vorgabe: Sperrbildschirm zeigt das
  Kategorie-Cover
- ReplayGain: Tags werden gelesen, laute Titel abgesenkt, abschaltbar

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
2026-08-20 18:41:36 +02:00
dustinandClaude Opus 5 1325badf90 Equalizer (nativ), Dolby-Atmos-Zugang und Auto-Wiedergabe bei Kopfhoerern
- Native Bruecke AudioEffectsBridge.kt: Equalizer + BassBoost + Virtualizer
  auf der Audio-Session des Players, inkl. System-Klangeffekt-Panel
- Dart-Seite AudioEffects: Presets, Baender, Bass/Immersiv, persistiert
- EqualizerScreen nach Vorlage inkl. Drehregler (CustomPainter)
- Auto-Wiedergabe bei verbundenen Kopfhoerern (Klinke + Bluetooth)
- MODIFY_AUDIO_SETTINGS im Manifest
- Einstellungen: neuer Bereich "Ton"

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
2026-08-20 18:35:06 +02:00
dustinandClaude Opus 5 7aa98864aa Kategorien (mehrere je Song), Metadaten-Ansicht mit Expertenmodus
- DB-Schema 4: Tabelle song_categories + Spalte categories_edited
- Kategorien kommen aus dem Genre-Tag (Trennung an ; , | /), manuell
  bearbeitbar; von Hand gesetzte Kategorien ueberlebt der naechste Scan
- Songzeile zeigt "Kuenstler | Kategorie1 - Kategorie2"
- Einstellung "Gleiche Kategorie = gleiches Coverbild" (Standard an)
- Metadaten-Sheet mit ausklappbarem Expertenmodus
- Neu: categories.dart, category_service.dart, song_detail_sheet.dart,
  app_settings.dart

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
2026-08-20 18:29:45 +02:00
dustinandClaude Opus 5 2667613a2e Neue Melo-UI Phase 1: 4 Tabs (Meine Musik/Suche/Favoriten/Download) + Sortierung
- Meine Musik als Startbildschirm ohne Topbar: Kopfzeile (Einstellungen,
  Suche, Musikerkennung), Schnellzugriffe, Shuffle + Sortieren, Liederliste
- Sortierung nach Zuletzt hinzugefuegt / Name (A-Z-#) / Wie oft abgespielt,
  auf- und absteigend, pro Liste gespeichert (SortStore)
- Favoriten als eigener Tab mit gleicher Shuffle-/Sortier-Leiste
- Download-Tab uebernimmt den Navidrome-Server-Browser
- DB-Schema 3: playCount, gezaehlt beim Titelstart
- Theme auf #0B0B10 / #c0392b
- Scan-Aktionen aus der entfallenen Topbar jetzt in den Einstellungen

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
2026-08-20 18:00:53 +02:00
Hermes (Server)andClaude Fable 5 5d08da1086 Login-Dialog zeigt echte Server-Fehlermeldung + pwLen im Log
Tiefe Debug-Runde bewiesen: Server, DB-Passwort und App-Token-Logik sind
korrekt (8/8-Repro gegen Live-Server) — abgelehnt wird ein falscher
Passwort-Wert vom Gerät. Damit das künftig sofort sichtbar ist:
- NavidromeService.letzterLoginFehler hält die Server-Meldung fest
- Login-Dialog zeigt sie statt generischem "Login fehlgeschlagen"
- Fehler-Log enthält die Passwort-Länge (nie das Passwort selbst)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JRj3pupcigUi683vy2Wwnz
2026-08-20 16:13:34 +02:00
Hermes (Server)andClaude Opus 4.8 a7d2da9512 Default-User im Navidrome-Login auf 'Baka' setzen
Vorher war der Dialog-Default 'Dustin' — versehentlicher Login-Versuch mit
falschem User. Default ist jetzt 'Baka'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
2026-08-20 10:04:04 +02:00
Hermes (Server)andClaude Opus 4.8 3d1e00646a Fix: Navidrome-Login — Passwort-Sichtbarkeit + Trim (Login fehlgeschlagen)
Systematische Diagnose bewies: App-Code, Server, User 'Baka' und Passwort sind
korrekt (1:1-Nachbau des App-Requests inkl. Salt/Token -> Navidrome status:ok).
Der Fehler lag im auf dem Gerät verwendeten Credential-Wert:
- der alte Build (Ping-Fehlalarm) persistierte ungültige Zugangsdaten,
- verdeckte Tippfehler im obscureText-Passwortfeld blieben unsichtbar.

Fix:
- Passwort-Anzeigen-Umschalter (Auge-Icon) im Login-Dialog.
- URL + Passwort werden getrimmt (Autofill/Tastatur-Leerzeichen).
Ein erfolgreicher Login ueberschreibt die alten gespeicherten Credentials;
der Ping-Fix stellt sicher, dass nur gueltige gespeichert werden.

84/84 Tests gruen, analyze sauber.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
2026-08-20 09:52:07 +02:00
Hermes (Server)andClaude Opus 4.8 d83f8c8c54 Datenschutz: Log-Bereinigung vor Server-Upload (Scrubber + Quelle)
Diagnose-Logs werden zentral bereinigt, bevor sie an logs.baka-net.de gehen.
Lokaler debugPrint bleibt vollständig.

- Freitext-Scrubber (LoggerService.scrubText) für message + stackTrace:
  maskiert user=/pw=/password=/token=/secret=/url= sowie Datei-Pfade,
  nackte URLs, Bearer-Token, JWTs und lange Hex-IDs.
- stackTrace auf 8 Zeilen gekürzt (capFrames).
- deviceModel nur noch grobe Plattform (android/ios) statt Hersteller+Modell;
  device_info_plus im Logger entfernt.
- Quelle entschärft: settings_screen loggte Navidrome-Login mit Klartext
  user=/url= — jetzt nur neutraler Status inkl. pwLeer-Flag.
- Neue Tests: test/logger_service_test.dart (9). 79/79 grün, analyze sauber.

Opt-in/Einwilligung bleibt separater Folgeschritt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
2026-08-20 01:38:56 +02:00
Hermes (Server)andClaude Haiku 4.5 61e28d128f 🔧 Fix Log-Upload System: ERROR-Level sofort hochladen + Navidrome-Fehler tracken
- error() ist jetzt async mit await — ERROR-Logs werden SOFORT zum Server hochgeladen
- Alle Navidrome API-Fehler nutzen logger.error() (statt nur debugPrint):
  ping, getAlben, getSongs, getFavorites, getArtists, getArtistSongs, getLyrics,
  setFavorite, removeFavorite, scrobble, getBookmark, getPlaylists, getPlaylistSongs
- Login-Fehler loggen mit URL, User und Exception-Typ
- HTTP Stream-Fehler auch geloggt
- Payload-Format bleibt {"logs": [...]} Array (https://logs.baka-net.de/api/logs)

Alle 70 Tests bestanden 

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiRmGyzAMkzHMqBsBe2h3n
2026-08-19 22:36:58 +02:00
Hermes (Server)andClaude Haiku 4.5 323a67e3a2 🐛 Fix: INTERNET-Permission fehlte im Release-Manifest
ROOT CAUSE für die fehlenden Logs — und für den fehlschlagenden
Navidrome-Login: Flutter injiziert android.permission.INTERNET nur in
debug/ und profile/AndroidManifest.xml. In main/AndroidManifest.xml
stand sie nicht, das Release-APK hatte damit gar keinen Netzzugriff.
Jede http-Anfrage schlug sofort mit SocketException fehl.

- INTERNET + ACCESS_NETWORK_STATE in main/AndroidManifest.xml ergänzt
- Login-Versuch/-Erfolg/-Fehlschlag im Settings-Dialog explizit geloggt
  (URL + User + ob das Passwortfeld leer war; das Passwort selbst nicht)
- Batch-Schwelle 20 -> 5, damit INFO-Logs auch ohne vorherigen Fehler
  hochgeladen werden

Nicht geaendert: der Sofort-Upload bei ERROR war bereits implementiert
(error() ruft _uploadIfError -> _uploadLogs direkt auf) und war nicht
die Ursache.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
2026-08-19 22:28:36 +02:00
Hermes (Server)andClaude Haiku 4.5 2948285d82 Feature: Login-Verbesserungen für Dustin!
1. 🔗 AUTO-URL: Server-URL \"https://musik.baka-net.de\" vorausgefüllt (editierbar)
2. 👤 USER-BUTTONS: Baka/Tinker/Dustin als Button-Auswahl (statt Text-Input)
3. 🔐 PASSWORT-ONLY: Dialog zeigt nur Passwort-Feld + User-Auswahl (wie beim Register!)
4. 💡 GAST-MODUS: Info-Text erklärt lokale Nutzung ohne Server-Konto
   → App funktioniert auch komplett offline mit lokaler Musikbibliothek!

UX-Verbesserungen:
- Weniger zu tippen (URL + User vorgegeben)
- Schneller Login für Baka/Tinker/Dustin
- Klare Fallback-Option für lokale Nutzung

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
2026-08-19 21:12:38 +02:00
Hermes (Server)andClaude Haiku 4.5 221e6fd923 📋 Feature: Playlisten-Sync vom Navidrome-Server (Phase 2, Part 6/X)
- getPlaylists() + getPlaylistSongs() APIs für Subsonic-Playlist-Laden
- syncPlaylistsFromServer() in PlaylistService importiert alle Server-Playlisten als lokale
- Benennung mit 🌐 Präfix um Server-Playlisten zu kennzeichnen
- Settings-Button lädt alle Playlisten mit ihren Songs vom Server
- Zeigt Anzahl importierter Playlisten mit SnackBar

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
2026-08-19 19:30:50 +02:00
Hermes (Server)andClaude Haiku 4.5 b37f7c7a2f 🌟 Feature: Favoriten-Sync vom Navidrome-Server (Phase 2, Part 4/X)
- syncFavoritesFromServer() in PlaylistService laden Server-Favoriten
- Prüft lokal existierende Songs und markiert als Favorit
- Settings-Button: "🌟 Favoriten-Sync" mit Cloud-Download Icon
- Zeigt Anzahl importierter Favoriten mit SnackBar
- DB-Methoden hinzugefügt: songExists() + setFavorite()

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
2026-08-19 19:12:14 +02:00
Hermes (Server) 2548e38af9 feat(settings): Cache-Status UI + Clear-Button (Phase 2)
- Neuer 'Cache-Speicher' ListTile in Musikserver-Sektion
- Zeigt Cache-Größe in MB/KB/B
- Clear-Button: Löscht alle gecachten Lieder
- _formatBytes() für Größen-Anzeige
- _clearCache() mit SnackBar-Feedback

Nutzer kann jetzt Cache-Status sehen + leeren!
Tests: 70/70 
2026-08-19 19:04:47 +02:00
Hermes (Server) 0635c92d22 feat(settings): Offline-Mode Toggle UI (Phase 2)
- Toggle in Settings unter 'Musikserver'-Sektion
- Label: '📴 Offline-Modus' + Beschreibung
- Switch: Ein/Aus Toggle
- OfflineMode ChangeNotifierProvider in main.dart
- Tests angepasst für Provider-Setup

Nutzer kann jetzt Offline-Mode an/aus schalten!
Tests: 70/70 
2026-08-19 19:03:26 +02:00
Hermes (Server)andClaude Haiku 4.5 06be0a7065 feat(navidrome): Musikserver-Integration (Subsonic API)
- NavidromeService mit Credential-Verwaltung (secure storage)
- Navidrome-Settings in Settings-Tab: Login/Logout für Server-Verbindung
- Dependencies hinzugefügt: http, crypto, shared_preferences, flutter_secure_storage
- Tests: 70/70 grün
- Analyzer:  keine Fehler

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJzQjUtnvYUtHdnTs3iCru
2026-08-19 07:21:32 +02:00
Hermes (Server)andClaude Haiku 4.5 23a1e7838d feat(settings): Settings-Tab mit Bibliotheks-Statistik, Berechtigungen, Über Melo
- Bibliotheks-Statistik: Song-Anzahl + Gesamtspieldauer via watchSongs()
  (reine Summier-/Format-Funktion in lib/settings/library_stats.dart,
  unabhängig von Flutter/Plattform testbar)
- Berechtigungen: Musik-Berechtigung öffnet Systemeinstellungen über das
  bereits vorhandene openMusicPermissionSettings()
- Über Melo: kurzer Name + Slogan, keine erfundene Versionsnummer
  (package_info_plus ist keine Dependency)
- Keine Platzhalter für Profil/Cloud-Sync/Geräte-Verwaltung, da es noch
  kein Account-/Cloud-System gibt (Phase 2)
- HomeShell nutzt SettingsScreen statt des Settings-Placeholders,
  toter _Placeholder-Widget-Code entfernt

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-18 18:31:30 +02:00