Skip to content

Feature: Added option to confirm permanent deletion only #11212

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ await DialogDisplayHelper.ShowDialogAsync(

#region Delete

public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPath> source, bool showDialog, bool permanently, bool registerHistory)
public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPath> source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
{
source = await source.ToListAsync();

Expand All @@ -125,7 +125,8 @@ public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPat
var deleteFromRecycleBin = source.Select(item => item.Path).Any(path => RecycleBinHelpers.IsPathUnderRecycleBin(path));
var canBeSentToBin = !deleteFromRecycleBin && await RecycleBinHelpers.HasRecycleBin(source.FirstOrDefault()?.Path);

if (showDialog)
if (showDialog is DeleteConfirmationPolicies.Always
|| showDialog is DeleteConfirmationPolicies.PermanentOnly && (permanently || !canBeSentToBin))
{
var incomingItems = new List<BaseFileSystemDialogItemViewModel>();
List<ShellFileItem>? binItems = null;
Expand Down Expand Up @@ -193,13 +194,13 @@ public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPat
return returnStatus;
}

public Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory)
public Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
=> DeleteItemsAsync(source.CreateEnumerable(), showDialog, permanently, registerHistory);

public Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItem> source, bool showDialog, bool permanently, bool registerHistory)
public Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItem> source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
=> DeleteItemsAsync(source.Select((item) => item.FromStorageItem()), showDialog, permanently, registerHistory);

public Task<ReturnResult> DeleteItemAsync(IStorageItem source, bool showDialog, bool permanently, bool registerHistory)
public Task<ReturnResult> DeleteItemAsync(IStorageItem source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
=> DeleteItemAsync(source.FromStorageItem(), showDialog, permanently, registerHistory);

#endregion Delete
Expand Down Expand Up @@ -258,7 +259,7 @@ public async Task<ReturnResult> PerformOperationTypeAsync(DataPackageOperation o
}
if (destination.StartsWith(CommonPaths.RecycleBinPath, StringComparison.Ordinal))
{
return await RecycleItemsFromClipboard(packageView, destination, UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, registerHistory);
return await RecycleItemsFromClipboard(packageView, destination, UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, registerHistory);
}
else if (operation.HasFlag(DataPackageOperation.Copy))
{
Expand Down Expand Up @@ -625,7 +626,7 @@ public async Task<ReturnResult> CreateShortcutFromClipboard(DataPackageView pack
return returnStatus;
}

public async Task<ReturnResult> RecycleItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory)
public async Task<ReturnResult> RecycleItemsFromClipboard(DataPackageView packageView, string destination, DeleteConfirmationPolicies showDialog, bool registerHistory)
{
if (!HasDraggedStorageItems(packageView))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public interface IFilesystemHelpers : IDisposable
/// <param name="permanently">Determines whether <paramref name="source"/> is be deleted permanently</param>
/// <param name="registerHistory">Determines whether <see cref="IStorageHistory"/> is saved</param>
/// <returns><see cref="ReturnResult"/> of performed operation</returns>
Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItem> source, bool showDialog, bool permanently, bool registerHistory);
Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItem> source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory);

/// <summary>
/// Deletes provided <paramref name="source"/>
Expand All @@ -38,7 +38,7 @@ public interface IFilesystemHelpers : IDisposable
/// <param name="permanently">Determines whether <paramref name="source"/> is be deleted permanently</param>
/// <param name="registerHistory">Determines whether <see cref="IStorageHistory"/> is saved</param>
/// <returns><see cref="ReturnResult"/> of performed operation</returns>
Task<ReturnResult> DeleteItemAsync(IStorageItem source, bool showDialog, bool permanently, bool registerHistory);
Task<ReturnResult> DeleteItemAsync(IStorageItem source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory);

/// <summary>
/// Deletes provided <paramref name="source"/>
Expand All @@ -48,7 +48,7 @@ public interface IFilesystemHelpers : IDisposable
/// <param name="permanently">Determines whether <paramref name="source"/> is be deleted permanently</param>
/// <param name="registerHistory">Determines whether <see cref="IStorageHistory"/> is saved</param>
/// <returns><see cref="ReturnResult"/> of performed operation</returns>
Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPath> source, bool showDialog, bool permanently, bool registerHistory);
Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPath> source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory);

/// <summary>
/// Deletes provided <paramref name="source"/>
Expand All @@ -58,7 +58,7 @@ public interface IFilesystemHelpers : IDisposable
/// <param name="permanently">Determines whether <paramref name="source"/> is be deleted permanently</param>
/// <param name="registerHistory">Determines whether <see cref="IStorageHistory"/> is saved</param>
/// <returns><see cref="ReturnResult"/> of performed operation</returns>
Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, bool showDialog, bool permanently, bool registerHistory);
Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory);

#endregion Delete

Expand Down Expand Up @@ -175,7 +175,7 @@ public interface IFilesystemHelpers : IDisposable
/// <returns><see cref="ReturnResult"/> of performed operation</returns>
Task<ReturnResult> CopyItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory);

Task<ReturnResult> RecycleItemsFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory);
Task<ReturnResult> RecycleItemsFromClipboard(DataPackageView packageView, string destination, DeleteConfirmationPolicies showDialog, bool registerHistory);

Task<ReturnResult> CreateShortcutFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ public async Task<ReturnResult> Undo(IStorageHistory history)
case FileOperationType.CreateNew: // Opposite: Delete created items
if (!IsHistoryNull(history.Source))
{
return await helpers.DeleteItemsAsync(history.Source, true, true, false); // Show a dialog to prevent unexpected deletion
// Show a dialog regardless of the setting to prevent unexpected deletion
return await helpers.DeleteItemsAsync(history.Source, DeleteConfirmationPolicies.Always, true, false);
}
break;
case FileOperationType.CreateLink: // Opposite: Delete created items
if (!IsHistoryNull(history.Destination))
{
return await helpers.DeleteItemsAsync(history.Destination, true, true, false); // Show a dialog to prevent unexpected deletion
// Show a dialog regardless of the setting to prevent unexpected deletion
return await helpers.DeleteItemsAsync(history.Destination, DeleteConfirmationPolicies.Always, true, false);
}
break;
case FileOperationType.Rename: // Opposite: Restore original item names
Expand All @@ -61,7 +63,8 @@ public async Task<ReturnResult> Undo(IStorageHistory history)
case FileOperationType.Copy: // Opposite: Delete copied items
if (!IsHistoryNull(history.Destination))
{
return await helpers.DeleteItemsAsync(history.Destination, true, true, false); // Show a dialog to prevent unexpected deletion
// Show a dialog regardless of the setting to prevent unexpected deletion
return await helpers.DeleteItemsAsync(history.Destination, DeleteConfirmationPolicies.Always, true, false);
}
break;
case FileOperationType.Move: // Opposite: Move the items to original directory
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Helpers/NavigationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public static async Task<bool> OpenPath(string path, IShellPage associatedInstan

// Delete shortcut
var shortcutItem = StorageHelpers.FromPathAndType(path, FilesystemItemType.File);
await associatedInstance.FilesystemHelpers.DeleteItemAsync(shortcutItem, false, false, true);
await associatedInstance.FilesystemHelpers.DeleteItemAsync(shortcutItem, DeleteConfirmationPolicies.Never, false, true);
}
}
else if (isReparsePoint)
Expand Down
6 changes: 3 additions & 3 deletions src/Files.App/Helpers/RecycleBinHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ public static async Task EmptyRecycleBin()
SecondaryButtonText = "Cancel".GetLocalizedResource(),
DefaultButton = ContentDialogButton.Primary
};
ContentDialogResult result = await SetContentDialogRoot(ConfirmEmptyBinDialog).ShowAsync();

if (result == ContentDialogResult.Primary)
if (userSettingsService.FoldersSettingsService.DeleteConfirmationPolicy is DeleteConfirmationPolicies.Never
|| await SetContentDialogRoot(ConfirmEmptyBinDialog).ShowAsync() == ContentDialogResult.Primary)
{
string bannerTitle = "EmptyRecycleBin".GetLocalizedResource();
var banner = App.OngoingTasksViewModel.PostBanner(
Expand Down Expand Up @@ -173,7 +173,7 @@ public static async Task DeleteItem(IShellPage associatedInstance)
var items = associatedInstance.SlimContentPage.SelectedItems.ToList().Select((item) => StorageHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory));
await associatedInstance.FilesystemHelpers.DeleteItemsAsync(items, userSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, false, true);
await associatedInstance.FilesystemHelpers.DeleteItemsAsync(items, userSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, false, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,10 @@ public bool ShowThumbnails
set => Set(value);
}

public bool ShowConfirmDeleteDialog
public DeleteConfirmationPolicies DeleteConfirmationPolicy
{
get => Get(true);
set => Set(value);
get => (DeleteConfirmationPolicies)Get((long)DeleteConfirmationPolicies.Always);
set => Set((long)value);
}

public bool SelectFilesOnHover
Expand Down Expand Up @@ -283,7 +283,7 @@ protected override void RaiseOnSettingChangedEvent(object sender, SettingChanged
case nameof(CalculateFolderSizes):
case nameof(ShowFileExtensions):
case nameof(ShowThumbnails):
case nameof(ShowConfirmDeleteDialog):
case nameof(DeleteConfirmationPolicy):
case nameof(SelectFilesOnHover):
case nameof(ShowSelectionCheckboxes):
case nameof(DoubleClickToGoUp):
Expand Down
9 changes: 9 additions & 0 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -2913,4 +2913,13 @@
<data name="WindowsVersion" xml:space="preserve">
<value>Windows version</value>
</data>
<data name="Always" xml:space="preserve">
<value>Always</value>
</data>
<data name="PermanentDeletionOnly" xml:space="preserve">
<value>Permanent deletion only</value>
</data>
<data name="Never" xml:space="preserve">
<value>Never</value>
</data>
</root>
23 changes: 19 additions & 4 deletions src/Files.App/ViewModels/SettingsViewModels/FoldersViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public FoldersViewModel()
SelectedDefaultLayoutModeIndex = (int)DefaultLayoutMode;
SelectedDefaultSortingIndex = UserSettingsService.FoldersSettingsService.DefaultSortOption == SortOption.FileTag ? FileTagSortingIndex : (int)UserSettingsService.FoldersSettingsService.DefaultSortOption;
SelectedDefaultGroupingIndex = UserSettingsService.FoldersSettingsService.DefaultGroupOption == GroupOption.FileTag ? FileTagGroupingIndex : (int)UserSettingsService.FoldersSettingsService.DefaultGroupOption;
SelectedDeleteConfirmationPolicyIndex = (int)DeleteConfirmationPolicy;
}

// Properties
Expand All @@ -39,6 +40,20 @@ public int SelectedDefaultLayoutModeIndex
}
}

private int selectedDeleteConfirmationPolicyIndex;
public int SelectedDeleteConfirmationPolicyIndex
{
get => selectedDeleteConfirmationPolicyIndex;
set
{
if (SetProperty(ref selectedDeleteConfirmationPolicyIndex, value))
{
OnPropertyChanged(nameof(SelectedDeleteConfirmationPolicyIndex));
DeleteConfirmationPolicy = (DeleteConfirmationPolicies)value;
}
}
}

public bool SyncFolderPreferencesAcrossDirectories
{
get => UserSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories;
Expand Down Expand Up @@ -315,14 +330,14 @@ public bool ShowThumbnails
}
}

public bool ShowConfirmDeleteDialog
public DeleteConfirmationPolicies DeleteConfirmationPolicy
{
get => UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog;
get => UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy;
set
{
if (value != UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog)
if (value != UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy)
{
UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog = value;
UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy = value;
OnPropertyChanged();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Files.App/Views/ColumnShellPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
var items = SlimContentPage.SelectedItems.ToList().Select((item) => StorageHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory));
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, true, true);
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, true, true);
}

break;
Expand Down Expand Up @@ -758,7 +758,7 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
var items = SlimContentPage.SelectedItems.ToList().Select((item) => StorageHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory));
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, false, true);
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, false, true);
}

break;
Expand Down
4 changes: 2 additions & 2 deletions src/Files.App/Views/ModernShellPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
var items = SlimContentPage.SelectedItems.ToList().Select((item) => StorageHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory));
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, true, true);
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, true, true);
}

break;
Expand Down Expand Up @@ -761,7 +761,7 @@ private async void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, Keybo
var items = SlimContentPage.SelectedItems.ToList().Select((item) => StorageHelpers.FromPathAndType(
item.ItemPath,
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory));
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.ShowConfirmDeleteDialog, false, true);
await FilesystemHelpers.DeleteItemsAsync(items, UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy, false, true);
}

break;
Expand Down
10 changes: 5 additions & 5 deletions src/Files.App/Views/SettingsPages/Folders.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,11 @@
<FontIcon Glyph="&#xE107;" />
</local:SettingsBlockControl.Icon>

<ToggleSwitch
x:Name="ShowConfirmDeleteDialogSwitch"
AutomationProperties.Name="{helpers:ResourceString Name=ShowConfirmationWhenDeletingItems}"
IsOn="{x:Bind ViewModel.ShowConfirmDeleteDialog, Mode=TwoWay}"
Style="{StaticResource RightAlignedToggleSwitchStyle}" />
<ComboBox AutomationProperties.Name="{helpers:ResourceString Name=ShowConfirmationWhenDeletingItems}" SelectedIndex="{x:Bind ViewModel.SelectedDeleteConfirmationPolicyIndex, Mode=TwoWay}">
<ComboBoxItem Content="{helpers:ResourceString Name=Always}" />
<ComboBoxItem Content="{helpers:ResourceString Name=PermanentDeletionOnly}" />
<ComboBoxItem Content="{helpers:ResourceString Name=Never}" />
</ComboBox>
</local:SettingsBlockControl>

<!-- Select On Hover -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public interface IFoldersSettingsService : IBaseSettingsService, INotifyProperty
/// <summary>
/// Gets or sets a value indicating whether or not to show the delete confirmation dialog when deleting items.
/// </summary>
bool ShowConfirmDeleteDialog { get; set; }
DeleteConfirmationPolicies DeleteConfirmationPolicy { get; set; }

/// <summary>
/// Gets or sets a value indicating whether or not to select files and folders when hovering them.
Expand Down
9 changes: 9 additions & 0 deletions src/Files.Shared/Enums/DeleteConfirmationPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Files.Shared.Enums
{
public enum DeleteConfirmationPolicies : byte
{
Always,
PermanentOnly,
Never,
}
}