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;
}
public void SetProcessCommand(HWND hwnd, ProcessCommand processCommand)
public void SetProcessCommand(IntPtr hwnd, ProcessCommand processCommand)
{
_hwnd = hwnd;
_hwnd = new HWND(hwnd);
_keyboardListener.SetProcessCommand(processCommand);
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.Messages;
using Microsoft.CommandPalette.UI.Services;
using Microsoft.CommandPalette.UI.Services.Helpers;
using Microsoft.CommandPalette.UI.ViewModels;
using Microsoft.CommandPalette.ViewModels;
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)
{
DispatcherQueue.TryEnqueue(() =>
@@ -242,21 +308,21 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
public void Receive(ShowDetailsMessage message)
{
if (ViewModel is not null &&
ViewModel.CurrentPage is not null)
if (viewModel 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(
() =>
{
// TERRIBLE HACK TODO GH #245
// 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)));
ViewModel.IsDetailsVisible = true;
viewModel.IsDetailsVisible = true;
return;
}
@@ -267,15 +333,15 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
_debounceTimer.Debounce(
() =>
{
ViewModel.Details = message.Details;
viewModel.Details = message.Details;
// Trigger a re-evaluation of whether we have a hero image based on
// the current theme
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(HasHeroImage)));
},
interval: TimeSpan.FromMilliseconds(50),
immediate: ViewModel.IsDetailsVisible == false);
ViewModel.IsDetailsVisible = true;
immediate: viewModel.IsDetailsVisible == false);
viewModel.IsDetailsVisible = true;
},
CancellationToken.None,
TaskCreationOptions.None,
@@ -290,8 +356,8 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
private void HideDetails()
{
ViewModel.Details = null;
ViewModel.IsDetailsVisible = false;
viewModel.Details = null;
viewModel.IsDetailsVisible = false;
}
public void Receive(ClearSearchMessage message) => SearchBox.ClearSearch();