From 91ee304c2fa3ae8918b2e06b6b21bc49987c5a48 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Tue, 12 Sep 2023 23:08:24 +0900
Subject: [PATCH 01/97] Initial commit
---
src/Files.App/Files.App.csproj | 1 +
src/Files.App/UserControls/StatusCenter.xaml | 6 +-
.../Utils/StatusCenter/StatusCenterItem.cs | 75 ++++++++++++++++++-
.../StatusCenterItemProgressModel.cs | 8 ++
4 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/src/Files.App/Files.App.csproj b/src/Files.App/Files.App.csproj
index 7321dbe9b3e8..87f5226f38be 100644
--- a/src/Files.App/Files.App.csproj
+++ b/src/Files.App/Files.App.csproj
@@ -82,6 +82,7 @@
+
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter.xaml
index 7f75ebddb7a6..34e79c2197ba 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter.xaml
@@ -7,6 +7,7 @@
xmlns:converters="using:Files.App.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="using:Files.App.Helpers"
+ xmlns:livecharts2="using:LiveChartsCore.SkiaSharpView.WinUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:statuscenter="using:Files.App.Utils.StatusCenter"
xmlns:uc="using:Files.App.UserControls"
@@ -543,7 +544,7 @@
Value="{x:Bind ProgressPercentage, Mode=OneWay}" />
-
+
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index f3f7be546f90..08ebea38d535 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -2,6 +2,12 @@
// Licensed under the MIT License. See the LICENSE.
using System.Windows.Input;
+using SkiaSharp;
+using LiveChartsCore;
+using LiveChartsCore.Drawing;
+using LiveChartsCore.Kernel.Sketches;
+using LiveChartsCore.SkiaSharpView;
+using LiveChartsCore.SkiaSharpView.Painting;
namespace Files.App.Utils.StatusCenter
{
@@ -70,6 +76,58 @@ public bool IsCancelled
set => SetProperty(ref _IsCancelled, value);
}
+ private StatusCenterItemProgressModel _Progress = null!;
+ public StatusCenterItemProgressModel Progress
+ {
+ get => _Progress;
+ set => SetProperty(ref _Progress, value);
+ }
+
+ // (_currentWriteAmount[Mib,kiB,B] - _previousWriteAmount[Mib,kiB,B]) / (pasted seconds[s])
+ private string? _SpeedText;
+ public string? SpeedText
+ {
+ get => _SpeedText;
+ set => SetProperty(ref _SpeedText, value);
+ }
+
+ public ObservableCollection Values { get; set; }
+
+ public ObservableCollection Series { get; set; }
+
+ public IList XAxes { get; set; } = new ICartesianAxis[]
+ {
+ new Axis
+ {
+ Padding = new Padding(0, 0),
+ Labels = new List(),
+ MaxLimit = 100,
+
+ ShowSeparatorLines = false,
+ //SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray)
+ //{
+ // StrokeThickness = 0.5F,
+ // PathEffect = new DashEffect(new float[] { 3, 3 })
+ //}
+ }
+ };
+
+ public IList YAxes { get; set; } = new ICartesianAxis[]
+ {
+ new Axis
+ {
+ Padding = new Padding(0, 0),
+ Labels = new List(),
+
+ ShowSeparatorLines = false,
+ //SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray)
+ //{
+ // StrokeThickness = 0.5F,
+ // PathEffect = new DashEffect(new float[] { 3, 3 })
+ //}
+ }
+ };
+
public CancellationToken CancellationToken
=> _operationCancellationToken?.Token ?? default;
@@ -86,15 +144,13 @@ public bool IsCancelable
public StatusCenterItemIconKind ItemIconKind { get; private set; }
- public readonly StatusCenterItemProgressModel Progress;
-
public readonly Progress ProgressEventSource;
private readonly CancellationTokenSource? _operationCancellationToken;
public ICommand CancelCommand { get; }
- public StatusCenterItem(string message, string title, float progress, ReturnResult status, FileOperationType operation, CancellationTokenSource operationCancellationToken = null)
+ public StatusCenterItem(string message, string title, float progress, ReturnResult status, FileOperationType operation, CancellationTokenSource? operationCancellationToken = null)
{
_operationCancellationToken = operationCancellationToken;
SubHeader = message;
@@ -107,6 +163,19 @@ public StatusCenterItem(string message, string title, float progress, ReturnResu
CancelCommand = new RelayCommand(ExecuteCancelCommand);
+ Values = new();
+
+ Series = new()
+ {
+ new LineSeries
+ {
+ Values = Values,
+ GeometrySize = 0,
+ Stroke = new SolidColorPaint(new(25, 118, 210), 1),
+ DataPadding = new(0, 0),
+ }
+ };
+
switch (FileSystemOperationReturnResult)
{
case ReturnResult.InProgress:
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index 082324384e68..ae610305817a 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -14,6 +14,14 @@ public class StatusCenterItemProgressModel : ObservableObject
private bool _criticalReport;
+ private int _previousWriteAmount;
+
+ private int _currentWriteAmount;
+
+ private DateTimeOffset _previousProgressUpdate;
+
+ private DateTimeOffset _currentProgressUpdate;
+
private FileSystemStatusCode? _Status;
public FileSystemStatusCode? Status
{
From 96bdacc1d960e3c671ce7257e22f1dc0c32d7660 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Tue, 12 Sep 2023 23:35:02 +0900
Subject: [PATCH 02/97] Update
---
src/Files.App/UserControls/StatusCenter.xaml | 4 +--
.../Utils/StatusCenter/StatusCenterItem.cs | 6 +++++
.../StatusCenterItemProgressModel.cs | 27 ++++++++++++++-----
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter.xaml
index 34e79c2197ba..eb38f9f70b19 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter.xaml
@@ -490,7 +490,7 @@
-
+
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index 08ebea38d535..c571b28cfed5 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -253,6 +253,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
{
Header = $"{HeaderBody} ({ProgressPercentage}%)";
ProgressPercentage = p;
+ SpeedText = $"{Progress.ProcessingSpeed}";
}
}
else if (value.EnumerationCompleted)
@@ -263,19 +264,23 @@ private void ReportProgress(StatusCenterItemProgressModel value)
case (not 0, not 0):
ProgressPercentage = (int)(value.ProcessedSize * 100f / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} ({value.ProcessedSize.ToSizeString()}) / {value.ItemsCount} ({value.TotalSize.ToSizeString()}): {ProgressPercentage}%)";
+ SpeedText = $"{Progress.ProcessingSpeed}";
break;
// In progress, displaying processed size
case (not 0, _):
ProgressPercentage = (int)(value.ProcessedSize * 100 / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedSize.ToSizeString()} / {value.TotalSize.ToSizeString()}: {ProgressPercentage}%)";
+ SpeedText = $"{Progress.ProcessingSpeed}";
break;
// In progress, displaying items count
case (_, not 0):
ProgressPercentage = (int)(value.ProcessedItemsCount * 100 / value.ItemsCount);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} / {value.ItemsCount}: {ProgressPercentage}%)";
+ SpeedText = $"{Progress.ProcessingSpeed}";
break;
default:
Header = $"{HeaderBody}";
+ SpeedText = $"{Progress.ProcessingSpeed}";
break;
}
}
@@ -288,6 +293,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
(_, not 0) => $"{HeaderBody} ({value.ProcessedItemsCount} / ...)",
_ => $"{HeaderBody}",
};
+ SpeedText = $"{Progress.ProcessingSpeed}";
}
_viewModel.NotifyChanges();
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index ae610305817a..ae82a36574a6 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -14,13 +14,9 @@ public class StatusCenterItemProgressModel : ObservableObject
private bool _criticalReport;
- private int _previousWriteAmount;
+ private long _previousWriteAmount;
- private int _currentWriteAmount;
-
- private DateTimeOffset _previousProgressUpdate;
-
- private DateTimeOffset _currentProgressUpdate;
+ private DateTimeOffset _previousProgressUpdateDate;
private FileSystemStatusCode? _Status;
public FileSystemStatusCode? Status
@@ -83,6 +79,13 @@ public long ProcessedItemsCount
set => SetProperty(ref _ProcessedItemsCount, value);
}
+ public long _ProcessingSpeed;
+ public long ProcessingSpeed
+ {
+ get => _ProcessingSpeed;
+ set => SetProperty(ref _ProcessingSpeed, value);
+ }
+
public DateTimeOffset _StartTime;
public DateTimeOffset StartTime
{
@@ -131,7 +134,19 @@ TotalSize is not 0 ||
if (_progress is not null && (_criticalReport || _sampler.CheckNow()))
{
+ var span = DateTimeOffset.Now - _previousProgressUpdateDate;
+ var amountDifferent = ProcessedSize - _previousWriteAmount;
+
+ if (span.Seconds == 0 || amountDifferent == 0)
+ ProcessingSpeed = amountDifferent / span.Seconds;
+ else
+ ProcessingSpeed = 0;
+
+ _previousProgressUpdateDate = DateTimeOffset.Now;
+ _previousWriteAmount = ProcessedSize;
+
_progress.Report(this);
+
_criticalReport = false;
}
}
From 15009978d0c31673db31e90e6a2805a31eab194a Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Wed, 13 Sep 2023 23:24:21 +0900
Subject: [PATCH 03/97] Update
---
src/Files.App/UserControls/StatusCenter.xaml | 7 +++++++
src/Files.App/Utils/StatusCenter/StatusCenterItem.cs | 1 -
.../Utils/StatusCenter/StatusCenterItemProgressModel.cs | 5 ++++-
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter.xaml
index eb38f9f70b19..39799c5ac217 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter.xaml
@@ -571,6 +571,13 @@
XAxes="{x:Bind XAxes}"
YAxes="{x:Bind YAxes}" />
+
+
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index c571b28cfed5..c9e35a026a6f 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -83,7 +83,6 @@ public StatusCenterItemProgressModel Progress
set => SetProperty(ref _Progress, value);
}
- // (_currentWriteAmount[Mib,kiB,B] - _previousWriteAmount[Mib,kiB,B]) / (pasted seconds[s])
private string? _SpeedText;
public string? SpeedText
{
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index ae82a36574a6..5d67b20eaad3 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -137,11 +137,14 @@ TotalSize is not 0 ||
var span = DateTimeOffset.Now - _previousProgressUpdateDate;
var amountDifferent = ProcessedSize - _previousWriteAmount;
- if (span.Seconds == 0 || amountDifferent == 0)
+ if (span.Seconds != 0 && amountDifferent != 0)
ProcessingSpeed = amountDifferent / span.Seconds;
else
ProcessingSpeed = 0;
+ ProcessingSpeed = 100;
+ ProcessingSpeed -= new Random().Next(10);
+
_previousProgressUpdateDate = DateTimeOffset.Now;
_previousWriteAmount = ProcessedSize;
From f757935509aa48327b5650c1c1fd54ff30d50be5 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Fri, 15 Sep 2023 11:42:57 +0900
Subject: [PATCH 04/97] Update
---
src/Files.App/Files.App.csproj | 20 +-
.../StatusCenterStyles.xaml | 363 +++++++++++++++++
src/Files.App/UserControls/StatusCenter.xaml | 373 +-----------------
.../Utils/Archives/ArchiveHelpers.cs | 2 +-
src/Files.App/Utils/Archives/ZipHelpers.cs | 12 +-
.../Utils/StatusCenter/StatusCenterItem.cs | 16 +-
.../Operations/FilesystemOperations.cs | 55 ++-
7 files changed, 431 insertions(+), 410 deletions(-)
create mode 100644 src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
diff --git a/src/Files.App/Files.App.csproj b/src/Files.App/Files.App.csproj
index e3e414e9b890..5797706867f9 100644
--- a/src/Files.App/Files.App.csproj
+++ b/src/Files.App/Files.App.csproj
@@ -1,4 +1,4 @@
-
+
@@ -68,12 +68,6 @@
-
-
-
-
-
-
@@ -139,16 +133,4 @@
-
-
- $(DefaultXamlRuntime)
-
-
- $(DefaultXamlRuntime)
-
-
- MSBuild:Compile
-
-
-
diff --git a/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml b/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
new file mode 100644
index 000000000000..4dd35bac125a
--- /dev/null
+++ b/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
@@ -0,0 +1,363 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter.xaml
index 39799c5ac217..819f98b9e7dc 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter.xaml
@@ -4,383 +4,20 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
- xmlns:converters="using:Files.App.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="using:Files.App.Helpers"
xmlns:livecharts2="using:LiveChartsCore.SkiaSharpView.WinUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:statuscenter="using:Files.App.Utils.StatusCenter"
xmlns:uc="using:Files.App.UserControls"
- xmlns:wctconverters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:wcttriggers="using:CommunityToolkit.WinUI.UI.Triggers"
mc:Ignorable="d">
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -673,6 +310,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/Files.App/Utils/Archives/ArchiveHelpers.cs b/src/Files.App/Utils/Archives/ArchiveHelpers.cs
index 43a8b0a6cc3b..d9e462d0411b 100644
--- a/src/Files.App/Utils/Archives/ArchiveHelpers.cs
+++ b/src/Files.App/Utils/Archives/ArchiveHelpers.cs
@@ -73,7 +73,7 @@ public static async Task CompressArchiveAsync(IArchiveCreator creator)
(
"CompressionInProgress".GetLocalizedResource(),
archivePath,
- 0,
+ initialProgress: 0,
ReturnResult.InProgress,
FileOperationType.Compressed,
compressionToken
diff --git a/src/Files.App/Utils/Archives/ZipHelpers.cs b/src/Files.App/Utils/Archives/ZipHelpers.cs
index ce9199568f44..313b4387761e 100644
--- a/src/Files.App/Utils/Archives/ZipHelpers.cs
+++ b/src/Files.App/Utils/Archives/ZipHelpers.cs
@@ -86,7 +86,17 @@ public static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFold
int entriesFinished = 0;
var minimumTime = new DateTime(1);
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress, entriesAmount);
+ ulong totalSize = 0;
+ foreach (var item in zipFile.ArchiveFileData)
+ totalSize += item.Size;
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ enumerationCompleted: true,
+ FileSystemStatusCode.InProgress,
+ entriesAmount,
+ (long)totalSize);
+
fsProgress.Report();
foreach (var entry in fileEntries)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index 6696e6d11f4b..706c6e7f4a1e 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -8,6 +8,7 @@
using LiveChartsCore.Kernel.Sketches;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
+using LiveChartsCore.Defaults;
namespace Files.App.Utils.StatusCenter
{
@@ -90,7 +91,7 @@ public string? SpeedText
set => SetProperty(ref _SpeedText, value);
}
- public ObservableCollection Values { get; set; }
+ public ObservableCollection Values { get; set; }
public ObservableCollection Series { get; set; }
@@ -166,7 +167,7 @@ public StatusCenterItem(string message, string title, float progress, ReturnResu
Series = new()
{
- new LineSeries
+ new LineSeries
{
Values = Values,
GeometrySize = 0,
@@ -262,23 +263,25 @@ private void ReportProgress(StatusCenterItemProgressModel value)
case (not 0, not 0):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} ({value.ProcessedSize.ToSizeString()}) / {value.ItemsCount} ({value.TotalSize.ToSizeString()}): {ProgressPercentage}%)";
- SpeedText = $"{Progress.ProcessingSpeed}";
+ SpeedText = $"{value.ProcessedItemsCount:0} items ({value.ProcessingSizeSpeed:0.00} bytes) / second";
+ Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying processed size
case (not 0, _):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedSize.ToSizeString()} / {value.TotalSize.ToSizeString()}: {ProgressPercentage}%)";
- SpeedText = $"{Progress.ProcessingSpeed}";
+ SpeedText = $"{value.ProcessingSizeSpeed:0.00} bytes / second";
+ Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying items count
case (_, not 0):
ProgressPercentage = (int)(value.ProcessedItemsCount * 100.0 / value.ItemsCount);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} / {value.ItemsCount}: {ProgressPercentage}%)";
- SpeedText = $"{Progress.ProcessingSpeed}";
+ SpeedText = $"{value.ProcessedItemsCount:0} items / second";
+ Values.Add(new(value.ProcessedItemsCount * 100.0 / value.ItemsCount, value.ProcessingItemsCountSpeed));
break;
default:
Header = $"{HeaderBody}";
- SpeedText = $"{Progress.ProcessingSpeed}";
break;
}
}
@@ -291,7 +294,6 @@ private void ReportProgress(StatusCenterItemProgressModel value)
(_, not 0) => $"{HeaderBody} ({value.ProcessedItemsCount} / ...)",
_ => $"{HeaderBody}",
};
- SpeedText = $"{Progress.ProcessingSpeed}";
}
_viewModel.NotifyChanges();
diff --git a/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
index 0d75c8833431..6d07963f08d6 100644
--- a/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
@@ -18,7 +18,7 @@ public class FilesystemOperations : IFilesystemOperations
public FilesystemOperations(IShellPage associatedInstance)
{
- this._associatedInstance = associatedInstance;
+ _associatedInstance = associatedInstance;
}
public async Task<(IStorageHistory, IStorageItem)> CreateAsync(IStorageItemWithPath source, IProgress progress, CancellationToken cancellationToken, bool asAdmin = false)
@@ -109,7 +109,13 @@ public Task CopyAsync(IStorageItem source, string destination,
public async Task CopyAsync(IStorageItemWithPath source, string destination, NameCollisionOption collision, IProgress progress, CancellationToken cancellationToken)
{
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress);
+
+ // TODO: Get total size
+
fsProgress.Report();
if (destination.StartsWith(Constants.UserEnvironmentPaths.RecycleBinPath, StringComparison.Ordinal))
@@ -125,7 +131,6 @@ await DialogDisplayHelper.ShowDialogAsync(
}
IStorageItem copiedItem = null;
- //long itemSize = await FilesystemHelpers.GetItemSize(await source.ToStorageItem(associatedInstance));
if (source.ItemType == FilesystemItemType.Directory)
{
@@ -289,7 +294,13 @@ public Task MoveAsync(IStorageItem source, string destination,
public async Task MoveAsync(IStorageItemWithPath source, string destination, NameCollisionOption collision, IProgress progress, CancellationToken cancellationToken)
{
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress);
+
+ // TODO: Get total size
+
fsProgress.Report();
if (source.Path == destination)
@@ -321,8 +332,6 @@ await DialogDisplayHelper.ShowDialogAsync(
IStorageItem movedItem = null;
- //long itemSize = await FilesystemHelpers.GetItemSize(await source.ToStorageItem(associatedInstance));
-
if (source.ItemType == FilesystemItemType.Directory)
{
// Also check if user tried to move anything above the source.ItemPath
@@ -465,7 +474,13 @@ public Task DeleteAsync(IStorageItem source, IProgress DeleteAsync(IStorageItemWithPath source, IProgress progress, bool permanently, CancellationToken cancellationToken)
{
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress);
+
+ // TODO: Get total size
+
fsProgress.Report();
bool deleteFromRecycleBin = RecycleBinHelpers.IsPathUnderRecycleBin(source.Path);
@@ -547,15 +562,18 @@ public Task RenameAsync(IStorageItem source, string newName, Na
return RenameAsync(StorageHelpers.FromStorageItem(source), newName, collision, progress, cancellationToken);
}
- public async Task RenameAsync(IStorageItemWithPath source,
- string newName,
- NameCollisionOption collision,
- IProgress progress,
- CancellationToken cancellationToken,
- bool asAdmin = false)
+ public async Task RenameAsync(
+ IStorageItemWithPath source,
+ string newName,
+ NameCollisionOption collision,
+ IProgress progress,
+ CancellationToken cancellationToken,
+ bool asAdmin = false)
{
StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ // TODO: Get total size
+
fsProgress.Report();
if (Path.GetFileName(source.Path) == newName && collision == NameCollisionOption.FailIfExists)
@@ -652,11 +670,12 @@ public async Task RestoreItemsFromTrashAsync(IList item.FromStorageItem()).ToListAsync(), destination, progress, cancellationToken);
}
- public async Task RestoreItemsFromTrashAsync(IList source,
- IList destination,
- IProgress progress,
- CancellationToken token,
- bool asAdmin = false)
+ public async Task RestoreItemsFromTrashAsync(
+ IList source,
+ IList destination,
+ IProgress progress,
+ CancellationToken token,
+ bool asAdmin = false)
{
StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress, source.Count);
fsProgress.Report();
From fcd3824938301b97bb5aa6f001a920273bf8402a Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Fri, 15 Sep 2023 23:45:10 +0900
Subject: [PATCH 05/97] Update
---
.../Utils/StatusCenter/StatusCenterItem.cs | 3 +
.../StatusCenterItemProgressModel.cs | 10 ++++
.../Storage/Helpers/FileOperationsHelpers.cs | 58 +++++++++++++++----
.../Operations/ShellFilesystemOperations.cs | 34 ++++++++++-
4 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index 706c6e7f4a1e..f2a453768bdb 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -253,6 +253,9 @@ private void ReportProgress(StatusCenterItemProgressModel value)
{
Header = $"{HeaderBody} ({ProgressPercentage:0}%)";
ProgressPercentage = (int)p;
+
+ SpeedText = $"{value.ProcessedItemsCount:0} items ({value.ProcessingSizeSpeed:0.00} bytes) / second";
+ Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
}
}
else if (value.EnumerationCompleted)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index aba3135b8398..a5ae7253b0ae 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -141,6 +141,7 @@ public void Report(double? percentage = null)
{
Percentage = percentage;
+ // Set the progress state as success
if ((EnumerationCompleted &&
ProcessedItemsCount == ItemsCount &&
ProcessedSize == TotalSize &&
@@ -151,6 +152,7 @@ TotalSize is not 0 ||
_Status = FileSystemStatusCode.Success;
}
+ // Set time at completed when succeed
if (_Status is FileSystemStatusCode.Success)
CompletedTime = DateTimeOffset.Now;
@@ -165,10 +167,18 @@ TotalSize is not 0 ||
PropertyChanged?.Invoke(this, new(propertyName));
}
}
+
+ if (ProcessedSize == 0 && Percentage is not null)
+ ProcessedSize = TotalSize * (long)(Percentage / 100);
+
ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+
+ // NOTE: This won't work yet
ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+
PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
+
_progress?.Report(this);
_previousReportTime = DateTimeOffset.Now;
_previousProcessedSize = ProcessedSize;
diff --git a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
index cb67b489a45d..582cf11a34b9 100644
--- a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
+++ b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
@@ -444,7 +444,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in fileToCopyPath)
+ {
+ totalSize += FileOperationsHelpers.GetFileSize(item);
+ }
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ fileToCopyPath.Count(),
+ totalSize);
+
fsProgress.Report();
progressHandler ??= new();
@@ -454,24 +466,32 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
var shellOperationResult = new ShellOperationResult();
- op.Options = ShellFileOperations.OperationFlags.NoConfirmMkDir
- | ShellFileOperations.OperationFlags.Silent
- | ShellFileOperations.OperationFlags.NoErrorUI;
+ op.Options =
+ ShellFileOperations.OperationFlags.NoConfirmMkDir |
+ ShellFileOperations.OperationFlags.Silent |
+ ShellFileOperations.OperationFlags.NoErrorUI;
+
if (asAdmin)
{
- op.Options |= ShellFileOperations.OperationFlags.ShowElevationPrompt
- | ShellFileOperations.OperationFlags.RequireElevation;
+ op.Options |=
+ ShellFileOperations.OperationFlags.ShowElevationPrompt |
+ ShellFileOperations.OperationFlags.RequireElevation;
}
+
op.OwnerWindow = (IntPtr)ownerHwnd;
- op.Options |= !overwriteOnCopy ? ShellFileOperations.OperationFlags.PreserveFileExtensions | ShellFileOperations.OperationFlags.RenameOnCollision
- : ShellFileOperations.OperationFlags.NoConfirmation;
+ op.Options |=
+ !overwriteOnCopy
+ ? ShellFileOperations.OperationFlags.PreserveFileExtensions | ShellFileOperations.OperationFlags.RenameOnCollision
+ : ShellFileOperations.OperationFlags.NoConfirmation;
for (var i = 0; i < fileToCopyPath.Length; i++)
{
if (!SafetyExtensions.IgnoreExceptions(() =>
{
- using ShellItem shi = new ShellItem(fileToCopyPath[i]);
- using ShellFolder shd = new ShellFolder(Path.GetDirectoryName(copyDestination[i]));
+ using ShellItem shi = new(fileToCopyPath[i]);
+ using ShellFolder shd = new(Path.GetDirectoryName(copyDestination[i]));
+
+ // Performa copy operation
op.QueueCopyOperation(shi, shd, Path.GetFileName(copyDestination[i]));
}))
{
@@ -807,6 +827,24 @@ private static void UpdateFileTagsDb(ShellFileOperations.ShellFileOpEventArgs e,
public static void WaitForCompletion()
=> progressHandler?.WaitForCompletion();
+ public static long GetFileSize(string path)
+ {
+ var hFile = Kernel32.CreateFile(
+ path,
+ Kernel32.FileAccess.FILE_READ_ATTRIBUTES,
+ FileShare.Read,
+ null,
+ FileMode.Open,
+ 0,
+ null);
+
+ Kernel32.GetFileSizeEx(hFile, out var size);
+
+ hFile.Dispose();
+
+ return size;
+ }
+
private class ProgressHandler : Disposable
{
private readonly ManualResetEvent operationsCompletedEvent;
diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
index 2d88fd8f0b0c..3e81b9b2e52d 100644
--- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
@@ -43,8 +43,12 @@ public async Task CopyItemsAsync(IList so
// Fallback to built-in file operations
return await _filesystemOperations.CopyItemsAsync(source, destination, collisions, progress, cancellationToken);
}
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ source.Count);
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
fsProgress.Report();
var sourceNoSkip = source.Zip(collisions, (src, coll) => new { src, coll }).Where(item => item.coll != FileNameConflictResolveOptionType.Skip).Select(item => item.src);
@@ -343,7 +347,19 @@ public async Task DeleteItemsAsync(IList
return await _filesystemOperations.DeleteItemsAsync(source, progress, permanently, cancellationToken);
}
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in source)
+ {
+ totalSize += FileOperationsHelpers.GetFileSize(item.Path);
+ }
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ source.Count,
+ totalSize);
+
fsProgress.Report();
var deleteFilePaths = source.Select(s => s.Path).Distinct();
@@ -457,7 +473,19 @@ public async Task MoveItemsAsync(IList so
return await _filesystemOperations.MoveItemsAsync(source, destination, collisions, progress, cancellationToken);
}
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in source)
+ {
+ totalSize += FileOperationsHelpers.GetFileSize(item.Path);
+ }
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ source.Count,
+ totalSize);
+
fsProgress.Report();
var sourceNoSkip = source.Zip(collisions, (src, coll) => new { src, coll }).Where(item => item.coll != FileNameConflictResolveOptionType.Skip).Select(item => item.src);
From 67c03fa926c253b87e98dfe57bd1f116bde9eb75 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sat, 16 Sep 2023 00:04:43 +0900
Subject: [PATCH 06/97] Update
---
.../Utils/StatusCenter/StatusCenterItemProgressModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index a5ae7253b0ae..d2e23d3a8c56 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -169,7 +169,7 @@ TotalSize is not 0 ||
}
if (ProcessedSize == 0 && Percentage is not null)
- ProcessedSize = TotalSize * (long)(Percentage / 100);
+ ProcessedSize = (long)((double)TotalSize * Percentage / 100);
ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
From d20e14a35b9ae03692354ba524df4ac57fc87c37 Mon Sep 17 00:00:00 2001
From: Marco Gavelli
Date: Sat, 16 Sep 2023 13:05:25 +0200
Subject: [PATCH 07/97] Speed calc
---
.../StatusCenterItemProgressModel.cs | 22 +++++++++++--------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index d2e23d3a8c56..ba2455183442 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -168,21 +168,25 @@ TotalSize is not 0 ||
}
}
- if (ProcessedSize == 0 && Percentage is not null)
+ if (Percentage is not null)
ProcessedSize = (long)((double)TotalSize * Percentage / 100);
- ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+ if (ProcessedSize != _previousProcessedSize)
+ {
+ ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+
+ // NOTE: This won't work yet
+ ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
- // NOTE: This won't work yet
- ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+ PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
+ PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
- PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
- PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
+ _previousReportTime = DateTimeOffset.Now;
+ _previousProcessedSize = ProcessedSize;
+ _previousProcessedItemsCount = ProcessedItemsCount;
+ }
_progress?.Report(this);
- _previousReportTime = DateTimeOffset.Now;
- _previousProcessedSize = ProcessedSize;
- _previousProcessedItemsCount = ProcessedItemsCount;
}
}
From feaeea721ae1166e2853bd951fac49d38bb2dcfe Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sat, 16 Sep 2023 23:56:27 +0900
Subject: [PATCH 08/97] Update
---
src/Files.App/Extensions/StringExtensions.cs | 1 +
src/Files.App/UserControls/StatusCenter.xaml | 33 ++++++++++++++-----
.../Utils/StatusCenter/StatusCenterItem.cs | 31 +++++++++++++----
.../StatusCenterItemProgressModel.cs | 17 +++++-----
.../Storage/Helpers/FileOperationsHelpers.cs | 30 +++++++++++++++--
.../Operations/ShellFilesystemOperations.cs | 10 +++++-
6 files changed, 95 insertions(+), 27 deletions(-)
diff --git a/src/Files.App/Extensions/StringExtensions.cs b/src/Files.App/Extensions/StringExtensions.cs
index 06d9166ad1d5..d3be80df286f 100644
--- a/src/Files.App/Extensions/StringExtensions.cs
+++ b/src/Files.App/Extensions/StringExtensions.cs
@@ -79,6 +79,7 @@ public static string ConvertSizeAbbreviation(this string value)
return value;
}
+ public static string ToSizeString(this double size) => ByteSize.FromBytes(size).ToSizeString();
public static string ToSizeString(this long size) => ByteSize.FromBytes(size).ToSizeString();
public static string ToSizeString(this ulong size) => ByteSize.FromBytes(size).ToSizeString();
public static string ToSizeString(this ByteSize size) => size.ToBinaryString().ConvertSizeAbbreviation();
diff --git a/src/Files.App/UserControls/StatusCenter.xaml b/src/Files.App/UserControls/StatusCenter.xaml
index 819f98b9e7dc..3e534e66efc5 100644
--- a/src/Files.App/UserControls/StatusCenter.xaml
+++ b/src/Files.App/UserControls/StatusCenter.xaml
@@ -185,7 +185,7 @@
x:Name="MainGraphCartesianChartClipGrid"
Height="64"
Margin="4,8,0,8"
- BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
+ BorderBrush="{ThemeResource ControlStrongStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="4"
Visibility="{x:Bind IsExpanded, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
@@ -202,18 +202,33 @@
-
+
+
+
+
+
+
+
@@ -352,7 +367,7 @@
-
+
{
Values = Values,
- GeometrySize = 0,
- Stroke = new SolidColorPaint(new(25, 118, 210), 1),
+ GeometrySize = 0d,
DataPadding = new(0, 0),
+ IsHoverable = false,
+
+ // Stroke
+ Stroke = new SolidColorPaint(
+ new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B),
+ 1),
+
+ // Fill under the stroke
+ Fill = new LinearGradientPaint(
+ new SKColor[] {
+ new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 50),
+ new(accentBrush.Color.R, accentBrush.Color.G, accentBrush.Color.B, 10)
+ },
+ new(0.5f, 0f),
+ new(0.5f, 1.0f),
+ new[] { 0.2f, 1.3f }),
}
};
@@ -254,7 +273,7 @@ private void ReportProgress(StatusCenterItemProgressModel value)
Header = $"{HeaderBody} ({ProgressPercentage:0}%)";
ProgressPercentage = (int)p;
- SpeedText = $"{value.ProcessedItemsCount:0} items ({value.ProcessingSizeSpeed:0.00} bytes) / second";
+ SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
}
}
@@ -266,21 +285,21 @@ private void ReportProgress(StatusCenterItemProgressModel value)
case (not 0, not 0):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} ({value.ProcessedSize.ToSizeString()}) / {value.ItemsCount} ({value.TotalSize.ToSizeString()}): {ProgressPercentage}%)";
- SpeedText = $"{value.ProcessedItemsCount:0} items ({value.ProcessingSizeSpeed:0.00} bytes) / second";
+ SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying processed size
case (not 0, _):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
Header = $"{HeaderBody} ({value.ProcessedSize.ToSizeString()} / {value.TotalSize.ToSizeString()}: {ProgressPercentage}%)";
- SpeedText = $"{value.ProcessingSizeSpeed:0.00} bytes / second";
+ SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying items count
case (_, not 0):
ProgressPercentage = (int)(value.ProcessedItemsCount * 100.0 / value.ItemsCount);
Header = $"{HeaderBody} ({value.ProcessedItemsCount} / {value.ItemsCount}: {ProgressPercentage}%)";
- SpeedText = $"{value.ProcessedItemsCount:0} items / second";
+ SpeedText = $"{value.ProcessedItemsCount:0} items/s";
Values.Add(new(value.ProcessedItemsCount * 100.0 / value.ItemsCount, value.ProcessingItemsCountSpeed));
break;
default:
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index d2e23d3a8c56..15e031d83dbf 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -139,8 +139,6 @@ private void SetProperty(ref T field, T value, [CallerMemberName] string? pro
public void Report(double? percentage = null)
{
- Percentage = percentage;
-
// Set the progress state as success
if ((EnumerationCompleted &&
ProcessedItemsCount == ItemsCount &&
@@ -168,17 +166,20 @@ TotalSize is not 0 ||
}
}
- if (ProcessedSize == 0 && Percentage is not null)
- ProcessedSize = (long)((double)TotalSize * Percentage / 100);
-
- ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+ if (percentage is not null && Percentage != percentage)
+ {
+ ProcessedSize = (long)(TotalSize * percentage / 100);
+ ProcessingSizeSpeed = (ProcessedSize - _previousProcessedSize) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
- // NOTE: This won't work yet
- ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+ // NOTE: This won't work yet
+ ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
+ }
PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
+ Percentage = percentage;
+
_progress?.Report(this);
_previousReportTime = DateTimeOffset.Now;
_previousProcessedSize = ProcessedSize;
diff --git a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
index 582cf11a34b9..c039043fb0d0 100644
--- a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
+++ b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
@@ -199,7 +199,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in fileToDeletePath)
+ {
+ totalSize += GetFileSize(item);
+ }
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ fileToDeletePath.Count(),
+ totalSize);
+
fsProgress.Report();
progressHandler ??= new();
@@ -359,7 +371,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in fileToMovePath)
+ {
+ totalSize += GetFileSize(item);
+ }
+
+ StatusCenterItemProgressModel fsProgress = new(
+ progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ fileToMovePath.Count(),
+ totalSize);
+
fsProgress.Report();
progressHandler ??= new();
@@ -447,7 +471,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
long totalSize = 0;
foreach (var item in fileToCopyPath)
{
- totalSize += FileOperationsHelpers.GetFileSize(item);
+ totalSize += GetFileSize(item);
}
StatusCenterItemProgressModel fsProgress = new(
diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
index 3e81b9b2e52d..f60ad064e446 100644
--- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
@@ -43,11 +43,19 @@ public async Task CopyItemsAsync(IList so
// Fallback to built-in file operations
return await _filesystemOperations.CopyItemsAsync(source, destination, collisions, progress, cancellationToken);
}
+
+ long totalSize = 0;
+ foreach (var item in source)
+ {
+ totalSize += FileOperationsHelpers.GetFileSize(item.Path);
+ }
+
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count);
+ source.Count(),
+ totalSize);
fsProgress.Report();
From 181552f9062c99ad7239cff651103db1d7bafe08 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 00:04:15 +0900
Subject: [PATCH 09/97] Update
---
.../Storage/Helpers/FileOperationsHelpers.cs | 8 +--
.../Storage/Operations/FilesystemHelpers.cs | 69 ++-----------------
.../Operations/ShellFilesystemOperations.cs | 4 +-
3 files changed, 13 insertions(+), 68 deletions(-)
diff --git a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
index c039043fb0d0..c2c74ad0e26f 100644
--- a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
+++ b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
@@ -200,7 +200,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
long totalSize = 0;
- foreach (var item in fileToDeletePath)
+ foreach (var item in fileToCopyPath)
{
totalSize += GetFileSize(item);
}
@@ -209,7 +209,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progress,
true,
FileSystemStatusCode.InProgress,
- fileToDeletePath.Count(),
+ fileToCopyPath.Count(),
totalSize);
fsProgress.Report();
@@ -372,7 +372,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
long totalSize = 0;
- foreach (var item in fileToMovePath)
+ foreach (var item in fileToCopyPath)
{
totalSize += GetFileSize(item);
}
@@ -381,7 +381,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progress,
true,
FileSystemStatusCode.InProgress,
- fileToMovePath.Count(),
+ fileToCopyPath.Count(),
totalSize);
fsProgress.Report();
diff --git a/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.cs b/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.cs
index 9e574df7e537..35b551211e79 100644
--- a/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.cs
+++ b/src/Files.App/Utils/Storage/Operations/FilesystemHelpers.cs
@@ -19,8 +19,6 @@ namespace Files.App.Utils.Storage
{
public sealed class FilesystemHelpers : IFilesystemHelpers
{
- #region Private Members
-
private readonly static StatusCenterViewModel _statusCenterViewModel = Ioc.Default.GetRequiredService();
private IShellPage associatedInstance;
@@ -30,9 +28,6 @@ public sealed class FilesystemHelpers : IFilesystemHelpers
private ItemManipulationModel itemManipulationModel => associatedInstance.SlimContentPage?.ItemManipulationModel;
private readonly CancellationToken cancellationToken;
-
- #region Helpers Members
-
private static char[] RestrictedCharacters
{
get
@@ -55,18 +50,7 @@ private static char[] RestrictedCharacters
"LPT6", "LPT7", "LPT8", "LPT9"
};
- #endregion Helpers Members
-
- #endregion Private Members
-
- #region Properties
-
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService();
-
- #endregion
-
- #region Constructor
-
public FilesystemHelpers(IShellPage associatedInstance, CancellationToken cancellationToken)
{
this.associatedInstance = associatedInstance;
@@ -74,13 +58,6 @@ public FilesystemHelpers(IShellPage associatedInstance, CancellationToken cancel
jumpListService = Ioc.Default.GetRequiredService();
filesystemOperations = new ShellFilesystemOperations(this.associatedInstance);
}
-
- #endregion Constructor
-
- #region IFilesystemHelpers
-
- #region Create
-
public async Task<(ReturnResult, IStorageItem)> CreateAsync(IStorageItemWithPath source, bool registerHistory)
{
var returnStatus = ReturnResult.InProgress;
@@ -106,10 +83,6 @@ await DialogDisplayHelper.ShowDialogAsync(
return (returnStatus, result.Item2);
}
- #endregion Create
-
- #region Delete
-
public async Task DeleteItemsAsync(IEnumerable source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
{
source = await source.ToListAsync();
@@ -198,10 +171,6 @@ public Task DeleteItemsAsync(IEnumerable source, Del
public Task DeleteItemAsync(IStorageItem source, DeleteConfirmationPolicies showDialog, bool permanently, bool registerHistory)
=> DeleteItemAsync(source.FromStorageItem(), showDialog, permanently, registerHistory);
- #endregion Delete
-
- #region Restore
-
public Task RestoreItemFromTrashAsync(IStorageItem source, string destination, bool registerHistory)
=> RestoreItemFromTrashAsync(source.FromStorageItem(), destination, registerHistory);
@@ -237,14 +206,13 @@ public async Task RestoreItemsFromTrashAsync(IEnumerable PerformOperationTypeAsync(DataPackageOperation operation,
- DataPackageView packageView,
- string destination,
- bool showDialog,
- bool registerHistory,
- bool isTargetExecutable = false)
+ public async Task PerformOperationTypeAsync(
+ DataPackageOperation operation,
+ DataPackageView packageView,
+ string destination,
+ bool showDialog,
+ bool registerHistory,
+ bool isTargetExecutable = false)
{
try
{
@@ -293,8 +261,6 @@ public async Task PerformOperationTypeAsync(DataPackageOperation o
}
}
- #region Copy
-
public Task CopyItemsAsync(IEnumerable source, IEnumerable destination, bool showDialog, bool registerHistory)
=> CopyItemsAsync(source.Select((item) => item.FromStorageItem()), destination, showDialog, registerHistory);
@@ -418,10 +384,6 @@ public async Task CopyItemsFromClipboard(DataPackageView packageVi
return ReturnResult.BadArgumentException;
}
- #endregion Copy
-
- #region Move
-
public Task MoveItemsAsync(IEnumerable source, IEnumerable destination, bool showDialog, bool registerHistory)
=> MoveItemsAsync(source.Select((item) => item.FromStorageItem()), destination, showDialog, registerHistory);
@@ -528,10 +490,6 @@ public async Task MoveItemsFromClipboard(DataPackageView packageVi
return returnStatus;
}
- #endregion Move
-
- #region Rename
-
public Task RenameAsync(IStorageItem source, string newName, NameCollisionOption collision, bool registerHistory, bool showExtensionDialog = true)
=> RenameAsync(source.FromStorageItem(), newName, collision, registerHistory, showExtensionDialog);
@@ -595,8 +553,6 @@ await DialogDisplayHelper.ShowDialogAsync(
return returnStatus;
}
- #endregion Rename
-
public async Task CreateShortcutFromClipboard(DataPackageView packageView, string destination, bool showDialog, bool registerHistory)
{
if (!HasDraggedStorageItems(packageView))
@@ -645,9 +601,6 @@ public async Task RecycleItemsFromClipboard(DataPackageView packag
return returnStatus;
}
-
- #endregion IFilesystemHelpers
-
public static bool IsValidForFilename(string name)
=> !string.IsNullOrWhiteSpace(name) && !ContainsRestrictedCharacters(name) && !ContainsRestrictedFileName(name);
@@ -728,8 +681,6 @@ await Ioc.Default.GetRequiredService().TryGetFileAsync(item.
return (newCollisions, false, itemsResult ?? new List());
}
- #region Public Helpers
-
public static bool HasDraggedStorageItems(DataPackageView packageView)
{
return packageView is not null && (packageView.Contains(StandardDataFormats.StorageItems) || packageView.Contains("FileDrop"));
@@ -865,10 +816,6 @@ public static bool ContainsRestrictedFileName(string input)
return false;
}
- #endregion Public Helpers
-
- #region IDisposable
-
public void Dispose()
{
filesystemOperations?.Dispose();
@@ -876,7 +823,5 @@ public void Dispose()
associatedInstance = null;
filesystemOperations = null;
}
-
- #endregion IDisposable
}
}
diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
index f60ad064e446..999e2119034f 100644
--- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
@@ -365,7 +365,7 @@ public async Task DeleteItemsAsync(IList
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count,
+ source.Count(),
totalSize);
fsProgress.Report();
@@ -491,7 +491,7 @@ public async Task MoveItemsAsync(IList so
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count,
+ source.Count(),
totalSize);
fsProgress.Report();
From 5405899d9683d5f3fea4463dc9a04250b47c2071 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 00:25:07 +0900
Subject: [PATCH 10/97] Update
---
.../Compress/BaseCompressArchiveAction.cs | 2 +-
.../Compress/CompressIntoArchiveAction.cs | 22 +++++-----
.../Compress/CompressIntoSevenZipAction.cs | 18 ++++----
.../Compress/CompressIntoZipAction.cs | 18 ++++----
.../Decompress/BaseDecompressArchiveAction.cs | 2 +-
.../Archives/Decompress/DecompressArchive.cs | 2 +-
.../Decompress/DecompressArchiveHere.cs | 2 +-
.../DecompressArchiveToChildFolderAction.cs | 2 +-
.../MenuFlyout/ContextFlyoutItemHelper.cs | 4 +-
...hiveCreator.cs => CompressArchiveModel.cs} | 41 +++++++++++++++----
.../{ArchiveHelpers.cs => CompressHelper.cs} | 17 +++++---
.../{ZipHelpers.cs => DecompressHelper.cs} | 2 +-
...iveCreator.cs => ICompressArchiveModel.cs} | 2 +-
13 files changed, 78 insertions(+), 56 deletions(-)
rename src/Files.App/Utils/Archives/{ArchiveCreator.cs => CompressArchiveModel.cs} (86%)
rename src/Files.App/Utils/Archives/{ArchiveHelpers.cs => CompressHelper.cs} (92%)
rename src/Files.App/Utils/Archives/{ZipHelpers.cs => DecompressHelper.cs} (99%)
rename src/Files.App/Utils/Archives/{IArchiveCreator.cs => ICompressArchiveModel.cs} (97%)
diff --git a/src/Files.App/Actions/Content/Archives/Compress/BaseCompressArchiveAction.cs b/src/Files.App/Actions/Content/Archives/Compress/BaseCompressArchiveAction.cs
index e9e4cb06d6ba..67ad4de8c847 100644
--- a/src/Files.App/Actions/Content/Archives/Compress/BaseCompressArchiveAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Compress/BaseCompressArchiveAction.cs
@@ -13,7 +13,7 @@ internal abstract class BaseCompressArchiveAction : BaseUIAction, IAction
public override bool IsExecutable =>
IsContextPageTypeAdaptedToCommand() &&
- ArchiveHelpers.CanCompress(context.SelectedItems) &&
+ CompressHelper.CanCompress(context.SelectedItems) &&
UIHelpers.CanShowDialog;
public BaseCompressArchiveAction()
diff --git a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoArchiveAction.cs b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoArchiveAction.cs
index 9455c0b42a15..bb7c7a0fd2d7 100644
--- a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoArchiveAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoArchiveAction.cs
@@ -20,7 +20,7 @@ public CompressIntoArchiveAction()
public override async Task ExecuteAsync()
{
- var (sources, directory, fileName) = ArchiveHelpers.GetCompressDestination(context.ShellPage);
+ var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
var dialog = new CreateArchiveDialog
{
@@ -32,18 +32,16 @@ public override async Task ExecuteAsync()
if (!dialog.CanCreate || result != ContentDialogResult.Primary)
return;
- IArchiveCreator creator = new ArchiveCreator
- {
- Sources = sources,
- Directory = directory,
- FileName = dialog.FileName,
- Password = dialog.Password,
- FileFormat = dialog.FileFormat,
- CompressionLevel = dialog.CompressionLevel,
- SplittingSize = dialog.SplittingSize,
- };
+ ICompressArchiveModel creator = new CompressArchiveModel(
+ sources,
+ directory,
+ dialog.FileName,
+ dialog.Password,
+ dialog.FileFormat,
+ dialog.CompressionLevel,
+ dialog.SplittingSize);
- await ArchiveHelpers.CompressArchiveAsync(creator);
+ await CompressHelper.CompressArchiveAsync(creator);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoSevenZipAction.cs b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoSevenZipAction.cs
index 7f4a79e79819..b4a24e40b69d 100644
--- a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoSevenZipAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoSevenZipAction.cs
@@ -6,7 +6,7 @@ namespace Files.App.Actions
internal sealed class CompressIntoSevenZipAction : BaseCompressArchiveAction
{
public override string Label
- => string.Format("CreateNamedArchive".GetLocalizedResource(), $"{ArchiveHelpers.DetermineArchiveNameFromSelection(context.SelectedItems)}.7z");
+ => string.Format("CreateNamedArchive".GetLocalizedResource(), $"{CompressHelper.DetermineArchiveNameFromSelection(context.SelectedItems)}.7z");
public override string Description
=> "CompressIntoSevenZipDescription".GetLocalizedResource();
@@ -17,17 +17,15 @@ public CompressIntoSevenZipAction()
public override Task ExecuteAsync()
{
- var (sources, directory, fileName) = ArchiveHelpers.GetCompressDestination(context.ShellPage);
+ var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
- IArchiveCreator creator = new ArchiveCreator
- {
- Sources = sources,
- Directory = directory,
- FileName = fileName,
- FileFormat = ArchiveFormats.SevenZip,
- };
+ ICompressArchiveModel creator = new CompressArchiveModel(
+ sources,
+ directory,
+ fileName,
+ fileFormat: ArchiveFormats.SevenZip);
- return ArchiveHelpers.CompressArchiveAsync(creator);
+ return CompressHelper.CompressArchiveAsync(creator);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoZipAction.cs b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoZipAction.cs
index 6c473f7beb82..c611d47bacd7 100644
--- a/src/Files.App/Actions/Content/Archives/Compress/CompressIntoZipAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Compress/CompressIntoZipAction.cs
@@ -6,7 +6,7 @@ namespace Files.App.Actions
internal sealed class CompressIntoZipAction : BaseCompressArchiveAction
{
public override string Label
- => string.Format("CreateNamedArchive".GetLocalizedResource(), $"{ArchiveHelpers.DetermineArchiveNameFromSelection(context.SelectedItems)}.zip");
+ => string.Format("CreateNamedArchive".GetLocalizedResource(), $"{CompressHelper.DetermineArchiveNameFromSelection(context.SelectedItems)}.zip");
public override string Description
=> "CompressIntoZipDescription".GetLocalizedResource();
@@ -17,17 +17,15 @@ public CompressIntoZipAction()
public override Task ExecuteAsync()
{
- var (sources, directory, fileName) = ArchiveHelpers.GetCompressDestination(context.ShellPage);
+ var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
- IArchiveCreator creator = new ArchiveCreator
- {
- Sources = sources,
- Directory = directory,
- FileName = fileName,
- FileFormat = ArchiveFormats.Zip,
- };
+ ICompressArchiveModel creator = new CompressArchiveModel(
+ sources,
+ directory,
+ fileName,
+ fileFormat: ArchiveFormats.SevenZip);
- return ArchiveHelpers.CompressArchiveAsync(creator);
+ return CompressHelper.CompressArchiveAsync(creator);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
index 52075e7e7978..f5f47979ab74 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
@@ -16,7 +16,7 @@ public virtual HotKey HotKey
public override bool IsExecutable =>
(IsContextPageTypeAdaptedToCommand() &&
- ArchiveHelpers.CanDecompress(context.SelectedItems) ||
+ CompressHelper.CanDecompress(context.SelectedItems) ||
CanDecompressInsideArchive()) &&
UIHelpers.CanShowDialog;
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
index 62754bf93664..c9ed484b265b 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
@@ -23,7 +23,7 @@ public DecompressArchive()
public override Task ExecuteAsync()
{
- return ArchiveHelpers.DecompressArchive(context.ShellPage);
+ return CompressHelper.DecompressArchive(context.ShellPage);
}
protected override bool CanDecompressInsideArchive()
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
index 7106d0a18bdd..7e0419bfc613 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
@@ -17,7 +17,7 @@ public DecompressArchiveHere()
public override Task ExecuteAsync()
{
- return ArchiveHelpers.DecompressArchiveHere(context.ShellPage);
+ return CompressHelper.DecompressArchiveHere(context.ShellPage);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
index 7d1dbc3c4d35..44836ae649d7 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
@@ -17,7 +17,7 @@ public DecompressArchiveToChildFolderAction()
public override Task ExecuteAsync()
{
- return ArchiveHelpers.DecompressArchiveToChildFolder(context.ShellPage);
+ return CompressHelper.DecompressArchiveToChildFolder(context.ShellPage);
}
protected override void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
diff --git a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
index 3327eac8b7c9..643d3cc54726 100644
--- a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
+++ b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
@@ -503,7 +503,7 @@ public static List GetBaseItemMenuItems(
new ContextMenuFlyoutItemViewModelBuilder(commands.CompressIntoZip).Build(),
new ContextMenuFlyoutItemViewModelBuilder(commands.CompressIntoSevenZip).Build(),
},
- ShowItem = itemsSelected && ArchiveHelpers.CanCompress(selectedItems)
+ ShowItem = itemsSelected && CompressHelper.CanCompress(selectedItems)
},
new ContextMenuFlyoutItemViewModel
{
@@ -519,7 +519,7 @@ public static List GetBaseItemMenuItems(
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveHere).Build(),
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveToChildFolder).Build(),
},
- ShowItem = ArchiveHelpers.CanDecompress(selectedItems)
+ ShowItem = CompressHelper.CanDecompress(selectedItems)
},
new ContextMenuFlyoutItemViewModel()
{
diff --git a/src/Files.App/Utils/Archives/ArchiveCreator.cs b/src/Files.App/Utils/Archives/CompressArchiveModel.cs
similarity index 86%
rename from src/Files.App/Utils/Archives/ArchiveCreator.cs
rename to src/Files.App/Utils/Archives/CompressArchiveModel.cs
index 2da88e9a719e..622837c74781 100644
--- a/src/Files.App/Utils/Archives/ArchiveCreator.cs
+++ b/src/Files.App/Utils/Archives/CompressArchiveModel.cs
@@ -10,7 +10,7 @@ namespace Files.App.Utils.Archives
///
/// Provides an archive creation support.
///
- public class ArchiveCreator : IArchiveCreator
+ public class CompressArchiveModel : ICompressArchiveModel
{
///
/// Represents the total number of items to be processed.
@@ -106,16 +106,38 @@ public IProgress Progress
///
public ArchiveSplittingSizes SplittingSize { get; init; }
- public ArchiveCreator()
+ public CompressArchiveModel(
+ string[] source,
+ string directory,
+ string fileName,
+ string? password = null,
+ ArchiveFormats fileFormat = ArchiveFormats.Zip,
+ ArchiveCompressionLevels compressionLevel = ArchiveCompressionLevels.Normal,
+ ArchiveSplittingSizes splittingSize = ArchiveSplittingSizes.None)
{
- // Initialize
- _fileSystemProgress = new(Progress, true, FileSystemStatusCode.InProgress);
+ long totalSize = 0;
+ foreach (var item in Sources)
+ {
+ totalSize += FileOperationsHelpers.GetFileSize(item);
+ }
+
+ _fileSystemProgress = new(
+ Progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ Sources.Count(),
+ totalSize);
+
_Progress = new Progress();
+
+ Sources = source;
+ Directory = directory;
+ FileName = fileName;
+ Password = password ?? string.Empty;
ArchivePath = string.Empty;
- Sources = Enumerable.Empty();
- FileFormat = ArchiveFormats.Zip;
- CompressionLevel = ArchiveCompressionLevels.Normal;
- SplittingSize = ArchiveSplittingSizes.None;
+ FileFormat = fileFormat;
+ CompressionLevel = compressionLevel;
+ SplittingSize = splittingSize;
_fileSystemProgress.Report(0);
}
@@ -131,7 +153,7 @@ public async Task RunCreationAsync()
{
string[] sources = Sources.ToArray();
- var compressor = new SevenZipCompressor
+ var compressor = new SevenZipCompressor()
{
ArchiveFormat = SevenZipArchiveFormat,
CompressionLevel = SevenZipCompressionLevel,
@@ -142,6 +164,7 @@ public async Task RunCreationAsync()
PreserveDirectoryRoot = sources.Length > 1,
EventSynchronization = EventSynchronizationStrategy.AlwaysAsynchronous,
};
+
compressor.Compressing += Compressor_Compressing;
compressor.CompressionFinished += Compressor_CompressionFinished;
diff --git a/src/Files.App/Utils/Archives/ArchiveHelpers.cs b/src/Files.App/Utils/Archives/CompressHelper.cs
similarity index 92%
rename from src/Files.App/Utils/Archives/ArchiveHelpers.cs
rename to src/Files.App/Utils/Archives/CompressHelper.cs
index d9e462d0411b..554d2ee9b712 100644
--- a/src/Files.App/Utils/Archives/ArchiveHelpers.cs
+++ b/src/Files.App/Utils/Archives/CompressHelper.cs
@@ -11,7 +11,10 @@
namespace Files.App.Utils.Archives
{
- public static class ArchiveHelpers
+ ///
+ /// Provides static helper for compressing archive.
+ ///
+ public static class CompressHelper
{
private readonly static StatusCenterViewModel _statusCenterViewModel = Ioc.Default.GetRequiredService();
@@ -59,7 +62,7 @@ public static (string[] Sources, string directory, string fileName) GetCompressD
return (sources, directory, fileName);
}
- public static async Task CompressArchiveAsync(IArchiveCreator creator)
+ public static async Task CompressArchiveAsync(ICompressArchiveModel creator)
{
var archivePath = creator.GetArchivePath();
@@ -110,6 +113,8 @@ public static async Task CompressArchiveAsync(IArchiveCreator creator)
}
}
+ // TODO: Move all below code to DecompressHelper class
+
private static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFolder? destinationFolder, string password)
{
if (archive is null || destinationFolder is null)
@@ -125,7 +130,7 @@ private static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFol
FileOperationType.Extract,
extractCancellation);
- await FilesystemTasks.Wrap(() => ZipHelpers.ExtractArchive(archive, destinationFolder, password, banner.ProgressEventSource, extractCancellation.Token));
+ await FilesystemTasks.Wrap(() => DecompressHelper.ExtractArchive(archive, destinationFolder, password, banner.ProgressEventSource, extractCancellation.Token));
_statusCenterViewModel.RemoveItem(banner);
@@ -149,7 +154,7 @@ public static async Task DecompressArchive(IShellPage associatedInstance)
if (archive is null)
return;
- var isArchiveEncrypted = await FilesystemTasks.Wrap(() => ZipHelpers.IsArchiveEncrypted(archive));
+ var isArchiveEncrypted = await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive));
var password = string.Empty;
DecompressArchiveDialog decompressArchiveDialog = new();
@@ -197,7 +202,7 @@ public static async Task DecompressArchiveHere(IShellPage associatedInstance)
BaseStorageFile archive = await StorageHelpers.ToStorageItem(selectedItem.ItemPath);
BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
- if (await FilesystemTasks.Wrap(() => ZipHelpers.IsArchiveEncrypted(archive)))
+ if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
{
DecompressArchiveDialog decompressArchiveDialog = new();
DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
@@ -232,7 +237,7 @@ public static async Task DecompressArchiveToChildFolder(IShellPage associatedIns
BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
BaseStorageFolder destinationFolder = null;
- if (await FilesystemTasks.Wrap(() => ZipHelpers.IsArchiveEncrypted(archive)))
+ if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
{
DecompressArchiveDialog decompressArchiveDialog = new();
DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
diff --git a/src/Files.App/Utils/Archives/ZipHelpers.cs b/src/Files.App/Utils/Archives/DecompressHelper.cs
similarity index 99%
rename from src/Files.App/Utils/Archives/ZipHelpers.cs
rename to src/Files.App/Utils/Archives/DecompressHelper.cs
index 313b4387761e..a4acf926643d 100644
--- a/src/Files.App/Utils/Archives/ZipHelpers.cs
+++ b/src/Files.App/Utils/Archives/DecompressHelper.cs
@@ -7,7 +7,7 @@
namespace Files.App.Utils.Archives
{
- public static class ZipHelpers
+ public static class DecompressHelper
{
private static async Task GetZipFile(BaseStorageFile archive, string password = "")
{
diff --git a/src/Files.App/Utils/Archives/IArchiveCreator.cs b/src/Files.App/Utils/Archives/ICompressArchiveModel.cs
similarity index 97%
rename from src/Files.App/Utils/Archives/IArchiveCreator.cs
rename to src/Files.App/Utils/Archives/ICompressArchiveModel.cs
index b7af5a9134b1..e61b3e0e808f 100644
--- a/src/Files.App/Utils/Archives/IArchiveCreator.cs
+++ b/src/Files.App/Utils/Archives/ICompressArchiveModel.cs
@@ -6,7 +6,7 @@ namespace Files.App.Utils.Archives
///
/// Represents an interface for archive creation support.
///
- public interface IArchiveCreator
+ public interface ICompressArchiveModel
{
///
/// File path to archive.
From 80b2e5f100e75c0bc9ff74ebe26ec898834e13a1 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 00:27:36 +0900
Subject: [PATCH 11/97] Update
src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
Co-authored-by: Steve
---
src/Files.App/Utils/StatusCenter/StatusCenterItem.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index 2719f56c308d..8bd21ee885a2 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -151,7 +151,7 @@ public bool IsCancelable
public ICommand CancelCommand { get; }
- public StatusCenterItem(string message, string title, float progress, ReturnResult status, FileOperationType operation, CancellationTokenSource? operationCancellationToken = null)
+ public StatusCenterItem(string message, string title, float progress, ReturnResult status, FileOperationType operation, CancellationTokenSource operationCancellationToken = default)
{
_operationCancellationToken = operationCancellationToken;
SubHeader = message;
From 6f9fe761aa14957719024f7deeed811d9cec73b7 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 00:40:39 +0900
Subject: [PATCH 12/97] Remove unncessary comments
---
.../Utils/Storage/Operations/FilesystemOperations.cs | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
index 6d07963f08d6..c6e6f6bd17c6 100644
--- a/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/FilesystemOperations.cs
@@ -114,8 +114,6 @@ public async Task CopyAsync(IStorageItemWithPath source, string
true,
FileSystemStatusCode.InProgress);
- // TODO: Get total size
-
fsProgress.Report();
if (destination.StartsWith(Constants.UserEnvironmentPaths.RecycleBinPath, StringComparison.Ordinal))
@@ -299,8 +297,6 @@ public async Task MoveAsync(IStorageItemWithPath source, string
true,
FileSystemStatusCode.InProgress);
- // TODO: Get total size
-
fsProgress.Report();
if (source.Path == destination)
@@ -479,8 +475,6 @@ public async Task DeleteAsync(IStorageItemWithPath source, IPro
true,
FileSystemStatusCode.InProgress);
- // TODO: Get total size
-
fsProgress.Report();
bool deleteFromRecycleBin = RecycleBinHelpers.IsPathUnderRecycleBin(source.Path);
@@ -572,8 +566,6 @@ public async Task RenameAsync(
{
StatusCenterItemProgressModel fsProgress = new(progress, true, FileSystemStatusCode.InProgress);
- // TODO: Get total size
-
fsProgress.Report();
if (Path.GetFileName(source.Path) == newName && collision == NameCollisionOption.FailIfExists)
From 9e65a238f8f8eaf0bd003e6d875cb1593b6ef1a6 Mon Sep 17 00:00:00 2001
From: Marco Gavelli
Date: Sun, 17 Sep 2023 03:36:44 +0200
Subject: [PATCH 13/97] Get progress percentage as double
---
.../Utils/Shell/ShellFileOperations2.cs | 1075 +++++++++++++++++
.../StatusCenterItemProgressModel.cs | 15 +-
.../Storage/Helpers/FileOperationsHelpers.cs | 26 +-
3 files changed, 1096 insertions(+), 20 deletions(-)
create mode 100644 src/Files.App/Utils/Shell/ShellFileOperations2.cs
diff --git a/src/Files.App/Utils/Shell/ShellFileOperations2.cs b/src/Files.App/Utils/Shell/ShellFileOperations2.cs
new file mode 100644
index 000000000000..058bf936931d
--- /dev/null
+++ b/src/Files.App/Utils/Shell/ShellFileOperations2.cs
@@ -0,0 +1,1075 @@
+using System.Runtime.InteropServices;
+using Vanara.PInvoke;
+using static Vanara.PInvoke.Shell32;
+using static Vanara.Windows.Shell.ShellFileOperations;
+
+namespace Vanara.Windows.Shell;
+
+/// Queued and static file operations using the Shell.
+///
+/// https://github.com/dahall/Vanara/blob/master/Windows.Shell.Common/ShellFileOperations/ShellFileOperations.cs
+public class ShellFileOperations2 : IDisposable
+{
+ private const OperationFlags defaultOptions = OperationFlags.AllowUndo | OperationFlags.NoConfirmMkDir;
+ private ShellFileOperationDialog customProgressDialog;
+ private bool disposedValue = false;
+ private IFileOperation op;
+ private OperationFlags opFlags = defaultOptions;
+ private HWND owner;
+ private readonly IFileOperationProgressSink sink;
+ private readonly uint sinkCookie;
+
+ /// Initializes a new instance of the class.
+ /// The window that owns the modal dialog. This value can be .
+ public ShellFileOperations2(HWND owner = default)
+ {
+ op = new IFileOperation();
+ if (owner != default)
+ {
+ op.SetOwnerWindow(owner);
+ }
+
+ sink = new OpSink(this);
+ sinkCookie = op.Advise(sink);
+ }
+
+ /// Initializes a new instance of the class.
+ /// An existing instance.
+ public ShellFileOperations2(IFileOperation operation)
+ {
+ op = operation;
+ sink = new OpSink(this);
+ sinkCookie = op.Advise(sink);
+ }
+
+ /// Finalizes an instance of the class.
+ ~ShellFileOperations2()
+ {
+ Dispose(false);
+ }
+
+ /// Performs caller-implemented actions after the last operation performed by the call to IFileOperation is complete.
+ public event EventHandler FinishOperations;
+
+ /// Performs caller-implemented actions after the copy process for each item is complete.
+ public event EventHandler PostCopyItem;
+
+ /// Performs caller-implemented actions after the delete process for each item is complete.
+ public event EventHandler PostDeleteItem;
+
+ /// Performs caller-implemented actions after the move process for each item is complete.
+ public event EventHandler PostMoveItem;
+
+ /// Performs caller-implemented actions after the new item is created.
+ public event EventHandler PostNewItem;
+
+ /// Performs caller-implemented actions after the rename process for each item is complete.
+ public event EventHandler PostRenameItem;
+
+ /// Performs caller-implemented actions before the copy process for each item begins.
+ public event EventHandler PreCopyItem;
+
+ /// Performs caller-implemented actions before the delete process for each item begins.
+ public event EventHandler PreDeleteItem;
+
+ /// Performs caller-implemented actions before the move process for each item begins.
+ public event EventHandler PreMoveItem;
+
+ /// Performs caller-implemented actions before the process to create a new item begins.
+ public event EventHandler PreNewItem;
+
+ /// Performs caller-implemented actions before the rename process for each item begins.
+ public event EventHandler PreRenameItem;
+
+ /// Performs caller-implemented actions before any specific file operations are performed.
+ public event EventHandler StartOperations;
+
+ /// Occurs when a progress update is received.
+ public event ProgressChangedEventHandler UpdateProgress;
+
+ ///
+ /// Gets a value that states whether any file operations initiated by a call to were stopped before they
+ /// were complete. The operations could be stopped either by user action or silently by the system.
+ ///
+ /// if any file operations were aborted before they were complete; otherwise, .
+ public bool AnyOperationsAborted => op.GetAnyOperationsAborted();
+
+ /// Specifies a dialog box used to display the progress of the operation.
+ /// A ShellFileOperationDialog object that represents the dialog box.
+ public ShellFileOperationDialog CustomProgressDialog
+ {
+ get => customProgressDialog;
+ set => op.SetProgressDialog((customProgressDialog = value)?.iProgressDialog);
+ }
+
+ /// Gets or sets options that control file operations.
+ public OperationFlags Options
+ {
+ get => opFlags;
+ set { if (value == opFlags) { return; } op.SetOperationFlags((FILEOP_FLAGS)(opFlags = value)); }
+ }
+
+ /// Gets or sets the parent or owner window for progress and dialog windows.
+ /// The owner window of the operation. This window will receive error messages.
+ public HWND OwnerWindow
+ {
+ get => owner;
+ set => op.SetOwnerWindow(owner = value);
+ }
+
+ /// Gets the number of queued operations.
+ public int QueuedOperations { get; protected set; }
+
+ /// Copies a single item to a specified destination using the Shell to provide progress and error dialogs.
+ /// A string that specifies the source item's full file path.
+ /// A string that specifies the full path of the destination folder to contain the copy of the item.
+ ///
+ /// An optional new name for the item after it has been copied. This can be . If , the name
+ /// of the destination item is the same as the source.
+ ///
+ /// Options that control file operations.
+ public static void Copy(string source, string dest, string newName = null, OperationFlags options = defaultOptions)
+ {
+ using ShellItem shfile = new(source);
+ using ShellFolder shfld = new(dest);
+ Copy(shfile, shfld, newName, options);
+ }
+
+ /// Copies a single item to a specified destination using the Shell to provide progress and error dialogs.
+ /// A that specifies the source item.
+ /// A that specifies the destination folder to contain the copy of the item.
+ ///
+ /// An optional new name for the item after it has been copied. This can be . If , the name
+ /// of the destination item is the same as the source.
+ ///
+ /// Options that control file operations.
+ public static void Copy(ShellItem source, ShellFolder dest, string newName = null, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostCopyItem += OnPost;
+ try
+ {
+ sop.QueueCopyOperation(source, dest, newName);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostCopyItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Copies a set of items to a specified destination using the Shell to provide progress and error dialogs.
+ ///
+ /// An of instances that represent the group of items to be copied.
+ ///
+ /// A that specifies the destination folder to contain the copy of the items.
+ /// Options that control file operations.
+ public static void Copy(IEnumerable sourceItems, ShellFolder dest, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostCopyItem += OnPost;
+ try
+ {
+ sop.QueueCopyOperation(sourceItems, dest);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostCopyItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Deletes a single item using the Shell to provide progress and error dialogs.
+ /// A string that specifies the full path of the item to be deleted.
+ /// Options that control file operations.
+ public static void Delete(string source, OperationFlags options = defaultOptions)
+ {
+ using ShellItem shfile = new(source);
+ Delete(shfile, options);
+ }
+
+ /// Deletes a single item using the Shell to provide progress and error dialogs.
+ /// A that specifies the item to be deleted.
+ /// Options that control file operations.
+ public static void Delete(ShellItem source, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostDeleteItem += OnPost;
+ try
+ {
+ sop.QueueDeleteOperation(source);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostDeleteItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Deletes a set of items using the Shell to provide progress and error dialogs.
+ ///
+ /// An of instances which represents the group of items to be deleted.
+ ///
+ /// Options that control file operations.
+ public static void Delete(IEnumerable sourceItems, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostDeleteItem += OnPost;
+ try
+ {
+ sop.QueueDeleteOperation(sourceItems);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostDeleteItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Moves a single item to a specified destination using the Shell to provide progress and error dialogs.
+ /// A string that specifies the source item's full file path.
+ /// A string that specifies the full path of the destination folder to contain the copy of the item.
+ ///
+ /// An optional new name for the item in its new location. This can be . If , the name of the
+ /// destination item is the same as the source.
+ ///
+ /// Options that control file operations.
+ public static void Move(string source, string dest, string newName = null, OperationFlags options = defaultOptions)
+ {
+ using ShellItem shfile = new(source);
+ using ShellFolder shfld = new(dest);
+ Move(shfile, shfld, newName, options);
+ }
+
+ /// Moves a single item to a specified destination using the Shell to provide progress and error dialogs.
+ /// A that specifies the source item.
+ /// A that specifies the destination folder to contain the moved item.
+ ///
+ /// An optional new name for the item in its new location. This can be . If , the name of the
+ /// destination item is the same as the source.
+ ///
+ /// Options that control file operations.
+ public static void Move(ShellItem source, ShellFolder dest, string newName = null, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new() { Options = options };
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostMoveItem += OnPost;
+ try
+ {
+ sop.QueueMoveOperation(source, dest, newName);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostMoveItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Moves a set of items to a specified destination using the Shell to provide progress and error dialogs.
+ ///
+ /// An of instances which represents the group of items to be moved.
+ ///
+ /// A that specifies the destination folder to contain the moved items.
+ /// Options that control file operations.
+ public static void Move(IEnumerable sourceItems, ShellFolder dest, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostMoveItem += OnPost;
+ try
+ {
+ sop.QueueMoveOperation(sourceItems, dest);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostMoveItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Creates a new item in a specified location using the Shell to provide progress and error dialogs.
+ /// A that specifies the destination folder that will contain the new item.
+ /// The file name of the new item, for instance Newfile.txt.
+ /// A value that specifies the file system attributes for the file or folder.
+ ///
+ /// The name of the template file (for example Excel9.xls) that the new item is based on, stored in one of the following locations:
+ ///
+ /// -
+ /// CSIDL_COMMON_TEMPLATES. The default path for this folder is %ALLUSERSPROFILE%\Templates.
+ ///
+ /// -
+ /// CSIDL_TEMPLATES. The default path for this folder is %USERPROFILE%\Templates.
+ ///
+ /// -
+ /// %SystemRoot%\shellnew
+ ///
+ ///
+ ///
+ /// This is a string used to specify an existing file of the same type as the new file, containing the minimal content that an
+ /// application wants to include in any new file.
+ ///
+ /// This parameter is normally to specify a new, blank file.
+ ///
+ /// Options that control file operations.
+ public static void NewItem(ShellFolder dest, string name, System.IO.FileAttributes attr = System.IO.FileAttributes.Normal, string template = null, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostNewItem += OnPost;
+ try
+ {
+ sop.QueueNewItemOperation(dest, name, attr, template);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostRenameItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Renames a single item to a new display name using the Shell to provide progress and error dialogs.
+ /// A that specifies the source item.
+ /// The new display name of the item.
+ /// Options that control file operations.
+ public static void Rename(ShellItem source, string newName = null, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostRenameItem += OnPost;
+ try
+ {
+ sop.QueueRenameOperation(source, newName);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostRenameItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ ///
+ /// Renames a set of items that are to be given a new display name using the Shell to provide progress and error dialogs. All items are
+ /// given the same name.
+ ///
+ ///
+ /// An of instances which represents the group of items to be renamed.
+ ///
+ /// The new display name of the items.
+ /// Options that control file operations.
+ public static void Rename(IEnumerable sourceItems, string newName, OperationFlags options = defaultOptions)
+ {
+ using ShellFileOperations2 sop = new();
+ sop.Options = options;
+ HRESULT hr = HRESULT.S_OK;
+ sop.PostRenameItem += OnPost;
+ try
+ {
+ sop.QueueRenameOperation(sourceItems, newName);
+ sop.PerformOperations();
+ hr.ThrowIfFailed();
+ }
+ finally
+ {
+ sop.PostRenameItem -= OnPost;
+ }
+
+ void OnPost(object sender, ShellFileOpEventArgs e) => hr = e.Result;
+ }
+
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// Executes all selected operations.
+ ///
+ /// This method is called last to execute those actions that have been specified earlier by calling their individual methods. For
+ /// instance, does not rename the item, it simply sets the parameters. The actual
+ /// renaming is done when you call PerformOperations.
+ ///
+ public void PerformOperations()
+ {
+ op.PerformOperations();
+ QueuedOperations = 0;
+ }
+
+ /// Declares a set of properties and values to be set on an item.
+ /// The item to receive the new property values.
+ ///
+ /// An , which contains a dictionary of objects that specify the properties to be set and their new values.
+ ///
+ public void QueueApplyPropertiesOperation(ShellItem item, ShellItemPropertyUpdates props)
+ {
+ op.SetProperties(props.IPropertyChangeArray);
+ op.ApplyPropertiesToItem(item.IShellItem);
+ QueuedOperations++;
+ }
+
+ /// Declares a set of properties and values to be set on a set of items.
+ ///
+ /// An of instances that represent the group of items to which to apply the properties.
+ ///
+ ///
+ /// An , which contains a dictionary of objects that specify the properties to be set and their new values.
+ ///
+ public void QueueApplyPropertiesOperation(IEnumerable items, ShellItemPropertyUpdates props)
+ {
+ op.SetProperties(props.IPropertyChangeArray);
+ op.ApplyPropertiesToItems(GetSHArray(items).IShellItemArray);
+ QueuedOperations++;
+ }
+
+ /// Declares a single item that is to be copied to a specified destination.
+ /// A that specifies the source item.
+ /// A that specifies the destination folder to contain the copy of the item.
+ ///
+ /// An optional new name for the item after it has been copied. This can be . If , the name
+ /// of the destination item is the same as the source.
+ ///
+ public void QueueCopyOperation(ShellItem source, ShellFolder dest, string newName = null)
+ {
+ op.CopyItem(source.IShellItem, dest.IShellItem, newName, null);
+ QueuedOperations++;
+ }
+
+ /// Declares a set of items that are to be copied to a specified destination.
+ ///
+ /// An of instances that represent the group of items to be copied.
+ ///
+ /// A that specifies the destination folder to contain the copy of the items.
+ public void QueueCopyOperation(IEnumerable sourceItems, ShellFolder dest)
+ {
+ op.CopyItems(GetSHArray(sourceItems).IShellItemArray, dest.IShellItem);
+ QueuedOperations++;
+ }
+
+ /// Declares a single item that is to be deleted.
+ /// >A that specifies the item to be deleted.
+ public void QueueDeleteOperation(ShellItem item)
+ {
+ op.DeleteItem(item.IShellItem, null);
+ QueuedOperations++;
+ }
+
+ /// Declares a set of items that are to be deleted.
+ ///
+ /// An of instances which represents the group of items to be deleted.
+ ///
+ public void QueueDeleteOperation(IEnumerable items)
+ {
+ op.DeleteItems(GetSHArray(items).IShellItemArray);
+ QueuedOperations++;
+ }
+
+ /// Declares a single item that is to be moved to a specified destination.
+ /// A that specifies the source item.
+ /// A that specifies the destination folder to contain the moved item.
+ ///
+ /// An optional new name for the item in its new location. This can be . If , the name of the
+ /// destination item is the same as the source.
+ ///
+ public void QueueMoveOperation(ShellItem source, ShellFolder dest, string newName = null)
+ {
+ op.MoveItem(source.IShellItem, dest.IShellItem, newName, null);
+ QueuedOperations++;
+ }
+
+ /// Declares a set of items that are to be moved to a specified destination.
+ ///
+ /// An of instances which represents the group of items to be moved.
+ ///
+ /// A that specifies the destination folder to contain the moved items.
+ public void QueueMoveOperation(IEnumerable sourceItems, ShellFolder dest)
+ {
+ op.MoveItems(GetSHArray(sourceItems).IShellItemArray, dest.IShellItem);
+ QueuedOperations++;
+ }
+
+ /// Declares a new item that is to be created in a specified location.
+ /// A that specifies the destination folder that will contain the new item.
+ /// The file name of the new item, for instance Newfile.txt.
+ /// A value that specifies the file system attributes for the file or folder.
+ ///
+ /// The name of the template file (for example Excel9.xls) that the new item is based on, stored in one of the following locations:
+ ///
+ /// -
+ /// CSIDL_COMMON_TEMPLATES. The default path for this folder is %ALLUSERSPROFILE%\Templates.
+ ///
+ /// -
+ /// CSIDL_TEMPLATES. The default path for this folder is %USERPROFILE%\Templates.
+ ///
+ /// -
+ /// %SystemRoot%\shellnew
+ ///
+ ///
+ ///
+ /// This is a string used to specify an existing file of the same type as the new file, containing the minimal content that an
+ /// application wants to include in any new file.
+ ///
+ /// This parameter is normally to specify a new, blank file.
+ ///
+ public void QueueNewItemOperation(ShellFolder dest, string name, System.IO.FileAttributes attr = System.IO.FileAttributes.Normal, string template = null)
+ {
+ op.NewItem(dest.IShellItem, attr, name, template, null);
+ QueuedOperations++;
+ }
+
+ /// Declares a single item that is to be given a new display name.
+ /// A that specifies the source item.
+ /// The new display name of the item.
+ public void QueueRenameOperation(ShellItem source, string newName)
+ {
+ op.RenameItem(source.IShellItem, newName, null);
+ QueuedOperations++;
+ }
+
+ /// Declares a set of items that are to be given a new display name. All items are given the same name.
+ ///
+ /// An of instances which represents the group of items to be renamed.
+ ///
+ /// The new display name of the items.
+ public void QueueRenameOperation(IEnumerable sourceItems, string newName)
+ {
+ op.RenameItems(GetSHArray(sourceItems).IShellItemArray, newName);
+ QueuedOperations++;
+ }
+
+ /// Releases unmanaged and - optionally - managed resources.
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // Dispose managed state (managed objects).
+ }
+
+ if (sink != null)
+ {
+ op.Unadvise(sinkCookie);
+ }
+
+ op = null;
+ disposedValue = true;
+ }
+ }
+
+ private ShellItemArray GetSHArray(IEnumerable items) => items is ShellItemArray a ? a : new ShellItemArray(items);
+
+ private class OpSink : IFileOperationProgressSink
+ {
+ private readonly ShellFileOperations2 parent;
+
+ public OpSink(ShellFileOperations2 ops) => parent = ops;
+
+ public HRESULT FinishOperations(HRESULT hrResult) => CallChkErr(() => parent.FinishOperations?.Invoke(parent, new ShellFileOpEventArgs(0, null, null, null, null, hrResult)));
+
+ public HRESULT PauseTimer() => HRESULT.E_NOTIMPL;
+
+ public HRESULT PostCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrCopy, IShellItem psiNewlyCreated) =>
+ CallChkErr(() => parent.PostCopyItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrCopy)));
+
+ public HRESULT PostDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, HRESULT hrDelete, IShellItem psiNewlyCreated) =>
+ CallChkErr(() => parent.PostDeleteItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, null, hrDelete)));
+
+ public HRESULT PostMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrMove, IShellItem psiNewlyCreated) =>
+ CallChkErr(() => parent.PostMoveItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrMove)));
+
+ public HRESULT PostNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, [MarshalAs(UnmanagedType.LPWStr)] string pszTemplateName, uint dwFileAttributes, HRESULT hrNew, IShellItem psiNewItem) =>
+ CallChkErr(() => parent.PostNewItem?.Invoke(parent, new ShellFileNewOpEventArgs(dwFlags, null, psiDestinationFolder, psiNewItem, pszNewName, hrNew, pszTemplateName, dwFileAttributes)));
+
+ public HRESULT PostRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrRename, IShellItem psiNewlyCreated) =>
+ CallChkErr(() => parent.PostRenameItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, pszNewName, hrRename)));
+
+ public HRESULT PreCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) =>
+ CallChkErr(() => parent.PreCopyItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName)));
+
+ public HRESULT PreDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem) =>
+ CallChkErr(() => parent.PreDeleteItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem)));
+
+ public HRESULT PreMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) =>
+ CallChkErr(() => parent.PreMoveItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName)));
+
+ public HRESULT PreNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) =>
+ CallChkErr(() => parent.PreNewItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, null, psiDestinationFolder, null, pszNewName)));
+
+ public HRESULT PreRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) => CallChkErr(() => parent.PreRenameItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, null, pszNewName)));
+
+ public HRESULT ResetTimer() => HRESULT.E_NOTIMPL;
+
+ public HRESULT ResumeTimer() => HRESULT.E_NOTIMPL;
+
+ public HRESULT StartOperations() => CallChkErr(() => parent.StartOperations?.Invoke(parent, EventArgs.Empty));
+
+ public HRESULT UpdateProgress(uint iWorkTotal, uint iWorkSoFar) => CallChkErr(() => parent.UpdateProgress?.Invoke(parent, new ProgressChangedEventArgs(iWorkTotal == 0 ? 0 : iWorkSoFar * 100.0 / iWorkTotal, null)));
+
+ private HRESULT CallChkErr(Action action)
+ {
+ try { action(); }
+ catch (COMException comex) { return comex.ErrorCode; }
+ catch (Win32Exception w32ex) { return new Win32Error(unchecked((uint)w32ex.NativeErrorCode)).ToHRESULT(); }
+ catch (Exception e)
+ {
+ return e.HResult;
+ }
+ return HRESULT.S_OK;
+ }
+ }
+
+ /// Arguments supplied to the event.
+ ///
+ public class ShellFileNewOpEventArgs : ShellFileOpEventArgs
+ {
+ internal ShellFileNewOpEventArgs(TRANSFER_SOURCE_FLAGS flags, IShellItem source, IShellItem folder, IShellItem dest, string name, HRESULT hr, string templ, uint attr) :
+ base(flags, source, folder, dest, name, hr)
+ {
+ TemplateName = templ;
+ FileAttributes = (System.IO.FileAttributes)attr;
+ }
+
+ /// Gets the name of the template.
+ /// The name of the template.
+ public string TemplateName { get; protected set; }
+
+ /// Gets the file attributes.
+ /// The file attributes.
+ public System.IO.FileAttributes FileAttributes { get; protected set; }
+ }
+
+ ///
+ /// Arguments supplied to events from . Depending on the event, some properties may not be set.
+ ///
+ ///
+ public class ShellFileOpEventArgs : EventArgs
+ {
+ internal ShellFileOpEventArgs(TRANSFER_SOURCE_FLAGS flags, IShellItem source, IShellItem folder = null, IShellItem dest = null, string name = null, HRESULT hr = default)
+ {
+ Flags = (TransferFlags)flags;
+ if (source != null) try { SourceItem = ShellItem.Open(source); } catch { }
+ if (folder != null) try { DestFolder = ShellItem.Open(folder); } catch { }
+ if (dest != null) try { DestItem = ShellItem.Open(dest); } catch { }
+ Name = name;
+ Result = hr;
+ }
+
+ /// Gets the destination folder.
+ /// The destination folder.
+ public ShellItem DestFolder { get; protected set; }
+
+ /// Gets the destination item.
+ /// The destination item.
+ public ShellItem DestItem { get; protected set; }
+
+ /// Gets the tranfer flag values.
+ /// The flags.
+ public TransferFlags Flags { get; protected set; }
+
+ /// Gets the name of the item.
+ /// The item name.
+ public string Name { get; protected set; }
+
+ /// Gets the result of the operation.
+ /// The result.
+ public HRESULT Result { get; protected set; }
+
+ /// Gets the source item.
+ /// The source item.
+ public ShellItem SourceItem { get; protected set; }
+
+ /// Returns a that represents this instance.
+ /// A that represents this instance.
+ public override string ToString() => $"HR:{Result};Src:{SourceItem};DFld:{DestFolder};Dst:{DestItem};Name:{Name}";
+ }
+
+ /// The Shell's progress dialog.
+ ///
+ public class ShellFileOperationDialog : Component
+ {
+ internal IOperationsProgressDialog iProgressDialog;
+
+ private ShellItem currentItem;
+ private long currentItems;
+ private long currentProgress;
+ private long currentSize;
+ private ShellItem destItem;
+ private OperationMode mode;
+ private OperationType operation;
+ private ShellItem sourceItem;
+ private long totalItems = 100;
+ private long totalProgress = 100;
+ private long totalSize = 100;
+
+ /// Initializes a new instance of the class.
+ public ShellFileOperationDialog()
+ {
+ }
+
+ /// Initializes a new instance of the class.
+ /// The container.
+ public ShellFileOperationDialog(IContainer container) : this()
+ {
+ container.Add(this);
+ }
+
+ /// Provides operation status flags for ShellFileOperationDialog.
+ public enum DialogStatus
+ {
+ /// The dialog has not been started.
+ NotStarted = 0,
+
+ /// Operation is running, no user intervention.
+ Running = PDOPSTATUS.PDOPS_RUNNING,
+
+ /// Operation has been paused by the user.
+ Paused = PDOPSTATUS.PDOPS_PAUSED,
+
+ /// Operation has been canceled by the user - now go undo.
+ Cancelled = PDOPSTATUS.PDOPS_CANCELLED,
+
+ /// Operation has been stopped by the user - terminate completely.
+ Stopped = PDOPSTATUS.PDOPS_STOPPED,
+
+ /// Operation has gone as far as it can go without throwing error dialogs.
+ Errors = PDOPSTATUS.PDOPS_ERRORS,
+ }
+
+ /// Flags used in Mode
+ [Flags]
+ public enum OperationMode
+ {
+ /// Use the default progress dialog operations mode.
+ Default = PDMODE.PDM_DEFAULT,
+
+ /// The operation is running.
+ Running = PDMODE.PDM_RUN,
+
+ /// The operation is gathering data before it begins, such as calculating the predicted operation time.
+ Starting = PDMODE.PDM_PREFLIGHT,
+
+ /// The operation is rolling back due to an Undo command from the user.
+ Undoing = PDMODE.PDM_UNDOING,
+
+ /// Error dialogs are blocking progress from continuing.
+ BlockedByErrors = PDMODE.PDM_ERRORSBLOCKING,
+
+ /// The length of the operation is indeterminate. Do not show a timer and display the progress bar in marquee mode.
+ Indeterminate = PDMODE.PDM_INDETERMINATE,
+ }
+
+ /// Describes an action being performed that requires progress to be shown to the user using progress dialog.
+ public enum OperationType
+ {
+ /// No action is being performed.
+ None = SPACTION.SPACTION_NONE,
+
+ /// Files are being moved.
+ Moving = SPACTION.SPACTION_MOVING,
+
+ /// Files are being copied.
+ Copying = SPACTION.SPACTION_COPYING,
+
+ /// Files are being deleted.
+ Recycling = SPACTION.SPACTION_RECYCLING,
+
+ /// A set of attributes are being applied to files.
+ ApplyingAttributes = SPACTION.SPACTION_APPLYINGATTRIBS,
+
+ /// A file is being downloaded from a remote source.
+ Downloading = SPACTION.SPACTION_DOWNLOADING,
+
+ /// An Internet search is being performed.
+ SearchingInternet = SPACTION.SPACTION_SEARCHING_INTERNET,
+
+ /// A calculation is being performed.
+ Calculating = SPACTION.SPACTION_CALCULATING,
+
+ /// A file is being uploaded to a remote source.
+ Uploading = SPACTION.SPACTION_UPLOADING,
+
+ /// A local search is being performed.
+ SearchingFiles = SPACTION.SPACTION_SEARCHING_FILES,
+
+ /// Windows Vista and later. A deletion is being performed.
+ Deleting = SPACTION.SPACTION_DELETING,
+
+ /// Windows Vista and later. A renaming action is being performed.
+ Renaming = SPACTION.SPACTION_RENAMING,
+
+ /// Windows Vista and later. A formatting action is being performed.
+ Formatting = SPACTION.SPACTION_FORMATTING,
+
+ /// Windows 7 and later. A copy or move action is being performed.
+ CopyMoving = SPACTION.SPACTION_COPY_MOVING,
+ }
+
+ /// The operation can be undone in the dialog. (The Stop button becomes Undo)
+ [DefaultValue(false)]
+ public bool AllowUndo { get; set; }
+
+ ///
+ /// A ShellItem that represents the item currently being operated on by the operation engine. This property is only used in Windows
+ /// 7 and later. In earlier versions, this property should be
+ ///
+ public ShellItem CurrentItem { get => currentItem; set { currentItem = value; UpdateLocations(); } }
+
+ /// A ShellItem that represents the target Shell item.
+ public ShellItem Destination { get => destItem; set { destItem = value ?? throw new ArgumentNullException(nameof(Source)); UpdateLocations(); } }
+
+ /// Gets the elapsed time.
+ /// The elapsed time, accurate to milliseconds.
+ public TimeSpan ElapsedTime
+ {
+ get
+ {
+ ulong t = 0;
+ if (CanProcess)
+ try { iProgressDialog.GetMilliseconds(out t, out _); } catch { }
+ return TimeSpan.FromMilliseconds(t);
+ }
+ }
+
+ /// Don't display the path of destination file in progress dialog
+ [DefaultValue(false)]
+ public bool HideDestinationPath { get; set; }
+
+ /// Don't display the location line in the progress dialog
+ [DefaultValue(false)]
+ public bool HideLocations { get; set; }
+
+ /// Don't display the path of source file in progress dialog
+ [DefaultValue(false)]
+ public bool HideSourcePath { get; set; }
+
+ /// Gets or sets progress dialog operations mode.
+ /// The mode.
+ public OperationMode Mode
+ {
+ get => mode;
+ set
+ {
+ if (mode == value) return;
+ mode = value;
+ if (CanProcess)
+ iProgressDialog.SetMode((PDMODE)mode);
+ }
+ }
+
+ /// Sets which progress dialog operation is occurring, and whether we are in pre-flight or undo mode.
+ /// Specifies operation. See .
+ public OperationType Operation
+ {
+ get => operation;
+ set
+ {
+ if (operation == value) return;
+ operation = value;
+ if (CanProcess)
+ iProgressDialog.SetOperation((SPACTION)operation);
+ }
+ }
+
+ /// Total points, used for showing progress in points.
+ [DefaultValue(100)]
+ public long ProgressBarMaxValue
+ {
+ get => totalProgress;
+ set { totalProgress = value; UpdateProgress(); }
+ }
+
+ /// Current points, used for showing progress in points.
+ [DefaultValue(0)]
+ public long ProgressBarValue
+ {
+ get => currentProgress;
+ set { currentProgress = value; UpdateProgress(); }
+ }
+
+ /// Specifies total items, used for showing progress in items.
+ [DefaultValue(100)]
+ public long ProgressDialogItemsMaxValue
+ {
+ get => totalItems;
+ set { totalItems = value; UpdateProgress(); }
+ }
+
+ /// Current items, used for showing progress in items.
+ [DefaultValue(0)]
+ public long ProgressDialogItemsValue
+ {
+ get => currentItems;
+ set { currentItems = value; UpdateProgress(); }
+ }
+
+ /// Total size in bytes, used for showing progress in bytes.
+ [DefaultValue(100)]
+ public long ProgressDialogSizeMaxValue
+ {
+ get => totalSize;
+ set { totalSize = value; UpdateProgress(); }
+ }
+
+ /// Current size in bytes, used for showing progress in bytes.
+ [DefaultValue(0)]
+ public long ProgressDialogSizeValue
+ {
+ get => currentSize;
+ set { currentSize = value; UpdateProgress(); }
+ }
+
+ /// Gets the remaining time.
+ /// The remaining time, accurate to milliseconds.
+ public TimeSpan RemainingTime
+ {
+ get
+ {
+ ulong t = 0;
+ if (CanProcess)
+ try { iProgressDialog.GetMilliseconds(out _, out t); } catch { }
+ return TimeSpan.FromMilliseconds(t);
+ }
+ }
+
+ /// Add a pause button (operation can be paused)
+ [DefaultValue(false)]
+ public bool ShowPauseButton { get; set; }
+
+ /// A ShellItem that represents the source Shell item.
+ public ShellItem Source { get => sourceItem; set { sourceItem = value ?? throw new ArgumentNullException(nameof(Source)); UpdateLocations(); } }
+
+ /// Gets operation status for progress dialog.
+ /// The operation status. See .
+ public DialogStatus Status => (DialogStatus)(CanProcess ? iProgressDialog.GetOperationStatus() : 0);
+
+ private bool CanProcess => iProgressDialog != null;
+
+ private OPPROGDLGF DialogFlags => (ShowPauseButton ? OPPROGDLGF.OPPROGDLG_ENABLEPAUSE : 0) |
+ (AllowUndo ? OPPROGDLGF.OPPROGDLG_ALLOWUNDO : 0) |
+ (HideSourcePath ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYSOURCEPATH : 0) |
+ (HideDestinationPath ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYDESTPATH : 0) |
+ (HideLocations ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYLOCATIONS : 0);
+
+ /// Pauses progress dialog timer.
+ public void PauseTimer() { if (CanProcess) iProgressDialog.PauseTimer(); }
+
+ /// Resets progress dialog timer to 0.
+ public void ResetTimer() { if (CanProcess) iProgressDialog.ResetTimer(); }
+
+ /// Resumes progress dialog timer.
+ public void ResumeTimer() { if (CanProcess) iProgressDialog.ResumeTimer(); }
+
+ /// Starts the specified progress dialog.
+ ///
+ /// A value that represents the window of the owner window for the common dialog box. This value can be .
+ ///
+ public void Start(HWND owner = default)
+ {
+ iProgressDialog = new IOperationsProgressDialog();
+ iProgressDialog.StartProgressDialog(owner, DialogFlags);
+ iProgressDialog.SetOperation((SPACTION)operation);
+ iProgressDialog.SetMode((PDMODE)mode);
+ UpdateLocations();
+ UpdateProgress();
+ }
+
+ /// Stops current progress dialog.
+ public void Stop()
+ {
+ if (!CanProcess)
+ return;
+
+ iProgressDialog.StopProgressDialog();
+ Thread.Sleep(500);
+ iProgressDialog = null;
+ }
+
+ ///
+ /// Releases the unmanaged resources used by the and optionally releases the managed resources.
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ protected override void Dispose(bool disposing)
+ {
+ Stop();
+ base.Dispose(disposing);
+ }
+
+ private void UpdateLocations()
+ {
+ if (CanProcess)
+ iProgressDialog.UpdateLocations(sourceItem.IShellItem, destItem.IShellItem, currentItem?.IShellItem);
+ }
+
+ private void UpdateProgress()
+ {
+ if (CanProcess)
+ iProgressDialog.UpdateProgress((ulong)currentProgress, (ulong)totalProgress, (ulong)currentSize, (ulong)totalSize, (ulong)currentItems, (ulong)totalItems);
+ }
+ }
+
+ public delegate void ProgressChangedEventHandler(object? sender, ProgressChangedEventArgs e);
+
+ public class ProgressChangedEventArgs : EventArgs
+ {
+ private readonly double _progressPercentage;
+ private readonly object? _userState;
+
+ public ProgressChangedEventArgs(double progressPercentage, object? userState)
+ {
+ _progressPercentage = progressPercentage;
+ _userState = userState;
+ }
+
+ public double ProgressPercentage
+ {
+ get
+ {
+ return _progressPercentage;
+ }
+ }
+
+ public object? UserState
+ {
+ get
+ {
+ return _userState;
+ }
+ }
+ }
+}
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index 15e031d83dbf..74e2678a72a7 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -173,17 +173,18 @@ TotalSize is not 0 ||
// NOTE: This won't work yet
ProcessingItemsCountSpeed = (ProcessedItemsCount - _previousProcessedItemsCount) / (DateTimeOffset.Now - _previousReportTime).TotalSeconds;
- }
- PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
- PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
+ PropertyChanged?.Invoke(this, new(nameof(ProcessingSizeSpeed)));
+ PropertyChanged?.Invoke(this, new(nameof(ProcessingItemsCountSpeed)));
+
+ Percentage = percentage;
- Percentage = percentage;
+ _previousReportTime = DateTimeOffset.Now;
+ _previousProcessedSize = ProcessedSize;
+ _previousProcessedItemsCount = ProcessedItemsCount;
+ }
_progress?.Report(this);
- _previousReportTime = DateTimeOffset.Now;
- _previousProcessedSize = ProcessedSize;
- _previousProcessedItemsCount = ProcessedItemsCount;
}
}
diff --git a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
index c2c74ad0e26f..69f2f2fb87ec 100644
--- a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
+++ b/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
@@ -42,7 +42,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
op.Options = ShellFileOperations.OperationFlags.Silent
| ShellFileOperations.OperationFlags.NoConfirmMkDir
@@ -111,7 +111,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
op.Options = ShellFileOperations.OperationFlags.Silent
| ShellFileOperations.OperationFlags.NoConfirmation
@@ -200,7 +200,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
long totalSize = 0;
- foreach (var item in fileToCopyPath)
+ foreach (var item in fileToDeletePath)
{
totalSize += GetFileSize(item);
}
@@ -209,7 +209,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progress,
true,
FileSystemStatusCode.InProgress,
- fileToCopyPath.Count(),
+ fileToDeletePath.Count(),
totalSize);
fsProgress.Report();
@@ -217,7 +217,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
op.Options = ShellFileOperations.OperationFlags.Silent
| ShellFileOperations.OperationFlags.NoConfirmation
| ShellFileOperations.OperationFlags.NoErrorUI;
@@ -308,7 +308,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
var shellOperationResult = new ShellOperationResult();
op.Options = ShellFileOperations.OperationFlags.Silent
@@ -372,7 +372,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
long totalSize = 0;
- foreach (var item in fileToCopyPath)
+ foreach (var item in fileToMovePath)
{
totalSize += GetFileSize(item);
}
@@ -381,7 +381,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progress,
true,
FileSystemStatusCode.InProgress,
- fileToCopyPath.Count(),
+ fileToMovePath.Count(),
totalSize);
fsProgress.Report();
@@ -389,7 +389,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
var shellOperationResult = new ShellOperationResult();
op.Options = ShellFileOperations.OperationFlags.NoConfirmMkDir
@@ -486,7 +486,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
return Win32API.StartSTATask(async () =>
{
- using var op = new ShellFileOperations();
+ using var op = new ShellFileOperations2();
var shellOperationResult = new ShellOperationResult();
@@ -773,7 +773,7 @@ public static bool SetCompatOptions(string filePath, string options)
return null;
}
- private static void UpdateFileTagsDb(ShellFileOperations.ShellFileOpEventArgs e, string operationType)
+ private static void UpdateFileTagsDb(ShellFileOperations2.ShellFileOpEventArgs e, string operationType)
{
var dbInstance = FileTagsHelper.GetDbInstance();
if (e.Result.Succeeded)
@@ -875,7 +875,7 @@ private class ProgressHandler : Disposable
private class OperationWithProgress
{
- public int Progress { get; set; }
+ public double Progress { get; set; }
public bool Canceled { get; set; }
}
@@ -917,7 +917,7 @@ public void RemoveOperation(string uid)
}
}
- public void UpdateOperation(string uid, int progress)
+ public void UpdateOperation(string uid, double progress)
{
if (operations.TryGetValue(uid, out var op))
{
From 5a3f7a40d96eb6587fdfe1d6fd28fca0e7e18596 Mon Sep 17 00:00:00 2001
From: Marco Gavelli
Date: Sun, 17 Sep 2023 04:02:27 +0200
Subject: [PATCH 14/97] Remove extra class
---
.../Utils/Shell/ShellFileOperations2.cs | 333 ------------------
1 file changed, 333 deletions(-)
diff --git a/src/Files.App/Utils/Shell/ShellFileOperations2.cs b/src/Files.App/Utils/Shell/ShellFileOperations2.cs
index 058bf936931d..ef36ddafe494 100644
--- a/src/Files.App/Utils/Shell/ShellFileOperations2.cs
+++ b/src/Files.App/Utils/Shell/ShellFileOperations2.cs
@@ -11,7 +11,6 @@ namespace Vanara.Windows.Shell;
public class ShellFileOperations2 : IDisposable
{
private const OperationFlags defaultOptions = OperationFlags.AllowUndo | OperationFlags.NoConfirmMkDir;
- private ShellFileOperationDialog customProgressDialog;
private bool disposedValue = false;
private IFileOperation op;
private OperationFlags opFlags = defaultOptions;
@@ -94,14 +93,6 @@ public ShellFileOperations2(IFileOperation operation)
/// if any file operations were aborted before they were complete; otherwise, .
public bool AnyOperationsAborted => op.GetAnyOperationsAborted();
- /// Specifies a dialog box used to display the progress of the operation.
- /// A ShellFileOperationDialog object that represents the dialog box.
- public ShellFileOperationDialog CustomProgressDialog
- {
- get => customProgressDialog;
- set => op.SetProgressDialog((customProgressDialog = value)?.iProgressDialog);
- }
-
/// Gets or sets options that control file operations.
public OperationFlags Options
{
@@ -719,330 +710,6 @@ internal ShellFileOpEventArgs(TRANSFER_SOURCE_FLAGS flags, IShellItem source, IS
public override string ToString() => $"HR:{Result};Src:{SourceItem};DFld:{DestFolder};Dst:{DestItem};Name:{Name}";
}
- /// The Shell's progress dialog.
- ///
- public class ShellFileOperationDialog : Component
- {
- internal IOperationsProgressDialog iProgressDialog;
-
- private ShellItem currentItem;
- private long currentItems;
- private long currentProgress;
- private long currentSize;
- private ShellItem destItem;
- private OperationMode mode;
- private OperationType operation;
- private ShellItem sourceItem;
- private long totalItems = 100;
- private long totalProgress = 100;
- private long totalSize = 100;
-
- /// Initializes a new instance of the class.
- public ShellFileOperationDialog()
- {
- }
-
- /// Initializes a new instance of the class.
- /// The container.
- public ShellFileOperationDialog(IContainer container) : this()
- {
- container.Add(this);
- }
-
- /// Provides operation status flags for ShellFileOperationDialog.
- public enum DialogStatus
- {
- /// The dialog has not been started.
- NotStarted = 0,
-
- /// Operation is running, no user intervention.
- Running = PDOPSTATUS.PDOPS_RUNNING,
-
- /// Operation has been paused by the user.
- Paused = PDOPSTATUS.PDOPS_PAUSED,
-
- /// Operation has been canceled by the user - now go undo.
- Cancelled = PDOPSTATUS.PDOPS_CANCELLED,
-
- /// Operation has been stopped by the user - terminate completely.
- Stopped = PDOPSTATUS.PDOPS_STOPPED,
-
- /// Operation has gone as far as it can go without throwing error dialogs.
- Errors = PDOPSTATUS.PDOPS_ERRORS,
- }
-
- /// Flags used in Mode
- [Flags]
- public enum OperationMode
- {
- /// Use the default progress dialog operations mode.
- Default = PDMODE.PDM_DEFAULT,
-
- /// The operation is running.
- Running = PDMODE.PDM_RUN,
-
- /// The operation is gathering data before it begins, such as calculating the predicted operation time.
- Starting = PDMODE.PDM_PREFLIGHT,
-
- /// The operation is rolling back due to an Undo command from the user.
- Undoing = PDMODE.PDM_UNDOING,
-
- /// Error dialogs are blocking progress from continuing.
- BlockedByErrors = PDMODE.PDM_ERRORSBLOCKING,
-
- /// The length of the operation is indeterminate. Do not show a timer and display the progress bar in marquee mode.
- Indeterminate = PDMODE.PDM_INDETERMINATE,
- }
-
- /// Describes an action being performed that requires progress to be shown to the user using progress dialog.
- public enum OperationType
- {
- /// No action is being performed.
- None = SPACTION.SPACTION_NONE,
-
- /// Files are being moved.
- Moving = SPACTION.SPACTION_MOVING,
-
- /// Files are being copied.
- Copying = SPACTION.SPACTION_COPYING,
-
- /// Files are being deleted.
- Recycling = SPACTION.SPACTION_RECYCLING,
-
- /// A set of attributes are being applied to files.
- ApplyingAttributes = SPACTION.SPACTION_APPLYINGATTRIBS,
-
- /// A file is being downloaded from a remote source.
- Downloading = SPACTION.SPACTION_DOWNLOADING,
-
- /// An Internet search is being performed.
- SearchingInternet = SPACTION.SPACTION_SEARCHING_INTERNET,
-
- /// A calculation is being performed.
- Calculating = SPACTION.SPACTION_CALCULATING,
-
- /// A file is being uploaded to a remote source.
- Uploading = SPACTION.SPACTION_UPLOADING,
-
- /// A local search is being performed.
- SearchingFiles = SPACTION.SPACTION_SEARCHING_FILES,
-
- /// Windows Vista and later. A deletion is being performed.
- Deleting = SPACTION.SPACTION_DELETING,
-
- /// Windows Vista and later. A renaming action is being performed.
- Renaming = SPACTION.SPACTION_RENAMING,
-
- /// Windows Vista and later. A formatting action is being performed.
- Formatting = SPACTION.SPACTION_FORMATTING,
-
- /// Windows 7 and later. A copy or move action is being performed.
- CopyMoving = SPACTION.SPACTION_COPY_MOVING,
- }
-
- /// The operation can be undone in the dialog. (The Stop button becomes Undo)
- [DefaultValue(false)]
- public bool AllowUndo { get; set; }
-
- ///
- /// A ShellItem that represents the item currently being operated on by the operation engine. This property is only used in Windows
- /// 7 and later. In earlier versions, this property should be
- ///
- public ShellItem CurrentItem { get => currentItem; set { currentItem = value; UpdateLocations(); } }
-
- /// A ShellItem that represents the target Shell item.
- public ShellItem Destination { get => destItem; set { destItem = value ?? throw new ArgumentNullException(nameof(Source)); UpdateLocations(); } }
-
- /// Gets the elapsed time.
- /// The elapsed time, accurate to milliseconds.
- public TimeSpan ElapsedTime
- {
- get
- {
- ulong t = 0;
- if (CanProcess)
- try { iProgressDialog.GetMilliseconds(out t, out _); } catch { }
- return TimeSpan.FromMilliseconds(t);
- }
- }
-
- /// Don't display the path of destination file in progress dialog
- [DefaultValue(false)]
- public bool HideDestinationPath { get; set; }
-
- /// Don't display the location line in the progress dialog
- [DefaultValue(false)]
- public bool HideLocations { get; set; }
-
- /// Don't display the path of source file in progress dialog
- [DefaultValue(false)]
- public bool HideSourcePath { get; set; }
-
- /// Gets or sets progress dialog operations mode.
- /// The mode.
- public OperationMode Mode
- {
- get => mode;
- set
- {
- if (mode == value) return;
- mode = value;
- if (CanProcess)
- iProgressDialog.SetMode((PDMODE)mode);
- }
- }
-
- /// Sets which progress dialog operation is occurring, and whether we are in pre-flight or undo mode.
- /// Specifies operation. See .
- public OperationType Operation
- {
- get => operation;
- set
- {
- if (operation == value) return;
- operation = value;
- if (CanProcess)
- iProgressDialog.SetOperation((SPACTION)operation);
- }
- }
-
- /// Total points, used for showing progress in points.
- [DefaultValue(100)]
- public long ProgressBarMaxValue
- {
- get => totalProgress;
- set { totalProgress = value; UpdateProgress(); }
- }
-
- /// Current points, used for showing progress in points.
- [DefaultValue(0)]
- public long ProgressBarValue
- {
- get => currentProgress;
- set { currentProgress = value; UpdateProgress(); }
- }
-
- /// Specifies total items, used for showing progress in items.
- [DefaultValue(100)]
- public long ProgressDialogItemsMaxValue
- {
- get => totalItems;
- set { totalItems = value; UpdateProgress(); }
- }
-
- /// Current items, used for showing progress in items.
- [DefaultValue(0)]
- public long ProgressDialogItemsValue
- {
- get => currentItems;
- set { currentItems = value; UpdateProgress(); }
- }
-
- /// Total size in bytes, used for showing progress in bytes.
- [DefaultValue(100)]
- public long ProgressDialogSizeMaxValue
- {
- get => totalSize;
- set { totalSize = value; UpdateProgress(); }
- }
-
- /// Current size in bytes, used for showing progress in bytes.
- [DefaultValue(0)]
- public long ProgressDialogSizeValue
- {
- get => currentSize;
- set { currentSize = value; UpdateProgress(); }
- }
-
- /// Gets the remaining time.
- /// The remaining time, accurate to milliseconds.
- public TimeSpan RemainingTime
- {
- get
- {
- ulong t = 0;
- if (CanProcess)
- try { iProgressDialog.GetMilliseconds(out _, out t); } catch { }
- return TimeSpan.FromMilliseconds(t);
- }
- }
-
- /// Add a pause button (operation can be paused)
- [DefaultValue(false)]
- public bool ShowPauseButton { get; set; }
-
- /// A ShellItem that represents the source Shell item.
- public ShellItem Source { get => sourceItem; set { sourceItem = value ?? throw new ArgumentNullException(nameof(Source)); UpdateLocations(); } }
-
- /// Gets operation status for progress dialog.
- /// The operation status. See .
- public DialogStatus Status => (DialogStatus)(CanProcess ? iProgressDialog.GetOperationStatus() : 0);
-
- private bool CanProcess => iProgressDialog != null;
-
- private OPPROGDLGF DialogFlags => (ShowPauseButton ? OPPROGDLGF.OPPROGDLG_ENABLEPAUSE : 0) |
- (AllowUndo ? OPPROGDLGF.OPPROGDLG_ALLOWUNDO : 0) |
- (HideSourcePath ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYSOURCEPATH : 0) |
- (HideDestinationPath ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYDESTPATH : 0) |
- (HideLocations ? OPPROGDLGF.OPPROGDLG_DONTDISPLAYLOCATIONS : 0);
-
- /// Pauses progress dialog timer.
- public void PauseTimer() { if (CanProcess) iProgressDialog.PauseTimer(); }
-
- /// Resets progress dialog timer to 0.
- public void ResetTimer() { if (CanProcess) iProgressDialog.ResetTimer(); }
-
- /// Resumes progress dialog timer.
- public void ResumeTimer() { if (CanProcess) iProgressDialog.ResumeTimer(); }
-
- /// Starts the specified progress dialog.
- ///
- /// A value that represents the window of the owner window for the common dialog box. This value can be .
- ///
- public void Start(HWND owner = default)
- {
- iProgressDialog = new IOperationsProgressDialog();
- iProgressDialog.StartProgressDialog(owner, DialogFlags);
- iProgressDialog.SetOperation((SPACTION)operation);
- iProgressDialog.SetMode((PDMODE)mode);
- UpdateLocations();
- UpdateProgress();
- }
-
- /// Stops current progress dialog.
- public void Stop()
- {
- if (!CanProcess)
- return;
-
- iProgressDialog.StopProgressDialog();
- Thread.Sleep(500);
- iProgressDialog = null;
- }
-
- ///
- /// Releases the unmanaged resources used by the and optionally releases the managed resources.
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
- protected override void Dispose(bool disposing)
- {
- Stop();
- base.Dispose(disposing);
- }
-
- private void UpdateLocations()
- {
- if (CanProcess)
- iProgressDialog.UpdateLocations(sourceItem.IShellItem, destItem.IShellItem, currentItem?.IShellItem);
- }
-
- private void UpdateProgress()
- {
- if (CanProcess)
- iProgressDialog.UpdateProgress((ulong)currentProgress, (ulong)totalProgress, (ulong)currentSize, (ulong)totalSize, (ulong)currentItems, (ulong)totalItems);
- }
- }
-
public delegate void ProgressChangedEventHandler(object? sender, ProgressChangedEventArgs e);
public class ProgressChangedEventArgs : EventArgs
From f43af45dcb1da5a3c76e924fb2152f2d655cdee0 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 22:48:47 +0900
Subject: [PATCH 15/97] Fixed build issues
---
.../StatusCenterStyles.xaml | 8 +-
.../StatusCenterItemProgressModel.cs | 5 +
.../FileOperationsHelpers.cs | 125 +++++++++++-------
.../Operations/ShellFilesystemOperations.cs | 27 +---
4 files changed, 86 insertions(+), 79 deletions(-)
rename src/Files.App/Utils/Storage/{Helpers => Operations}/FileOperationsHelpers.cs (92%)
diff --git a/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml b/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
index 4dd35bac125a..4c975d9a5886 100644
--- a/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
+++ b/src/Files.App/ResourceDictionaries/StatusCenterStyles.xaml
@@ -7,7 +7,7 @@
-
+
@@ -15,7 +15,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
@@ -43,7 +43,7 @@
-
+
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
index 15e031d83dbf..1883589307f4 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItemProgressModel.cs
@@ -9,6 +9,11 @@ namespace Files.App.Utils.StatusCenter
///
/// Represents a model for file system operation progress.
///
+ ///
+ /// Every instance that have the same instance will update the same progress.
+ ///
+ /// Therefore, the storage operation classes can portably instance this class and update progress from everywhere with the same instance.
+ ///
public class StatusCenterItemProgressModel : INotifyPropertyChanged
{
private readonly IProgress? _progress;
diff --git a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs
similarity index 92%
rename from src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
rename to src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs
index c2c74ad0e26f..f36975cb1154 100644
--- a/src/Files.App/Utils/Storage/Helpers/FileOperationsHelpers.cs
+++ b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs
@@ -199,17 +199,13 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- long totalSize = 0;
- foreach (var item in fileToCopyPath)
- {
- totalSize += GetFileSize(item);
- }
+ long totalSize = fileToDeletePath.Select(GetFileSize).Sum();
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- fileToCopyPath.Count(),
+ fileToDeletePath.Count(),
totalSize);
fsProgress.Report();
@@ -218,19 +214,26 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
return Win32API.StartSTATask(async () =>
{
using var op = new ShellFileOperations();
- op.Options = ShellFileOperations.OperationFlags.Silent
- | ShellFileOperations.OperationFlags.NoConfirmation
- | ShellFileOperations.OperationFlags.NoErrorUI;
+
+ op.Options =
+ ShellFileOperations.OperationFlags.Silent |
+ ShellFileOperations.OperationFlags.NoConfirmation |
+ ShellFileOperations.OperationFlags.NoErrorUI;
+
if (asAdmin)
{
- op.Options |= ShellFileOperations.OperationFlags.ShowElevationPrompt
- | ShellFileOperations.OperationFlags.RequireElevation;
+ op.Options |=
+ ShellFileOperations.OperationFlags.ShowElevationPrompt |
+ ShellFileOperations.OperationFlags.RequireElevation;
}
+
op.OwnerWindow = (IntPtr)ownerHwnd;
+
if (!permanently)
{
- op.Options |= ShellFileOperations.OperationFlags.RecycleOnDelete
- | ShellFileOperations.OperationFlags.WantNukeWarning;
+ op.Options |=
+ ShellFileOperations.OperationFlags.RecycleOnDelete |
+ ShellFileOperations.OperationFlags.WantNukeWarning;
}
var shellOperationResult = new ShellOperationResult();
@@ -240,6 +243,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
if (!SafetyExtensions.IgnoreExceptions(() =>
{
using var shi = new ShellItem(fileToDeletePath[i]);
+
op.QueueDeleteOperation(shi);
}))
{
@@ -256,13 +260,16 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progressHandler.AddOperation(operationID);
var deleteTcs = new TaskCompletionSource();
+
+ // Right before deleting item
op.PreDeleteItem += (s, e) =>
{
+ // E_FAIL, stops operation
if (!permanently && !e.Flags.HasFlag(ShellFileOperations.TransferFlags.DeleteRecycleIfPossible))
- {
- throw new Win32Exception(HRESULT.COPYENGINE_E_RECYCLE_BIN_NOT_FOUND); // E_FAIL, stops operation
- }
+ throw new Win32Exception(HRESULT.COPYENGINE_E_RECYCLE_BIN_NOT_FOUND);
};
+
+ // Right after deleted item
op.PostDeleteItem += (s, e) =>
{
shellOperationResult.Items.Add(new ShellOperationItemResult()
@@ -272,15 +279,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
Destination = e.DestItem.GetParsingPath(),
HResult = (int)e.Result
});
+
+ UpdateFileTagsDb(e, "delete");
};
- op.PostDeleteItem += (_, e) => UpdateFileTagsDb(e, "delete");
- op.FinishOperations += (s, e) => deleteTcs.TrySetResult(e.Result.Succeeded);
+
+ op.FinishOperations += (s, e)
+ => deleteTcs.TrySetResult(e.Result.Succeeded);
+
op.UpdateProgress += (s, e) =>
{
+ // E_FAIL, stops operation
if (progressHandler.CheckCanceled(operationID))
- {
- throw new Win32Exception(unchecked((int)0x80004005)); // E_FAIL, stops operation
- }
+ throw new Win32Exception(unchecked((int)0x80004005));
+
fsProgress.Report(e.ProgressPercentage);
progressHandler.UpdateOperation(operationID, e.ProgressPercentage);
};
@@ -371,17 +382,13 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- long totalSize = 0;
- foreach (var item in fileToCopyPath)
- {
- totalSize += GetFileSize(item);
- }
+ long totalSize = fileToMovePath.Select(GetFileSize).Sum();
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- fileToCopyPath.Count(),
+ fileToMovePath.Count(),
totalSize);
fsProgress.Report();
@@ -392,24 +399,32 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
using var op = new ShellFileOperations();
var shellOperationResult = new ShellOperationResult();
- op.Options = ShellFileOperations.OperationFlags.NoConfirmMkDir
- | ShellFileOperations.OperationFlags.Silent
- | ShellFileOperations.OperationFlags.NoErrorUI;
+ op.Options =
+ ShellFileOperations.OperationFlags.NoConfirmMkDir |
+ ShellFileOperations.OperationFlags.Silent |
+ ShellFileOperations.OperationFlags.NoErrorUI;
+
if (asAdmin)
{
- op.Options |= ShellFileOperations.OperationFlags.ShowElevationPrompt
- | ShellFileOperations.OperationFlags.RequireElevation;
+ op.Options |=
+ ShellFileOperations.OperationFlags.ShowElevationPrompt |
+ ShellFileOperations.OperationFlags.RequireElevation;
}
+
op.OwnerWindow = (IntPtr)ownerHwnd;
- op.Options |= !overwriteOnMove ? ShellFileOperations.OperationFlags.PreserveFileExtensions | ShellFileOperations.OperationFlags.RenameOnCollision
- : ShellFileOperations.OperationFlags.NoConfirmation;
+
+ op.Options |=
+ !overwriteOnMove
+ ? ShellFileOperations.OperationFlags.PreserveFileExtensions | ShellFileOperations.OperationFlags.RenameOnCollision
+ : ShellFileOperations.OperationFlags.NoConfirmation;
for (var i = 0; i < fileToMovePath.Length; i++)
{
if (!SafetyExtensions.IgnoreExceptions(() =>
{
- using ShellItem shi = new ShellItem(fileToMovePath[i]);
- using ShellFolder shd = new ShellFolder(Path.GetDirectoryName(moveDestination[i]));
+ using ShellItem shi = new(fileToMovePath[i]);
+ using ShellFolder shd = new(Path.GetDirectoryName(moveDestination[i]));
+
op.QueueMoveOperation(shi, shd, Path.GetFileName(moveDestination[i]));
}))
{
@@ -427,6 +442,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
progressHandler.AddOperation(operationID);
var moveTcs = new TaskCompletionSource();
+
op.PostMoveItem += (s, e) =>
{
shellOperationResult.Items.Add(new ShellOperationItemResult()
@@ -437,14 +453,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
HResult = (int)e.Result
});
};
- op.PostMoveItem += (_, e) => UpdateFileTagsDb(e, "move");
- op.FinishOperations += (s, e) => moveTcs.TrySetResult(e.Result.Succeeded);
+
+ op.PostMoveItem += (_, e)
+ => UpdateFileTagsDb(e, "move");
+
+ op.FinishOperations += (s, e)
+ => moveTcs.TrySetResult(e.Result.Succeeded);
+
op.UpdateProgress += (s, e) =>
{
+ // E_FAIL, stops operation
if (progressHandler.CheckCanceled(operationID))
- {
- throw new Win32Exception(unchecked((int)0x80004005)); // E_FAIL, stops operation
- }
+ throw new Win32Exception(unchecked((int)0x80004005));
+
fsProgress.Report(e.ProgressPercentage);
progressHandler.UpdateOperation(operationID, e.ProgressPercentage);
};
@@ -468,11 +489,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
{
operationID = string.IsNullOrEmpty(operationID) ? Guid.NewGuid().ToString() : operationID;
- long totalSize = 0;
- foreach (var item in fileToCopyPath)
- {
- totalSize += GetFileSize(item);
- }
+ long totalSize = fileToCopyPath.Select(GetFileSize).Sum();
StatusCenterItemProgressModel fsProgress = new(
progress,
@@ -503,6 +520,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
}
op.OwnerWindow = (IntPtr)ownerHwnd;
+
op.Options |=
!overwriteOnCopy
? ShellFileOperations.OperationFlags.PreserveFileExtensions | ShellFileOperations.OperationFlags.RenameOnCollision
@@ -543,14 +561,19 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera
HResult = (int)e.Result
});
};
- op.PostCopyItem += (_, e) => UpdateFileTagsDb(e, "copy");
- op.FinishOperations += (s, e) => copyTcs.TrySetResult(e.Result.Succeeded);
+
+ op.PostCopyItem += (_, e)
+ => UpdateFileTagsDb(e, "copy");
+
+ op.FinishOperations += (s, e)
+ => copyTcs.TrySetResult(e.Result.Succeeded);
+
op.UpdateProgress += (s, e) =>
{
+ // E_FAIL, stops operation
if (progressHandler.CheckCanceled(operationID))
- {
- throw new Win32Exception(unchecked((int)0x80004005)); // E_FAIL, stops operation
- }
+ throw new Win32Exception(unchecked((int)0x80004005));
+
fsProgress.Report(e.ProgressPercentage);
progressHandler.UpdateOperation(operationID, e.ProgressPercentage);
};
diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
index 999e2119034f..1ba84ed19283 100644
--- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
+++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs
@@ -44,18 +44,11 @@ public async Task CopyItemsAsync(IList so
return await _filesystemOperations.CopyItemsAsync(source, destination, collisions, progress, cancellationToken);
}
- long totalSize = 0;
- foreach (var item in source)
- {
- totalSize += FileOperationsHelpers.GetFileSize(item.Path);
- }
-
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count(),
- totalSize);
+ source.Count());
fsProgress.Report();
@@ -355,18 +348,11 @@ public async Task DeleteItemsAsync(IList
return await _filesystemOperations.DeleteItemsAsync(source, progress, permanently, cancellationToken);
}
- long totalSize = 0;
- foreach (var item in source)
- {
- totalSize += FileOperationsHelpers.GetFileSize(item.Path);
- }
-
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count(),
- totalSize);
+ source.Count());
fsProgress.Report();
@@ -481,18 +467,11 @@ public async Task MoveItemsAsync(IList so
return await _filesystemOperations.MoveItemsAsync(source, destination, collisions, progress, cancellationToken);
}
- long totalSize = 0;
- foreach (var item in source)
- {
- totalSize += FileOperationsHelpers.GetFileSize(item.Path);
- }
-
StatusCenterItemProgressModel fsProgress = new(
progress,
true,
FileSystemStatusCode.InProgress,
- source.Count(),
- totalSize);
+ source.Count());
fsProgress.Report();
From e8322d2dc82b4ae3fab0767adbef328992c1a1de Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Sun, 17 Sep 2023 22:57:40 +0900
Subject: [PATCH 16/97] fix
---
.../Utils/Archives/CompressArchiveModel.cs | 27 +++++++++----------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/Files.App/Utils/Archives/CompressArchiveModel.cs b/src/Files.App/Utils/Archives/CompressArchiveModel.cs
index 622837c74781..c1f8a9799295 100644
--- a/src/Files.App/Utils/Archives/CompressArchiveModel.cs
+++ b/src/Files.App/Utils/Archives/CompressArchiveModel.cs
@@ -77,7 +77,19 @@ public IProgress Progress
set
{
_Progress = value;
- _fileSystemProgress = new(Progress, true, FileSystemStatusCode.InProgress);
+
+ long totalSize = 0;
+
+ if (Sources is not null)
+ totalSize = Sources.Select(FileOperationsHelpers.GetFileSize).Sum();
+
+ _fileSystemProgress = new(
+ Progress,
+ true,
+ FileSystemStatusCode.InProgress,
+ Sources is null ? 0 : Sources.Count(),
+ totalSize);
+
_fileSystemProgress.Report(0);
}
}
@@ -115,19 +127,6 @@ public CompressArchiveModel(
ArchiveCompressionLevels compressionLevel = ArchiveCompressionLevels.Normal,
ArchiveSplittingSizes splittingSize = ArchiveSplittingSizes.None)
{
- long totalSize = 0;
- foreach (var item in Sources)
- {
- totalSize += FileOperationsHelpers.GetFileSize(item);
- }
-
- _fileSystemProgress = new(
- Progress,
- true,
- FileSystemStatusCode.InProgress,
- Sources.Count(),
- totalSize);
-
_Progress = new Progress();
Sources = source;
From b90dd1f440c9af6a26483af26827ef28d928e1c6 Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Mon, 18 Sep 2023 22:35:09 +0900
Subject: [PATCH 17/97] Update
---
.../Decompress/BaseDecompressArchiveAction.cs | 2 +-
.../Archives/Decompress/DecompressArchive.cs | 2 +-
.../Decompress/DecompressArchiveHere.cs | 2 +-
.../DecompressArchiveToChildFolderAction.cs | 2 +-
.../MenuFlyout/ContextFlyoutItemHelper.cs | 2 +-
src/Files.App/Strings/en-US/Resources.resw | 218 +++++++-----
.../Utils/Archives/CompressHelper.cs | 211 ++---------
.../Utils/Archives/DecompressHelper.cs | 168 +++++++++
.../Utils/StatusCenter/StatusCenterHelper.cs | 330 +++++++++++++++---
.../Utils/StatusCenter/StatusCenterItem.cs | 54 ++-
10 files changed, 620 insertions(+), 371 deletions(-)
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
index f5f47979ab74..f7bfd13e9094 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
@@ -16,7 +16,7 @@ public virtual HotKey HotKey
public override bool IsExecutable =>
(IsContextPageTypeAdaptedToCommand() &&
- CompressHelper.CanDecompress(context.SelectedItems) ||
+ DecompressHelper.CanDecompress(context.SelectedItems) ||
CanDecompressInsideArchive()) &&
UIHelpers.CanShowDialog;
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
index c9ed484b265b..089e7aada9f9 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
@@ -23,7 +23,7 @@ public DecompressArchive()
public override Task ExecuteAsync()
{
- return CompressHelper.DecompressArchive(context.ShellPage);
+ return DecompressHelper.DecompressArchive(context.ShellPage);
}
protected override bool CanDecompressInsideArchive()
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
index 7e0419bfc613..e41c9d6487c9 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
@@ -17,7 +17,7 @@ public DecompressArchiveHere()
public override Task ExecuteAsync()
{
- return CompressHelper.DecompressArchiveHere(context.ShellPage);
+ return DecompressHelper.DecompressArchiveHere(context.ShellPage);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
index 44836ae649d7..dd7359ee9f01 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
@@ -17,7 +17,7 @@ public DecompressArchiveToChildFolderAction()
public override Task ExecuteAsync()
{
- return CompressHelper.DecompressArchiveToChildFolder(context.ShellPage);
+ return DecompressHelper.DecompressArchiveToChildFolder(context.ShellPage);
}
protected override void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
diff --git a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
index 643d3cc54726..080bcf5227ff 100644
--- a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
+++ b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
@@ -519,7 +519,7 @@ public static List GetBaseItemMenuItems(
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveHere).Build(),
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveToChildFolder).Build(),
},
- ShowItem = CompressHelper.CanDecompress(selectedItems)
+ ShowItem = DecompressHelper.CanDecompress(selectedItems)
},
new ContextMenuFlyoutItemViewModel()
{
diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw
index e6b9d123db9e..5c34cf80041f 100644
--- a/src/Files.App/Strings/en-US/Resources.resw
+++ b/src/Files.App/Strings/en-US/Resources.resw
@@ -426,11 +426,11 @@
items
-
- Deleting files
+
+ Delete in progress
-
- Moving files to the Recycle Bin
+
+ Recycle in progress
Yes
@@ -1176,22 +1176,22 @@
Item count
-
- Deletion Failed
+
+ Delete error
-
- Deletion complete
+
+ Delete done successfully
-
- Deletion cancelled
+
+ Canceled deleting
-
- Recycle complete
+
+ Recycle done successfully
-
- Move complete
+
+ Move successfully
-
+
Copy complete
@@ -1416,101 +1416,95 @@
Privacy
-
- Move canceled
+
+ Canceled move
-
- Copy canceled
+
+ Canceled copying
-
- Moving {0} item from {1} to {2} was canceled
+
+ Move in progress
-
- Moving {0} items from {1} to {2} was canceled after moving {3} items
+
+ Successfully copied {0} items to {1}
-
- Moving {0} items from {1} to {2} was canceled after moving {3} item
+
+ Canceled move
-
- Moving {0} item from {1} to {2}
+
+ Canceled move
-
- Moving {0} items from {1} to {2}
+
+ Canceled move
-
- Successfully moved {0} item from {1} to {2}
+
+ Move in progress
-
- Successfully moved {0} items from {1} to {2}
+
+ Move successfully
-
- Failed to move {0} item from {1} to {2}
+
+ Move successfully
-
- Failed to move {0} items from {1} to {2}
+
+ Move error
-
- Copying {0} item to {1} was canceled
+
+ Move error
-
- Copying {0} items to {1} was canceled after copying {2} items
+
+ {0} item copied to "{1}"
-
- Copying {0} items to {1} was canceled after copying {2} item
+
+ {0} / {1} items copied to"{2}"
-
+
Copying {0} item to {1}
-
+
Copying {0} items to {1}
-
+
Successfully copied {0} item to {1}
-
- Successfully copied {0} items to {1}
-
-
- Deleting {0} item from {1} was canceled
-
-
- Deleting {0} items from {1} was canceled after deleting {3} items
+
+ Canceled deleting
-
- Deleting {0} items from {1} was canceled after deleting {3} item
+
+ Canceled deleting
-
- Deleting {0} item from {1}
+
+ Delete in progress
-
- Deleting {0} items from {1}
+
+ Delete in progress
-
- Successfully deleted {0} item from {1}
+
+ Delete done successfully
-
- Successfully deleted {0} items from {1}
+
+ Delete done successfully
-
- Failed to delete {0} item from {1}
+
+ Delete error
-
- Failed to delete {0} items from {1}
+
+ Delete error
the Recycle Bin
-
- Moving items
+
+ Move in progress
-
+
Copying items
-
- Recycle failed
+
+ Recycle error
-
- Recycle cancelled
+
+ Canceled recycling
canceling
@@ -1791,11 +1785,11 @@
The archive extraction completed successfully.
-
- Extracting archive
+
+ Decompress in progress
-
- Extracting complete!
+
+ Decompress done successfully
Open parent folder
@@ -2097,23 +2091,23 @@
Update Files
-
+
Preparing {0} items
-
+
Preparing items
-
- Copy failed
+
+ Copy unsuccessful
-
- Failed to copy {0} items from {1} to {2}
+
+ {0} items failed to copy to {1}
-
- Failed to copy {0} item from {1} to {2}
+
+ {0} item failed to copy to {1}
-
- Move failed
+
+ Move error
Tags
@@ -2205,17 +2199,17 @@
Opening items
-
- Compression completed
+
+ Archive "{0}" created
-
- {0} has been compressed
+
+ Archive "{0}" created
-
- {0} couldn't be compressed
+
+ Failed to create an archive
-
- Compressing archive
+
+ Creating archive "{0}"
Compress
@@ -3526,4 +3520,34 @@
Clear completed
+
+ Canceled creating archive "{0}"
+
+
+ Canceled creating archive "{0}"
+
+
+ Failed to create an archive
+
+
+ Creating archive "{0}"
+
+
+ Decompress cancel
+
+
+ Decompress cancel
+
+
+ Decompress error
+
+
+ Decompress error
+
+
+ Decompress in progress
+
+
+ Decompress done successfully
+
\ No newline at end of file
diff --git a/src/Files.App/Utils/Archives/CompressHelper.cs b/src/Files.App/Utils/Archives/CompressHelper.cs
index 554d2ee9b712..5eebdeae3ebd 100644
--- a/src/Files.App/Utils/Archives/CompressHelper.cs
+++ b/src/Files.App/Utils/Archives/CompressHelper.cs
@@ -1,13 +1,7 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
-using Files.App.Dialogs;
-using Files.App.ViewModels.Dialogs;
-using Files.Shared.Helpers;
-using Microsoft.UI.Xaml.Controls;
using System.IO;
-using System.Text;
-using Windows.Storage;
namespace Files.App.Utils.Archives
{
@@ -18,16 +12,9 @@ public static class CompressHelper
{
private readonly static StatusCenterViewModel _statusCenterViewModel = Ioc.Default.GetRequiredService();
- public static bool CanDecompress(IReadOnlyList selectedItems)
- {
- return selectedItems.Any() &&
- (selectedItems.All(x => x.IsArchive)
- || selectedItems.All(x => x.PrimaryItemAttribute == StorageItemTypes.File && FileExtensionHelpers.IsZipFile(x.FileExtension)));
- }
-
public static bool CanCompress(IReadOnlyList selectedItems)
{
- return !CanDecompress(selectedItems) || selectedItems.Count > 1;
+ return !DecompressHelper.CanDecompress(selectedItems) || selectedItems.Count > 1;
}
public static string DetermineArchiveNameFromSelection(IReadOnlyList selectedItems)
@@ -67,197 +54,49 @@ public static async Task CompressArchiveAsync(ICompressArchiveModel creator)
var archivePath = creator.GetArchivePath();
int index = 1;
- while (File.Exists(archivePath) || System.IO.Directory.Exists(archivePath))
+
+ while (File.Exists(archivePath) || Directory.Exists(archivePath))
archivePath = creator.GetArchivePath($" ({++index})");
+
creator.ArchivePath = archivePath;
- CancellationTokenSource compressionToken = new();
- StatusCenterItem banner = _statusCenterViewModel.AddItem
- (
- "CompressionInProgress".GetLocalizedResource(),
- archivePath,
- initialProgress: 0,
+ // Add in-progress status banner
+ var banner = StatusCenterHelper.PostBanner_Compress(
+ creator.Sources,
+ archivePath.CreateEnumerable(),
ReturnResult.InProgress,
- FileOperationType.Compressed,
- compressionToken
- );
+ false,
+ 0);
creator.Progress = banner.ProgressEventSource;
+
+ // Perform compress operation
bool isSuccess = await creator.RunCreationAsync();
+ // Remove in-progress status banner
_statusCenterViewModel.RemoveItem(banner);
if (isSuccess)
{
- _statusCenterViewModel.AddItem
- (
- "CompressionCompleted".GetLocalizedResource(),
- string.Format("CompressionSucceded".GetLocalizedResource(), archivePath),
- 0,
+ // Add successful status banner
+ StatusCenterHelper.PostBanner_Compress(
+ creator.Sources,
+ archivePath.CreateEnumerable(),
ReturnResult.Success,
- FileOperationType.Compressed
- );
+ false,
+ creator.Sources.Count());
}
else
{
NativeFileOperationsHelper.DeleteFileFromApp(archivePath);
- _statusCenterViewModel.AddItem
- (
- "CompressionCompleted".GetLocalizedResource(),
- string.Format("CompressionFailed".GetLocalizedResource(), archivePath),
- 0,
+ // Add error status banner
+ StatusCenterHelper.PostBanner_Compress(
+ creator.Sources,
+ archivePath.CreateEnumerable(),
ReturnResult.Failed,
- FileOperationType.Compressed
- );
- }
- }
-
- // TODO: Move all below code to DecompressHelper class
-
- private static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFolder? destinationFolder, string password)
- {
- if (archive is null || destinationFolder is null)
- return;
-
- CancellationTokenSource extractCancellation = new();
-
- StatusCenterItem banner = _statusCenterViewModel.AddItem(
- "ExtractingArchiveText".GetLocalizedResource(),
- archive.Path,
- 0,
- ReturnResult.InProgress,
- FileOperationType.Extract,
- extractCancellation);
-
- await FilesystemTasks.Wrap(() => DecompressHelper.ExtractArchive(archive, destinationFolder, password, banner.ProgressEventSource, extractCancellation.Token));
-
- _statusCenterViewModel.RemoveItem(banner);
-
- _statusCenterViewModel.AddItem(
- "ExtractingCompleteText".GetLocalizedResource(),
- "ArchiveExtractionCompletedSuccessfullyText".GetLocalizedResource(),
- 0,
- ReturnResult.Success,
- FileOperationType.Extract);
- }
-
- public static async Task DecompressArchive(IShellPage associatedInstance)
- {
- if (associatedInstance == null)
- return;
-
- BaseStorageFile archive = await StorageHelpers.ToStorageItem(associatedInstance.SlimContentPage.SelectedItems.Count != 0
- ? associatedInstance.SlimContentPage.SelectedItem.ItemPath
- : associatedInstance.FilesystemViewModel.WorkingDirectory);
-
- if (archive is null)
- return;
-
- var isArchiveEncrypted = await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive));
- var password = string.Empty;
-
- DecompressArchiveDialog decompressArchiveDialog = new();
- DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
- {
- IsArchiveEncrypted = isArchiveEncrypted,
- ShowPathSelection = true
- };
- decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
-
- ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
- if (option != ContentDialogResult.Primary)
- return;
-
- if (isArchiveEncrypted)
- password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
-
- // Check if archive still exists
- if (!StorageHelpers.Exists(archive.Path))
- return;
-
- BaseStorageFolder destinationFolder = decompressArchiveViewModel.DestinationFolder;
- string destinationFolderPath = decompressArchiveViewModel.DestinationFolderPath;
-
- if (destinationFolder is null)
- {
- BaseStorageFolder parentFolder = await StorageHelpers.ToStorageItem(Path.GetDirectoryName(archive.Path));
- destinationFolder = await FilesystemTasks.Wrap(() => parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName).AsTask());
- }
-
- await ExtractArchive(archive, destinationFolder, password);
-
- if (decompressArchiveViewModel.OpenDestinationFolderOnCompletion)
- await NavigationHelpers.OpenPath(destinationFolderPath, associatedInstance, FilesystemItemType.Directory);
- }
-
- public static async Task DecompressArchiveHere(IShellPage associatedInstance)
- {
- if (associatedInstance == null)
- return;
-
- foreach (var selectedItem in associatedInstance.SlimContentPage.SelectedItems)
- {
- var password = string.Empty;
- BaseStorageFile archive = await StorageHelpers.ToStorageItem(selectedItem.ItemPath);
- BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
-
- if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
- {
- DecompressArchiveDialog decompressArchiveDialog = new();
- DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
- {
- IsArchiveEncrypted = true,
- ShowPathSelection = false
- };
-
- decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
-
- ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
- if (option != ContentDialogResult.Primary)
- return;
-
- password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
- }
-
- await ExtractArchive(archive, currentFolder, password);
- }
- }
-
- public static async Task DecompressArchiveToChildFolder(IShellPage associatedInstance)
- {
- if (associatedInstance == null)
- return;
-
- foreach (var selectedItem in associatedInstance.SlimContentPage.SelectedItems)
- {
- var password = string.Empty;
-
- BaseStorageFile archive = await StorageHelpers.ToStorageItem(selectedItem.ItemPath);
- BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
- BaseStorageFolder destinationFolder = null;
-
- if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
- {
- DecompressArchiveDialog decompressArchiveDialog = new();
- DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
- {
- IsArchiveEncrypted = true,
- ShowPathSelection = false
- };
- decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
-
- ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
- if (option != ContentDialogResult.Primary)
- return;
-
- password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
- }
-
- if (currentFolder is not null)
- destinationFolder = await FilesystemTasks.Wrap(() => currentFolder.CreateFolderAsync(Path.GetFileNameWithoutExtension(archive.Path), CreationCollisionOption.GenerateUniqueName).AsTask());
-
- await ExtractArchive(archive, destinationFolder, password);
+ false,
+ 0);
}
}
}
diff --git a/src/Files.App/Utils/Archives/DecompressHelper.cs b/src/Files.App/Utils/Archives/DecompressHelper.cs
index a4acf926643d..65b63d498f96 100644
--- a/src/Files.App/Utils/Archives/DecompressHelper.cs
+++ b/src/Files.App/Utils/Archives/DecompressHelper.cs
@@ -1,14 +1,29 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
+using Files.App.Dialogs;
+using Files.App.ViewModels.Dialogs;
+using Files.Shared.Helpers;
using Microsoft.Extensions.Logging;
+using Microsoft.UI.Xaml.Controls;
using SevenZip;
using System.IO;
+using System.Text;
+using Windows.Storage;
namespace Files.App.Utils.Archives
{
public static class DecompressHelper
{
+ private readonly static StatusCenterViewModel _statusCenterViewModel = Ioc.Default.GetRequiredService();
+
+ public static bool CanDecompress(IReadOnlyList selectedItems)
+ {
+ return selectedItems.Any() &&
+ (selectedItems.All(x => x.IsArchive)
+ || selectedItems.All(x => x.PrimaryItemAttribute == StorageItemTypes.File && FileExtensionHelpers.IsZipFile(x.FileExtension)));
+ }
+
private static async Task GetZipFile(BaseStorageFile archive, string password = "")
{
return await FilesystemTasks.Wrap(async () =>
@@ -137,5 +152,158 @@ public static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFold
fsProgress.Report();
}
}
+
+ private static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFolder? destinationFolder, string password)
+ {
+ if (archive is null || destinationFolder is null)
+ return;
+
+ // Add in-progress status banner
+ var banner = StatusCenterHelper.PostBanner_Compress(
+ archive.Path.CreateEnumerable(),
+ destinationFolder.Path.CreateEnumerable(),
+ ReturnResult.InProgress,
+ false,
+ 0);
+
+ // Perform decompress operation
+ await FilesystemTasks.Wrap(()
+ => ExtractArchive(
+ archive,
+ destinationFolder,
+ password,
+ banner.ProgressEventSource,
+ banner.CancellationToken));
+
+ // Remove in-progress status banner
+ _statusCenterViewModel.RemoveItem(banner);
+
+ // Add successful status banner
+ StatusCenterHelper.PostBanner_Compress(
+ archive.Path.CreateEnumerable(),
+ destinationFolder.Path.CreateEnumerable(),
+ ReturnResult.Success,
+ false,
+ 1);
+ }
+
+ public static async Task DecompressArchive(IShellPage associatedInstance)
+ {
+ if (associatedInstance == null)
+ return;
+
+ BaseStorageFile archive = await StorageHelpers.ToStorageItem(associatedInstance.SlimContentPage.SelectedItems.Count != 0
+ ? associatedInstance.SlimContentPage.SelectedItem.ItemPath
+ : associatedInstance.FilesystemViewModel.WorkingDirectory);
+
+ if (archive is null)
+ return;
+
+ var isArchiveEncrypted = await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive));
+ var password = string.Empty;
+
+ DecompressArchiveDialog decompressArchiveDialog = new();
+ DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
+ {
+ IsArchiveEncrypted = isArchiveEncrypted,
+ ShowPathSelection = true
+ };
+ decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
+
+ ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
+ if (option != ContentDialogResult.Primary)
+ return;
+
+ if (isArchiveEncrypted)
+ password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
+
+ // Check if archive still exists
+ if (!StorageHelpers.Exists(archive.Path))
+ return;
+
+ BaseStorageFolder destinationFolder = decompressArchiveViewModel.DestinationFolder;
+ string destinationFolderPath = decompressArchiveViewModel.DestinationFolderPath;
+
+ if (destinationFolder is null)
+ {
+ BaseStorageFolder parentFolder = await StorageHelpers.ToStorageItem(Path.GetDirectoryName(archive.Path));
+ destinationFolder = await FilesystemTasks.Wrap(() => parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName).AsTask());
+ }
+
+ await ExtractArchive(archive, destinationFolder, password);
+
+ if (decompressArchiveViewModel.OpenDestinationFolderOnCompletion)
+ await NavigationHelpers.OpenPath(destinationFolderPath, associatedInstance, FilesystemItemType.Directory);
+ }
+
+ public static async Task DecompressArchiveHere(IShellPage associatedInstance)
+ {
+ if (associatedInstance == null)
+ return;
+
+ foreach (var selectedItem in associatedInstance.SlimContentPage.SelectedItems)
+ {
+ var password = string.Empty;
+ BaseStorageFile archive = await StorageHelpers.ToStorageItem(selectedItem.ItemPath);
+ BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
+
+ if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
+ {
+ DecompressArchiveDialog decompressArchiveDialog = new();
+ DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
+ {
+ IsArchiveEncrypted = true,
+ ShowPathSelection = false
+ };
+
+ decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
+
+ ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
+ if (option != ContentDialogResult.Primary)
+ return;
+
+ password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
+ }
+
+ await ExtractArchive(archive, currentFolder, password);
+ }
+ }
+
+ public static async Task DecompressArchiveToChildFolder(IShellPage associatedInstance)
+ {
+ if (associatedInstance == null)
+ return;
+
+ foreach (var selectedItem in associatedInstance.SlimContentPage.SelectedItems)
+ {
+ var password = string.Empty;
+
+ BaseStorageFile archive = await StorageHelpers.ToStorageItem(selectedItem.ItemPath);
+ BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath);
+ BaseStorageFolder destinationFolder = null;
+
+ if (await FilesystemTasks.Wrap(() => DecompressHelper.IsArchiveEncrypted(archive)))
+ {
+ DecompressArchiveDialog decompressArchiveDialog = new();
+ DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
+ {
+ IsArchiveEncrypted = true,
+ ShowPathSelection = false
+ };
+ decompressArchiveDialog.ViewModel = decompressArchiveViewModel;
+
+ ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
+ if (option != ContentDialogResult.Primary)
+ return;
+
+ password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
+ }
+
+ if (currentFolder is not null)
+ destinationFolder = await FilesystemTasks.Wrap(() => currentFolder.CreateFolderAsync(Path.GetFileNameWithoutExtension(archive.Path), CreationCollisionOption.GenerateUniqueName).AsTask());
+
+ await ExtractArchive(archive, destinationFolder, password);
+ }
+ }
}
}
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs
index 7090ccb675ac..d94562058a4f 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs
@@ -5,7 +5,7 @@ namespace Files.App.Utils.StatusCenter
{
public static class StatusCenterHelper
{
- private readonly static StatusCenterViewModel StatusCenterViewModel = Ioc.Default.GetRequiredService();
+ private readonly static StatusCenterViewModel _statusCenterViewModel = Ioc.Default.GetRequiredService();
public static StatusCenterItem PostBanner_Delete(IEnumerable source, ReturnResult returnStatus, bool permanently, bool canceled, int itemsDeleted)
{
@@ -15,22 +15,37 @@ public static StatusCenterItem PostBanner_Delete(IEnumerable 1 ?
- itemsDeleted > 1 ? "StatusDeleteCanceledDetails_Plural".GetLocalizedResource() : "StatusDeleteCanceledDetails_Plural2".GetLocalizedResource()
- : "StatusDeleteCanceledDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, null, itemsDeleted),
+ // Cancel permanent deletion
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DeleteCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsDeleted > 1
+ ? "StatusCenter_DeleteCancel_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_DeleteCancel_SubHeader_Plural2".GetLocalizedResource()
+ : "StatusCenter_DeleteCancel_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ null,
+ itemsDeleted),
0,
ReturnResult.Cancelled,
FileOperationType.Delete);
}
else
{
- return StatusCenterViewModel.AddItem(
- "StatusRecycleCancelled".GetLocalizedResource(),
- string.Format(source.Count() > 1 ?
- itemsDeleted > 1 ? "StatusMoveCanceledDetails_Plural".GetLocalizedResource() : "StatusMoveCanceledDetails_Plural2".GetLocalizedResource()
- : "StatusMoveCanceledDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, "TheRecycleBin".GetLocalizedResource(), itemsDeleted),
+ // Cancel recycling
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DeleteCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsDeleted > 1
+ ? "StatusCenter_MoveCancel_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveCancel_SubHeader_Plural2".GetLocalizedResource()
+ : "StatusCenter_MoveCancel_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ "TheRecycleBin".GetLocalizedResource(), itemsDeleted),
0,
ReturnResult.Cancelled,
FileOperationType.Recycle);
@@ -40,9 +55,14 @@ public static StatusCenterItem PostBanner_Delete(IEnumerable
- return StatusCenterViewModel.AddItem(string.Empty,
- string.Format(source.Count() > 1 ? "StatusDeletingItemsDetails_Plural".GetLocalizedResource() : "StatusDeletingItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir),
+ // Permanent deletion in progress
+ return _statusCenterViewModel.AddItem(string.Empty,
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_DeleteInProgress_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_DeleteInProgress_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir),
0,
ReturnResult.InProgress,
FileOperationType.Delete,
@@ -50,9 +70,15 @@ public static StatusCenterItem PostBanner_Delete(IEnumerable to recycle bin"
- return StatusCenterViewModel.AddItem(string.Empty,
- string.Format(source.Count() > 1 ? "StatusMovingItemsDetails_Plural".GetLocalizedResource() : "StatusMovingItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, "TheRecycleBin".GetLocalizedResource()),
+ // Recycling in progress
+ return _statusCenterViewModel.AddItem(string.Empty,
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_MoveInProgress_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveInProgress_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ "TheRecycleBin".GetLocalizedResource()),
0,
ReturnResult.InProgress,
FileOperationType.Recycle,
@@ -63,18 +89,32 @@ public static StatusCenterItem PostBanner_Delete(IEnumerable 1 ? "StatusDeletedItemsDetails_Plural".GetLocalizedResource() : "StatusDeletedItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, itemsDeleted),
+ // Done done permanent deletion successfully
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DeleteSuccessful_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_DeleteSuccessful_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_DeleteSuccessful_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ itemsDeleted),
0,
ReturnResult.Success,
FileOperationType.Delete);
}
else
{
- return StatusCenterViewModel.AddItem(
- "StatusRecycleComplete".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusMovedItemsDetails_Plural".GetLocalizedResource() : "StatusMovedItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, "TheRecycleBin".GetLocalizedResource()),
+ // Done done recycling successfully
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_RecycleSuccessful_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_DeleteSuccessful_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_DeleteSuccessful_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ "TheRecycleBin".GetLocalizedResource()),
0,
ReturnResult.Success,
FileOperationType.Recycle);
@@ -84,18 +124,32 @@ public static StatusCenterItem PostBanner_Delete(IEnumerable 1 ? "StatusDeletionFailedDetails_Plural".GetLocalizedResource() : "StatusDeletionFailedDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir),
+ // Done permanent deletion with error
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DeleteError_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_DeleteError_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_DeleteError_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir
+ ),
0,
ReturnResult.Failed,
FileOperationType.Delete);
}
else
{
- return StatusCenterViewModel.AddItem(
- "StatusRecycleFailed".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusMoveFailedDetails_Plural".GetLocalizedResource() : "StatusMoveFailedDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, "TheRecycleBin".GetLocalizedResource()),
+ // Done recycling with error
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_RecycleError_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_MoveError_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveError_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ "TheRecycleBin".GetLocalizedResource()),
0,
ReturnResult.Failed,
FileOperationType.Recycle);
@@ -110,38 +164,65 @@ public static StatusCenterItem PostBanner_Copy(IEnumerable
if (canceled)
{
- return StatusCenterViewModel.AddItem(
- "StatusCopyCanceled".GetLocalizedResource(),
- string.Format(source.Count() > 1 ?
- itemsCopied > 1 ? "StatusCopyCanceledDetails_Plural".GetLocalizedResource() : "StatusCopyCanceledDetails_Plural2".GetLocalizedResource() :
- "StatusCopyCanceledDetails_Singular".GetLocalizedResource(), source.Count(), destinationDir, itemsCopied),
+ // Cancel
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CopyCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsCopied > 1
+ ? "StatusCenter_CopyCancel_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_CopyCancel_SubHeader_Plural2".GetLocalizedResource()
+ : "StatusCenter_CopyCancel_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ destinationDir,
+ itemsCopied),
0,
ReturnResult.Cancelled,
FileOperationType.Copy);
}
else if (returnStatus == ReturnResult.InProgress)
{
- return StatusCenterViewModel.AddItem(
+ // In progress
+ return _statusCenterViewModel.AddItem(
string.Empty,
- string.Format(source.Count() > 1 ? "StatusCopyingItemsDetails_Plural".GetLocalizedResource() : "StatusCopyingItemsDetails_Singular".GetLocalizedResource(), source.Count(), destinationDir),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_CopyInProgress_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_CopyInProgress_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ destinationDir),
0,
ReturnResult.InProgress,
FileOperationType.Copy, new CancellationTokenSource());
}
else if (returnStatus == ReturnResult.Success)
{
- return StatusCenterViewModel.AddItem(
- "StatusCopyComplete".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusCopiedItemsDetails_Plural".GetLocalizedResource() : "StatusCopiedItemsDetails_Singular".GetLocalizedResource(), source.Count(), destinationDir, itemsCopied),
+ // Done successfully
+ return _statusCenterViewModel.AddItem(
+ "StatusCopySuccessful".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_CopySuccessfulSubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_CopySuccessfulSubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ destinationDir,
+ itemsCopied),
0,
ReturnResult.Success,
FileOperationType.Copy);
}
else
{
- return StatusCenterViewModel.AddItem(
- "StatusCopyFailed".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusCopyFailedDetails_Plural".GetLocalizedResource() : "StatusCopyFailedDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, destinationDir),
+ // Done with error
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CopyError_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_CopyError_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_CopyError_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ destinationDir),
0,
ReturnResult.Failed,
FileOperationType.Copy);
@@ -155,42 +236,181 @@ public static StatusCenterItem PostBanner_Move(IEnumerable
if (canceled)
{
- return StatusCenterViewModel.AddItem(
- "StatusMoveCanceled".GetLocalizedResource(),
- string.Format(source.Count() > 1 ?
- itemsMoved > 1 ? "StatusMoveCanceledDetails_Plural".GetLocalizedResource() : "StatusMoveCanceledDetails_Plural2".GetLocalizedResource()
- : "StatusMoveCanceledDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, destinationDir, itemsMoved),
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_MoveCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsMoved > 1
+ ? "StatusCenter_MoveCancel_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveCancel_SubHeader_Plural2".GetLocalizedResource()
+ : "StatusCenter_MoveCancel_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ destinationDir,
+ itemsMoved),
0,
ReturnResult.Cancelled,
FileOperationType.Move);
}
else if (returnStatus == ReturnResult.InProgress)
{
- return StatusCenterViewModel.AddItem(
+ return _statusCenterViewModel.AddItem(
string.Empty,
- string.Format(source.Count() > 1 ? "StatusMovingItemsDetails_Plural".GetLocalizedResource() : "StatusMovingItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, destinationDir),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_MoveInProgress_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveInProgress_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ destinationDir),
0,
ReturnResult.InProgress,
FileOperationType.Move, new CancellationTokenSource());
}
else if (returnStatus == ReturnResult.Success)
{
- return StatusCenterViewModel.AddItem(
- "StatusMoveComplete".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusMovedItemsDetails_Plural".GetLocalizedResource() : "StatusMovedItemsDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, destinationDir, itemsMoved),
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_MoveSuccessful_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_MoveSuccessful_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveSuccessful_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir, destinationDir, itemsMoved),
0,
ReturnResult.Success,
FileOperationType.Move);
}
else
{
- return StatusCenterViewModel.AddItem(
- "StatusMoveFailed".GetLocalizedResource(),
- string.Format(source.Count() > 1 ? "StatusMoveFailedDetails_Plural".GetLocalizedResource() : "StatusMoveFailedDetails_Singular".GetLocalizedResource(), source.Count(), sourceDir, destinationDir),
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_MoveError_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? "StatusCenter_MoveError_SubHeader_Plural".GetLocalizedResource()
+ : "StatusCenter_MoveError_SubHeader_Singular".GetLocalizedResource(),
+ source.Count(),
+ sourceDir, destinationDir),
0,
ReturnResult.Failed,
FileOperationType.Move);
}
}
+
+ public static StatusCenterItem PostBanner_Compress(IEnumerable source, IEnumerable destination, ReturnResult returnStatus, bool canceled, int itemsProcessedSuccessfully)
+ {
+ var sourceDir = PathNormalization.GetParentDir(source.FirstOrDefault());
+ var destinationDir = PathNormalization.GetParentDir(destination.FirstOrDefault());
+
+ if (canceled)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CompressCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsProcessedSuccessfully > 1
+ ? "StatusCenter_CompressCancel_SubHeader".GetLocalizedResource()
+ : "StatusCenter_CompressCancel_SubHeader".GetLocalizedResource()
+ : "StatusCenter_CompressCancel_SubHeader".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ destinationDir,
+ itemsProcessedSuccessfully),
+ 0,
+ ReturnResult.Cancelled,
+ FileOperationType.Move);
+ }
+ else if (returnStatus == ReturnResult.InProgress)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CompressInProgress_Header".GetLocalizedResource(),
+ destinationDir,
+ initialProgress: 0,
+ ReturnResult.InProgress,
+ FileOperationType.Compressed,
+ new CancellationTokenSource());
+ }
+ else if (returnStatus == ReturnResult.Success)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CompressSuccessful_Header".GetLocalizedResource(),
+ string.Format(
+ "StatusCenter_CompressSuccessful_SubHeader".GetLocalizedResource(),
+ destinationDir),
+ 0,
+ ReturnResult.Success,
+ FileOperationType.Compressed);
+ }
+ else
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_CompressError_Header".GetLocalizedResource(),
+ string.Format(
+ "StatusCenter_CompressError_SubHeader".GetLocalizedResource(),
+ destinationDir),
+ 0,
+ ReturnResult.Failed,
+ FileOperationType.Compressed
+ );
+ }
+ }
+
+ public static StatusCenterItem PostBanner_Decompress(IEnumerable source, IEnumerable destination, ReturnResult returnStatus, bool canceled, int itemsProcessedSuccessfully)
+ {
+ var sourceDir = PathNormalization.GetParentDir(source.FirstOrDefault());
+ var destinationDir = PathNormalization.GetParentDir(destination.FirstOrDefault());
+
+ if (canceled)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DecompressCancel_Header".GetLocalizedResource(),
+ string.Format(
+ source.Count() > 1
+ ? itemsProcessedSuccessfully > 1
+ ? "StatusCenter_DecompressCancel_SubHeader".GetLocalizedResource()
+ : "StatusCenter_DecompressCancel_SubHeader".GetLocalizedResource()
+ : "StatusCenter_DecompressCancel_SubHeader".GetLocalizedResource(),
+ source.Count(),
+ sourceDir,
+ destinationDir,
+ itemsProcessedSuccessfully),
+ 0,
+ ReturnResult.Cancelled,
+ FileOperationType.Move);
+ }
+ else if (returnStatus == ReturnResult.InProgress)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DecompressInProgress_Header".GetLocalizedResource(),
+ destinationDir,
+ initialProgress: 0,
+ ReturnResult.InProgress,
+ FileOperationType.Compressed,
+ new CancellationTokenSource());
+ }
+ else if (returnStatus == ReturnResult.Success)
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DecompressSuccessful_Header".GetLocalizedResource(),
+ string.Format(
+ "StatusCenter_DecompressSuccessful_SubHeader".GetLocalizedResource(),
+ destinationDir),
+ 0,
+ ReturnResult.Success,
+ FileOperationType.Compressed);
+ }
+ else
+ {
+ return _statusCenterViewModel.AddItem(
+ "StatusCenter_DecompressError_Header".GetLocalizedResource(),
+ string.Format(
+ "StatusCenter_DecompressError_SubHeader".GetLocalizedResource(),
+ destinationDir),
+ 0,
+ ReturnResult.Failed,
+ FileOperationType.Compressed
+ );
+ }
+ }
}
}
diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
index 8bd21ee885a2..03a4f0cad20c 100644
--- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
+++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs
@@ -105,11 +105,6 @@ public string? SpeedText
MaxLimit = 100,
ShowSeparatorLines = false,
- //SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray)
- //{
- // StrokeThickness = 0.5F,
- // PathEffect = new DashEffect(new float[] { 3, 3 })
- //}
}
};
@@ -121,11 +116,6 @@ public string? SpeedText
Labels = new List(),
ShowSeparatorLines = false,
- //SeparatorsPaint = new SolidColorPaint(SKColors.LightSlateGray)
- //{
- // StrokeThickness = 0.5F,
- // PathEffect = new DashEffect(new float[] { 3, 3 })
- //}
}
};
@@ -153,15 +143,18 @@ public bool IsCancelable
public StatusCenterItem(string message, string title, float progress, ReturnResult status, FileOperationType operation, CancellationTokenSource operationCancellationToken = default)
{
- _operationCancellationToken = operationCancellationToken;
- SubHeader = message;
- HeaderBody = title;
Header = title;
+ HeaderBody = title;
+ SubHeader = message;
+
FileSystemOperationReturnResult = status;
Operation = operation;
+
ProgressEventSource = new Progress(ReportProgress);
Progress = new(ProgressEventSource, status: FileSystemStatusCode.InProgress);
+ _operationCancellationToken = operationCancellationToken;
+
CancelCommand = new RelayCommand(ExecuteCancelCommand);
Values = new();
@@ -203,13 +196,14 @@ public StatusCenterItem(string message, string title, float progress, ReturnResu
HeaderBody = Operation switch
{
- FileOperationType.Extract => "ExtractInProgress/Title".GetLocalizedResource(),
- FileOperationType.Copy => "CopyInProgress/Title".GetLocalizedResource(),
- FileOperationType.Move => "MoveInProgress".GetLocalizedResource(),
- FileOperationType.Delete => "DeleteInProgress/Title".GetLocalizedResource(),
- FileOperationType.Recycle => "RecycleInProgress/Title".GetLocalizedResource(),
- FileOperationType.Prepare => "PrepareInProgress".GetLocalizedResource(),
- _ => "PrepareInProgress".GetLocalizedResource(),
+ FileOperationType.Compressed => "StatusCenter_CompressInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Extract => "StatusCenter_DecompressInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Copy => "StatusCenter_CopyInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Move => "StatusCenter_MoveInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Delete => "StatusCenter_DeleteInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Recycle => "StatusCenter_RecycleInProgress_Header".GetLocalizedResource(),
+ FileOperationType.Prepare => "StatusCenter_PrepareInProgress_Header_Plural".GetLocalizedResource(),
+ _ => "StatusCenter_PrepareInProgress_Header_Plural".GetLocalizedResource(),
};
Header = $"{HeaderBody} ({progress}%)";
@@ -217,11 +211,12 @@ public StatusCenterItem(string message, string title, float progress, ReturnResu
ItemIconKind = Operation switch
{
- FileOperationType.Extract => StatusCenterItemIconKind.Extract,
- FileOperationType.Copy => StatusCenterItemIconKind.Copy,
- FileOperationType.Move => StatusCenterItemIconKind.Move,
- FileOperationType.Delete => StatusCenterItemIconKind.Delete,
- FileOperationType.Recycle => StatusCenterItemIconKind.Recycle,
+ FileOperationType.Compressed => StatusCenterItemIconKind.Extract,
+ FileOperationType.Extract => StatusCenterItemIconKind.Extract,
+ FileOperationType.Copy => StatusCenterItemIconKind.Copy,
+ FileOperationType.Move => StatusCenterItemIconKind.Move,
+ FileOperationType.Delete => StatusCenterItemIconKind.Delete,
+ FileOperationType.Recycle => StatusCenterItemIconKind.Recycle,
_ => StatusCenterItemIconKind.Delete,
};
@@ -284,21 +279,24 @@ private void ReportProgress(StatusCenterItemProgressModel value)
// In progress, displaying items count & processed size
case (not 0, not 0):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
- Header = $"{HeaderBody} ({value.ProcessedItemsCount} ({value.ProcessedSize.ToSizeString()}) / {value.ItemsCount} ({value.TotalSize.ToSizeString()}): {ProgressPercentage}%)";
+ Header = $"{HeaderBody} ({ProgressPercentage:0}%)";
+
SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying processed size
case (not 0, _):
ProgressPercentage = (int)(value.ProcessedSize * 100.0 / value.TotalSize);
- Header = $"{HeaderBody} ({value.ProcessedSize.ToSizeString()} / {value.TotalSize.ToSizeString()}: {ProgressPercentage}%)";
+ Header = $"{HeaderBody} ({ProgressPercentage:0}%)";
+
SpeedText = $"{value.ProcessingSizeSpeed.ToSizeString()}/s";
Values.Add(new(value.ProcessedSize * 100.0 / value.TotalSize, value.ProcessingSizeSpeed));
break;
// In progress, displaying items count
case (_, not 0):
ProgressPercentage = (int)(value.ProcessedItemsCount * 100.0 / value.ItemsCount);
- Header = $"{HeaderBody} ({value.ProcessedItemsCount} / {value.ItemsCount}: {ProgressPercentage}%)";
+ Header = $"{HeaderBody} ({ProgressPercentage:0}%)";
+
SpeedText = $"{value.ProcessedItemsCount:0} items/s";
Values.Add(new(value.ProcessedItemsCount * 100.0 / value.ItemsCount, value.ProcessingItemsCountSpeed));
break;
From 80dad8a10df81d03eb3f5ac46e4870707eb221ea Mon Sep 17 00:00:00 2001
From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com>
Date: Mon, 18 Sep 2023 23:39:22 +0900
Subject: [PATCH 18/97] Revert "Update"
This reverts commit b90dd1f440c9af6a26483af26827ef28d928e1c6.
---
.../Decompress/BaseDecompressArchiveAction.cs | 2 +-
.../Archives/Decompress/DecompressArchive.cs | 2 +-
.../Decompress/DecompressArchiveHere.cs | 2 +-
.../DecompressArchiveToChildFolderAction.cs | 2 +-
.../MenuFlyout/ContextFlyoutItemHelper.cs | 2 +-
src/Files.App/Strings/en-US/Resources.resw | 218 +++++-------
.../Utils/Archives/CompressHelper.cs | 211 +++++++++--
.../Utils/Archives/DecompressHelper.cs | 168 ---------
.../Utils/StatusCenter/StatusCenterHelper.cs | 330 +++---------------
.../Utils/StatusCenter/StatusCenterItem.cs | 54 +--
10 files changed, 371 insertions(+), 620 deletions(-)
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
index f7bfd13e9094..f5f47979ab74 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/BaseDecompressArchiveAction.cs
@@ -16,7 +16,7 @@ public virtual HotKey HotKey
public override bool IsExecutable =>
(IsContextPageTypeAdaptedToCommand() &&
- DecompressHelper.CanDecompress(context.SelectedItems) ||
+ CompressHelper.CanDecompress(context.SelectedItems) ||
CanDecompressInsideArchive()) &&
UIHelpers.CanShowDialog;
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
index 089e7aada9f9..c9ed484b265b 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchive.cs
@@ -23,7 +23,7 @@ public DecompressArchive()
public override Task ExecuteAsync()
{
- return DecompressHelper.DecompressArchive(context.ShellPage);
+ return CompressHelper.DecompressArchive(context.ShellPage);
}
protected override bool CanDecompressInsideArchive()
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
index e41c9d6487c9..7e0419bfc613 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveHere.cs
@@ -17,7 +17,7 @@ public DecompressArchiveHere()
public override Task ExecuteAsync()
{
- return DecompressHelper.DecompressArchiveHere(context.ShellPage);
+ return CompressHelper.DecompressArchiveHere(context.ShellPage);
}
}
}
diff --git a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
index dd7359ee9f01..44836ae649d7 100644
--- a/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
+++ b/src/Files.App/Actions/Content/Archives/Decompress/DecompressArchiveToChildFolderAction.cs
@@ -17,7 +17,7 @@ public DecompressArchiveToChildFolderAction()
public override Task ExecuteAsync()
{
- return DecompressHelper.DecompressArchiveToChildFolder(context.ShellPage);
+ return CompressHelper.DecompressArchiveToChildFolder(context.ShellPage);
}
protected override void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
diff --git a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
index 080bcf5227ff..643d3cc54726 100644
--- a/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
+++ b/src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs
@@ -519,7 +519,7 @@ public static List GetBaseItemMenuItems(
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveHere).Build(),
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveToChildFolder).Build(),
},
- ShowItem = DecompressHelper.CanDecompress(selectedItems)
+ ShowItem = CompressHelper.CanDecompress(selectedItems)
},
new ContextMenuFlyoutItemViewModel()
{
diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw
index 5c34cf80041f..e6b9d123db9e 100644
--- a/src/Files.App/Strings/en-US/Resources.resw
+++ b/src/Files.App/Strings/en-US/Resources.resw
@@ -426,11 +426,11 @@
items
-
- Delete in progress
+
+ Deleting files
-
- Recycle in progress
+
+ Moving files to the Recycle Bin
Yes
@@ -1176,22 +1176,22 @@
Item count
-
- Delete error
+
+ Deletion Failed
-
- Delete done successfully
+
+ Deletion complete
-
- Canceled deleting
+
+ Deletion cancelled
-
- Recycle done successfully
+
+ Recycle complete
-
- Move successfully
+
+ Move complete
-
+
Copy complete
@@ -1416,95 +1416,101 @@
Privacy
-
- Canceled move
+
+ Move canceled
-
- Canceled copying
+
+ Copy canceled
-
- Move in progress
+
+ Moving {0} item from {1} to {2} was canceled
-
- Successfully copied {0} items to {1}
+
+ Moving {0} items from {1} to {2} was canceled after moving {3} items
-
- Canceled move
+
+ Moving {0} items from {1} to {2} was canceled after moving {3} item
-
- Canceled move
+
+ Moving {0} item from {1} to {2}
-
- Canceled move
+
+ Moving {0} items from {1} to {2}
-
- Move in progress
+
+ Successfully moved {0} item from {1} to {2}
-
- Move successfully
+
+ Successfully moved {0} items from {1} to {2}
-
- Move successfully
+
+ Failed to move {0} item from {1} to {2}
-
- Move error
+
+ Failed to move {0} items from {1} to {2}
-
- Move error
+
+ Copying {0} item to {1} was canceled
-
- {0} item copied to "{1}"
+
+ Copying {0} items to {1} was canceled after copying {2} items
-
- {0} / {1} items copied to"{2}"
+
+ Copying {0} items to {1} was canceled after copying {2} item
-
+