mirror of
https://github.com/immich-app/immich.git
synced 2025-12-16 09:13:13 +03:00
refactor(mobile): asset provider (#16159)
* refactor(mobile): asset provider * wip * wip: delete local assets * wip: delete remote assets * wip: deletion logic * refactor * pr feedback
This commit is contained in:
@@ -9,6 +9,7 @@ import 'package:immich_mobile/entities/backup_album.entity.dart';
|
||||
import 'package:immich_mobile/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/asset_api.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/asset_media.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/backup.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/etag.interface.dart';
|
||||
import 'package:immich_mobile/interfaces/exif_info.interface.dart';
|
||||
@@ -17,6 +18,7 @@ import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||
import 'package:immich_mobile/repositories/asset_media.repository.dart';
|
||||
import 'package:immich_mobile/repositories/backup.repository.dart';
|
||||
import 'package:immich_mobile/repositories/etag.repository.dart';
|
||||
import 'package:immich_mobile/repositories/exif_info.repository.dart';
|
||||
@@ -43,6 +45,7 @@ final assetServiceProvider = Provider(
|
||||
ref.watch(userServiceProvider),
|
||||
ref.watch(backupServiceProvider),
|
||||
ref.watch(albumServiceProvider),
|
||||
ref.watch(assetMediaRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -58,6 +61,7 @@ class AssetService {
|
||||
final UserService _userService;
|
||||
final BackupService _backupService;
|
||||
final AlbumService _albumService;
|
||||
final IAssetMediaRepository _assetMediaRepository;
|
||||
final log = Logger('AssetService');
|
||||
|
||||
AssetService(
|
||||
@@ -72,6 +76,7 @@ class AssetService {
|
||||
this._userService,
|
||||
this._backupService,
|
||||
this._albumService,
|
||||
this._assetMediaRepository,
|
||||
);
|
||||
|
||||
/// Checks the server for updated assets and updates the local database if
|
||||
@@ -158,30 +163,6 @@ class AssetService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> deleteAssets(
|
||||
Iterable<Asset> deleteAssets, {
|
||||
bool? force = false,
|
||||
}) async {
|
||||
try {
|
||||
final List<String> payload = [];
|
||||
|
||||
for (final asset in deleteAssets) {
|
||||
payload.add(asset.remoteId!);
|
||||
}
|
||||
|
||||
await _apiService.assetsApi.deleteAssets(
|
||||
AssetBulkDeleteDto(
|
||||
ids: payload,
|
||||
force: force,
|
||||
),
|
||||
);
|
||||
return true;
|
||||
} catch (error, stack) {
|
||||
log.severe("Error while deleting assets", error, stack);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Loads the exif information from the database. If there is none, loads
|
||||
/// the exif info from the server (remote assets only)
|
||||
Future<Asset> loadExif(Asset a) async {
|
||||
@@ -432,4 +413,105 @@ class AssetService {
|
||||
Future<List<Asset>> getStackAssets(String stackId) {
|
||||
return _assetRepository.getStackAssets(stackId);
|
||||
}
|
||||
|
||||
Future<void> clearTable() {
|
||||
return _assetRepository.clearTable();
|
||||
}
|
||||
|
||||
/// Delete assets from local file system and unreference from the database
|
||||
Future<void> deleteLocalAssets(Iterable<Asset> assets) async {
|
||||
// Delete files from local gallery
|
||||
final candidates = assets.where((asset) => asset.isLocal);
|
||||
|
||||
final deletedIds = await _assetMediaRepository
|
||||
.deleteAll(candidates.map((asset) => asset.localId!).toList());
|
||||
|
||||
// Modify local database by removing the reference to the local assets
|
||||
if (deletedIds.isNotEmpty) {
|
||||
// Delete records from local database
|
||||
final isarIds = assets
|
||||
.where((asset) => asset.storage == AssetState.local)
|
||||
.map((asset) => asset.id)
|
||||
.toList();
|
||||
await _assetRepository.deleteByIds(isarIds);
|
||||
|
||||
// Modify Merged asset to be remote only
|
||||
final updatedAssets = assets
|
||||
.where((asset) => asset.storage == AssetState.merged)
|
||||
.map((asset) {
|
||||
asset.localId = null;
|
||||
return asset;
|
||||
}).toList();
|
||||
|
||||
await _assetRepository.updateAll(updatedAssets);
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete assets from the server and unreference from the database
|
||||
Future<void> deleteRemoteAssets(
|
||||
Iterable<Asset> assets, {
|
||||
bool shouldDeletePermanently = false,
|
||||
}) async {
|
||||
final candidates = assets.where((a) => a.isRemote);
|
||||
if (candidates.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
await _apiService.assetsApi.deleteAssets(
|
||||
AssetBulkDeleteDto(
|
||||
ids: candidates.map((a) => a.remoteId!).toList(),
|
||||
force: shouldDeletePermanently,
|
||||
),
|
||||
);
|
||||
|
||||
/// Update asset info bassed on the deletion type.
|
||||
final payload = shouldDeletePermanently
|
||||
? assets
|
||||
.where((asset) => asset.storage == AssetState.merged)
|
||||
.map((asset) {
|
||||
asset.remoteId = null;
|
||||
return asset;
|
||||
})
|
||||
: assets.where((asset) => asset.isRemote).map((asset) {
|
||||
asset.isTrashed = true;
|
||||
return asset;
|
||||
});
|
||||
|
||||
await _assetRepository.transaction(() async {
|
||||
await _assetRepository.updateAll(payload.toList());
|
||||
|
||||
if (shouldDeletePermanently) {
|
||||
final remoteAssetIds = assets
|
||||
.where((asset) => asset.storage == AssetState.remote)
|
||||
.map((asset) => asset.id)
|
||||
.toList();
|
||||
await _assetRepository.deleteByIds(remoteAssetIds);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Delete assets on both local file system and the server.
|
||||
/// Unreference from the database.
|
||||
Future<void> deleteAssets(
|
||||
Iterable<Asset> assets, {
|
||||
bool shouldDeletePermanently = false,
|
||||
}) async {
|
||||
final hasLocal = assets.any((asset) => asset.isLocal);
|
||||
final hasRemote = assets.any((asset) => asset.isRemote);
|
||||
|
||||
if (hasLocal) {
|
||||
await deleteLocalAssets(assets);
|
||||
}
|
||||
|
||||
if (hasRemote) {
|
||||
await deleteRemoteAssets(
|
||||
assets,
|
||||
shouldDeletePermanently: shouldDeletePermanently,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<Asset?> watchAsset(int id, {bool fireImmediately = false}) {
|
||||
return _assetRepository.watchAsset(id, fireImmediately: fireImmediately);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user