Skip to content
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f25b39e
Add robocopy support for move and copy operations
DarkEden-coding Sep 18, 2025
3b4bc2e
Add robocopy perminant remove support
DarkEden-coding Sep 18, 2025
e504f89
Add batch size setting
DarkEden-coding Sep 18, 2025
efc459c
fix formatting in ShellFilesystemOperations.cs
DarkEden-coding Sep 19, 2025
6c448a6
Fix folder and file transfer seperation issues, fix folder not moving…
DarkEden-coding Sep 19, 2025
7808c6c
Fix issue where empty folders are erroneously removed
DarkEden-coding Sep 19, 2025
248c65f
Make rename file conflicts go to shell functions
DarkEden-coding Sep 23, 2025
985a8c8
Make file operations with 20 or under files use shell only for less r…
DarkEden-coding Sep 23, 2025
5b86fd0
Make threads setting styling consistant with standards
DarkEden-coding Sep 24, 2025
93702e0
Add finer progress reporting
DarkEden-coding Sep 24, 2025
1ce4c41
reduce robocopy output overhead
DarkEden-coding Sep 24, 2025
37885e3
Fix robocopy bugs
DarkEden-coding Feb 28, 2026
427d1bb
Merge remote-tracking branch 'main/main' into Robocopy-Support
DarkEden-coding Jun 16, 2026
164f954
Fix merge issue
DarkEden-coding Jul 17, 2026
f2d6c9d
Preformance improvements
DarkEden-coding Jul 17, 2026
b566a99
Code Quality: Align Robocopy paths with upstream style and reduce dup…
DarkEden-coding Jul 19, 2026
c9f59cb
Code Quality: Format AdvancedPage.xaml with XamlStyler
DarkEden-coding Jul 19, 2026
15aa51c
Merge branch 'files-community:main' into Robocopy-Support
DarkEden-coding Jul 20, 2026
93beac1
Convert settings to use SettingsCard for thread count
DarkEden-coding Jul 26, 2026
62fc4d8
Show folder-in-use errors and others for Robocopy deletes
DarkEden-coding Aug 11, 2026
945041b
Cache the Robocopy settings service
DarkEden-coding Aug 17, 2026
7c81658
Use arrays for fixed operation snapshots
DarkEden-coding Aug 17, 2026
a84bedc
Expose Status Center paths as arrays
DarkEden-coding Aug 17, 2026
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
10 changes: 10 additions & 0 deletions src/Files.App/Data/Contracts/IDevToolsSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,15 @@ public interface IDevToolsSettingsService : IBaseSettingsService, INotifyPropert
/// Gets or sets the name of the chosen IDE.
/// </summary>
string IDEName { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to use Robocopy for file operations.
/// </summary>
bool UseRobocopyForFileOperations { get; set; }

/// <summary>
/// Gets or sets the number of threads to use with Robocopy.
/// </summary>
int RobocopyThreads { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/Files.App/Data/Contracts/IUserSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ public interface IUserSettingsService : IBaseSettingsService
ILayoutSettingsService LayoutSettingsService { get; }

IAppSettingsService AppSettingsService { get; }

IDevToolsSettingsService DevToolsSettingsService { get; }
}
}
5 changes: 5 additions & 0 deletions src/Files.App/Data/Contracts/IWindowsJumpListService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ public interface IWindowsJumpListService

Task RemoveFolderAsync(string path);

/// <summary>
/// Removes multiple folders using a single Jump List update.
/// </summary>
Task RemoveFoldersAsync(IEnumerable<string> paths);

Task<IEnumerable<string>> GetFoldersAsync();
}
}
1 change: 1 addition & 0 deletions src/Files.App/Data/Enums/CopyEngineResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static FileSystemStatusCode Convert(int? hres)
{
CopyEngineResult.S_OK => FileSystemStatusCode.Success,
CopyEngineResult.COPYENGINE_E_ACCESS_DENIED_SRC => FileSystemStatusCode.Unauthorized,
CopyEngineResult.COPYENGINE_E_USER_CANCELLED => FileSystemStatusCode.Generic,
CopyEngineResult.COPYENGINE_E_ACCESS_DENIED_DEST => FileSystemStatusCode.Unauthorized,
CopyEngineResult.COPYENGINE_E_REQUIRES_ELEVATION => FileSystemStatusCode.Unauthorized,
CopyEngineResult.COPYENGINE_E_RECYCLE_PATH_TOO_LONG => FileSystemStatusCode.NameTooLong,
Expand Down
14 changes: 14 additions & 0 deletions src/Files.App/Services/Settings/DevToolsSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ public string IDEName
set => Set(value);
}

/// <inheritdoc/>
public bool UseRobocopyForFileOperations
{
get => Get(false);
set => Set(value);
}

/// <inheritdoc/>
public int RobocopyThreads
{
get => Get(8);
set => Set(value);
}

protected override void RaiseOnSettingChangedEvent(object sender, SettingChangedEventArgs e)
{
base.RaiseOnSettingChangedEvent(sender, e);
Expand Down
6 changes: 6 additions & 0 deletions src/Files.App/Services/Settings/UserSettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ public IAppSettingsService AppSettingsService
get => GetSettingsService(ref _AppSettingsService);
}

private IDevToolsSettingsService _DevToolsSettingsService;
public IDevToolsSettingsService DevToolsSettingsService
{
get => GetSettingsService(ref _DevToolsSettingsService);
}

public UserSettingsService()
{
SettingsSerializer = new DefaultSettingsSerializer();
Expand Down
38 changes: 28 additions & 10 deletions src/Files.App/Services/Windows/WindowsJumpListService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,37 @@ public async Task RefreshPinnedFoldersAsync()

public async Task RemoveFolderAsync(string path)
{
if (JumpList.IsSupported())
await RemoveFoldersAsync([path]);
}

/// <inheritdoc/>
public async Task RemoveFoldersAsync(IEnumerable<string> paths)
{
if (!JumpList.IsSupported())
return;

try
{
try
{
var instance = await JumpList.LoadCurrentAsync();
// Disable automatic jumplist. It doesn't work.
instance.SystemGroupKind = JumpListSystemGroupKind.None;
var pathsToRemove = paths.ToHashSet(StringComparer.OrdinalIgnoreCase);
if (pathsToRemove.Count == 0)
return;

var instance = await JumpList.LoadCurrentAsync();
// Disable automatic jumplist. It doesn't work.
instance.SystemGroupKind = JumpListSystemGroupKind.None;

var itemToRemove = instance.Items.Where(x => x.Arguments == path).Select(x => x).FirstOrDefault();
instance.Items.Remove(itemToRemove);
var itemsToRemove = instance.Items

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ToArray

.Where(item => pathsToRemove.Contains(item.Arguments))
.ToList();
foreach (var item in itemsToRemove)
instance.Items.Remove(item);

if (itemsToRemove.Count > 0)
await instance.SaveAsync();
}
catch { }
}
catch (Exception ex)
{
App.Logger.LogWarning(ex, ex.Message);
}
}

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 @@ -2177,6 +2177,15 @@
<data name="ShowFlattenOptions" xml:space="preserve">
<value>Show flatten options</value>
</data>
<data name="UseRobocopyForFileOperations" xml:space="preserve">
<value>Use Robocopy for file operations</value>
</data>
<data name="UseRobocopyForFileOperationsDescription" xml:space="preserve">
<value>Use multi-threaded Robocopy engine for large copy, move, and delete operations</value>
</data>
<data name="RobocopyThreads" xml:space="preserve">
<value>Threads</value>
</data>
<data name="SelectFilesAndFoldersOnHover" xml:space="preserve">
<value>Select files and folders when hovering over them</value>
</data>
Expand Down
6 changes: 4 additions & 2 deletions src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,10 @@ public StatusCenterItem(
SpeedGraphValues = [];
CancelCommand = new RelayCommand(ExecuteCancelCommand);
Message = Strings.DiscoveringItems.GetLocalizedResource();
Source = source;
Destination = destination;
// Status text only uses the first path. Retaining every path keeps large completed
// operations and their source storage objects alive for the lifetime of the card.
Source = source?.Take(1).ToArray();
Destination = destination?.Take(1).ToArray();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No changes needed here, but I wonder whether we actually need Source and Destination. At the very least, they could be made into arrays. There are no usages of them here; however, I didn't check other files that might use them

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are used in src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs:624-640 and are used to build the Status Center card, I have converted it to arrays.


// Get the graph color
if (App.Current.Resources["App.Theme.FillColorAttentionBrush"] is not SolidColorBrush accentBrush)
Expand Down
Loading