diff --git a/mobile/lib/modules/archive/providers/archive_asset_provider.dart b/mobile/lib/modules/archive/providers/archive_asset_provider.dart index 26d0b2eea9..1f151b9228 100644 --- a/mobile/lib/modules/archive/providers/archive_asset_provider.dart +++ b/mobile/lib/modules/archive/providers/archive_asset_provider.dart @@ -13,8 +13,9 @@ final archiveProvider = StreamProvider((ref) async* { final query = ref .watch(dbProvider) .assets + .where() + .ownerIdEqualToAnyChecksum(user.isarId) .filter() - .ownerIdEqualTo(user.isarId) .isArchivedEqualTo(true) .sortByFileCreatedAt(); final settings = ref.watch(appSettingsServiceProvider); diff --git a/mobile/lib/modules/favorite/providers/favorite_provider.dart b/mobile/lib/modules/favorite/providers/favorite_provider.dart index 4ddb73ea69..2439d627fa 100644 --- a/mobile/lib/modules/favorite/providers/favorite_provider.dart +++ b/mobile/lib/modules/favorite/providers/favorite_provider.dart @@ -13,8 +13,9 @@ final favoriteAssetsProvider = StreamProvider((ref) async* { final query = ref .watch(dbProvider) .assets + .where() + .ownerIdEqualToAnyChecksum(user.isarId) .filter() - .ownerIdEqualTo(user.isarId) .isFavoriteEqualTo(true) .sortByFileCreatedAt(); final settings = ref.watch(appSettingsServiceProvider); diff --git a/mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart b/mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart index d5a0c0d928..9e5f77caf6 100644 --- a/mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart +++ b/mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart @@ -142,7 +142,7 @@ class RenderList { ) async { final List elements = []; - const pageSize = 500; + const pageSize = 50000; const sectionSize = 60; // divides evenly by 2,3,4,5,6 if (groupBy == GroupAssetsBy.none) { diff --git a/mobile/lib/shared/models/asset.dart b/mobile/lib/shared/models/asset.dart index e8f969a111..cea12e7b62 100644 --- a/mobile/lib/shared/models/asset.dart +++ b/mobile/lib/shared/models/asset.dart @@ -100,12 +100,6 @@ class Asset { /// stores the raw SHA1 bytes as a base64 String /// because Isar cannot sort lists of byte arrays - @Index( - unique: true, - replace: false, - type: IndexType.hash, - composite: [CompositeIndex("ownerId")], - ) String checksum; @Index(unique: false, replace: false, type: IndexType.hash) @@ -114,6 +108,11 @@ class Asset { @Index(unique: false, replace: false, type: IndexType.hash) String? localId; + @Index( + unique: true, + replace: false, + composite: [CompositeIndex("checksum", type: IndexType.hash)], + ) int ownerId; DateTime fileCreatedAt; diff --git a/mobile/lib/shared/models/asset.g.dart b/mobile/lib/shared/models/asset.g.dart index 713c26885b..606f9692e9 100644 --- a/mobile/lib/shared/models/asset.g.dart +++ b/mobile/lib/shared/models/asset.g.dart @@ -100,24 +100,6 @@ const AssetSchema = CollectionSchema( deserializeProp: _assetDeserializeProp, idName: r'id', indexes: { - r'checksum_ownerId': IndexSchema( - id: 5611361749756160119, - name: r'checksum_ownerId', - unique: true, - replace: false, - properties: [ - IndexPropertySchema( - name: r'checksum', - type: IndexType.hash, - caseSensitive: true, - ), - IndexPropertySchema( - name: r'ownerId', - type: IndexType.value, - caseSensitive: false, - ) - ], - ), r'remoteId': IndexSchema( id: 6301175856541681032, name: r'remoteId', @@ -143,6 +125,24 @@ const AssetSchema = CollectionSchema( caseSensitive: true, ) ], + ), + r'ownerId_checksum': IndexSchema( + id: -3295822444433175883, + name: r'ownerId_checksum', + unique: true, + replace: false, + properties: [ + IndexPropertySchema( + name: r'ownerId', + type: IndexType.value, + caseSensitive: false, + ), + IndexPropertySchema( + name: r'checksum', + type: IndexType.hash, + caseSensitive: true, + ) + ], ) }, links: {}, @@ -302,89 +302,89 @@ void _assetAttach(IsarCollection col, Id id, Asset object) { } extension AssetByIndex on IsarCollection { - Future getByChecksumOwnerId(String checksum, int ownerId) { - return getByIndex(r'checksum_ownerId', [checksum, ownerId]); + Future getByOwnerIdChecksum(int ownerId, String checksum) { + return getByIndex(r'ownerId_checksum', [ownerId, checksum]); } - Asset? getByChecksumOwnerIdSync(String checksum, int ownerId) { - return getByIndexSync(r'checksum_ownerId', [checksum, ownerId]); + Asset? getByOwnerIdChecksumSync(int ownerId, String checksum) { + return getByIndexSync(r'ownerId_checksum', [ownerId, checksum]); } - Future deleteByChecksumOwnerId(String checksum, int ownerId) { - return deleteByIndex(r'checksum_ownerId', [checksum, ownerId]); + Future deleteByOwnerIdChecksum(int ownerId, String checksum) { + return deleteByIndex(r'ownerId_checksum', [ownerId, checksum]); } - bool deleteByChecksumOwnerIdSync(String checksum, int ownerId) { - return deleteByIndexSync(r'checksum_ownerId', [checksum, ownerId]); + bool deleteByOwnerIdChecksumSync(int ownerId, String checksum) { + return deleteByIndexSync(r'ownerId_checksum', [ownerId, checksum]); } - Future> getAllByChecksumOwnerId( - List checksumValues, List ownerIdValues) { - final len = checksumValues.length; - assert(ownerIdValues.length == len, + Future> getAllByOwnerIdChecksum( + List ownerIdValues, List checksumValues) { + final len = ownerIdValues.length; + assert(checksumValues.length == len, 'All index values must have the same length'); final values = >[]; for (var i = 0; i < len; i++) { - values.add([checksumValues[i], ownerIdValues[i]]); + values.add([ownerIdValues[i], checksumValues[i]]); } - return getAllByIndex(r'checksum_ownerId', values); + return getAllByIndex(r'ownerId_checksum', values); } - List getAllByChecksumOwnerIdSync( - List checksumValues, List ownerIdValues) { - final len = checksumValues.length; - assert(ownerIdValues.length == len, + List getAllByOwnerIdChecksumSync( + List ownerIdValues, List checksumValues) { + final len = ownerIdValues.length; + assert(checksumValues.length == len, 'All index values must have the same length'); final values = >[]; for (var i = 0; i < len; i++) { - values.add([checksumValues[i], ownerIdValues[i]]); + values.add([ownerIdValues[i], checksumValues[i]]); } - return getAllByIndexSync(r'checksum_ownerId', values); + return getAllByIndexSync(r'ownerId_checksum', values); } - Future deleteAllByChecksumOwnerId( - List checksumValues, List ownerIdValues) { - final len = checksumValues.length; - assert(ownerIdValues.length == len, + Future deleteAllByOwnerIdChecksum( + List ownerIdValues, List checksumValues) { + final len = ownerIdValues.length; + assert(checksumValues.length == len, 'All index values must have the same length'); final values = >[]; for (var i = 0; i < len; i++) { - values.add([checksumValues[i], ownerIdValues[i]]); + values.add([ownerIdValues[i], checksumValues[i]]); } - return deleteAllByIndex(r'checksum_ownerId', values); + return deleteAllByIndex(r'ownerId_checksum', values); } - int deleteAllByChecksumOwnerIdSync( - List checksumValues, List ownerIdValues) { - final len = checksumValues.length; - assert(ownerIdValues.length == len, + int deleteAllByOwnerIdChecksumSync( + List ownerIdValues, List checksumValues) { + final len = ownerIdValues.length; + assert(checksumValues.length == len, 'All index values must have the same length'); final values = >[]; for (var i = 0; i < len; i++) { - values.add([checksumValues[i], ownerIdValues[i]]); + values.add([ownerIdValues[i], checksumValues[i]]); } - return deleteAllByIndexSync(r'checksum_ownerId', values); + return deleteAllByIndexSync(r'ownerId_checksum', values); } - Future putByChecksumOwnerId(Asset object) { - return putByIndex(r'checksum_ownerId', object); + Future putByOwnerIdChecksum(Asset object) { + return putByIndex(r'ownerId_checksum', object); } - Id putByChecksumOwnerIdSync(Asset object, {bool saveLinks = true}) { - return putByIndexSync(r'checksum_ownerId', object, saveLinks: saveLinks); + Id putByOwnerIdChecksumSync(Asset object, {bool saveLinks = true}) { + return putByIndexSync(r'ownerId_checksum', object, saveLinks: saveLinks); } - Future> putAllByChecksumOwnerId(List objects) { - return putAllByIndex(r'checksum_ownerId', objects); + Future> putAllByOwnerIdChecksum(List objects) { + return putAllByIndex(r'ownerId_checksum', objects); } - List putAllByChecksumOwnerIdSync(List objects, + List putAllByOwnerIdChecksumSync(List objects, {bool saveLinks = true}) { - return putAllByIndexSync(r'checksum_ownerId', objects, + return putAllByIndexSync(r'ownerId_checksum', objects, saveLinks: saveLinks); } } @@ -463,145 +463,6 @@ extension AssetQueryWhere on QueryBuilder { }); } - QueryBuilder checksumEqualToAnyOwnerId( - String checksum) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'checksum_ownerId', - value: [checksum], - )); - }); - } - - QueryBuilder checksumNotEqualToAnyOwnerId( - String checksum) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [], - upper: [checksum], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum], - includeLower: false, - upper: [], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum], - includeLower: false, - upper: [], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [], - upper: [checksum], - includeUpper: false, - )); - } - }); - } - - QueryBuilder checksumOwnerIdEqualTo( - String checksum, int ownerId) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.equalTo( - indexName: r'checksum_ownerId', - value: [checksum, ownerId], - )); - }); - } - - QueryBuilder - checksumEqualToOwnerIdNotEqualTo(String checksum, int ownerId) { - return QueryBuilder.apply(this, (query) { - if (query.whereSort == Sort.asc) { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum], - upper: [checksum, ownerId], - includeUpper: false, - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum, ownerId], - includeLower: false, - upper: [checksum], - )); - } else { - return query - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum, ownerId], - includeLower: false, - upper: [checksum], - )) - .addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum], - upper: [checksum, ownerId], - includeUpper: false, - )); - } - }); - } - - QueryBuilder - checksumEqualToOwnerIdGreaterThan( - String checksum, - int ownerId, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum, ownerId], - includeLower: include, - upper: [checksum], - )); - }); - } - - QueryBuilder checksumEqualToOwnerIdLessThan( - String checksum, - int ownerId, { - bool include = false, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum], - upper: [checksum, ownerId], - includeUpper: include, - )); - }); - } - - QueryBuilder checksumEqualToOwnerIdBetween( - String checksum, - int lowerOwnerId, - int upperOwnerId, { - bool includeLower = true, - bool includeUpper = true, - }) { - return QueryBuilder.apply(this, (query) { - return query.addWhereClause(IndexWhereClause.between( - indexName: r'checksum_ownerId', - lower: [checksum, lowerOwnerId], - includeLower: includeLower, - upper: [checksum, upperOwnerId], - includeUpper: includeUpper, - )); - }); - } - QueryBuilder remoteIdIsNull() { return QueryBuilder.apply(this, (query) { return query.addWhereClause(IndexWhereClause.equalTo( @@ -731,6 +592,141 @@ extension AssetQueryWhere on QueryBuilder { } }); } + + QueryBuilder ownerIdEqualToAnyChecksum( + int ownerId) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'ownerId_checksum', + value: [ownerId], + )); + }); + } + + QueryBuilder ownerIdNotEqualToAnyChecksum( + int ownerId) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [], + upper: [ownerId], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId], + includeLower: false, + upper: [], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId], + includeLower: false, + upper: [], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [], + upper: [ownerId], + includeUpper: false, + )); + } + }); + } + + QueryBuilder ownerIdGreaterThanAnyChecksum( + int ownerId, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId], + includeLower: include, + upper: [], + )); + }); + } + + QueryBuilder ownerIdLessThanAnyChecksum( + int ownerId, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [], + upper: [ownerId], + includeUpper: include, + )); + }); + } + + QueryBuilder ownerIdBetweenAnyChecksum( + int lowerOwnerId, + int upperOwnerId, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [lowerOwnerId], + includeLower: includeLower, + upper: [upperOwnerId], + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder ownerIdChecksumEqualTo( + int ownerId, String checksum) { + return QueryBuilder.apply(this, (query) { + return query.addWhereClause(IndexWhereClause.equalTo( + indexName: r'ownerId_checksum', + value: [ownerId, checksum], + )); + }); + } + + QueryBuilder + ownerIdEqualToChecksumNotEqualTo(int ownerId, String checksum) { + return QueryBuilder.apply(this, (query) { + if (query.whereSort == Sort.asc) { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId], + upper: [ownerId, checksum], + includeUpper: false, + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId, checksum], + includeLower: false, + upper: [ownerId], + )); + } else { + return query + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId, checksum], + includeLower: false, + upper: [ownerId], + )) + .addWhereClause(IndexWhereClause.between( + indexName: r'ownerId_checksum', + lower: [ownerId], + upper: [ownerId, checksum], + includeUpper: false, + )); + } + }); + } } extension AssetQueryFilter on QueryBuilder { diff --git a/mobile/lib/shared/providers/asset.provider.dart b/mobile/lib/shared/providers/asset.provider.dart index 27e70298ab..a4ded2b532 100644 --- a/mobile/lib/shared/providers/asset.provider.dart +++ b/mobile/lib/shared/providers/asset.provider.dart @@ -186,8 +186,9 @@ final assetsProvider = final query = ref .watch(dbProvider) .assets + .where() + .ownerIdEqualToAnyChecksum(userId) .filter() - .ownerIdEqualTo(userId) .isArchivedEqualTo(false) .sortByFileCreatedAtDesc(); final settings = ref.watch(appSettingsServiceProvider); diff --git a/mobile/lib/shared/services/sync.service.dart b/mobile/lib/shared/services/sync.service.dart index 2580ed9521..a11bb8eefc 100644 --- a/mobile/lib/shared/services/sync.service.dart +++ b/mobile/lib/shared/services/sync.service.dart @@ -123,7 +123,7 @@ class SyncService { /// Syncs a new asset to the db. Returns `true` if successful Future _syncNewAssetToDb(Asset a) async { final Asset? inDb = - await _db.assets.getByChecksumOwnerId(a.checksum, a.ownerId); + await _db.assets.getByOwnerIdChecksum(a.ownerId, a.checksum); if (inDb != null) { // unify local/remote assets by replacing the // local-only asset in the DB with a local&remote asset @@ -195,8 +195,8 @@ class SyncService { return false; } final List inDb = await _db.assets - .filter() - .ownerIdEqualTo(user.isarId) + .where() + .ownerIdEqualToAnyChecksum(user.isarId) .sortByChecksum() .findAll(); assert(inDb.isSorted(Asset.compareByChecksum), "inDb not sorted!"); @@ -638,9 +638,9 @@ class SyncService { ) async { if (assets.isEmpty) return ([].cast(), [].cast()); - final List inDb = await _db.assets.getAllByChecksumOwnerId( - assets.map((a) => a.checksum).toList(growable: false), + final List inDb = await _db.assets.getAllByOwnerIdChecksum( assets.map((a) => a.ownerId).toInt64List(), + assets.map((a) => a.checksum).toList(growable: false), ); assert(inDb.length == assets.length); final List existing = [], toUpsert = []; @@ -683,9 +683,9 @@ class SyncService { ); // give details on the errors assets.sort(Asset.compareByOwnerChecksum); - final inDb = await _db.assets.getAllByChecksumOwnerId( - assets.map((e) => e.checksum).toList(growable: false), + final inDb = await _db.assets.getAllByOwnerIdChecksum( assets.map((e) => e.ownerId).toInt64List(), + assets.map((e) => e.checksum).toList(growable: false), ); for (int i = 0; i < assets.length; i++) { final Asset a = assets[i];