mirror of
https://github.com/immich-app/immich.git
synced 2025-01-12 15:32:36 +02:00
fix(mobile): asset deletion state management (#4568)
This commit is contained in:
parent
aefd052888
commit
52e09b4857
@ -2,9 +2,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/modules/trash/services/trash.service.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/models/exif_info.dart';
|
||||
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/shared/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/shared/services/sync.service.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
@ -28,19 +28,18 @@ class TrashNotifier extends StateNotifier<bool> {
|
||||
}
|
||||
await _trashService.emptyTrash();
|
||||
|
||||
final dbIds = await _db.assets
|
||||
final idsToRemove = await _db.assets
|
||||
.where()
|
||||
.remoteIdIsNotNull()
|
||||
.filter()
|
||||
.ownerIdEqualTo(user.isarId)
|
||||
.isTrashedEqualTo(true)
|
||||
.idProperty()
|
||||
.remoteIdProperty()
|
||||
.findAll();
|
||||
|
||||
await _db.writeTxn(() async {
|
||||
await _db.exifInfos.deleteAll(dbIds);
|
||||
await _db.assets.deleteAll(dbIds);
|
||||
});
|
||||
_ref
|
||||
.read(syncServiceProvider)
|
||||
.handleRemoteAssetRemoval(idsToRemove.cast<String>().toList());
|
||||
} catch (error, stack) {
|
||||
_log.severe("Cannot empty trash ${error.toString()}", error, stack);
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ class AssetNotifier extends StateNotifier<bool> {
|
||||
|
||||
Future<bool> deleteAssets(
|
||||
Iterable<Asset> deleteAssets, {
|
||||
bool? force = false,
|
||||
bool force = false,
|
||||
}) async {
|
||||
_deleteInProgress = true;
|
||||
state = true;
|
||||
@ -102,25 +102,69 @@ class AssetNotifier extends StateNotifier<bool> {
|
||||
final localDeleted = await _deleteLocalAssets(deleteAssets);
|
||||
final remoteDeleted = await _deleteRemoteAssets(deleteAssets, force);
|
||||
if (localDeleted.isNotEmpty || remoteDeleted.isNotEmpty) {
|
||||
List<Asset>? assetsToUpdate;
|
||||
// Local only assets are permanently deleted for now. So always remove them from db
|
||||
final dbIds = deleteAssets
|
||||
.where((a) => a.isLocal && !a.isRemote)
|
||||
.map((e) => e.id)
|
||||
.toList();
|
||||
if (force == null || !force) {
|
||||
assetsToUpdate = remoteDeleted.map((e) {
|
||||
e.isTrashed = true;
|
||||
return e;
|
||||
}).toList();
|
||||
} else {
|
||||
// Add all remote assets to be deleted from isar as since they are permanently deleted
|
||||
dbIds.addAll(remoteDeleted.map((e) => e.id));
|
||||
}
|
||||
await _db.writeTxn(() async {
|
||||
if (assetsToUpdate != null) {
|
||||
await _db.assets.putAll(assetsToUpdate);
|
||||
final dbIds = <int>[];
|
||||
final dbUpdates = <Asset>[];
|
||||
|
||||
// Local assets are removed
|
||||
if (localDeleted.isNotEmpty) {
|
||||
// Permanently remove local only assets from isar
|
||||
dbIds.addAll(
|
||||
deleteAssets
|
||||
.where((a) => a.storage == AssetState.local)
|
||||
.map((e) => e.id),
|
||||
);
|
||||
|
||||
if (remoteDeleted.any((e) => e.isLocal)) {
|
||||
// Force delete: Add all local assets including merged assets
|
||||
if (force) {
|
||||
dbIds.addAll(remoteDeleted.map((e) => e.id));
|
||||
// Soft delete: Remove local Id from asset and trash it
|
||||
} else {
|
||||
dbUpdates.addAll(
|
||||
remoteDeleted.map((e) {
|
||||
e.localId = null;
|
||||
e.isTrashed = true;
|
||||
return e;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle remote deletion
|
||||
if (remoteDeleted.isNotEmpty) {
|
||||
if (force) {
|
||||
// Remove remote only assets
|
||||
dbIds.addAll(
|
||||
deleteAssets
|
||||
.where((a) => a.storage == AssetState.remote)
|
||||
.map((e) => e.id),
|
||||
);
|
||||
// Local assets are not removed and there are merged assets
|
||||
final hasLocal = remoteDeleted.any((e) => e.isLocal);
|
||||
if (localDeleted.isEmpty && hasLocal) {
|
||||
// Remove remote Id from local assets
|
||||
dbUpdates.addAll(
|
||||
remoteDeleted.map((e) {
|
||||
e.remoteId = null;
|
||||
// Remove from trashed if remote asset is removed
|
||||
e.isTrashed = false;
|
||||
return e;
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
dbUpdates.addAll(
|
||||
remoteDeleted.map((e) {
|
||||
e.isTrashed = true;
|
||||
return e;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await _db.writeTxn(() async {
|
||||
await _db.assets.putAll(dbUpdates);
|
||||
await _db.exifInfos.deleteAll(dbIds);
|
||||
await _db.assets.deleteAll(dbIds);
|
||||
});
|
||||
|
@ -173,7 +173,14 @@ class SyncService {
|
||||
/// Deletes remote-only assets, updates merged assets to be local-only
|
||||
Future<void> handleRemoteAssetRemoval(List<String> idsToDelete) {
|
||||
return _db.writeTxn(() async {
|
||||
await _db.assets.remote(idsToDelete).filter().localIdIsNull().deleteAll();
|
||||
final idsToRemove = await _db.assets
|
||||
.remote(idsToDelete)
|
||||
.filter()
|
||||
.localIdIsNull()
|
||||
.idProperty()
|
||||
.findAll();
|
||||
await _db.assets.deleteAll(idsToRemove);
|
||||
await _db.exifInfos.deleteAll(idsToRemove);
|
||||
final onlyLocal = await _db.assets.remote(idsToDelete).findAll();
|
||||
if (onlyLocal.isNotEmpty) {
|
||||
for (final Asset a in onlyLocal) {
|
||||
|
Loading…
Reference in New Issue
Block a user