import 'dart:io'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/android_device_asset.entity.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/device_asset.entity.dart'; import 'package:immich_mobile/entities/ios_device_asset.entity.dart'; import 'package:immich_mobile/entities/user.entity.dart'; import 'package:immich_mobile/interfaces/asset.interface.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:isar/isar.dart'; final assetRepositoryProvider = Provider((ref) => AssetRepository(ref.watch(dbProvider))); class AssetRepository implements IAssetRepository { final Isar _db; AssetRepository( this._db, ); @override Future> getByAlbum(Album album, {User? notOwnedBy}) { var query = album.assets.filter(); if (notOwnedBy != null) { query = query.not().ownerIdEqualTo(notOwnedBy.isarId); } return query.findAll(); } @override Future deleteById(List ids) => _db.writeTxn(() => _db.assets.deleteAll(ids)); @override Future getByRemoteId(String id) => _db.assets.getByRemoteId(id); @override Future> getAllByRemoteId(Iterable ids) => _db.assets.getAllByRemoteId(ids); @override Future> getAll({ required int ownerId, bool? remote, int limit = 100, }) { if (remote == null) { return _db.assets .where() .ownerIdEqualToAnyChecksum(ownerId) .limit(limit) .findAll(); } final QueryBuilder query; if (remote) { query = _db.assets .where() .localIdIsNull() .filter() .remoteIdIsNotNull() .ownerIdEqualTo(ownerId); } else { query = _db.assets .where() .remoteIdIsNull() .filter() .localIdIsNotNull() .ownerIdEqualTo(ownerId); } return query.limit(limit).findAll(); } @override Future> updateAll(List assets) async { await _db.writeTxn(() => _db.assets.putAll(assets)); return assets; } @override Future> getMatches({ required List assets, required int ownerId, bool? remote, int limit = 100, }) { final QueryBuilder query; if (remote == null) { query = _db.assets.filter().remoteIdIsNotNull().or().localIdIsNotNull(); } else if (remote) { query = _db.assets.where().localIdIsNull().filter().remoteIdIsNotNull(); } else { query = _db.assets.where().remoteIdIsNull().filter().localIdIsNotNull(); } return _getMatchesImpl(query, ownerId, assets, limit); } @override Future> getDeviceAssetsById(List ids) => Platform.isAndroid ? _db.androidDeviceAssets.getAll(ids.cast()) : _db.iOSDeviceAssets.getAllById(ids.cast()); @override Future upsertDeviceAssets(List deviceAssets) => _db.writeTxn( () => Platform.isAndroid ? _db.androidDeviceAssets.putAll(deviceAssets.cast()) : _db.iOSDeviceAssets.putAll(deviceAssets.cast()), ); } Future> _getMatchesImpl( QueryBuilder query, int ownerId, List assets, int limit, ) => query .ownerIdEqualTo(ownerId) .anyOf( assets, (q, Asset a) => q .fileNameEqualTo(a.fileName) .and() .durationInSecondsEqualTo(a.durationInSeconds) .and() .fileCreatedAtBetween( a.fileCreatedAt.subtract(const Duration(hours: 12)), a.fileCreatedAt.add(const Duration(hours: 12)), ) .and() .not() .checksumEqualTo(a.checksum), ) .sortByFileName() .thenByFileCreatedAt() .thenByFileModifiedAt() .limit(limit) .findAll();