Skip to content

Commit 3340637

Browse files
authored
Feature: Added an option for "smart" extract (#14205)
1 parent 0ccf13e commit 3340637

File tree

8 files changed

+62
-3
lines changed

8 files changed

+62
-3
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2023 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
namespace Files.App.Actions
5+
{
6+
internal sealed class DecompressArchiveHereSmart : BaseDecompressArchiveAction
7+
{
8+
public override string Label
9+
=> "ExtractHereSmart".GetLocalizedResource();
10+
11+
public override string Description
12+
=> "DecompressArchiveHereSmartDescription".GetLocalizedResource();
13+
14+
public override HotKey HotKey
15+
=> new(Keys.E, KeyModifiers.CtrlShift);
16+
17+
public DecompressArchiveHereSmart()
18+
{
19+
}
20+
21+
public override Task ExecuteAsync()
22+
{
23+
return DecompressHelper.DecompressArchiveHereAsync(context.ShellPage, true);
24+
}
25+
}
26+
}

src/Files.App/Data/Commands/CommandCodes.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public enum CommandCodes
9292
CompressIntoZip,
9393
DecompressArchive,
9494
DecompressArchiveHere,
95+
DecompressArchiveHereSmart,
9596
DecompressArchiveToChildFolder,
9697

9798
// Image Manipulation

src/Files.App/Data/Commands/Manager/CommandManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public IRichCommand this[HotKey hotKey]
9595
public IRichCommand CompressIntoZip => commands[CommandCodes.CompressIntoZip];
9696
public IRichCommand DecompressArchive => commands[CommandCodes.DecompressArchive];
9797
public IRichCommand DecompressArchiveHere => commands[CommandCodes.DecompressArchiveHere];
98+
public IRichCommand DecompressArchiveHereSmart => commands[CommandCodes.DecompressArchiveHereSmart];
9899
public IRichCommand DecompressArchiveToChildFolder => commands[CommandCodes.DecompressArchiveToChildFolder];
99100
public IRichCommand RotateLeft => commands[CommandCodes.RotateLeft];
100101
public IRichCommand RotateRight => commands[CommandCodes.RotateRight];
@@ -259,6 +260,7 @@ public CommandManager()
259260
[CommandCodes.CompressIntoZip] = new CompressIntoZipAction(),
260261
[CommandCodes.DecompressArchive] = new DecompressArchive(),
261262
[CommandCodes.DecompressArchiveHere] = new DecompressArchiveHere(),
263+
[CommandCodes.DecompressArchiveHereSmart] = new DecompressArchiveHereSmart(),
262264
[CommandCodes.DecompressArchiveToChildFolder] = new DecompressArchiveToChildFolderAction(),
263265
[CommandCodes.RotateLeft] = new RotateLeftAction(),
264266
[CommandCodes.RotateRight] = new RotateRightAction(),

src/Files.App/Data/Commands/Manager/ICommandManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public interface ICommandManager : IEnumerable<IRichCommand>
8181
IRichCommand CompressIntoZip { get; }
8282
IRichCommand DecompressArchive { get; }
8383
IRichCommand DecompressArchiveHere { get; }
84+
IRichCommand DecompressArchiveHereSmart { get; }
8485
IRichCommand DecompressArchiveToChildFolder { get; }
8586

8687
IRichCommand RotateLeft { get; }

src/Files.App/Helpers/MenuFlyout/ContextFlyoutItemHelper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseItemMenuItems(
516516
Items = new List<ContextMenuFlyoutItemViewModel>
517517
{
518518
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchive).Build(),
519+
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveHereSmart).Build(),
519520
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveHere).Build(),
520521
new ContextMenuFlyoutItemViewModelBuilder(commands.DecompressArchiveToChildFolder).Build(),
521522
},

src/Files.App/Strings/en-US/Resources.resw

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3638,4 +3638,10 @@
36383638
<data name="Login" xml:space="preserve">
36393639
<value>Login</value>
36403640
</data>
3641-
</root>
3641+
<data name="DecompressArchiveHereSmartDescription" xml:space="preserve">
3642+
<value>Extract items from selected archive(s) to current folder for single-item archive, or to new folder for multi-item archive</value>
3643+
</data>
3644+
<data name="ExtractHereSmart" xml:space="preserve">
3645+
<value>Extract here (Smart)</value>
3646+
</data>
3647+
</root>

src/Files.App/UserControls/InnerNavigationToolbar.xaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@
273273
KeyboardAcceleratorTextOverride="{x:Bind Commands.DecompressArchive.HotKeyText, Mode=OneWay}"
274274
Text="{x:Bind Commands.DecompressArchive.Label}"
275275
Visibility="{x:Bind ViewModel.IsMultipleArchivesSelected, Mode=OneWay, Converter={StaticResource NegatedBoolToVisibilityConverter}}" />
276+
<MenuFlyoutItem
277+
x:Name="ExtractHereSmart"
278+
Command="{x:Bind Commands.DecompressArchiveHereSmart, Mode=OneWay}"
279+
IsEnabled="{x:Bind ViewModel.IsSelectionArchivesOnly, Mode=OneWay, FallbackValue=False}"
280+
KeyboardAcceleratorTextOverride="{x:Bind Commands.DecompressArchiveHereSmart.HotKeyText, Mode=OneWay}"
281+
Text="{x:Bind Commands.DecompressArchiveHereSmart.Label}"
282+
Visibility="{x:Bind ViewModel.IsArchiveOpened, Mode=OneWay, Converter={StaticResource NegatedBoolToVisibilityConverter}}" />
276283
<MenuFlyoutItem
277284
x:Name="ExtractHere"
278285
Command="{x:Bind Commands.DecompressArchiveHere, Mode=OneWay}"

src/Files.App/Utils/Archives/DecompressHelper.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public static async Task DecompressArchiveAsync(IShellPage associatedInstance)
175175
await NavigationHelpers.OpenPath(destinationFolderPath, associatedInstance, FilesystemItemType.Directory);
176176
}
177177

178-
public static async Task DecompressArchiveHereAsync(IShellPage associatedInstance)
178+
public static async Task DecompressArchiveHereAsync(IShellPage associatedInstance, bool smart = false)
179179
{
180180
if (associatedInstance?.SlimContentPage?.SelectedItems == null)
181181
return;
@@ -210,7 +210,13 @@ public static async Task DecompressArchiveHereAsync(IShellPage associatedInstanc
210210
password = Encoding.UTF8.GetString(decompressArchiveViewModel.Password);
211211
}
212212

213-
await DecompressArchiveAsync(archive, currentFolder, password);
213+
if (smart && currentFolder is not null && await FilesystemTasks.Wrap(() => IsMultipleItems(archive)))
214+
{
215+
var destinationFolder = await FilesystemTasks.Wrap(() => currentFolder.CreateFolderAsync(Path.GetFileNameWithoutExtension(archive.Path), CreationCollisionOption.GenerateUniqueName).AsTask());
216+
await DecompressArchiveAsync(archive, destinationFolder, password);
217+
}
218+
else
219+
await DecompressArchiveAsync(archive, currentFolder, password);
214220
}
215221
}
216222

@@ -274,5 +280,14 @@ private static async Task<bool> IsArchiveEncrypted(BaseStorageFile archive)
274280

275281
return zipFile.ArchiveFileData.Any(file => file.Encrypted || file.Method.Contains("Crypto") || file.Method.Contains("AES"));
276282
}
283+
284+
private static async Task<bool> IsMultipleItems(BaseStorageFile archive)
285+
{
286+
using SevenZipExtractor? zipFile = await GetZipFile(archive);
287+
if (zipFile is null)
288+
return true;
289+
290+
return zipFile.ArchiveFileData.Count > 1;
291+
}
277292
}
278293
}

0 commit comments

Comments
 (0)