diff --git a/src/Files.App/Actions/Open/OpenStorageSenseAction.cs b/src/Files.App/Actions/Open/OpenStorageSenseAction.cs new file mode 100644 index 000000000000..32245edcda6d --- /dev/null +++ b/src/Files.App/Actions/Open/OpenStorageSenseAction.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2024 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Actions +{ + internal class OpenStorageSenseAction : ObservableObject, IAction + { + private readonly IContentPageContext context = Ioc.Default.GetRequiredService(); + private readonly DrivesViewModel drivesViewModel = Ioc.Default.GetRequiredService(); + + public virtual string Label + => Strings.Cleanup.GetLocalizedResource(); + + public virtual string Description + => Strings.OpenStorageSenseDescription.GetLocalizedResource(); + + public virtual bool IsExecutable => + context.HasItem && + !context.HasSelection && + drivesViewModel.Drives + .Cast() + .FirstOrDefault(x => string.Equals(x.Path, context.Folder?.ItemPath)) is DriveItem driveItem && + driveItem.Type != DriveType.Network; + + public virtual bool IsAccessibleGlobally + => true; + + public OpenStorageSenseAction() + { + context.PropertyChanged += Context_PropertyChanged; + } + + public virtual Task ExecuteAsync(object? parameter = null) + { + return StorageSenseHelper.OpenStorageSenseAsync(context.Folder?.ItemPath ?? string.Empty); + } + + public void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName is nameof(IContentPageContext.HasItem)) + OnPropertyChanged(nameof(IsExecutable)); + } + } +} diff --git a/src/Files.App/Actions/Open/OpenStorageSenseFromHomeAction.cs b/src/Files.App/Actions/Open/OpenStorageSenseFromHomeAction.cs new file mode 100644 index 000000000000..c3b4593e409f --- /dev/null +++ b/src/Files.App/Actions/Open/OpenStorageSenseFromHomeAction.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2024 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Actions +{ + internal sealed class OpenStorageSenseFromHomeAction : OpenStorageSenseAction + { + private IHomePageContext HomePageContext { get; } = Ioc.Default.GetRequiredService(); + private readonly DrivesViewModel drivesViewModel = Ioc.Default.GetRequiredService(); + + public override bool IsExecutable => + HomePageContext.IsAnyItemRightClicked && + HomePageContext.RightClickedItem is not null && + HomePageContext.RightClickedItem.Path is not null && + drivesViewModel.Drives + .Cast() + .FirstOrDefault(x => string.Equals(x.Path, HomePageContext.RightClickedItem.Path)) is DriveItem driveItem && + driveItem.Type != DriveType.Network; + + public override bool IsAccessibleGlobally + => false; + + public override Task ExecuteAsync(object? parameter = null) + { + return StorageSenseHelper.OpenStorageSenseAsync(HomePageContext?.RightClickedItem?.Path ?? string.Empty); + } + } +} diff --git a/src/Files.App/Actions/Open/OpenStorageSenseFromSidebarAction.cs b/src/Files.App/Actions/Open/OpenStorageSenseFromSidebarAction.cs new file mode 100644 index 000000000000..49902797555d --- /dev/null +++ b/src/Files.App/Actions/Open/OpenStorageSenseFromSidebarAction.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2024 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Actions +{ + internal sealed class OpenStorageSenseFromSidebarAction : OpenStorageSenseAction + { + private ISidebarContext SidebarContext { get; } = Ioc.Default.GetRequiredService(); + private readonly DrivesViewModel drivesViewModel = Ioc.Default.GetRequiredService(); + + public override bool IsExecutable => + SidebarContext.IsItemRightClicked && + SidebarContext.RightClickedItem is not null && + SidebarContext.RightClickedItem.Path is not null && + drivesViewModel.Drives + .Cast() + .FirstOrDefault(x => string.Equals(x.Path, SidebarContext.RightClickedItem.Path)) is DriveItem driveItem && + driveItem.Type != DriveType.Network; + + public override bool IsAccessibleGlobally + => false; + + public override Task ExecuteAsync(object? parameter = null) + { + return StorageSenseHelper.OpenStorageSenseAsync(SidebarContext?.RightClickedItem?.Path ?? string.Empty); + } + } +} \ No newline at end of file diff --git a/src/Files.App/Data/Commands/Manager/CommandCodes.cs b/src/Files.App/Data/Commands/Manager/CommandCodes.cs index fb66e73f8b44..58e6b57097ed 100644 --- a/src/Files.App/Data/Commands/Manager/CommandCodes.cs +++ b/src/Files.App/Data/Commands/Manager/CommandCodes.cs @@ -114,6 +114,9 @@ public enum CommandCodes OpenProperties, OpenClassicProperties, OpenSettings, + OpenStorageSense, + OpenStorageSenseFromHome, + OpenStorageSenseFromSidebar, OpenTerminal, OpenTerminalAsAdmin, OpenTerminalFromSidebar, diff --git a/src/Files.App/Data/Commands/Manager/CommandManager.cs b/src/Files.App/Data/Commands/Manager/CommandManager.cs index 3d3f1a1f250c..a4711d2c0127 100644 --- a/src/Files.App/Data/Commands/Manager/CommandManager.cs +++ b/src/Files.App/Data/Commands/Manager/CommandManager.cs @@ -116,6 +116,9 @@ public IRichCommand this[HotKey hotKey] public IRichCommand OpenRepoInVSCode => commands[CommandCodes.OpenRepoInVSCode]; public IRichCommand OpenProperties => commands[CommandCodes.OpenProperties]; public IRichCommand OpenClassicProperties => commands[CommandCodes.OpenClassicProperties]; + public IRichCommand OpenStorageSense => commands[CommandCodes.OpenStorageSense]; + public IRichCommand OpenStorageSenseFromHome => commands[CommandCodes.OpenStorageSenseFromHome]; + public IRichCommand OpenStorageSenseFromSidebar => commands[CommandCodes.OpenStorageSenseFromSidebar]; public IRichCommand OpenSettings => commands[CommandCodes.OpenSettings]; public IRichCommand OpenTerminal => commands[CommandCodes.OpenTerminal]; public IRichCommand OpenTerminalAsAdmin => commands[CommandCodes.OpenTerminalAsAdmin]; @@ -313,6 +316,9 @@ public IEnumerator GetEnumerator() => [CommandCodes.OpenRepoInVSCode] = new OpenRepoInVSCodeAction(), [CommandCodes.OpenProperties] = new OpenPropertiesAction(), [CommandCodes.OpenClassicProperties] = new OpenClassicPropertiesAction(), + [CommandCodes.OpenStorageSense] = new OpenStorageSenseAction(), + [CommandCodes.OpenStorageSenseFromHome] = new OpenStorageSenseFromHomeAction(), + [CommandCodes.OpenStorageSenseFromSidebar] = new OpenStorageSenseFromSidebarAction(), [CommandCodes.OpenSettings] = new OpenSettingsAction(), [CommandCodes.OpenTerminal] = new OpenTerminalAction(), [CommandCodes.OpenTerminalAsAdmin] = new OpenTerminalAsAdminAction(), diff --git a/src/Files.App/Data/Commands/Manager/ICommandManager.cs b/src/Files.App/Data/Commands/Manager/ICommandManager.cs index bd788085d662..f33e0c7f4544 100644 --- a/src/Files.App/Data/Commands/Manager/ICommandManager.cs +++ b/src/Files.App/Data/Commands/Manager/ICommandManager.cs @@ -102,6 +102,9 @@ public interface ICommandManager : IEnumerable IRichCommand OpenRepoInVSCode { get; } IRichCommand OpenProperties { get; } IRichCommand OpenClassicProperties { get; } + IRichCommand OpenStorageSense { get; } + IRichCommand OpenStorageSenseFromHome { get; } + IRichCommand OpenStorageSenseFromSidebar { get; } IRichCommand OpenSettings { get; } IRichCommand OpenTerminal { get; } IRichCommand OpenTerminalAsAdmin { get; } diff --git a/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs b/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs index 6058791f568f..dfa20e6d538f 100644 --- a/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs +++ b/src/Files.App/Data/Factories/ContentPageContextFlyoutFactory.cs @@ -368,7 +368,6 @@ public static List GetBaseItemMenuItems( ShowItem = !itemsSelected, ShowInFtpPage = true }, - new ContextMenuFlyoutItemViewModelBuilder(Commands.FormatDrive).Build(), new ContextMenuFlyoutItemViewModelBuilder(Commands.EmptyRecycleBin) { IsVisible = currentInstanceViewModel.IsPageTypeRecycleBin && !itemsSelected, @@ -598,12 +597,17 @@ public static List GetBaseItemMenuItems( new ContextMenuFlyoutItemViewModel() { ItemType = ContextMenuFlyoutItemType.Separator, - ShowItem = !itemsSelected && Commands.OpenTerminal.IsExecutable || areAllItemsFolders && Commands.OpenTerminal.IsExecutable + ShowItem = (!itemsSelected && Commands.OpenTerminal.IsExecutable) || + (areAllItemsFolders && Commands.OpenTerminal.IsExecutable) || + Commands.OpenStorageSense.IsExecutable || + Commands.FormatDrive.IsExecutable }, new ContextMenuFlyoutItemViewModelBuilder(Commands.OpenTerminal) { - IsVisible = !itemsSelected && Commands.OpenTerminal.IsExecutable || areAllItemsFolders && Commands.OpenTerminal.IsExecutable + IsVisible = (!itemsSelected && Commands.OpenTerminal.IsExecutable) || (areAllItemsFolders && Commands.OpenTerminal.IsExecutable) }.Build(), + new ContextMenuFlyoutItemViewModelBuilder(Commands.OpenStorageSense).Build(), + new ContextMenuFlyoutItemViewModelBuilder(Commands.FormatDrive).Build(), // Shell extensions are not available on the FTP server or in the archive, // but following items are intentionally added because icons in the context menu will not appear // unless there is at least one menu item with an icon that is not an ThemedIconModel. (#12943) diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw index 65d121ad30e0..9403407c441a 100644 --- a/src/Files.App/Strings/en-US/Resources.resw +++ b/src/Files.App/Strings/en-US/Resources.resw @@ -1244,6 +1244,12 @@ Open Storage Sense + + Open the Storage Sense page in Windows Settings + + + Cleanup + Copy @@ -2274,7 +2280,7 @@ Show hidden items - Format... + Format Help diff --git a/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs b/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs index 54325eb6c25e..d9d1dea92a41 100644 --- a/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/SidebarViewModel.cs @@ -3,7 +3,6 @@ using Files.App.Helpers.ContextFlyouts; using Files.App.UserControls.Sidebar; -using Files.App.ViewModels.Dialogs; using Microsoft.UI.Input; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -12,13 +11,11 @@ using System.Collections.Specialized; using System.IO; using System.Windows.Input; -using Windows.ApplicationModel.DataTransfer.DragDrop; using Windows.ApplicationModel.DataTransfer; +using Windows.ApplicationModel.DataTransfer.DragDrop; using Windows.Storage; using Windows.System; using Windows.UI.Core; -using Files.Core.Storage; -using Files.Core.Storage.Extensions; namespace Files.App.ViewModels.UserControls { @@ -1046,13 +1043,6 @@ private List GetLocationItemMenuItems(INavigatio ShowItem = options.ShowEjectDevice }, new ContextMenuFlyoutItemViewModel() - { - Text = "FormatDriveText".GetLocalizedResource(), - Command = FormatDriveCommand, - CommandParameter = item, - ShowItem = options.ShowFormatDrive - }, - new ContextMenuFlyoutItemViewModel() { Text = "Properties".GetLocalizedResource(), ThemedIconModel = new ThemedIconModel() @@ -1066,9 +1056,19 @@ private List GetLocationItemMenuItems(INavigatio new ContextMenuFlyoutItemViewModel() { ItemType = ContextMenuFlyoutItemType.Separator, - ShowItem = Commands.OpenTerminalFromSidebar.IsExecutable + ShowItem = Commands.OpenTerminalFromSidebar.IsExecutable || + Commands.OpenStorageSenseFromSidebar.IsExecutable || + options.ShowFormatDrive }, new ContextMenuFlyoutItemViewModelBuilder(Commands.OpenTerminalFromSidebar).Build(), + new ContextMenuFlyoutItemViewModelBuilder(Commands.OpenStorageSenseFromSidebar).Build(), + new ContextMenuFlyoutItemViewModel() + { + Text = Strings.FormatDriveText.GetLocalizedResource(), + Command = FormatDriveCommand, + CommandParameter = item, + ShowItem = options.ShowFormatDrive + }, new ContextMenuFlyoutItemViewModel() { ItemType = ContextMenuFlyoutItemType.Separator, diff --git a/src/Files.App/ViewModels/UserControls/Widgets/DrivesWidgetViewModel.cs b/src/Files.App/ViewModels/UserControls/Widgets/DrivesWidgetViewModel.cs index fb1eab81c327..3853923c46b7 100644 --- a/src/Files.App/ViewModels/UserControls/Widgets/DrivesWidgetViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/Widgets/DrivesWidgetViewModel.cs @@ -121,13 +121,6 @@ public override List GetItemMenuItems(WidgetCard ShowItem = options?.ShowEjectDevice ?? false }, new() - { - Text = "FormatDriveText".GetLocalizedResource(), - Command = FormatDriveCommand, - CommandParameter = item, - ShowItem = options?.ShowFormatDrive ?? false - }, - new() { Text = "Properties".GetLocalizedResource(), ThemedIconModel = new ThemedIconModel() { ThemedIconStyle = "App.ThemedIcons.Properties" }, @@ -149,9 +142,19 @@ public override List GetItemMenuItems(WidgetCard new ContextMenuFlyoutItemViewModel() { ItemType = ContextMenuFlyoutItemType.Separator, - ShowItem = CommandManager.OpenTerminalFromHome.IsExecutable + ShowItem = CommandManager.OpenTerminalFromHome.IsExecutable || + CommandManager.OpenStorageSenseFromHome.IsExecutable || + (options?.ShowFormatDrive ?? false) }, new ContextMenuFlyoutItemViewModelBuilder(CommandManager.OpenTerminalFromHome).Build(), + new ContextMenuFlyoutItemViewModelBuilder(CommandManager.OpenStorageSenseFromHome).Build(), + new() + { + Text = "FormatDriveText".GetLocalizedResource(), + Command = FormatDriveCommand, + CommandParameter = item, + ShowItem = options?.ShowFormatDrive ?? false + }, new() { ItemType = ContextMenuFlyoutItemType.Separator,