This commit is contained in:
Michael Jolley
2025-12-12 20:03:39 -06:00
parent 69d706560f
commit 0f4f0f35f3
3 changed files with 88 additions and 13 deletions

View File

@@ -42,9 +42,9 @@ public partial class KeyboardService : IDisposable
_settingsService.SettingsChanged += SettingsChanged; _settingsService.SettingsChanged += SettingsChanged;
} }
public void SetProcessCommand(HWND hwnd, ProcessCommand processCommand) public void SetProcessCommand(IntPtr hwnd, ProcessCommand processCommand)
{ {
_hwnd = hwnd; _hwnd = new HWND(hwnd);
_keyboardListener.SetProcessCommand(processCommand); _keyboardListener.SetProcessCommand(processCommand);
SetupHotkeys(); SetupHotkeys();
} }

View File

@@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CommandPalette.UI.Services;
internal class NavigationManager
{
}

View File

@@ -11,6 +11,7 @@ using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.UI.Models.Events; using Microsoft.CommandPalette.UI.Models.Events;
using Microsoft.CommandPalette.UI.Models.Messages; using Microsoft.CommandPalette.UI.Models.Messages;
using Microsoft.CommandPalette.UI.Services; using Microsoft.CommandPalette.UI.Services;
using Microsoft.CommandPalette.UI.Services.Helpers;
using Microsoft.CommandPalette.UI.ViewModels; using Microsoft.CommandPalette.UI.ViewModels;
using Microsoft.CommandPalette.ViewModels; using Microsoft.CommandPalette.ViewModels;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -160,6 +161,71 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
}); });
} }
public void Receive(GoBackMessage message)
{
_ = DispatcherQueue.TryEnqueue(() => GoBack(message.WithAnimation, message.FocusSearch));
}
private void GoBack(bool withAnimation = true, bool focusSearch = true)
{
HideDetails();
viewModel.CancelNavigation();
// Note: That we restore the VM state below in RootFrame_Navigated call back after this occurs.
// In the future, we may want to manage the back stack ourselves vs. relying on Frame
// We could replace Frame with a ContentPresenter, but then have to manage transition animations ourselves.
// However, then we have more fine-grained control on the back stack, managing the VM cache, and not
// having that all be a black box, though then we wouldn't cache the XAML page itself, but sometimes that is a drawback.
// However, we do a good job here, see ForwardStack.Clear below, and BackStack.Clear above about managing that.
if (withAnimation)
{
RootFrame.GoBack();
}
else
{
RootFrame.GoBack(_noAnimation);
}
// Don't store pages we're navigating away from in the Frame cache
// TODO: In the future we probably want a short cache (3-5?) of recent VMs in case the user re-navigates
// back to a recent page they visited (like the Pokedex) so we don't have to reload it from scratch.
// That'd be retrieved as we re-navigate in the PerformCommandMessage logic above
RootFrame.ForwardStack.Clear();
if (!RootFrame.CanGoBack)
{
viewModel.GoHome();
}
if (focusSearch)
{
SearchBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
SearchBox.SelectSearch();
}
}
public void Receive(GoHomeMessage message)
{
_ = DispatcherQueue.TryEnqueue(() => GoHome(withAnimation: message.WithAnimation, focusSearch: message.FocusSearch));
}
private void GoHome(bool withAnimation = true, bool focusSearch = true)
{
while (RootFrame.CanGoBack)
{
// don't focus on each step, just at the end
GoBack(withAnimation, focusSearch: false);
}
// focus search box, even if we were already home
if (focusSearch)
{
SearchBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
SearchBox.SelectSearch();
}
}
public void Receive(ShowToastMessage message) public void Receive(ShowToastMessage message)
{ {
DispatcherQueue.TryEnqueue(() => DispatcherQueue.TryEnqueue(() =>
@@ -242,21 +308,21 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
public void Receive(ShowDetailsMessage message) public void Receive(ShowDetailsMessage message)
{ {
if (ViewModel is not null && if (viewModel is not null &&
ViewModel.CurrentPage is not null) viewModel.CurrentPage is not null)
{ {
if (ViewModel.CurrentPage.PageContext.TryGetTarget(out var pageContext)) if (viewModel.CurrentPage.PageContext.TryGetTarget(out var pageContext))
{ {
Task.Factory.StartNew( Task.Factory.StartNew(
() => () =>
{ {
// TERRIBLE HACK TODO GH #245 // TERRIBLE HACK TODO GH #245
// There's weird wacky bugs with debounce currently. // There's weird wacky bugs with debounce currently.
if (!ViewModel.IsDetailsVisible) if (!viewModel.IsDetailsVisible)
{ {
ViewModel.Details = message.Details; viewModel.Details = message.Details;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
ViewModel.IsDetailsVisible = true; viewModel.IsDetailsVisible = true;
return; return;
} }
@@ -267,15 +333,15 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
_debounceTimer.Debounce( _debounceTimer.Debounce(
() => () =>
{ {
ViewModel.Details = message.Details; viewModel.Details = message.Details;
// Trigger a re-evaluation of whether we have a hero image based on // Trigger a re-evaluation of whether we have a hero image based on
// the current theme // the current theme
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
}, },
interval: TimeSpan.FromMilliseconds(50), interval: TimeSpan.FromMilliseconds(50),
immediate: ViewModel.IsDetailsVisible == false); immediate: viewModel.IsDetailsVisible == false);
ViewModel.IsDetailsVisible = true; viewModel.IsDetailsVisible = true;
}, },
CancellationToken.None, CancellationToken.None,
TaskCreationOptions.None, TaskCreationOptions.None,
@@ -290,8 +356,8 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
private void HideDetails() private void HideDetails()
{ {
ViewModel.Details = null; viewModel.Details = null;
ViewModel.IsDetailsVisible = false; viewModel.IsDetailsVisible = false;
} }
public void Receive(ClearSearchMessage message) => SearchBox.ClearSearch(); public void Receive(ClearSearchMessage message) => SearchBox.ClearSearch();