From bc09be718ac38ba3053fa5f9677262cae3368799 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Mon, 10 Aug 2026 12:24:17 -0700 Subject: [PATCH] chore(mobile): use Drift @DriftAccessor() and collapse some providers --- mobile/build.yaml | 3 +- mobile/lib/domain/services/asset.service.dart | 12 ++-- .../services/background_worker.service.dart | 23 ++++---- mobile/lib/domain/services/hash.service.dart | 6 +- .../domain/services/local_album.service.dart | 2 +- .../domain/services/local_sync.service.dart | 8 +-- mobile/lib/domain/services/map.service.dart | 2 +- .../lib/domain/services/memory.service.dart | 2 +- .../lib/domain/services/partner.service.dart | 4 +- .../lib/domain/services/people.service.dart | 2 +- .../domain/services/remote_album.service.dart | 4 +- mobile/lib/domain/services/store.service.dart | 10 ++-- .../services/sync_linked_album.service.dart | 19 ++++--- .../domain/services/sync_stream.service.dart | 4 +- .../lib/domain/services/timeline.service.dart | 2 +- .../lib/domain/utils/migrate_cloud_ids.dart | 2 +- .../repositories/backup.repository.dart | 13 ++--- .../repositories/db.repository.dart | 48 +++++++++++++--- .../repositories/local_album.repository.dart | 10 ++-- .../repositories/local_asset.repository.dart | 11 ++-- .../repositories/map.repository.dart | 9 ++- .../repositories/memory.repository.dart | 9 ++- .../repositories/ocr.repository.dart | 9 ++- .../repositories/partner.repository.dart | 13 +++-- .../repositories/people.repository.dart | 9 ++- .../repositories/remote_album.repository.dart | 11 ++-- .../repositories/remote_asset.repository.dart | 13 +++-- .../repositories/remote_exif.repository.dart | 11 ++-- .../repositories/stack.repository.dart | 9 ++- .../repositories/store.repository.dart | 15 +++-- .../sync_migration.repository.dart | 10 +++- .../repositories/sync_stream.repository.dart | 11 ++-- .../repositories/timeline.repository.dart | 9 ++- .../trashed_local_asset.repository.dart | 9 ++- .../repositories/user.repository.dart | 17 ++++-- .../user_metadata.repository.dart | 8 ++- .../backup/drift_upload_detail.page.dart | 6 +- .../actions/edit_asset.action.dart | 3 +- .../actions/edit_datetime.action.dart | 3 +- .../actions/edit_location.action.dart | 3 +- .../pages/dev/media_stat.page.dart | 5 +- .../backup/backup_album.provider.dart | 4 +- .../backup/drift_backup.provider.dart | 7 ++- .../infrastructure/album.provider.dart | 20 +------ .../infrastructure/asset.provider.dart | 35 +++--------- .../infrastructure/map.provider.dart | 8 +-- .../infrastructure/memory.provider.dart | 11 +--- .../infrastructure/ocr.provider.dart | 7 +-- .../infrastructure/people.provider.dart | 7 +-- .../infrastructure/stack.provider.dart | 5 -- .../infrastructure/sync.provider.dart | 55 +++++++++---------- .../infrastructure/timeline.provider.dart | 9 +-- .../infrastructure/trash_sync.provider.dart | 4 +- .../infrastructure/user.provider.dart | 17 ++---- .../user_metadata.provider.dart | 7 +-- mobile/lib/services/action.service.dart | 4 +- .../services/background_upload.service.dart | 11 ++-- mobile/lib/services/cleanup.service.dart | 8 +-- mobile/lib/services/deep_link.service.dart | 4 +- .../services/foreground_upload.service.dart | 5 +- .../view_intent_asset_resolver.service.dart | 6 +- mobile/lib/utils/bootstrap.dart | 2 +- .../sync_status_and_actions.dart | 8 ++- .../services/local_sync_service_test.dart | 8 +-- .../domain/services/store_service_test.dart | 8 +-- .../sync_linked_album_service_test.dart | 9 ++- .../services/sync_stream_service_test.dart | 6 +- .../local_album_repository_test.dart | 6 +- .../repositories/store_repository_test.dart | 6 +- .../sync_api_repository_test.dart | 2 +- .../test/infrastructure/repository.mock.dart | 20 ++++--- .../repositories/backup_repository_test.dart | 4 +- .../local_asset_repository_test.dart | 4 +- .../repositories/memory_repository_test.dart | 4 +- .../repositories/partner_repository_test.dart | 4 +- .../repositories/people_repository_test.dart | 4 +- .../remote_album_repository_test.dart | 4 +- .../timeline_repository_test.dart | 4 +- .../trashed_local_asset_repository_test.dart | 4 +- .../modules/map/map_theme_override_test.dart | 2 +- .../infrastructure/memory_provider_test.dart | 32 +++++++---- mobile/test/services/action.service_test.dart | 2 +- mobile/test/services/auth.service_test.dart | 2 +- .../background_upload.service_test.dart | 10 ++-- .../test/services/cleanup.service_test.dart | 14 ++--- .../foreground_upload.service_test.dart | 6 +- .../view_intent_asset_resolver_test.dart | 11 ++-- mobile/test/test_utils/medium_factory.dart | 4 +- mobile/test/unit/mocks.dart | 10 ++-- .../presentation/presentation_context.dart | 12 +++- .../unit/services/asset_service_test.dart | 14 ++--- mobile/test/utils/image_url_builder_test.dart | 2 +- 92 files changed, 439 insertions(+), 402 deletions(-) delete mode 100644 mobile/lib/providers/infrastructure/stack.provider.dart diff --git a/mobile/build.yaml b/mobile/build.yaml index cb718d9d3e..32cd96c5d3 100644 --- a/mobile/build.yaml +++ b/mobile/build.yaml @@ -18,8 +18,7 @@ targets: generate_for: &drift_generate_for - lib/infrastructure/entities/*.dart - lib/infrastructure/entities/*.drift - - lib/infrastructure/repositories/db.repository.dart - - lib/infrastructure/repositories/logger_db.repository.dart + - lib/infrastructure/repositories/*.repository.dart drift_dev:modular: enabled: true options: *drift_options diff --git a/mobile/lib/domain/services/asset.service.dart b/mobile/lib/domain/services/asset.service.dart index 59f41f1e51..0032403348 100644 --- a/mobile/lib/domain/services/asset.service.dart +++ b/mobile/lib/domain/services/asset.service.dart @@ -17,10 +17,10 @@ import 'package:maplibre_gl/maplibre_gl.dart'; class AssetService { final RemoteAssetRepository _remoteRepository; final RemoteExifRepository _exifRepository; - final DriftLocalAssetRepository _localRepository; + final LocalAssetRepository _localRepository; final AssetApiRepository _apiRepository; final AssetMediaRepository _mediaRepository; - final DriftTrashedLocalAssetRepository _trashedLocalRepository; + final TrashedLocalAssetRepository _trashedLocalRepository; const AssetService({ required this._remoteRepository, @@ -136,13 +136,13 @@ class AssetService { location: location, dateTimeOriginal: dateTime, ); - await _remoteRepository.update( + await _remoteRepository.updateAssets( remoteIds, isFavorite: isFavorite, visibility: visibility, createdAt: parsedDateTime, ); - await _exifRepository.update( + await _exifRepository.updateExif( remoteIds, location: location, dateTimeOriginal: parsedDateTime, @@ -165,7 +165,7 @@ class AssetService { } await _apiRepository.delete(remoteIds, true); - await _remoteRepository.delete(remoteIds); + await _remoteRepository.deleteAssets(remoteIds); } Future applyEdits(String remoteId, List edits) async { @@ -189,7 +189,7 @@ class AssetService { if (CurrentPlatform.isAndroid && Store.get(StoreKey.manageLocalMediaAndroid, false)) { await _trashedLocalRepository.applyTrashedAssets(deletedIds); } else { - await _localRepository.delete(deletedIds); + await _localRepository.deleteAssets(deletedIds); } return deletedIds.length; } diff --git a/mobile/lib/domain/services/background_worker.service.dart b/mobile/lib/domain/services/background_worker.service.dart index 8161df5c51..817cc33380 100644 --- a/mobile/lib/domain/services/background_worker.service.dart +++ b/mobile/lib/domain/services/background_worker.service.dart @@ -19,8 +19,6 @@ import 'package:immich_mobile/platform/background_worker_api.g.dart'; import 'package:immich_mobile/platform/background_worker_lock_api.g.dart'; import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/sync.provider.dart'; @@ -76,31 +74,32 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { : _backgroundHostApi = BackgroundWorkerBgHostApi() { final ref = ProviderContainer(overrides: [driftProvider.overrideWith(driftOverride(_drift))]); _ref = ref; + final db = ref.read(driftProvider); _localSyncService = LocalSyncService( - localAlbumRepository: ref.read(localAlbumRepository), - localAssetRepository: ref.read(localAssetRepository), + localAlbumRepository: db.localAlbumRepository, + localAssetRepository: db.localAssetRepository, nativeSyncApi: ref.read(nativeSyncApiProvider), - trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository), + trashedLocalAssetRepository: db.trashedLocalAssetRepository, assetMediaRepository: ref.read(assetMediaRepositoryProvider), permissionRepository: ref.read(permissionRepositoryProvider), cancellation: _cancellationToken, ); _remoteSyncService = SyncStreamService( syncApiRepository: ref.read(syncApiRepositoryProvider), - syncStreamRepository: ref.read(syncStreamRepositoryProvider), - localAssetRepository: ref.read(localAssetRepository), - trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository), + syncStreamRepository: db.syncStreamRepository, + localAssetRepository: db.localAssetRepository, + trashedLocalAssetRepository: db.trashedLocalAssetRepository, assetMediaRepository: ref.read(assetMediaRepositoryProvider), permissionRepository: ref.read(permissionRepositoryProvider), - syncMigrationRepository: ref.read(syncMigrationRepositoryProvider), + syncMigrationRepository: db.syncMigrationRepository, api: ref.read(apiServiceProvider), cancellation: _cancellationToken, ); _hashService = HashService( - localAlbumRepository: ref.read(localAlbumRepository), - localAssetRepository: ref.read(localAssetRepository), + localAlbumRepository: db.localAlbumRepository, + localAssetRepository: db.localAssetRepository, nativeSyncApi: ref.read(nativeSyncApiProvider), - trashedLocalAssetRepository: ref.read(trashedLocalAssetRepository), + trashedLocalAssetRepository: db.trashedLocalAssetRepository, cancellation: _cancellationToken, ); BackgroundWorkerFlutterApi.setUp(this); diff --git a/mobile/lib/domain/services/hash.service.dart b/mobile/lib/domain/services/hash.service.dart index 8a573ee209..64595aff2b 100644 --- a/mobile/lib/domain/services/hash.service.dart +++ b/mobile/lib/domain/services/hash.service.dart @@ -15,9 +15,9 @@ const String _kHashCancelledCode = "HASH_CANCELLED"; class HashService { final int _batchSize; - final DriftLocalAlbumRepository _localAlbumRepository; - final DriftLocalAssetRepository _localAssetRepository; - final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository; + final LocalAlbumRepository _localAlbumRepository; + final LocalAssetRepository _localAssetRepository; + final TrashedLocalAssetRepository _trashedLocalAssetRepository; final NativeSyncApi _nativeSyncApi; final Completer? _cancellation; final _log = Logger('HashService'); diff --git a/mobile/lib/domain/services/local_album.service.dart b/mobile/lib/domain/services/local_album.service.dart index e3d888f063..8661a8d10a 100644 --- a/mobile/lib/domain/services/local_album.service.dart +++ b/mobile/lib/domain/services/local_album.service.dart @@ -3,7 +3,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; class LocalAlbumService { - final DriftLocalAlbumRepository _repository; + final LocalAlbumRepository _repository; const LocalAlbumService(this._repository); diff --git a/mobile/lib/domain/services/local_sync.service.dart b/mobile/lib/domain/services/local_sync.service.dart index 9e272ac65f..0793d191b0 100644 --- a/mobile/lib/domain/services/local_sync.service.dart +++ b/mobile/lib/domain/services/local_sync.service.dart @@ -21,11 +21,11 @@ import 'package:logging/logging.dart'; const String _kSyncCancelledCode = "SYNC_CANCELLED"; class LocalSyncService { - final DriftLocalAlbumRepository _localAlbumRepository; + final LocalAlbumRepository _localAlbumRepository; // ignore: unused_field - final DriftLocalAssetRepository _localAssetRepository; + final LocalAssetRepository _localAssetRepository; final NativeSyncApi _nativeSyncApi; - final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository; + final TrashedLocalAssetRepository _trashedLocalAssetRepository; final AssetMediaRepository _assetMediaRepository; final DevicePermissionRepository _permissionRepository; final Completer? _cancellation; @@ -186,7 +186,7 @@ class LocalSyncService { _log.fine("Removing device album ${a.name}"); try { // Asset deletion is handled in the repository - await _localAlbumRepository.delete(a.id); + await _localAlbumRepository.deleteAlbum(a.id); } catch (e, s) { _log.warning("Error while removing device album", e, s); } diff --git a/mobile/lib/domain/services/map.service.dart b/mobile/lib/domain/services/map.service.dart index 6c484d1a14..5e0a3bd857 100644 --- a/mobile/lib/domain/services/map.service.dart +++ b/mobile/lib/domain/services/map.service.dart @@ -8,7 +8,7 @@ typedef MapMarkerSource = Future> Function(LatLngBounds? bounds); typedef MapQuery = ({MapMarkerSource markerSource}); class MapFactory { - final DriftMapRepository _mapRepository; + final MapRepository _mapRepository; const MapFactory({required this._mapRepository}); diff --git a/mobile/lib/domain/services/memory.service.dart b/mobile/lib/domain/services/memory.service.dart index ead613370f..ccb865fb64 100644 --- a/mobile/lib/domain/services/memory.service.dart +++ b/mobile/lib/domain/services/memory.service.dart @@ -5,7 +5,7 @@ import 'package:logging/logging.dart'; class DriftMemoryService { final log = Logger("DriftMemoryService"); - final DriftMemoryRepository _repository; + final MemoryRepository _repository; DriftMemoryService(this._repository); diff --git a/mobile/lib/domain/services/partner.service.dart b/mobile/lib/domain/services/partner.service.dart index 63985823aa..3fd0d32683 100644 --- a/mobile/lib/domain/services/partner.service.dart +++ b/mobile/lib/domain/services/partner.service.dart @@ -27,7 +27,7 @@ class PartnerService { Future update({required String sharedById, required String sharedWithId, required bool inTimeline}) async { await _partnerApiRepository.update(sharedById, inTimeline: inTimeline); - await _partnerRepository.update(sharedById: sharedById, sharedWithId: sharedWithId, inTimeline: inTimeline); + await _partnerRepository.updatePartner(sharedById: sharedById, sharedWithId: sharedWithId, inTimeline: inTimeline); } Future create({required String sharedById, required String sharedWithId, bool inTimeline = false}) async { @@ -37,6 +37,6 @@ class PartnerService { Future delete({required String sharedById, required String sharedWithId}) async { await _partnerApiRepository.delete(sharedWithId); - await _partnerRepository.delete(sharedById: sharedById, sharedWithId: sharedWithId); + await _partnerRepository.deletePartner(sharedById: sharedById, sharedWithId: sharedWithId); } } diff --git a/mobile/lib/domain/services/people.service.dart b/mobile/lib/domain/services/people.service.dart index 73972dbdc0..1bff6f6a30 100644 --- a/mobile/lib/domain/services/people.service.dart +++ b/mobile/lib/domain/services/people.service.dart @@ -5,7 +5,7 @@ import 'package:immich_mobile/infrastructure/repositories/people.repository.dart import 'package:immich_mobile/repositories/person_api.repository.dart'; class DriftPeopleService { - final DriftPeopleRepository _repository; + final PeopleRepository _repository; final PersonApiRepository _personApiRepository; const DriftPeopleService(this._repository, this._personApiRepository); diff --git a/mobile/lib/domain/services/remote_album.service.dart b/mobile/lib/domain/services/remote_album.service.dart index e59d75b01a..8e6a6c8aae 100644 --- a/mobile/lib/domain/services/remote_album.service.dart +++ b/mobile/lib/domain/services/remote_album.service.dart @@ -25,7 +25,7 @@ class AlbumAssetCandidates { class RemoteAlbumService { static final _logger = Logger('RemoteAlbumService'); - final DriftRemoteAlbumRepository _repository; + final RemoteAlbumRepository _repository; final DriftAlbumApiRepository _albumApiRepository; final ForegroundUploadService _uploadService; @@ -152,7 +152,7 @@ class RemoteAlbumService { ); // Update the local database - await _repository.update(updatedAlbum); + await _repository.updateAlbum(updatedAlbum); return updatedAlbum; } diff --git a/mobile/lib/domain/services/store.service.dart b/mobile/lib/domain/services/store.service.dart index 758622a43b..ea830dc322 100644 --- a/mobile/lib/domain/services/store.service.dart +++ b/mobile/lib/domain/services/store.service.dart @@ -6,13 +6,13 @@ import 'package:immich_mobile/infrastructure/repositories/store.repository.dart' /// Provides access to a persistent key-value store with an in-memory cache. /// Listens for repository changes to keep the cache updated. class StoreService { - final DriftStoreRepository _storeRepository; + final StoreRepository _storeRepository; /// In-memory cache. Keys are [StoreKey.id] final Map _cache = {}; StreamSubscription>? _storeUpdateSubscription; - StoreService._({required DriftStoreRepository isarStoreRepository}) : _storeRepository = isarStoreRepository; + StoreService._({required StoreRepository isarStoreRepository}) : _storeRepository = isarStoreRepository; // TODO: Temporary typedef to make minimal changes. Remove this and make the presentation layer access store through a provider static StoreService? _instance; @@ -24,12 +24,12 @@ class StoreService { } // TODO: Replace the implementation with the one from create after removing the typedef - static Future init({required DriftStoreRepository storeRepository, bool listenUpdates = true}) async { + static Future init({required StoreRepository storeRepository, bool listenUpdates = true}) async { _instance ??= await create(storeRepository: storeRepository, listenUpdates: listenUpdates); return _instance!; } - static Future create({required DriftStoreRepository storeRepository, bool listenUpdates = true}) async { + static Future create({required StoreRepository storeRepository, bool listenUpdates = true}) async { final instance = StoreService._(isarStoreRepository: storeRepository); await instance.populateCache(); if (listenUpdates) { @@ -90,7 +90,7 @@ class StoreService { /// Removes the value for [key] Future delete(StoreKey key) async { - await _storeRepository.delete(key); + await _storeRepository.deleteValue(key); _cache.remove(key.id); } diff --git a/mobile/lib/domain/services/sync_linked_album.service.dart b/mobile/lib/domain/services/sync_linked_album.service.dart index 091ca222f0..80a1fbaf9e 100644 --- a/mobile/lib/domain/services/sync_linked_album.service.dart +++ b/mobile/lib/domain/services/sync_linked_album.service.dart @@ -6,24 +6,25 @@ import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/store.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/store.provider.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; import 'package:immich_mobile/utils/debug_print.dart'; import 'package:logging/logging.dart'; -final syncLinkedAlbumServiceProvider = Provider( - (ref) => SyncLinkedAlbumService( - ref.watch(localAlbumRepository), - ref.watch(remoteAlbumRepository), +final syncLinkedAlbumServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return SyncLinkedAlbumService( + db.localAlbumRepository, + db.remoteAlbumRepository, ref.watch(driftAlbumApiRepositoryProvider), ref.watch(storeServiceProvider), - ), -); + ); +}); class SyncLinkedAlbumService { - final DriftLocalAlbumRepository _localAlbumRepository; - final DriftRemoteAlbumRepository _remoteAlbumRepository; + final LocalAlbumRepository _localAlbumRepository; + final RemoteAlbumRepository _remoteAlbumRepository; final DriftAlbumApiRepository _albumApiRepository; final StoreService _storeService; diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index 0eb3ff2f99..52dcfff05f 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -33,8 +33,8 @@ class SyncStreamService { final SyncApiRepository _syncApiRepository; final SyncStreamRepository _syncStreamRepository; - final DriftLocalAssetRepository _localAssetRepository; - final DriftTrashedLocalAssetRepository _trashedLocalAssetRepository; + final LocalAssetRepository _localAssetRepository; + final TrashedLocalAssetRepository _trashedLocalAssetRepository; final AssetMediaRepository _assetMediaRepository; final DevicePermissionRepository _permissionRepository; final SyncMigrationRepository _syncMigrationRepository; diff --git a/mobile/lib/domain/services/timeline.service.dart b/mobile/lib/domain/services/timeline.service.dart index b20ba306ff..84895b6056 100644 --- a/mobile/lib/domain/services/timeline.service.dart +++ b/mobile/lib/domain/services/timeline.service.dart @@ -38,7 +38,7 @@ enum TimelineOrigin { } class TimelineFactory { - final DriftTimelineRepository _timelineRepository; + final TimelineRepository _timelineRepository; final SettingsRepository _settingsRepository; const TimelineFactory({required this._timelineRepository, required this._settingsRepository}); diff --git a/mobile/lib/domain/utils/migrate_cloud_ids.dart b/mobile/lib/domain/utils/migrate_cloud_ids.dart index efef6e8327..06a52312f7 100644 --- a/mobile/lib/domain/utils/migrate_cloud_ids.dart +++ b/mobile/lib/domain/utils/migrate_cloud_ids.dart @@ -171,7 +171,7 @@ Future _populateCloudIds(Drift drift) async { ); } } - await DriftLocalAlbumRepository(drift).updateCloudMapping(cloudMapping); + await LocalAlbumRepository(drift).updateCloudMapping(cloudMapping); } typedef _CloudIdMapping = ({String remoteAssetId, LocalAsset localAsset}); diff --git a/mobile/lib/infrastructure/repositories/backup.repository.dart b/mobile/lib/infrastructure/repositories/backup.repository.dart index eb3cba95d0..c4c07118d6 100644 --- a/mobile/lib/infrastructure/repositories/backup.repository.dart +++ b/mobile/lib/infrastructure/repositories/backup.repository.dart @@ -1,21 +1,18 @@ import 'dart:async'; import 'package:drift/drift.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; +import 'package:immich_mobile/infrastructure/repositories/backup.repository.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; -final backupRepositoryProvider = Provider( - (ref) => DriftBackupRepository(ref.watch(driftProvider)), -); +@DriftAccessor() +class BackupRepository extends DatabaseAccessor with $BackupRepositoryMixin { + BackupRepository(super.attachedDatabase); -class DriftBackupRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftBackupRepository(this._db) : super(_db); + Drift get _db => attachedDatabase; JoinedSelectStatement<$LocalAlbumAssetEntityTable, LocalAlbumAssetEntityData> _getExcludedSubquery() { return _db.localAlbumAssetEntity.selectOnly() diff --git a/mobile/lib/infrastructure/repositories/db.repository.dart b/mobile/lib/infrastructure/repositories/db.repository.dart index 69e45685de..195f1455d2 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.dart @@ -32,8 +32,27 @@ import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'; +import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.steps.dart'; +import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/map.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/ocr.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/partner.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/people.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_exif.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/stack.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_migration.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/user.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; @@ -69,6 +88,28 @@ import 'package:sqlite_async/sqlite_async.dart'; AssetOcrEntity, ], include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'}, + daos: [ + AuthUserRepository, + BackupRepository, + LocalAlbumRepository, + LocalAssetRepository, + MapRepository, + MemoryRepository, + OcrRepository, + PartnerRepository, + PeopleRepository, + RemoteAlbumRepository, + RemoteAssetRepository, + RemoteExifRepository, + StackRepository, + StoreRepository, + SyncMigrationRepository, + SyncStreamRepository, + TimelineRepository, + TrashedLocalAssetRepository, + UserMetadataRepository, + UserRepository, + ], ) class Drift extends $Drift { final SqliteConnectionPool? _updatePool; @@ -344,13 +385,6 @@ class Drift extends $Drift { ); } -class DriftDatabaseRepository { - final Drift _db; - const DriftDatabaseRepository(this._db); - - Future transaction(Future Function() callback) => _db.transaction(callback); -} - // ignore: invalid_use_of_internal_member final class _DriftPoolStreamQueries extends StreamQueryStore { _DriftPoolStreamQueries(this._pool); diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index a9911fe044..780b4f5ef9 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -10,13 +10,15 @@ import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.d import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/local_album.repository.drift.dart'; enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum, name, assetCount, newestAsset } -class DriftLocalAlbumRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class LocalAlbumRepository extends DatabaseAccessor with $LocalAlbumRepositoryMixin { + LocalAlbumRepository(super.attachedDatabase); - const DriftLocalAlbumRepository(this._db) : super(_db); + Drift get _db => attachedDatabase; Future> getAll({Set sortBy = const {}}) { final assetCount = _db.localAlbumAssetEntity.assetId.count(); @@ -57,7 +59,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { return query.map((row) => row.toDto()).get(); } - Future delete(String albumId) => transaction(() async { + Future deleteAlbum(String albumId) => transaction(() async { // Remove all assets that are only in this particular album // We cannot remove all assets in the album because they might be in other albums in iOS // That is not the case on Android since asset <-> album has one:one mapping diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index 8396d6d2a6..2fdbae690c 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -10,6 +10,7 @@ import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.drift.dart'; class RemovalCandidatesResult { final List assets; @@ -18,10 +19,12 @@ class RemovalCandidatesResult { const RemovalCandidatesResult({required this.assets, required this.totalBytes}); } -class DriftLocalAssetRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class LocalAssetRepository extends DatabaseAccessor with $LocalAssetRepositoryMixin { - const DriftLocalAssetRepository(this._db) : super(_db); + LocalAssetRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; SingleOrNullSelectable _assetSelectable(String id) { final query = @@ -72,7 +75,7 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { }); } - Future delete(List ids) { + Future deleteAssets(List ids) { if (ids.isEmpty) { return Future.value(); } diff --git a/mobile/lib/infrastructure/repositories/map.repository.dart b/mobile/lib/infrastructure/repositories/map.repository.dart index 267ea08d20..1c281ca0a4 100644 --- a/mobile/lib/infrastructure/repositories/map.repository.dart +++ b/mobile/lib/infrastructure/repositories/map.repository.dart @@ -5,13 +5,16 @@ import 'package:immich_mobile/domain/services/map.service.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/map.repository.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; -class DriftMapRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class MapRepository extends DatabaseAccessor with $MapRepositoryMixin { - const DriftMapRepository(super._db) : _db = _db; + MapRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; MapQuery remote(List ownerIds, TimelineMapOptions options) => _mapQueryBuilder( assetFilter: (row) { diff --git a/mobile/lib/infrastructure/repositories/memory.repository.dart b/mobile/lib/infrastructure/repositories/memory.repository.dart index 37cccbf2d4..11bb99ba7b 100644 --- a/mobile/lib/infrastructure/repositories/memory.repository.dart +++ b/mobile/lib/infrastructure/repositories/memory.repository.dart @@ -4,10 +4,13 @@ import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.drift.dart'; -class DriftMemoryRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftMemoryRepository(this._db) : super(_db); +@DriftAccessor() +class MemoryRepository extends DatabaseAccessor with $MemoryRepositoryMixin { + MemoryRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future> getAll(String ownerId) async { final now = DateTime.now(); diff --git a/mobile/lib/infrastructure/repositories/ocr.repository.dart b/mobile/lib/infrastructure/repositories/ocr.repository.dart index c3465df357..f374937b4a 100644 --- a/mobile/lib/infrastructure/repositories/ocr.repository.dart +++ b/mobile/lib/infrastructure/repositories/ocr.repository.dart @@ -2,10 +2,13 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/ocr.model.dart'; import 'package:immich_mobile/infrastructure/entities/asset_ocr.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/ocr.repository.drift.dart'; -class OcrRepository extends DriftDatabaseRepository { - final Drift _db; - const OcrRepository(this._db) : super(_db); +@DriftAccessor() +class OcrRepository extends DatabaseAccessor with $OcrRepositoryMixin { + OcrRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future> get(String assetId) async { final query = _db.select(_db.assetOcrEntity) diff --git a/mobile/lib/infrastructure/repositories/partner.repository.dart b/mobile/lib/infrastructure/repositories/partner.repository.dart index ee18c84b4e..fd38f12686 100644 --- a/mobile/lib/infrastructure/repositories/partner.repository.dart +++ b/mobile/lib/infrastructure/repositories/partner.repository.dart @@ -4,10 +4,13 @@ import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; import 'package:immich_mobile/infrastructure/mapper.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/partner.repository.drift.dart'; -class PartnerRepository { - final Drift _db; - const PartnerRepository(this._db); +@DriftAccessor() +class PartnerRepository extends DatabaseAccessor with $PartnerRepositoryMixin { + PartnerRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future get({required String sharedById, required String sharedWithId}) => (_db.select(_db.partnerEntity).join([ @@ -46,11 +49,11 @@ class PartnerRepository { ), ); - Future update({required String sharedById, required String sharedWithId, required bool inTimeline}) => + Future updatePartner({required String sharedById, required String sharedWithId, required bool inTimeline}) => (_db.partnerEntity.update()..where((t) => t.sharedById.equals(sharedById) & t.sharedWithId.equals(sharedWithId))) .write(PartnerEntityCompanion(inTimeline: Value(inTimeline))); - Future delete({required String sharedById, required String sharedWithId}) => + Future deletePartner({required String sharedById, required String sharedWithId}) => (_db.partnerEntity.delete()..where((t) => t.sharedById.equals(sharedById) & t.sharedWithId.equals(sharedWithId))) .go(); diff --git a/mobile/lib/infrastructure/repositories/people.repository.dart b/mobile/lib/infrastructure/repositories/people.repository.dart index 0dd73cc81d..39f3e048b5 100644 --- a/mobile/lib/infrastructure/repositories/people.repository.dart +++ b/mobile/lib/infrastructure/repositories/people.repository.dart @@ -3,10 +3,13 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/person.model.dart'; import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/people.repository.drift.dart'; -class DriftPeopleRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftPeopleRepository(this._db) : super(_db); +@DriftAccessor() +class PeopleRepository extends DatabaseAccessor with $PeopleRepositoryMixin { + PeopleRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future get(String personId) async { final query = _db.select(_db.personEntity)..where((row) => row.id.equals(personId)); diff --git a/mobile/lib/infrastructure/repositories/remote_album.repository.dart b/mobile/lib/infrastructure/repositories/remote_album.repository.dart index b9cd41c960..2f7106c270 100644 --- a/mobile/lib/infrastructure/repositories/remote_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_album.repository.dart @@ -12,12 +12,15 @@ import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.d import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.drift.dart'; enum SortRemoteAlbumsBy { id, updatedAt } -class DriftRemoteAlbumRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftRemoteAlbumRepository(this._db) : super(_db); +@DriftAccessor() +class RemoteAlbumRepository extends DatabaseAccessor with $RemoteAlbumRepositoryMixin { + RemoteAlbumRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future> getAll({Set sortBy = const {SortRemoteAlbumsBy.updatedAt}}) { // Count non-trashed assets via the joined asset table. Filtering trashed assets in the @@ -191,7 +194,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { }); } - Future update(RemoteAlbum album) async { + Future updateAlbum(RemoteAlbum album) async { await _db.remoteAlbumEntity.update().replace( RemoteAlbumEntityCompanion( id: Value(album.id), diff --git a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart index d18284b636..7550ff7ec7 100644 --- a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart @@ -10,13 +10,16 @@ import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.drift.dart'; import 'package:immich_mobile/utils/option.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; -class RemoteAssetRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class RemoteAssetRepository extends DatabaseAccessor with $RemoteAssetRepositoryMixin { - const RemoteAssetRepository(this._db) : super(_db); + RemoteAssetRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; /// For testing purposes Future> getSome(String userId) { @@ -163,7 +166,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository { ); } - Future delete(List ids) { + Future deleteAssets(List ids) { return _db.batch((batch) { for (final id in ids) { batch.deleteWhere(_db.remoteAssetEntity, (row) => row.id.equals(id)); @@ -244,7 +247,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository { return query.map((row) => row.toDto()!).get(); } - Future update( + Future updateAssets( List remoteIds, { Option isFavorite = const .none(), Option visibility = const .none(), diff --git a/mobile/lib/infrastructure/repositories/remote_exif.repository.dart b/mobile/lib/infrastructure/repositories/remote_exif.repository.dart index 568342b321..f3064104f2 100644 --- a/mobile/lib/infrastructure/repositories/remote_exif.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_exif.repository.dart @@ -1,14 +1,17 @@ +import 'package:drift/drift.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/remote_exif.repository.drift.dart'; import 'package:immich_mobile/utils/option.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; -class RemoteExifRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class RemoteExifRepository extends DatabaseAccessor with $RemoteExifRepositoryMixin { + RemoteExifRepository(super.attachedDatabase); - const RemoteExifRepository(this._db) : super(_db); + Drift get _db => attachedDatabase; - Future update( + Future updateExif( List ids, { Option dateTimeOriginal = const .none(), Option timeZone = const .none(), diff --git a/mobile/lib/infrastructure/repositories/stack.repository.dart b/mobile/lib/infrastructure/repositories/stack.repository.dart index 28f7496f97..eecf7b9147 100644 --- a/mobile/lib/infrastructure/repositories/stack.repository.dart +++ b/mobile/lib/infrastructure/repositories/stack.repository.dart @@ -2,10 +2,13 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/stack.model.dart'; import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/stack.repository.drift.dart'; -class DriftStackRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftStackRepository(this._db) : super(_db); +@DriftAccessor() +class StackRepository extends DatabaseAccessor with $StackRepositoryMixin { + StackRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future> getAll(String userId) { final query = _db.stackEntity.select()..where((e) => e.ownerId.equals(userId)); diff --git a/mobile/lib/infrastructure/repositories/store.repository.dart b/mobile/lib/infrastructure/repositories/store.repository.dart index 9680aa0425..62cf38c209 100644 --- a/mobile/lib/infrastructure/repositories/store.repository.dart +++ b/mobile/lib/infrastructure/repositories/store.repository.dart @@ -3,13 +3,16 @@ import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/store.repository.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/user.repository.dart'; -class DriftStoreRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class StoreRepository extends DatabaseAccessor with $StoreRepositoryMixin { final validStoreKeys = StoreKey.values.map((e) => e.id).toSet(); - DriftStoreRepository(super.db) : _db = db; + StoreRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future deleteAll() async { await _db.storeEntity.deleteAll(); @@ -27,7 +30,7 @@ class DriftStoreRepository extends DriftDatabaseRepository { return query.asyncMap((entity) => _toUpdateEvent(entity)).watch(); } - Future delete(StoreKey key) async { + Future deleteValue(StoreKey key) async { await _db.storeEntity.deleteWhere((entity) => entity.id.equals(key.id)); return; } @@ -64,7 +67,7 @@ class DriftStoreRepository extends DriftDatabaseRepository { const (bool) => entity.intValue == 1, const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!), const (UserDto) => - entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!), + entity.stringValue == null ? null : await AuthUserRepository(_db).get(entity.stringValue!), _ => null, } as T?; @@ -75,7 +78,7 @@ class DriftStoreRepository extends DriftDatabaseRepository { const (String) => (null, value as String), const (bool) => ((value as bool) ? 1 : 0, null), const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null), - const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id), + const (UserDto) => (null, (await AuthUserRepository(_db).upsert(value as UserDto)).id), _ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"), }; return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue)); diff --git a/mobile/lib/infrastructure/repositories/sync_migration.repository.dart b/mobile/lib/infrastructure/repositories/sync_migration.repository.dart index 814c8780ad..e27ed8e823 100644 --- a/mobile/lib/infrastructure/repositories/sync_migration.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_migration.repository.dart @@ -1,9 +1,13 @@ +import 'package:drift/drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_migration.repository.drift.dart'; -class SyncMigrationRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class SyncMigrationRepository extends DatabaseAccessor with $SyncMigrationRepositoryMixin { - const SyncMigrationRepository(super.db) : _db = db; + SyncMigrationRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future v20260128CopyExifWidthHeightToAsset() async { await _db.customStatement(''' diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index c43de69c5d..d118b51c62 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -29,16 +29,19 @@ import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.drift.dart'; import 'package:immich_mobile/infrastructure/utils/exif.converter.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart' as api show AlbumUserRole, AssetEditAction, AssetVisibility, UserMetadataKey; import 'package:openapi/api.dart' hide AlbumUserRole, AssetEditAction, AssetVisibility, UserMetadataKey; -class SyncStreamRepository extends DriftDatabaseRepository { - final Logger _logger = Logger('DriftSyncStreamRepository'); - final Drift _db; +@DriftAccessor() +class SyncStreamRepository extends DatabaseAccessor with $SyncStreamRepositoryMixin { + final Logger _logger = Logger('SyncStreamRepository'); - SyncStreamRepository(super.db) : _db = db; + SyncStreamRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future reset() async { _logger.fine("SyncResetV1 received. Resetting remote entities"); diff --git a/mobile/lib/infrastructure/repositories/timeline.repository.dart b/mobile/lib/infrastructure/repositories/timeline.repository.dart index 82ad38c80f..b0271f74a3 100644 --- a/mobile/lib/infrastructure/repositories/timeline.repository.dart +++ b/mobile/lib/infrastructure/repositories/timeline.repository.dart @@ -12,6 +12,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/map.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/timeline.repository.drift.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:stream_transform/stream_transform.dart'; @@ -33,10 +34,12 @@ class TimelineMapOptions { }); } -class DriftTimelineRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class TimelineRepository extends DatabaseAccessor with $TimelineRepositoryMixin { - const DriftTimelineRepository(super._db) : _db = _db; + TimelineRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Stream> watchTimelineUserIds(String userId) { final query = _db.partnerEntity.selectOnly() diff --git a/mobile/lib/infrastructure/repositories/trashed_local_asset.repository.dart b/mobile/lib/infrastructure/repositories/trashed_local_asset.repository.dart index 0f50776e4e..814db36977 100644 --- a/mobile/lib/infrastructure/repositories/trashed_local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/trashed_local_asset.repository.dart @@ -8,13 +8,16 @@ import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.d import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.drift.dart'; typedef TrashedAsset = ({String albumId, LocalAsset asset}); -class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository { - final Drift _db; +@DriftAccessor() +class TrashedLocalAssetRepository extends DatabaseAccessor with $TrashedLocalAssetRepositoryMixin { - const DriftTrashedLocalAssetRepository(this._db) : super(_db); + TrashedLocalAssetRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; /// Matches remote_asset_entity rows owned by the current user. The asset is unique over (owner, checksum), /// so partners can have a duplicate checksum diff --git a/mobile/lib/infrastructure/repositories/user.repository.dart b/mobile/lib/infrastructure/repositories/user.repository.dart index 6df7344991..157851ab58 100644 --- a/mobile/lib/infrastructure/repositories/user.repository.dart +++ b/mobile/lib/infrastructure/repositories/user.repository.dart @@ -4,18 +4,23 @@ import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/mapper.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/user.repository.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart'; -class UserRepository { - final Drift _db; - const UserRepository(this._db); +@DriftAccessor() +class UserRepository extends DatabaseAccessor with $UserRepositoryMixin { + UserRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Stream> getAll() => _db.select(_db.userEntity).map(mapToUser).watch(); } -class DriftAuthUserRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftAuthUserRepository(super.db) : _db = db; +@DriftAccessor() +class AuthUserRepository extends DatabaseAccessor with $AuthUserRepositoryMixin { + AuthUserRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future get(String id) async { final user = await _db.managers.authUserEntity.filter((user) => user.id.equals(id)).getSingleOrNull(); diff --git a/mobile/lib/infrastructure/repositories/user_metadata.repository.dart b/mobile/lib/infrastructure/repositories/user_metadata.repository.dart index 173ec10b97..001e482f5c 100644 --- a/mobile/lib/infrastructure/repositories/user_metadata.repository.dart +++ b/mobile/lib/infrastructure/repositories/user_metadata.repository.dart @@ -3,9 +3,11 @@ import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; -class DriftUserMetadataRepository extends DriftDatabaseRepository { - final Drift _db; - const DriftUserMetadataRepository(this._db) : super(_db); +@DriftAccessor() +class UserMetadataRepository extends DatabaseAccessor { + UserMetadataRepository(super.attachedDatabase); + + Drift get _db => attachedDatabase; Future> getUserMetadata(String userId) { final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(userId)); diff --git a/mobile/lib/pages/backup/drift_upload_detail.page.dart b/mobile/lib/pages/backup/drift_upload_detail.page.dart index 5ed43672d9..b010371370 100644 --- a/mobile/lib/pages/backup/drift_upload_detail.page.dart +++ b/mobile/lib/pages/backup/drift_upload_detail.page.dart @@ -6,7 +6,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:path/path.dart' as path; @@ -530,7 +530,7 @@ class _CurrentUploadThumbnail extends ConsumerWidget { Future _getAsset(WidgetRef ref) async { try { - return await ref.read(localAssetRepository).getById(taskId); + return await ref.read(driftProvider).localAssetRepository.getById(taskId); } catch (e) { return null; } @@ -667,7 +667,7 @@ class FileDetailDialog extends ConsumerWidget { Future _getAssetDetails(WidgetRef ref, String localAssetId) async { try { - return await ref.read(localAssetRepository).getById(localAssetId); + return await ref.read(driftProvider).localAssetRepository.getById(localAssetId); } catch (e) { return null; } diff --git a/mobile/lib/presentation/actions/edit_asset.action.dart b/mobile/lib/presentation/actions/edit_asset.action.dart index 9b11032df9..3595137e7f 100644 --- a/mobile/lib/presentation/actions/edit_asset.action.dart +++ b/mobile/lib/presentation/actions/edit_asset.action.dart @@ -12,6 +12,7 @@ import 'package:immich_mobile/presentation/actions/action.dart'; import 'package:immich_mobile/presentation/pages/edit/editor.provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -50,7 +51,7 @@ class EditAssetAction extends AssetActionBuilder { try { // TODO(shenlong): Move all EXIF and Apply Edits logic onto the Route - final repository = ref.read(remoteAssetRepositoryProvider); + final repository = ref.read(driftProvider).remoteAssetRepository; final (edits, exif) = await (repository.getAssetEdits(asset.id), repository.getExif(asset.id)).wait; if (exif == null || !context.mounted) { return; diff --git a/mobile/lib/presentation/actions/edit_datetime.action.dart b/mobile/lib/presentation/actions/edit_datetime.action.dart index 31de23d1a7..4ca3ddbaf4 100644 --- a/mobile/lib/presentation/actions/edit_datetime.action.dart +++ b/mobile/lib/presentation/actions/edit_datetime.action.dart @@ -7,6 +7,7 @@ import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/presentation/actions/action.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/toast.provider.dart'; import 'package:immich_mobile/utils/error_handler.dart'; import 'package:immich_mobile/utils/timezone.dart'; @@ -46,7 +47,7 @@ class EditDateTimeAction extends AssetActionBuilder { } final (:assetIds, :origin) = state; - final remoteAssetRepository = ref.read(remoteAssetRepositoryProvider); + final remoteAssetRepository = ref.read(driftProvider).remoteAssetRepository; final clearSelection = ref.read(clearSelectionProvider(source)); try { diff --git a/mobile/lib/presentation/actions/edit_location.action.dart b/mobile/lib/presentation/actions/edit_location.action.dart index 5ce74a0f40..01318de999 100644 --- a/mobile/lib/presentation/actions/edit_location.action.dart +++ b/mobile/lib/presentation/actions/edit_location.action.dart @@ -7,6 +7,7 @@ import 'package:immich_mobile/generated/translations.g.dart'; import 'package:immich_mobile/presentation/actions/action.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/toast.provider.dart'; import 'package:immich_mobile/utils/error_handler.dart'; import 'package:immich_mobile/widgets/common/location_picker.dart'; @@ -46,7 +47,7 @@ class EditLocationAction extends AssetActionBuilder { } final (:assetIds, :origin) = state; - final remoteAssetRepository = ref.read(remoteAssetRepositoryProvider); + final remoteAssetRepository = ref.read(driftProvider).remoteAssetRepository; final clearSelection = ref.read(clearSelectionProvider(source)); try { diff --git a/mobile/lib/presentation/pages/dev/media_stat.page.dart b/mobile/lib/presentation/pages/dev/media_stat.page.dart index 4c18a09200..8655f1f88b 100644 --- a/mobile/lib/presentation/pages/dev/media_stat.page.dart +++ b/mobile/lib/presentation/pages/dev/media_stat.page.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -60,7 +59,7 @@ class LocalMediaSummaryPage extends StatelessWidget { body: Consumer( builder: (ctx, ref, __) { final db = ref.watch(driftProvider); - final albumsFuture = ref.watch(localAlbumRepository).getAll(); + final albumsFuture = db.localAlbumRepository.getAll(); return CustomScrollView( slivers: [ @@ -140,7 +139,7 @@ class RemoteMediaSummaryPage extends StatelessWidget { body: Consumer( builder: (ctx, ref, __) { final db = ref.watch(driftProvider); - final albumsFuture = ref.watch(remoteAlbumRepository).getAll(); + final albumsFuture = db.remoteAlbumRepository.getAll(); return CustomScrollView( slivers: [ diff --git a/mobile/lib/providers/backup/backup_album.provider.dart b/mobile/lib/providers/backup/backup_album.provider.dart index 25a4204928..68610b46ff 100644 --- a/mobile/lib/providers/backup/backup_album.provider.dart +++ b/mobile/lib/providers/backup/backup_album.provider.dart @@ -4,10 +4,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/services/local_album.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; final backupAlbumProvider = StateNotifierProvider>( - (ref) => BackupAlbumNotifier(ref.watch(localAlbumServiceProvider)), + (ref) => BackupAlbumNotifier(LocalAlbumService(ref.watch(driftProvider).localAlbumRepository)), ); class BackupAlbumNotifier extends StateNotifier> { diff --git a/mobile/lib/providers/backup/drift_backup.provider.dart b/mobile/lib/providers/backup/drift_backup.provider.dart index 1756d0fd30..89847d23dd 100644 --- a/mobile/lib/providers/backup/drift_backup.provider.dart +++ b/mobile/lib/providers/backup/drift_backup.provider.dart @@ -6,7 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/services/background_upload.service.dart'; import 'package:immich_mobile/services/foreground_upload.service.dart'; @@ -367,5 +367,8 @@ final driftCandidateBackupAlbumInfoProvider = FutureProvider.autoDispose.family< ref, assetId, ) { - return ref.read(localAssetRepository).getSourceAlbums(assetId, backupSelection: BackupSelection.selected); + return ref + .read(driftProvider) + .localAssetRepository + .getSourceAlbums(assetId, backupSelection: BackupSelection.selected); }); diff --git a/mobile/lib/providers/infrastructure/album.provider.dart b/mobile/lib/providers/infrastructure/album.provider.dart index 379e7b3101..579cc17838 100644 --- a/mobile/lib/providers/infrastructure/album.provider.dart +++ b/mobile/lib/providers/infrastructure/album.provider.dart @@ -5,41 +5,27 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/services/local_album.service.dart'; import 'package:immich_mobile/domain/services/remote_album.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/remote_album.provider.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; import 'package:immich_mobile/services/foreground_upload.service.dart'; -final localAlbumRepository = Provider( - (ref) => DriftLocalAlbumRepository(ref.watch(driftProvider)), -); - -final localAlbumServiceProvider = Provider( - (ref) => LocalAlbumService(ref.watch(localAlbumRepository)), -); - final localAlbumProvider = FutureProvider>( - (ref) => LocalAlbumService(ref.watch(localAlbumRepository)) + (ref) => LocalAlbumService(ref.watch(driftProvider).localAlbumRepository) .getAll(sortBy: {SortLocalAlbumsBy.newestAsset}) .then((albums) => albums.where((album) => album.assetCount > 0).toList()), ); final localAlbumThumbnailProvider = FutureProvider.family( - (ref, albumId) => LocalAlbumService(ref.watch(localAlbumRepository)).getThumbnail(albumId), -); - -final remoteAlbumRepository = Provider( - (ref) => DriftRemoteAlbumRepository(ref.watch(driftProvider)), + (ref, albumId) => LocalAlbumService(ref.watch(driftProvider).localAlbumRepository).getThumbnail(albumId), ); final remoteAlbumServiceProvider = Provider( (ref) => RemoteAlbumService( - ref.watch(remoteAlbumRepository), + ref.watch(driftProvider).remoteAlbumRepository, ref.watch(driftAlbumApiRepositoryProvider), ref.watch(foregroundUploadServiceProvider), ), - dependencies: [remoteAlbumRepository], ); final remoteAlbumProvider = NotifierProvider( diff --git a/mobile/lib/providers/infrastructure/asset.provider.dart b/mobile/lib/providers/infrastructure/asset.provider.dart index 8ca0ca0ec9..ea89d1b9fb 100644 --- a/mobile/lib/providers/infrastructure/asset.provider.dart +++ b/mobile/lib/providers/infrastructure/asset.provider.dart @@ -1,38 +1,21 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/asset.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/remote_exif.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/trashed_local_asset.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/repositories/asset_api.repository.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; -final localAssetRepository = Provider( - (ref) => DriftLocalAssetRepository(ref.watch(driftProvider)), -); - -final remoteAssetRepositoryProvider = Provider( - (ref) => RemoteAssetRepository(ref.watch(driftProvider)), -); - -final remoteExifRepositoryProvider = Provider((ref) => RemoteExifRepository(ref.watch(driftProvider))); - -final trashedLocalAssetRepository = Provider( - (ref) => DriftTrashedLocalAssetRepository(ref.watch(driftProvider)), -); - -final assetServiceProvider = Provider( - (ref) => AssetService( - remoteRepository: ref.watch(remoteAssetRepositoryProvider), - exifRepository: ref.watch(remoteExifRepositoryProvider), - localRepository: ref.watch(localAssetRepository), +final assetServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return AssetService( + remoteRepository: db.remoteAssetRepository, + exifRepository: db.remoteExifRepository, + localRepository: db.localAssetRepository, apiRepository: ref.watch(assetApiRepositoryProvider), mediaRepository: ref.watch(assetMediaRepositoryProvider), - trashedLocalRepository: ref.watch(trashedLocalAssetRepository), - ), -); + trashedLocalRepository: db.trashedLocalAssetRepository, + ); +}); final placesProvider = FutureProvider>((ref) { final assetService = ref.watch(assetServiceProvider); diff --git a/mobile/lib/providers/infrastructure/map.provider.dart b/mobile/lib/providers/infrastructure/map.provider.dart index d9d261521e..7f2fa5b40c 100644 --- a/mobile/lib/providers/infrastructure/map.provider.dart +++ b/mobile/lib/providers/infrastructure/map.provider.dart @@ -1,13 +1,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/map.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/map.repository.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -final mapRepositoryProvider = Provider((ref) => DriftMapRepository(ref.watch(driftProvider))); - final mapServiceProvider = Provider( (ref) { final user = ref.watch(currentUserProvider); @@ -19,12 +16,11 @@ final mapServiceProvider = Provider( ? ref.watch(timelineUsersProvider).valueOrNull ?? [user.id] : [user.id]; - final mapService = ref.watch(mapFactoryProvider).remote(users, ref.watch(mapStateProvider).toOptions()); + final mapFactory = MapFactory(mapRepository: ref.watch(driftProvider).mapRepository); + final mapService = mapFactory.remote(users, ref.watch(mapStateProvider).toOptions()); return mapService; }, // Empty dependencies to inform the framework that this provider // might be used in a ProviderScope dependencies: const [], ); - -final mapFactoryProvider = Provider((ref) => MapFactory(mapRepository: ref.watch(mapRepositoryProvider))); diff --git a/mobile/lib/providers/infrastructure/memory.provider.dart b/mobile/lib/providers/infrastructure/memory.provider.dart index 3dd32454b8..a2817f9c07 100644 --- a/mobile/lib/providers/infrastructure/memory.provider.dart +++ b/mobile/lib/providers/infrastructure/memory.provider.dart @@ -3,18 +3,9 @@ import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/domain/services/memory.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -final driftMemoryRepositoryProvider = Provider( - (ref) => DriftMemoryRepository(ref.watch(driftProvider)), -); - -final driftMemoryServiceProvider = Provider( - (ref) => DriftMemoryService(ref.watch(driftMemoryRepositoryProvider)), -); - final driftMemoryFutureProvider = FutureProvider.autoDispose>((ref) { final (userId, enabled) = ref.watch(currentUserProvider.select((user) => (user?.id, user?.memoryEnabled ?? true))); if (userId == null || !enabled) { @@ -26,6 +17,6 @@ final driftMemoryFutureProvider = FutureProvider.autoDispose>( final timer = Timer(nextMidnight.difference(now) + const Duration(seconds: 5), ref.invalidateSelf); ref.onDispose(timer.cancel); - final service = ref.watch(driftMemoryServiceProvider); + final service = DriftMemoryService(ref.watch(driftProvider).memoryRepository); return service.getMemoryLane(userId); }); diff --git a/mobile/lib/providers/infrastructure/ocr.provider.dart b/mobile/lib/providers/infrastructure/ocr.provider.dart index 111f3952ce..20cfdbf5b2 100644 --- a/mobile/lib/providers/infrastructure/ocr.provider.dart +++ b/mobile/lib/providers/infrastructure/ocr.provider.dart @@ -1,14 +1,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/ocr.model.dart'; import 'package:immich_mobile/domain/services/ocr.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/ocr.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; -final ocrRepositoryProvider = Provider((ref) => OcrRepository(ref.watch(driftProvider))); - -final ocrServiceProvider = Provider((ref) => OcrService(ref.watch(ocrRepositoryProvider))); - final ocrAssetProvider = FutureProvider.autoDispose.family?, String>((ref, assetId) async { - final service = ref.watch(ocrServiceProvider); + final service = OcrService(ref.watch(driftProvider).ocrRepository); return service.get(assetId); }); diff --git a/mobile/lib/providers/infrastructure/people.provider.dart b/mobile/lib/providers/infrastructure/people.provider.dart index 1939940975..cccb968202 100644 --- a/mobile/lib/providers/infrastructure/people.provider.dart +++ b/mobile/lib/providers/infrastructure/people.provider.dart @@ -1,17 +1,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/person.model.dart'; import 'package:immich_mobile/domain/services/people.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/people.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart'; import 'package:immich_mobile/repositories/person_api.repository.dart'; -final driftPeopleRepositoryProvider = Provider( - (ref) => DriftPeopleRepository(ref.watch(driftProvider)), -); - final driftPeopleServiceProvider = Provider( - (ref) => DriftPeopleService(ref.watch(driftPeopleRepositoryProvider), ref.watch(personApiRepositoryProvider)), + (ref) => DriftPeopleService(ref.watch(driftProvider).peopleRepository, ref.watch(personApiRepositoryProvider)), ); final driftPeopleAssetProvider = FutureProvider.family, String>((ref, assetId) async { diff --git a/mobile/lib/providers/infrastructure/stack.provider.dart b/mobile/lib/providers/infrastructure/stack.provider.dart deleted file mode 100644 index 0528fd0c91..0000000000 --- a/mobile/lib/providers/infrastructure/stack.provider.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/infrastructure/repositories/stack.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; - -final driftStackProvider = Provider((ref) => DriftStackRepository(ref.watch(driftProvider))); diff --git a/mobile/lib/providers/infrastructure/sync.provider.dart b/mobile/lib/providers/infrastructure/sync.provider.dart index 700b51f12d..618c6039ff 100644 --- a/mobile/lib/providers/infrastructure/sync.provider.dart +++ b/mobile/lib/providers/infrastructure/sync.provider.dart @@ -3,55 +3,50 @@ import 'package:immich_mobile/domain/services/hash.service.dart'; import 'package:immich_mobile/domain/services/local_sync.service.dart'; import 'package:immich_mobile/domain/services/sync_stream.service.dart'; import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/sync_migration.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; import 'package:immich_mobile/providers/api.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; import 'package:immich_mobile/repositories/permission.repository.dart'; -final syncMigrationRepositoryProvider = Provider((ref) => SyncMigrationRepository(ref.watch(driftProvider))); - -final syncStreamServiceProvider = Provider( - (ref) => SyncStreamService( +final syncStreamServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return SyncStreamService( syncApiRepository: ref.watch(syncApiRepositoryProvider), - syncStreamRepository: ref.watch(syncStreamRepositoryProvider), - localAssetRepository: ref.watch(localAssetRepository), - trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository), + syncStreamRepository: db.syncStreamRepository, + localAssetRepository: db.localAssetRepository, + trashedLocalAssetRepository: db.trashedLocalAssetRepository, assetMediaRepository: ref.watch(assetMediaRepositoryProvider), permissionRepository: ref.watch(permissionRepositoryProvider), - syncMigrationRepository: ref.watch(syncMigrationRepositoryProvider), + syncMigrationRepository: db.syncMigrationRepository, api: ref.watch(apiServiceProvider), cancellation: ref.watch(cancellationProvider), - ), -); + ); +}); final syncApiRepositoryProvider = Provider((ref) => SyncApiRepository(ref.watch(apiServiceProvider))); -final syncStreamRepositoryProvider = Provider((ref) => SyncStreamRepository(ref.watch(driftProvider))); - -final localSyncServiceProvider = Provider( - (ref) => LocalSyncService( - localAlbumRepository: ref.watch(localAlbumRepository), - localAssetRepository: ref.watch(localAssetRepository), - trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository), +final localSyncServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return LocalSyncService( + localAlbumRepository: db.localAlbumRepository, + localAssetRepository: db.localAssetRepository, + trashedLocalAssetRepository: db.trashedLocalAssetRepository, assetMediaRepository: ref.watch(assetMediaRepositoryProvider), permissionRepository: ref.watch(permissionRepositoryProvider), nativeSyncApi: ref.watch(nativeSyncApiProvider), cancellation: ref.watch(cancellationProvider), - ), -); + ); +}); -final hashServiceProvider = Provider( - (ref) => HashService( - localAlbumRepository: ref.watch(localAlbumRepository), - localAssetRepository: ref.watch(localAssetRepository), +final hashServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return HashService( + localAlbumRepository: db.localAlbumRepository, + localAssetRepository: db.localAssetRepository, nativeSyncApi: ref.watch(nativeSyncApiProvider), - trashedLocalAssetRepository: ref.watch(trashedLocalAssetRepository), + trashedLocalAssetRepository: db.trashedLocalAssetRepository, cancellation: ref.watch(cancellationProvider), - ), -); + ); +}); diff --git a/mobile/lib/providers/infrastructure/timeline.provider.dart b/mobile/lib/providers/infrastructure/timeline.provider.dart index e5ac1389e9..e1fb515e45 100644 --- a/mobile/lib/providers/infrastructure/timeline.provider.dart +++ b/mobile/lib/providers/infrastructure/timeline.provider.dart @@ -1,16 +1,11 @@ import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/timeline.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/settings.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -final timelineRepositoryProvider = Provider( - (ref) => DriftTimelineRepository(ref.watch(driftProvider)), -); - final timelineArgsProvider = Provider.autoDispose( (ref) => throw UnimplementedError('Will be overridden through a ProviderScope.'), ); @@ -29,7 +24,7 @@ final timelineServiceProvider = Provider( final timelineFactoryProvider = Provider( (ref) => TimelineFactory( - timelineRepository: ref.watch(timelineRepositoryProvider), + timelineRepository: ref.watch(driftProvider).timelineRepository, settingsRepository: ref.watch(settingsProvider), ), ); @@ -43,7 +38,7 @@ final timelineUsersProvider = StreamProvider>((ref) { // Drift re-emits a fresh but content-identical list on unrelated table updates, // which would dispose and rebuild the timeline service mid-load return ref - .watch(timelineRepositoryProvider) + .watch(driftProvider).timelineRepository .watchTimelineUserIds(currentUserId) .distinct(const ListEquality().equals); }); diff --git a/mobile/lib/providers/infrastructure/trash_sync.provider.dart b/mobile/lib/providers/infrastructure/trash_sync.provider.dart index a783080f33..13e1424d75 100644 --- a/mobile/lib/providers/infrastructure/trash_sync.provider.dart +++ b/mobile/lib/providers/infrastructure/trash_sync.provider.dart @@ -1,11 +1,11 @@ import 'package:async/async.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; typedef TrashedAssetsCount = ({int total, int hashed}); final trashedAssetsCountProvider = StreamProvider((ref) { - final repo = ref.watch(trashedLocalAssetRepository); + final repo = ref.watch(driftProvider).trashedLocalAssetRepository; final total$ = repo.watchCount(); final hashed$ = repo.watchHashedCount(); return StreamZip([total$, hashed$]).map((values) => (total: values[0], hashed: values[1])); diff --git a/mobile/lib/providers/infrastructure/user.provider.dart b/mobile/lib/providers/infrastructure/user.provider.dart index 09f74db37d..a36082f31b 100644 --- a/mobile/lib/providers/infrastructure/user.provider.dart +++ b/mobile/lib/providers/infrastructure/user.provider.dart @@ -1,16 +1,12 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/partner.service.dart'; import 'package:immich_mobile/domain/services/user.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/partner.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/user.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart'; import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/store.provider.dart'; import 'package:immich_mobile/repositories/partner_api.repository.dart'; -final userRepositoryProvider = Provider((ref) => UserRepository(ref.watch(driftProvider))); - final userApiRepositoryProvider = Provider((ref) => UserApiRepository(ref.watch(apiServiceProvider).usersApi)); final userServiceProvider = Provider( @@ -20,12 +16,7 @@ final userServiceProvider = Provider( ), ); -final partnerRepositoryProvider = Provider((ref) => PartnerRepository(ref.watch(driftProvider))); - -final partnerServiceProvider = Provider( - (ref) => PartnerService( - ref.watch(userRepositoryProvider), - ref.watch(partnerRepositoryProvider), - ref.watch(partnerApiRepositoryProvider), - ), -); +final partnerServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); + return PartnerService(db.userRepository, db.partnerRepository, ref.watch(partnerApiRepositoryProvider)); +}); diff --git a/mobile/lib/providers/infrastructure/user_metadata.provider.dart b/mobile/lib/providers/infrastructure/user_metadata.provider.dart index 357b43f4f6..dd29b41a44 100644 --- a/mobile/lib/providers/infrastructure/user_metadata.provider.dart +++ b/mobile/lib/providers/infrastructure/user_metadata.provider.dart @@ -1,16 +1,11 @@ import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/user_metadata.model.dart'; -import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -final userMetadataRepository = Provider( - (ref) => DriftUserMetadataRepository(ref.watch(driftProvider)), -); - final userMetadataProvider = FutureProvider>((ref) async { - final repository = ref.watch(userMetadataRepository); + final repository = ref.watch(driftProvider).userMetadataRepository; final user = ref.watch(currentUserProvider); if (user == null) { return []; diff --git a/mobile/lib/services/action.service.dart b/mobile/lib/services/action.service.dart index ec9b7cd446..fcfb96d988 100644 --- a/mobile/lib/services/action.service.dart +++ b/mobile/lib/services/action.service.dart @@ -2,11 +2,11 @@ import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/repositories/asset_api.repository.dart'; final actionServiceProvider = Provider( - (ref) => ActionService(ref.watch(assetApiRepositoryProvider), ref.watch(remoteAssetRepositoryProvider)), + (ref) => ActionService(ref.watch(assetApiRepositoryProvider), ref.watch(driftProvider).remoteAssetRepository), ); class ActionService { diff --git a/mobile/lib/services/background_upload.service.dart b/mobile/lib/services/background_upload.service.dart index 5312107f6c..0c026e1e31 100644 --- a/mobile/lib/services/background_upload.service.dart +++ b/mobile/lib/services/background_upload.service.dart @@ -15,7 +15,7 @@ import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; import 'package:immich_mobile/repositories/upload.repository.dart'; @@ -26,11 +26,12 @@ import 'package:openapi/api.dart' as api; import 'package:path/path.dart' as p; final backgroundUploadServiceProvider = Provider((ref) { + final db = ref.watch(driftProvider); final service = BackgroundUploadService( ref.watch(uploadRepositoryProvider), ref.watch(storageRepositoryProvider), - ref.watch(localAssetRepository), - ref.watch(backupRepositoryProvider), + db.localAssetRepository, + db.backupRepository, ref.watch(assetMediaRepositoryProvider), ); @@ -112,8 +113,8 @@ class BackgroundUploadService { final UploadRepository _uploadRepository; final StorageRepository _storageRepository; - final DriftLocalAssetRepository _localAssetRepository; - final DriftBackupRepository _backupRepository; + final LocalAssetRepository _localAssetRepository; + final BackupRepository _backupRepository; final AssetMediaRepository _assetMediaRepository; final Logger _logger = Logger('BackgroundUploadService'); diff --git a/mobile/lib/services/cleanup.service.dart b/mobile/lib/services/cleanup.service.dart index fca5584859..06cda2cf0d 100644 --- a/mobile/lib/services/cleanup.service.dart +++ b/mobile/lib/services/cleanup.service.dart @@ -2,17 +2,17 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; final cleanupServiceProvider = Provider((ref) { - return CleanupService(ref.watch(localAssetRepository), ref.watch(assetMediaRepositoryProvider)); + return CleanupService(ref.watch(driftProvider).localAssetRepository, ref.watch(assetMediaRepositoryProvider)); }); class CleanupService { static final int _deleteBatchSize = CurrentPlatform.isAndroid ? 2000 : 10000; - final DriftLocalAssetRepository _localAssetRepository; + final LocalAssetRepository _localAssetRepository; final AssetMediaRepository _assetMediaRepository; const CleanupService(this._localAssetRepository, this._assetMediaRepository); @@ -46,7 +46,7 @@ class CleanupService { final deletedIds = await _assetMediaRepository.deleteAll(batch); if (deletedIds.isNotEmpty) { - await _localAssetRepository.delete(deletedIds); + await _localAssetRepository.deleteAssets(deletedIds); deletedCount += deletedIds.length; } } diff --git a/mobile/lib/services/deep_link.service.dart b/mobile/lib/services/deep_link.service.dart index d5947ceb8f..617a5b6132 100644 --- a/mobile/lib/services/deep_link.service.dart +++ b/mobile/lib/services/deep_link.service.dart @@ -10,7 +10,7 @@ import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.page.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart' as beta_asset_provider; -import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; @@ -21,7 +21,7 @@ final deepLinkServiceProvider = Provider( ref.watch(timelineFactoryProvider), ref.watch(beta_asset_provider.assetServiceProvider), ref.watch(remoteAlbumServiceProvider), - ref.watch(driftMemoryServiceProvider), + DriftMemoryService(ref.watch(driftProvider).memoryRepository), ref.watch(driftPeopleServiceProvider), ref.watch(currentUserProvider), ), diff --git a/mobile/lib/services/foreground_upload.service.dart b/mobile/lib/services/foreground_upload.service.dart index 11cbd03017..260b7c5cb3 100644 --- a/mobile/lib/services/foreground_upload.service.dart +++ b/mobile/lib/services/foreground_upload.service.dart @@ -15,6 +15,7 @@ import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; import 'package:immich_mobile/platform/connectivity_api.g.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; @@ -39,7 +40,7 @@ final foregroundUploadServiceProvider = Provider((ref) { return ForegroundUploadService( ref.watch(uploadRepositoryProvider), ref.watch(storageRepositoryProvider), - ref.watch(backupRepositoryProvider), + ref.watch(driftProvider).backupRepository, ref.watch(connectivityApiProvider), ref.watch(assetMediaRepositoryProvider), ); @@ -61,7 +62,7 @@ class ForegroundUploadService { final UploadRepository _uploadRepository; final StorageRepository _storageRepository; - final DriftBackupRepository _backupRepository; + final BackupRepository _backupRepository; final ConnectivityApi _connectivityApi; final AssetMediaRepository _assetMediaRepository; final Logger _logger = Logger('ForegroundUploadService'); diff --git a/mobile/lib/services/view_intent_asset_resolver.service.dart b/mobile/lib/services/view_intent_asset_resolver.service.dart index 7bda1bdc13..94296f5293 100644 --- a/mobile/lib/services/view_intent_asset_resolver.service.dart +++ b/mobile/lib/services/view_intent_asset_resolver.service.dart @@ -4,7 +4,7 @@ import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/models/view_intent/view_intent_payload.extension.dart'; import 'package:immich_mobile/platform/view_intent_api.g.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:logging/logging.dart'; @@ -19,13 +19,13 @@ class ViewIntentResolvedAsset { final viewIntentAssetResolverProvider = Provider( (ref) => ViewIntentAssetResolver( - localAssetRepository: ref.read(localAssetRepository), + localAssetRepository: ref.read(driftProvider).localAssetRepository, timelineFactory: ref.read(timelineFactoryProvider), ), ); class ViewIntentAssetResolver { - final DriftLocalAssetRepository _localAssetRepository; + final LocalAssetRepository _localAssetRepository; final TimelineFactory _timelineFactory; static final Logger _logger = Logger('ViewIntentAssetResolver'); diff --git a/mobile/lib/utils/bootstrap.dart b/mobile/lib/utils/bootstrap.dart index 37ad748a57..b1f57db6f1 100644 --- a/mobile/lib/utils/bootstrap.dart +++ b/mobile/lib/utils/bootstrap.dart @@ -49,7 +49,7 @@ abstract final class Bootstrap { await configureSqliteCache(); final (db, updatePool) = await openSqliteConnectionWithUpdatePool(name: 'immich'); final drift = Drift.sqlite(db, updatePool); - final DriftStoreRepository storeRepo = DriftStoreRepository(drift); + final StoreRepository storeRepo = StoreRepository(drift); await StoreService.init(storeRepository: storeRepo, listenUpdates: listenStoreUpdates); diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index 097f72e1e1..eba2585830 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -3,6 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/services/local_album.service.dart'; +import 'package:immich_mobile/domain/services/memory.service.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; @@ -12,7 +14,6 @@ import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; import 'package:immich_mobile/providers/infrastructure/trash_sync.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; @@ -230,10 +231,11 @@ class _SyncStatsCounts extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final db = ref.watch(driftProvider); final assetService = ref.watch(assetServiceProvider); - final localAlbumService = ref.watch(localAlbumServiceProvider); + final localAlbumService = LocalAlbumService(db.localAlbumRepository); final remoteAlbumService = ref.watch(remoteAlbumServiceProvider); - final memoryService = ref.watch(driftMemoryServiceProvider); + final memoryService = DriftMemoryService(db.memoryRepository); final appSettingsService = ref.watch(appSettingsServiceProvider); Future> loadCounts() async { diff --git a/mobile/test/domain/services/local_sync_service_test.dart b/mobile/test/domain/services/local_sync_service_test.dart index 14277709da..2cbabd77e9 100644 --- a/mobile/test/domain/services/local_sync_service_test.dart +++ b/mobile/test/domain/services/local_sync_service_test.dart @@ -23,9 +23,9 @@ import '../../service.mocks.dart'; void main() { late LocalSyncService sut; - late DriftLocalAlbumRepository mockLocalAlbumRepository; - late DriftLocalAssetRepository mockLocalAssetRepository; - late DriftTrashedLocalAssetRepository mockTrashedLocalAssetRepository; + late LocalAlbumRepository mockLocalAlbumRepository; + late LocalAssetRepository mockLocalAssetRepository; + late TrashedLocalAssetRepository mockTrashedLocalAssetRepository; late AssetMediaRepository mockAssetMediaRepository; late MockPermissionRepository mockPermissionRepository; late MockNativeSyncApi mockNativeSyncApi; @@ -36,7 +36,7 @@ void main() { debugDefaultTargetPlatformOverride = TargetPlatform.android; db = Drift(drift.DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); }); tearDownAll(() async { diff --git a/mobile/test/domain/services/store_service_test.dart b/mobile/test/domain/services/store_service_test.dart index bb439b3d72..adab8863c1 100644 --- a/mobile/test/domain/services/store_service_test.dart +++ b/mobile/test/domain/services/store_service_test.dart @@ -14,12 +14,12 @@ const _kVersion = 2; void main() { late StoreService sut; - late DriftStoreRepository mockDriftStoreRepo; + late StoreRepository mockDriftStoreRepo; late StreamController>> controller; setUp(() async { controller = StreamController>>.broadcast(); - mockDriftStoreRepo = MockDriftStoreRepository(); + mockDriftStoreRepo = MockStoreRepository(); // For generics, we need to provide fallback to each concrete type to avoid runtime errors registerFallbackValue(StoreKey.accessToken); registerFallbackValue(StoreKey.version); @@ -124,12 +124,12 @@ void main() { group('Store Service delete:', () { setUp(() { - when(() => mockDriftStoreRepo.delete(any>())).thenAnswer((_) async => true); + when(() => mockDriftStoreRepo.deleteValue(any>())).thenAnswer((_) async => true); }); test('Removes the value from the DB', () async { await sut.delete(StoreKey.accessToken); - verify(() => mockDriftStoreRepo.delete(StoreKey.accessToken)).called(1); + verify(() => mockDriftStoreRepo.deleteValue(StoreKey.accessToken)).called(1); }); test('Removes the value from the cache', () async { diff --git a/mobile/test/domain/services/sync_linked_album_service_test.dart b/mobile/test/domain/services/sync_linked_album_service_test.dart index e5f4c3b5dc..60b230ba65 100644 --- a/mobile/test/domain/services/sync_linked_album_service_test.dart +++ b/mobile/test/domain/services/sync_linked_album_service_test.dart @@ -1,9 +1,10 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/store.provider.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; +import 'package:mocktail/mocktail.dart'; import '../../infrastructure/repository.mock.dart'; import '../../service.mocks.dart'; @@ -13,10 +14,12 @@ void main() { // alone, i.e. the root (main) isolate, where cancellationProvider has no // override and throws if read. The UI reads this provider here. ProviderContainer rootContainer() { + final drift = MockDrift(); + when(() => drift.localAlbumRepository).thenReturn(MockLocalAlbumRepository()); + when(() => drift.remoteAlbumRepository).thenReturn(MockRemoteAlbumRepository()); final container = ProviderContainer( overrides: [ - localAlbumRepository.overrideWithValue(MockLocalAlbumRepository()), - remoteAlbumRepository.overrideWithValue(MockRemoteAlbumRepository()), + driftProvider.overrideWithValue(drift), driftAlbumApiRepositoryProvider.overrideWithValue(MockDriftAlbumApiRepository()), storeServiceProvider.overrideWithValue(MockStoreService()), ], diff --git a/mobile/test/domain/services/sync_stream_service_test.dart b/mobile/test/domain/services/sync_stream_service_test.dart index 5cd4104f91..58b96a2fc6 100644 --- a/mobile/test/domain/services/sync_stream_service_test.dart +++ b/mobile/test/domain/services/sync_stream_service_test.dart @@ -40,8 +40,8 @@ void main() { late SyncStreamService sut; late SyncStreamRepository mockSyncStreamRepo; late SyncApiRepository mockSyncApiRepo; - late DriftLocalAssetRepository mockLocalAssetRepo; - late DriftTrashedLocalAssetRepository mockTrashedLocalAssetRepo; + late LocalAssetRepository mockLocalAssetRepo; + late TrashedLocalAssetRepository mockTrashedLocalAssetRepo; late AssetMediaRepository mockAssetMediaRepo; late MockPermissionRepository mockPermissionRepo; late MockApiService mockApi; @@ -60,7 +60,7 @@ void main() { registerFallbackValue(const SemVer(major: 2, minor: 5, patch: 0)); db = Drift(drift.DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); }); tearDownAll(() async { diff --git a/mobile/test/infrastructure/repositories/local_album_repository_test.dart b/mobile/test/infrastructure/repositories/local_album_repository_test.dart index ada4281e2a..7498360c87 100644 --- a/mobile/test/infrastructure/repositories/local_album_repository_test.dart +++ b/mobile/test/infrastructure/repositories/local_album_repository_test.dart @@ -23,7 +23,7 @@ void main() { group('getAll', () { test('sorts albums by backupSelection & isIosSharedAlbum', () async { - final localAlbumRepo = mediumFactory.getRepository(); + final localAlbumRepo = mediumFactory.getRepository(); await localAlbumRepo.upsert(mediumFactory.localAlbum(id: '1', backupSelection: BackupSelection.none)); await localAlbumRepo.upsert(mediumFactory.localAlbum(id: '2', backupSelection: BackupSelection.excluded)); await localAlbumRepo.upsert( @@ -46,7 +46,7 @@ void main() { // Android was dropped. The delta reports only the asset's new album, and the // stale link to its old album made the per-album delete sweep wipe the asset. test('keeps an asset moved to another album that still holds other assets', () async { - final localAlbumRepo = mediumFactory.getRepository(); + final localAlbumRepo = mediumFactory.getRepository(); final moved = _localAsset('moved'); final other = _localAsset('other'); @@ -83,7 +83,7 @@ void main() { }); test('replaces album membership with exactly what the delta reports', () async { - final localAlbumRepo = mediumFactory.getRepository(); + final localAlbumRepo = mediumFactory.getRepository(); final moved = _localAsset('moved'); await localAlbumRepo.upsert(mediumFactory.localAlbum(id: 'src'), toUpsert: [moved]); diff --git a/mobile/test/infrastructure/repositories/store_repository_test.dart b/mobile/test/infrastructure/repositories/store_repository_test.dart index 3e160c29ca..08ed5f66ab 100644 --- a/mobile/test/infrastructure/repositories/store_repository_test.dart +++ b/mobile/test/infrastructure/repositories/store_repository_test.dart @@ -47,11 +47,11 @@ Future _populateStore(Drift db) async { void main() { late Drift db; - late DriftStoreRepository sut; + late StoreRepository sut; setUp(() async { db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - sut = DriftStoreRepository(db); + sut = StoreRepository(db); }); tearDown(() async { @@ -100,7 +100,7 @@ void main() { test('delete()', () async { bool? advancedTroubleshooting = await sut.tryGet(StoreKey.advancedTroubleshooting); expect(advancedTroubleshooting, isFalse); - await sut.delete(StoreKey.advancedTroubleshooting); + await sut.deleteValue(StoreKey.advancedTroubleshooting); advancedTroubleshooting = await sut.tryGet(StoreKey.advancedTroubleshooting); expect(advancedTroubleshooting, isNull); }); diff --git a/mobile/test/infrastructure/repositories/sync_api_repository_test.dart b/mobile/test/infrastructure/repositories/sync_api_repository_test.dart index 3a3e40cbae..5764aee5ff 100644 --- a/mobile/test/infrastructure/repositories/sync_api_repository_test.dart +++ b/mobile/test/infrastructure/repositories/sync_api_repository_test.dart @@ -41,7 +41,7 @@ void main() { setUpAll(() async { final db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); }); setUp(() { diff --git a/mobile/test/infrastructure/repository.mock.dart b/mobile/test/infrastructure/repository.mock.dart index 355e128fc0..ef266b243c 100644 --- a/mobile/test/infrastructure/repository.mock.dart +++ b/mobile/test/infrastructure/repository.mock.dart @@ -1,7 +1,9 @@ import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/log.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/partner.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; @@ -18,7 +20,11 @@ import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; import 'package:immich_mobile/repositories/upload.repository.dart'; import 'package:mocktail/mocktail.dart'; -class MockDriftStoreRepository extends Mock implements DriftStoreRepository {} +class MockDrift extends Mock implements Drift {} + +class MockMemoryRepository extends Mock implements MemoryRepository {} + +class MockStoreRepository extends Mock implements StoreRepository {} class MockSettingsRepository extends Mock implements SettingsRepository {} @@ -26,21 +32,19 @@ class MockLogRepository extends Mock implements LogRepository {} class MockSyncStreamRepository extends Mock implements SyncStreamRepository {} -class MockLocalAlbumRepository extends Mock implements DriftLocalAlbumRepository {} +class MockLocalAlbumRepository extends Mock implements LocalAlbumRepository {} -class MockRemoteAlbumRepository extends Mock implements DriftRemoteAlbumRepository {} +class MockRemoteAlbumRepository extends Mock implements RemoteAlbumRepository {} -class MockLocalAssetRepository extends Mock implements DriftLocalAssetRepository {} - -class MockDriftLocalAssetRepository extends Mock implements DriftLocalAssetRepository {} +class MockLocalAssetRepository extends Mock implements LocalAssetRepository {} class MockRemoteAssetRepository extends Mock implements RemoteAssetRepository {} -class MockTrashedLocalAssetRepository extends Mock implements DriftTrashedLocalAssetRepository {} +class MockTrashedLocalAssetRepository extends Mock implements TrashedLocalAssetRepository {} class MockStorageRepository extends Mock implements StorageRepository {} -class MockDriftBackupRepository extends Mock implements DriftBackupRepository {} +class MockBackupRepository extends Mock implements BackupRepository {} class MockUploadRepository extends Mock implements UploadRepository {} diff --git a/mobile/test/medium/repositories/backup_repository_test.dart b/mobile/test/medium/repositories/backup_repository_test.dart index 00ab28df87..8e56502022 100644 --- a/mobile/test/medium/repositories/backup_repository_test.dart +++ b/mobile/test/medium/repositories/backup_repository_test.dart @@ -7,11 +7,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftBackupRepository sut; + late BackupRepository sut; setUp(() { ctx = MediumRepositoryContext(); - sut = DriftBackupRepository(ctx.db); + sut = BackupRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/local_asset_repository_test.dart b/mobile/test/medium/repositories/local_asset_repository_test.dart index 2376445d1a..bd048a13fd 100644 --- a/mobile/test/medium/repositories/local_asset_repository_test.dart +++ b/mobile/test/medium/repositories/local_asset_repository_test.dart @@ -8,11 +8,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftLocalAssetRepository sut; + late LocalAssetRepository sut; setUp(() { ctx = MediumRepositoryContext(); - sut = DriftLocalAssetRepository(ctx.db); + sut = LocalAssetRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/memory_repository_test.dart b/mobile/test/medium/repositories/memory_repository_test.dart index e57098f3bd..af9309f4aa 100644 --- a/mobile/test/medium/repositories/memory_repository_test.dart +++ b/mobile/test/medium/repositories/memory_repository_test.dart @@ -5,11 +5,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftMemoryRepository sut; + late MemoryRepository sut; setUp(() { ctx = MediumRepositoryContext(); - sut = DriftMemoryRepository(ctx.db); + sut = MemoryRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/partner_repository_test.dart b/mobile/test/medium/repositories/partner_repository_test.dart index 298b8b852d..4d730a0be4 100644 --- a/mobile/test/medium/repositories/partner_repository_test.dart +++ b/mobile/test/medium/repositories/partner_repository_test.dart @@ -78,7 +78,7 @@ void main() { final sharer = await ctx.newUser(); await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id, inTimeline: false); - await sut.update(sharedById: sharer.id, sharedWithId: me.id, inTimeline: true); + await sut.updatePartner(sharedById: sharer.id, sharedWithId: me.id, inTimeline: true); final result = await sut.get(sharedById: sharer.id, sharedWithId: me.id); expect(result.inTimeline, isTrue); @@ -91,7 +91,7 @@ void main() { final recipient = await ctx.newUser(); await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id); - await sut.delete(sharedById: me.id, sharedWithId: recipient.id); + await sut.deletePartner(sharedById: me.id, sharedWithId: recipient.id); final rows = await ctx.db.select(ctx.db.partnerEntity).get(); expect(rows, isEmpty); diff --git a/mobile/test/medium/repositories/people_repository_test.dart b/mobile/test/medium/repositories/people_repository_test.dart index 4b51862a7d..979dd95373 100644 --- a/mobile/test/medium/repositories/people_repository_test.dart +++ b/mobile/test/medium/repositories/people_repository_test.dart @@ -5,11 +5,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftPeopleRepository sut; + late PeopleRepository sut; setUp(() { ctx = MediumRepositoryContext(); - sut = DriftPeopleRepository(ctx.db); + sut = PeopleRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/remote_album_repository_test.dart b/mobile/test/medium/repositories/remote_album_repository_test.dart index 5a82ff315f..b05a687f16 100644 --- a/mobile/test/medium/repositories/remote_album_repository_test.dart +++ b/mobile/test/medium/repositories/remote_album_repository_test.dart @@ -6,11 +6,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftRemoteAlbumRepository sut; + late RemoteAlbumRepository sut; setUp(() async { ctx = MediumRepositoryContext(); - sut = DriftRemoteAlbumRepository(ctx.db); + sut = RemoteAlbumRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/timeline_repository_test.dart b/mobile/test/medium/repositories/timeline_repository_test.dart index 502a65d45b..bc572b0e2f 100644 --- a/mobile/test/medium/repositories/timeline_repository_test.dart +++ b/mobile/test/medium/repositories/timeline_repository_test.dart @@ -7,7 +7,7 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftTimelineRepository sut; + late TimelineRepository sut; setUpAll(() async { await initializeDateFormatting(); @@ -15,7 +15,7 @@ void main() { setUp(() { ctx = MediumRepositoryContext(); - sut = DriftTimelineRepository(ctx.db); + sut = TimelineRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/medium/repositories/trashed_local_asset_repository_test.dart b/mobile/test/medium/repositories/trashed_local_asset_repository_test.dart index 0af09715c7..532502ca3d 100644 --- a/mobile/test/medium/repositories/trashed_local_asset_repository_test.dart +++ b/mobile/test/medium/repositories/trashed_local_asset_repository_test.dart @@ -6,11 +6,11 @@ import '../repository_context.dart'; void main() { late MediumRepositoryContext ctx; - late DriftTrashedLocalAssetRepository sut; + late TrashedLocalAssetRepository sut; setUp(() { ctx = MediumRepositoryContext(); - sut = DriftTrashedLocalAssetRepository(ctx.db); + sut = TrashedLocalAssetRepository(ctx.db); }); tearDown(() async { diff --git a/mobile/test/modules/map/map_theme_override_test.dart b/mobile/test/modules/map/map_theme_override_test.dart index 817ce0c4b1..3ea54bc9b5 100644 --- a/mobile/test/modules/map/map_theme_override_test.dart +++ b/mobile/test/modules/map/map_theme_override_test.dart @@ -32,7 +32,7 @@ void main() { setUp(() async { mapState = const MapState(themeMode: ThemeMode.dark); mapStateNotifier = MockMapStateNotifier(mapState); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); overrides = [ mapStateNotifierProvider.overrideWith(() => mapStateNotifier), localeProvider.overrideWithValue(const Locale("en")), diff --git a/mobile/test/providers/infrastructure/memory_provider_test.dart b/mobile/test/providers/infrastructure/memory_provider_test.dart index e588153fc9..c70ef1c84a 100644 --- a/mobile/test/providers/infrastructure/memory_provider_test.dart +++ b/mobile/test/providers/infrastructure/memory_provider_test.dart @@ -2,18 +2,20 @@ import 'package:fake_async/fake_async.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; -import 'package:immich_mobile/domain/services/memory.service.dart'; import 'package:immich_mobile/domain/services/user.service.dart'; +import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:mocktail/mocktail.dart'; -class MockDriftMemoryService extends Mock implements DriftMemoryService {} +import '../../infrastructure/repository.mock.dart'; class MockUserService extends Mock implements UserService {} void main() { - late MockDriftMemoryService memoryService; + late MockMemoryRepository memoryRepository; late MockUserService userService; UserDto user({bool memoryEnabled = true}) => UserDto( @@ -24,10 +26,16 @@ void main() { profileChangedAt: DateTime(2026), ); + Drift mockDrift(MemoryRepository repository) { + final drift = MockDrift(); + when(() => drift.memoryRepository).thenReturn(repository); + return drift; + } + ProviderContainer makeContainer() { final container = ProviderContainer( overrides: [ - driftMemoryServiceProvider.overrideWithValue(memoryService), + driftProvider.overrideWithValue(mockDrift(memoryRepository)), currentUserProvider.overrideWith((ref) => CurrentUserProvider(userService)), ], ); @@ -36,10 +44,10 @@ void main() { } setUp(() { - memoryService = MockDriftMemoryService(); + memoryRepository = MockMemoryRepository(); userService = MockUserService(); - when(() => memoryService.getMemoryLane('user-1')).thenAnswer((_) async => []); + when(() => memoryRepository.getAll('user-1')).thenAnswer((_) async => []); when(() => userService.tryGetMyUser()).thenReturn(user()); when(() => userService.watchMyUser()).thenAnswer((_) => const Stream.empty()); }); @@ -51,15 +59,15 @@ void main() { container.listen(driftMemoryFutureProvider, (_, __) {}); async.flushMicrotasks(); - verify(() => memoryService.getMemoryLane('user-1')).called(1); + verify(() => memoryRepository.getAll('user-1')).called(1); async.elapse(const Duration(seconds: 4)); async.flushMicrotasks(); - verifyNever(() => memoryService.getMemoryLane('user-1')); + verifyNever(() => memoryRepository.getAll('user-1')); async.elapse(const Duration(hours: 25)); async.flushMicrotasks(); - verify(() => memoryService.getMemoryLane('user-1')).called(greaterThanOrEqualTo(1)); + verify(() => memoryRepository.getAll('user-1')).called(greaterThanOrEqualTo(1)); }); }); @@ -68,13 +76,13 @@ void main() { final container = makeContainer(); final subscription = container.listen(driftMemoryFutureProvider, (_, __) {}); async.flushMicrotasks(); - verify(() => memoryService.getMemoryLane('user-1')).called(1); + verify(() => memoryRepository.getAll('user-1')).called(1); subscription.close(); async.elapse(const Duration(hours: 25)); async.flushMicrotasks(); - verifyNever(() => memoryService.getMemoryLane('user-1')); + verifyNever(() => memoryRepository.getAll('user-1')); }); }); @@ -89,7 +97,7 @@ void main() { async.elapse(const Duration(hours: 25)); async.flushMicrotasks(); - verifyNever(() => memoryService.getMemoryLane(any())); + verifyNever(() => memoryRepository.getAll(any())); }); }); }); diff --git a/mobile/test/services/action.service_test.dart b/mobile/test/services/action.service_test.dart index 2d90e24503..b008ff9bfc 100644 --- a/mobile/test/services/action.service_test.dart +++ b/mobile/test/services/action.service_test.dart @@ -25,7 +25,7 @@ void main() { debugDefaultTargetPlatformOverride = TargetPlatform.android; db = Drift(drift.DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); }); tearDownAll(() async { diff --git a/mobile/test/services/auth.service_test.dart b/mobile/test/services/auth.service_test.dart index b62ad3ad2c..6d79993aa8 100644 --- a/mobile/test/services/auth.service_test.dart +++ b/mobile/test/services/auth.service_test.dart @@ -36,7 +36,7 @@ void main() { setUpAll(() async { WidgetsFlutterBinding.ensureInitialized(); db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); }); tearDownAll(() async { diff --git a/mobile/test/services/background_upload.service_test.dart b/mobile/test/services/background_upload.service_test.dart index aa46bd9de3..2d9b5b1209 100644 --- a/mobile/test/services/background_upload.service_test.dart +++ b/mobile/test/services/background_upload.service_test.dart @@ -25,8 +25,8 @@ void main() { late BackgroundUploadService sut; late MockUploadRepository mockUploadRepository; late MockStorageRepository mockStorageRepository; - late MockDriftLocalAssetRepository mockLocalAssetRepository; - late MockDriftBackupRepository mockBackupRepository; + late MockLocalAssetRepository mockLocalAssetRepository; + late MockBackupRepository mockBackupRepository; late MockAssetMediaRepository mockAssetMediaRepository; late Drift db; @@ -37,7 +37,7 @@ void main() { (MethodCall methodCall) async => 'test', ); db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); await SettingsRepository.ensureInitialized(db); await Store.put(StoreKey.serverEndpoint, 'http://test-server.com'); @@ -47,8 +47,8 @@ void main() { setUp(() { mockUploadRepository = MockUploadRepository(); mockStorageRepository = MockStorageRepository(); - mockLocalAssetRepository = MockDriftLocalAssetRepository(); - mockBackupRepository = MockDriftBackupRepository(); + mockLocalAssetRepository = MockLocalAssetRepository(); + mockBackupRepository = MockBackupRepository(); mockAssetMediaRepository = MockAssetMediaRepository(); sut = BackgroundUploadService( diff --git a/mobile/test/services/cleanup.service_test.dart b/mobile/test/services/cleanup.service_test.dart index 2038941ecb..294b8550ea 100644 --- a/mobile/test/services/cleanup.service_test.dart +++ b/mobile/test/services/cleanup.service_test.dart @@ -9,11 +9,11 @@ import '../repository.mocks.dart'; void main() { late CleanupService sut; - late MockDriftLocalAssetRepository localAssetRepository; + late MockLocalAssetRepository localAssetRepository; late MockAssetMediaRepository assetMediaRepository; setUp(() { - localAssetRepository = MockDriftLocalAssetRepository(); + localAssetRepository = MockLocalAssetRepository(); assetMediaRepository = MockAssetMediaRepository(); sut = CleanupService(localAssetRepository, assetMediaRepository); }); @@ -24,7 +24,7 @@ void main() { expect(result, 0); verifyNever(() => assetMediaRepository.deleteAll(any())); - verifyNever(() => localAssetRepository.delete(any())); + verifyNever(() => localAssetRepository.deleteAssets(any())); }); test('deletes in a single batch when under limit', () async { @@ -33,13 +33,13 @@ void main() { when(() => assetMediaRepository.deleteAll(any())).thenAnswer((invocation) async { return (invocation.positionalArguments.first as List).toList(); }); - when(() => localAssetRepository.delete(any())).thenAnswer((_) async {}); + when(() => localAssetRepository.deleteAssets(any())).thenAnswer((_) async {}); final result = await sut.deleteLocalAssets(ids); expect(result, ids.length); verify(() => assetMediaRepository.deleteAll(ids)).called(1); - verify(() => localAssetRepository.delete(ids)).called(1); + verify(() => localAssetRepository.deleteAssets(ids)).called(1); }); test('deletes in platform-specific batches when over limit', () async { @@ -52,7 +52,7 @@ void main() { capturedBatches.add(batch); return batch; }); - when(() => localAssetRepository.delete(any())).thenAnswer((_) async {}); + when(() => localAssetRepository.deleteAssets(any())).thenAnswer((_) async {}); final result = await sut.deleteLocalAssets(ids); @@ -67,7 +67,7 @@ void main() { expect(capturedBatches[1].last, 'asset-${batchSize * 2 - 1}'); expect(capturedBatches[2].first, 'asset-${batchSize * 2}'); expect(capturedBatches[2].last, 'asset-${batchSize * 2 + 500}'); - verify(() => localAssetRepository.delete(any())).called(3); + verify(() => localAssetRepository.deleteAssets(any())).called(3); }); }); } diff --git a/mobile/test/services/foreground_upload.service_test.dart b/mobile/test/services/foreground_upload.service_test.dart index d4344ed77e..4f0a01dfd0 100644 --- a/mobile/test/services/foreground_upload.service_test.dart +++ b/mobile/test/services/foreground_upload.service_test.dart @@ -24,7 +24,7 @@ void main() { late ForegroundUploadService sut; late MockUploadRepository mockUploadRepository; late MockStorageRepository mockStorageRepository; - late MockDriftBackupRepository mockBackupRepository; + late MockBackupRepository mockBackupRepository; late MockConnectivityApi mockConnectivityApi; late MockAssetMediaRepository mockAssetMediaRepository; late Drift db; @@ -36,7 +36,7 @@ void main() { (MethodCall methodCall) async => 'test', ); db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db)); + await StoreService.init(storeRepository: StoreRepository(db)); await SettingsRepository.ensureInitialized(db); await Store.put(StoreKey.serverEndpoint, 'http://demo.immich.app'); @@ -49,7 +49,7 @@ void main() { setUp(() { mockUploadRepository = MockUploadRepository(); mockStorageRepository = MockStorageRepository(); - mockBackupRepository = MockDriftBackupRepository(); + mockBackupRepository = MockBackupRepository(); mockConnectivityApi = MockConnectivityApi(); mockAssetMediaRepository = MockAssetMediaRepository(); diff --git a/mobile/test/services/view_intent_asset_resolver_test.dart b/mobile/test/services/view_intent_asset_resolver_test.dart index 38d2f71f88..36c343180a 100644 --- a/mobile/test/services/view_intent_asset_resolver_test.dart +++ b/mobile/test/services/view_intent_asset_resolver_test.dart @@ -6,7 +6,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart'; import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/platform/view_intent_api.g.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/services/view_intent_asset_resolver.service.dart'; import 'package:mocktail/mocktail.dart'; @@ -16,13 +16,13 @@ import '../infrastructure/repository.mock.dart'; class MockTimelineFactory extends Mock implements TimelineFactory {} void main() { - late MockDriftLocalAssetRepository mockLocalAssetRepository; + late MockLocalAssetRepository mockLocalAssetRepository; late MockTimelineFactory timelineFactory; late List createdTimelineServices; late ProviderContainer container; setUp(() { - mockLocalAssetRepository = MockDriftLocalAssetRepository(); + mockLocalAssetRepository = MockLocalAssetRepository(); timelineFactory = MockTimelineFactory(); createdTimelineServices = []; @@ -33,9 +33,12 @@ void main() { return timelineService; }); + final drift = MockDrift(); + when(() => drift.localAssetRepository).thenReturn(mockLocalAssetRepository); + container = ProviderContainer( overrides: [ - localAssetRepository.overrideWith((ref) => mockLocalAssetRepository), + driftProvider.overrideWithValue(drift), timelineFactoryProvider.overrideWith((ref) => timelineFactory), ], ); diff --git a/mobile/test/test_utils/medium_factory.dart b/mobile/test/test_utils/medium_factory.dart index c8c41bbf0f..fa40de0160 100644 --- a/mobile/test/test_utils/medium_factory.dart +++ b/mobile/test/test_utils/medium_factory.dart @@ -31,8 +31,8 @@ class MediumFactory { T getRepository() { switch (T) { - case const (DriftLocalAlbumRepository): - return DriftLocalAlbumRepository(_db) as T; + case const (LocalAlbumRepository): + return LocalAlbumRepository(_db) as T; default: throw Exception('Unknown repository: $T'); } diff --git a/mobile/test/unit/mocks.dart b/mobile/test/unit/mocks.dart index 6c41320a85..754c20aa48 100644 --- a/mobile/test/unit/mocks.dart +++ b/mobile/test/unit/mocks.dart @@ -26,7 +26,7 @@ import 'factories/user_factory.dart'; class RepositoryMocks { final localAlbum = LocalAlbumRepositoryStub(MockLocalAlbumRepository()); - final localAsset = LocalAssetRepositoryStub(MockDriftLocalAssetRepository()); + final localAsset = LocalAssetRepositoryStub(MockLocalAssetRepository()); final remoteAsset = RemoteAssetRepositoryStub(MockRemoteAssetRepository()); final remoteExif = RemoteExifRepositoryStub(MockRemoteExifRepository()); final trashedAsset = MockTrashedLocalAssetRepository(); @@ -247,8 +247,8 @@ extension type const LocalAlbumRepositoryStub(MockLocalAlbumRepository repo) imp () => repo.getAssetsToHash(any()); } -extension type const LocalAssetRepositoryStub(MockDriftLocalAssetRepository repo) - implements Stub { +extension type const LocalAssetRepositoryStub(MockLocalAssetRepository repo) + implements Stub { Future Function() get reconcileHashesFromCloudId => () => repo.reconcileHashesFromCloudId(); @@ -265,7 +265,7 @@ extension type const RemoteAssetRepositoryStub(MockRemoteAssetRepository repo) () => repo.getAssetEdits(any()); Future Function() get update => - () => repo.update( + () => repo.updateAssets( any(), isFavorite: any(named: 'isFavorite'), visibility: any(named: 'visibility'), @@ -275,7 +275,7 @@ extension type const RemoteAssetRepositoryStub(MockRemoteAssetRepository repo) extension type const RemoteExifRepositoryStub(MockRemoteExifRepository repo) implements Stub { Future Function() get update => - () => repo.update( + () => repo.updateExif( any(), dateTimeOriginal: any(named: 'dateTimeOriginal'), timeZone: any(named: 'timeZone'), diff --git a/mobile/test/unit/presentation/presentation_context.dart b/mobile/test/unit/presentation/presentation_context.dart index 36ae8d087d..1d46260435 100644 --- a/mobile/test/unit/presentation/presentation_context.dart +++ b/mobile/test/unit/presentation/presentation_context.dart @@ -17,6 +17,7 @@ import 'package:immich_mobile/presentation/actions/action.dart'; import 'package:immich_mobile/presentation/actions/action.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/user.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; @@ -28,6 +29,7 @@ import 'package:immich_mobile/services/server_info.service.dart'; import 'package:immich_ui/immich_ui.dart'; import 'package:mocktail/mocktail.dart'; +import '../../infrastructure/repository.mock.dart'; import '../../test_utils.dart'; import '../factories/user_factory.dart'; import '../mocks.dart'; @@ -49,6 +51,7 @@ class PresentationContext { final RepositoryMocks repository; List get overrides => [ + driftProvider.overrideWithValue(_mockDrift()), currentUserProvider.overrideWith((ref) => CurrentUserProvider(service.user.service)), assetServiceProvider.overrideWithValue(service.asset.service), cleanupServiceProvider.overrideWithValue(service.cleanup.service), @@ -57,10 +60,15 @@ class PresentationContext { gCastServiceProvider.overrideWithValue(service.cast), serverInfoServiceProvider.overrideWithValue(service.serverInfo), inLockedViewProvider.overrideWithValue(false), - remoteAssetRepositoryProvider.overrideWithValue(repository.remoteAsset.repo), assetMediaRepositoryProvider.overrideWithValue(repository.assetMedia.api), ]; + Drift _mockDrift() { + final drift = MockDrift(); + when(() => drift.remoteAssetRepository).thenReturn(repository.remoteAsset.repo); + return drift; + } + List selected(Set assets) => [ multiSelectProvider.overrideWith( () => MultiSelectNotifier(MultiSelectState(selectedAssets: assets, lockedSelectionAssets: const {})), @@ -71,7 +79,7 @@ class PresentationContext { TestUtils.init(); if (_db == null) { final db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db), listenUpdates: false); + await StoreService.init(storeRepository: StoreRepository(db), listenUpdates: false); await StoreService.I.put(StoreKey.serverEndpoint, serverEndpoint); _db = db; } diff --git a/mobile/test/unit/services/asset_service_test.dart b/mobile/test/unit/services/asset_service_test.dart index a09465701b..b857be1fcb 100644 --- a/mobile/test/unit/services/asset_service_test.dart +++ b/mobile/test/unit/services/asset_service_test.dart @@ -22,7 +22,7 @@ void main() { sut = AssetService( remoteRepository: remoteRepository, exifRepository: exifRepository, - localRepository: MockDriftLocalAssetRepository(), + localRepository: MockLocalAssetRepository(), apiRepository: apiRepository, mediaRepository: mocks.assetMedia.api, trashedLocalRepository: mocks.trashedAsset, @@ -37,9 +37,9 @@ void main() { await sut.update(ids, dateTime: const .some(picked)); verify(() => apiRepository.update(ids, dateTimeOriginal: const .some(picked))).called(1); - verify(() => remoteRepository.update(ids, createdAt: .some(DateTime.parse(picked)))).called(1); + verify(() => remoteRepository.updateAssets(ids, createdAt: .some(DateTime.parse(picked)))).called(1); verify( - () => exifRepository.update( + () => exifRepository.updateExif( ids, dateTimeOriginal: .some(DateTime.parse(picked)), timeZone: const .some('UTC+06:00'), @@ -51,9 +51,9 @@ void main() { const picked = '2026-01-05T08:00:00.000-05:30'; await sut.update(ids, dateTime: const .some(picked)); - verify(() => remoteRepository.update(ids, createdAt: .some(DateTime.parse(picked)))).called(1); + verify(() => remoteRepository.updateAssets(ids, createdAt: .some(DateTime.parse(picked)))).called(1); verify( - () => exifRepository.update( + () => exifRepository.updateExif( ids, dateTimeOriginal: .some(DateTime.parse(picked)), timeZone: const .some('UTC-05:30'), @@ -65,9 +65,9 @@ void main() { const picked = '2026-06-10T13:15:00.000Z'; await sut.update(ids, dateTime: const .some(picked)); - verify(() => remoteRepository.update(ids, createdAt: .some(DateTime.parse(picked)))).called(1); + verify(() => remoteRepository.updateAssets(ids, createdAt: .some(DateTime.parse(picked)))).called(1); verify( - () => exifRepository.update(ids, dateTimeOriginal: .some(DateTime.parse(picked)), timeZone: const .none()), + () => exifRepository.updateExif(ids, dateTimeOriginal: .some(DateTime.parse(picked)), timeZone: const .none()), ).called(1); }); diff --git a/mobile/test/utils/image_url_builder_test.dart b/mobile/test/utils/image_url_builder_test.dart index 1845d38eeb..055af185f7 100644 --- a/mobile/test/utils/image_url_builder_test.dart +++ b/mobile/test/utils/image_url_builder_test.dart @@ -12,7 +12,7 @@ void main() { setUpAll(() async { final db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); - await StoreService.init(storeRepository: DriftStoreRepository(db), listenUpdates: false); + await StoreService.init(storeRepository: StoreRepository(db), listenUpdates: false); await StoreService.I.put(StoreKey.serverEndpoint, endpoint); });