Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Fixed issue where progress was not updated when creating an archive #11811

Merged
merged 9 commits into from
Apr 2, 2023
66 changes: 48 additions & 18 deletions src/Files.App/Filesystem/Archive/ArchiveCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@ namespace Files.App.Filesystem.Archive
{
public class ArchiveCreator : IArchiveCreator
{
// Represents the total number of items to be processed.
// It is used to calculate a weighted progress with this formula:
// Progress = [OldProgress + (ProgressDelta / ItemsAmount)]
private int itemsAmount = 1;
ferrariofilippo marked this conversation as resolved.
Show resolved Hide resolved
private int processedItems = 0;

private string archivePath = string.Empty;
public string ArchivePath => archivePath;
public string ArchivePath
{
get => archivePath;
set => archivePath = value;
}

public string Directory { get; init; } = string.Empty;
public string FileName { get; init; } = string.Empty;
Expand All @@ -24,13 +34,24 @@ public class ArchiveCreator : IArchiveCreator
public ArchiveCompressionLevels CompressionLevel { get; init; } = ArchiveCompressionLevels.Normal;
public ArchiveSplittingSizes SplittingSize { get; init; } = ArchiveSplittingSizes.None;

public IProgress<FileSystemProgress> Progress { get; set; } = new Progress<FileSystemProgress>();
private readonly FileSystemProgress fsProgress;
private IProgress<FileSystemProgress> progress = new Progress<FileSystemProgress>();
public IProgress<FileSystemProgress> Progress
{
get => progress;
set
{
progress = value;
fsProgress = new(Progress, true, Shared.Enums.FileSystemStatusCode.InProgress);
fsProgress.Report(0);
}
}

private FileSystemProgress fsProgress;

public ArchiveCreator()
{
fsProgress = new(Progress, true, Shared.Enums.FileSystemStatusCode.InProgress);
fsProgress.Report();
fsProgress.Report(0);
}

private string ArchiveExtension => FileFormat switch
Expand Down Expand Up @@ -75,16 +96,15 @@ public ArchiveCreator()
_ => throw new ArgumentOutOfRangeException(nameof(SplittingSize)),
};

public string GetArchivePath(string suffix = "")
{
return Path.Combine(Directory, $"{FileName}{suffix}{ArchiveExtension}");
}

public async Task<bool> RunCreationAsync()
{
var path = Path.Combine(Directory, FileName + ArchiveExtension);
string[] sources = Sources.ToArray();

int index = 1;
while (File.Exists(path) || System.IO.Directory.Exists(path))
path = Path.Combine(Directory, $"{FileName} ({++index}){ArchiveExtension}");
archivePath = path;

var compressor = new SevenZipCompressor
{
ArchiveFormat = SevenZipArchiveFormat,
Expand All @@ -104,41 +124,51 @@ public async Task<bool> RunCreationAsync()
var files = sources.Where(source => File.Exists(source)).ToArray();
var directories = sources.Where(source => System.IO.Directory.Exists(source));

itemsAmount = files.Length + directories.Count();

foreach (string directory in directories)
{
await compressor.CompressDirectoryAsync(directory, path, Password);
await compressor.CompressDirectoryAsync(directory, archivePath, Password);
compressor.CompressionMode = CompressionMode.Append;
}

if (files.Any())
{
if (string.IsNullOrEmpty(Password))
await compressor.CompressFilesAsync(path, files);
await compressor.CompressFilesAsync(archivePath, files);
else
await compressor.CompressFilesEncryptedAsync(path, Password, files);
await compressor.CompressFilesEncryptedAsync(archivePath, Password, files);
}

return true;
}
catch (Exception ex)
{
var logger = Ioc.Default.GetService<ILogger>();
logger?.Warn(ex, $"Error compressing folder: {path}");
logger?.Warn(ex, $"Error compressing folder: {archivePath}");

return false;
}
}

private void Compressor_CompressionFinished(object? sender, EventArgs e)
{
fsProgress.Percentage = null;
fsProgress.ReportStatus(Shared.Enums.FileSystemStatusCode.Success);
if (++processedItems == itemsAmount)
{
fsProgress.Percentage = null;
fsProgress.ReportStatus(Shared.Enums.FileSystemStatusCode.Success);
}
else
{
fsProgress.Percentage = processedItems * 100 / itemsAmount;
fsProgress.Report(fsProgress.Percentage);
}
}

private void Compressor_Compressing(object? _, ProgressEventArgs e)
{
fsProgress.Percentage = e.PercentDone;
fsProgress.Report();
fsProgress.Percentage += e.PercentDelta / itemsAmount;
fsProgress.Report(fsProgress.Percentage);
}
}
}
4 changes: 3 additions & 1 deletion src/Files.App/Filesystem/Archive/IArchiveCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Files.App.Filesystem.Archive
{
public interface IArchiveCreator
{
string ArchivePath { get; }
string ArchivePath { get; set; }

string Directory { get; }
string FileName { get; }
Expand All @@ -20,6 +20,8 @@ public interface IArchiveCreator

IProgress<FileSystemProgress> Progress { get; set; }

string GetArchivePath(string suffix = "");

Task<bool> RunCreationAsync();
}
}
7 changes: 6 additions & 1 deletion src/Files.App/Helpers/ArchiveHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ public static (string[] Sources, string directory, string fileName) GetCompressD

public static async Task CompressArchiveAsync(IArchiveCreator creator)
{
var archivePath = creator.ArchivePath;
var archivePath = creator.GetArchivePath();

int index = 1;
while (File.Exists(archivePath) || System.IO.Directory.Exists(archivePath))
archivePath = creator.GetArchivePath($" ({++index})");
creator.ArchivePath = archivePath;

CancellationTokenSource compressionToken = new();
PostedStatusBanner banner = App.OngoingTasksViewModel.PostOperationBanner
Expand Down