Skip to content

Commit 5fac69c

Browse files
committed
Init
1 parent aa05b1a commit 5fac69c

19 files changed

+363
-332
lines changed

src/Files.App/Actions/FileSystem/EmptyRecycleBinAction.cs

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Microsoft.UI.Xaml.Controls;
5+
using Windows.Foundation.Metadata;
6+
47
namespace Files.App.Actions
58
{
69
internal sealed class EmptyRecycleBinAction : BaseUIAction, IAction
710
{
11+
private readonly IWindowsRecycleBinService WindowsRecycleBinService = Ioc.Default.GetRequiredService<IWindowsRecycleBinService>();
12+
private readonly StatusCenterViewModel StatusCenterViewModel = Ioc.Default.GetRequiredService<StatusCenterViewModel>();
13+
private readonly IUserSettingsService UserSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
814
private readonly IContentPageContext context;
915

1016
public string Label
@@ -19,7 +25,7 @@ public RichGlyph Glyph
1925
public override bool IsExecutable =>
2026
UIHelpers.CanShowDialog &&
2127
((context.PageType == ContentPageTypes.RecycleBin && context.HasItem) ||
22-
RecycleBinHelpers.RecycleBinHasItems());
28+
WindowsRecycleBinService.HasItems());
2329

2430
public EmptyRecycleBinAction()
2531
{
@@ -30,7 +36,31 @@ public EmptyRecycleBinAction()
3036

3137
public async Task ExecuteAsync(object? parameter = null)
3238
{
33-
await RecycleBinHelpers.EmptyRecycleBinAsync();
39+
// TODO: Use AppDialogService
40+
var confirmationDialog = new ContentDialog()
41+
{
42+
Title = "ConfirmEmptyBinDialogTitle".GetLocalizedResource(),
43+
Content = "ConfirmEmptyBinDialogContent".GetLocalizedResource(),
44+
PrimaryButtonText = "Yes".GetLocalizedResource(),
45+
SecondaryButtonText = "Cancel".GetLocalizedResource(),
46+
DefaultButton = ContentDialogButton.Primary
47+
};
48+
49+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
50+
confirmationDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
51+
52+
if (UserSettingsService.FoldersSettingsService.DeleteConfirmationPolicy is DeleteConfirmationPolicies.Never ||
53+
await confirmationDialog.TryShowAsync() is ContentDialogResult.Primary)
54+
{
55+
var banner = StatusCenterHelper.AddCard_EmptyRecycleBin(ReturnResult.InProgress);
56+
57+
bool bResult = await WindowsRecycleBinService.DeleteAllAsync();
58+
59+
StatusCenterViewModel.RemoveItem(banner);
60+
61+
// Post a status based on the result
62+
StatusCenterHelper.AddCard_EmptyRecycleBin(bResult ? ReturnResult.Success : ReturnResult.Failed);
63+
}
3464
}
3565

3666
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)

src/Files.App/Actions/FileSystem/RestoreAllRecycleBinAction.cs

+61-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Microsoft.UI.Xaml.Controls;
5+
using Windows.Foundation.Metadata;
6+
47
namespace Files.App.Actions
58
{
69
internal sealed class RestoreAllRecycleBinAction : BaseUIAction, IAction
710
{
11+
private readonly IWindowsRecycleBinService WindowsRecycleBinService = Ioc.Default.GetRequiredService<IWindowsRecycleBinService>();
12+
813
public string Label
914
=> "RestoreAllItems".GetLocalizedResource();
1015

@@ -16,11 +21,65 @@ public RichGlyph Glyph
1621

1722
public override bool IsExecutable =>
1823
UIHelpers.CanShowDialog &&
19-
RecycleBinHelpers.RecycleBinHasItems();
24+
WindowsRecycleBinService.HasItems();
2025

2126
public async Task ExecuteAsync(object? parameter = null)
2227
{
23-
await RecycleBinHelpers.RestoreRecycleBinAsync();
28+
// TODO: Use AppDialogService
29+
var confirmationDialog = new ContentDialog()
30+
{
31+
Title = "ConfirmRestoreBinDialogTitle".GetLocalizedResource(),
32+
Content = "ConfirmRestoreBinDialogContent".GetLocalizedResource(),
33+
PrimaryButtonText = "Yes".GetLocalizedResource(),
34+
SecondaryButtonText = "Cancel".GetLocalizedResource(),
35+
DefaultButton = ContentDialogButton.Primary
36+
};
37+
38+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
39+
confirmationDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
40+
41+
if (await confirmationDialog.TryShowAsync() is not ContentDialogResult.Primary)
42+
return;
43+
44+
//using var sop = new ShellFileOperations { Options = GetDeleteOpFlags(hideUI) };
45+
//HRESULT hr = HRESULT.S_OK;
46+
47+
try
48+
{
49+
//foreach (var item in deletedItems)
50+
//{
51+
// if (item.Parent != ShellFolderInstance) throw new InvalidOperationException("Unable to restore a ShellItem that is not in the Recycle Bin.");
52+
// // Manually create a ShellFolder instance to the original location.
53+
// using var sf = new ShellFolder(Path.GetDirectoryName(item.Name)!);
54+
// sop.QueueMoveOperation(item, sf, Path.GetFileName(item.Name));
55+
//}
56+
//sop.PerformOperations();
57+
//hr.ThrowIfFailed();
58+
}
59+
catch (Exception)
60+
{
61+
var errorDialog = new ContentDialog()
62+
{
63+
Title = "FailedToRestore".GetLocalizedResource(),
64+
PrimaryButtonText = "OK".GetLocalizedResource(),
65+
};
66+
67+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
68+
errorDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
69+
70+
await errorDialog.TryShowAsync();
71+
}
72+
finally
73+
{
74+
try
75+
{
76+
// Call the undocumented function to reset the icon.
77+
//SHUpdateRecycleBinIcon();
78+
}
79+
catch
80+
{
81+
}
82+
}
2483
}
2584
}
2685
}

src/Files.App/Actions/FileSystem/RestoreRecycleBinAction.cs

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Microsoft.UI.Xaml.Controls;
5+
using Windows.Foundation.Metadata;
6+
using Windows.Storage;
7+
48
namespace Files.App.Actions
59
{
610
internal sealed class RestoreRecycleBinAction : BaseUIAction, IAction
@@ -30,8 +34,33 @@ public RestoreRecycleBinAction()
3034

3135
public async Task ExecuteAsync(object? parameter = null)
3236
{
33-
if (context.ShellPage is not null)
34-
await RecycleBinHelpers.RestoreSelectionRecycleBinAsync(context.ShellPage);
37+
var confirmationDialog = new ContentDialog()
38+
{
39+
Title = "ConfirmRestoreSelectionBinDialogTitle".GetLocalizedResource(),
40+
Content = string.Format("ConfirmRestoreSelectionBinDialogContent".GetLocalizedResource(), context.SelectedItems.Count),
41+
PrimaryButtonText = "Yes".GetLocalizedResource(),
42+
SecondaryButtonText = "Cancel".GetLocalizedResource(),
43+
DefaultButton = ContentDialogButton.Primary
44+
};
45+
46+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
47+
confirmationDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
48+
49+
ContentDialogResult result = await confirmationDialog.TryShowAsync();
50+
51+
if (result is not ContentDialogResult.Primary)
52+
return;
53+
54+
var items = context.SelectedItems.ToList().Where(x => x is RecycleBinItem).Select((item) => new
55+
{
56+
Source = StorageHelpers.FromPathAndType(
57+
item.ItemPath,
58+
item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory),
59+
Dest = ((RecycleBinItem)item).ItemOriginalPath
60+
});
61+
62+
await context.ShellPage!.FilesystemHelpers.RestoreItemsFromTrashAsync(items.Select(x => x.Source), items.Select(x => x.Dest), true);
63+
3564
}
3665

3766
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
namespace Files.App.Data.Contracts
5+
{
6+
public interface IWindowsRecycleBinService : ITrashWatcher
7+
{
8+
Task<List<ShellFileItem>> GetAllRecycleBinFoldersAsync();
9+
10+
ulong GetSize();
11+
12+
bool IsRecycled(string? path);
13+
14+
Task<bool> IsRecyclableAsync(string? path);
15+
16+
bool HasItems();
17+
18+
Task<bool> DeleteAllAsync();
19+
20+
bool RestoreAll();
21+
}
22+
}

src/Files.App/Data/Items/LocationItem.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,13 @@ public int CompareTo(INavigationControlItem other)
123123

124124
public sealed class RecycleBinLocationItem : LocationItem
125125
{
126-
public void RefreshSpaceUsed(object sender, FileSystemEventArgs e)
126+
private readonly IWindowsRecycleBinService WindowsRecycleBinService = Ioc.Default.GetRequiredService<IWindowsRecycleBinService>();
127+
128+
public void RefreshSpaceUsed(object? sender, FileSystemEventArgs e)
127129
{
128130
MainWindow.Instance.DispatcherQueue.TryEnqueue(() =>
129131
{
130-
SpaceUsed = RecycleBinHelpers.GetSize();
132+
SpaceUsed = WindowsRecycleBinService.GetSize();
131133
});
132134
}
133135

@@ -149,10 +151,10 @@ public override object ToolTip
149151

150152
public RecycleBinLocationItem()
151153
{
152-
SpaceUsed = RecycleBinHelpers.GetSize();
154+
SpaceUsed = WindowsRecycleBinService.GetSize();
153155

154-
RecycleBinManager.Default.RecycleBinItemCreated += RefreshSpaceUsed;
155-
RecycleBinManager.Default.RecycleBinItemDeleted += RefreshSpaceUsed;
156+
WindowsRecycleBinService.ItemAdded += RefreshSpaceUsed;
157+
WindowsRecycleBinService.ItemDeleted += RefreshSpaceUsed;
156158
}
157159
}
158160
}

src/Files.App/Helpers/Application/AppLifecycleHelper.cs

+1
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ public static IHost ConfigureHost()
192192
.AddSingleton<IQuickAccessService, QuickAccessService>()
193193
.AddSingleton<IResourcesService, ResourcesService>()
194194
.AddSingleton<IWindowsJumpListService, WindowsJumpListService>()
195+
.AddSingleton<IWindowsRecycleBinService, WindowsRecycleBinService>()
195196
.AddSingleton<IRemovableDrivesService, RemovableDrivesService>()
196197
.AddSingleton<INetworkService, NetworkService>()
197198
.AddSingleton<IStartMenuService, StartMenuService>()

src/Files.App/NativeMethods.txt

+1
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,4 @@ D3D11CreateDevice
7070
IDXGIDevice
7171
DCompositionCreateDevice
7272
IDCompositionDevice
73+
SHEmptyRecycleBin

src/Files.App/Services/App/FileTagsService.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ namespace Files.App.Services
1111
/// <inheritdoc cref="IFileTagsService"/>
1212
internal sealed class FileTagsService : IFileTagsService
1313
{
14-
private IStorageService StorageService { get; } = Ioc.Default.GetRequiredService<IStorageService>();
15-
16-
private IFileTagsSettingsService FileTagsSettingsService { get; } = Ioc.Default.GetRequiredService<IFileTagsSettingsService>();
14+
private readonly IWindowsRecycleBinService WindowsRecycleBinService = Ioc.Default.GetRequiredService<IWindowsRecycleBinService>();
15+
private readonly IFileTagsSettingsService FileTagsSettingsService = Ioc.Default.GetRequiredService<IFileTagsSettingsService>();
16+
private readonly IStorageService StorageService = Ioc.Default.GetRequiredService<IStorageService>();
1717

1818
/// <inheritdoc/>
1919
public Task<bool> IsSupportedAsync()
@@ -42,7 +42,7 @@ public async IAsyncEnumerable<TaggedItemModel> GetItemsForTagAsync(string tagUid
4242
{
4343
foreach (var item in FileTagsHelper.GetDbInstance().GetAll())
4444
{
45-
if (!item.Tags.Contains(tagUid) || RecycleBinHelpers.IsPathUnderRecycleBin(item.FilePath))
45+
if (!item.Tags.Contains(tagUid) || WindowsRecycleBinService.IsRecycled(item.FilePath))
4646
continue;
4747

4848
var storable = await StorageService.TryGetStorableAsync(item.FilePath, cancellationToken);

0 commit comments

Comments
 (0)