This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
melo-app/lib/main.dart
T
Dustin 15993b1d0a 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
2026-08-01 19:32:35 +02:00

107 lines
3.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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';
import 'screens/home_screen.dart';
import 'screens/login_screen.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Logger startet sofort zeichnet ALLES auf
MeloLogger().init('2.35');
try {
await DbHelper().db;
await FavoritenService().init();
// Hintergrund-Audio-Service starten
await AudioService.init(
builder: () => MeloAudioHandler(),
config: const AudioServiceConfig(
androidNotificationChannelId: 'de.baka.melo.audio',
androidNotificationChannelName: 'Melo Wiedergabe',
androidNotificationOngoing: true,
),
);
MeloLogger().zustand('start_ok', {'db': 'ok', 'audio': 'ok'});
} catch (e, stack) {
MeloLogger().fehler('App-Start', e, stack);
}
// 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});
@override
Widget build(BuildContext context) {
final auth = AuthService();
return MaterialApp(
title: 'Melo',
debugShowCheckedModeBanner: false,
theme: MeloTheme.theme,
home: auth.istEingeloggt
? const Scaffold(body: MeloHome())
: const LoginScreen(),
);
}
}