v2.52.3 — F3-Rest: ☁️-Chip-Puls + Auto-Sync-Timer app-weit
## Chip-Puls (home_screen)
- ListenableBuilder hört auf Listenable.merge([_vm, _cloud, SyncService.laeuftNotifier]) — der ☁️-Musikserver-Chip pulsiert jetzt bei laufendem Sync (auch im Hintergrund/Auto-Sync), nicht nur beim Verbinden/Laden
- serverSyncLaeuft = SyncService.laeuftNotifier.value || CloudStatus.verbinde || serverLadt
## Auto-Sync-Timer app-weit (main.dart)
- _starteAutoSyncFallsNoetig() entfernt (F3a: kein Sync beim App-Start); stattdessen SyncService.starteAutoSyncTimer() — Timer tickt erst nach dem Intervall, Fälligkeit via istSyncFaellig
- shared_preferences-Import aus main.dart entfernt (Intervall-Logik lebt in SyncService/CloudScreen)
## Sync-Notification
- Sync-Kanal de.baka.melo.sync wird in main() angelegt (Android 8+: Channel nötig, sonst erscheint die Notification nicht)
- onDidReceiveNotificationResponse: Tipp auf 'sync_fertig'/'sync_fehler' → SyncService.syncBenachrichtigungGetippt++ → MeloHome öffnet den Cloud-Tab
## Version
- Versionsanzeige 2.51 → 2.52.3 (settings/home/erweitert), MeloLogger.init('2.35') → '2.52.3'
This commit is contained in:
+31
-48
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_background_service/flutter_background_service.dart';
|
||||
@@ -13,7 +12,9 @@ import 'services/cloud_service.dart';
|
||||
import 'services/melo_logger.dart';
|
||||
import 'services/audio_handler.dart';
|
||||
import 'services/musik_scanner.dart';
|
||||
import 'services/sync_service.dart';
|
||||
import 'utils/farb_theme.dart';
|
||||
import 'utils/user_effekte.dart';
|
||||
import 'screens/home_screen.dart';
|
||||
import 'screens/login_screen.dart';
|
||||
|
||||
@@ -28,13 +29,20 @@ void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Logger startet sofort – zeichnet ALLES auf
|
||||
MeloLogger().init('2.35');
|
||||
MeloLogger().init('2.52.3');
|
||||
|
||||
// ── Notifications initialisieren (Issue #9) ──
|
||||
const androidInit = AndroidInitializationSettings('@mipmap/ic_launcher');
|
||||
const initSettings = InitializationSettings(android: androidInit);
|
||||
await notificationsPlugin.initialize(
|
||||
settings: initSettings,
|
||||
// Tipp auf die Sync-Abschluss-/Fehler-Notification → Cloud-Tab öffnen
|
||||
onDidReceiveNotificationResponse: (response) {
|
||||
if (response.payload == 'sync_fertig' ||
|
||||
response.payload == 'sync_fehler') {
|
||||
SyncService.syncBenachrichtigungGetippt.value++;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Notification-Channel für Downloads (Fortschritt + Abschluss)
|
||||
@@ -51,6 +59,20 @@ void main() async {
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.createNotificationChannel(downloadChannel);
|
||||
|
||||
// Notification-Channel für den Cloud-Sync (Fortschritt + Abschluss)
|
||||
const syncChannel = AndroidNotificationChannel(
|
||||
'de.baka.melo.sync',
|
||||
'Melo Sync',
|
||||
description: 'Cloud-Sync-Fortschritt und Abschluss',
|
||||
importance: Importance.low,
|
||||
playSound: false,
|
||||
enableVibration: false,
|
||||
);
|
||||
await notificationsPlugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.createNotificationChannel(syncChannel);
|
||||
|
||||
// ── Background Service initialisieren (Issue #3) ──
|
||||
await FlutterBackgroundService().configure(
|
||||
iosConfiguration: IosConfiguration(),
|
||||
@@ -108,8 +130,13 @@ void main() async {
|
||||
await Permission.notification.request();
|
||||
}
|
||||
|
||||
// Auto-Sync beim Start (wenn eingeloggt und Auto-Sync aktiv)
|
||||
_starteAutoSyncFallsNoetig();
|
||||
// Per-User-Akzent (überschreibbar in den Einstellungen) + Begrüßungs-Sound
|
||||
// beim App-Start (wenn Token vorhanden). Fehler sind unkritisch.
|
||||
await UserEffekt.anwenden(AuthService().benutzer);
|
||||
|
||||
// App-weiter Auto-Sync-Timer (F3): Intervall aus `cloud_interval`
|
||||
// (0 = Aus), erster Tick erst NACH dem Intervall — kein Sync beim Start.
|
||||
unawaited(SyncService.starteAutoSyncTimer());
|
||||
|
||||
runApp(const MeloApp());
|
||||
}
|
||||
@@ -134,50 +161,6 @@ void _starteAutoScan() {
|
||||
});
|
||||
}
|
||||
|
||||
/// 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.statusDaten();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Background Service Callback – hält App im Vordergrund beim Download (Issue #3)
|
||||
@pragma('vm:entry-point')
|
||||
Future<bool> _onServiceStart(ServiceInstance service) async {
|
||||
|
||||
Reference in New Issue
Block a user