diff --git a/src/modules/Hosts/Hosts/MainWindow.xaml.cs b/src/modules/Hosts/Hosts/MainWindow.xaml.cs index cbebd397a3..a8b4f97c73 100644 --- a/src/modules/Hosts/Hosts/MainWindow.xaml.cs +++ b/src/modules/Hosts/Hosts/MainWindow.xaml.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using Hosts.Helpers; -using Microsoft.UI.Windowing; using WinUIEx; namespace Hosts diff --git a/src/modules/Hosts/Hosts/Strings/en-us/Resources.resw b/src/modules/Hosts/Hosts/Strings/en-us/Resources.resw index 5a3cb3f060..e7757f3a9a 100644 --- a/src/modules/Hosts/Hosts/Strings/en-us/Resources.resw +++ b/src/modules/Hosts/Hosts/Strings/en-us/Resources.resw @@ -132,6 +132,9 @@ New entry + + New entry (CTRL+N) + Additional content @@ -187,6 +190,9 @@ Duplicate entry + + Edit + Entries diff --git a/src/modules/Hosts/Hosts/Views/MainPage.xaml b/src/modules/Hosts/Hosts/Views/MainPage.xaml index 1732586dea..ddc20b64c6 100644 --- a/src/modules/Hosts/Hosts/Views/MainPage.xaml +++ b/src/modules/Hosts/Hosts/Views/MainPage.xaml @@ -56,6 +56,11 @@ Glyph="" /> + + + @@ -213,11 +220,27 @@ - + + + + + + + Icon="TwoBars"> + + + + + Icon="Delete"> + + + + diff --git a/src/modules/Hosts/Hosts/Views/MainPage.xaml.cs b/src/modules/Hosts/Hosts/Views/MainPage.xaml.cs index 37303b358b..b067420971 100644 --- a/src/modules/Hosts/Hosts/Views/MainPage.xaml.cs +++ b/src/modules/Hosts/Hosts/Views/MainPage.xaml.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Linq; using System.Threading.Tasks; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; @@ -15,6 +16,8 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Input; using Windows.ApplicationModel.Resources; +using Windows.System; +using Windows.UI.Core; namespace Hosts.Views { @@ -60,9 +63,14 @@ namespace Hosts.Views } private async void Entries_ItemClick(object sender, ItemClickEventArgs e) + { + await ShowEditDialogAsync(e.ClickedItem as Entry); + } + + public async Task ShowEditDialogAsync(Entry entry) { var resourceLoader = ResourceLoader.GetForViewIndependentUse(); - ViewModel.Selected = e.ClickedItem as Entry; + ViewModel.Selected = entry; EntryDialog.Title = resourceLoader.GetString("UpdateEntry_Title"); EntryDialog.PrimaryButtonText = resourceLoader.GetString("UpdateBtn"); EntryDialog.PrimaryButtonCommand = UpdateCommand; @@ -111,21 +119,40 @@ namespace Hosts.Views if (menuFlyoutItem != null) { - var selectedEntry = menuFlyoutItem.DataContext as Entry; - ViewModel.Selected = selectedEntry; - DeleteDialog.Title = selectedEntry.Address; - await DeleteDialog.ShowAsync(); + await ShowDeleteDialogAsync(menuFlyoutItem.DataContext as Entry); } } + public async Task ShowDeleteDialogAsync(Entry entry) + { + ViewModel.Selected = entry; + DeleteDialog.Title = entry.Address; + await DeleteDialog.ShowAsync(); + } + private async void Ping_Click(object sender, RoutedEventArgs e) { var menuFlyoutItem = sender as MenuFlyoutItem; if (menuFlyoutItem != null) { - ViewModel.Selected = menuFlyoutItem.DataContext as Entry; - await ViewModel.PingSelectedAsync(); + await PingAsync(menuFlyoutItem.DataContext as Entry); + } + } + + private async Task PingAsync(Entry entry) + { + ViewModel.Selected = entry; + await ViewModel.PingSelectedAsync(); + } + + private async void Edit_Click(object sender, RoutedEventArgs e) + { + var menuFlyoutItem = sender as MenuFlyoutItem; + + if (menuFlyoutItem != null) + { + await ShowEditDialogAsync(menuFlyoutItem.DataContext as Entry); } } @@ -197,5 +224,56 @@ namespace Hosts.Views Logger.LogError("Couldn't set the margin for a content dialog. It will appear on top of the title bar.", ex); } } + + /// + /// Handle the keyboard shortcuts at list view level since + /// KeyboardAccelerators in FlyoutBase.AttachedFlyout works only when the flyout is open + /// + private async void Entries_KeyDown(object sender, KeyRoutedEventArgs e) + { + var listView = sender as ListView; + if (listView != null && e.KeyStatus.WasKeyDown == false) + { + var entry = listView.SelectedItem as Entry; + + if (Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down)) + { + if (e.Key == VirtualKey.E) + { + await ShowEditDialogAsync(entry); + } + else if (e.Key == VirtualKey.P) + { + await PingAsync(entry); + } + } + else if (e.Key == VirtualKey.Delete) + { + await ShowDeleteDialogAsync(entry); + } + } + } + + /// + /// Focus the first item when the list view gets the focus with keyboard + /// + private void Entries_GotFocus(object sender, RoutedEventArgs e) + { + var listView = sender as ListView; + if (listView.SelectedItem == null && listView.Items.Count > 0) + { + listView.SelectedIndex = 0; + } + } + + private void MenuFlyout_Opened(object sender, object e) + { + // Focus the first item: required for workaround https://github.com/microsoft/PowerToys/issues/21263 + var menuFlyout = sender as MenuFlyout; + if (menuFlyout != null && menuFlyout.Items.Count > 0) + { + menuFlyout.Items.First().Focus(FocusState.Programmatic); + } + } } }