diff --git a/lib/db/collections_db.dart b/lib/db/collections_db.dart index 88cb44697..d49a16000 100644 --- a/lib/db/collections_db.dart +++ b/lib/db/collections_db.dart @@ -188,6 +188,24 @@ class CollectionsDB { return collections; } + // getActiveCollectionIDsAndUpdationTime returns map of collectionID to + // updationTime for non-deleted collections + Future> getActiveIDsAndRemoteUpdateTime() async { + final db = await instance.database; + final rows = await db.query( + table, + where: '($columnIsDeleted = ? OR $columnIsDeleted IS NULL)', + whereArgs: [_sqlBoolFalse], + columns: [columnID, columnUpdationTime], + ); + final collectionIDsAndUpdationTime = {}; + for (final row in rows) { + collectionIDsAndUpdationTime[row[columnID] as int] = + int.parse(row[columnUpdationTime] as String); + } + return collectionIDsAndUpdationTime; + } + Future deleteCollection(int collectionID) async { final db = await instance.database; return db.delete( diff --git a/lib/services/collections_service.dart b/lib/services/collections_service.dart index 08854b336..15ea92136 100644 --- a/lib/services/collections_service.dart +++ b/lib/services/collections_service.dart @@ -167,15 +167,18 @@ class CollectionsService { _cachedKeys.clear(); } - Future> getCollectionsToBeSynced() async { - final collections = await _db.getAllCollections(); - final updatedCollections = []; - for (final c in collections) { - if (c.updationTime > getCollectionSyncTime(c.id) && !c.isDeleted) { - updatedCollections.add(c); + Future> getCollectionIDsToBeSynced() async { + final idsToRemoveUpdateTimeMap = + await _db.getActiveIDsAndRemoteUpdateTime(); + final result = {}; + for (final MapEntry e in idsToRemoveUpdateTimeMap.entries) { + final int cid = e.key; + final int remoteUpdateTime = e.value; + if (remoteUpdateTime > getCollectionSyncTime(cid)) { + result[cid] = remoteUpdateTime; } } - return updatedCollections; + return result; } Set getArchivedCollections() { diff --git a/lib/services/remote_sync_service.dart b/lib/services/remote_sync_service.dart index 5de50955a..3a272297c 100644 --- a/lib/services/remote_sync_service.dart +++ b/lib/services/remote_sync_service.dart @@ -181,14 +181,19 @@ class RemoteSyncService { } Future _syncUpdatedCollections() async { - final updatedCollections = - await _collectionsService.getCollectionsToBeSynced(); - for (final c in updatedCollections) { + final idsToRemoteUpdationTimeMap = + await _collectionsService.getCollectionIDsToBeSynced(); + for (final cid in idsToRemoteUpdationTimeMap.keys) { await _syncCollectionDiff( - c.id, - _collectionsService.getCollectionSyncTime(c.id), + cid, + _collectionsService.getCollectionSyncTime(cid), ); - await _collectionsService.setCollectionSyncTime(c.id, c.updationTime); + // update syncTime for the collection in sharedPrefs. Note: the + // syncTime can change on remote but we might not get a diff for the + // collection if there are not changes in the file, but the collection + // metadata (name, archive status, sharing etc) has changed. + final remoteUpdateTime = idsToRemoteUpdationTimeMap[cid]; + await _collectionsService.setCollectionSyncTime(cid, remoteUpdateTime); } _logger.info("All updated collections synced"); } @@ -216,24 +221,7 @@ class RemoteSyncService { final diff = await _diffFetcher.getEncryptedFilesDiff(collectionID, sinceTime); if (diff.deletedFiles.isNotEmpty) { - final fileIDs = diff.deletedFiles.map((f) => f.uploadedFileID!).toList(); - final deletedFiles = (await _db.getFilesFromIDs(fileIDs)).values.toList(); - await _db.deleteFilesFromCollection(collectionID, fileIDs); - Bus.instance.fire( - CollectionUpdatedEvent( - collectionID, - deletedFiles, - "syncDeleteFromRemote", - type: EventType.deletedFromRemote, - ), - ); - Bus.instance.fire( - LocalPhotosUpdatedEvent( - deletedFiles, - type: EventType.deletedFromRemote, - source: "syncDeleteFromRemote", - ), - ); + await _syncCollectionDiffDelete(diff, collectionID); } if (diff.updatedFiles.isNotEmpty) { await _storeDiff(diff.updatedFiles, collectionID); @@ -274,6 +262,32 @@ class RemoteSyncService { } } + Future _syncCollectionDiffDelete(Diff diff, int collectionID) async { + final fileIDs = diff.deletedFiles.map((f) => f.uploadedFileID!).toList(); + final localDeleteCount = + await _db.deleteFilesFromCollection(collectionID, fileIDs); + if (localDeleteCount > 0) { + final collectionFiles = + (await _db.getFilesFromIDs(fileIDs)).values.toList(); + collectionFiles.removeWhere((f) => f.collectionID != collectionID); + Bus.instance.fire( + CollectionUpdatedEvent( + collectionID, + collectionFiles, + "syncDeleteFromRemote", + type: EventType.deletedFromRemote, + ), + ); + Bus.instance.fire( + LocalPhotosUpdatedEvent( + collectionFiles, + type: EventType.deletedFromRemote, + source: "syncDeleteFromRemote", + ), + ); + } + } + Future syncDeviceCollectionFilesForUpload() async { _logger.info("Syncing device collections to be uploaded"); final int ownerID = _config.getUserID()!;