Compare commits

...

1 Commits

Author SHA1 Message Date
Niels Laute
07eee51a8b Settings: speed up page navigation, fix Advanced Paste double-load
- Enable NavigationCacheMode.Enabled in NavigablePage so pages inheriting it are kept warm by the Frame; re-navigation no longer rebuilds the XAML tree, ViewModel, file watchers and IPC handlers each time.

- Drop EntranceThemeTransition from SettingsCardsAnimations. It replayed on every nav and produced a visible cards-in animation on top of an already slow construction. RepositionThemeTransition is preserved so SettingsExpander expand/collapse stays smooth.

- AdvancedPastePage: stop calling UpdatePasteAIUIVisibility() and UpdateFoundryLocalUIAsync() in the Loaded handler. They only affect controls inside the (hidden) provider configuration dialog, and the Add/Edit handlers already call them right before ShowAsync. Removing the duplicate work eliminates the visible second reflow (the 'double load') and avoids an unnecessary Foundry Local process probe on every nav.

- Guard RefreshEnabledState so dialog-only updates only run while the provider configuration dialog is actually open, preventing duplicate work on IPC general-settings broadcasts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-15 11:43:47 +02:00
3 changed files with 27 additions and 7 deletions

View File

@@ -10,6 +10,7 @@ using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Hosting;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.UI;
namespace Microsoft.PowerToys.Settings.UI.Helpers;
@@ -23,6 +24,10 @@ public abstract partial class NavigablePage : Page
public NavigablePage()
{
// Cache the page instance so re-navigating doesn't rebuild the XAML tree, ViewModel,
// file watchers and IPC handlers each time. The Frame's default CacheSize (10) is
// sufficient to keep all top-level settings pages warm.
NavigationCacheMode = NavigationCacheMode.Enabled;
Loaded += OnPageLoaded;
}

View File

@@ -90,10 +90,9 @@
<tkcontrols:MarkdownConfig x:Key="DescriptionTextMarkdownConfig" Themes="{StaticResource DescriptionTextMarkdownThemeConfig}" />
<TransitionCollection x:Key="SettingsCardsAnimations">
<EntranceThemeTransition FromVerticalOffset="50" />
<!-- Animates cards when loaded -->
<RepositionThemeTransition IsStaggeringEnabled="False" />
<!-- Smoothly animates individual cards upon whenever Expanders are expanded/collapsed -->
<!-- EntranceThemeTransition removed: it replayed on every page navigation, causing a visible "second load" reflow and slowing perceived nav. -->
</TransitionCollection>
</ResourceDictionary>
</Application.Resources>

View File

@@ -30,6 +30,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private CancellationTokenSource _foundryModelLoadCts;
private bool _suppressFoundrySelectionChanged;
private bool _isFoundryLocalAvailable;
private bool _isPasteAIProviderDialogOpen;
private bool _disposed;
private const string PasteAiDialogDefaultTitle = "Paste with AI provider configuration";
@@ -60,11 +61,16 @@ namespace Microsoft.PowerToys.Settings.UI.Views
FoundryLocalPicker.LoadRequested += FoundryLocalPicker_LoadRequested;
}
Loaded += async (s, e) =>
Loaded += (s, e) =>
{
ViewModel.OnPageLoaded();
UpdatePasteAIUIVisibility();
await UpdateFoundryLocalUIAsync();
// Note: UpdatePasteAIUIVisibility() and UpdateFoundryLocalUIAsync() are deliberately
// NOT called here. They only affect controls inside PasteAIProviderConfigurationDialog,
// which is hidden until the user clicks Add/Edit provider. Both Add/Edit handlers call
// them right before ShowAsync(), so running them on every navigation is wasted work
// that produced a visible second reflow ("double load") and, for FoundryLocal, an
// unnecessary process probe.
};
Unloaded += (_, _) =>
@@ -81,8 +87,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
UpdatePasteAIUIVisibility();
_ = UpdateFoundryLocalUIAsync();
// Only refresh the provider-configuration dialog state if it is currently open;
// otherwise this is wasted work (and, for FoundryLocal, an unnecessary process probe)
// that fires every time the runner broadcasts a general-settings update.
if (_isPasteAIProviderDialogOpen)
{
UpdatePasteAIUIVisibility();
_ = UpdateFoundryLocalUIAsync();
}
}
private void EnableAdvancedPasteAI() => ViewModel.EnableAI();
@@ -1116,6 +1129,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
RefreshDialogBindings();
PasteAIApiKeyPasswordBox.Password = string.Empty;
_isPasteAIProviderDialogOpen = true;
await PasteAIProviderConfigurationDialog.ShowAsync();
}
@@ -1143,6 +1157,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
await UpdateFoundryLocalUIAsync();
RefreshDialogBindings();
PasteAIApiKeyPasswordBox.Password = ViewModel.GetPasteAIApiKey(provider.Id, provider.ServiceType);
_isPasteAIProviderDialogOpen = true;
await PasteAIProviderConfigurationDialog.ShowAsync();
}
@@ -1159,6 +1174,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private void PasteAIProviderConfigurationDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args)
{
_isPasteAIProviderDialogOpen = false;
ViewModel?.CancelPasteAIProviderDraft();
PasteAIProviderConfigurationDialog.Title = PasteAiDialogDefaultTitle;
PasteAIApiKeyPasswordBox.Password = string.Empty;