From e7821d605db35e19425c0ce8b2d38a9b66f2da36 Mon Sep 17 00:00:00 2001 From: Vishnu Mohandas Date: Tue, 1 Dec 2020 19:32:36 +0530 Subject: [PATCH] Add option to delete file from just the device --- lib/ui/detail_page.dart | 43 ++++++++++++++----- lib/ui/gallery_app_bar_widget.dart | 68 +++++++++++++++++++++--------- lib/utils/file_util.dart | 31 +++++++++++++- 3 files changed, 111 insertions(+), 31 deletions(-) diff --git a/lib/ui/detail_page.dart b/lib/ui/detail_page.dart index eefeb5d0c..662dee3d0 100644 --- a/lib/ui/detail_page.dart +++ b/lib/ui/detail_page.dart @@ -319,17 +319,41 @@ class _DetailPageState extends State { } void _showDeleteSheet() { - final action = CupertinoActionSheet( - title: Text("Delete file?"), - actions: [ - CupertinoActionSheetAction( - child: Text("Delete"), + final fileToBeDeleted = _files[_selectedIndex]; + final actions = List(); + if (fileToBeDeleted.uploadedFileID == null) { + actions.add(CupertinoActionSheetAction( + child: Text("Everywhere"), + isDestructiveAction: true, + onPressed: () async { + await deleteFilesFromEverywhere(context, [fileToBeDeleted]); + _onFileDeleted(); + }, + )); + } else { + if (fileToBeDeleted.localID != null) { + actions.add(CupertinoActionSheetAction( + child: Text("On this device"), isDestructiveAction: true, onPressed: () async { - await _delete(); + await deleteFilesOnDeviceOnly(context, [fileToBeDeleted]); + showToast("File deleted from device"); + Navigator.of(context, rootNavigator: true).pop(); }, - ), - ], + )); + } + actions.add(CupertinoActionSheetAction( + child: Text("Everywhere"), + isDestructiveAction: true, + onPressed: () async { + await deleteFilesFromEverywhere(context, [fileToBeDeleted]); + _onFileDeleted(); + }, + )); + } + final action = CupertinoActionSheet( + title: Text("Delete file?"), + actions: actions, cancelButton: CupertinoActionSheetAction( child: Text("Cancel"), onPressed: () { @@ -340,9 +364,8 @@ class _DetailPageState extends State { showCupertinoModalPopup(context: context, builder: (_) => action); } - Future _delete() async { + Future _onFileDeleted() async { final file = _files[_selectedIndex]; - await deleteFilesFromEverywhere([file]); final totalFiles = _files.length; if (totalFiles == 1) { // Deleted the only file diff --git a/lib/ui/gallery_app_bar_widget.dart b/lib/ui/gallery_app_bar_widget.dart index e2f670a41..845291f52 100644 --- a/lib/ui/gallery_app_bar_widget.dart +++ b/lib/ui/gallery_app_bar_widget.dart @@ -15,6 +15,7 @@ import 'package:photos/ui/share_collection_widget.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/file_util.dart'; import 'package:photos/utils/share_util.dart'; +import 'package:photos/utils/toast_util.dart'; enum GalleryAppBarType { homepage, @@ -284,20 +285,56 @@ class _GalleryAppBarWidgetState extends State { void _showDeleteSheet(BuildContext context) { final count = widget.selectedFiles.files.length; + bool containsUploadedFile = false; + for (final file in widget.selectedFiles.files) { + if (file.uploadedFileID != null) { + containsUploadedFile = true; + } + } + final actions = List(); + if (containsUploadedFile) { + actions.add(CupertinoActionSheetAction( + child: Text("This Device"), + isDestructiveAction: true, + onPressed: () async { + await deleteFilesOnDeviceOnly( + context, widget.selectedFiles.files.toList()); + _clearSelectedFiles(); + showToast("Files deleted from device"); + Navigator.of(context, rootNavigator: true).pop(); + }, + )); + actions.add(CupertinoActionSheetAction( + child: Text("Everywhere"), + isDestructiveAction: true, + onPressed: () async { + await deleteFilesFromEverywhere( + context, widget.selectedFiles.files.toList()); + _clearSelectedFiles(); + showToast("Files deleted from everywhere"); + Navigator.of(context, rootNavigator: true).pop(); + }, + )); + } else { + actions.add(CupertinoActionSheetAction( + child: Text("Delete forever"), + isDestructiveAction: true, + onPressed: () async { + await deleteFilesFromEverywhere( + context, widget.selectedFiles.files.toList()); + _clearSelectedFiles(); + showToast("Files deleted from everywhere"); + Navigator.of(context, rootNavigator: true).pop(); + }, + )); + } final action = CupertinoActionSheet( - title: Text("Permanently delete " + + title: Text("Delete " + count.toString() + " file" + - (count == 1 ? "?" : "s?")), - actions: [ - CupertinoActionSheetAction( - child: Text("Delete"), - isDestructiveAction: true, - onPressed: () async { - await _deleteSelected(); - }, - ), - ], + (count == 1 ? "" : "s") + + (containsUploadedFile ? " from" : "?")), + actions: actions, cancelButton: CupertinoActionSheetAction( child: Text("Cancel"), onPressed: () { @@ -308,15 +345,6 @@ class _GalleryAppBarWidgetState extends State { showCupertinoModalPopup(context: context, builder: (_) => action); } - _deleteSelected() async { - Navigator.of(context, rootNavigator: true).pop(); - final dialog = createProgressDialog(context, "Deleting..."); - await dialog.show(); - await deleteFilesFromEverywhere(widget.selectedFiles.files.toList()); - _clearSelectedFiles(); - await dialog.hide(); - } - void _clearSelectedFiles() { widget.selectedFiles.clearAll(); } diff --git a/lib/utils/file_util.dart b/lib/utils/file_util.dart index 729d96414..0d9a50234 100644 --- a/lib/utils/file_util.dart +++ b/lib/utils/file_util.dart @@ -2,6 +2,7 @@ import 'dart:io' as io; import 'dart:io'; import 'dart:typed_data'; +import 'package:flutter/widgets.dart'; import 'package:flutter_sodium/flutter_sodium.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart'; @@ -24,12 +25,16 @@ import 'package:photos/models/file_type.dart'; import 'package:photos/repositories/file_repository.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/sync_service.dart'; +import 'package:photos/utils/dialog_util.dart'; import 'crypto_util.dart'; final _logger = Logger("FileUtil"); -Future deleteFilesFromEverywhere(List files) async { +Future deleteFilesFromEverywhere( + BuildContext context, List files) async { + final dialog = createProgressDialog(context, "Deleting..."); + await dialog.show(); final localIDs = List(); for (final file in files) { if (file.localID != null) { @@ -54,6 +59,7 @@ Future deleteFilesFromEverywhere(List files) async { hasUploadedFiles = true; await FilesDB.instance.markForDeletion(file.uploadedFileID); } + await dialog.hide(); } await FileRepository.instance.reloadFiles(); @@ -64,6 +70,29 @@ Future deleteFilesFromEverywhere(List files) async { } } +Future deleteFilesOnDeviceOnly( + BuildContext context, List files) async { + final dialog = createProgressDialog(context, "Deleting..."); + await dialog.show(); + final localIDs = List(); + for (final file in files) { + if (file.localID != null) { + localIDs.add(file.localID); + } + } + final deletedIDs = + (await PhotoManager.editor.deleteWithIds(localIDs)).toSet(); + for (final file in files) { + // Remove only those files that have been removed from disk + if (deletedIDs.contains(file.localID)) { + file.localID = null; + FilesDB.instance.update(file); + } + } + await FileRepository.instance.reloadFiles(); + await dialog.hide(); +} + void preloadFile(File file) { if (file.fileType == FileType.video) { return;