Skip to content

Commit 2f36a71

Browse files
authored
RichCommand: Glyph + ContextMenu + EmptyRecycleBinAction (#11415)
1 parent 105c1c3 commit 2f36a71

21 files changed

+178
-69
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Files.App.Commands;
2+
using Files.App.Extensions;
3+
using Files.App.Helpers;
4+
using System.Threading.Tasks;
5+
6+
namespace Files.App.Actions
7+
{
8+
internal class EmptyRecycleBinAction : IAction
9+
{
10+
public string Label { get; } = "EmptyRecycleBin".GetLocalizedResource();
11+
12+
public RichGlyph Glyph { get; } = new RichGlyph("\uEF88", fontFamily: "RecycleBinIcons");
13+
14+
public async Task ExecuteAsync()
15+
{
16+
await RecycleBinHelpers.EmptyRecycleBin();
17+
}
18+
}
19+
}

src/Files.App/Actions/IAction.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public interface IAction
77
{
88
string Label { get; }
99

10+
RichGlyph Glyph => RichGlyph.None;
11+
1012
HotKey HotKey => HotKey.None;
1113

1214
bool IsExecutable => true;

src/Files.App/Commands/CommandCodes.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ public enum CommandCodes
1111
// show
1212
ToggleShowHiddenItems,
1313
ToggleShowFileExtensions,
14+
15+
// file system
16+
EmptyRecycleBin,
1417
}
1518
}

src/Files.App/Commands/HotKey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public static HotKey Parse(string hotKey)
5757
continue;
5858
}
5959

60-
if (key is not VirtualKey.None)
60+
if (key is VirtualKey.None)
6161
{
6262
var k = ToKey(part);
6363
if (k is not VirtualKey.None)

src/Files.App/Commands/IRichCommand.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Microsoft.UI.Xaml.Input;
1+
using Files.App.UserControls;
2+
using Microsoft.UI.Xaml.Controls;
3+
using Microsoft.UI.Xaml.Input;
24
using System.ComponentModel;
35
using System.Threading.Tasks;
46
using System.Windows.Input;
@@ -13,6 +15,10 @@ public interface IRichCommand : ICommand, INotifyPropertyChanging, INotifyProper
1315
string LabelWithHotKey { get; }
1416
string AutomationName { get; }
1517

18+
RichGlyph Glyph { get; }
19+
FontIcon? FontIcon { get; }
20+
ColoredIcon? ColoredIcon { get; }
21+
1622
HotKey DefaultHotKey { get; }
1723
HotKey CustomHotKey { get; set; }
1824

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using CommunityToolkit.Mvvm.ComponentModel;
22
using CommunityToolkit.Mvvm.Input;
33
using Files.App.Actions;
4+
using Files.App.UserControls;
5+
using Microsoft.UI.Xaml.Controls;
46
using Microsoft.UI.Xaml.Input;
57
using System;
68
using System.Collections;
@@ -29,6 +31,7 @@ internal class CommandManager : ICommandManager
2931
public IRichCommand ToggleFullScreen => commands[CommandCodes.ToggleFullScreen];
3032
public IRichCommand ToggleShowHiddenItems => commands[CommandCodes.ToggleShowHiddenItems];
3133
public IRichCommand ToggleShowFileExtensions => commands[CommandCodes.ToggleShowFileExtensions];
34+
public IRichCommand EmptyRecycleBin => commands[CommandCodes.EmptyRecycleBin];
3235

3336
public CommandManager()
3437
{
@@ -52,6 +55,7 @@ public CommandManager()
5255
[CommandCodes.ToggleFullScreen] = new ToggleFullScreenAction(),
5356
[CommandCodes.ToggleShowHiddenItems] = new ToggleShowHiddenItemsAction(),
5457
[CommandCodes.ToggleShowFileExtensions] = new ToggleShowFileExtensionsAction(),
58+
[CommandCodes.EmptyRecycleBin] = new EmptyRecycleBinAction(),
5559
};
5660

5761
[DebuggerDisplay("Command None")]
@@ -67,6 +71,10 @@ public event PropertyChangedEventHandler? PropertyChanged { add {} remove {} }
6771
public string LabelWithHotKey => string.Empty;
6872
public string AutomationName => string.Empty;
6973

74+
public RichGlyph Glyph => RichGlyph.None;
75+
public FontIcon? FontIcon => null;
76+
public ColoredIcon? ColoredIcon => null;
77+
7078
public HotKey DefaultHotKey => HotKey.None;
7179

7280
public HotKey CustomHotKey
@@ -101,6 +109,14 @@ private class ActionCommand : ObservableObject, IRichCommand
101109
public string LabelWithHotKey => $"{Label} ({CustomHotKey})";
102110
public string AutomationName => Label;
103111

112+
public RichGlyph Glyph => action.Glyph;
113+
114+
private readonly Lazy<FontIcon?> fontIcon;
115+
public FontIcon? FontIcon => fontIcon.Value;
116+
117+
private readonly Lazy<ColoredIcon?> coloredIcon;
118+
public ColoredIcon? ColoredIcon => coloredIcon.Value;
119+
104120
public HotKey DefaultHotKey => action.HotKey;
105121

106122
private HotKey customHotKey;
@@ -152,6 +168,8 @@ public ActionCommand(CommandManager manager, CommandCodes code, IAction action)
152168
this.manager = manager;
153169
Code = code;
154170
this.action = action;
171+
fontIcon = new(action.Glyph.ToFontIcon);
172+
coloredIcon = new(action.Glyph.ToColoredIcon);
155173
customHotKey = action.HotKey;
156174
command = new AsyncRelayCommand(ExecuteAsync, () => action.IsExecutable);
157175

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ public interface ICommandManager : IEnumerable<IRichCommand>
1717

1818
IRichCommand ToggleShowHiddenItems { get; }
1919
IRichCommand ToggleShowFileExtensions { get; }
20+
21+
IRichCommand EmptyRecycleBin { get; }
2022
}
2123
}

src/Files.App/Commands/RichGlyph.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using Files.App.UserControls;
2+
using Microsoft.UI.Xaml.Controls;
3+
using Microsoft.UI.Xaml.Media;
4+
using static Microsoft.UI.Xaml.Application;
5+
6+
namespace Files.App.Commands
7+
{
8+
public readonly struct RichGlyph
9+
{
10+
public static RichGlyph None { get; } = new(string.Empty);
11+
12+
public bool IsNone => string.IsNullOrEmpty(BaseGlyph);
13+
14+
public string BaseGlyph { get; }
15+
public string OverlayGlyph { get; }
16+
public string FontFamily { get; }
17+
18+
public RichGlyph(string baseGlyph, string overlayGlyph = "", string fontFamily = "")
19+
{
20+
BaseGlyph = baseGlyph;
21+
OverlayGlyph = overlayGlyph;
22+
FontFamily = fontFamily;
23+
}
24+
25+
public void Deconstruct(out string baseGlyph, out string overlayGlyph, out string fontFamily)
26+
{
27+
baseGlyph = BaseGlyph;
28+
overlayGlyph = OverlayGlyph;
29+
fontFamily = FontFamily;
30+
}
31+
32+
public FontFamily ToFontFamily()
33+
{
34+
return string.IsNullOrEmpty(FontFamily)
35+
? App.AppModel.SymbolFontFamily
36+
: (FontFamily)Current.Resources[FontFamily];
37+
}
38+
39+
public FontIcon? ToFontIcon()
40+
{
41+
if (IsNone)
42+
return null;
43+
44+
var icon = new FontIcon
45+
{
46+
Glyph = BaseGlyph,
47+
};
48+
if (!string.IsNullOrEmpty(FontFamily))
49+
icon.FontFamily = (FontFamily)Current.Resources[FontFamily];
50+
51+
return icon;
52+
}
53+
54+
public ColoredIcon? ToColoredIcon()
55+
{
56+
if (IsNone)
57+
return null;
58+
59+
var icon = new ColoredIcon
60+
{
61+
BaseLayerGlyph = BaseGlyph,
62+
OverlayLayerGlyph = OverlayGlyph,
63+
};
64+
if (!string.IsNullOrEmpty(FontFamily))
65+
icon.FontFamily = (FontFamily)Current.Resources[FontFamily];
66+
67+
return icon;
68+
}
69+
}
70+
}

src/Files.App/Helpers/ContextFlyoutItemHelper.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using CommunityToolkit.Mvvm.DependencyInjection;
22
using CommunityToolkit.Mvvm.Input;
3+
using Files.App.Commands;
34
using Files.App.Extensions;
45
using Files.App.Filesystem;
56
using Files.App.Interacts;
@@ -8,7 +9,6 @@
89
using Files.Backend.Services;
910
using Files.Backend.Services.Settings;
1011
using Files.Shared.Enums;
11-
using Microsoft.UI.Text;
1212
using Microsoft.UI.Xaml.Input;
1313
using Microsoft.UI.Xaml.Media.Imaging;
1414
using System;
@@ -25,6 +25,8 @@ namespace Files.App.Helpers
2525
{
2626
public static class ContextFlyoutItemHelper
2727
{
28+
private static readonly IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
29+
private static readonly ICommandManager commands = Ioc.Default.GetRequiredService<ICommandManager>();
2830
private static readonly IAddItemService addItemService = Ioc.Default.GetRequiredService<IAddItemService>();
2931

3032
public static List<ContextMenuFlyoutItemViewModel> GetItemContextCommandsWithoutShellItems(CurrentInstanceViewModel currentInstanceViewModel, List<ListedItem> selectedItems, BaseLayoutCommandsViewModel commandsViewModel, bool shiftPressed, SelectedItemsPropertiesViewModel? selectedItemsPropertiesViewModel, ItemViewModel? itemViewModel = null)
@@ -42,8 +44,6 @@ public static List<ContextMenuFlyoutItemViewModel> Filter(List<ContextMenuFlyout
4244
items = items.Where(x => Check(item: x, currentInstanceViewModel: currentInstanceViewModel, selectedItems: selectedItems)).ToList();
4345
items.ForEach(x => x.Items = x.Items?.Where(y => Check(item: y, currentInstanceViewModel: currentInstanceViewModel, selectedItems: selectedItems)).ToList());
4446

45-
IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
46-
4747
var overflow = items.Where(x => x.ID == "ItemOverflow").FirstOrDefault();
4848
if (overflow is not null)
4949
{
@@ -84,8 +84,6 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseItemMenuItems(
8484
CurrentInstanceViewModel currentInstanceViewModel,
8585
ItemViewModel itemViewModel = null)
8686
{
87-
IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
88-
8987
bool itemsSelected = itemViewModel is null;
9088
bool canDecompress = selectedItems.Any() && selectedItems.All(x => x.IsArchive)
9189
|| selectedItems.All(x => x.PrimaryItemAttribute == StorageItemTypes.File && FileExtensionHelpers.IsZipFile(x.FileExtension));
@@ -565,14 +563,10 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseItemMenuItems(
565563
CommandParameter = itemViewModel?.CurrentFolder,
566564
ShowItem = itemViewModel?.CurrentFolder is not null && (App.DrivesManager.Drives.FirstOrDefault(x => string.Equals(x.Path, itemViewModel?.CurrentFolder.ItemPath))?.MenuOptions.ShowFormatDrive ?? false),
567565
},
568-
new ContextMenuFlyoutItemViewModel()
566+
new ContextMenuFlyoutItemViewModel(commands.EmptyRecycleBin)
569567
{
570-
Text = "BaseLayoutContextFlyoutEmptyRecycleBin/Text".GetLocalizedResource(),
571-
Glyph = "\uEF88",
572-
GlyphFontFamilyName = "RecycleBinIcons",
573-
Command = commandsViewModel.EmptyRecycleBinCommand,
568+
IsEnabled = RecycleBinHelpers.RecycleBinHasItems(),
574569
ShowItem = !itemsSelected && currentInstanceViewModel.IsPageTypeRecycleBin,
575-
ShowInRecycleBin = true,
576570
},
577571
new ContextMenuFlyoutItemViewModel()
578572
{

src/Files.App/Interacts/BaseLayoutCommandImplementationModel.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,6 @@ public virtual void UnpinDirectoryFromFavorites(RoutedEventArgs e)
156156
_ = QuickAccessService.UnpinFromSidebar(associatedInstance.FilesystemViewModel.WorkingDirectory);
157157
}
158158

159-
public virtual async void EmptyRecycleBin(RoutedEventArgs e)
160-
{
161-
await RecycleBinHelpers.EmptyRecycleBin();
162-
}
163-
164159
public virtual async void RestoreRecycleBin(RoutedEventArgs e)
165160
{
166161
await RecycleBinHelpers.RestoreRecycleBin(associatedInstance);

src/Files.App/Interacts/BaseLayoutCommandsViewModel.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ private void InitializeCommands()
3939
SidebarUnpinItemCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.SidebarUnpinItem);
4040
UnpinDirectoryFromFavoritesCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.UnpinDirectoryFromFavorites);
4141
OpenItemCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.OpenItem);
42-
EmptyRecycleBinCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.EmptyRecycleBin);
4342
RestoreRecycleBinCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.RestoreRecycleBin);
4443
RestoreSelectionRecycleBinCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.RestoreSelectionRecycleBin);
4544
QuickLookCommand = new RelayCommand<RoutedEventArgs>(CommandsModel.QuickLook);
@@ -114,8 +113,6 @@ private void InitializeCommands()
114113

115114
public ICommand UnpinDirectoryFromFavoritesCommand { get; private set; }
116115

117-
public ICommand EmptyRecycleBinCommand { get; private set; }
118-
119116
public ICommand RestoreRecycleBinCommand { get; private set; }
120117

121118
public ICommand RestoreSelectionRecycleBinCommand { get; private set; }

src/Files.App/Interacts/IBaseLayoutCommandImplementationModel.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public interface IBaseLayoutCommandImplementationModel : IDisposable
3333

3434
void OpenItem(RoutedEventArgs e);
3535

36-
void EmptyRecycleBin(RoutedEventArgs e);
37-
3836
void RestoreRecycleBin(RoutedEventArgs e);
3937

4038
void RestoreSelectionRecycleBin(RoutedEventArgs e);

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,9 +468,6 @@
468468
<data name="PropertiesDialogHidden.Text" xml:space="preserve">
469469
<value>Hidden</value>
470470
</data>
471-
<data name="BaseLayoutContextFlyoutEmptyRecycleBin.Text" xml:space="preserve">
472-
<value>Empty recycle bin</value>
473-
</data>
474471
<data name="BaseLayoutItemContextFlyoutRestore.Text" xml:space="preserve">
475472
<value>Restore</value>
476473
</data>

src/Files.App/UserControls/InnerNavigationToolbar.xaml

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,11 @@
210210
x:Name="EmptyRecycleBinButton"
211211
x:Load="{x:Bind ViewModel.InstanceViewModel.IsPageTypeRecycleBin, Mode=OneWay, FallbackValue=False}"
212212
AccessKey="B"
213-
Command="{x:Bind ViewModel.EmptyRecycleBinCommand, Mode=OneWay}"
213+
Command="{x:Bind Commands.EmptyRecycleBin}"
214+
Icon="{x:Bind Commands.EmptyRecycleBin.FontIcon}"
214215
IsEnabled="{x:Bind ViewModel.CanEmptyRecycleBin, Mode=OneWay}"
215-
Label="{helpers:ResourceString Name=EmptyRecycleBin}"
216-
ToolTipService.ToolTip="{helpers:ResourceString Name=EmptyRecycleBin}">
217-
<AppBarButton.Icon>
218-
<FontIcon FontFamily="{StaticResource RecycleBinIcons}" Glyph="&#xEF88;" />
219-
</AppBarButton.Icon>
220-
</AppBarButton>
216+
Label="{x:Bind Commands.EmptyRecycleBin.Label}"
217+
ToolTipService.ToolTip="{x:Bind Commands.EmptyRecycleBin.Label}" />
221218
<AppBarButton
222219
x:Name="RestoreRecycleBinButton"
223220
x:Load="{x:Bind ViewModel.InstanceViewModel.IsPageTypeRecycleBin, Mode=OneWay, FallbackValue=False}"
@@ -798,26 +795,26 @@
798795
Grid.Row="0"
799796
Grid.Column="0"
800797
VerticalAlignment="Center"
801-
Text="{x:Bind CommandManager.ToggleShowHiddenItems.Label}" />
798+
Text="{x:Bind Commands.ToggleShowHiddenItems.Label}" />
802799
<ToggleSwitch
803800
Grid.Row="0"
804801
Grid.Column="1"
805802
HorizontalAlignment="Right"
806-
AutomationProperties.Name="{x:Bind CommandManager.ToggleShowHiddenItems.AutomationName}"
807-
IsOn="{x:Bind CommandManager.ToggleShowHiddenItems.IsOn, Mode=TwoWay}"
803+
AutomationProperties.Name="{x:Bind Commands.ToggleShowHiddenItems.AutomationName}"
804+
IsOn="{x:Bind Commands.ToggleShowHiddenItems.IsOn, Mode=TwoWay}"
808805
Style="{StaticResource RightAlignedToggleSwitchStyle}" />
809806

810807
<TextBlock
811808
Grid.Row="1"
812809
Grid.Column="0"
813810
VerticalAlignment="Center"
814-
Text="{x:Bind CommandManager.ToggleShowFileExtensions.Label}" />
811+
Text="{x:Bind Commands.ToggleShowFileExtensions.Label}" />
815812
<ToggleSwitch
816813
Grid.Row="1"
817814
Grid.Column="1"
818815
HorizontalAlignment="Right"
819-
AutomationProperties.Name="{x:Bind CommandManager.ToggleShowFileExtensions.AutomationName}"
820-
IsOn="{x:Bind CommandManager.ToggleShowFileExtensions.IsOn, Mode=TwoWay}"
816+
AutomationProperties.Name="{x:Bind Commands.ToggleShowFileExtensions.AutomationName}"
817+
IsOn="{x:Bind Commands.ToggleShowFileExtensions.IsOn, Mode=TwoWay}"
821818
Rotation="1"
822819
Style="{StaticResource RightAlignedToggleSwitchStyle}" />
823820
</Grid>

src/Files.App/UserControls/InnerNavigationToolbar.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public InnerNavigationToolbar()
2525
}
2626

2727
public IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();
28-
public ICommandManager CommandManager { get; } = Ioc.Default.GetRequiredService<ICommandManager>();
28+
public ICommandManager Commands { get; } = Ioc.Default.GetRequiredService<ICommandManager>();
2929

3030
private readonly IAddItemService addItemService = Ioc.Default.GetRequiredService<IAddItemService>();
3131

0 commit comments

Comments
 (0)