mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
CmdPal: Adds a back button to Settings window (#44013)
## Summary of the Pull Request This PR introduces proper navigation support in the Settings window. - Enables the Go back button in the title bar. - Adds support for Alt + Left Arrow, mouse X1 button, and the Go back button. - Fixes breadcrumb updates and localization issues to prevent them from breaking during navigation. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #44011 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
This commit is contained in:
@@ -20,13 +20,15 @@
|
||||
<winuiex:WindowEx.SystemBackdrop>
|
||||
<MicaBackdrop />
|
||||
</winuiex:WindowEx.SystemBackdrop>
|
||||
<Grid>
|
||||
<Grid x:Name="RootElement">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TitleBar
|
||||
x:Name="AppTitleBar"
|
||||
BackRequested="TitleBar_BackRequested"
|
||||
IsBackButtonVisible="{x:Bind NavFrame.CanGoBack, Mode=OneWay}"
|
||||
IsTabStop="False"
|
||||
PaneToggleRequested="AppTitleBar_PaneToggleRequested">
|
||||
<!-- This is a workaround for https://github.com/microsoft/microsoft-ui-xaml/issues/10374, once fixed we should just be using IconSource -->
|
||||
@@ -56,10 +58,12 @@
|
||||
</NavigationView.Resources>
|
||||
<NavigationView.MenuItems>
|
||||
<NavigationViewItem
|
||||
x:Name="GeneralPageNavItem"
|
||||
x:Uid="Settings_GeneralPage_NavigationViewItem_General"
|
||||
Icon="{ui:FontIcon Glyph=}"
|
||||
Tag="General" />
|
||||
<NavigationViewItem
|
||||
x:Name="ExtensionPageNavItem"
|
||||
x:Uid="Settings_GeneralPage_NavigationViewItem_Extensions"
|
||||
Icon="{ui:FontIcon Glyph=}"
|
||||
Tag="Extensions" />
|
||||
@@ -90,7 +94,10 @@
|
||||
</BreadcrumbBar.Resources>
|
||||
</BreadcrumbBar>
|
||||
</Grid>
|
||||
<Frame x:Name="NavFrame" Grid.Row="1" />
|
||||
<Frame
|
||||
x:Name="NavFrame"
|
||||
Grid.Row="1"
|
||||
Navigated="NavFrame_OnNavigated" />
|
||||
</Grid>
|
||||
</NavigationView>
|
||||
</Grid>
|
||||
|
||||
@@ -4,14 +4,19 @@
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.UI.Helpers;
|
||||
using Microsoft.CmdPal.UI.Messages;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Windows.System;
|
||||
using Windows.UI.Core;
|
||||
using WinUIEx;
|
||||
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
|
||||
using TitleBar = Microsoft.UI.Xaml.Controls.TitleBar;
|
||||
@@ -19,9 +24,12 @@ using TitleBar = Microsoft.UI.Xaml.Controls.TitleBar;
|
||||
namespace Microsoft.CmdPal.UI.Settings;
|
||||
|
||||
public sealed partial class SettingsWindow : WindowEx,
|
||||
IDisposable,
|
||||
IRecipient<NavigateToExtensionSettingsMessage>,
|
||||
IRecipient<QuitMessage>
|
||||
{
|
||||
private readonly LocalKeyboardListener _localKeyboardListener;
|
||||
|
||||
public ObservableCollection<Crumb> BreadCrumbs { get; } = [];
|
||||
|
||||
// Gets or sets optional action invoked after NavigationView is loaded.
|
||||
@@ -40,6 +48,17 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
|
||||
WeakReferenceMessenger.Default.Register<NavigateToExtensionSettingsMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<QuitMessage>(this);
|
||||
|
||||
_localKeyboardListener = new LocalKeyboardListener();
|
||||
_localKeyboardListener.KeyPressed += LocalKeyboardListener_OnKeyPressed;
|
||||
_localKeyboardListener.Start();
|
||||
Closed += SettingsWindow_Closed;
|
||||
RootElement.AddHandler(UIElement.PointerPressedEvent, new PointerEventHandler(RootElement_OnPointerPressed), true);
|
||||
}
|
||||
|
||||
private void SettingsWindow_Closed(object sender, WindowEventArgs args)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
// Handles NavigationView loaded event.
|
||||
@@ -85,10 +104,9 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
"Extensions" => typeof(ExtensionsPage),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
if (pageType is not null)
|
||||
{
|
||||
BreadCrumbs.Clear();
|
||||
BreadCrumbs.Add(new(page, page));
|
||||
NavFrame.Navigate(pageType);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +114,6 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
private void Navigate(ProviderSettingsViewModel extension)
|
||||
{
|
||||
NavFrame.Navigate(typeof(ExtensionPage), extension);
|
||||
BreadCrumbs.Add(new(extension.DisplayName, string.Empty));
|
||||
}
|
||||
|
||||
private void PositionCentered()
|
||||
@@ -127,9 +144,9 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Activated(object sender, WindowActivatedEventArgs args)
|
||||
private void Window_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<WindowActivatedEventArgs>(args);
|
||||
WeakReferenceMessenger.Default.Send<Microsoft.UI.Xaml.WindowActivatedEventArgs>(args);
|
||||
}
|
||||
|
||||
private void Window_Closed(object sender, WindowEventArgs args)
|
||||
@@ -141,7 +158,7 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
|
||||
private void NavView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
|
||||
{
|
||||
if (args.DisplayMode == NavigationViewDisplayMode.Compact || args.DisplayMode == NavigationViewDisplayMode.Minimal)
|
||||
if (args.DisplayMode is NavigationViewDisplayMode.Compact or NavigationViewDisplayMode.Minimal)
|
||||
{
|
||||
AppTitleBar.IsPaneToggleButtonVisible = true;
|
||||
WorkAroundIcon.Margin = new Thickness(8, 0, 16, 0); // Required for workaround, see XAML comment
|
||||
@@ -149,7 +166,7 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
else
|
||||
{
|
||||
AppTitleBar.IsPaneToggleButtonVisible = false;
|
||||
WorkAroundIcon.Margin = new Thickness(16, 0, 0, 0); // Required for workaround, see XAML comment
|
||||
WorkAroundIcon.Margin = new Thickness(16, 0, 8, 0); // Required for workaround, see XAML comment
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +180,93 @@ public sealed partial class SettingsWindow : WindowEx,
|
||||
{
|
||||
NavView.IsPaneOpen = !NavView.IsPaneOpen;
|
||||
}
|
||||
|
||||
private void TryGoBack()
|
||||
{
|
||||
if (NavFrame.CanGoBack)
|
||||
{
|
||||
NavFrame.GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
private void TitleBar_BackRequested(TitleBar sender, object args)
|
||||
{
|
||||
TryGoBack();
|
||||
}
|
||||
|
||||
private void LocalKeyboardListener_OnKeyPressed(object? sender, LocalKeyboardListenerKeyPressedEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case VirtualKey.GoBack:
|
||||
case VirtualKey.XButton1:
|
||||
TryGoBack();
|
||||
break;
|
||||
|
||||
case VirtualKey.Left:
|
||||
var altPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down);
|
||||
if (altPressed)
|
||||
{
|
||||
TryGoBack();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RootElement_OnPointerPressed(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.Pointer.PointerDeviceType == PointerDeviceType.Mouse)
|
||||
{
|
||||
var ptrPt = e.GetCurrentPoint(RootElement);
|
||||
if (ptrPt.Properties.IsXButton1Pressed)
|
||||
{
|
||||
TryGoBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Error handling mouse button press event", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_localKeyboardListener?.Dispose();
|
||||
}
|
||||
|
||||
private void NavFrame_OnNavigated(object sender, NavigationEventArgs e)
|
||||
{
|
||||
BreadCrumbs.Clear();
|
||||
|
||||
if (e.SourcePageType == typeof(GeneralPage))
|
||||
{
|
||||
NavView.SelectedItem = GeneralPageNavItem;
|
||||
var pageType = RS_.GetString("Settings_PageTitles_GeneralPage");
|
||||
BreadCrumbs.Add(new(pageType, pageType));
|
||||
}
|
||||
else if (e.SourcePageType == typeof(ExtensionsPage))
|
||||
{
|
||||
NavView.SelectedItem = ExtensionPageNavItem;
|
||||
var pageType = RS_.GetString("Settings_PageTitles_ExtensionsPage");
|
||||
BreadCrumbs.Add(new(pageType, pageType));
|
||||
}
|
||||
else if (e.SourcePageType == typeof(ExtensionPage) && e.Parameter is ProviderSettingsViewModel vm)
|
||||
{
|
||||
NavView.SelectedItem = ExtensionPageNavItem;
|
||||
var extensionsPageType = RS_.GetString("Settings_PageTitles_ExtensionsPage");
|
||||
BreadCrumbs.Add(new(extensionsPageType, extensionsPageType));
|
||||
BreadCrumbs.Add(new(vm.DisplayName, vm));
|
||||
}
|
||||
else
|
||||
{
|
||||
BreadCrumbs.Add(new($"[{e.SourcePageType?.Name}]", string.Empty));
|
||||
Logger.LogError($"Unknown breadcrumb for page type '{e.SourcePageType}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct Crumb
|
||||
|
||||
@@ -550,4 +550,10 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<data name="Settings_GeneralPage_AutoGoHome_SettingsCard.Description" xml:space="preserve">
|
||||
<value>Automatically returns to home page after a period of inactivity when Command Palette is closed</value>
|
||||
</data>
|
||||
<data name="Settings_PageTitles_GeneralPage" xml:space="preserve">
|
||||
<value>General</value>
|
||||
</data>
|
||||
<data name="Settings_PageTitles_ExtensionsPage" xml:space="preserve">
|
||||
<value>Extensions</value>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user