[DevDocs] More content and restructure (#40165)

## Summary of the Pull Request
Accumulated information from internal transition about the modules
development, and reworked it to be added in dev docs. Also the dev docs
intself was restructured to be more organized. New pages was
verified by transition team.

## PR Checklist
- [x] **Dev docs:** Added/updated

---------

Co-authored-by: Zhaopeng Wang (from Dev Box) <zhaopengwang@microsoft.com>
Co-authored-by: Hao Liu <liuhao3418@gmail.com>
Co-authored-by: Peiyao Zhao <105847726+zhaopy536@users.noreply.github.com>
Co-authored-by: Mengyuan <162882040+chenmy77@users.noreply.github.com>
Co-authored-by: zhaopeng wang <33367956+wang563681252@users.noreply.github.com>
Co-authored-by: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com>
This commit is contained in:
Gleb Khmyznikov
2025-07-01 14:27:34 +02:00
committed by GitHub
parent 9c2e83d6eb
commit 725535b760
102 changed files with 5361 additions and 325 deletions

View File

@@ -0,0 +1,15 @@
# Communication with modules
## Through runner
- The settings process communicates changes in the UI to most modules using the runner through delegates.
- More details on this are mentioned in [`runner-ipc.md`](runner-ipc.md).
## PT Run
- Any changes to the UI are saved by the settings process in the `settings.json` file located within the `/Local/Microsoft/PowerToys/Launcher/` folder.
- PT Run watches for any changes within this file and updates its general settings or propagates the information to the plugins, depending on the type of information.
Eg: The maximum number of results drop down updates the maximum number of rows in the results list which updates the general settings of PT Run whereas the drive detection checkbox details are dispatched to the indexer plugin.
## Keyboard Manager
- The Settings process and keyboard manager share access to a common `default.json` file which contains information about the remapped keys and shortcuts.
- To ensure that there is no contention while both processes try to access the common file, there is a named file mutex.
- The settings process expects the keyboard manager process to create the `default.json` file if it does not exist. It does not create the file in case it is not present.

View File

@@ -0,0 +1,12 @@
# Compatibility with legacy settings and runner
The following must be kept in mind regarding compatibility with settings v1 and runner.
### 1. Folder Naming structure
- Each of the modules has a folder within the `Local/Microsoft/PowerToys` directory which contains the module configurations within the `settings.json` file. The name of this folder must be the same across settingsv1 and settingsv2.
- The name of the settings folder for each powertoy is the same as the `ModuleName`. It is set within each of the viewModel files. This name must not be changed to ensure that the user configurations for each of the powertoys rolls over on update.
### 2. Communication with runner
- The status of each of the modules is communicated with the runner in the form of a json object. The names of all the powerToys is set in the [`EnableModules.cs`](src/settings-ui/Settings.UI.Library/EnabledModules.cs) file. The `JsonPropertyName` must not be changed to ensure that the information is dispatched properly to all the modules by the runner.
### ImageResizer anomaly
All the powertoys have the same folder name as well as JsonPropertyName to communicate information with the runner. However that is not the case with ImageResizer. The folder name is `ImageResizer` whereas the JsonPropertyName is `Image Resizer`(Note the additional space). This should not be changed to ensure backward compatibility as well as proper functioning of the module.

View File

@@ -0,0 +1,98 @@
# What is it
We would like to enable our users to use [`winget configure`](https://learn.microsoft.com/en-us/windows/package-manager/winget/configure) command to install PowerToys and configure its settings with a [Winget configuration file](https://learn.microsoft.com/en-us/windows/package-manager/configuration/create). For example:
```yaml
properties:
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Install PowerToys
allowPrerelease: true
settings:
id: PowerToys (Preview)
source: winget
- resource: PowerToysConfigure
directives:
description: Configure PowerToys
settings:
ShortcutGuide:
Enabled: false
OverlayOpacity: 1
FancyZones:
Enabled: true
FancyzonesEditorHotkey: "Shift+Ctrl+Alt+F"
configurationVersion: 0.2.0
```
This should install PowerToys and make `PowerToysConfigure` resource available. We can use it in the same file.
# How it works
`PowerToysConfigure` is a [class-based DSC resource](https://learn.microsoft.com/en-us/powershell/dsc/concepts/class-based-resources?view=dsc-2.0). It looks up whether each setting was specified or not by checking whether it's `$null` or `0` for `enum`s and invokes `PowerToys.Settings.exe` with the updated value like so:
```
PowerToys.Settings.exe set <ModuleName>.<SettingName> <SettingValue>
```
So for the example the config above should perform 3 following invocations:
```
PowerToys.Settings.exe set ShortcutGuide.Enabled false
PowerToys.Settings.exe set FancyZones.Enabled true
PowerToys.Settings.exe set FancyZones.FancyzonesEditorHotkey "Shift+Ctrl+Alt+F"
```
`PowerToys.Settings` uses dotnet reflection capabilities to determine `SettingName` type and tries to convert the supplied `SettingValue` string accordingly. We use `ICmdReprParsable` for custom setting types.
# How DSC is implemented
We use `PowerToys.Settings.DSC.Schema.Generator` to generate the bulk of `PowerToysConfigure.psm1` and `PowerToysConfigure.psd1` files. It also uses dotnet reflection capabilities to inspect `PowerToys.Settings.UI.Lib.dll` assembly and generate properties for the modules we have. The actual generation is done as a `PowerToys.Settings.DSC.Schema.Generator.csproj` post-build action.
# Debugging DSC resources
First, make sure that PowerShell 7.4+ is installed. Then make sure that you have DSC installed:
```ps
Install-Module -Name PSDesiredStateConfiguration -RequiredVersion 2.0.7
```
After that, start a new `pwsh` session and `cd` to `src\dsc\Microsoft.PowerToys.Configure\Generated` directory. From there, you should execute:
```ps
$env:PSModulePath += ";$pwd"
```
You should have the generated `Microsoft.PowerToys.Configure.psm1` and `Microsoft.PowerToys.Configure.psd1` files inside the `src\dsc\Microsoft.PowerToys.Configure\Generated\Microsoft.PowerToys.Configure\0.0.1\` folder.
This will allow DSC to discover our DSC Resource module. See [PSModulePath](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_psmodulepath?view=powershell-7.4#long-description) for more info.
If everything works, you should see that your module is discovered by executing the following command:
```ps
Get-Module -ListAvailable | grep PowerToys
```
The resource itself should also be available:
```ps
Get-DSCResource | grep PowerToys
```
Otherwise, you can force-import the module to diagnose issues:
```
Import-Module .\Microsoft.PowerToys.Configure.psd1
```
If it's imported successfully, you could also try to invoke it directly:
```ps
Invoke-DscResource -Name PowerToysConfigure -Method Set -ModuleName Microsoft.PowerToys.Configure -Property @{ Debug = $true; Awake = @{ Enabled = $false; Mode = "TIMED"; IntervalMinutes = "10" } }
```
Note that we've supplied `Debug` option, so a `%TEMP\PowerToys.DSC.TestConfigure.txt` is created with the supplied properties, a current timestamp, and other debug output.
Finally, you can test it with winget by invoking it as such:
```ps
winget configure .\configuration.winget --accept-configuration-agreements --disable-interactivity
```

View File

@@ -0,0 +1,64 @@
# Group Policy Integration
PowerToys settings can be controlled and enforced via Group Policy. This document describes how Group Policy integration is implemented in the settings system.
## Overview
Group Policy settings for PowerToys allow administrators to:
- Enable or disable PowerToys entirely
- Control which modules are available
- Configure specific settings for individual modules
- Enforce settings across an organization
## Implementation Details
When a setting is controlled by Group Policy:
1. The UI shows the setting as locked (disabled)
2. The module checks GPO settings before applying user settings
3. GPO settings take precedence over user settings
## Group Policy Settings Detection
The settings UI checks for Group Policy settings during initialization:
```csharp
// Example code for checking if a setting is controlled by GPO
bool isControlledByPolicy = RegistryHelper.GetGPOValue("PolicyKeyPath", "PolicyValueName", out object value);
if (isControlledByPolicy)
{
// Use the policy value and disable UI controls
setting.IsEnabled = false;
setting.Value = (bool)value;
}
```
## UI Indication for Managed Settings
When a setting is managed by Group Policy, the UI indicates this to the user:
- Controls are disabled (grayed out)
- A tooltip indicates the setting is managed by policy
- The actual policy value is displayed
## Testing Group Policy Settings
To test Group Policy integration:
1. Create a test GPO using the PowerToys ADMX template
2. Apply settings in the Group Policy Editor
3. Verify that the settings UI correctly reflects the policy settings
4. Verify that the modules honor the policy settings
## GPO Settings vs. User Settings
The precedence order for settings is:
1. Group Policy settings (highest priority)
2. User settings (lower priority)
3. Default settings (lowest priority)
When a setting is controlled by Group Policy, attempts to modify it through the settings UI or programmatically will not persist, as the policy value will always take precedence.
For more information on PowerToys Group Policy implementation, see the [GPO Implementation](/doc/devdocs/processes/gpo.md) documentation.

View File

@@ -0,0 +1,46 @@
# Custom HotKey Control
The Settings project provides a custom hotkey control which consumes key presses. This control can be used to set the hotkey of any PowerToy.
## HotKey Control in FancyZones
![Image of hotkey control](/doc/images/settingsv2/settingshotkeycontrol.png)
## Hotkey related files
#### [`HotkeySettingsControlHook.cs`](/src/settings-ui/Settings.UI.Library/HotkeySettingsControlHook.cs)
- This function initializes and starts the [`keyboardHook`](src/common/interop/KeyboardHook.cpp) for the hotkey control.
```csharp
public HotkeySettingsControlHook(KeyEvent keyDown, KeyEvent keyUp, IsActive isActive, FilterAccessibleKeyboardEvents filterAccessibleKeyboardEvents)
{
_keyDown = keyDown;
_keyUp = keyUp;
_isActive = isActive;
_filterKeyboardEvent = filterAccessibleKeyboardEvents;
_hook = new KeyboardHook(HotkeySettingsHookCallback, IsActive, FilterKeyboardEvents);
_hook.Start();
}
```
#### [`HotkeySettingsControl.xaml.cs`](/src/settings-ui/Settings.UI/HotkeySettingsControl.xaml.cs)
- The function of this class is to update the state of the keys being pressed within the custom control. This information is stored in `internalSettings`.
- It provides the following callbacks to the `HotKeySettingsControlHook`:
- `KeyUp`: Resets the key state in `internalSettings` when a key is released.
- `KeyDown`: Updates the user facing text of the hotkey control as soon as a key is pressed.
- `isActive`: Sets the current status of the keyboard hook.
- `FilterAccessibleKeyboardEvents`: This function is used to ignore the `Tab` and `Shift+Tab` key presses to meet the accessibility requirements.
#### [`HotkeySettings.cs`](/src/settings-ui/Settings.UI.Library/HotkeySettings.cs)
- Contains the structure of a HotKey where it is represented as a combination of one of the modifier keys (`Alt`, `Shift`, `Win` and `Ctrl`) and a non-modifier key.
#### Note
- The control displays all key presses to the user (except Tab and Shift+Tab which move focus out of the control). However, when the focus is being lost from the control, the `lastValidHotkeySettings` is set as the user facing text.

View File

@@ -0,0 +1,17 @@
# Overview
`Settings` is Windows App Sdk WinUI3 .Net Unpackaged desktop application. More details about Windows App Sdk can be found in [Windows App SDK - Calling all Windows developers!](https://github.com/microsoft/WindowsAppSDK#windows-app-sdk---calling-all-windows-developers). More details about WinUI can be found in [Build apps with WinUI](https://developer.microsoft.com/en-us/windows/develop/).
## Settings V2 Project structure
The Settings project .Net WinUI3 based project which
follows the [MVVM architectural pattern][MVVM] where the graphical user interface is separated from the view models.
#### [UI Components:](/src/settings-ui/Settings.UI/)
The UI Components are part of PowerToys.Settings project. It contains the xaml files for each of the UI components. It also contains the Hotkey logic for the settings control.
#### [Viewmodels:](/src/settings-ui/Settings.UI.Library)
The Settings.UI.Library project contains the data that is to be rendered by the UI components.
#### [Settings Runner:](/src/settings-ui/Settings.UI)
The function of the settings runner project is to communicate all changes that the user makes in the user interface, to the runner so that it can be dispatched and reflected in all the modules.
[MVVM]: https://learn.microsoft.com/windows/uwp/data-binding/data-binding-and-mvvm

View File

@@ -0,0 +1,19 @@
# PowerToys Settings System
PowerToys provides a comprehensive settings system that allows users to configure various aspects of the application and its modules. This document provides an overview of the settings system architecture and links to more detailed documentation.
# Table of Contents
1. [Settings overview](/doc/devdocs/core/settings/project-overview.md)
2. [UI Architecture](/doc/devdocs/core/settings/ui-architecture.md)
3. [ViewModels](/doc/devdocs/core/settings/viewmodels.md)
4. [Settings Implementation](/doc/devdocs/core/settings/settings-implementation.md)
5. [Group Policy Integration](/doc/devdocs/core/settings/gpo-integration.md)
6. Data flow
- [Inter-Process Communication with runner](/doc/devdocs/core/settings/runner-ipc.md)
- [Communication with modules](/doc/devdocs/core/settings/communication-with-modules.md)
7. [Settings Utilities](/doc/devdocs/core/settings/settings-utilities.md)
8. [Custom Hotkey control and keyboard hook handling](hotkeycontrol.md)
9. [Compatibility with legacy settings and runner](/doc/devdocs/core/settings/compatibility-legacy-settings.md)
10. [XAML Island tweaks](/doc/devdocs/core/settings/xaml-island-tweaks.md)
11. [Telemetry](/doc/devdocs/core/settings/telemetry.md)
12. [DSC Configuration](/doc/devdocs/core/settings/dsc-configure.md)

View File

@@ -0,0 +1,46 @@
# Inter-Process Communication with Runner
The Settings v2 process uses two way IPC to communicate with the runner process.
## Initialization
- On the settings' side, the two way IPC delegates are contained with the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs) file. The delegates are static and the views for all the powerToys send the ipc information to the viewmodels as `ShellPage.DefaultSndMSGCallBack`.
- These delegates are initialized within the [`MainWindow.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml.cs) file in the `Settings.Runner` project.
## Types of IPC delegates
- There are three types of delegates for the settings to communicate with the runner:
1. `SendDefaultMessage` - This is used by all the viewmodels to communicate changes in the UI to the runner so that the information can be dispatched to the modules.
2. `RestartAsAdmin`
3. `CheckForUpdates`
## Sending information to runner
- The settings process communicates with the runner by using the delegates defined within the [`ShellPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml.cs) file.
- Depending on the type of object sending the information, the json is created accordingly.
- If any information has been modified by the user in the GeneralSettings page, then the json file sent to the runner has the name set to `general`, whereas if any information has been modified by the user in any powertoy related settings page, the name of the json file being communicated with the runner is set to `powertoy`.
## Receiving information from runner
- The `ShellPage` object has a `IPCResponseHandleList` which is a list of functions which handle IPC responses.
```csharp
// receive IPC Message
Program.IPCMessageReceivedCallback = (string msg) =>
{
if (ShellPage.ShellHandler.IPCResponseHandleList != null)
{
try
{
JsonObject json = JsonObject.Parse(msg);
foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
{
handle(json);
}
}
catch (Exception)
{
}
}
};
```
- Whenever any information is sent from the runner each of the functions in the handle list perform their action on that json object.
- One example of where information sent from the runner is being processed by the settings is in [`GeneralPage.xaml.cs`](/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs) when the user clicks the check for updates button. The information displayed after, such as the user has the latest version installed is a result of this handle.

View File

@@ -0,0 +1,158 @@
# Settings Implementation
This document describes how settings are implemented in PowerToys modules, including code examples for C++ and C# modules, and details on debugging settings issues.
## C++ Settings Implementation
For C++ modules, the settings system is implemented in the following files:
- `settings_objects.h` and `settings_objects.cpp`: Define the basic settings objects
- `settings_helpers.h` and `settings_helpers.cpp`: Helper functions for reading/writing settings
- `settings_manager.h` and `settings_manager.cpp`: Main interface for managing settings
### Reading Settings in C++
```cpp
#include <common/settings_objects.h>
#include <common/settings_helpers.h>
auto settings = PowerToysSettings::Settings::LoadSettings(L"ModuleName");
bool enabled = settings.GetValue(L"enabled", true);
```
### Writing Settings in C++
```cpp
PowerToysSettings::Settings settings(L"ModuleName");
settings.SetValue(L"setting_name", true);
settings.Save();
```
## C# Settings Implementation
For C# modules, the settings are accessed through the `SettingsUtils` class in the `Microsoft.PowerToys.Settings.UI.Library` namespace:
### Reading Settings in C#
```csharp
using Microsoft.PowerToys.Settings.UI.Library;
// Read settings
var settings = SettingsUtils.GetSettings<ModuleSettings>("ModuleName");
bool enabled = settings.Enabled;
```
### Writing Settings in C#
```csharp
using Microsoft.PowerToys.Settings.UI.Library;
// Write settings
settings.Enabled = true;
SettingsUtils.SaveSettings(settings.ToJsonString(), "ModuleName");
```
## Settings Handling in Modules
Each PowerToys module must implement settings-related functions in its module interface:
```cpp
// Get the module's settings
virtual PowertoyModuleSettings get_settings() = 0;
// Called when settings are changed
virtual void set_config(const wchar_t* config_string) = 0;
```
When the user changes settings in the UI:
1. The settings UI serializes the settings to JSON
2. The JSON is sent to the PowerToys runner via IPC
3. The runner calls the `set_config` function on the appropriate module
4. The module parses the JSON and applies the new settings
## Debugging Settings
To debug settings issues:
1. Check the settings files in `%LOCALAPPDATA%\Microsoft\PowerToys\`
2. Ensure JSON is well-formed
3. Monitor IPC communication between settings UI and runner using debugger breakpoints at key points:
- In the Settings UI when sending configuration changes
- In the Runner when receiving and dispatching changes
- In the Module when applying changes
4. Look for log messages related to settings changes in the PowerToys logs
### Common Issues
- **Settings not saving**: Check file permissions or conflicts with other processes accessing the file
- **Settings not applied**: Verify IPC communication is working and the module is properly handling the configuration
- **Incorrect settings values**: Check JSON parsing and type conversion in the module code
## Adding a New Module with Settings
Adding a new module with settings requires changes across multiple projects. Here's a step-by-step guide with references to real implementation examples:
### 1. Settings UI Library (Data Models)
Define the data models for your module's settings in the Settings UI Library project. These data models will be serialized to JSON configuration files stored in `%LOCALAPPDATA%\Microsoft\PowerToys\`.
Example: [Settings UI Library implementation](https://github.com/shuaiyuanxx/PowerToys/pull/3/files#diff-9be1cb88a52ce119e5ff990811e5fbb476c15d0d6b7d5de4877b1fd51d9241c3)
### 2. Settings UI (User Interface)
#### 2.1 Add a navigation item in ShellPage.xaml
The ShellPage.xaml is the entry point for the PowerToys settings, providing a navigation view of all modules. Add a navigation item for your new module.
Example: [Adding navigation item](https://github.com/shuaiyuanxx/PowerToys/pull/3/files#diff-5a06e6e7a5c99ae327c350c9dcc10036b49a2d66d66eac79a8364b4c99719c6b)
#### 2.2 Create a settings page for your module
Create a new XAML page that contains all the settings controls for your module.
Example: [New settings page](https://github.com/shuaiyuanxx/PowerToys/pull/3/files#diff-310fd49eba464ddf6a876dcf61f06a6f000ca6744f3a1f915c48c58384d7bacb)
#### 2.3 Implement the ViewModel
Create a ViewModel class that handles the settings data and operations for your module.
Example: [ViewModel implementation](https://github.com/shuaiyuanxx/PowerToys/pull/3/files#diff-409472a53326f2288c5b76b87c7ea8b5527c43ede12214a15b6caabe0403c1d0)
### 3. Module Implementation
#### 3.1 Implement PowertoyModuleIface in dllmain.cpp
The module interface must implement the PowertoyModuleIface to allow the runner to interact with it.
Reference: [PowertoyModuleIface definition](https://github.com/microsoft/PowerToys/blob/cc644b19982d09fcd2122fe7590c77496c4973b9/src/modules/interface/powertoy_module_interface.h#L6C1-L35C4)
#### 3.2 Implement Module UI
Create a UI for your module using either WPF (like ColorPicker) or WinUI3 (like Advanced Paste).
### 4. Runner Integration
Add your module to the known modules list in the runner so it can be brought up and initialized.
Example: [Runner integration](https://github.com/shuaiyuanxx/PowerToys/pull/3/files#diff-c07e4e5e9ce3c371d4c47f496b5f66734978a3c4f355c7e446c1ef19e086a4d6)
### 5. Testing and Debugging
1. Test each component individually:
- Verify settings serialization/deserialization
- Test module activation/deactivation
- Test IPC communication
2. For signal-related issues, ensure all modules work correctly before debugging signal handling.
3. You can debug each module directly in Visual Studio or by attaching to running processes.
### Recommended Implementation Order
1. Module/ModuleUI implementation
2. Module interface (dllmain.cpp)
3. Runner integration
4. Settings UI implementation
5. OOBE (Out of Box Experience) integration
6. Other components

View File

@@ -0,0 +1,13 @@
# Settings Utilities
- Abstractions for each of the file/folder related operations are present in [`SettingsUtils.cs`](src/settings-ui/Settings.UI.Library/SettingsUtils.cs).
- To reduce contention between the settings process and runner while trying to access the `settings.json` file of any powertoy, the settings process tries to access the file only when it needs to load the information for the first time. However, there is still no mechanism in place which ensures that both the settings and runner processes do not access the information simultaneously leading to `IOExceptions`.
## Utilities
### `GetSettings<T>(powertoy, filename)`
- The GetSettings function tries to read the file in the powertoy settings folder and creates a new file with default configurations if it does not exist.
- Ideally this function should only be called by the [`SettingsRepository`](src/settings-ui/Settings.UI.Library/SettingsRepository`1.cs) which would be accessed only when a powertoy settings object is being loaded for the first time.
- The reason behind ensuring that it is not accessed elsewhere is to avoid contention with the runner during file access.
- Each of the objects which are deserialized using this function must implement the `ISettingsConfig` interface.

View File

@@ -0,0 +1,8 @@
# Telemetry
## Overview
[`Settings.UI.Library/Telemetry`](/src/settings-ui/Settings.UI.Library/Telemetry) contains telemetry events generated by `Settingsv2.` These event classes are derived from the [`EventBase`](/src/common/ManagedTelemetry/Telemetry/Events/EventBase.cs) class and [`IEvent`](/src/common/ManagedTelemetry/Telemetry/Events/IEvent.cs) class. [`IEvent`](/src/common/ManagedTelemetry/Telemetry/Events/IEvent.cs) class provides the lowest level abstraction, containing attributes such as privacy tags needed for every telemetry data. [`EventBase`](/src/common/ManagedTelemetry/Telemetry/Events/EventBase.cs) class provides a higher-level abstraction, having attributes common to all `PowerToys` telemetry events.
## Events
The following events are generated by `Settingsv2`:
1. [`SettingsBootEvent`](/src/settings-ui/Settings.UI.Library/Telemetry/Events/SettingsBootEvent.cs): This event captures the time taken by `Settingsv2` to initialize `MainWindow` UI control.
2. [`SettingsEnabledEvent.cs`](/src/settings-ui/Settings.UI.Library/Telemetry/Events/SettingsEnabledEvent.cs): This event is generated when a module is enabled or disabled.

View File

@@ -0,0 +1,7 @@
# UI Architecture
The UI code is distributed between two projects: [`PowerToys.Settings`](/src/settings-ui/Settings.UI) and [`Settings.UI`](/src/settings-ui/Settings.UI.Library). [`PowerToys.Settings`](/src/settings-ui/Settings.UI) is a Windows App Sdk .net Unpackaged application. It contains the views for base navigation and modules. Parent display window and corresponding code is present in [`MainWindow.xaml`](/src/settings-ui/Settings.UI/SettingsXAML/MainWindow.xaml). Fig 1 provides a description of the UI controls hierarchy and each of the controls have been summarized below :
- [`ShellPage.xaml`](/src/settings-ui/Settings.UI/SettingsXAML/Views/ShellPage.xaml) is a WinUI control, consisting of a side navigation panel with an icon for each module. Clicking on a module icon loads the corresponding `setting.json` file and displays the data in the UI.
![Settings UI architecture](/doc/images/settingsv2/ui-architecture.png)
**Fig 1: UI Architecture for settingsv2**

View File

@@ -0,0 +1,26 @@
# Viewmodels
The viewmodels are located within the [`Settings.UI.Library`](/src/settings-ui/Settings.UI.Library) project.
## Components
- Each viewmodel takes in the general `settingsRepository`, the `moduleSettingsRepository` if it exists and the delegates for IPC communication.
- The general `settingsRepository` contains the general configurations of all powertoys whereas the `moduleSettingsRepository` is specific to the module. This is to ensure that the configuration details are shared amongst the viewmodels without having to re-open the `settings.json` file.
- Whenever there is a change in the UI, the `OnPropertyChanged` event is invoked and the viewmodel sends a corresponding IPC message to the runner which would perform the designated action such as dispatching the change to the modules or enabling/disabling the powertoy etc.
#### Difference between viewmodels
- The [`GeneralViewModel`](/src/settings-ui/Settings.UI.Library/ViewModels/GeneralViewModel.cs) is different from the rest of the view models with regard to the IPC communication wherein it sends special IPC messages to the runner to check for updates and to restart as admin.
- Each of the powerToy viewmodels have two types of IPC communications, one for the general status of the powerToy and the other for communication powerToy specific change in properties to the runner.
## [`SettingsRepository`](src/settings-ui/Settings.UI.Library/SettingsRepository`1.cs)
- The [`SettingsRepository`](src/settings-ui/Settings.UI.Library/SettingsRepository`1.cs) is a generic singleton which contains the configurations for each viewmodel.
- As it is a generic singleton, there can only be one instance of the settings repository of a particular type. This ensures that all the viewmodels are modifying a common object and a change made in one locations reflects everywhere.
- The singleton implementation is thread-safe. Unit tests have been added for the same.
### Settings viewmodel anomalies
- The reason behind using the `SettingsRepository` is to ensure that the settings process does not try to access the `settings.json` files directly but rather does it through this class which encapsulates all the file operations from the viewmodels.
- However, this could not be expanded to all the viewmodels directly for the following reasons. Some refactoring must be done to unify these cases and to bring them under the same model:
- The PowerRename viewmodel does not save the settings configurations in the same format as the rest of the powertoys, ie. {name, version, properties}. However, it only stores the properties directly.
- Some viewmodels expect the runner to create the file instead of creating the file themselves, like in keyboard manager.
- The colorpicker powertoy creates the `settings.json` within the module. This must be taken care of when encapsulated within the settingsRepository.
- Currently, all modules use the `SettingsRepository` to access the General Settings config.
- However, only FancyZones, ShortcutGuide and PowerPreview use the `SettingsRepository` to access the module properties.