mobile: add backed up only toggle for delete device only
This commit is contained in:
parent
3d7c13b30f
commit
5219f55b6a
5 changed files with 112 additions and 36 deletions
|
@ -144,6 +144,7 @@
|
|||
"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_merged_only": "Delete only backed up assets",
|
||||
"delete_dialog_cancel": "Cancel",
|
||||
"delete_dialog_ok": "Delete",
|
||||
"delete_dialog_title": "Delete Permanently",
|
||||
|
|
|
@ -16,7 +16,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;
|
||||
|
@ -47,7 +47,8 @@ class ControlBottomAppBar extends ConsumerWidget {
|
|||
var isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
||||
var hasRemote = selectionAssetState == AssetState.remote ||
|
||||
selectionAssetState == AssetState.merged;
|
||||
var hasMerged = selectionAssetState == AssetState.merged;
|
||||
var hasLocal = selectionAssetState == AssetState.merged ||
|
||||
selectionAssetState == AssetState.local;
|
||||
final trashEnabled =
|
||||
ref.watch(serverInfoProvider.select((v) => v.serverFeatures.trash));
|
||||
|
||||
|
@ -72,6 +73,7 @@ class ControlBottomAppBar extends ConsumerWidget {
|
|||
label: "control_bottom_app_bar_favorite".tr(),
|
||||
onPressed: enabled ? onFavorite : null,
|
||||
),
|
||||
if (hasRemote)
|
||||
ControlBoxButton(
|
||||
iconData: Icons.delete_outline_rounded,
|
||||
label: "control_bottom_app_bar_delete".tr(),
|
||||
|
@ -92,7 +94,7 @@ class ControlBottomAppBar extends ConsumerWidget {
|
|||
}
|
||||
: null,
|
||||
),
|
||||
if (hasMerged)
|
||||
if (hasLocal)
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 100),
|
||||
child: ControlBoxButton(
|
||||
|
@ -103,8 +105,7 @@ class ControlBottomAppBar extends ConsumerWidget {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DeleteDialog(
|
||||
content: 'delete_dialog_alert_local',
|
||||
return DeleteLocalDialog(
|
||||
onDelete: onDeleteLocal,
|
||||
);
|
||||
},
|
||||
|
@ -161,7 +162,7 @@ class ControlBottomAppBar extends ConsumerWidget {
|
|||
const CustomDraggingHandle(),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: hasMerged ? 90 : 75,
|
||||
height: hasLocal ? 90 : 75,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: renderActionButtons(),
|
||||
|
|
|
@ -1,16 +1,86 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
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})
|
||||
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: "delete_dialog_ok",
|
||||
onOk: onDelete,
|
||||
);
|
||||
}
|
||||
|
||||
class DeleteLocalDialog extends HookConsumerWidget {
|
||||
final Function(bool onlyMerged) onDelete;
|
||||
|
||||
const DeleteLocalDialog({
|
||||
Key? key,
|
||||
required this.onDelete,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final themeData = Theme.of(context);
|
||||
final onlyMerged = useState(true);
|
||||
|
||||
return AlertDialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
title: const Text("delete_dialog_title").tr(),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text("delete_dialog_alert_local").tr(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
child: SwitchListTile.adaptive(
|
||||
value: onlyMerged.value,
|
||||
onChanged: (value) {
|
||||
onlyMerged.value = value;
|
||||
},
|
||||
activeColor: themeData.primaryColor,
|
||||
dense: true,
|
||||
title: Text(
|
||||
"delete_dialog_alert_merged_only",
|
||||
style: themeData.textTheme.labelLarge
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: Text(
|
||||
"delete_dialog_cancel",
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
onDelete(onlyMerged.value);
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: Text(
|
||||
"delete_dialog_ok",
|
||||
style: TextStyle(
|
||||
color: Colors.red[400],
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,22 +163,20 @@ class HomePage extends HookConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
void onDeleteLocal() async {
|
||||
void onDeleteLocal(bool onlyMerged) async {
|
||||
processing.value = true;
|
||||
try {
|
||||
final mergedIds = selection.value
|
||||
.where((a) => a.storage == AssetState.merged)
|
||||
.toList();
|
||||
final localIds = selection.value.where((a) => a.isLocal).toList();
|
||||
|
||||
final isDeleted = await ref
|
||||
.read(assetProvider.notifier)
|
||||
.deleteLocalAssets(mergedIds);
|
||||
.deleteLocalAssets(localIds, onlyMerged: onlyMerged);
|
||||
if (isDeleted) {
|
||||
final assetOrAssets = mergedIds.length > 1 ? 'assets' : 'asset';
|
||||
final assetOrAssets = localIds.length > 1 ? 'assets' : 'asset';
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg:
|
||||
'${mergedIds.length} $assetOrAssets removed permanently from your device',
|
||||
'${localIds.length} $assetOrAssets removed permanently from your device',
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -91,11 +91,17 @@ class AssetNotifier extends StateNotifier<bool> {
|
|||
await _syncService.syncNewAssetToDb(newAsset);
|
||||
}
|
||||
|
||||
Future<bool> deleteLocalAssets(Iterable<Asset> deleteAssets) async {
|
||||
Future<bool> deleteLocalAssets(
|
||||
Iterable<Asset> deleteAssets, {
|
||||
bool onlyMerged = true,
|
||||
}) 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)
|
||||
|
|
Loading…
Reference in a new issue