Compare commits

...

3 Commits

Author SHA1 Message Date
Gordon Lam (SH)
240083bede feat(paste): add setting to show/hide AI paste section 2026-01-30 22:37:05 -08:00
Jaylyn Barbee
055c3011cc Documentation walking through important steps for writing a New PowerToy (#44242)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
This new document serves as a handy guide, packed with key details and
helpful tips to keep in mind when creating a new PowerToy.
2026-01-30 14:45:35 +01:00
leileizhang
2f7fc91956 Fix OOBE pages Launch buttons remain clickable when modules are disabled (#44736)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Fixes the issue where Launch/Open buttons on OOBE (Welcome to PowerToys)
pages remain clickable even when the corresponding module is disabled.

Added enabled state checks to the following OOBE pages:
- **OobeColorPicker** - checks `ModuleType.ColorPicker`
- **OobeEnvironmentVariables** - checks
`ModuleType.EnvironmentVariables`
- **OobeHosts** - checks `ModuleType.Hosts`
- **OobeRun** - checks `ModuleType.PowerLauncher`
- **OobeRegistryPreview** - checks `ModuleType.RegistryPreview`
- **OobeShortcutGuide** - checks `ModuleType.ShortcutGuide`

<img width="1538" height="239" alt="image"
src="https://github.com/user-attachments/assets/da20628e-9c82-4619-8a5c-4b75a22b6901"
/>

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #44737
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2026-01-30 14:48:09 +08:00
24 changed files with 395 additions and 2 deletions

View File

@@ -647,6 +647,8 @@ GSM
gtm
guiddata
GUITHREADINFO
Gotcha
Gotchas
GValue
gwl
GWLP

View File

@@ -0,0 +1,311 @@
# 🧭 Creating a new PowerToy: end-to-end developer guide
First of all, thank you for wanting to contribute to PowerToys. The work we do would not be possible without the support of community supporters like you.
This guide documents the process of building a new PowerToys utility from scratch, including architecture decisions, integration steps, and common pitfalls.
---
## 1. Overview and prerequisites
A PowerToy module is a self-contained utility integrated into the PowerToys ecosystem. It can be UI-based, service-based, or both.
### Requirements
- [Visual Studio 2026](https://visualstudio.microsoft.com/downloads/) and the following workloads/individual components:
- Desktop Development with C++
- WinUI application development
- .NET desktop development
- Windows 10 SDK (10.0.22621.0)
- Windows 11 SDK (10.0.26100.3916)
- .NET 8 SDK
- Fork the [PowerToys repository](https://github.com/microsoft/PowerToys/tree/main) locally
- [Validate that you are able to build and run](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/development/debugging.md) `PowerToys.slnx`.
Optional:
- [WiX v5 toolset](https://github.com/microsoft/PowerToys/tree/main) for the installer
> [!NOTE]
> To ensure all the correct VS Workloads are installed, use [the WinGet configuration files](https://github.com/microsoft/PowerToys/tree/e13d6a78aafbcf32a4bb5f8581d041e1d057c3f1/.config) in the project repository. (Use the one that matches your VS distribution. ie: VS Community would use `configuration.winget`)
### Folder structure
```
src/
modules/
your_module/
YourModule.sln
YourModuleInterface/
YourModuleUI/ (if needed)
YourModuleService/ (if needed)
```
---
## 2. Design and planning
### Decide the type of module
Think about how your module works and which existing modules behave similarly. You are going to want to think about the UI needed for the application, the lifecycle, whether it is a service that is always running or event based. Below are some basic scenarios with some modules to explore. You can write your application in C++ or C#.
- **UI-only:** e.g., ColorPicker
- **Background service:** e.g., LightSwitch, Awake
- **Hybrid (UI + background logic):** e.g., ShortcutGuide
- **C++/C# interop:** e.g., PowerRename
### Write your module interface
Begin by setting up the [PowerToy module template project](https://github.com/microsoft/PowerToys/tree/main/tools/project_template). This will generate boilerplate for you to begin your new module. Below are the key headers in the Module Interface (`dllmain.cpp`) and an explanation of their purpose:
1. This is where module settings are defined. These can be anything from strings, bools, ints, and even custom Enums.
```c++
struct ModuleSettings {};
```
2. This is the header for the full class. It inherits the PowerToyModuleIface
```c++
class ModuleInterface : public PowertoyModuleIface
{
private:
// the private members of the class
// Can include the enabled variable, logic for event handlers, or hotkeys.
public:
// the public members of the class
// Will include the constructor and initialization logic.
}
```
> [!NOTE]
> Many of the class functions are boilerplate and need simple string replacements with your module name. The rest of the functions below will require bigger changes.
3. GPO stands for "Group Policy Object" and allows for administrators to configure settings across a network of machines. It is required that your module is on this list of settings. You can right click the `powertoys_gpo` object to go to the definition and set up the `getConfiguredModuleEnabledValue` for your module.
```c++
virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
{
return powertoys_gpo::getConfiguredModuleEnabledValue();
}
```
4. `init_settings()` initializes the settings for the interface. Will either pull from existing settings.json or use defaults.
```c++
void ModuleInterface::init_settings()
```
5. `get_config` retrieves the settings from the settings.json file.
```c++
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
```
6. `set_config` sets the new settings to the settings.json file.
```c++
virtual void set_config(const wchar_t* config) override
```
7. `call_custom_action` allows custom actions to be called based on signals from the settings app.
```c++
void call_custom_action(const wchar_t* action) override
```
8. Lifecycle events control whether the module is enabled or not, as well as the default status of the module.
```c++
virtual void enable() // starts the module
virtual void disable() // terminates the module and performs any cleanup
virtual bool is_enabled() // returns if the module is currently enabled
virtual bool is_enabled_by_default() const override // allows the module to dictate whether it should be enabled by default in the PowerToys app.
```
9. Hotkey functions control the status of the hotkey.
```c++
// takes the hotkey from settings into a format that the interface can understand
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
// returns the hotkeys from settings
virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
// performs logic when the hotkey event is fired
virtual bool on_hotkey(size_t hotkeyId) override
```
### Notes
- Keep module logic isolated under `/modules/<YourModule>`
- Use shared utilities from [`common`](https://github.com/microsoft/PowerToys/tree/main/src/common) instead of cross-module dependencies
- init/set/get config use preset functions to access the settings. Check out the [`settings_objects.h`](https://github.com/microsoft/PowerToys/blob/main/src/common/SettingsAPI/settings_helpers.h) in `src\common\SettingsAPI`
---
## 3. Bootstrapping your module
1. Use the [template](https://github.com/microsoft/PowerToys/tree/main/tools/project_template) to generate the module interface starter code.
2. Update all projects and namespaces with your module name.
3. Update GUIDs in `.vcxproj` and solution files.
4. Update the functions mentioned in the above section with your custom logic.
5. In order for your module to be detected by the runner you are required to add references to various lists. In order to register your module, add the corresponding module reference to the lists that can be found in the following files. (Hint: search other modules names to find the lists quicker)
- `src/runner/modules.h`
- `src/runner/modules.cpp`
- `src/runner/resource.h`
- `src/runner/settings_window.h`
- `src/runner/settings_window.cpp`
- `src/runner/main.cpp`
- `src/common/logger.h` (for logging)
6. ModuleInterface should build your `ModuleInterface.dll`. This will allow the runner to interact with your service.
> [!TIP]
> Mismatched module IDs are one of the most common causes of load failures. Keep your ID consistent across manifest, registry, and service.
---
## 4. Write your service
This is going to look different for every PowerToy. It may be easier to develop the application independently, and then link in the PowerToys settings logic later. But you have to write the service first, before connecting it to the runner.
### Notes
- This is a separate project from the Module Interface.
- You can develop this project using C# or C++.
- Set the service icon using the `.rc` file.
- Set the service name in the `.vcxproj` by setting the `<TargetName>`
```
<PropertyGroup>
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\$(MSBuildProjectName)\</OutDir>
<TargetName>PowerToys.LightSwitchService</TargetName>
</PropertyGroup>
```
- To view the code of the `.vcxproj`, right click the item and select **Unload project**
- Use the following functions to interact with settings from your service
```
ModuleSettings::instance().InitFileWatcher();
ModuleSettings::instance().LoadSettings();
auto& settings = ModuleSettings::instance().settings();
```
These come from the `ModuleSettings.h` file that lives with the Service. You can copy this from another module (e.g., Light Switch) and adjust to fit your needs.
If your module has a user interface:
- Use the **WinUI Blank App** template when setting up your project
- Use [Windows design best practices](https://learn.microsoft.com/windows/apps/design/basics/)
- Use the [WinUI 3 Gallery](https://apps.microsoft.com/detail/9p3jfpwwdzrc) for help with your UI code, and additional guidance.
## 5. Settings integration
PowerToys settings are stored per-module as JSON under:
```
%LOCALAPPDATA%\Microsoft\PowerToys\<module>\settings.json
```
### Implementation steps
- In `src\settings-ui\Settings.UI.Library\` create `<module>Properties.cs` and `<module>Settings.cs`
- `<module>Properties.cs` is where you will define your defaults. Every setting needs to be represented here. This should match what was set in the Module Interface.
- `<module>Settings.cs`is where your settings.json will be built from. The structure should match the following
```cs
public ModuleSettings()
{
Name = ModuleName;
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Properties = new ModuleProperties(); // settings properties you set above.
}
```
- In `src\settings-ui\Settings.UI\ViewModels` create `<module>ViewModel.cs` this is where the interaction happens between your settings page in the PowerToys app and the settings file that is stored on the device. Changes here will trigger the settings watcher via a `NotifyPropertyChanged` event.
- Create a `SettingsPage.xaml` at `src\settings-ui\Settings.UI\SettingsXAML\Views`. This will be the page where the user interacts with the settings of your module.
- Be sure to use resource strings for user facing strings so they can be localized. (`x:Uid` connects to Resources.resw)
```xaml
// LightSwitch.xaml
<ComboBoxItem
x:Uid="LightSwitch_ModeOff"
AutomationProperties.AutomationId="OffCBItem_LightSwitch"
Tag="Off" />
// Resources.resw
<data name="LightSwitch_ModeOff.Content" xml:space="preserve">
<value>Off</value>
</data>
```
> [!IMPORTANT]
> In the above example we use `.Content` to target the content of the Combobox. This can change per UI element (e.g., `.Text`, `.Header`, etc.)
> **Reminder:** Manual changes via external editors (VS Code, Notepad) do **not** trigger the settings watcher. Only changes written through PowerToys trigger reloads.
---
### Gotchas:
- Only use the WinUI 3 framework, _not_ UWP.
- Use [`DispatcherQueue`](https://learn.microsoft.com/windows/apps/develop/dispatcherqueue) when updating UI from non-UI threads.
---
## 6. Building and debugging
### Debugging steps
1. If this is your first time debugging PowerToys, be sure to follow [these steps first](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/development/debugging.md#pre-debugging-setup).
2. Set "runner" as the start up project and ensure your build configuration is set to match your system (ARM64/x64)
3. Select <kbd>F5</kbd> or the **Local Windows Debugger** button to begin debugging. This should start the PowerToys runner.
4. To set breakpoints in your service, select Ctrl+Alt+P and search for your service to attach to the runner.
5. Use logs to document changes. The logs live at `%LOCALAPPDATA%\Microsoft\PowerToys\RunnerLogs` and `%LOCALAPPDATA%\Microsoft\PowerToys\Module\Service\<version>` for the specific module.
> [!TIP]
> PowerToys caches `.nuget` artifacts aggressively. Use `git clean -xfd` when builds behave unexpectedly.
---
## 7. Installer and packaging (WiX)
### Add your module to installer
1. Install [`WixToolset.Heat`](https://www.nuget.org/packages/WixToolset.Heat/) for Wix5 via nuget
2. Inside `installer\PowerToysInstallerVNext` add a new file for your module: `Module.wxs`
3. Inside of this file you will need copy the format from another module (ie: Light Switch) and replace the strings and GUID values.
4. The key part will be `<!--ModuleNameFiles_Component_Def-->` which is a placeholder for code that will be generated by `generateFileComponents.ps1`.
5. Inside `Product.wxs` add a line item in the `<Feature Id="CoreFeature" ... >` section. It will look like a list of ` <ComponentGroupRef Id="ModuleComponentGroup" />` items.
6. Inside `generateFileComponents.ps1` you will need to add an entry to the bottom for your new module. It will follow the following format. `-fileListName <Module>Files` will match the string you set in `Module.wxs`, `<ModuleServiceName>` will match the name of your exe.
```bash
# Module Name
Generate-FileList -fileDepsJson "" -fileListName <Module>Files -wxsFilePath $PSScriptRoot\<Module>.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\<ModuleServiceName>"
Generate-FileComponents -fileListName "<Module>Files" -wxsFilePath $PSScriptRoot\<Module>.wxs -regroot $registryroot
```
---
## 8. Testing and validation
### UI tests
- Place under `/modules/<YourModule>/Tests`
- Create a new [WinUI Unit Test App](https://learn.microsoft.com/windows/apps/winui/winui3/testing/create-winui-unit-test-project)
- Write unit tests following the format from previous modules (ie: Light Switch). This can be to test your standalone UI (if you're a module like Color Picker) or to verify that the Settings UI in the PowerToys app is controlling your service.
### Manual validation
- Enable/disable in PowerToys Settings
- Check initialization in logs
- Confirm icons, tooltips, and OOBE page appear correctly
### Pro tips
1. Validate wake/sleep and elevation states. Background modules often fail silently after resume if event handles arent recreated.
2. Use Windows Sandbox to simulate clean install environments
3. To simulate a "new user" you can delete the PowerToys folder from `%LOCALAPPDATA%\Microsoft`
### Shortcut conflict detection
If your module has a shortcut, ensure that it is properly registered following [the steps listed in the documentation](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/core/settings/settings-implementation.md#shortcut-conflict-detection) for conflict detection.
---
## 9. The final touches
### Out-of-Box experience (OOBE) page
The OOBE page is a custom settings page that gives the user at a glance information about each module. This window opens before the Settings application for new users and after updates. Create `OOBE<ModuleName>.xaml` at `src\settings-ui\Settings.UI\SettingsXAML\OOBE\Views`. You will also need to add your module name to the enum at `src\settings-ui\Settings.UI\OOBE\Enums\PowerToysModules.cs`.
### Module assets
Now that your PowerToy is _done_ you can start to think about the assets that will represent your module.
- Module Icon: This will be displayed in a number of places: OOBE page, in the README, on the home screen of PowerToys, on your individual module settings page, etc.
- Module Image: This is the image you see at the top of each individual settings page.
- OOBE Image: This is the header you see on the OOBE page for each module
> [!NOTE]
> This step is something that the Design team will handle internally to ensure consistency throughout the application. If you have ideas or recommendations on what the icon or screenshots should be for your module feel free to leave it in the "Additional Comments" section of the PR and the team will take it into consideration.
### Documentation
There are two types of documentation that will be required when submitting a new PowerToy:
1. Developer documentation: This will live in the [PowerToys repo](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/modules) at `/doc/devdocs/modules/` and should tell a developer how to work on your app. It should outline the module architecture, key files, testing, and tips on debugging if necessary.
2. Microsoft Learn documentation: When your new Module is ready to be merged into the PowerToys repository, an internal team member will create Microsoft Learn documentation so that users will understand how to use your module. There is not much work on your end as the developer for this step, but keep an eye on your PR in case we need more information about your PowerToy for this step.
---
Thank you again for contributing! If you need help, feel free to [open an issue](https://github.com/microsoft/PowerToys/issues/new/choose) and use the `Needs-Team-Response` label so we know you need attention.

View File

@@ -47,6 +47,8 @@ internal sealed class IntegrationTestUserSettings : IUserSettings
public bool ShowCustomPreview => false;
public bool ShowAIPaste => true;
public bool CloseAfterLosingFocus => false;
public bool EnableClipboardPreview => true;

View File

@@ -251,7 +251,8 @@
Margin="20,0,20,0"
x:FieldModifier="public"
IsEnabled="{x:Bind ViewModel.IsCustomAIServiceEnabled, Mode=OneWay}"
TabIndex="0">
TabIndex="0"
Visibility="{x:Bind ViewModel.ShowAIPasteSection, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
<controls:PromptBox.Footer>
<StackPanel Orientation="Horizontal">
<TextBlock

View File

@@ -17,6 +17,8 @@ namespace AdvancedPaste.Settings
public bool ShowCustomPreview { get; }
public bool ShowAIPaste { get; }
public bool CloseAfterLosingFocus { get; }
public bool EnableClipboardPreview { get; }

View File

@@ -38,6 +38,8 @@ namespace AdvancedPaste.Settings
public bool ShowCustomPreview { get; private set; }
public bool ShowAIPaste { get; private set; }
public bool CloseAfterLosingFocus { get; private set; }
public bool EnableClipboardPreview { get; private set; }
@@ -54,6 +56,7 @@ namespace AdvancedPaste.Settings
IsAIEnabled = false;
ShowCustomPreview = true;
ShowAIPaste = true;
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
PasteAIConfiguration = new PasteAIConfiguration();
@@ -109,6 +112,7 @@ namespace AdvancedPaste.Settings
IsAIEnabled = properties.IsAIEnabled;
ShowCustomPreview = properties.ShowCustomPreview;
ShowAIPaste = properties.ShowAIPaste;
CloseAfterLosingFocus = properties.CloseAfterLosingFocus;
EnableClipboardPreview = properties.EnableClipboardPreview;
PasteAIConfiguration = properties.PasteAIConfiguration ?? new PasteAIConfiguration();

View File

@@ -234,6 +234,8 @@ namespace AdvancedPaste.ViewModels
public bool ShowClipboardHistoryButton => ClipboardHistoryEnabled;
public bool ShowAIPasteSection => _userSettings.ShowAIPaste && IsAllowedByGPO;
public bool HasIndeterminateTransformProgress => double.IsNaN(TransformProgress);
private PasteFormats CustomAIFormat =>
@@ -320,6 +322,7 @@ namespace AdvancedPaste.ViewModels
OnPropertyChanged(nameof(AIProviders));
OnPropertyChanged(nameof(AllowedAIProviders));
OnPropertyChanged(nameof(ShowClipboardPreview));
OnPropertyChanged(nameof(ShowAIPasteSection));
NotifyActiveProviderChanged();

View File

@@ -1 +1 @@
{"properties":{"IsAIEnabled":{"value":false},"ShowCustomPreview":{"value":true},"CloseAfterLosingFocus":{"value":false},"advanced-paste-ui-hotkey":{"win":true,"ctrl":false,"alt":false,"shift":true,"code":86,"key":""},"paste-as-plain-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":79,"key":""},"paste-as-markdown-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":77,"key":""},"paste-as-json-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":74,"key":""},"custom-actions":{"value":[]},"additional-actions":{"image-to-text":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-file":{"isShown":true,"paste-as-txt-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-png-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-html-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true}},"transcode":{"isShown":true,"transcode-to-mp3":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"transcode-to-mp4":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true}}},"paste-ai-configuration":{"active-provider-id":"","providers":[],"use-shared-credentials":true}},"name":"AdvancedPaste","version":"1"}
{"properties":{"IsAIEnabled":{"value":false},"ShowCustomPreview":{"value":true},"ShowAIPaste":{"value":true},"CloseAfterLosingFocus":{"value":false},"advanced-paste-ui-hotkey":{"win":true,"ctrl":false,"alt":false,"shift":true,"code":86,"key":""},"paste-as-plain-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":79,"key":""},"paste-as-markdown-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":77,"key":""},"paste-as-json-hotkey":{"win":true,"ctrl":true,"alt":true,"shift":false,"code":74,"key":""},"custom-actions":{"value":[]},"additional-actions":{"image-to-text":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-file":{"isShown":true,"paste-as-txt-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-png-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"paste-as-html-file":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true}},"transcode":{"isShown":true,"transcode-to-mp3":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true},"transcode-to-mp4":{"shortcut":{"win":false,"ctrl":false,"alt":false,"shift":false,"code":0,"key":""},"isShown":true}}},"paste-ai-configuration":{"active-provider-id":"","providers":[],"use-shared-credentials":true}},"name":"AdvancedPaste","version":"1"}

View File

@@ -26,6 +26,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
AdditionalActions = new();
IsAIEnabled = false;
ShowCustomPreview = true;
ShowAIPaste = true;
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
PasteAIConfiguration = new();
@@ -73,6 +74,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowCustomPreview { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowAIPaste { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool CloseAfterLosingFocus { get; set; }

View File

@@ -21,6 +21,7 @@
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_ColorPicker"
Click="Start_ColorPicker_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -5,6 +5,7 @@
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -53,6 +54,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ColorPickerSettings settings = SettingsUtils.Default.GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerSettings.ModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
HotkeyControl.Keys = settings.Properties.ActivationShortcut.GetKeysList();
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.ColorPicker);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -12,6 +12,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_EnvironmentVariables"
Click="Launch_EnvironmentVariables_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -5,6 +5,7 @@
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -28,6 +29,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.EnvironmentVariables);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -12,6 +12,7 @@
<StackPanel Orientation="Vertical" Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_Hosts"
Click="Launch_Hosts_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -5,6 +5,7 @@
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -28,6 +29,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.Hosts);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -21,6 +21,7 @@
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_RegistryPreview"
Click="Launch_RegistryPreview_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -43,6 +44,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.RegistryPreview);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -21,6 +21,7 @@
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_Run"
Click="Start_Run_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -5,6 +5,7 @@
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -55,6 +56,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PowerLauncherSettings>.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList();
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.PowerLauncher);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -16,6 +16,7 @@
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="LaunchButton"
x:Uid="Launch_ShortcutGuide"
Click="Start_ShortcutGuide_Click"
Style="{StaticResource AccentButtonStyle}" />

View File

@@ -8,6 +8,7 @@ using System.Globalization;
using System.IO;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
@@ -66,6 +67,10 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
HotkeyControl.Keys = settingsProperties.OpenShortcutGuide.GetKeysList();
}
// Disable the Launch button if the module is disabled
var generalSettings = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default).SettingsConfig;
LaunchButton.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettings, ManagedCommon.ModuleType.ShortcutGuide);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)

View File

@@ -183,6 +183,9 @@
<tkcontrols:SettingsCard Name="AdvancedPasteShowCustomPreviewSettingsCard" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl x:Uid="AdvancedPaste_ShowCustomPreviewSettingsCard" IsChecked="{x:Bind ViewModel.ShowCustomPreview, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard Name="AdvancedPasteShowAIPasteSettingsCard" ContentAlignment="Left">
<controls:CheckBoxWithDescriptionControl x:Uid="AdvancedPaste_ShowAIPasteSettingsCard" IsChecked="{x:Bind ViewModel.ShowAIPaste, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>

View File

@@ -4117,6 +4117,12 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="AdvancedPaste_ShowCustomPreviewSettingsCard.Description" xml:space="preserve">
<value>Preview the output of AI formats and Image to text before pasting</value>
</data>
<data name="AdvancedPaste_ShowAIPasteSettingsCard.Header" xml:space="preserve">
<value>Show AI paste section</value>
</data>
<data name="AdvancedPaste_ShowAIPasteSettingsCard.Description" xml:space="preserve">
<value>Show the AI paste input box in the Advanced Paste window</value>
</data>
<data name="AdvancedPaste_EnableAdvancedAI.Text" xml:space="preserve">
<value>Advanced AI</value>
</data>

View File

@@ -543,6 +543,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool ShowAIPaste
{
get => _advancedPasteSettings.Properties.ShowAIPaste;
set
{
if (value != _advancedPasteSettings.Properties.ShowAIPaste)
{
_advancedPasteSettings.Properties.ShowAIPaste = value;
NotifySettingsChanged();
}
}
}
public bool CloseAfterLosingFocus
{
get => _advancedPasteSettings.Properties.CloseAfterLosingFocus;
@@ -1221,6 +1234,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(nameof(ShowCustomPreview));
}
if (target.ShowAIPaste != source.ShowAIPaste)
{
target.ShowAIPaste = source.ShowAIPaste;
OnPropertyChanged(nameof(ShowAIPaste));
}
if (target.CloseAfterLosingFocus != source.CloseAfterLosingFocus)
{
target.CloseAfterLosingFocus = source.CloseAfterLosingFocus;