// lib/remote/collection_source_remote_ext.dart import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/events.dart'; import 'package:aves/services/common/services.dart'; import 'package:flutter/foundation.dart'; import 'remote_origin.dart'; import 'package:aves/remote/remote_sync_bus.dart'; extension CollectionSourceRemoteExt on CollectionSource { /// Sincronizza le entry remote in memoria con il DB: /// - ADD: aggiunge solo i remoti nuovi /// - DEL: rimuove solo i remoti spariti dal DB /// /// Versione base: diff tra DB e in-memory, senza cache interna. Future appendRemoteEntriesFromDb() async { // 1) carica dal DB tutte le entry remote final Set remotiDb = await localMediaDb.loadEntries(origin: RemoteOrigin.value); final Map dbById = { for (final e in remotiDb) if (e.remoteId != null && e.remoteId!.isNotEmpty) e.remoteId!: e, }; // 2) mappa in-memory dei remoti attuali final Map memById = { for (final e in allEntries) if (e.origin == RemoteOrigin.value && !e.trashed && e.remoteId != null && e.remoteId!.isNotEmpty) e.remoteId!: e, }; // 3) calcola differenze final Set idsDb = dbById.keys.toSet(); final Set idsMem = memById.keys.toSet(); final Set toAddIds = idsDb.difference(idsMem); final Set toRemoveIds = idsMem.difference(idsDb); final List toAdd = [ for (final id in toAddIds) dbById[id]!, ]; final List toRemove = [ for (final id in toRemoveIds) memById[id]!, ]; debugPrint('[remote-diff] add=${toAdd.length} del=${toRemove.length}'); // 4) applica differenze if (toRemove.isNotEmpty) { removeEntries( toRemove.map((e) => e.uri).whereType().toSet(), includeTrash: false, ); } if (toAdd.isNotEmpty) { addEntries(toAdd.toSet()); } // 5) notifica la CollectionLens if (toAdd.isNotEmpty) { try { eventBus.fire(EntryAddedEvent(toAdd.toSet())); } catch (e) { debugPrint('[remote-diff] fire EntryAddedEvent failed: $e'); } } if (toRemove.isNotEmpty) { try { eventBus.fire(EntryRefreshedEvent(const {})); } catch (e) { debugPrint('[remote-diff] fire EntryRefreshedEvent failed: $e'); } } final remotesMem = allEntries .where((e) => e.origin == RemoteOrigin.value && !e.trashed) .length; debugPrint('[remote-diff] done: remotesMem=$remotesMem'); } } /// Visibilità dei remoti (usata da CollectionLens) extension RemoteVisibilityExt on CollectionSource { bool get remoteVisible { final state = RemoteSyncBus.instance.stateNotifier.value; return state == RemoteSyncState.syncing || state == RemoteSyncState.upToDate; } }