From cd1751be06acfe6410f482a7d5cecc884ef798e4 Mon Sep 17 00:00:00 2001 From: Saravanan Ganapathi Date: Mon, 29 Sep 2025 16:21:58 +0530 Subject: [PATCH 1/2] Feature: Implement real-time discovery progress for Status Center operations --- src/Files.App/Strings/en-US/Resources.resw | 15 ++++++ .../Utils/StatusCenter/StatusCenterHelper.cs | 46 ++++++++++++++----- .../Utils/StatusCenter/StatusCenterItem.cs | 18 ++++++-- .../Operations/FileOperationsHelpers.cs | 24 ++++++++++ .../Storage/Operations/FileSizeCalculator.cs | 5 ++ .../Operations/ShellFilesystemOperations.cs | 2 +- 6 files changed, 93 insertions(+), 17 deletions(-) diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw index 266665c3a502..0612d6a14ba4 100644 --- a/src/Files.App/Strings/en-US/Resources.resw +++ b/src/Files.App/Strings/en-US/Resources.resw @@ -3487,6 +3487,9 @@ Processing items... + + Discovery in progress... + Speed: @@ -3618,6 +3621,10 @@ Copying {0, plural, one {# item} other {# items}} from "{1}" to "{2}" Shown in a StatusCenter card. + + Discovered {0, plural, one {# item} other {# items}} + Shown in a StatusCenter card during file discovery phase. + Canceled extracting "{0}" to "{1}" Shown in a StatusCenter card. @@ -3670,6 +3677,10 @@ Deleting {0, plural, one {# item} other {# items}} from "{1}" Shown in a StatusCenter card. + + Discovered {0, plural, one {# item} other {# items}} + Shown in a StatusCenter card during file discovery phase. + Canceled moving {0, plural, one {# item} other {# items}} to "{1}" Shown in a StatusCenter card. @@ -3694,6 +3705,10 @@ Moving {0, plural, one {# item} other {# items}} from "{1}" to "{2}" Shown in a StatusCenter card. + + Discovered {0, plural, one {# item} other {# items}} + Shown in a StatusCenter card during file discovery phase. + Error moving {0, plural, one {# item} other {# items}} to "{1}" Shown in a StatusCenter card. diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs index 8669ba974e38..5ddbd63d7894 100644 --- a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs +++ b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs @@ -611,7 +611,7 @@ public static StatusCenterItem AddCard_Prepare() false); } - public static void UpdateCardStrings(StatusCenterItem card) + public static void UpdateCardStrings(StatusCenterItem card, StatusCenterItemProgressModel? progressValue = null) { // Aren't used for now string sourcePath = string.Empty; @@ -645,20 +645,36 @@ public static void UpdateCardStrings(StatusCenterItem card) { case FileOperationType.Copy: { - string headerString = string.IsNullOrWhiteSpace(card.HeaderStringResource) ? string.Empty - : card.HeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, destinationDirName); - card.Header = headerString; + string headerResource = card.HeaderStringResource; + + if (card.IsDiscovering && card.TotalItemsCount > 0 && card.IsInProgress) + headerResource = "StatusCenter_CopyDiscovery_Header"; + + if (string.IsNullOrWhiteSpace(headerResource)) + card.Header = string.Empty; + else if (headerResource == "StatusCenter_CopyDiscovery_Header") + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount); + else + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount, destinationDirName); string subHeaderString = string.IsNullOrWhiteSpace(card.SubHeaderStringResource) ? string.Empty : card.SubHeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, sourcePath, destinationPath); - card.SubHeader = subHeaderString; + card.SubHeader = subHeaderString; break; } case FileOperationType.Move: { - string headerString = string.IsNullOrWhiteSpace(card.HeaderStringResource) ? string.Empty - : card.HeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, destinationDirName); - card.Header = headerString; + string headerResource = card.HeaderStringResource; + + if (card.IsDiscovering && card.TotalItemsCount > 0 && card.IsInProgress) + headerResource = "StatusCenter_MoveDiscovery_Header"; + + if (string.IsNullOrWhiteSpace(headerResource)) + card.Header = string.Empty; + else if (headerResource == "StatusCenter_MoveDiscovery_Header") + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount); + else + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount, destinationDirName); string subHeaderString = string.IsNullOrWhiteSpace(card.SubHeaderStringResource) ? string.Empty : card.SubHeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, sourcePath, destinationPath); @@ -667,9 +683,17 @@ public static void UpdateCardStrings(StatusCenterItem card) } case FileOperationType.Delete: { - string headerString = string.IsNullOrWhiteSpace(card.HeaderStringResource) ? string.Empty - : card.HeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, sourceDirName); - card.Header = headerString; + string headerResource = card.HeaderStringResource; + + if (card.IsDiscovering && card.TotalItemsCount > 0 && card.IsInProgress) + headerResource = "StatusCenter_DeleteDiscovery_Header"; + + if (string.IsNullOrWhiteSpace(headerResource)) + card.Header = string.Empty; + else if (headerResource == "StatusCenter_DeleteDiscovery_Header") + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount); + else + card.Header = headerResource.GetLocalizedFormatResource(card.TotalItemsCount, sourceDirName); string subHeaderString = string.IsNullOrWhiteSpace(card.SubHeaderStringResource) ? string.Empty : card.SubHeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, sourcePath); diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs index f715fd7e94a4..cc86f8bf3083 100644 --- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs +++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs @@ -147,6 +147,8 @@ public StatusCenterItemProgressModel Progress public bool IsInProgress { get; private set; } + public bool IsDiscovering { get; private set; } = true; + public IEnumerable? Source { get; private set; } public IEnumerable? Destination { get; private set; } @@ -199,7 +201,7 @@ public StatusCenterItem( AnimatedIconState = "NormalOff"; SpeedGraphValues = []; CancelCommand = new RelayCommand(ExecuteCancelCommand); - Message = Strings.ProcessingItems.GetLocalizedResource(); + Message = Strings.DiscoveringItems.GetLocalizedResource(); Source = source; Destination = destination; @@ -299,7 +301,7 @@ private void ReportProgress(StatusCenterItemProgressModel value) Operation == FileOperationType.Compressed || Operation == FileOperationType.GitClone) { - Message = + Message = $"{string.Format( Strings.StatusCenter_ProcessedItems_Header.GetLocalizedFormatResource(value.ProcessedItemsCount, value.ItemsCount), value.ProcessedItemsCount, @@ -307,7 +309,7 @@ private void ReportProgress(StatusCenterItemProgressModel value) } else { - Message = + Message = $"{string.Format( Strings.StatusCenter_ProcessedSize_Header.GetLocalizedResource(), value.ProcessedSize.ToSizeString(), @@ -327,8 +329,14 @@ private void ReportProgress(StatusCenterItemProgressModel value) if (TotalSize < value.TotalSize) TotalSize = value.TotalSize; + if (value.EnumerationCompleted && IsDiscovering) + { + IsDiscovering = false; + Message = Strings.ProcessingItems.GetLocalizedResource(); + } + // Update UI for strings - StatusCenterHelper.UpdateCardStrings(this); + StatusCenterHelper.UpdateCardStrings(this, value); OnPropertyChanged(nameof(HeaderTooltip)); // Graph item point @@ -382,7 +390,7 @@ private void ReportProgress(StatusCenterItemProgressModel value) SpeedGraphValues?.Add(point); // Add percentage to the header - if (!IsIndeterminateProgress) + if (!IsIndeterminateProgress && value.EnumerationCompleted) Header = $"{Header} ({ProgressPercentage}%)"; // Update UI of the address bar diff --git a/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs index 870a8d2563ad..cd1fd047ff2e 100644 --- a/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs +++ b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs @@ -207,6 +207,14 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera var cts = new CancellationTokenSource(); var sizeCalculator = new FileSizeCalculator(fileToDeletePath); + + // Track the count and update the progress + sizeCalculator.ItemsCountChanged += (newCount) => + { + fsProgress.ItemsCount = newCount; + fsProgress.Report(); + }; + var sizeTask = sizeCalculator.ComputeSizeAsync(cts.Token); sizeTask.ContinueWith(_ => { @@ -405,6 +413,14 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera var cts = new CancellationTokenSource(); var sizeCalculator = new FileSizeCalculator(fileToMovePath); + + // Track the count and update the progress + sizeCalculator.ItemsCountChanged += (newCount) => + { + fsProgress.ItemsCount = newCount; + fsProgress.Report(); + }; + var sizeTask = sizeCalculator.ComputeSizeAsync(cts.Token); sizeTask.ContinueWith(_ => { @@ -533,6 +549,14 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera var cts = new CancellationTokenSource(); var sizeCalculator = new FileSizeCalculator(fileToCopyPath); + + // Track the count and update the progress + sizeCalculator.ItemsCountChanged += (newCount) => + { + fsProgress.ItemsCount = newCount; + fsProgress.Report(); + }; + var sizeTask = sizeCalculator.ComputeSizeAsync(cts.Token); sizeTask.ContinueWith(_ => { diff --git a/src/Files.App/Utils/Storage/Operations/FileSizeCalculator.cs b/src/Files.App/Utils/Storage/Operations/FileSizeCalculator.cs index 3e60af00da9b..a260e315ebfb 100644 --- a/src/Files.App/Utils/Storage/Operations/FileSizeCalculator.cs +++ b/src/Files.App/Utils/Storage/Operations/FileSizeCalculator.cs @@ -18,6 +18,8 @@ internal sealed class FileSizeCalculator public int ItemsCount => _computedFiles.Count; public bool Completed { get; private set; } + public event Action? ItemsCountChanged; + public FileSizeCalculator(params string[] paths) { _paths = paths; @@ -118,7 +120,10 @@ private long ComputeFileSize(string path) null); if (!hFile.IsInvalid && PInvoke.GetFileSizeEx(hFile, out size) && _computedFiles.TryAdd(path, size)) + { Interlocked.Add(ref _size, size); + ItemsCountChanged?.Invoke(ItemsCount); + } return size; } diff --git a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs index e512d9c39978..1db895210523 100644 --- a/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs +++ b/src/Files.App/Utils/Storage/Operations/ShellFilesystemOperations.cs @@ -49,7 +49,7 @@ public async Task CopyItemsAsync(IList so StatusCenterItemProgressModel fsProgress = new( progress, - true, + false, FileSystemStatusCode.InProgress, source.Count); From 0b65b3365cdec05f9f323af2a3c7f348b4172db8 Mon Sep 17 00:00:00 2001 From: Yair <39923744+yaira2@users.noreply.github.com> Date: Mon, 29 Sep 2025 10:55:35 -0400 Subject: [PATCH 2/2] Fixed spacing --- src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs | 2 +- src/Files.App/Utils/StatusCenter/StatusCenterItem.cs | 4 ++-- .../Utils/Storage/Operations/FileOperationsHelpers.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs index 5ddbd63d7894..5bf5dc8c7182 100644 --- a/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs +++ b/src/Files.App/Utils/StatusCenter/StatusCenterHelper.cs @@ -659,7 +659,7 @@ public static void UpdateCardStrings(StatusCenterItem card, StatusCenterItemProg string subHeaderString = string.IsNullOrWhiteSpace(card.SubHeaderStringResource) ? string.Empty : card.SubHeaderStringResource.GetLocalizedFormatResource(card.TotalItemsCount, sourcePath, destinationPath); - card.SubHeader = subHeaderString; + card.SubHeader = subHeaderString; break; } case FileOperationType.Move: diff --git a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs index cc86f8bf3083..dbd1b0b6b472 100644 --- a/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs +++ b/src/Files.App/Utils/StatusCenter/StatusCenterItem.cs @@ -301,7 +301,7 @@ private void ReportProgress(StatusCenterItemProgressModel value) Operation == FileOperationType.Compressed || Operation == FileOperationType.GitClone) { - Message = + Message = $"{string.Format( Strings.StatusCenter_ProcessedItems_Header.GetLocalizedFormatResource(value.ProcessedItemsCount, value.ItemsCount), value.ProcessedItemsCount, @@ -309,7 +309,7 @@ private void ReportProgress(StatusCenterItemProgressModel value) } else { - Message = + Message = $"{string.Format( Strings.StatusCenter_ProcessedSize_Header.GetLocalizedResource(), value.ProcessedSize.ToSizeString(), diff --git a/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs index cd1fd047ff2e..b6e109e0fc64 100644 --- a/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs +++ b/src/Files.App/Utils/Storage/Operations/FileOperationsHelpers.cs @@ -207,7 +207,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera var cts = new CancellationTokenSource(); var sizeCalculator = new FileSizeCalculator(fileToDeletePath); - + // Track the count and update the progress sizeCalculator.ItemsCountChanged += (newCount) => { @@ -413,7 +413,7 @@ public static Task SetClipboard(string[] filesToCopy, DataPackageOperation opera var cts = new CancellationTokenSource(); var sizeCalculator = new FileSizeCalculator(fileToMovePath); - + // Track the count and update the progress sizeCalculator.ItemsCountChanged += (newCount) => {