Skip to content

Commit 6812749

Browse files
authored
Display commands hotkeys (#11637)
1 parent 70dd58e commit 6812749

File tree

10 files changed

+74
-97
lines changed

10 files changed

+74
-97
lines changed

src/Files.App/Actions/FileSystem/CopyItemAction.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ internal class CopyItemAction : ObservableObject, IAction
1616

1717
public string Label { get; } = "Copy".GetLocalizedResource();
1818

19-
public HotKey HotKey = new(VirtualKey.C, VirtualKeyModifiers.Control);
20-
2119
public RichGlyph Glyph { get; } = new RichGlyph(opacityStyle: "ColorIconCopy");
2220

21+
public HotKey HotKey { get; } = new(VirtualKey.C, VirtualKeyModifiers.Control);
22+
2323
public bool IsExecutable => context.HasSelection;
2424

2525
public CopyItemAction()

src/Files.App/Actions/FileSystem/CreateFolderAction.cs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
using Files.App.Extensions;
66
using Files.App.Helpers;
77
using Files.Backend.Enums;
8-
using System.Linq;
8+
using System.ComponentModel;
99
using System.Threading.Tasks;
1010

1111
namespace Files.App.Actions
1212
{
1313
internal class CreateFolderAction : ObservableObject, IAction
1414
{
15-
public IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
15+
private readonly IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
1616

1717
public string Label { get; } = "Folder".GetLocalizedResource();
1818

@@ -25,21 +25,17 @@ public CreateFolderAction()
2525
context.PropertyChanged += Context_PropertyChanged;
2626
}
2727

28-
29-
public async Task ExecuteAsync()
28+
public Task ExecuteAsync()
3029
{
31-
UIFilesystemHelpers.CreateFileFromDialogResultType(AddItemDialogItemType.Folder, null!, context.ShellPage!);
30+
if (context.ShellPage is not null)
31+
UIFilesystemHelpers.CreateFileFromDialogResultType(AddItemDialogItemType.Folder, null!, context.ShellPage);
32+
return Task.CompletedTask;
3233
}
3334

34-
public void Context_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
35+
public void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
3536
{
36-
switch (e.PropertyName)
37-
{
38-
case nameof(IContentPageContext.SelectedItems):
39-
case nameof(IContentPageContext.Folder):
40-
OnPropertyChanged(nameof(IsExecutable));
41-
break;
42-
}
37+
if (e.PropertyName is nameof(IContentPageContext.HasSelection))
38+
OnPropertyChanged(nameof(IsExecutable));
4339
}
4440
}
4541
}

src/Files.App/Actions/FileSystem/CreateShortcutAction.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
using Files.App.Extensions;
66
using Files.App.Filesystem;
77
using Files.App.Helpers;
8+
using System.ComponentModel;
89
using System.IO;
910
using System.Threading.Tasks;
1011

1112
namespace Files.App.Actions
1213
{
1314
internal class CreateShortcutAction : ObservableObject, IAction
1415
{
15-
public IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
16+
private readonly IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
1617

1718
public string Label { get; } = "BaseLayoutItemContextFlyoutShortcut/Text".GetLocalizedResource();
1819

1920
public RichGlyph Glyph { get; } = new RichGlyph(opacityStyle: "ColorIconShortcut");
2021

21-
public bool IsExecutable => context.ShellPage is not null && context.SelectedItems.Count > 0;
22+
public bool IsExecutable => context.HasSelection;
2223

2324
public CreateShortcutAction()
2425
{
@@ -44,15 +45,10 @@ public async Task ExecuteAsync()
4445
}
4546
}
4647

47-
public void Context_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
48+
public void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
4849
{
49-
switch (e.PropertyName)
50-
{
51-
case nameof(IContentPageContext.SelectedItems):
52-
case nameof(IContentPageContext.Folder):
53-
OnPropertyChanged(nameof(IsExecutable));
54-
break;
55-
}
50+
if (e.PropertyName is nameof(IContentPageContext.HasSelection))
51+
OnPropertyChanged(nameof(IsExecutable));
5652
}
5753
}
5854
}

src/Files.App/Actions/FileSystem/CreateShortcutFromDialogAction.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,36 @@
44
using Files.App.Contexts;
55
using Files.App.Extensions;
66
using Files.App.Helpers;
7+
using System.ComponentModel;
78
using System.Threading.Tasks;
89

910
namespace Files.App.Actions
1011
{
1112
internal class CreateShortcutFromDialogAction : ObservableObject, IAction
1213
{
13-
public IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
14+
private readonly IContentPageContext context = Ioc.Default.GetRequiredService<IContentPageContext>();
1415

1516
public string Label { get; } = "Shortcut".GetLocalizedResource();
1617

1718
public RichGlyph Glyph { get; } = new RichGlyph(opacityStyle: "ColorIconShortcut");
18-
19-
public bool IsExecutable => context.ShellPage is not null && context.SelectedItems.Count > 0;
19+
20+
public bool IsExecutable => context.HasSelection;
2021

2122
public CreateShortcutFromDialogAction()
2223
{
2324
context.PropertyChanged += Context_PropertyChanged;
2425
}
25-
26+
2627
public async Task ExecuteAsync()
2728
{
28-
await UIFilesystemHelpers.CreateShortcutFromDialogAsync(context.ShellPage);
29+
if (context.ShellPage is not null)
30+
await UIFilesystemHelpers.CreateShortcutFromDialogAsync(context.ShellPage);
2931
}
3032

31-
public void Context_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
33+
public void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
3234
{
33-
switch (e.PropertyName)
34-
{
35-
case nameof(IContentPageContext.SelectedItems):
36-
case nameof(IContentPageContext.Folder):
37-
OnPropertyChanged(nameof(IsExecutable));
38-
break;
39-
}
35+
if (e.PropertyName is nameof(IContentPageContext.HasSelection))
36+
OnPropertyChanged(nameof(IsExecutable));
4037
}
4138
}
4239
}

src/Files.App/Actions/FileSystem/CutItemAction.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ internal class CutItemAction : ObservableObject, IAction
1616

1717
public string Label { get; } = "BaseLayoutItemContextFlyoutCut/Text".GetLocalizedResource();
1818

19-
public HotKey HotKey = new(VirtualKey.X, VirtualKeyModifiers.Control);
20-
2119
public RichGlyph Glyph { get; } = new RichGlyph(opacityStyle: "ColorIconCut");
2220

21+
public HotKey HotKey { get; } = new(VirtualKey.X, VirtualKeyModifiers.Control);
22+
2323
public bool IsExecutable => context.HasSelection;
2424

2525
public CutItemAction()

src/Files.App/Actions/FileSystem/DeleteItemAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ internal class DeleteItemAction : ObservableObject, IAction
1818

1919
public RichGlyph Glyph { get; } = new RichGlyph(opacityStyle: "ColorIconDelete");
2020

21-
public HotKey HotKey = new(VirtualKey.Delete);
21+
public HotKey HotKey { get; } = new(VirtualKey.Delete);
2222

2323
public bool IsExecutable => context.HasSelection;
2424

src/Files.App/Commands/HotKey.cs

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
24
using System.Linq;
35
using System.Text;
46
using Windows.System;
@@ -7,6 +9,31 @@ namespace Files.App.Commands
79
{
810
public readonly struct HotKey : IEquatable<HotKey>
911
{
12+
private static IImmutableDictionary<VirtualKey, string> keys = new Dictionary<VirtualKey, string>
13+
{
14+
[VirtualKey.Number0] = "0",
15+
[VirtualKey.Number1] = "1",
16+
[VirtualKey.Number2] = "2",
17+
[VirtualKey.Number3] = "3",
18+
[VirtualKey.Number4] = "4",
19+
[VirtualKey.Number5] = "5",
20+
[VirtualKey.Number6] = "6",
21+
[VirtualKey.Number7] = "7",
22+
[VirtualKey.Number8] = "8",
23+
[VirtualKey.Number9] = "9",
24+
[VirtualKey.NumberPad0] = "Pad0",
25+
[VirtualKey.NumberPad1] = "Pad1",
26+
[VirtualKey.NumberPad2] = "Pad2",
27+
[VirtualKey.NumberPad3] = "Pad3",
28+
[VirtualKey.NumberPad4] = "Pad4",
29+
[VirtualKey.NumberPad5] = "Pad5",
30+
[VirtualKey.NumberPad6] = "Pad6",
31+
[VirtualKey.NumberPad7] = "Pad7",
32+
[VirtualKey.NumberPad8] = "Pad8",
33+
[VirtualKey.NumberPad9] = "Pad9",
34+
[VirtualKey.Delete] = "Del",
35+
}.ToImmutableDictionary();
36+
1037
public static HotKey None { get; } = new(VirtualKey.None, VirtualKeyModifiers.None);
1138

1239
public bool IsNone => Key is VirtualKey.None;
@@ -80,34 +107,16 @@ public static HotKey Parse(string hotKey)
80107
_ => VirtualKeyModifiers.None,
81108
};
82109

83-
static VirtualKey ToKey(string part) => part switch
110+
static VirtualKey ToKey(string part)
84111
{
85-
"alt" or "menu" => VirtualKey.None,
86-
"ctrl" or "control" => VirtualKey.None,
87-
"shift" => VirtualKey.None,
88-
"windows" => VirtualKey.None,
89-
"0" => VirtualKey.Number0,
90-
"1" => VirtualKey.Number1,
91-
"2" => VirtualKey.Number2,
92-
"3" => VirtualKey.Number3,
93-
"4" => VirtualKey.Number4,
94-
"5" => VirtualKey.Number5,
95-
"6" => VirtualKey.Number6,
96-
"7" => VirtualKey.Number7,
97-
"8" => VirtualKey.Number8,
98-
"9" => VirtualKey.Number9,
99-
"Pad0" => VirtualKey.NumberPad0,
100-
"Pad1" => VirtualKey.NumberPad1,
101-
"Pad2" => VirtualKey.NumberPad2,
102-
"Pad3" => VirtualKey.NumberPad3,
103-
"Pad4" => VirtualKey.NumberPad4,
104-
"Pad5" => VirtualKey.NumberPad5,
105-
"Pad6" => VirtualKey.NumberPad6,
106-
"Pad7" => VirtualKey.NumberPad7,
107-
"Pad8" => VirtualKey.NumberPad8,
108-
"Pad9" => VirtualKey.NumberPad9,
109-
_ => Enum.TryParse(part, true, out VirtualKey key) ? key : VirtualKey.None,
110-
};
112+
if (part is "alt" or "menu" or "ctrl" or "control" or "shift" or "windows")
113+
return VirtualKey.None;
114+
115+
if (keys.Values.Contains(part))
116+
return keys.First(k => k.Value == part).Key;
117+
118+
return Enum.TryParse(part, true, out VirtualKey key) ? key : VirtualKey.None;
119+
}
111120
}
112121

113122
public override string ToString()
@@ -124,30 +133,7 @@ public override string ToString()
124133
builder.Append(ToString(Key));
125134
return builder.ToString();
126135

127-
static string ToString(VirtualKey key) => key switch
128-
{
129-
VirtualKey.Number0 => "0",
130-
VirtualKey.Number1 => "1",
131-
VirtualKey.Number2 => "2",
132-
VirtualKey.Number3 => "3",
133-
VirtualKey.Number4 => "4",
134-
VirtualKey.Number5 => "5",
135-
VirtualKey.Number6 => "6",
136-
VirtualKey.Number7 => "7",
137-
VirtualKey.Number8 => "8",
138-
VirtualKey.Number9 => "9",
139-
VirtualKey.NumberPad0 => "Pad0",
140-
VirtualKey.NumberPad1 => "Pad1",
141-
VirtualKey.NumberPad2 => "Pad2",
142-
VirtualKey.NumberPad3 => "Pad3",
143-
VirtualKey.NumberPad4 => "Pad4",
144-
VirtualKey.NumberPad5 => "Pad5",
145-
VirtualKey.NumberPad6 => "Pad6",
146-
VirtualKey.NumberPad7 => "Pad7",
147-
VirtualKey.NumberPad8 => "Pad8",
148-
VirtualKey.NumberPad9 => "Pad9",
149-
_ => key.ToString(),
150-
};
136+
static string ToString(VirtualKey key) => keys.ContainsKey(key) ? keys[key] : key.ToString();
151137
}
152138

153139
public override int GetHashCode() => (Key, Modifiers).GetHashCode();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ private class ActionCommand : ObservableObject, IRichCommand
167167
public CommandCodes Code { get; }
168168

169169
public string Label => action.Label;
170-
public string LabelWithHotKey => $"{Label} ({CustomHotKey})";
170+
public string LabelWithHotKey => !customHotKey.IsNone ? $"{Label} ({CustomHotKey})" : Label;
171171
public string AutomationName => Label;
172172

173173
public RichGlyph Glyph => action.Glyph;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@
267267
<data name="BaseLayoutItemContextFlyoutShare.Text" xml:space="preserve">
268268
<value>Share</value>
269269
</data>
270-
<data name="BaseLayoutItemContextFlyoutCut.Text" xml:space="preserve">
270+
<data name="Cut" xml:space="preserve">
271271
<value>Cut</value>
272272
</data>
273273
<data name="Delete" xml:space="preserve">

src/Files.App/UserControls/InnerNavigationToolbar.xaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,23 @@
104104
x:Name="CutButton"
105105
Width="Auto"
106106
MinWidth="40"
107+
AccessKey="X"
107108
AutomationProperties.AutomationId="InnerNavigationToolbarCutButton"
108109
Command="{x:Bind Commands.CutItem}"
109110
Label="{x:Bind Commands.CutItem.Label}"
110111
LabelPosition="Collapsed"
111-
ToolTipService.ToolTip="{x:Bind Commands.CutItem.Label}">
112+
ToolTipService.ToolTip="{x:Bind Commands.CutItem.LabelWithHotKey, Mode=OneWay}">
112113
<local:OpacityIcon Style="{x:Bind Commands.CutItem.OpacityStyle}" />
113114
</AppBarButton>
114115
<AppBarButton
115116
Width="Auto"
116117
MinWidth="40"
118+
AccessKey="C"
117119
AutomationProperties.AutomationId="InnerNavigationToolbarCopyButton"
118120
Command="{x:Bind Commands.CopyItem, Mode=OneWay}"
119121
Label="{x:Bind Commands.CopyItem}"
120122
LabelPosition="Collapsed"
121-
ToolTipService.ToolTip="{x:Bind Commands.CopyItem}">
123+
ToolTipService.ToolTip="{x:Bind Commands.CopyItem.LabelWithHotKey, Mode=OneWay}">
122124
<local:OpacityIcon Style="{x:Bind Commands.CopyItem.OpacityStyle}" />
123125
</AppBarButton>
124126
<AppBarButton
@@ -176,7 +178,7 @@
176178
Command="{x:Bind Commands.DeleteItem}"
177179
Label="{x:Bind Commands.DeleteItem.Label}"
178180
LabelPosition="Collapsed"
179-
ToolTipService.ToolTip="{x:Bind Commands.DeleteItem.Label}">
181+
ToolTipService.ToolTip="{x:Bind Commands.DeleteItem.LabelWithHotKey, Mode=OneWay}">
180182
<local:OpacityIcon Style="{x:Bind Commands.DeleteItem.OpacityStyle}" />
181183
</AppBarButton>
182184
<AppBarButton

0 commit comments

Comments
 (0)