diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 3cef6acb2..e0a09eb63 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -147,11 +147,12 @@ "daily_title_text_date_year": "E, MMM dd, yyyy", "date_format": "E, LLL d, y • h:mm a", "delete_dialog_alert": "These items will be permanently deleted from Immich and from your device", - "delete_dialog_alert_local": "These items will be permanently removed from your device", + "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", "delete_dialog_cancel": "Cancel", "delete_dialog_ok": "Delete", - "delete_dialog_ok_force": "Delete Anyway", + "delete_local_dialog_ok_force": "Delete Anyway", + "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", "delete_dialog_title": "Delete Permanently", "delete_shared_link_dialog_content": "Are you sure you want to delete this shared link?", "delete_shared_link_dialog_title": "Delete Shared Link", diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 3ee26642d..8b8c1d245 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart @@ -15,7 +15,7 @@ class ControlBottomAppBar extends ConsumerWidget { final void Function() onFavorite; final void Function() onArchive; final void Function() onDelete; - final void Function() onDeleteLocal; + final void Function(bool onlyMerged) onDeleteLocal; final Function(Album album) onAddToAlbum; final void Function() onCreateNewAlbum; final void Function() onUpload; @@ -109,17 +109,9 @@ class ControlBottomAppBar extends ConsumerWidget { showDialog( context: context, builder: (BuildContext context) { - return DeleteDialog( - content: selectionAssetState.hasLocal - ? "delete_dialog_alert_local_non_backed_up" - : "delete_dialog_alert_local", - ok: selectionAssetState.hasLocal - ? "delete_dialog_ok_force" - : "delete_dialog_ok", - onDelete: onDeleteLocal, - contentColor: selectionAssetState.hasLocal - ? Colors.red[400] - : null, + return DeleteLocalOnlyDialog( + showWarning: selectionAssetState.hasLocal, + onDeleteLocal: onDeleteLocal, ); }, ); @@ -218,6 +210,69 @@ class ControlBottomAppBar extends ConsumerWidget { } } +class DeleteLocalOnlyDialog extends StatelessWidget { + final bool showWarning; + final void Function(bool onlyMerged) onDeleteLocal; + + const DeleteLocalOnlyDialog({ + super.key, + this.showWarning = false, + required this.onDeleteLocal, + }); + + @override + Widget build(BuildContext context) { + return AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + title: const Text("delete_dialog_title").tr(), + content: Text( + showWarning + ? "delete_dialog_alert_local_non_backed_up" + : "delete_dialog_alert_local", + ).tr(), + actions: [ + TextButton( + onPressed: () => context.pop(false), + child: Text( + "delete_dialog_cancel", + style: TextStyle( + color: context.primaryColor, + fontWeight: FontWeight.bold, + ), + ).tr(), + ), + if (showWarning) + TextButton( + onPressed: () { + context.pop(true); + onDeleteLocal(true); + }, + child: Text( + "delete_local_dialog_ok_backed_up_only", + style: TextStyle( + color: showWarning ? null : Colors.red[400], + fontWeight: FontWeight.bold, + ), + ).tr(), + ), + TextButton( + onPressed: () { + context.pop(true); + onDeleteLocal(false); + }, + child: Text( + showWarning ? "delete_local_dialog_ok_force" : "delete_dialog_ok", + style: TextStyle( + color: Colors.red[400], + fontWeight: FontWeight.bold, + ), + ).tr(), + ), + ], + ); + } +} + class AddToAlbumTitleRow extends StatelessWidget { const AddToAlbumTitleRow({ super.key, diff --git a/mobile/lib/modules/home/ui/delete_dialog.dart b/mobile/lib/modules/home/ui/delete_dialog.dart index 3b97a674d..7d290cd1a 100644 --- a/mobile/lib/modules/home/ui/delete_dialog.dart +++ b/mobile/lib/modules/home/ui/delete_dialog.dart @@ -4,19 +4,13 @@ import 'package:immich_mobile/shared/ui/confirm_dialog.dart'; class DeleteDialog extends ConfirmDialog { final Function onDelete; - const DeleteDialog({ - Key? key, - required this.onDelete, - String? content, - String? ok, - Color? contentColor, - }) : super( + const DeleteDialog({Key? key, required this.onDelete}) + : super( key: key, title: "delete_dialog_title", - content: content ?? "delete_dialog_alert", + content: "delete_dialog_alert", cancel: "delete_dialog_cancel", - ok: ok ?? "delete_dialog_ok", + ok: "delete_dialog_ok", onOk: onDelete, - contentColor: contentColor, ); } diff --git a/mobile/lib/modules/home/views/home_page.dart b/mobile/lib/modules/home/views/home_page.dart index 64cb36791..cc43f633b 100644 --- a/mobile/lib/modules/home/views/home_page.dart +++ b/mobile/lib/modules/home/views/home_page.dart @@ -163,14 +163,14 @@ class HomePage extends HookConsumerWidget { } } - void onDeleteLocal() async { + void onDeleteLocal(bool onlyMerged) async { processing.value = true; try { final localIds = selection.value.where((a) => a.isLocal).toList(); final isDeleted = await ref .read(assetProvider.notifier) - .deleteLocalAssets(localIds); + .deleteLocalAssets(localIds, onlyMerged: onlyMerged); if (isDeleted) { final assetOrAssets = localIds.length > 1 ? 'assets' : 'asset'; ImmichToast.show( diff --git a/mobile/lib/shared/providers/asset.provider.dart b/mobile/lib/shared/providers/asset.provider.dart index 6dd88608f..b5179f33c 100644 --- a/mobile/lib/shared/providers/asset.provider.dart +++ b/mobile/lib/shared/providers/asset.provider.dart @@ -92,11 +92,17 @@ class AssetNotifier extends StateNotifier { await _syncService.syncNewAssetToDb(newAsset); } - Future deleteLocalAssets(Iterable deleteAssets) async { + Future deleteLocalAssets( + Iterable deleteAssets, { + bool onlyMerged = false, + }) async { _deleteInProgress = true; state = true; try { - final localDeleted = await _deleteLocalAssets(deleteAssets); + final assets = onlyMerged + ? deleteAssets.where((e) => e.storage == AssetState.merged) + : deleteAssets; + final localDeleted = await _deleteLocalAssets(assets); if (localDeleted.isNotEmpty) { final localOnlyIds = deleteAssets .where((e) => e.storage == AssetState.local) diff --git a/mobile/lib/shared/ui/confirm_dialog.dart b/mobile/lib/shared/ui/confirm_dialog.dart index 1fd255a15..8ae0b346c 100644 --- a/mobile/lib/shared/ui/confirm_dialog.dart +++ b/mobile/lib/shared/ui/confirm_dialog.dart @@ -6,7 +6,6 @@ class ConfirmDialog extends StatelessWidget { final Function onOk; final String title; final String content; - final Color? contentColor; final String cancel; final String ok; @@ -17,7 +16,6 @@ class ConfirmDialog extends StatelessWidget { required this.content, this.cancel = "delete_dialog_cancel", this.ok = "backup_controller_page_background_battery_info_ok", - this.contentColor, }) : super(key: key); @override @@ -25,10 +23,7 @@ class ConfirmDialog extends StatelessWidget { return AlertDialog( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), title: Text(title).tr(), - content: Text( - content, - style: TextStyle(color: contentColor), - ).tr(), + content: Text(content).tr(), actions: [ TextButton( onPressed: () => context.pop(false),