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

Code Quality: Introduced IStorageArchiveService #15341

Merged
merged 9 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ namespace Files.App.Actions
internal abstract class BaseCompressArchiveAction : BaseUIAction, IAction
{
protected readonly IContentPageContext context;
protected IStorageArchiveService StorageArchiveService { get; } = Ioc.Default.GetRequiredService<IStorageArchiveService>();

public abstract string Label { get; }

public abstract string Description { get; }

public override bool IsExecutable =>
IsContextPageTypeAdaptedToCommand() &&
CompressHelper.CanCompress(context.SelectedItems) &&
StorageArchiveService.CanCompress(context.SelectedItems) &&
UIHelpers.CanShowDialog;

public BaseCompressArchiveAction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,22 @@ public override async Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
string[] sources = context.SelectedItems.Select(item => item.ItemPath).ToArray();
string directory = string.Empty;
string fileName = string.Empty;

if (sources.Length is not 0)
{
// Get the current directory path
directory = context.ShellPage.FilesystemViewModel.WorkingDirectory.Normalize();

// Get the library save folder if the folder is library item
if (App.LibraryManager.TryGetLibrary(directory, out var library) && !library.IsEmpty)
directory = library.DefaultSaveFolder;

// Gets the file name from the directory path
fileName = SystemIO.Path.GetFileName(sources.Length is 1 ? sources[0] : directory);
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
}

var dialog = new CreateArchiveDialog
{
Expand All @@ -48,7 +63,7 @@ public override async Task ExecuteAsync(object? parameter = null)
dialog.CompressionLevel,
dialog.SplittingSize);

await CompressHelper.CompressArchiveAsync(creator);
await StorageArchiveService.CompressAsync(creator);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Files.App.Actions
internal sealed class CompressIntoSevenZipAction : BaseCompressArchiveAction
{
public override string Label
=> string.Format("CreateNamedArchive".GetLocalizedResource(), $"{CompressHelper.DetermineArchiveNameFromSelection(context.SelectedItems)}.7z");
=> string.Format("CreateNamedArchive".GetLocalizedResource(), $"{StorageArchiveService.GenerateArchiveNameFromItems(context.SelectedItems)}.7z");

public override string Description
=> "CompressIntoSevenZipDescription".GetLocalizedResource();
Expand All @@ -20,15 +20,30 @@ public override Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return Task.CompletedTask;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
string[] sources = context.SelectedItems.Select(item => item.ItemPath).ToArray();
string directory = string.Empty;
string fileName = string.Empty;

if (sources.Length is not 0)
{
// Get the current directory path
directory = context.ShellPage.FilesystemViewModel.WorkingDirectory.Normalize();

// Get the library save folder if the folder is library item
if (App.LibraryManager.TryGetLibrary(directory, out var library) && !library.IsEmpty)
directory = library.DefaultSaveFolder;

// Gets the file name from the directory path
fileName = SystemIO.Path.GetFileName(sources.Length is 1 ? sources[0] : directory);
}

ICompressArchiveModel creator = new CompressArchiveModel(
sources,
directory,
fileName,
fileFormat: ArchiveFormats.SevenZip);

return CompressHelper.CompressArchiveAsync(creator);
return StorageArchiveService.CompressAsync(creator);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Files.App.Actions
internal sealed class CompressIntoZipAction : BaseCompressArchiveAction
{
public override string Label
=> string.Format("CreateNamedArchive".GetLocalizedResource(), $"{CompressHelper.DetermineArchiveNameFromSelection(context.SelectedItems)}.zip");
=> string.Format("CreateNamedArchive".GetLocalizedResource(), $"{StorageArchiveService.GenerateArchiveNameFromItems(context.SelectedItems)}.zip");

public override string Description
=> "CompressIntoZipDescription".GetLocalizedResource();
Expand All @@ -20,15 +20,30 @@ public override Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return Task.CompletedTask;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
string[] sources = context.SelectedItems.Select(item => item.ItemPath).ToArray();
string directory = string.Empty;
string fileName = string.Empty;

if (sources.Length is not 0)
{
// Get the current directory path
directory = context.ShellPage.FilesystemViewModel.WorkingDirectory.Normalize();

// Get the library save folder if the folder is library item
if (App.LibraryManager.TryGetLibrary(directory, out var library) && !library.IsEmpty)
directory = library.DefaultSaveFolder;

// Gets the file name from the directory path
fileName = SystemIO.Path.GetFileName(sources.Length is 1 ? sources[0] : directory);
}

ICompressArchiveModel creator = new CompressArchiveModel(
sources,
directory,
fileName,
fileFormat: ArchiveFormats.Zip);

return CompressHelper.CompressArchiveAsync(creator);
return StorageArchiveService.CompressAsync(creator);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.Dialogs;
using Microsoft.UI.Xaml.Controls;
using SevenZip;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Windows.Foundation.Metadata;
using Windows.Storage;

namespace Files.App.Actions
{
internal abstract class BaseDecompressArchiveAction : BaseUIAction, IAction
{
protected readonly IContentPageContext context;
protected IStorageArchiveService StorageArchiveService { get; } = Ioc.Default.GetRequiredService<IStorageArchiveService>();

public abstract string Label { get; }

Expand All @@ -16,7 +25,7 @@ public virtual HotKey HotKey

public override bool IsExecutable =>
(IsContextPageTypeAdaptedToCommand() &&
CompressHelper.CanDecompress(context.SelectedItems) ||
StorageArchiveService.CanDecompress(context.SelectedItems) ||
CanDecompressInsideArchive()) &&
UIHelpers.CanShowDialog;

Expand All @@ -37,6 +46,80 @@ protected bool IsContextPageTypeAdaptedToCommand()
context.PageType != ContentPageTypes.None;
}

protected async Task DecompressArchiveHereAsync(bool smart = false)
{
if (context.SelectedItems.Count is 0)
return;

foreach (var selectedItem in context.SelectedItems)
{
var password = string.Empty;
BaseStorageFile archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(selectedItem.ItemPath);
BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem<BaseStorageFolder>(context.ShellPage?.FilesystemViewModel.CurrentFolder?.ItemPath ?? string.Empty);

if (archive?.Path is null)
return;

if (await FilesystemTasks.Wrap(() => StorageArchiveService.IsEncryptedAsync(archive.Path)))
{
DecompressArchiveDialog decompressArchiveDialog = new();
DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
{
IsArchiveEncrypted = true,
ShowPathSelection = false
};

decompressArchiveDialog.ViewModel = decompressArchiveViewModel;

if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
decompressArchiveDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;

ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
if (option != ContentDialogResult.Primary)
return;

if (decompressArchiveViewModel.Password is not null)
password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
}

BaseStorageFolder? destinationFolder = null;

var isMultipleItems = await FilesystemTasks.Wrap(async () =>
{
using SevenZipExtractor? zipFile = await StorageArchiveService.GetSevenZipExtractorAsync(archive.Path);
if (zipFile is null)
return true;

return zipFile.ArchiveFileData.Select(file =>
{
var pathCharIndex = file.FileName.IndexOfAny(['/', '\\']);
if (pathCharIndex == -1)
return file.FileName;
else
return file.FileName.Substring(0, pathCharIndex);
})
.Distinct().Count() > 1;
});

if (smart && currentFolder is not null && isMultipleItems)
{
destinationFolder =
await FilesystemTasks.Wrap(() =>
currentFolder.CreateFolderAsync(
SystemIO.Path.GetFileNameWithoutExtension(archive.Path),
CreationCollisionOption.GenerateUniqueName).AsTask());
}
else
{
destinationFolder = currentFolder;
}

// Operate decompress
var result = await FilesystemTasks.Wrap(() =>
StorageArchiveService.DecompressAsync(selectedItem.ItemPath, destinationFolder?.Path ?? string.Empty, password));
}
}

protected virtual bool CanDecompressInsideArchive()
{
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.Dialogs;
using Files.Shared.Helpers;
using Microsoft.UI.Xaml.Controls;
using System.IO;
using System.Text;
using Windows.Foundation.Metadata;
using Windows.Storage;

namespace Files.App.Actions
{
Expand All @@ -21,12 +26,56 @@ public DecompressArchive()
{
}

public override Task ExecuteAsync(object? parameter = null)
public override async Task ExecuteAsync(object? parameter = null)
{
if (context.ShellPage is null)
return Task.CompletedTask;
return;

return DecompressHelper.DecompressArchiveAsync(context.ShellPage);
BaseStorageFile archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(context.SelectedItem?.ItemPath ?? string.Empty);

if (archive?.Path is null)
return;

var isArchiveEncrypted = await FilesystemTasks.Wrap(() => StorageArchiveService.IsEncryptedAsync(archive.Path));
var password = string.Empty;

DecompressArchiveDialog decompressArchiveDialog = new();
DecompressArchiveDialogViewModel decompressArchiveViewModel = new(archive)
{
IsArchiveEncrypted = isArchiveEncrypted,
ShowPathSelection = true
};
decompressArchiveDialog.ViewModel = decompressArchiveViewModel;

if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
decompressArchiveDialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;

ContentDialogResult option = await decompressArchiveDialog.TryShowAsync();
if (option != ContentDialogResult.Primary)
return;

if (isArchiveEncrypted && decompressArchiveViewModel.Password is not null)
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<BaseStorageFolder>(Path.GetDirectoryName(archive.Path) ?? string.Empty);
destinationFolder = await FilesystemTasks.Wrap(() => parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName).AsTask());
}

// Operate decompress
var result = await FilesystemTasks.Wrap(() =>
StorageArchiveService.DecompressAsync(archive?.Path ?? string.Empty, destinationFolder?.Path ?? string.Empty, password));

if (decompressArchiveViewModel.OpenDestinationFolderOnCompletion)
await NavigationHelpers.OpenPath(destinationFolderPath, context.ShellPage, FilesystemItemType.Directory);
}

protected override bool CanDecompressInsideArchive()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public DecompressArchiveHere()

public override Task ExecuteAsync(object? parameter = null)
{
return DecompressHelper.DecompressArchiveHereAsync(context.ShellPage);
return DecompressArchiveHereAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public DecompressArchiveHereSmart()

public override Task ExecuteAsync(object? parameter = null)
{
return DecompressHelper.DecompressArchiveHereAsync(context.ShellPage, true);
return DecompressArchiveHereAsync(true);
}
}
}