mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
## Summary This PR refactors CmdPal settings/state to be immutable end-to-end. ### Core changes - Convert model types to immutable records / init-only properties: - `SettingsModel` - `AppStateModel` - `ProviderSettings` - `DockSettings` - `RecentCommandsManager` - supporting settings types (fallback/hotkey/alias/top-level hotkey/history items, etc.) - Replace mutable collections with immutable equivalents where appropriate: - `ImmutableDictionary<,>` - `ImmutableList<>` - Move mutation flow to atomic service updates: - `ISettingsService.UpdateSettings(Func<SettingsModel, SettingsModel>)` - `IAppStateService.UpdateState(Func<AppStateModel, AppStateModel>)` - Update ViewModels/managers/services to use copy-on-write (`with`) patterns instead of in-place mutation. - Update serialization context + tests for immutable model graph compatibility. ## Why Issue #46437 is caused by mutable shared state being updated from different execution paths/threads, leading to race-prone behavior during persistence/serialization. By making settings/app state immutable and using atomic swap/update patterns, we remove in-place mutation and eliminate this class of concurrency bug. ## Validation - Built successfully: - `Microsoft.CmdPal.UI.ViewModels` - `Microsoft.CmdPal.UI` - `Microsoft.CmdPal.UI.ViewModels.UnitTests` - Updated unit tests for immutable update patterns. Fixes #46437 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
35 lines
1.1 KiB
C#
35 lines
1.1 KiB
C#
// 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.
|
|
|
|
using Windows.Foundation;
|
|
|
|
namespace Microsoft.CmdPal.UI.ViewModels.Services;
|
|
|
|
/// <summary>
|
|
/// Manages the lifecycle of <see cref="AppStateModel"/>: load, save, and change notification.
|
|
/// </summary>
|
|
public interface IAppStateService
|
|
{
|
|
/// <summary>
|
|
/// Gets the current application state instance.
|
|
/// </summary>
|
|
AppStateModel State { get; }
|
|
|
|
/// <summary>
|
|
/// Persists the current state to disk and raises <see cref="StateChanged"/>.
|
|
/// </summary>
|
|
void Save();
|
|
|
|
/// <summary>
|
|
/// Atomically applies a transformation to the current state, persists the result,
|
|
/// and raises <see cref="StateChanged"/>.
|
|
/// </summary>
|
|
void UpdateState(Func<AppStateModel, AppStateModel> transform);
|
|
|
|
/// <summary>
|
|
/// Raised after state has been saved to disk.
|
|
/// </summary>
|
|
event TypedEventHandler<IAppStateService, AppStateModel> StateChanged;
|
|
}
|