From e4f9dd6b33aad19aecb602b73bbbd634ec888087 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 7 Jul 2025 15:57:47 +0530 Subject: [PATCH] Simplify new files notification + avoid redundant compute --- mobile/apps/photos/lib/db/files_db.dart | 16 ------- .../lib/db/remote/table/files_table.dart | 21 ++++++++++ .../services/sync/remote_sync_service.dart | 42 ++++++++++--------- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/mobile/apps/photos/lib/db/files_db.dart b/mobile/apps/photos/lib/db/files_db.dart index e4b3c27b1d..ae5b901ecf 100644 --- a/mobile/apps/photos/lib/db/files_db.dart +++ b/mobile/apps/photos/lib/db/files_db.dart @@ -597,22 +597,6 @@ class FilesDB with SqlDbBase { return files; } - Future> getNewFilesInCollection( - int collectionID, - int addedTime, - ) async { - final db = await instance.sqliteAsyncDB; - const String whereClause = - '$columnCollectionID = ? AND $columnAddedTime > ?'; - final List whereArgs = [collectionID, addedTime]; - final results = await db.getAll( - 'SELECT * FROM $filesTable WHERE $whereClause', - whereArgs, - ); - final files = convertToFiles(results); - return files; - } - // Files which user added to a collection manually but they are not // uploaded yet or files belonging to a collection which is marked for backup Future> getFilesPendingForUpload() async { diff --git a/mobile/apps/photos/lib/db/remote/table/files_table.dart b/mobile/apps/photos/lib/db/remote/table/files_table.dart index 02b94514a8..2d2d7cf7cd 100644 --- a/mobile/apps/photos/lib/db/remote/table/files_table.dart +++ b/mobile/apps/photos/lib/db/remote/table/files_table.dart @@ -1,4 +1,5 @@ import "package:photos/db/remote/db.dart"; +import "package:photos/models/api/diff/diff.dart"; extension FilesTable on RemoteDB { // For a given userID, return unique uploadedFileId for the given userID @@ -39,4 +40,24 @@ extension FilesTable on RemoteDB { parameterSets, ); } + + Future>> getNotificationCandidate( + List collectionIDs, + int lastAppOpen, + ) async { + if (collectionIDs.isEmpty) return {}; + final placeholders = List.filled(collectionIDs.length, '?').join(','); + final rows = await sqliteDB.getAll( + "SELECT collection_id, files.owner_id, metadata FROM collection_files join files ON collection_files.file_id = files.id WHERE collection_id IN ($placeholders) AND collection_files.created_at > ?", + [...collectionIDs, lastAppOpen], + ); + final result = >{}; + for (final row in rows) { + final collectionID = row['collection_id'] as int; + final ownerID = row['owner_id'] as int; + final metadata = Metadata.fromEncodedJson(row['metadata']); + result.putIfAbsent(collectionID, () => []).add((ownerID, metadata)); + } + return result; + } } diff --git a/mobile/apps/photos/lib/services/sync/remote_sync_service.dart b/mobile/apps/photos/lib/services/sync/remote_sync_service.dart index a7269eda03..cd1031dd6e 100644 --- a/mobile/apps/photos/lib/services/sync/remote_sync_service.dart +++ b/mobile/apps/photos/lib/services/sync/remote_sync_service.dart @@ -11,6 +11,7 @@ import "package:photos/core/network/network.dart"; import 'package:photos/db/files_db.dart'; import "package:photos/db/local/table/path_config_table.dart"; import "package:photos/db/local/table/upload_queue_table.dart"; +import "package:photos/db/remote/table/files_table.dart"; import "package:photos/db/remote/table/mapping_table.dart"; import 'package:photos/events/backup_folders_updated_event.dart'; import 'package:photos/events/collection_updated_event.dart'; @@ -22,6 +23,7 @@ import "package:photos/models/file/extensions/file_props.dart"; import 'package:photos/models/file/file.dart'; import 'package:photos/models/file/file_type.dart'; import "package:photos/models/local/path_config.dart"; +import "package:photos/models/metadata/file_magic.dart"; import 'package:photos/models/upload_strategy.dart'; import "package:photos/service_locator.dart"; import 'package:photos/services/app_lifecycle_service.dart'; @@ -590,45 +592,47 @@ class RemoteSyncService { }); } - bool _shouldShowNotification(int collectionID) { - // TODO: Add option to opt out of notifications for a specific collection - // Screen: https://www.figma.com/file/SYtMyLBs5SAOkTbfMMzhqt/ente-Visual-Design?type=design&node-id=7689-52943&t=IyWOfh0Gsb0p7yVC-4 + bool _shouldShowNotification() { final isForeground = AppLifecycleService.instance.isForeground; final bool showNotification = NotificationService.instance.shouldShowNotificationsForSharedPhotos() && isFirstRemoteSyncDone() && !isForeground; _logger.info( - "[Collection-$collectionID] shouldShow notification: $showNotification, " - "isAppInForeground: $isForeground", + " notification: $showNotification isAppInForeground: $isForeground", ); return showNotification; } Future _notifyNewFiles(List collectionIDs) async { + if (!_shouldShowNotification()) { + return; + } final userID = Configuration.instance.getUserID(); final appOpenTime = AppLifecycleService.instance.getLastAppOpenTime(); + final data = await remoteDB.getNotificationCandidate( + collectionIDs, + appOpenTime, + ); for (final collectionID in collectionIDs) { - if (!_shouldShowNotification(collectionID)) { - continue; - } - final files = - await _db.getNewFilesInCollection(collectionID, appOpenTime); - final Set sharedFilesIDs = {}; - final Set collectedFilesIDs = {}; - for (final file in files) { - if (file.isUploaded && file.ownerID != userID) { - sharedFilesIDs.add(file.uploadedFileID!); - } else if (file.isUploaded && file.isCollect) { - collectedFilesIDs.add(file.uploadedFileID!); + // TODO: Add option to opt out of notifications for a specific collection + // Screen: https://www.figma.com/file/SYtMyLBs5SAOkTbfMMzhqt/ente-Visual-Design?type=design&node-id=7689-52943&t=IyWOfh0Gsb0p7yVC-4 + final ownerAndMetadataList = data[collectionID] ?? []; + int sharedFileCount = 0; + int collectedFileCount = 0; + for (final (ownerID, metadata) in ownerAndMetadataList) { + if (ownerID != userID) { + sharedFileCount = sharedFileCount + 1; + } else if (metadata?.data.containsKey(uploaderNameKey) ?? false) { + collectedFileCount = collectedFileCount + 1; } } - final totalCount = sharedFilesIDs.length + collectedFilesIDs.length; + final totalCount = sharedFileCount + collectedFileCount; if (totalCount > 0) { final collection = _collectionsService.getCollectionByID(collectionID); _logger.info( 'creating notification for ${collection?.displayName} ' - 'shared: $sharedFilesIDs, collected: $collectedFilesIDs files', + 'shared: $sharedFileCount, collected: $collectedFileCount files', ); final s = await LanguageService.s; // ignore: unawaited_futures