v2.35 — Vollständiges Sync-System: Playlisten, Favoriten, Auto-Sync, Persistent Login, Benutzerdefinierte Namen

## Server (melo_cloud.py v3.0.0)
- Neue DB-Tabellen: user_playlists, user_playlist_songs, user_favorites, user_history, sync_meta
- Playlist-Endpunkte: GET/POST /api/cloud/playlists, GET /api/cloud/playlists/<id>, POST songs, DELETE songs, PUT positions
- Favoriten-Endpunkte: GET/POST /api/cloud/favorites, POST /api/cloud/favorites/toggle
- History-Endpunkte: GET/POST /api/cloud/history (mit Dedup)
- Rename-Endpunkt: POST /api/cloud/rename (custom_title/custom_artist)
- Sync-Endpunkte: POST /api/cloud/sync-all, GET /api/cloud/sync-status
- delete-all erweitert um Playlists + Favorites + History

## App
- db_helper.dart: Migration v4→v5 (cloud_id, cloud_title, cloud_artist, server_favorites, sync_metadata)
- auth_service.dart: Token-Validierung beim Start (online check + Offline-Fallback), Persistent Login
- cloud_service.dart: Neue Methoden für Playlists (CRUD), Favorites (get/sync/toggle), Rename, History, syncAll/syncStatus
- cloud_screen.dart: Komplett-Rewrite mit Sync-Modus (Manuell/Auto), Intervall-Auswahl, Sync-Fortschritt-Anzeige, Playlist-Verwaltung, Favoriten-Anzeige + Umbenennen, Sync-Info-Karte, nächster Sync
- main.dart: Auto-Sync beim App-Start (nur wenn konfiguriert + fällig)

## Flutter Analyze
- 0 neue Issues — nur 7 pre-existing
This commit is contained in:
Dustin
2026-08-01 19:32:35 +02:00
parent 2b06a8e496
commit 15993b1d0a
5 changed files with 1551 additions and 463 deletions
+51 -2
View File
@@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:audio_service/audio_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'database/db_helper.dart';
import 'services/favoriten_service.dart';
import 'services/auth_service.dart';
import 'services/cloud_service.dart';
import 'services/melo_logger.dart';
import 'services/audio_handler.dart';
import 'utils/farb_theme.dart';
@@ -13,7 +15,7 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Logger startet sofort zeichnet ALLES auf
MeloLogger().init('2.31');
MeloLogger().init('2.35');
try {
await DbHelper().db;
@@ -32,12 +34,59 @@ void main() async {
MeloLogger().fehler('App-Start', e, stack);
}
// Auth initialisieren (Token aus SharedPreferences laden)
// Auth initialisieren (Token aus SharedPreferences laden + online validieren)
await AuthService().initialisieren();
// Auto-Sync beim Start (wenn eingeloggt und Auto-Sync aktiv)
_starteAutoSyncFallsNoetig();
runApp(const MeloApp());
}
/// Führt Cloud-Auto-Sync beim App-Start aus, falls konfiguriert
Future<void> _starteAutoSyncFallsNoetig() async {
try {
final auth = AuthService();
if (!auth.istEingeloggt) return;
// Prüfen, ob Auto-Sync aktiviert ist
final SharedPreferences prefs =
await SharedPreferences.getInstance();
final autoSync = prefs.getBool('cloud_auto') ?? true;
if (!autoSync) return;
final cloud = CloudService();
final ok = await cloud.login(auth.benutzer);
if (!ok) return;
// Letzten Sync prüfen — nur syncen wenn nötig
final lastSync = prefs.getString('cloud_last_sync_ts');
final now = DateTime.now();
if (lastSync != null) {
final last = DateTime.tryParse(lastSync);
if (last != null) {
final interval = prefs.getInt('cloud_interval') ?? 6;
if (now.difference(last).inHours < interval) {
return; // Noch nicht fällig
}
}
}
// Sync ausführen
MeloLogger().aktion('auto_sync_start', {});
final st = await cloud.status();
if (st != null) {
final serverSongs = await cloud.listSongs();
MeloLogger().aktion('auto_sync_done',
{'songs': serverSongs.length});
}
await prefs.setString('cloud_last_sync_ts', now.toIso8601String());
} catch (e) {
MeloLogger().fehler('auto_sync_init', e);
}
}
class MeloApp extends StatelessWidget {
const MeloApp({super.key});