Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
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 All @@ -25,6 +26,26 @@ public BaseCompressArchiveAction()

public abstract Task ExecuteAsync(object? parameter = null);

protected void GetDestination(out string[] sources, out string directory, out string fileName)
{
sources = context.SelectedItems.Select(item => item.ItemPath).ToArray();
directory = string.Empty;
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);
}
}

private bool IsContextPageTypeAdaptedToCommand()
{
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ public override async Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
GetDestination(out var sources, out var directory, out var fileName);

var dialog = new CreateArchiveDialog
{
FileName = fileName,
};
var dialog = new CreateArchiveDialog() { FileName = fileName };

if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
dialog.XamlRoot = MainWindow.Instance.Content.XamlRoot;
Expand All @@ -39,7 +36,7 @@ public override async Task ExecuteAsync(object? parameter = null)
if (!dialog.CanCreate || result != ContentDialogResult.Primary)
return;

ICompressArchiveModel creator = new CompressArchiveModel(
ICompressArchiveModel compressionModel = new CompressArchiveModel(
sources,
directory,
dialog.FileName,
Expand All @@ -48,7 +45,7 @@ public override async Task ExecuteAsync(object? parameter = null)
dialog.CompressionLevel,
dialog.SplittingSize);

await CompressHelper.CompressArchiveAsync(creator);
await StorageArchiveService.CompressAsync(compressionModel);
}
}
}
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,15 @@ public override Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return Task.CompletedTask;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
GetDestination(out var sources, out var directory, out var fileName);

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

return CompressHelper.CompressArchiveAsync(creator);
return StorageArchiveService.CompressAsync(compressionModel);
}
}
}
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,15 @@ public override Task ExecuteAsync(object? parameter = null)
if (context.ShellPage is null)
return Task.CompletedTask;

var (sources, directory, fileName) = CompressHelper.GetCompressDestination(context.ShellPage);
GetDestination(out var sources, out var directory, out var fileName);

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

return CompressHelper.CompressArchiveAsync(creator);
return StorageArchiveService.CompressAsync(compressionModel);
}
}
}
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);
}
}
}
Loading