diff --git a/mobile/lib/providers/asset.provider.dart b/mobile/lib/providers/asset.provider.dart index c7e75df79b..5c9b716691 100644 --- a/mobile/lib/providers/asset.provider.dart +++ b/mobile/lib/providers/asset.provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; @@ -14,6 +15,7 @@ import 'package:immich_mobile/services/sync.service.dart'; import 'package:immich_mobile/services/user.service.dart'; import 'package:immich_mobile/utils/db.dart'; import 'package:immich_mobile/utils/renderlist_generator.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; @@ -78,27 +80,48 @@ class AssetNotifier extends StateNotifier { } Future deleteLocalOnlyAssets( + BuildContext context, Iterable deleteAssets, { bool onlyBackedUp = false, }) async { _deleteInProgress = true; state = true; try { + // Filter local assets based on the backup status (`isRemote`). + // If `onlyBackedUp` is true, only select assets that are also present on the server (`isRemote`). + final assetsToDelete = deleteAssets + .where((e) => e.isLocal && (!onlyBackedUp || e.isRemote)) + .toList(); + + if (assetsToDelete.isEmpty) { + // No assets to delete, exit early + ImmichToast.show( + context: context, + msg: 'No backed-up assets selected for deletion.', + gravity: ToastGravity.BOTTOM, + ); + return false; + } + + // Continue with deletion of the filtered assets final assets = onlyBackedUp - ? deleteAssets.where((e) => e.storage == AssetState.merged) - : deleteAssets; + ? assetsToDelete.where((e) => e.storage == AssetState.merged) + : assetsToDelete; + final localDeleted = await _deleteLocalAssets(assets); if (localDeleted.isNotEmpty) { - final localOnlyIds = deleteAssets + final localOnlyIds = assetsToDelete .where((e) => e.storage == AssetState.local) .map((e) => e.id) .toList(); // Update merged assets to remote only - final mergedAssets = - deleteAssets.where((e) => e.storage == AssetState.merged).map((e) { + final mergedAssets = assetsToDelete + .where((e) => e.storage == AssetState.merged) + .map((e) { e.localId = null; return e; }).toList(); + await _db.writeTxn(() async { if (mergedAssets.isNotEmpty) { await _db.assets.putAll(mergedAssets); diff --git a/mobile/lib/widgets/asset_grid/multiselect_grid.dart b/mobile/lib/widgets/asset_grid/multiselect_grid.dart index a672f3c22f..af3ccd72cb 100644 --- a/mobile/lib/widgets/asset_grid/multiselect_grid.dart +++ b/mobile/lib/widgets/asset_grid/multiselect_grid.dart @@ -204,25 +204,11 @@ class MultiselectGrid extends HookConsumerWidget { void onDeleteLocal(bool onlyBackedUp) async { processing.value = true; try { - // Filter local assets based on the backup status (`isRemote`). - // If `onlyBackedUp` is true, only select assets that are also present on the server (`isRemote`). - final localIds = selection.value - .where((a) => a.isLocal && (!onlyBackedUp || a.isRemote)) - .toList(); - - if (localIds.isEmpty) { - ImmichToast.show( - context: context, - msg: 'No backed-up assets selected for deletion.', - gravity: ToastGravity.BOTTOM, - ); - return; - } - - // Proceed with deletion of filtered assets + final localIds = selection.value.where((a) => a.isLocal).toList(); final isDeleted = await ref .read(assetProvider.notifier) - .deleteLocalOnlyAssets(localIds, onlyBackedUp: onlyBackedUp); + .deleteLocalOnlyAssets(context, localIds, + onlyBackedUp: onlyBackedUp); if (isDeleted) { ImmichToast.show(