Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d9f6acb
Save changes
hecksmosis Dec 30, 2022
e1a8267
Save changes
hecksmosis Dec 31, 2022
5731b85
Merge branch 'main' of https://github.com/files-community/Files into …
hecksmosis Dec 31, 2022
aed1503
save more changes
hecksmosis Jan 1, 2023
5688928
save more changes
hecksmosis Jan 1, 2023
5c346bb
Display recycle bin size in tooltip
hecksmosis Jan 2, 2023
ae350f5
Fix conflicts
hecksmosis Jan 2, 2023
a70b5b1
Refresh in file watcher
hecksmosis Jan 2, 2023
8f9a13e
Update Win32StorageEnumerator.cs
hecksmosis Jan 2, 2023
11aae4e
Update FolderHelpers.cs
hecksmosis Jan 2, 2023
4996838
Update UniversalStorageEnumerator.cs
hecksmosis Jan 2, 2023
4ffccaa
Update Win32StorageEnumerator.cs
hecksmosis Jan 2, 2023
f21dcc8
Update SidebarViewModel.cs
hecksmosis Jan 2, 2023
2989a54
Minor fixes
hecksmosis Jan 2, 2023
4028088
Remove changes to the sidebar
hecksmosis Jan 2, 2023
a6d33c1
Update SidebarControl.xaml.cs
hecksmosis Jan 2, 2023
5f379d2
Remove debug Logger call
hecksmosis Jan 2, 2023
17e2efd
Some refactoring
hecksmosis Jan 3, 2023
5dad5fc
Requested changes
hecksmosis Jan 3, 2023
8def1bb
Revert changes to RecycleBinManager
hecksmosis Jan 3, 2023
533f92e
Requested Changes
hecksmosis Jan 3, 2023
f6f7e4a
Fix spacing
hecksmosis Jan 3, 2023
052704c
Fix spacing
hecksmosis Jan 3, 2023
dba1f69
Merge branch 'main' into recyclebinsize
hecksmosis Jan 4, 2023
77b09c3
Fixed indent
QuaintMako Jan 4, 2023
1a04bf6
Fixed indent
QuaintMako Jan 4, 2023
efc6c25
Merge branch 'main' into recyclebinsize
yaira2 Jan 4, 2023
4dad6b7
Merge branch 'main' of https://github.com/files-community/Files into …
gave92 Jan 8, 2023
288ee4d
Minor changes
gave92 Jan 8, 2023
a183906
Update LocationItem.cs
hecksmosis Jan 8, 2023
e2be6f3
Update Resources.resw
hecksmosis Jan 8, 2023
ca90155
Merge branch 'main' into recyclebinsize
yaira2 Jan 9, 2023
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
36 changes: 33 additions & 3 deletions src/Files.App/DataModels/NavigationControlItems/LocationItem.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.WinUI;
using Files.App.Extensions;
using Files.App.Filesystem;
using Files.App.Helpers;
using Files.Shared;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Threading.Tasks;

namespace Files.App.DataModels.NavigationControlItems
{
Expand Down Expand Up @@ -33,10 +35,10 @@ public string Path
{
path = value;
ToolTipText = string.IsNullOrEmpty(Path) || Path.Contains('?', StringComparison.Ordinal) || Path.StartsWith("shell:", StringComparison.OrdinalIgnoreCase) || Path.EndsWith(ShellLibraryItem.EXTENSION, StringComparison.OrdinalIgnoreCase) || Path == "Home".GetLocalizedResource() ? Text : Path;
}
}
}

public string ToolTipText { get; private set; }
public virtual string ToolTipText { get; private set; }
public FontFamily Font { get; set; }
public NavigationControlItemType ItemType => NavigationControlItemType.Location;
public bool IsDefaultLocation { get; set; }
Expand All @@ -52,11 +54,39 @@ public bool IsExpanded
}

public bool IsInvalid { get; set; } = false;

public bool IsRecycleBin => string.Equals(Path, "shell:RecycleBinFolder", StringComparison.OrdinalIgnoreCase);
public SectionType Section { get; set; }

public ContextMenuOptions MenuOptions { get; set; }

public int CompareTo(INavigationControlItem other) => Text.CompareTo(other.Text);
}

public class RecycleBinLocationItem : LocationItem
{
public void RefreshSpaceUsed()
{
App.Logger.Warn("Refreshing Recycle Bin used space");
SpaceUsed = RecycleBinHelpers.GetSize();
}

private ulong spaceUsed;
public ulong SpaceUsed
{
get => spaceUsed;
set {
if (SetProperty(ref spaceUsed, value))
OnPropertyChanged(nameof(ToolTipText));

App.Logger.Warn(ToolTipText + $", real value: {spaceUsed}");
}
}

public override string ToolTipText => "RecycleBinSizeText".GetLocalizedResource() + SpaceUsed.ToSizeString();

public RecycleBinLocationItem()
{
RecycleBinHelpers.sidebarBin = this;
}
}
}
52 changes: 38 additions & 14 deletions src/Files.App/DataModels/SidebarPinnedModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,22 +204,46 @@ public async Task AddItemToSidebarAsync(string path)
{
var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path));
var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item));
var locationItem = new LocationItem
LocationItem locationItem;
if (path == CommonPaths.RecycleBinPath) {
locationItem = new RecycleBinLocationItem
{
Font = App.AppModel.SymbolFontFamily,
Path = path,
Section = SectionType.Favorites,
MenuOptions = new ContextMenuOptions
{
IsLocationItem = true,
ShowProperties = true,
ShowUnpinItem = true,
ShowShellItems = true,
ShowEmptyRecycleBin = true,
},
IsDefaultLocation = false,
Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\'))
};

((RecycleBinLocationItem)locationItem).RefreshSpaceUsed();
}
else
{
Font = App.AppModel.SymbolFontFamily,
Path = path,
Section = SectionType.Favorites,
MenuOptions = new ContextMenuOptions
locationItem = new LocationItem
{
IsLocationItem = true,
ShowProperties = true,
ShowUnpinItem = true,
ShowShellItems = true,
ShowEmptyRecycleBin = path == CommonPaths.RecycleBinPath,
},
IsDefaultLocation = false,
Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\'))
};
Font = App.AppModel.SymbolFontFamily,
Path = path,
Section = SectionType.Favorites,
MenuOptions = new ContextMenuOptions
{
IsLocationItem = true,
ShowProperties = true,
ShowUnpinItem = true,
ShowShellItems = true,
ShowEmptyRecycleBin = false,
},
IsDefaultLocation = false,
Text = res.Result?.DisplayName ?? Path.GetFileName(path.TrimEnd('\\'))
};
}

if (res || (FilesystemResult)FolderHelpers.CheckFolderAccessWithWin32(path))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
if (!permanently)
{
// Enumerate Recycle Bin
IEnumerable<ShellFileItem> nameMatchItems, items = await recycleBinHelpers.EnumerateRecycleBin();
IEnumerable<ShellFileItem> nameMatchItems, items = await RecycleBinHelpers.EnumerateRecycleBin();

// Get name matching files
if (FileExtensionHelpers.IsShortcutOrUrlFile(source.Path)) // We need to check if it is a shortcut file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPat
{
if (recycleBinHelpers.IsPathUnderRecycleBin(src.Path))
{
binItems ??= await recycleBinHelpers.EnumerateRecycleBin();
binItems ??= await RecycleBinHelpers.EnumerateRecycleBin();
if (!binItems.IsEmpty()) // Might still be null because we're deserializing the list from Json
{
var matchingItem = binItems.FirstOrDefault(x => x.RecyclePath == src.Path); // Get original file name
Expand Down Expand Up @@ -372,7 +372,7 @@ public async Task<ReturnResult> CopyItemsFromClipboard(DataPackageView packageVi
{
if (recycleBinHelpers.IsPathUnderRecycleBin(item.Path))
{
binItems ??= await recycleBinHelpers.EnumerateRecycleBin();
binItems ??= await RecycleBinHelpers.EnumerateRecycleBin();
if (!binItems.IsEmpty()) // Might still be null because we're deserializing the list from Json
{
var matchingItem = binItems.FirstOrDefault(x => x.RecyclePath == item.Path); // Get original file name
Expand Down Expand Up @@ -517,7 +517,7 @@ public async Task<ReturnResult> MoveItemsFromClipboard(DataPackageView packageVi
{
if (recycleBinHelpers.IsPathUnderRecycleBin(item.Path))
{
binItems ??= await recycleBinHelpers.EnumerateRecycleBin();
binItems ??= await RecycleBinHelpers.EnumerateRecycleBin();
if (!binItems.IsEmpty()) // Might still be null because we're deserializing the list from Json
{
var matchingItem = binItems.FirstOrDefault(x => x.RecyclePath == item.Path); // Get original file name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ public async Task<IStorageHistory> DeleteItemsAsync(IList<IStorageItemWithPath>
{
var sourceMatch = await recycledSources.Select(x => source.DistinctBy(x => x.Path)
.SingleOrDefault(s => s.Path.Equals(x.Source, StringComparison.OrdinalIgnoreCase))).Where(x => x is not null).ToListAsync();

return new StorageHistory(FileOperationType.Recycle,
sourceMatch,
await recycledSources.Zip(sourceMatch, (rSrc, oSrc) => new { rSrc, oSrc })
Expand Down Expand Up @@ -669,6 +670,7 @@ public async Task<IStorageHistory> RestoreItemsFromTrashAsync(IList<IStorageItem
.Select(src => StorageHelpers.FromPathAndType(
Path.Combine(Path.GetDirectoryName(src.rSrc.Source), Path.GetFileName(src.rSrc.Source).Replace("$R", "$I", StringComparison.Ordinal)),
src.oSrc.ItemType)).ToListAsync(), null, true, cancellationToken);

return new StorageHistory(FileOperationType.Restore,
sourceMatch,
await movedSources.Zip(sourceMatch, (rSrc, oSrc) => new { rSrc, oSrc })
Expand Down Expand Up @@ -748,7 +750,7 @@ private async Task<DialogResult> GetFileListDialog(IEnumerable<string> source, s
{
if (recycleBinHelpers.IsPathUnderRecycleBin(src))
{
binItems ??= await recycleBinHelpers.EnumerateRecycleBin();
binItems ??= await RecycleBinHelpers.EnumerateRecycleBin();
if (!binItems.IsEmpty()) // Might still be null because we're deserializing the list from Json
{
var matchingItem = binItems.FirstOrDefault(x => x.RecyclePath == src); // Get original file name
Expand Down
13 changes: 12 additions & 1 deletion src/Files.App/Helpers/RecycleBinHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Files.App.DataModels.NavigationControlItems;
using Files.App.Extensions;
using Files.App.Filesystem;
using Files.App.Shell;
Expand All @@ -22,11 +23,21 @@ public class RecycleBinHelpers

#endregion Private Members

public async Task<List<ShellFileItem>> EnumerateRecycleBin()
public static RecycleBinLocationItem? sidebarBin;

public static async Task<List<ShellFileItem>> EnumerateRecycleBin()
{
return (await Win32Shell.GetShellFolderAsync(CommonPaths.RecycleBinPath, "Enumerate", 0, int.MaxValue)).Enumerate;
}

public static void RefreshSidebarRecycleBin()
=> sidebarBin?.RefreshSpaceUsed();

public static ulong GetSize()
{
return (ulong)Win32Shell.QueryRecycleBin().BinSize;
}

public async Task<bool> IsRecycleBinItem(IStorageItem item)
{
List<ShellFileItem> recycleBinItems = await EnumerateRecycleBin();
Expand Down
4 changes: 3 additions & 1 deletion src/Files.App/Shell/RecycleBinManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Files.App.Helpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Principal;
Expand Down Expand Up @@ -74,6 +75,7 @@ private void RecycleBinWatcher_Changed(object sender, FileSystemEventArgs e)
// Recycle bin also stores a file starting with $I for each item
return;
}
RecycleBinHelpers.RefreshSidebarRecycleBin();

switch (e.ChangeType)
{
Expand Down
52 changes: 30 additions & 22 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema

<!--
Microsoft ResX Schema
Version 2.0

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -24,33 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple

There are any number of "resheader" rows that contain simple
name/value pairs.

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -2926,4 +2931,7 @@
<data name="RecentFilesDisabledOnWindowsWarning" xml:space="preserve">
<value>Recently used files is currently disabled in Windows File Explorer.</value>
</data>
<data name="RecycleBinSizeText" xml:space="preserve">
<value>Recycle Bin size: </value>
</data>
</root>
2 changes: 1 addition & 1 deletion src/Files.App/UserControls/SidebarControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,6 @@
DriveNavItemTemplate="{StaticResource DriveNavItem}"
FileTagNavItemTemplate="{StaticResource FileTagNavItem}"
LinuxNavItemTemplate="{StaticResource LinuxNavItem}"
LocationNavItemTemplate="{StaticResource LocationNavItem}" />
LocationNavItemTemplate="{StaticResource LocationNavItem}"/>
</NavigationView.MenuItemTemplateSelector>
</NavigationView>
2 changes: 1 addition & 1 deletion src/Files.App/UserControls/SidebarControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1233,4 +1233,4 @@ public class NavItemDataTemplateSelector : DataTemplateSelector
};
}
}
}
}
2 changes: 1 addition & 1 deletion src/Files.App/ViewModels/SidebarViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -605,4 +605,4 @@ public GridLength TabControlMargin
set => SetProperty(ref tabControlMargin, value);
}
}
}
}