v2.52 — Favoriten-Sync-Fix: bidirektionaler Merge (lokal↔Server), Toggle-Push sofort, cloud_id-Verdrahtung
This commit is contained in:
@@ -8,6 +8,8 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import '../utils/farb_theme.dart';
|
||||
import '../utils/sanitize.dart';
|
||||
import '../services/cloud_service.dart';
|
||||
import '../services/favoriten_service.dart';
|
||||
import '../services/favoriten_sync.dart';
|
||||
import '../database/db_helper.dart';
|
||||
import '../services/melo_logger.dart';
|
||||
import '../models/song.dart';
|
||||
@@ -36,6 +38,9 @@ class _CloudScreenState extends State<CloudScreen>
|
||||
bool _statusOk = false;
|
||||
bool _serverDatenGeladen = false;
|
||||
|
||||
// ─── Favoriten (bidirektionaler Sync) ───
|
||||
final FavoritenService _favoriten = FavoritenService();
|
||||
|
||||
// ─── Sync-Animation ───
|
||||
late final AnimationController _syncAnimController;
|
||||
|
||||
@@ -324,17 +329,29 @@ class _CloudScreenState extends State<CloudScreen>
|
||||
const Duration(milliseconds: 50)); // UI-Update erlauben
|
||||
}
|
||||
|
||||
// Phase 2: Favoriten syncen
|
||||
_updateSync('Synchronisiere Favoriten...', 0.55);
|
||||
final favs = await widget.cloud.getFavorites();
|
||||
final favIds = favs
|
||||
// Phase 2: Favoriten bidirektional synchronisieren
|
||||
// Root-Cause-Fix (Sprint D): Vorher wurden die Server-Favoriten nur
|
||||
// zurückgespiegelt (Server → Server) — lokale ⭐-Toggles gingen
|
||||
// verloren. Jetzt: Vereinigung lokal ∪ Server, Push + lokales Markieren.
|
||||
_updateSync('Sync Favoriten…', 0.55);
|
||||
final serverFavs = await widget.cloud.getFavorites();
|
||||
final serverIds = serverFavs
|
||||
.map((f) => f['id']?.toString() ?? '')
|
||||
.where((id) => id.isNotEmpty)
|
||||
.toList();
|
||||
await widget.cloud.syncFavorites(favIds);
|
||||
await db.serverFavoritesSet(favIds);
|
||||
setState(() => _favServerCount = favIds.length);
|
||||
_syncedItems += favIds.length;
|
||||
.toSet();
|
||||
final lokalIds = await _favoriten.favoritenCloudIds();
|
||||
final merged = favoritenMerge(lokal: lokalIds, server: serverIds);
|
||||
// Lokal → Server: lokale Toggles erreichen den Server, Server-Favoriten
|
||||
// bleiben erhalten (kein Datenverlust in beide Richtungen)
|
||||
await widget.cloud.syncFavorites(merged);
|
||||
// Server → Lokal: Server-Favoriten lokal als ⭐ markieren (wenn Song
|
||||
// lokal existiert); `server_favorites` spiegelt den Merge-Zustand
|
||||
for (final cid in serverIds) {
|
||||
await _favoriten.merkeCloudFavorit(cid);
|
||||
}
|
||||
await db.serverFavoritesSet(merged);
|
||||
setState(() => _favServerCount = merged.length);
|
||||
_syncedItems += merged.length;
|
||||
|
||||
// Phase 3: Playlisten abgleichen
|
||||
_updateSync('Lade Playlisten...', 0.7);
|
||||
@@ -349,22 +366,22 @@ class _CloudScreenState extends State<CloudScreen>
|
||||
_updateSync('Fertig!', 1.0);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_syncedItems = downloaded + favIds.length;
|
||||
_syncedItems = downloaded + merged.length;
|
||||
});
|
||||
_setzeStatus(
|
||||
'$downloaded Songs + ${favIds.length} Favoriten synchronisiert',
|
||||
'$downloaded Songs + ${merged.length} Favoriten synchronisiert',
|
||||
ok: true);
|
||||
// Sync-Historie fürs Dashboard festhalten
|
||||
await _syncHistorieEintragen(
|
||||
dateien: downloaded,
|
||||
favoriten: favIds.length,
|
||||
favoriten: merged.length,
|
||||
playlists: _serverPlaylists.length,
|
||||
);
|
||||
await _ladeStatus();
|
||||
}
|
||||
MeloLogger().aktion('cloud_sync_all', {
|
||||
'downloaded': downloaded,
|
||||
'favorites': favIds.length,
|
||||
'favorites': merged.length,
|
||||
'playlists': _serverPlaylists.length,
|
||||
});
|
||||
return true;
|
||||
@@ -714,6 +731,7 @@ class _CloudScreenState extends State<CloudScreen>
|
||||
setState(() => _ladt = true);
|
||||
_setzeStatus('Suche lokale Songs...');
|
||||
try {
|
||||
final db = DbHelper();
|
||||
final dir = Directory(
|
||||
'${(await getApplicationDocumentsDirectory()).path}/music');
|
||||
if (!await dir.exists()) {
|
||||
@@ -754,7 +772,19 @@ class _CloudScreenState extends State<CloudScreen>
|
||||
);
|
||||
}
|
||||
final sid = await widget.cloud.upload(f.path, f.path.split('/').last);
|
||||
if (sid != null) count++;
|
||||
if (sid != null) {
|
||||
count++;
|
||||
// Lokalen Song mit dem Server verknüpfen (cloud_id) — Grundlage
|
||||
// für den bidirektionalen Favoriten-Sync (lokal → Server).
|
||||
try {
|
||||
final lokalerSong = await db.songNachPfad(f.path);
|
||||
if (lokalerSong?.id != null) {
|
||||
await db.cloudIdSetzen(lokalerSong!.id!, sid);
|
||||
}
|
||||
} catch (_) {
|
||||
// Verknüpfung ist nice-to-have — Upload selbst war erfolgreich
|
||||
}
|
||||
}
|
||||
}
|
||||
// Abschluss-Notification
|
||||
if (Platform.isAndroid) {
|
||||
|
||||
Reference in New Issue
Block a user