Skip to content

Commit dfd34b0

Browse files
authored
Feature: Implemented the fundamentals for rich progress (#10814)
1 parent 988749d commit dfd34b0

28 files changed

+572
-415
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[*.cs]
2+
indent_style = tab
3+
indent_size = 4
4+
tab_width = 4

src/BackgroundTasks/UpdateTask.cs

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,51 @@
88

99
namespace BackgroundTasks
1010
{
11-
public sealed class UpdateTask : IBackgroundTask
12-
{
13-
public async void Run(IBackgroundTaskInstance taskInstance)
14-
{
15-
var deferral = taskInstance.GetDeferral();
16-
17-
// Refresh jump list to update string resources
18-
try { await RefreshJumpList(); } catch { }
19-
20-
// Delete previous version log files
21-
try { DeleteLogFiles(); } catch { }
22-
23-
deferral.Complete();
24-
}
25-
26-
private void DeleteLogFiles()
27-
{
28-
File.Delete(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug.log"));
29-
File.Delete(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug_fulltrust.log"));
30-
}
31-
32-
private async Task RefreshJumpList()
33-
{
34-
if (JumpList.IsSupported())
35-
{
36-
var instance = await JumpList.LoadCurrentAsync();
37-
// Disable automatic jumplist. It doesn't work with Files UWP.
38-
instance.SystemGroupKind = JumpListSystemGroupKind.None;
39-
40-
var jumpListItems = instance.Items.ToList();
41-
42-
// Clear all items to avoid localization issues
43-
instance.Items.Clear();
44-
45-
foreach (var temp in jumpListItems)
46-
{
47-
var jumplistItem = JumpListItem.CreateWithArguments(temp.Arguments, temp.DisplayName);
48-
jumplistItem.Description = jumplistItem.Arguments;
49-
jumplistItem.GroupName = "ms-resource:///Resources/JumpListRecentGroupHeader";
50-
jumplistItem.Logo = new Uri("ms-appx:///Assets/FolderIcon.png");
51-
instance.Items.Add(jumplistItem);
52-
}
53-
54-
await instance.SaveAsync();
55-
}
56-
}
57-
}
11+
public sealed class UpdateTask : IBackgroundTask
12+
{
13+
public async void Run(IBackgroundTaskInstance taskInstance)
14+
{
15+
var deferral = taskInstance.GetDeferral();
16+
17+
// Refresh jump list to update string resources
18+
try { await RefreshJumpList(); } catch { }
19+
20+
// Delete previous version log files
21+
try { DeleteLogFiles(); } catch { }
22+
23+
deferral.Complete();
24+
}
25+
26+
private void DeleteLogFiles()
27+
{
28+
File.Delete(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug.log"));
29+
File.Delete(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug_fulltrust.log"));
30+
}
31+
32+
private async Task RefreshJumpList()
33+
{
34+
if (JumpList.IsSupported())
35+
{
36+
var instance = await JumpList.LoadCurrentAsync();
37+
// Disable automatic jumplist. It doesn't work with Files UWP.
38+
instance.SystemGroupKind = JumpListSystemGroupKind.None;
39+
40+
var jumpListItems = instance.Items.ToList();
41+
42+
// Clear all items to avoid localization issues
43+
instance.Items.Clear();
44+
45+
foreach (var temp in jumpListItems)
46+
{
47+
var jumplistItem = JumpListItem.CreateWithArguments(temp.Arguments, temp.DisplayName);
48+
jumplistItem.Description = jumplistItem.Arguments;
49+
jumplistItem.GroupName = "ms-resource:///Resources/JumpListRecentGroupHeader";
50+
jumplistItem.Logo = new Uri("ms-appx:///Assets/FolderIcon.png");
51+
instance.Items.Add(jumplistItem);
52+
}
53+
54+
await instance.SaveAsync();
55+
}
56+
}
57+
}
5858
}

src/Files.App.Storage/WindowsStorage/WindowsStorageFolder.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,18 @@ private static Windows.Storage.NameCollisionOption GetWindowsNameCollisionOption
149149
};
150150
}
151151

152-
private static Windows.Storage.CreationCollisionOption GetWindowsCreationCollisionOption(
153-
CreationCollisionOption options)
154-
{
155-
return options switch
156-
{
157-
CreationCollisionOption.GenerateUniqueName => Windows.Storage.CreationCollisionOption.GenerateUniqueName,
158-
CreationCollisionOption.ReplaceExisting => Windows.Storage.CreationCollisionOption.ReplaceExisting,
159-
CreationCollisionOption.OpenIfExists => Windows.Storage.CreationCollisionOption.OpenIfExists,
160-
CreationCollisionOption.FailIfExists => Windows.Storage.CreationCollisionOption.FailIfExists,
161-
_ => throw new ArgumentOutOfRangeException(nameof(options))
162-
};
163-
}
152+
private static Windows.Storage.CreationCollisionOption GetWindowsCreationCollisionOption(
153+
CreationCollisionOption options)
154+
{
155+
return options switch
156+
{
157+
CreationCollisionOption.GenerateUniqueName => Windows.Storage.CreationCollisionOption.GenerateUniqueName,
158+
CreationCollisionOption.ReplaceExisting => Windows.Storage.CreationCollisionOption.ReplaceExisting,
159+
CreationCollisionOption.OpenIfExists => Windows.Storage.CreationCollisionOption.OpenIfExists,
160+
CreationCollisionOption.FailIfExists => Windows.Storage.CreationCollisionOption.FailIfExists,
161+
_ => throw new ArgumentOutOfRangeException(nameof(options))
162+
};
163+
}
164164

165165
/// <inheritdoc/>
166166
public override async Task<ILocatableFolder?> GetParentAsync(CancellationToken cancellationToken = default)

src/Files.App/App.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ public static void SaveSessionTabs() // Enumerates through all tabs and gets the
319319
{
320320
IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
321321
IBundlesSettingsService bundlesSettingsService = Ioc.Default.GetRequiredService<IBundlesSettingsService>();
322-
322+
323323
bundlesSettingsService.FlushSettings();
324324

325325
userSettingsService.PreferencesSettingsService.LastSessionTabList = MainPageViewModel.AppInstances.DefaultIfEmpty().Select(tab =>

src/Files.App/DataModels/NavigationControlItems/DriveItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public float PercentageUsed
120120
get => percentageUsed;
121121
set
122122
{
123-
if (!SetProperty(ref percentageUsed, value))
123+
if (!SetProperty(ref percentageUsed, value))
124124
return;
125125

126126
if (Type == DriveType.Fixed)

src/Files.App/Filesystem/Archive/ArchiveCreator.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ public class ArchiveCreator : IArchiveCreator
2424
public ArchiveCompressionLevels CompressionLevel { get; init; } = ArchiveCompressionLevels.Normal;
2525
public ArchiveSplittingSizes SplittingSize { get; init; } = ArchiveSplittingSizes.None;
2626

27-
public IProgress<float> Progress { get; set; } = new Progress<float>();
27+
public IProgress<FileSystemProgress> Progress { get; set; } = new Progress<FileSystemProgress>();
28+
private readonly FileSystemProgress fsProgress;
29+
30+
public ArchiveCreator()
31+
{
32+
fsProgress = new(Progress, true, Shared.Enums.FileSystemStatusCode.InProgress);
33+
fsProgress.Report();
34+
}
2835

2936
private string ArchiveExtension => FileFormat switch
3037
{
@@ -90,6 +97,7 @@ public async Task<bool> RunCreationAsync()
9097
EventSynchronization = EventSynchronizationStrategy.AlwaysAsynchronous,
9198
};
9299
compressor.Compressing += Compressor_Compressing;
100+
compressor.CompressionFinished += Compressor_CompressionFinished;
93101

94102
try
95103
{
@@ -121,6 +129,16 @@ public async Task<bool> RunCreationAsync()
121129
}
122130
}
123131

124-
private void Compressor_Compressing(object? _, ProgressEventArgs e) => Progress.Report(e.PercentDone);
132+
private void Compressor_CompressionFinished(object? sender, EventArgs e)
133+
{
134+
fsProgress.Percentage = null;
135+
fsProgress.ReportStatus(Shared.Enums.FileSystemStatusCode.Success);
136+
}
137+
138+
private void Compressor_Compressing(object? _, ProgressEventArgs e)
139+
{
140+
fsProgress.Percentage = e.PercentDone;
141+
fsProgress.Report();
142+
}
125143
}
126144
}

src/Files.App/Filesystem/Archive/IArchiveCreator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface IArchiveCreator
1818
ArchiveCompressionLevels CompressionLevel { get; }
1919
ArchiveSplittingSizes SplittingSize { get; }
2020

21-
IProgress<float> Progress { get; set; }
21+
IProgress<FileSystemProgress> Progress { get; set; }
2222

2323
Task<bool> RunCreationAsync();
2424
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Files.App.Helpers;
2+
using Files.Shared.Enums;
3+
using System;
4+
5+
namespace Files.App.Filesystem
6+
{
7+
public class FileSystemProgress
8+
{
9+
private readonly IProgress<FileSystemProgress>? progress;
10+
private readonly IntervalSampler sampler;
11+
private FileSystemStatusCode? status;
12+
private bool criticalReport;
13+
private bool enumerationCompleted;
14+
15+
public FileSystemStatusCode? Status
16+
{
17+
get => status;
18+
set
19+
{
20+
if (status != value)
21+
{
22+
criticalReport = true;
23+
}
24+
status = value;
25+
}
26+
}
27+
public string? FileName { get; set; }
28+
public long TotalSize { get; set; }
29+
public long ProcessedSize { get; set; }
30+
public long ItemsCount { get; set; }
31+
public long ProcessedItemsCount { get; set; }
32+
public DateTimeOffset StartTime { get; }
33+
public DateTimeOffset CompletedTime { get; private set; }
34+
public bool EnumerationCompleted
35+
{
36+
get => enumerationCompleted;
37+
set
38+
{
39+
if (enumerationCompleted != value)
40+
{
41+
criticalReport = true;
42+
}
43+
enumerationCompleted = value;
44+
}
45+
}
46+
/// <summary>
47+
/// Only used when detailed count isn't available.
48+
/// </summary>
49+
public float? Percentage { get; set; }
50+
51+
public FileSystemProgress(
52+
IProgress<FileSystemProgress>? progress,
53+
bool enumerationCompleted = false,
54+
FileSystemStatusCode? status = null,
55+
long itemsCount = 0,
56+
long totalSize = 0,
57+
int samplerInterval = 100)
58+
{
59+
this.StartTime = DateTimeOffset.Now;
60+
this.progress = progress;
61+
this.sampler = new(samplerInterval);
62+
this.EnumerationCompleted = enumerationCompleted;
63+
this.Status = status;
64+
this.ItemsCount = itemsCount;
65+
this.TotalSize = totalSize;
66+
}
67+
68+
public void Report(float? percentage = null)
69+
{
70+
Percentage = percentage;
71+
if (((EnumerationCompleted && (ProcessedItemsCount == ItemsCount || ProcessedSize == TotalSize)) ||
72+
(percentage is float f && MathF.Abs(f - 100f) <= float.Epsilon)) &&
73+
status is FileSystemStatusCode.InProgress or null)
74+
{
75+
status = FileSystemStatusCode.Success;
76+
CompletedTime = DateTimeOffset.Now;
77+
}
78+
79+
if (status is FileSystemStatusCode.Success)
80+
CompletedTime = DateTimeOffset.Now;
81+
82+
if (progress is not null && (criticalReport || sampler.CheckNow()))
83+
{
84+
progress.Report(this);
85+
criticalReport = false;
86+
}
87+
}
88+
89+
public void ReportStatus(FileSystemStatusCode status)
90+
{
91+
Status = status;
92+
Report();
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)