broken services

This commit is contained in:
Michael Jolley
2025-11-14 16:50:36 -06:00
parent 1884e6abc1
commit 0873dcf341
13 changed files with 126 additions and 132 deletions

View File

@@ -16,7 +16,6 @@ using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Properties; using Microsoft.CmdPal.UI.ViewModels.Properties;
using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.CmdPal.UI.ViewModels.MainPage; namespace Microsoft.CmdPal.UI.ViewModels.MainPage;
@@ -38,8 +37,10 @@ public partial class MainListPage : DynamicListPage,
"com.microsoft.cmdpal.builtin.datetime", "com.microsoft.cmdpal.builtin.datetime",
]; ];
private readonly IServiceProvider _serviceProvider;
private readonly TopLevelCommandManager _tlcManager; private readonly TopLevelCommandManager _tlcManager;
private readonly SettingsModel _settings;
private readonly AliasManager _aliasManager;
private readonly AppStateModel _appState;
private List<Scored<IListItem>>? _filteredItems; private List<Scored<IListItem>>? _filteredItems;
private List<Scored<IListItem>>? _filteredApps; private List<Scored<IListItem>>? _filteredApps;
private List<Scored<IListItem>>? _fallbackItems; private List<Scored<IListItem>>? _fallbackItems;
@@ -53,17 +54,18 @@ public partial class MainListPage : DynamicListPage,
private CancellationTokenSource? _cancellationTokenSource; private CancellationTokenSource? _cancellationTokenSource;
public MainListPage(IServiceProvider serviceProvider) public MainListPage(TopLevelCommandManager topLevelCommandManager, SettingsModel settingsModel, AliasManager aliasManager, AppStateModel appStateModel)
{ {
Title = Resources.builtin_home_name; Title = Resources.builtin_home_name;
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png"); Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder; PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder;
_serviceProvider = serviceProvider;
_tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!; _tlcManager = topLevelCommandManager;
_tlcManager.PropertyChanged += TlcManager_PropertyChanged; _tlcManager.PropertyChanged += TlcManager_PropertyChanged;
_tlcManager.TopLevelCommands.CollectionChanged += Commands_CollectionChanged; _tlcManager.TopLevelCommands.CollectionChanged += Commands_CollectionChanged;
_appState = appStateModel;
// The all apps page will kick off a BG thread to start loading apps. // The all apps page will kick off a BG thread to start loading apps.
// We just want to know when it is done. // We just want to know when it is done.
var allApps = AllAppsCommandProvider.Page; var allApps = AllAppsCommandProvider.Page;
@@ -78,12 +80,13 @@ public partial class MainListPage : DynamicListPage,
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this); WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
WeakReferenceMessenger.Default.Register<UpdateFallbackItemsMessage>(this); WeakReferenceMessenger.Default.Register<UpdateFallbackItemsMessage>(this);
var settings = _serviceProvider.GetService<SettingsModel>()!; _settings = settingsModel;
settings.SettingsChanged += SettingsChangedHandler; _settings.SettingsChanged += SettingsChangedHandler;
HotReloadSettings(settings); HotReloadSettings(_settings);
_includeApps = _tlcManager.IsProviderActive(AllAppsCommandProvider.WellKnownId); _includeApps = _tlcManager.IsProviderActive(AllAppsCommandProvider.WellKnownId);
IsLoading = true; IsLoading = true;
_aliasManager = aliasManager;
} }
private void TlcManager_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) private void TlcManager_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -219,14 +222,12 @@ public partial class MainListPage : DynamicListPage,
// Handle changes to the filter text here // Handle changes to the filter text here
if (!string.IsNullOrEmpty(SearchText)) if (!string.IsNullOrEmpty(SearchText))
{ {
var aliases = _serviceProvider.GetService<AliasManager>()!;
if (token.IsCancellationRequested) if (token.IsCancellationRequested)
{ {
return; return;
} }
if (aliases.CheckAlias(newSearch)) if (_aliasManager.CheckAlias(newSearch))
{ {
if (_filteredItemsIncludesApps != _includeApps) if (_filteredItemsIncludesApps != _includeApps)
{ {
@@ -388,7 +389,7 @@ public partial class MainListPage : DynamicListPage,
} }
} }
var history = _serviceProvider.GetService<AppStateModel>()!.RecentCommands!; var history = _appState.RecentCommands!;
Func<string, IListItem, int> scoreItem = (a, b) => { return ScoreTopLevelItem(a, b, history); }; Func<string, IListItem, int> scoreItem = (a, b) => { return ScoreTopLevelItem(a, b, history); };
// Produce a list of everything that matches the current filter. // Produce a list of everything that matches the current filter.
@@ -483,9 +484,8 @@ public partial class MainListPage : DynamicListPage,
private bool ActuallyLoading() private bool ActuallyLoading()
{ {
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
var allApps = AllAppsCommandProvider.Page; var allApps = AllAppsCommandProvider.Page;
return allApps.IsLoading || tlcManager.IsLoading; return allApps.IsLoading || _tlcManager.IsLoading;
} }
// Almost verbatim ListHelpers.ScoreListItem, but also accounting for the // Almost verbatim ListHelpers.ScoreListItem, but also accounting for the
@@ -580,10 +580,9 @@ public partial class MainListPage : DynamicListPage,
public void UpdateHistory(IListItem topLevelOrAppItem) public void UpdateHistory(IListItem topLevelOrAppItem)
{ {
var id = IdForTopLevelOrAppItem(topLevelOrAppItem); var id = IdForTopLevelOrAppItem(topLevelOrAppItem);
var state = _serviceProvider.GetService<AppStateModel>()!; var history = _appState.RecentCommands;
var history = state.RecentCommands;
history.AddHistoryItem(id); history.AddHistoryItem(id);
AppStateModel.SaveState(state); AppStateModel.SaveState(_appState);
} }
private static string IdForTopLevelOrAppItem(IListItem topLevelOrAppItem) private static string IdForTopLevelOrAppItem(IListItem topLevelOrAppItem)
@@ -615,10 +614,9 @@ public partial class MainListPage : DynamicListPage,
_tlcManager.PropertyChanged -= TlcManager_PropertyChanged; _tlcManager.PropertyChanged -= TlcManager_PropertyChanged;
_tlcManager.TopLevelCommands.CollectionChanged -= Commands_CollectionChanged; _tlcManager.TopLevelCommands.CollectionChanged -= Commands_CollectionChanged;
var settings = _serviceProvider.GetService<SettingsModel>(); if (_settings is not null)
if (settings is not null)
{ {
settings.SettingsChanged -= SettingsChangedHandler; _settings.SettingsChanged -= SettingsChangedHandler;
} }
WeakReferenceMessenger.Default.UnregisterAll(this); WeakReferenceMessenger.Default.UnregisterAll(this);

View File

@@ -9,16 +9,14 @@ using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CmdPal.Core.ViewModels; using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Properties; using Microsoft.CmdPal.UI.ViewModels.Properties;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.CmdPal.UI.ViewModels; namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ProviderSettingsViewModel( public partial class ProviderSettingsViewModel(
CommandProviderWrapper _provider, CommandProviderWrapper _provider,
ProviderSettings _providerSettings, ProviderSettings _providerSettings,
IServiceProvider _serviceProvider) : ObservableObject SettingsModel _settings) : ObservableObject
{ {
private readonly SettingsModel _settings = _serviceProvider.GetService<SettingsModel>()!;
private readonly Lock _initializeSettingsLock = new(); private readonly Lock _initializeSettingsLock = new();
private Task? _initializeSettingsTask; private Task? _initializeSettingsTask;

View File

@@ -5,14 +5,13 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using Microsoft.CmdPal.UI.ViewModels.Settings; using Microsoft.CmdPal.UI.ViewModels.Settings;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.CmdPal.UI.ViewModels; namespace Microsoft.CmdPal.UI.ViewModels;
public partial class SettingsViewModel : INotifyPropertyChanged public partial class SettingsViewModel : INotifyPropertyChanged
{ {
private readonly SettingsModel _settings; private readonly SettingsModel _settings;
private readonly IServiceProvider _serviceProvider; private readonly TopLevelCommandManager _tlcManager;
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
@@ -142,10 +141,10 @@ public partial class SettingsViewModel : INotifyPropertyChanged
public SettingsExtensionsViewModel Extensions { get; } public SettingsExtensionsViewModel Extensions { get; }
public SettingsViewModel(SettingsModel settings, IServiceProvider serviceProvider, TaskScheduler scheduler) public SettingsViewModel(SettingsModel settings, TaskScheduler scheduler, TopLevelCommandManager topLevelCommandManager)
{ {
_settings = settings; _settings = settings;
_serviceProvider = serviceProvider; _tlcManager = topLevelCommandManager;
var activeProviders = GetCommandProviders(); var activeProviders = GetCommandProviders();
var allProviderSettings = _settings.ProviderSettings; var allProviderSettings = _settings.ProviderSettings;
@@ -154,7 +153,7 @@ public partial class SettingsViewModel : INotifyPropertyChanged
{ {
var providerSettings = settings.GetProviderSettings(item); var providerSettings = settings.GetProviderSettings(item);
var settingsModel = new ProviderSettingsViewModel(item, providerSettings, _serviceProvider); var settingsModel = new ProviderSettingsViewModel(item, providerSettings, _settings);
CommandProviders.Add(settingsModel); CommandProviders.Add(settingsModel);
} }
@@ -163,8 +162,7 @@ public partial class SettingsViewModel : INotifyPropertyChanged
private IEnumerable<CommandProviderWrapper> GetCommandProviders() private IEnumerable<CommandProviderWrapper> GetCommandProviders()
{ {
var manager = _serviceProvider.GetService<TopLevelCommandManager>()!; var allProviders = _tlcManager.CommandProviders;
var allProviders = manager.CommandProviders;
return allProviders; return allProviders;
} }

View File

@@ -23,6 +23,8 @@ using Microsoft.CmdPal.Ext.WindowsTerminal;
using Microsoft.CmdPal.Ext.WindowWalker; using Microsoft.CmdPal.Ext.WindowWalker;
using Microsoft.CmdPal.Ext.WinGet; using Microsoft.CmdPal.Ext.WinGet;
using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.Helpers;
using Microsoft.CmdPal.UI.Pages;
using Microsoft.CmdPal.UI.Settings;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.BuiltinCommands; using Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
using Microsoft.CmdPal.UI.ViewModels.Models; using Microsoft.CmdPal.UI.ViewModels.Models;
@@ -51,10 +53,7 @@ public partial class App : Application
public ETWTrace EtwTrace { get; private set; } = new ETWTrace(); public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
/// <summary> private readonly ServiceProvider _services;
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="App"/> class. /// Initializes a new instance of the <see cref="App"/> class.
@@ -67,7 +66,7 @@ public partial class App : Application
_globalErrorHandler.Register(this); _globalErrorHandler.Register(this);
#endif #endif
Services = ConfigureServices(); _services = ConfigureServices();
this.InitializeComponent(); this.InitializeComponent();
@@ -94,7 +93,7 @@ public partial class App : Application
/// <param name="args">Details about the launch request and process.</param> /// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{ {
AppWindow = new MainWindow(); AppWindow = _services.GetRequiredService<MainWindow>();
var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs(); var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
((MainWindow)AppWindow).HandleLaunchNonUI(activatedEventArgs); ((MainWindow)AppWindow).HandleLaunchNonUI(activatedEventArgs);
@@ -110,6 +109,10 @@ public partial class App : Application
// Root services // Root services
services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext()); services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext());
services.AddSingleton<IAppHostService, PowerToysAppHostService>();
services.AddSingleton<ITelemetryService, TelemetryForwarder>();
// TODO: Register ILogger
// Built-in Commands. Order matters - this is the order they'll be presented by default. // Built-in Commands. Order matters - this is the order they'll be presented by default.
var allApps = new AllAppsCommandProvider(); var allApps = new AllAppsCommandProvider();
@@ -152,26 +155,35 @@ public partial class App : Application
services.AddSingleton<ICommandProvider, TimeDateCommandsProvider>(); services.AddSingleton<ICommandProvider, TimeDateCommandsProvider>();
services.AddSingleton<ICommandProvider, SystemCommandExtensionProvider>(); services.AddSingleton<ICommandProvider, SystemCommandExtensionProvider>();
// Models // Settings & state
services.AddSingleton<TopLevelCommandManager>();
services.AddSingleton<AliasManager>();
services.AddSingleton<HotkeyManager>();
var sm = SettingsModel.LoadSettings(); var sm = SettingsModel.LoadSettings();
services.AddSingleton(sm); services.AddSingleton(sm);
var state = AppStateModel.LoadState(); var state = AppStateModel.LoadState();
services.AddSingleton(state); services.AddSingleton(state);
// Services
services.AddSingleton<TopLevelCommandManager>();
services.AddSingleton<AliasManager>();
services.AddSingleton<HotkeyManager>();
services.AddSingleton<IExtensionService, ExtensionService>(); services.AddSingleton<IExtensionService, ExtensionService>();
services.AddSingleton<TrayIconService>(); services.AddSingleton<TrayIconService>();
services.AddSingleton<IRunHistoryService, RunHistoryService>(); services.AddSingleton<IRunHistoryService, RunHistoryService>();
services.AddSingleton<IRootPageService, PowerToysRootPageService>();
services.AddSingleton<IAppHostService, PowerToysAppHostService>();
services.AddSingleton<ITelemetryService, TelemetryForwarder>();
// ViewModels // ViewModels
services.AddSingleton<ShellViewModel>(); services.AddSingleton<ShellViewModel>();
services.AddSingleton<SettingsViewModel>();
services.AddSingleton<IPageViewModelFactoryService, CommandPalettePageViewModelFactory>(); services.AddSingleton<IPageViewModelFactoryService, CommandPalettePageViewModelFactory>();
// Views
services.AddSingleton<IRootPageService, PowerToysRootPageService>();
services.AddSingleton<MainWindow>();
services.AddSingleton<ShellPage>();
services.AddTransient<ListPage>();
services.AddTransient<GeneralPage>();
services.AddTransient<ExtensionPage>();
services.AddTransient<ExtensionsPage>();
return services.BuildServiceProvider(); return services.BuildServiceProvider();
} }
} }

View File

@@ -11,7 +11,6 @@ using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.Helpers;
using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.Messages;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Controls.Primitives;
@@ -31,6 +30,7 @@ public sealed partial class ListPage : Page,
IRecipient<ActivateSelectedListItemMessage>, IRecipient<ActivateSelectedListItemMessage>,
IRecipient<ActivateSecondaryCommandMessage> IRecipient<ActivateSecondaryCommandMessage>
{ {
private readonly SettingsModel _settings;
private InputSource _lastInputSource; private InputSource _lastInputSource;
internal ListViewModel? ViewModel internal ListViewModel? ViewModel
@@ -51,9 +51,11 @@ public sealed partial class ListPage : Page,
} }
} }
public ListPage() public ListPage(SettingsModel settings)
{ {
this.InitializeComponent(); this.InitializeComponent();
_settings = settings;
this.NavigationCacheMode = NavigationCacheMode.Disabled; this.NavigationCacheMode = NavigationCacheMode.Disabled;
this.ItemView.Loaded += Items_Loaded; this.ItemView.Loaded += Items_Loaded;
this.ItemView.PreviewKeyDown += Items_PreviewKeyDown; this.ItemView.PreviewKeyDown += Items_PreviewKeyDown;
@@ -133,8 +135,7 @@ public sealed partial class ListPage : Page,
return; return;
} }
var settings = App.Current.Services.GetService<SettingsModel>()!; if (_settings.SingleClickActivates)
if (settings.SingleClickActivates)
{ {
ViewModel?.InvokeItemCommand.Execute(item); ViewModel?.InvokeItemCommand.Execute(item);
} }
@@ -150,8 +151,7 @@ public sealed partial class ListPage : Page,
{ {
if (ItemView.SelectedItem is ListItemViewModel vm) if (ItemView.SelectedItem is ListItemViewModel vm)
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!; if (!_settings.SingleClickActivates)
if (!settings.SingleClickActivates)
{ {
ViewModel?.InvokeItemCommand.Execute(vm); ViewModel?.InvokeItemCommand.Execute(vm);
} }

View File

@@ -20,7 +20,7 @@ namespace Microsoft.CmdPal.UI.Helpers;
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_*")] [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_*")]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_*")] [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_*")]
internal sealed partial class TrayIconService public sealed partial class TrayIconService
{ {
private const uint MY_NOTIFY_ID = 1000; private const uint MY_NOTIFY_ID = 1000;
private const uint WM_TRAY_ICON = PInvoke.WM_USER + 1; private const uint WM_TRAY_ICON = PInvoke.WM_USER + 1;

View File

@@ -13,6 +13,6 @@
MinHeight="240" MinHeight="240"
Activated="MainWindow_Activated" Activated="MainWindow_Activated"
Closed="MainWindow_Closed" Closed="MainWindow_Closed"
x:Name="Window"
mc:Ignorable="d"> mc:Ignorable="d">
<pages:ShellPage x:Name="RootShellPage" />
</winuiex:WindowEx> </winuiex:WindowEx>

View File

@@ -14,9 +14,9 @@ using Microsoft.CmdPal.Ext.ClipboardHistory.Messages;
using Microsoft.CmdPal.UI.Events; using Microsoft.CmdPal.UI.Events;
using Microsoft.CmdPal.UI.Helpers; using Microsoft.CmdPal.UI.Helpers;
using Microsoft.CmdPal.UI.Messages; using Microsoft.CmdPal.UI.Messages;
using Microsoft.CmdPal.UI.Pages;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerToys.Telemetry; using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Composition; using Microsoft.UI.Composition;
using Microsoft.UI.Composition.SystemBackdrops; using Microsoft.UI.Composition.SystemBackdrops;
@@ -58,6 +58,10 @@ public sealed partial class MainWindow : WindowEx,
private readonly KeyboardListener _keyboardListener; private readonly KeyboardListener _keyboardListener;
private readonly LocalKeyboardListener _localKeyboardListener; private readonly LocalKeyboardListener _localKeyboardListener;
private readonly HiddenOwnerWindowBehavior _hiddenOwnerBehavior = new(); private readonly HiddenOwnerWindowBehavior _hiddenOwnerBehavior = new();
private readonly SettingsModel _settings;
private readonly TrayIconService _trayIconService;
private readonly IExtensionService _extensionService;
private readonly ShellPage _rootShellPage;
private bool _ignoreHotKeyWhenFullScreen = true; private bool _ignoreHotKeyWhenFullScreen = true;
private DesktopAcrylicController? _acrylicController; private DesktopAcrylicController? _acrylicController;
@@ -65,10 +69,17 @@ public sealed partial class MainWindow : WindowEx,
private WindowPosition _currentWindowPosition = new(); private WindowPosition _currentWindowPosition = new();
public MainWindow() public MainWindow(SettingsModel settingsModel, TrayIconService trayIconService, IExtensionService extensionService, ShellPage shellPage)
{ {
InitializeComponent(); InitializeComponent();
_settings = settingsModel;
_trayIconService = trayIconService;
_extensionService = extensionService;
_rootShellPage = shellPage;
Window.WindowContent = _rootShellPage;
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32()); _hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
unsafe unsafe
@@ -102,7 +113,7 @@ public sealed partial class MainWindow : WindowEx,
ExtendsContentIntoTitleBar = true; ExtendsContentIntoTitleBar = true;
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed; AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed;
SizeChanged += WindowSizeChanged; SizeChanged += WindowSizeChanged;
RootShellPage.Loaded += RootShellPage_Loaded; _rootShellPage.Loaded += RootShellPage_Loaded;
WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated"); WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated");
@@ -116,10 +127,10 @@ public sealed partial class MainWindow : WindowEx,
// Load our settings, and then also wire up a settings changed handler // Load our settings, and then also wire up a settings changed handler
HotReloadSettings(); HotReloadSettings();
App.Current.Services.GetService<SettingsModel>()!.SettingsChanged += SettingsChangedHandler; _settings.SettingsChanged += SettingsChangedHandler;
// Make sure that we update the acrylic theme when the OS theme changes // Make sure that we update the acrylic theme when the OS theme changes
RootShellPage.ActualThemeChanged += (s, e) => DispatcherQueue.TryEnqueue(UpdateAcrylic); _rootShellPage.ActualThemeChanged += (s, e) => DispatcherQueue.TryEnqueue(UpdateAcrylic);
// Hardcoding event name to avoid bringing in the PowerToys.interop dependency. Event name must match CMDPAL_SHOW_EVENT from shared_constants.h // Hardcoding event name to avoid bringing in the PowerToys.interop dependency. Event name must match CMDPAL_SHOW_EVENT from shared_constants.h
NativeEventWaiter.WaitForEventLoop("Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a", () => NativeEventWaiter.WaitForEventLoop("Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a", () =>
@@ -160,8 +171,7 @@ public sealed partial class MainWindow : WindowEx,
private void RestoreWindowPosition() private void RestoreWindowPosition()
{ {
var settings = App.Current.Services.GetService<SettingsModel>(); if (_settings.LastWindowPosition is not WindowPosition savedPosition)
if (settings?.LastWindowPosition is not WindowPosition savedPosition)
{ {
PositionCentered(); PositionCentered();
return; return;
@@ -218,12 +228,10 @@ public sealed partial class MainWindow : WindowEx,
private void HotReloadSettings() private void HotReloadSettings()
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!; SetupHotkey(_settings);
_trayIconService.SetupTrayIcon(_settings.ShowSystemTrayIcon);
SetupHotkey(settings); _ignoreHotKeyWhenFullScreen = _settings.IgnoreShortcutWhenFullscreen;
App.Current.Services.GetService<TrayIconService>()!.SetupTrayIcon(settings.ShowSystemTrayIcon);
_ignoreHotKeyWhenFullScreen = settings.IgnoreShortcutWhenFullscreen;
} }
// We want to use DesktopAcrylicKind.Thin and custom colors as this is the default material // We want to use DesktopAcrylicKind.Thin and custom colors as this is the default material
@@ -378,9 +386,7 @@ public sealed partial class MainWindow : WindowEx,
public void Receive(ShowWindowMessage message) public void Receive(ShowWindowMessage message)
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!; ShowHwnd(message.Hwnd, _settings.SummonOn);
ShowHwnd(message.Hwnd, settings.SummonOn);
} }
public void Receive(HideWindowMessage message) public void Receive(HideWindowMessage message)
@@ -467,13 +473,11 @@ public sealed partial class MainWindow : WindowEx,
internal void MainWindow_Closed(object sender, WindowEventArgs args) internal void MainWindow_Closed(object sender, WindowEventArgs args)
{ {
var serviceProvider = App.Current.Services;
UpdateWindowPositionInMemory(); UpdateWindowPositionInMemory();
var settings = serviceProvider.GetService<SettingsModel>(); if (_settings is not null)
if (settings is not null)
{ {
settings.LastWindowPosition = new WindowPosition _settings.LastWindowPosition = new WindowPosition
{ {
X = _currentWindowPosition.X, X = _currentWindowPosition.X,
Y = _currentWindowPosition.Y, Y = _currentWindowPosition.Y,
@@ -481,13 +485,12 @@ public sealed partial class MainWindow : WindowEx,
Height = _currentWindowPosition.Height, Height = _currentWindowPosition.Height,
}; };
SettingsModel.SaveSettings(settings); SettingsModel.SaveSettings(_settings);
} }
var extensionService = serviceProvider.GetService<IExtensionService>()!; _extensionService.SignalStopExtensionsAsync();
extensionService.SignalStopExtensionsAsync();
App.Current.Services.GetService<TrayIconService>()!.Destroy(); _trayIconService.Destroy();
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592). // WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
// Workaround by turning it off before shutdown. // Workaround by turning it off before shutdown.
@@ -513,28 +516,28 @@ public sealed partial class MainWindow : WindowEx,
private void UpdateRegionsForCustomTitleBar() private void UpdateRegionsForCustomTitleBar()
{ {
// Specify the interactive regions of the title bar. // Specify the interactive regions of the title bar.
var scaleAdjustment = RootShellPage.XamlRoot.RasterizationScale; var scaleAdjustment = _rootShellPage.XamlRoot.RasterizationScale;
// Get the rectangle around our XAML content. We're going to mark this // Get the rectangle around our XAML content. We're going to mark this
// rectangle as "Passthrough", so that the normal window operations // rectangle as "Passthrough", so that the normal window operations
// (resizing, dragging) don't apply in this space. // (resizing, dragging) don't apply in this space.
var transform = RootShellPage.TransformToVisual(null); var transform = _rootShellPage.TransformToVisual(null);
// Reserve 16px of space at the top for dragging. // Reserve 16px of space at the top for dragging.
var topHeight = 16; var topHeight = 16;
var bounds = transform.TransformBounds(new Rect( var bounds = transform.TransformBounds(new Rect(
0, 0,
topHeight, topHeight,
RootShellPage.ActualWidth, _rootShellPage.ActualWidth,
RootShellPage.ActualHeight)); _rootShellPage.ActualHeight));
var contentRect = GetRect(bounds, scaleAdjustment); var contentRect = GetRect(bounds, scaleAdjustment);
var rectArray = new RectInt32[] { contentRect }; var rectArray = new RectInt32[] { contentRect };
var nonClientInputSrc = InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id); var nonClientInputSrc = InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id);
nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray); nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray);
// Add a drag-able region on top // Add a drag-able region on top
var w = RootShellPage.ActualWidth; var w = _rootShellPage.ActualWidth;
_ = RootShellPage.ActualHeight; _ = _rootShellPage.ActualHeight;
var dragSides = new RectInt32[] var dragSides = new RectInt32[]
{ {
GetRect(new Rect(0, 0, w, topHeight), scaleAdjustment), // the top, {topHeight=16} tall GetRect(new Rect(0, 0, w, topHeight), scaleAdjustment), // the top, {topHeight=16} tall
@@ -624,8 +627,7 @@ public sealed partial class MainWindow : WindowEx,
} }
else if (uri.StartsWith("x-cmdpal://reload", StringComparison.OrdinalIgnoreCase)) else if (uri.StartsWith("x-cmdpal://reload", StringComparison.OrdinalIgnoreCase))
{ {
var settings = App.Current.Services.GetService<SettingsModel>(); if (_settings.AllowExternalReload == true)
if (settings?.AllowExternalReload == true)
{ {
Logger.LogInfo("External Reload triggered"); Logger.LogInfo("External Reload triggered");
WeakReferenceMessenger.Default.Send<ReloadCommandsMessage>(new()); WeakReferenceMessenger.Default.Send<ReloadCommandsMessage>(new());

View File

@@ -16,12 +16,10 @@ using Microsoft.CmdPal.UI.Messages;
using Microsoft.CmdPal.UI.Settings; using Microsoft.CmdPal.UI.Settings;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerToys.Telemetry; using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching; using Microsoft.UI.Dispatching;
using Microsoft.UI.Input; using Microsoft.UI.Input;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Media.Animation;
@@ -62,6 +60,9 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
private readonly ToastWindow _toast = new(); private readonly ToastWindow _toast = new();
private readonly SettingsModel _settings;
private readonly TopLevelCommandManager tlcManager;
private readonly CompositeFormat _pageNavigatedAnnouncement; private readonly CompositeFormat _pageNavigatedAnnouncement;
private SettingsWindow? _settingsWindow; private SettingsWindow? _settingsWindow;
@@ -69,14 +70,18 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
private CancellationTokenSource? _focusAfterLoadedCts; private CancellationTokenSource? _focusAfterLoadedCts;
private WeakReference<Page>? _lastNavigatedPageRef; private WeakReference<Page>? _lastNavigatedPageRef;
public ShellViewModel ViewModel { get; private set; } = App.Current.Services.GetService<ShellViewModel>()!; public ShellViewModel ViewModel { get; private set; }
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
public ShellPage() public ShellPage(ShellViewModel shellViewModel, SettingsModel settingsModel, TopLevelCommandManager topLevelCommandManager)
{ {
this.InitializeComponent(); this.InitializeComponent();
ViewModel = shellViewModel;
_settings = settingsModel;
tlcManager = topLevelCommandManager;
// how we are doing navigation around // how we are doing navigation around
WeakReferenceMessenger.Default.Register<NavigateBackMessage>(this); WeakReferenceMessenger.Default.Register<NavigateBackMessage>(this);
WeakReferenceMessenger.Default.Register<OpenSettingsMessage>(this); WeakReferenceMessenger.Default.Register<OpenSettingsMessage>(this);
@@ -112,19 +117,16 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
{ {
get get
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!; return _settings.DisableAnimations ? _noAnimation : _slideRightTransition;
return settings.DisableAnimations ? _noAnimation : _slideRightTransition;
} }
} }
public void Receive(NavigateBackMessage message) public void Receive(NavigateBackMessage message)
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!;
if (RootFrame.CanGoBack) if (RootFrame.CanGoBack)
{ {
if (!message.FromBackspace || if (!message.FromBackspace ||
settings.BackspaceGoesBack) _settings.BackspaceGoesBack)
{ {
GoBack(); GoBack();
} }
@@ -335,7 +337,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
private void SummonOnUiThread(HotkeySummonMessage message) private void SummonOnUiThread(HotkeySummonMessage message)
{ {
var settings = App.Current.Services.GetService<SettingsModel>()!;
var commandId = message.CommandId; var commandId = message.CommandId;
var isRoot = string.IsNullOrEmpty(commandId); var isRoot = string.IsNullOrEmpty(commandId);
if (isRoot) if (isRoot)
@@ -346,11 +347,11 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
// Depending on the settings, either // Depending on the settings, either
// * Go home, or // * Go home, or
// * Select the search text (if we should remain open on this page) // * Select the search text (if we should remain open on this page)
if (settings.HotkeyGoesHome) if (_settings.HotkeyGoesHome)
{ {
GoHome(false); GoHome(false);
} }
else if (settings.HighlightSearchOnActivate) else if (_settings.HighlightSearchOnActivate)
{ {
SearchBox.SelectSearch(); SearchBox.SelectSearch();
} }
@@ -361,7 +362,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
{ {
// For a hotkey bound to a command, first lookup the // For a hotkey bound to a command, first lookup the
// command from our list of top level commands. // command from our list of top level commands.
var tlcManager = App.Current.Services.GetService<TopLevelCommandManager>()!;
var topLevelCommand = tlcManager.LookupCommand(commandId); var topLevelCommand = tlcManager.LookupCommand(commandId);
if (topLevelCommand is not null) if (topLevelCommand is not null)
{ {

View File

@@ -10,7 +10,6 @@ using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.MainPage; using Microsoft.CmdPal.UI.ViewModels.MainPage;
using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
using WinRT; using WinRT;
// To learn more about WinUI, the WinUI project structure, // To learn more about WinUI, the WinUI project structure,
@@ -19,24 +18,23 @@ namespace Microsoft.CmdPal.UI;
internal sealed class PowerToysRootPageService : IRootPageService internal sealed class PowerToysRootPageService : IRootPageService
{ {
private readonly IServiceProvider _serviceProvider; private readonly TopLevelCommandManager _topLevelCommandManager;
private IExtensionWrapper? _activeExtension; private IExtensionWrapper? _activeExtension;
private Lazy<MainListPage> _mainListPage; private Lazy<MainListPage> _mainListPage;
public PowerToysRootPageService(IServiceProvider serviceProvider) public PowerToysRootPageService(TopLevelCommandManager topLevelCommandManager, SettingsModel settingsModel, AliasManager aliasManager, AppStateModel appStateModel)
{ {
_serviceProvider = serviceProvider; _topLevelCommandManager = topLevelCommandManager;
_mainListPage = new Lazy<MainListPage>(() => _mainListPage = new Lazy<MainListPage>(() =>
{ {
return new MainListPage(_serviceProvider); return new MainListPage(_topLevelCommandManager, settingsModel, aliasManager, appStateModel);
}); });
} }
public async Task PreLoadAsync() public async Task PreLoadAsync()
{ {
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!; await _topLevelCommandManager.LoadBuiltinsAsync();
await tlcManager.LoadBuiltinsAsync();
} }
public Microsoft.CommandPalette.Extensions.IPage GetRootPage() public Microsoft.CommandPalette.Extensions.IPage GetRootPage()
@@ -46,13 +44,11 @@ internal sealed class PowerToysRootPageService : IRootPageService
public async Task PostLoadRootPageAsync() public async Task PostLoadRootPageAsync()
{ {
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
// After loading built-ins, and starting navigation, kick off a thread to load extensions. // After loading built-ins, and starting navigation, kick off a thread to load extensions.
tlcManager.LoadExtensionsCommand.Execute(null); _topLevelCommandManager.LoadExtensionsCommand.Execute(null);
await tlcManager.LoadExtensionsCommand.ExecutionTask!; await _topLevelCommandManager.LoadExtensionsCommand.ExecutionTask!;
if (tlcManager.LoadExtensionsCommand.ExecutionTask.Status != TaskStatus.RanToCompletion) if (_topLevelCommandManager.LoadExtensionsCommand.ExecutionTask.Status != TaskStatus.RanToCompletion)
{ {
// TODO: Handle failure case // TODO: Handle failure case
} }

View File

@@ -10,8 +10,6 @@ namespace Microsoft.CmdPal.UI.Settings;
public sealed partial class ExtensionPage : Page public sealed partial class ExtensionPage : Page
{ {
private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
public ProviderSettingsViewModel? ViewModel { get; private set; } public ProviderSettingsViewModel? ViewModel { get; private set; }
public ExtensionPage() public ExtensionPage()

View File

@@ -5,7 +5,6 @@
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Controls; using CommunityToolkit.WinUI.Controls;
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Input;
@@ -14,16 +13,13 @@ namespace Microsoft.CmdPal.UI.Settings;
public sealed partial class ExtensionsPage : Page public sealed partial class ExtensionsPage : Page
{ {
private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly SettingsViewModel? viewModel; private readonly SettingsViewModel? viewModel;
public ExtensionsPage() public ExtensionsPage(SettingsViewModel settingsViewModel)
{ {
this.InitializeComponent(); this.InitializeComponent();
var settings = App.Current.Services.GetService<SettingsModel>()!; viewModel = settingsViewModel;
viewModel = new SettingsViewModel(settings, App.Current.Services, _mainTaskScheduler);
} }
private void SettingsCard_Click(object sender, RoutedEventArgs e) private void SettingsCard_Click(object sender, RoutedEventArgs e)

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Windows.ApplicationModel; using Windows.ApplicationModel;
@@ -11,16 +10,13 @@ namespace Microsoft.CmdPal.UI.Settings;
public sealed partial class GeneralPage : Page public sealed partial class GeneralPage : Page
{ {
private readonly TaskScheduler _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly SettingsViewModel? viewModel; private readonly SettingsViewModel? viewModel;
public GeneralPage() public GeneralPage(SettingsViewModel settings, TopLevelCommandManager topLevelCommandManager)
{ {
this.InitializeComponent(); this.InitializeComponent();
var settings = App.Current.Services.GetService<SettingsModel>()!; viewModel = settings;
viewModel = new SettingsViewModel(settings, App.Current.Services, _mainTaskScheduler);
} }
public string ApplicationVersion public string ApplicationVersion