Compare commits

...

4 Commits

Author SHA1 Message Date
Shawn Yuan (from Dev Box)
ca4b52e8c2 update 2026-01-09 12:03:30 +08:00
Shawn Yuan (from Dev Box)
be06f081d1 update 2026-01-09 11:46:10 +08:00
Shawn Yuan (from Dev Box)
7cb41d8fe3 Optimize the module list logic 2026-01-09 11:41:05 +08:00
Shawn Yuan (from Dev Box)
73dda5a08d Fix quickaccess localization issue 2026-01-09 09:38:30 +08:00
6 changed files with 69 additions and 93 deletions

View File

@@ -50,8 +50,8 @@
</ItemGroup>
<ItemGroup>
<PRIResource Include="..\Settings.UI\Strings\en-us\Resources.resw">
<Link>Strings\en-us\Resources.resw</Link>
<PRIResource Include="..\Settings.UI\Strings\**\Resources.resw">
<Link>Strings\%(RecursiveDir)Resources.resw</Link>
</PRIResource>
</ItemGroup>

View File

@@ -10,6 +10,7 @@ using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.QuickAccess.Helpers;
using Microsoft.PowerToys.QuickAccess.Services;
using Microsoft.PowerToys.Settings.UI.Controls;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
@@ -26,6 +27,7 @@ public sealed class AllAppsViewModel : Observable
private readonly SettingsUtils _settingsUtils;
private readonly ResourceLoader _resourceLoader;
private readonly DispatcherQueue _dispatcherQueue;
private readonly List<FlyoutMenuItem> _allFlyoutMenuItems = new();
private GeneralSettings _generalSettings;
public ObservableCollection<FlyoutMenuItem> FlyoutMenuItems { get; }
@@ -58,9 +60,28 @@ public sealed class AllAppsViewModel : Observable
_resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
FlyoutMenuItems = new ObservableCollection<FlyoutMenuItem>();
BuildFlyoutMenuItems();
RefreshFlyoutMenuItems();
}
private void BuildFlyoutMenuItems()
{
_allFlyoutMenuItems.Clear();
foreach (ModuleType moduleType in Enum.GetValues<ModuleType>())
{
if (moduleType == ModuleType.GeneralSettings)
{
continue;
}
_allFlyoutMenuItems.Add(new FlyoutMenuItem
{
Tag = moduleType,
EnabledChangedCallback = EnabledChangedOnUI,
});
}
}
private void OnSettingsChanged(GeneralSettings newSettings)
{
_dispatcherQueue.TryEnqueue(() =>
@@ -82,63 +103,37 @@ public sealed class AllAppsViewModel : Observable
private void RefreshFlyoutMenuItems()
{
var desiredItems = new List<FlyoutMenuItem>();
foreach (ModuleType moduleType in Enum.GetValues<ModuleType>())
foreach (var item in _allFlyoutMenuItems)
{
if (moduleType == ModuleType.GeneralSettings)
{
continue;
}
var moduleType = item.Tag;
var gpo = Helpers.ModuleGpoHelper.GetModuleGpoConfiguration(moduleType);
var isLocked = gpo is GpoRuleConfigured.Enabled or GpoRuleConfigured.Disabled;
var isEnabled = gpo == GpoRuleConfigured.Enabled || (!isLocked && Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetIsModuleEnabled(_generalSettings, moduleType));
var existingItem = FlyoutMenuItems.FirstOrDefault(x => x.Tag == moduleType);
item.Label = _resourceLoader.GetString(Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleLabelResourceName(moduleType));
item.IsLocked = isLocked;
item.Icon = Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleTypeFluentIconName(moduleType);
if (existingItem != null)
if (item.IsEnabled != isEnabled)
{
existingItem.Label = _resourceLoader.GetString(Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleLabelResourceName(moduleType));
existingItem.IsLocked = isLocked;
existingItem.Icon = Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleTypeFluentIconName(moduleType);
if (existingItem.IsEnabled != isEnabled)
{
var callback = existingItem.EnabledChangedCallback;
existingItem.EnabledChangedCallback = null;
existingItem.IsEnabled = isEnabled;
existingItem.EnabledChangedCallback = callback;
}
desiredItems.Add(existingItem);
}
else
{
desiredItems.Add(new FlyoutMenuItem
{
Label = _resourceLoader.GetString(Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleLabelResourceName(moduleType)),
IsEnabled = isEnabled,
IsLocked = isLocked,
Tag = moduleType,
Icon = Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleTypeFluentIconName(moduleType),
EnabledChangedCallback = EnabledChangedOnUI,
});
item.UpdateStatus(isEnabled);
}
}
var sortedItems = DashboardSortOrder switch
{
DashboardSortOrder.ByStatus => desiredItems.OrderByDescending(x => x.IsEnabled).ThenBy(x => x.Label).ToList(),
_ => desiredItems.OrderBy(x => x.Label).ToList(),
DashboardSortOrder.ByStatus => _allFlyoutMenuItems.OrderByDescending(x => x.IsEnabled).ThenBy(x => x.Label).ToList(),
_ => _allFlyoutMenuItems.OrderBy(x => x.Label).ToList(),
};
for (int i = FlyoutMenuItems.Count - 1; i >= 0; i--)
if (FlyoutMenuItems.Count == 0)
{
if (!sortedItems.Contains(FlyoutMenuItems[i]))
foreach (var item in sortedItems)
{
FlyoutMenuItems.RemoveAt(i);
FlyoutMenuItems.Add(item);
}
return;
}
for (int i = 0; i < sortedItems.Count; i++)
@@ -146,20 +141,17 @@ public sealed class AllAppsViewModel : Observable
var item = sortedItems[i];
var oldIndex = FlyoutMenuItems.IndexOf(item);
if (oldIndex < 0)
{
FlyoutMenuItems.Insert(i, item);
}
else if (oldIndex != i)
if (oldIndex != -1 && oldIndex != i)
{
FlyoutMenuItems.Move(oldIndex, i);
}
}
}
private void EnabledChangedOnUI(FlyoutMenuItem item)
private void EnabledChangedOnUI(ModuleListItem item)
{
if (_coordinator.UpdateModuleEnabled(item.Tag, item.IsEnabled))
var flyoutItem = (FlyoutMenuItem)item;
if (_coordinator.UpdateModuleEnabled(flyoutItem.Tag, flyoutItem.IsEnabled))
{
_coordinator.NotifyUserSettingsInteraction();
}

View File

@@ -22,21 +22,6 @@ public sealed class FlyoutMenuItem : ModuleListItem
set => base.Tag = value;
}
public override bool IsEnabled
{
get => base.IsEnabled;
set
{
if (base.IsEnabled != value)
{
base.IsEnabled = value;
EnabledChangedCallback?.Invoke(this);
}
}
}
public Action<FlyoutMenuItem>? EnabledChangedCallback { get; set; }
public bool Visible
{
get => _visible;

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System; // For Action
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
@@ -17,6 +18,22 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
private bool _isLocked;
private object? _tag;
private ICommand? _clickCommand;
private bool _isUpdating;
public Action<ModuleListItem>? EnabledChangedCallback { get; set; }
public void UpdateStatus(bool isEnabled)
{
_isUpdating = true;
try
{
IsEnabled = isEnabled;
}
finally
{
_isUpdating = false;
}
}
public virtual string Label
{
@@ -79,6 +96,11 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
{
_isEnabled = value;
OnPropertyChanged();
if (!_isUpdating)
{
EnabledChangedCallback?.Invoke(this);
}
}
}
}

View File

@@ -26,21 +26,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
set => base.Tag = value;
}
public Action<DashboardListItem> EnabledChangedCallback { get; set; }
public override bool IsEnabled
{
get => base.IsEnabled;
set
{
if (base.IsEnabled != value)
{
base.IsEnabled = value;
EnabledChangedCallback?.Invoke(this);
}
}
}
public bool Visible
{
get => _visible;

View File

@@ -50,7 +50,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
// Flag to prevent circular updates when a UI toggle triggers settings changes.
private bool _isUpdatingFromUI;
private bool _isUpdatingFromSettings;
private AllHotkeyConflictsData _allHotkeyConflictsData = new AllHotkeyConflictsData();
@@ -258,7 +257,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
// Only update if there's an actual change to minimize UI notifications.
if (item.IsEnabled != newEnabledState)
{
item.IsEnabled = newEnabledState;
item.UpdateStatus(newEnabledState);
}
if (item.IsLocked != newLockedState)
@@ -275,19 +274,17 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
/// Sets the _isUpdatingFromUI flag to prevent circular updates, then updates
/// settings, re-sorts if needed, and refreshes dependent collections.
/// </summary>
private void EnabledChangedOnUI(DashboardListItem dashboardListItem)
private void EnabledChangedOnUI(ModuleListItem item)
{
if (_isUpdatingFromSettings)
{
return;
}
var dashboardListItem = (DashboardListItem)item;
var isEnabled = dashboardListItem.IsEnabled;
_isUpdatingFromUI = true;
try
{
Views.ShellPage.UpdateGeneralSettingsCallback(dashboardListItem.Tag, dashboardListItem.IsEnabled);
Views.ShellPage.UpdateGeneralSettingsCallback(dashboardListItem.Tag, isEnabled);
if (dashboardListItem.Tag == ModuleType.NewPlus && dashboardListItem.IsEnabled == true)
if (dashboardListItem.Tag == ModuleType.NewPlus && isEnabled == true)
{
var settingsUtils = SettingsUtils.Default;
var settings = NewPlusViewModel.LoadSettings(settingsUtils);
@@ -325,7 +322,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return;
}
_isUpdatingFromSettings = true;
try
{
RefreshModuleList();
@@ -340,10 +336,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
Logger.LogError($"Updating active/disabled modules list failed: {ex.Message}");
}
finally
{
_isUpdatingFromSettings = false;
}
}
/// <summary>