diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index 9d7cbd831b..651277c5d8 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -144,16 +144,13 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { bool keepFavorites = true, Set keepAlbumIds = const {}, }) async { + final iosSharedAlbumIds = _db.localAlbumEntity.selectOnly() + ..addColumns([_db.localAlbumEntity.id]) + ..where(_db.localAlbumEntity.isIosSharedAlbum.equals(true)); + final iosSharedAlbumAssets = _db.localAlbumAssetEntity.selectOnly() ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - useColumns: false, - ), - ]) - ..where(_db.localAlbumEntity.isIosSharedAlbum.equals(true)); + ..where(_db.localAlbumAssetEntity.albumId.isInQuery(iosSharedAlbumIds)); final query = _db.localAssetEntity.select().join([ innerJoin(_db.remoteAssetEntity, _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum)), diff --git a/mobile/test/infrastructure/repositories/local_asset_repository_test.dart b/mobile/test/infrastructure/repositories/local_asset_repository_test.dart index 245cc86a98..17aa440588 100644 --- a/mobile/test/infrastructure/repositories/local_asset_repository_test.dart +++ b/mobile/test/infrastructure/repositories/local_asset_repository_test.dart @@ -438,6 +438,39 @@ void main() { expect(result.assets, isEmpty); }); + test('excludes user-owned assets in iOS shared albums', () async { + await insertLocalAlbum(id: 'album-recents', name: 'Recents', isIosSharedAlbum: false); + + await insertLocalAlbum(id: 'album-shared', name: 'Shared Album', isIosSharedAlbum: true); + + await insertLocalAsset( + id: 'local-user-shared', + checksum: 'checksum-user-shared', + createdAt: beforeCutoff, + type: AssetType.image, + isFavorite: false, + ); + await insertRemoteAsset(id: 'remote-user-shared', checksum: 'checksum-user-shared', ownerId: userId); + await insertLocalAlbumAsset(albumId: 'album-recents', assetId: 'local-user-shared'); + await insertLocalAlbumAsset(albumId: 'album-shared', assetId: 'local-user-shared'); + + // User's asset only in Recents (not in iOS shared album) - should be included for removal + await insertLocalAsset( + id: 'local-user-regular', + checksum: 'checksum-user-regular', + createdAt: beforeCutoff, + type: AssetType.image, + isFavorite: false, + ); + await insertRemoteAsset(id: 'remote-user-regular', checksum: 'checksum-user-regular', ownerId: userId); + await insertLocalAlbumAsset(albumId: 'album-recents', assetId: 'local-user-regular'); + + final result = await repository.getRemovalCandidates(userId, cutoffDate); + + expect(result.assets.length, 1); + expect(result.assets[0].id, 'local-user-regular'); + }); + test('excludes assets with null checksum (not backed up)', () async { // Asset with null checksum cannot be matched to remote asset await db