[MWB] - Merge branch 'main' into dev/mikeclayton/mwb-common-refactor - #35155

This commit is contained in:
Michael Clayton 2025-01-29 16:41:07 +00:00
Родитель 093a5c53d2 5fe761949f
Коммит cd66dff0bd
86 изменённых файлов: 1372 добавлений и 1164 удалений

5
.github/actions/spell-check/allow/code.txt поставляемый
Просмотреть файл

@ -86,6 +86,9 @@ howto
onefuzzconfig
oip
onefuzzingestionpreparationtool
OTP
Yubi
Yubico
# KEYS
@ -262,4 +265,4 @@ onefuzz
leilzh
#Tools
OIP
OIP

1
.github/actions/spell-check/allow/names.txt поставляемый
Просмотреть файл

@ -193,6 +193,7 @@ capturevideosample
cmdow
Controlz
cortana
dlnilsson
fancymouse
firefox
gpt

1
.github/actions/spell-check/expect.txt поставляемый
Просмотреть файл

@ -993,6 +993,7 @@ NNN
NOACTIVATE
NOAGGREGATION
NOASYNC
NOCHANGEDIR
NOCLIP
NOCLOSEPROCESS
NOCOALESCE

Просмотреть файл

@ -1,52 +0,0 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
"PowerToys.HostsUILib.dll",
"PowerToys.EnvironmentVariablesUILib.dll",
"PowerToys.RegistryPreviewUILib.dll"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}

Просмотреть файл

@ -204,13 +204,6 @@ jobs:
- ${{ if eq(parameters.useLatestWinAppSDK, false)}}:
- template: .\steps-restore-nuget.yml
- pwsh: |-
& "$(build.sourcesdirectory)\.pipelines\verifyAndSetLatestVCToolsVersion.ps1"
displayName: Work around DD-1541167 (VCToolsVersion)
${{ if eq(parameters.useVSPreview, true) }}:
env:
VCWhereExtraVersionTarget: '-prerelease'
- pwsh: |-
& "$(build.sourcesdirectory)\.pipelines\installWiX.ps1"
displayName: Download and install WiX 3.14 development build
@ -242,103 +235,6 @@ jobs:
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- ${{ if eq(parameters.codeSign, true) }}:
- template: steps-esrp-signing.yml
parameters:
displayName: Sign Utilities
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: 'src/modules'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_abstracted_utils_dll.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
- task: VSBuild@1
displayName: Create Hosts File Editor package
inputs:
solution: '**\HostsUILib.csproj'
vsVersion: 17.0
msbuildArgs: >-
/p:CIBuild=true;NoBuild=true -t:pack
/bl:$(LogOutputDirectory)\build-hosts.binlog
/p:NoWarn=NU5104
$(RestoreAdditionalProjectSourcesArg)
configuration: $(BuildConfiguration)
msbuildArchitecture: x64
maximumCpuCount: true
${{ if eq(parameters.enableMsBuildCaching, true) }}:
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- task: VSBuild@1
displayName: Create Environment Variables Editor package
inputs:
solution: '**\EnvironmentVariablesUILib.csproj'
vsVersion: 17.0
msbuildArgs: >-
/p:CIBuild=true;NoBuild=true -t:pack
/bl:$(LogOutputDirectory)\build-env-var-editor.binlog
/p:NoWarn=NU5104
$(RestoreAdditionalProjectSourcesArg)
configuration: $(BuildConfiguration)
msbuildArchitecture: x64
maximumCpuCount: true
${{ if eq(parameters.enableMsBuildCaching, true) }}:
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- task: VSBuild@1
displayName: Create Registry Preview package
inputs:
solution: '**\RegistryPreviewUILib.csproj'
vsVersion: 17.0
msbuildArgs: >-
/p:CIBuild=true;NoBuild=true -t:pack
/bl:$(LogOutputDirectory)\build-registry-preview.binlog
/p:NoWarn=NU5104
$(RestoreAdditionalProjectSourcesArg)
configuration: $(BuildConfiguration)
msbuildArchitecture: x64
maximumCpuCount: true
${{ if eq(parameters.enableMsBuildCaching, true) }}:
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- task: CopyFiles@2
displayName: Stage NuGet packages
inputs:
contents: "**/bin/Release/PowerToys*.nupkg"
flattenFolders: True
targetFolder: $(JobOutputDirectory)/nupkg
- ${{ if eq(parameters.codeSign, true) }}:
- template: steps-esrp-signing.yml
parameters:
displayName: Sign NuGet packages
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: $(JobOutputDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- task: VSBuild@1
displayName: Build BugReportTool
inputs:

Просмотреть файл

@ -1,5 +0,0 @@
$LatestVCToolsVersion = (([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest $env:VCWhereExtraVersionTarget -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml)).instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.CRT.Source" }).version;
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
Write-Output "Updating VCToolsVersion environment variable for job"
Write-Output "##vso[task.setvariable variable=VCToolsVersion]$LatestVCToolsVersion"

172
README.md
Просмотреть файл

@ -18,7 +18,7 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
| [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Peek](https://aka.ms/PowerToysOverview_Peek) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) |
| [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) |
| [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_PowerToysOverview_ZoomIt) |
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_ZoomIt) |
## Installing and running Microsoft PowerToys
@ -34,19 +34,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
<!-- items that need to be updated release to release -->
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.88%22
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.87%22
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysUserSetup-0.87.1-x64.exe
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysUserSetup-0.87.1-arm64.exe
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysSetup-0.87.1-x64.exe
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysSetup-0.87.1-arm64.exe
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.89%22
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.88%22
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-x64.exe
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysUserSetup-0.88.0-arm64.exe
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-x64.exe
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.88.0/PowerToysSetup-0.88.0-arm64.exe
| Description | Filename | sha256 hash |
|----------------|----------|-------------|
| Per user - x64 | [PowerToysUserSetup-0.87.1-x64.exe][ptUserX64] | 8EFAF47ED00BF230D2C2CC3CB6765C903A6A47E0AAED0BBB329CEF918207B486 |
| Per user - ARM64 | [PowerToysUserSetup-0.87.1-arm64.exe][ptUserArm64] | 212FC8055789BD2DC4DE554B9AEE291A9C077907E263A302939266263A9D512B |
| Machine wide - x64 | [PowerToysSetup-0.87.1-x64.exe][ptMachineX64] | 69AD65DDAC6436AEF292D2CC6AB1530021CE98083CB3F5FD3380A52A3B0DBB9A |
| Machine wide - ARM64 | [PowerToysSetup-0.87.1-arm64.exe][ptMachineArm64] | AEC9F1D02F1E23F0C1FCFDF95C337C962902394F44C0568012DF78BEDB45CF19 |
| Per user - x64 | [PowerToysUserSetup-0.88.0-x64.exe][ptUserX64] | 5BBA2E06603CAAE0269DFBC991095C6664FD934130335197C1BA3120E19B7CA3 |
| Per user - ARM64 | [PowerToysUserSetup-0.88.0-arm64.exe][ptUserArm64] | E79723F9F94068C699E01334C8CC0C85F37818EB4664FC772D2B545A1C37C3FA |
| Machine wide - x64 | [PowerToysSetup-0.88.0-x64.exe][ptMachineX64] | C43742DB7AA3F8B01FE7AE1DA591F0342767AFE5BBACB72F2968CE5E8EE1E3AC |
| Machine wide - ARM64 | [PowerToysSetup-0.88.0-arm64.exe][ptMachineArm64] | AEE4A67643C886336F31F86C4117BA5F01BCA5E0E99FF34524217DC91AFA7132 |
This is our preferred method.
@ -92,119 +92,141 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
### 0.87 - December 2024 Update
### 0.88 - January 2025 Update
In this release, we focused on new features, stability, and improvements.
**Highlights**
- Advanced Paste has a new feature called "Advanced AI" that uses Semantic Kernel to allow setting up the orchestration of sequential clipboard transformations.
- Workspaces supports Progressive Web Applications.
- Workspaces has a new feature to move existing windows instead of creating new ones.
- Mouse Jump added new settings to allow customization of screens pop-up. Thanks [@mikeclayton](https://github.com/mikeclayton)!
- New+ now works on Windows 10. Thanks [@cgaarden](https://github.com/cgaarden)!
- Quick Accent allows selecting the character sets that should appear on the UI. Thanks [@Sirozha1337](https://github.com/Sirozha1337)!
- New utility: ZoomIt - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
- Video Conference Mute has been deprecated and was removed from PowerToys.
- .Net 9.0.1 fixed many issue in WPF, improving stability for PowerToys Run.
### General
- Applied a workaround for the Windows App SDK applications title bar override that was causing accent color to not be shown on the top bar of applications on Windows 10. Thanks [@pingzing](https://github.com/pingzing)!
- Improved the "admin application running" notification checking logic to be less demanding on resources. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
- Fixed an issue causing many utilities to crash when the GPO to disable data diagnostics was applied.
### Advanced Paste
- Added a new optional feature allowing using AI to set up the orchestration of sequential clipboard transformations.
- Fixed a crash when the application was exiting. (This was a hotfix for 0.87)
- Added a Json format validation step to verify if a conversion to Json should be applied.
- Fixed accessibility issues when using a screen reader.
- Added support for all BitmapDecoder supported image file types to the Image to Text functionality. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed an issue causing Advanced Paste initialization errors to hang the PowerToys main process.
### Awake
### FancyZones
- Initialization, logging and tray icon setup improvements. Thanks [@dend](https://github.com/dend)!
- Removed Workspaces Editor from the exclusions list so it can be snapped by FancyZones.
### File Explorer add-ons
### Keyboard Manager
- Preview Pane extensions now use the PerMonitorV2 DPI mode to fix errors on different scales. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
### Keyboard Manager.
- Added labels to the IME On, IME Off keys. Thanks [@kit494way](https://github.com/kit494way)!
- Fixed an issue that caused the Shift key to remain stuck if a numpad key was mapped to the Shift key.
- Added an option to make a shortcut remapping only trigger with exact modifiers.
### Monaco Preview
- Added support for .ahk files to be shown as a plaintext file in Peek and File Explorer add-ons. Thanks [@daverayment](https://github.com/daverayment)!
- Added support for .ion files to be shown as a plaintext file in Peek and File Explorer add-ons. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)!
- Added support for syntax highlighting for .srt files in Peek and File Explorer add-ons. Thanks [@PesBandi](https://github.com/PesBandi)!
- Added support for .resx and .resw files in Peek and File Explorer add-ons. Thanks [@asif4318](https://github.com/asif4318)!
- Added a setting to make the code minimap toggle-able in Peek and File Explorer add-ons. Thanks [@PesBandi](https://github.com/PesBandi)!
- Fixed an issue causing Json format preview setting to not be applied correctly.
- Fixed an issue causing the wrong Monaco assets to be used at runtime.
### Mouse Jump
### Mouse Without Borders
- Allow customizing the appearance of the UI of the Mouse Jump pop-up. Thanks [@mikeclayton](https://github.com/mikeclayton)!
- Fixed an issue causing clipboard to stop working after going through a UAC screen when using the Service mode. Thanks [@YDKK](https://github.com/YDKK)!
### New+
- Added support for Windows 10. Thanks [@cgaarden](https://github.com/cgaarden)!
- Fixed an issue causing the renaming of new files to not trigger some times. Thanks [@cgaarden](https://github.com/cgaarden)!
- Updated the New+ icons. Thanks [@niels9001](https://github.com/niels9001)!
- Fixed an issue causing New+ to override the New file or folder creation from the File Explorer Ribbon buttons or keyboard shortcuts on Windows 10.
- When creating file or folders through a template, they should now have the current time as the last modified date. Thanks [@cgaarden](https://github.com/cgaarden)!
### Peek
- Peek now checks local capabilities to decide what image formats Image Previewer is able to support. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed an issue causing the Code Files Previewer to not load correctly under certain conditions. Thanks [@daverayment](https://github.com/daverayment)!
- Refactored, improved and fixed logging when loading the user settings file. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed an issue causing Peek to not appear if it was previously minimized. Thanks [@asif4318](https://github.com/asif4318)!
### PowerToys Run
- Added a scoring function for proper ordering of the WindowWalker plugin results. Thanks [@andbartol](https://github.com/andbartol)!
- Added UUIDv7 support to the ValueGenerator plugin. Thanks [@frederik-hoeft](https://github.com/frederik-hoeft)!
- The calculator plugin now allows scientific notation numbers with a lowercase 'e'. Thanks [@PesBandi](https://github.com/PesBandi)!
- Ported the UI from WPF-UI to .NET 9 WPF, to fix "Desktop composition is disabled" crashes.
- Fixed a transparent border issue on Windows 10. (This was a hotfix for 0.87)
- Fixed a crash in the OneNote plugin after the .Net 9 update. (This was a hotfix for 0.87)
- Fixed an issue causing the Calculator plugin to return division by zero errors when dividing by hexadecimal numbers. Thanks [@plante-msft](https://github.com/plante-msft)!
- Updated the Calculator plugin Mages library to 3.0.0 and added support for the random integer function. Thanks [@htcfreek](https://github.com/htcfreek)!
- Improved handling of non-base 10 numbers to add support for binary and octal numbers in the Calculator plugin. Thanks [@PesBandi](https://github.com/PesBandi)!
- Added a setting to enable selection of which units to use for trigonometric functions. Thanks [@OldUser101](https://github.com/OldUser101)!
- Fixed a .NET 9 regression causing the PowerToys Run dialog to not be draggable. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
- Added context menu buttons for the VS Code Workspaces plugin, for copying the path, opening in File Explorer or in Console. Thanks [@programming-with-ia](https://github.com/programming-with-ia)!
- Added some telemetry to gather data on which hotkey is used to trigger PowerToys Run.
- Removed the workarounds that were in place to fix some WPF issues that were fixed in .NET 9.0.1.
- Fixed a typo in the Value Generator plugin messages. Thanks [@OldUser101](https://github.com/OldUser101)!
### Quick Accent
- Added a setting to allow selecting which character sets to show. Thanks [@Sirozha1337](https://github.com/Sirozha1337)!
- Added the ć character to the Slovenian character set. Thanks [@dsoklic](https://github.com/dsoklic)!
- Added the Proto-Indo-European character set.
### Screen Ruler
### Registry Preview
- Added a Setting to also allow showing measurements in inches, centimeters or millimeters. Thanks [@Sophanatprime](https://github.com/Sophanatprime)!
- Fixed an issue causing line breaks to not be parsed correctly for REG_MULTI_SZ values. Thanks [@htcfreek](https://github.com/htcfreek)!
- Added a tooltip to values to show multiple lines of data. Thanks [@htcfreek](https://github.com/htcfreek)!
- Added a context menu to enable copying type, value and key paths. Thanks [@htcfreek](https://github.com/htcfreek)!
### Settings
- Fixed an issue causing all the links to milestones in the "What's new?" OOBE page to point to the same milestone.
- Removed extra space from the Welcome page. Thanks [@agarwalishita](https://github.com/agarwalishita)!
- Updated left navigation bar icons. Thanks [@niels9001](https://github.com/niels9001)!
- Fixed accessibility issues in the dashboard page. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
- Made the Advanced Paste paste OpenAI configuration modal scrollable.
- Fixed the text on the Quick Accent page to refer to "character sets" instead of "character set". Thanks [@PesBandi](https://github.com/PesBandi)!
- Added the plugin's dll file version and website to the PowerToys Run plugin settings. Thanks [@htcfreek](https://github.com/htcfreek)!
- Added the Workspaces file to the list of files that gets backed up by the Back up / Restore functionality.
- Fixed an issue causing some of the selected character sets to be unselected when opening the character set expander in the Quick Accent page.
- Improved GPO logic, icons, info bar layout and enabled state of all modules settings pages. Thanks [@htcfreek](https://github.com/htcfreek)!
- Fixed some accessibility issues and refactored and improved quality of the code related to image sizes in the Image Resizer page. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed mentions of "Backup" to "Back up" when it should be used as a verb. Thanks [@JackStuart](https://github.com/JackStuart)!
- Added a "New" label to Settings to better highlight new utilities that get released. Thanks [@niels9001](https://github.com/niels9001) for the UI tweaks!
### Text Extractor
- Fixed many accessibility and UI issues on the overlay UI. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
### Workspaces
- Added support for Progressive Web Applications to Workspaces.
- Implemented a feature to move existing windows instead of creating new ones.
- Fixed a crash when opening the workspaces editor that was caused by passing incorrect encoder parameters when saving Bitmap files.
- Workspaces editor position is now saved so that we can start it at the same position when we open it again.
- Fixed an issue causing many instances of the same application to be put in the same position instead of the intended position due to timer issues.
- Fixed detection of exact application version when many versions of the same application are installed.
- Fixed an issue causing the Workspaces Editor to start outside of visible desktop area.
- Fixed an issue to maintain command line arguments for applications when trying using the "Launch and Edit" feature.
### Video Conference Mute
- The module has been deprecated in 0.88.0, being removed from PowerToys.
### ZoomIt
- New utility: Zoom It - a screen zoom, annotation, and recording tool for technical presentations and demos. This utility from Sysinternals has had its source code released and included in PowerToys. ZoomIt will still continue to be updated and shipped by Sysinternals for users who prefer to have it as a standalone utility outside of PowerToys. Thanks [@markrussinovich](https://github.com/markrussinovich), [@foxmsft](https://github.com/foxmsft) and [@johnstep](https://github.com/johnstep) for contributing the original code and reviewing the PowerToys integration!
### Documentation
- Improved language in CONTRIBUTE.md. Thanks [@sanskaarz](https://github.com/sanskaarz)!
- Added Bilibili plugin mention to thirdPartyRunPlugins.md. Thanks [@Whuihuan](https://github.com/Whuihuan)!
- Added CanIUse and TailwindCSS plugins mention to thirdPartyRunPlugins.md. Thanks [@skttl](https://github.com/skttl)!
- Added HttpStatusCodes plugin mention to thirdPartyRunPlugins.md. Thanks [@grzhan](https://github.com/grzhan)!
- Updated COMMUNITY.md with more contributors.
- Updated the PowerToys Run documentation to reflect documentation pages for new plugins.
- Added YubicoOauthOTP plugin mention to thirdPartyRunPlugins.md. Thanks [@dlnilsson](https://github.com/dlnilsson)!
### Development
- Upgraded to .NET 9. Thanks [@snickler](https://github.com/snickler)!
- Fixed building on Visual Studio 17.12.
- Upgraded the System.IO.Abstractions dependency to 21.0.29. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
- Upgraded the WindowsAppSDK dependency to 1.6.241114003. Thanks [@shuaiyuanxx](https://github.com/shuaiyuanxx)!
- Upgraded the MSTest dependency to 3.6.3. Thanks [@Youssef1313](https://github.com/Youssef1313)!
- Upgraded the check-spelling CI dependency to 0.0.24 and fixed related spell checking issues. Thanks [@jsoref](https://github.com/jsoref)!
- Removed duplicate names from the spellcheck allowed names file. Thanks [@htcfreek](https://github.com/htcfreek)!
- Improved logging of asynchronous methods call stacks when logging an error.
- Created a MSBuild props file to be imported by other projects to enable AOT support.
- Made the Peek utility source code AOT compatible.
- Updated .editorconfig rules to relax squiggly IDE errors in Visual Studio 17.12. Thanks [@snickler](https://github.com/snickler)!
- Moved Xaml.Styler from the root to the src folder.
- Added fuzz testing for AdvancedPaste, with a new pipeline for OneFuzz.
- Added a new CI pipeline to build with the latest WindowsAppSDK.
- Added a new CI pipeline to build with the latest webview2 from Edge Canary.
- Made the HostsUILib project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
- Made FilePreviewCommon and MarkdownPreviewHandler AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
- Made the PowerAccent.Core project AOT compatible. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
- Cleaned up some code for AOT compatibility in the Advanced Paste module. Thanks [@snickler](https://github.com/snickler) for your help reviewing this!
- Removed the prerelease flag from the PowerToys development DSC configurations. Thanks [@denelon](https://github.com/denelon)!
- Improved Dart CI reliability by improving error messages and retrying to the step that installs the correct dotnet version.
- Improved Dart CI reliability by fixing retries when downloading the localization files.
- Improved Dart CI build times by removing the steps to build the no longer needed abstracted utility nuget packages.
- Removed the solution.props file from the solution root.
- Fixed PowerToys Run Calculator plugin tests when running in systems with different number formats. Thanks [@htcfreek](https://github.com/htcfreek)!
- Updated many .NET packages from .NET 9.0.0 to 9.0.1 for security fixes. Thanks [@snickler](https://github.com/snickler)!
- Refactored the Mouse Without Borders Common.Log.cs and Common.Receiver.cs files. Thanks [@mikeclayton](https://github.com/mikeclayton)!
#### What is being planned for version 0.88
For [v0.88][github-next-release-work], we'll work on the items below:
For [v0.89][github-next-release-work], we'll work on the items below:
- Stability / bug fixes
- New module: File Actions Menu
- Integrate Sysinternals ZoomIt
- PowerToys Run v2 development work
## PowerToys Community

Просмотреть файл

@ -62,3 +62,4 @@ Below are community created plugins that target a website or software. They are
| [HackMD](https://github.com/8LWXpg/PowerToysRun-HackMD) | [8LWXpg](https://github.com/8LWXpg) | Open HackMD notes |
| [SSH](https://github.com/8LWXpg/PowerToysRun-SSH) | [8LWXpg](https://github.com/8LWXpg) | Connect to ssh clients |
| [Bilibili](https://github.com/Whuihuan/PowerToysRun-Bilibili) | [Whuihuan](https://github.com/Whuihuan) | Use AVID or BVID to parse and jump to Bilibili |
| [YubicoOauthOTP](https://github.com/dlnilsson/Community.PowerToys.Run.Plugin.YubicoOauthOTP) | [dlnilsson](https://github.com/dlnilsson) | Display generated codes from OATH accounts stored on the YubiKey in powerToys Run |

Просмотреть файл

@ -20,16 +20,16 @@ namespace Microsoft.PowerToys.Telemetry
try
{
registryValue = Registry.GetValue(DataDiagnosticsRegistryKey, DataDiagnosticsRegistryValueName, 0);
if (registryValue is not null)
{
return (int)registryValue == 1 ? true : false;
}
}
catch
{
}
if (registryValue is not null)
{
return (int)registryValue == 1 ? true : false;
}
return false;
}

Просмотреть файл

@ -9,6 +9,9 @@
#include <string>
#include <functional>
#include <wil/resource.h>
#include <wil/filesystem.h>
class FileWatcher
{
std::wstring m_path;

Просмотреть файл

@ -10,4 +10,3 @@
#include <fstream>
#include <common/logger/logger.h>
#include <wil/filesystem.h>

Просмотреть файл

@ -174,9 +174,8 @@ namespace PTSettingsHelper
return;
}
const bool value = enabled;
const size_t buf_size = sizeof(bool);
if (RegSetValueExW(key, DataDiagnosticsRegValueName, 0, REG_QWORD, reinterpret_cast<const BYTE*>(&value), buf_size) != ERROR_SUCCESS)
const DWORD value = enabled ? 1 : 0;
if (RegSetValueExW(key, DataDiagnosticsRegValueName, 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value)) != ERROR_SUCCESS)
{
RegCloseKey(key);
return;

Просмотреть файл

@ -0,0 +1,56 @@
#include "pch.h"
#include "NotificationUtil.h"
#include <common/notifications/notifications.h>
#include <common/notifications/dont_show_again.h>
#include <common/utils/resources.h>
#include <common/SettingsAPI/settings_helpers.h>
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t RunAsAdminInfoPage[] = L"https://aka.ms/powertoysDetectedElevatedHelp";
const wchar_t ToastNotificationButtonUrl[] = L"powertoys://cant_drag_elevated_disable/";
}
namespace notifications
{
NotificationUtil::NotificationUtil()
{
ReadSettings();
auto settingsFileName = PTSettingsHelper::get_powertoys_general_save_file_location();
m_settingsFileWatcher = std::make_unique<FileWatcher>(settingsFileName, [this]() {
ReadSettings();
});
}
NotificationUtil::~NotificationUtil()
{
m_settingsFileWatcher.reset();
}
void NotificationUtil::WarnIfElevationIsRequired(std::wstring title, std::wstring message, std::wstring button1, std::wstring button2)
{
if (m_warningsElevatedApps && !m_warningShown && !is_toast_disabled(ElevatedDontShowAgainRegistryPath, ElevatedDisableIntervalInDays))
{
std::vector<action_t> actions = {
link_button{ button1, NonLocalizable::RunAsAdminInfoPage },
link_button{ button2, NonLocalizable::ToastNotificationButtonUrl }
};
show_toast_with_activations(message,
title,
{},
std::move(actions));
m_warningShown = true;
}
}
void NotificationUtil::ReadSettings()
{
auto settings = PTSettingsHelper::load_general_settings();
m_warningsElevatedApps = settings.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
}
}

Просмотреть файл

@ -1,40 +1,22 @@
#pragma once
#include <common/notifications/notifications.h>
#include <common/notifications/dont_show_again.h>
#include <common/utils/resources.h>
#include <common/SettingsAPI/settings_helpers.h>
#include "Generated Files/resource.h"
#include <common/SettingsAPI/FileWatcher.h>
namespace notifications
{
// Non-Localizable strings
namespace NonLocalizable
class NotificationUtil
{
const wchar_t RunAsAdminInfoPage[] = L"https://aka.ms/powertoysDetectedElevatedHelp";
const wchar_t ToastNotificationButtonUrl[] = L"powertoys://cant_drag_elevated_disable/";
}
public:
NotificationUtil();
~NotificationUtil();
inline void WarnIfElevationIsRequired(std::wstring title, std::wstring message, std::wstring button1, std::wstring button2)
{
using namespace NonLocalizable;
void WarnIfElevationIsRequired(std::wstring title, std::wstring message, std::wstring button1, std::wstring button2);
auto settings = PTSettingsHelper::load_general_settings();
auto enableWarningsElevatedApps = settings.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
private:
std::unique_ptr<FileWatcher> m_settingsFileWatcher;
bool m_warningsElevatedApps;
bool m_warningShown = false;
static bool warning_shown = false;
if (enableWarningsElevatedApps && !warning_shown && !is_toast_disabled(ElevatedDontShowAgainRegistryPath, ElevatedDisableIntervalInDays))
{
std::vector<action_t> actions = {
link_button{ button1, RunAsAdminInfoPage },
link_button{ button2, ToastNotificationButtonUrl }
};
show_toast_with_activations(message,
title,
{},
std::move(actions));
warning_shown = true;
}
}
}
void ReadSettings();
};
}

Просмотреть файл

@ -27,13 +27,14 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="notifications.h" />
<ClInclude Include="NotificationUtil.h" />
<ClInclude Include="dont_show_again.h" />
<ClInclude Include="NotificationUtil.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dont_show_again.cpp" />
<ClCompile Include="notifications.cpp" />
<ClCompile Include="NotificationUtil.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
</ClCompile>

Просмотреть файл

@ -0,0 +1,45 @@
// 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 System.Text.Json;
using AdvancedPaste.Models.KernelQueryCache;
using AdvancedPaste.SerializationContext;
using AdvancedPaste.Telemetry;
namespace AdvancedPaste.Helpers
{
public class AIServiceFormatEvent
{
public AIServiceFormatEvent(AdvancedPasteSemanticKernelFormatEvent semanticKernelFormatEvent)
{
CacheUsed = semanticKernelFormatEvent.CacheUsed;
IsSavedQuery = semanticKernelFormatEvent.IsSavedQuery;
PromptTokens = semanticKernelFormatEvent.PromptTokens;
CompletionTokens = semanticKernelFormatEvent.CompletionTokens;
ModelName = semanticKernelFormatEvent.ModelName;
ActionChain = semanticKernelFormatEvent.ActionChain;
}
public AIServiceFormatEvent(AdvancedPasteGenerateCustomFormatEvent generateCustomFormatEvent)
{
PromptTokens = generateCustomFormatEvent.PromptTokens;
CompletionTokens = generateCustomFormatEvent.CompletionTokens;
ModelName = generateCustomFormatEvent.ModelName;
}
public bool IsSavedQuery { get; set; }
public bool CacheUsed { get; set; }
public int PromptTokens { get; set; }
public int CompletionTokens { get; set; }
public string ModelName { get; set; }
public string ActionChain { get; set; }
public string ToJsonString() => JsonSerializer.Serialize(this, SourceGenerationContext.Default.AIServiceFormatEvent);
}
}

Просмотреть файл

@ -18,7 +18,7 @@ namespace AdvancedPaste.Helpers
internal static int Size
{
get { return Marshal.SizeOf(typeof(INPUT)); }
get { return Marshal.SizeOf<INPUT>(); }
}
}

Просмотреть файл

@ -16,7 +16,7 @@ using Microsoft.PowerToys.Settings.UI.Library.Utilities;
namespace AdvancedPaste.Settings
{
internal sealed class UserSettings : IUserSettings, IDisposable
internal sealed partial class UserSettings : IUserSettings, IDisposable
{
private readonly SettingsUtils _settingsUtils;
private readonly TaskScheduler _taskScheduler;

Просмотреть файл

@ -7,6 +7,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using AdvancedPaste.Helpers;
using AdvancedPaste.SerializationContext;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace AdvancedPaste.Models.KernelQueryCache;
@ -15,15 +16,7 @@ public sealed class PersistedCache : ISettingsConfig
{
public record class CacheItem(CacheKey CacheKey, CacheValue CacheValue);
private static readonly JsonSerializerOptions SerializerOptions = new()
{
Converters =
{
new JsonStringEnumConverter(),
},
};
public static PersistedCache FromJsonString(string json) => JsonSerializer.Deserialize<PersistedCache>(json, SerializerOptions);
public static PersistedCache FromJsonString(string json) => JsonSerializer.Deserialize<PersistedCache>(json, SourceGenerationContext.Default.PersistedCache);
public string Version { get; init; }
@ -31,7 +24,7 @@ public sealed class PersistedCache : ISettingsConfig
public string GetModuleName() => Constants.AdvancedPasteModuleName;
public string ToJsonString() => JsonSerializer.Serialize(this, SerializerOptions);
public string ToJsonString() => JsonSerializer.Serialize(this, SourceGenerationContext.Default.PersistedCache);
public override string ToString() => ToJsonString();

Просмотреть файл

@ -0,0 +1,16 @@
// 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 System.Text.Json.Serialization;
using AdvancedPaste.Helpers;
using AdvancedPaste.Models.KernelQueryCache;
namespace AdvancedPaste.SerializationContext;
[JsonSerializable(typeof(PersistedCache))]
[JsonSerializable(typeof(AIServiceFormatEvent))]
[JsonSourceGenerationOptions(UseStringEnumConverter = true)]
public sealed partial class SourceGenerationContext : JsonSerializerContext
{
}

Просмотреть файл

@ -174,9 +174,8 @@ public abstract class KernelServiceBase(IKernelQueryCacheService queryCacheServi
{
AdvancedPasteSemanticKernelFormatEvent telemetryEvent = new(cacheUsed, isSavedQuery, usage.PromptTokens, usage.CompletionTokens, ModelName, AdvancedPasteSemanticKernelFormatEvent.FormatActionChain(actionChain));
PowerToysTelemetry.Log.WriteEvent(telemetryEvent);
var logEvent = new { telemetryEvent.CacheUsed, telemetryEvent.IsSavedQuery, telemetryEvent.PromptTokens, telemetryEvent.CompletionTokens, telemetryEvent.ModelName, telemetryEvent.ActionChain };
Logger.LogDebug($"{nameof(TransformClipboardAsync)} complete; {JsonSerializer.Serialize(logEvent)}");
var logEvent = new AIServiceFormatEvent(telemetryEvent);
Logger.LogDebug($"{nameof(TransformClipboardAsync)} complete; {logEvent.ToJsonString()}");
}
private Kernel CreateKernel()

Просмотреть файл

@ -85,9 +85,9 @@ Output:
var usage = response.Usage;
AdvancedPasteGenerateCustomFormatEvent telemetryEvent = new(usage.PromptTokens, usage.CompletionTokens, ModelName);
PowerToysTelemetry.Log.WriteEvent(telemetryEvent);
var logEvent = new AIServiceFormatEvent(telemetryEvent);
var logEvent = new { telemetryEvent.PromptTokens, telemetryEvent.CompletionTokens, telemetryEvent.ModelName };
Logger.LogDebug($"{nameof(TransformTextAsync)} complete; {JsonSerializer.Serialize(logEvent)}");
Logger.LogDebug($"{nameof(TransformTextAsync)} complete; {logEvent.ToJsonString()}");
return response.Choices[0].Text;
}

Просмотреть файл

@ -262,6 +262,10 @@ namespace MouseWithoutBorders
new Task(() =>
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
System.Threading.Thread thread = Thread.CurrentThread;
thread.Name = $"{nameof(SendClipboardDataUsingTCP)}.{thread.ManagedThreadId}";
Thread.UpdateThreads(thread);
@ -386,6 +390,10 @@ namespace MouseWithoutBorders
new Task(() =>
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
System.Threading.Thread thread = Thread.CurrentThread;
thread.Name = $"{nameof(ConnectAndGetData)}.{thread.ManagedThreadId}";
Thread.UpdateThreads(thread);

Просмотреть файл

@ -72,6 +72,10 @@ namespace MouseWithoutBorders
private static void HelperThread()
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
try
{
while (true)

Просмотреть файл

@ -380,6 +380,10 @@ namespace MouseWithoutBorders.Class
private static void InputCallbackThread()
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
Common.InputCallbackThreadID = Thread.CurrentThread.ManagedThreadId;
while (!Common.InitDone)
{

Просмотреть файл

@ -681,6 +681,10 @@ namespace MouseWithoutBorders.Class
private void TCPServerThread(object param)
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
try
{
TcpListener server = param as TcpListener;
@ -768,6 +772,10 @@ namespace MouseWithoutBorders.Class
{
void ServerThread()
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
try
{
// Receiving packages
@ -876,6 +884,10 @@ namespace MouseWithoutBorders.Class
{
void ClientThread(object obj)
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
IPHostEntry host;
bool useName2IP = false;
List<IPAddress> validAddresses = new();
@ -1117,6 +1129,10 @@ namespace MouseWithoutBorders.Class
{
void NewTcpClient()
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
TcpClient tcpClient = null;
try
@ -1549,6 +1565,10 @@ namespace MouseWithoutBorders.Class
private static void AcceptConnectionAndSendClipboardData(object param)
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
TcpListener server = param as TcpListener;
do
@ -1590,6 +1610,10 @@ namespace MouseWithoutBorders.Class
{
new Task(() =>
{
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
using var asyncFlowControl = ExecutionContext.SuppressFlow();
System.Threading.Thread thread = Thread.CurrentThread;
thread.Name = $"{nameof(SendOrReceiveClipboardData)}.{thread.ManagedThreadId}";
Thread.UpdateThreads(thread);

Просмотреть файл

@ -343,6 +343,21 @@ namespace newplus::utilities
}
}
inline void update_last_write_time(const std::filesystem::path path)
{
const std::filesystem::file_time_type now = std::filesystem::file_time_type::clock::now();
std::filesystem::last_write_time(path, now);
if (std::filesystem::is_directory(path))
{
for (const auto& entry : std::filesystem::recursive_directory_iterator(path))
{
std::filesystem::last_write_time(entry.path(), now);
}
}
}
inline HRESULT copy_template(const template_item* template_entry, const ComPtr<IUnknown> site_of_folder)
{
HRESULT hr = S_OK;
@ -376,6 +391,9 @@ namespace newplus::utilities
// Copy file and determine final filename
std::filesystem::path target_final_fullpath = template_entry->copy_object_to(GetActiveWindow(), target_fullpath);
// Touch all files and set last modified to "now"
update_last_write_time(target_final_fullpath);
// Consider copy completed. If we do tracing after enter_rename_mode, then rename mode won't consistently work
trace.UpdateState(true);
Trace::EventCopyTemplate(target_final_fullpath.extension().c_str());

Просмотреть файл

@ -3,6 +3,7 @@
#include <common/utils/elevation.h>
#include <common/utils/process_path.h>
#include <common/utils/resources.h>
#include <common/notifications/NotificationUtil.h>
#include <workspaces-common/WindowEnumerator.h>
@ -12,6 +13,8 @@
#include <WorkspacesLib/PwaHelper.h>
#include <WindowProperties/WorkspacesWindowPropertyUtils.h>
#include "Generated Files/resource.h"
#pragma comment(lib, "ntdll.lib")
namespace SnapshotUtils
@ -74,10 +77,12 @@ namespace SnapshotUtils
// Notify the user that running as admin is required to process elevated windows.
if (!is_process_elevated() && IsProcessElevated(pid))
{
notifications::WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_PROJECTS),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
auto notificationUtil = std::make_unique<notifications::NotificationUtil>();
notificationUtil->WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_PROJECTS),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
}
continue;

Просмотреть файл

@ -6023,6 +6023,12 @@ LRESULT APIENTRY MainWndProc(
// Apply tray icon setting
EnableDisableTrayIcon(hWnd, g_ShowTrayIcon);
// This is also called by ZoomIt when it starts and loads the Settings. Opacity is added after loading from registry, so we use the same pattern.
if ((g_PenColor >> 24) == 0)
{
g_PenColor |= 0xFF << 24;
}
// Apply hotkey settings
UnregisterAllHotkeys(hWnd);
g_ToggleMod = GetKeyMod(g_ToggleKey);
@ -7416,6 +7422,12 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
if( !ShowEula( APPNAME, NULL, NULL )) return 1;
#ifdef __ZOOMIT_POWERTOYS__
if (powertoys_gpo::getConfiguredZoomItEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)
{
Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
return 1;
}
Shared::Trace::ETWTrace* trace = nullptr;
std::wstring pid = std::wstring(lpCmdLine); // The PowerToys pid is the argument to the process.
auto mainThreadId = GetCurrentThreadId();
@ -7423,12 +7435,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
{
g_StartedByPowerToys = TRUE;
if (powertoys_gpo::getConfiguredZoomItEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)
{
Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
return 1;
}
trace = new Shared::Trace::ETWTrace();
Trace::RegisterProvider();
trace->UpdateState(true);

Просмотреть файл

@ -105,9 +105,12 @@ namespace winrt::PowerToys::ZoomItSettingsInterop::implementation
}
else if (special_semantics->second == SPECIAL_SEMANTICS_COLOR)
{
// PowerToys settings likes colors as #FFFFFF strings.
/* PowerToys settings likes colors as #FFFFFF strings.
But currently these Settings are internal state for ZoomIt, not something that we really need to send Settings.
Code is kept here as a reference if a future color Setting ends up being configured.
hstring s = winrt::to_hstring(std::format("#{:02x}{:02x}{:02x}", value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF));
_settings.add_property(curSetting->ValueName, s);
*/
}
}
break;
@ -211,6 +214,9 @@ namespace winrt::PowerToys::ZoomItSettingsInterop::implementation
}
else if (special_semantics->second == SPECIAL_SEMANTICS_COLOR)
{
/* PowerToys settings likes colors as #FFFFFF strings.
But currently these Settings are internal state for ZoomIt, not something that we really need to save from Settings.
Code is kept here as a reference if a future color Setting ends up being configured.
auto possibleValue = valuesFromSettings.get_string_value(curSetting->ValueName);
if (possibleValue.has_value())
{
@ -219,8 +225,8 @@ namespace winrt::PowerToys::ZoomItSettingsInterop::implementation
{
*static_cast<PDWORD>(curSetting->Setting) = RGB(r, g, b);
}
}
*/
}
}
break;

Просмотреть файл

@ -9,7 +9,6 @@
#include <common/utils/process_path.h>
#include <common/utils/elevation.h>
#include <common/notifications/NotificationUtil.h>
#include <Generated Files/resource.h>
#include <interop/shared_constants.h>
@ -36,7 +35,8 @@ AlwaysOnTop::AlwaysOnTop(bool useLLKH, DWORD mainThreadId) :
SettingsObserver({SettingId::FrameEnabled, SettingId::Hotkey, SettingId::ExcludeApps}),
m_hinstance(reinterpret_cast<HINSTANCE>(&__ImageBase)),
m_useCentralizedLLKH(useLLKH),
m_mainThreadId(mainThreadId)
m_mainThreadId(mainThreadId),
m_notificationUtil(std::make_unique<notifications::NotificationUtil>())
{
s_instance = this;
DPIAware::EnableDPIAwarenessForThisProcess();
@ -64,6 +64,7 @@ AlwaysOnTop::AlwaysOnTop(bool useLLKH, DWORD mainThreadId) :
AlwaysOnTop::~AlwaysOnTop()
{
m_running = false;
m_notificationUtil.reset();
if (m_hPinEvent)
{
@ -509,7 +510,10 @@ void AlwaysOnTop::HandleWinHookEvent(WinHookEvent* data) noexcept
{
if (!is_process_elevated() && IsProcessOfWindowElevated(data->hwnd))
{
notifications::WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_ALWAYSONTOP), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
m_notificationUtil->WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_ALWAYSONTOP),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE),
GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
}
RefreshBorders();
}

Просмотреть файл

@ -9,6 +9,7 @@
#include <WindowBorder.h>
#include <common/hooks/WinHookEvent.h>
#include <common/notifications/NotificationUtil.h>
class AlwaysOnTop : public SettingsObserver
{
@ -53,6 +54,7 @@ private:
std::thread m_thread;
const bool m_useCentralizedLLKH;
bool m_running = true;
std::unique_ptr<notifications::NotificationUtil> m_notificationUtil;
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
void HandleWinHookEvent(WinHookEvent* data) noexcept;

Просмотреть файл

@ -7,6 +7,7 @@
#include <common/utils/EventWaiter.h>
#include <common/utils/winapi_error.h>
#include <common/SettingsAPI/FileWatcher.h>
#include <common/notifications/NotificationUtil.h>
#include <FancyZonesLib/DraggingState.h>
#include <FancyZonesLib/EditorParameters.h>
@ -185,6 +186,8 @@ private:
EventWaiter m_toggleEditorEventWaiter;
std::unique_ptr<notifications::NotificationUtil> m_notificationUtil;
// If non-recoverable error occurs, trigger disabling of entire FancyZones.
static std::function<void()> disableModuleCallback;
@ -266,6 +269,8 @@ FancyZones::Run() noexcept
}
});
m_notificationUtil = std::make_unique<notifications::NotificationUtil>();
SyncVirtualDesktops();
// id format of applied-layouts and app-zone-history was changed in 0.60
@ -288,6 +293,8 @@ FancyZones::Destroy() noexcept
m_window = nullptr;
}
m_notificationUtil.reset();
CoUninitialize();
}
@ -302,7 +309,7 @@ FancyZones::VirtualDesktopChanged() noexcept
void FancyZones::MoveSizeStart(HWND window, HMONITOR monitor)
{
m_windowMouseSnapper = WindowMouseSnap::Create(window, m_workAreaConfiguration.GetAllWorkAreas());
m_windowMouseSnapper = WindowMouseSnap::Create(window, m_workAreaConfiguration.GetAllWorkAreas(), m_notificationUtil.get());
if (m_windowMouseSnapper)
{
if (FancyZonesSettings::settings().spanZonesAcrossMonitors)

Просмотреть файл

@ -11,7 +11,7 @@
#include <FancyZonesLib/trace.h>
#include <common/utils/elevation.h>
#include <common/notifications/NotificationUtil.h>
#include <common/utils/resources.h>
WindowMouseSnap::WindowMouseSnap(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas) :
m_window(window),
@ -27,7 +27,7 @@ WindowMouseSnap::~WindowMouseSnap()
ResetWindowTransparency();
}
std::unique_ptr<WindowMouseSnap> WindowMouseSnap::Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas)
std::unique_ptr<WindowMouseSnap> WindowMouseSnap::Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas, notifications::NotificationUtil* notificationUtil)
{
if (FancyZonesWindowUtils::IsCursorTypeIndicatingSizeEvent() || !FancyZonesWindowProcessing::IsProcessableManually(window))
{
@ -36,8 +36,15 @@ std::unique_ptr<WindowMouseSnap> WindowMouseSnap::Create(HWND window, const std:
if (!is_process_elevated() && IsProcessOfWindowElevated(window))
{
// Notifies user if unable to drag elevated window
notifications::WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_FANCYZONES), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
if (notificationUtil != nullptr)
{
// Notifies user if unable to drag elevated window
notificationUtil->WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_FANCYZONES),
GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED),
GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE),
GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
}
return nullptr;
}

Просмотреть файл

@ -1,6 +1,7 @@
#pragma once
#include <FancyZonesLib/HighlightedZones.h>
#include <common/notifications/NotificationUtil.h>
class WorkArea;
@ -9,7 +10,7 @@ class WindowMouseSnap
WindowMouseSnap(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas);
public:
static std::unique_ptr<WindowMouseSnap> Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas);
static std::unique_ptr<WindowMouseSnap> Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas, notifications::NotificationUtil* notificationUtil);
~WindowMouseSnap();
bool MoveSizeStart(HMONITOR monitor, bool isSnapping);

Просмотреть файл

@ -146,7 +146,7 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
// This is only for single chars
if (content.Length > 1)
{
throw new ArgumentException($"Invalid Query: {query.RawUserQuery} (To many characters.)");
throw new ArgumentException($"Invalid Query: {query.RawUserQuery} (Too many characters.)");
}
else if (content.Length == 0)
{

Просмотреть файл

@ -13,6 +13,7 @@ using ManagedCommon;
using Microsoft.PowerToys.Run.Plugin.Calculator.Properties;
using Microsoft.PowerToys.Settings.UI.Library;
using Wox.Plugin;
using Wox.Plugin.Logger;
namespace Microsoft.PowerToys.Run.Plugin.Calculator
{
@ -212,8 +213,18 @@ namespace Microsoft.PowerToys.Run.Plugin.Calculator
var optionReplaceInput = settings.AdditionalOptions.FirstOrDefault(x => x.Key == ReplaceInput);
replaceInput = optionReplaceInput?.Value ?? replaceInput;
var optionTrigMode = settings.AdditionalOptions.FirstOrDefault(x => x.Key == TrigMode);
trigMode = (CalculateEngine.TrigMode)int.Parse(optionTrigMode.ComboBoxValue.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
try
{
var optionTrigMode = settings.AdditionalOptions.FirstOrDefault(x => x.Key == TrigMode);
if (optionTrigMode != null)
{
trigMode = (CalculateEngine.TrigMode)int.Parse(optionTrigMode.ComboBoxValue.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
}
}
catch (Exception ex)
{
Log.Exception("Error while trying to load Trigonometry Mode setting: {ex.Message}", ex, GetType());
}
}
_inputUseEnglishFormat = inputUseEnglishFormat;

Просмотреть файл

@ -3,241 +3,119 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using Settings.UI.Library.Resources;
namespace Microsoft.PowerToys.Settings.UI.Library
namespace Microsoft.PowerToys.Settings.UI.Library;
public partial class ImageSize : INotifyPropertyChanged
{
public class ImageSize : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
public ImageSize(int id)
bool changed = !EqualityComparer<T>.Default.Equals(field, value);
if (changed)
{
Id = id;
Name = string.Empty;
Fit = ResizeFit.Fit;
Width = 0;
Height = 0;
Unit = ResizeUnit.Pixel;
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AccessibleTextHelper)));
}
public ImageSize()
return changed;
}
public ImageSize(int id = 0, string name = "", ResizeFit fit = ResizeFit.Fit, double width = 0, double height = 0, ResizeUnit unit = ResizeUnit.Pixel)
{
Id = id;
Name = name;
Fit = fit;
Width = width;
Height = height;
Unit = unit;
}
private int _id;
private string _name;
private ResizeFit _fit;
private double _height;
private double _width;
private ResizeUnit _unit;
public int Id
{
get => _id;
set => SetProperty(ref _id, value);
}
/// <summary>
/// Gets a value indicating whether the <see cref="Height"/> property is used. When false, the
/// <see cref="Width"/> property is used to evenly scale the image in both X and Y dimensions.
/// </summary>
[JsonIgnore]
public bool IsHeightUsed
{
// Height is ignored when using percentage scaling where the aspect ratio is maintained
// (i.e. non-stretch fits). In all other cases, both Width and Height are needed.
get => !(Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch);
}
[JsonPropertyName("name")]
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
[JsonPropertyName("fit")]
public ResizeFit Fit
{
get => _fit;
set
{
Id = 0;
Name = string.Empty;
Fit = ResizeFit.Fit;
Width = 0;
Height = 0;
Unit = ResizeUnit.Pixel;
}
public ImageSize(int id, string name, ResizeFit fit, double width, double height, ResizeUnit unit)
{
Id = id;
Name = name;
Fit = fit;
Width = width;
Height = height;
Unit = unit;
}
private int _id;
private string _name;
private ResizeFit _fit;
private double _height;
private double _width;
private ResizeUnit _unit;
public int Id
{
get
if (SetProperty(ref _fit, value))
{
return _id;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
}
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged();
}
}
}
public int ExtraBoxOpacity
{
get
{
if (Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch)
{
return 0;
}
else
{
return 100;
}
}
}
public bool EnableEtraBoxes
{
get
{
if (Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch)
{
return false;
}
else
{
return true;
}
}
}
[JsonPropertyName("name")]
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
[JsonPropertyName("fit")]
public ResizeFit Fit
{
get
{
return _fit;
}
set
{
if (_fit != value)
{
_fit = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ExtraBoxOpacity));
OnPropertyChanged(nameof(EnableEtraBoxes));
}
}
}
[JsonPropertyName("width")]
public double Width
{
get
{
return _width;
}
set
{
double newWidth = -1;
if (value < 0 || double.IsNaN(value))
{
newWidth = 0;
}
else
{
newWidth = value;
}
if (_width != newWidth)
{
_width = newWidth;
OnPropertyChanged();
}
}
}
[JsonPropertyName("height")]
public double Height
{
get
{
return _height;
}
set
{
double newHeight = -1;
if (value < 0 || double.IsNaN(value))
{
newHeight = 0;
}
else
{
newHeight = value;
}
if (_height != newHeight)
{
_height = newHeight;
OnPropertyChanged();
}
}
}
[JsonPropertyName("unit")]
public ResizeUnit Unit
{
get
{
return _unit;
}
set
{
if (_unit != value)
{
_unit = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ExtraBoxOpacity));
OnPropertyChanged(nameof(EnableEtraBoxes));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public void Update(ImageSize modifiedSize)
{
ArgumentNullException.ThrowIfNull(modifiedSize);
Id = modifiedSize.Id;
Name = modifiedSize.Name;
Fit = modifiedSize.Fit;
Width = modifiedSize.Width;
Height = modifiedSize.Height;
Unit = modifiedSize.Unit;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
[JsonPropertyName("width")]
public double Width
{
get => _width;
set => SetProperty(ref _width, value < 0 || double.IsNaN(value) ? 0 : value);
}
[JsonPropertyName("height")]
public double Height
{
get => _height;
set => SetProperty(ref _height, value < 0 || double.IsNaN(value) ? 0 : value);
}
[JsonPropertyName("unit")]
public ResizeUnit Unit
{
get => _unit;
set
{
if (SetProperty(ref _unit, value))
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
}
}
}
/// <summary>
/// Gets access to all properties for formatting accessibility descriptions.
/// </summary>
[JsonIgnore]
public ImageSize AccessibleTextHelper => this;
public string ToJsonString() => JsonSerializer.Serialize(this);
}

Просмотреть файл

@ -44,12 +44,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public KeyboardKeysProperty SnipToggleKey { get; set; }
public StringProperty PenColor { get; set; }
public IntProperty PenWidth { get; set; }
public StringProperty BreakPenColor { get; set; }
public KeyboardKeysProperty BreakTimerKey { get; set; }
public StringProperty Font { get; set; }
@ -80,24 +74,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public BoolProperty BreakShowDesktop { get; set; }
public BoolProperty BreakOnSecondary { get; set; }
public IntProperty FontScale { get; set; }
public BoolProperty ShowExpiredTime { get; set; }
public BoolProperty ShowTrayIcon { get; set; }
public BoolProperty AnimnateZoom { get; set; }
public BoolProperty TelescopeZoomOut { get; set; }
public BoolProperty SnapToGrid { get; set; }
public IntProperty ZoominSliderLevel { get; set; }
public IntProperty RecordFrameRate { get; set; }
public IntProperty RecordScaling { get; set; }
public BoolProperty CaptureAudio { get; set; }

Просмотреть файл

@ -205,7 +205,7 @@ namespace ViewModelTests
}
[TestMethod]
public void AddRowShouldAddNewImageSizeWhenSuccessful()
public void AddImageSizeShouldAddNewImageSizeWhenSuccessful()
{
// arrange
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
@ -214,7 +214,7 @@ namespace ViewModelTests
int sizeOfOriginalArray = viewModel.Sizes.Count;
// act
viewModel.AddRow("New size");
viewModel.AddImageSize();
// Assert
Assert.AreEqual(sizeOfOriginalArray + 1, viewModel.Sizes.Count);
@ -229,15 +229,15 @@ namespace ViewModelTests
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
// act
viewModel.AddRow("New size");
viewModel.AddImageSize("New size");
// Assert
ImageSize newTestSize = viewModel.Sizes.First(x => x.Id == 0);
Assert.AreEqual(newTestSize.Name, "New size 1");
Assert.AreEqual(newTestSize.Fit, ResizeFit.Fit);
Assert.AreEqual(newTestSize.Width, 854);
Assert.AreEqual(newTestSize.Height, 480);
Assert.AreEqual(newTestSize.Unit, ResizeUnit.Pixel);
Assert.AreEqual("New size 1", newTestSize.Name);
Assert.AreEqual(ResizeFit.Fit, newTestSize.Fit);
Assert.AreEqual(1024, newTestSize.Width);
Assert.AreEqual(640, newTestSize.Height);
Assert.AreEqual(ResizeUnit.Pixel, newTestSize.Unit);
}
[TestMethod]
@ -247,7 +247,7 @@ namespace ViewModelTests
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
Func<string, int> sendMockIPCConfigMSG = msg => { return 0; };
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
viewModel.AddRow("New Size");
viewModel.AddImageSize("New Size");
int sizeOfOriginalArray = viewModel.Sizes.Count;
ImageSize deleteCandidate = viewModel.Sizes.First(x => x.Id == 0);
@ -268,16 +268,16 @@ namespace ViewModelTests
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
// act
viewModel.AddRow("New size"); // Add: "New size 1"
viewModel.AddRow("New size"); // Add: "New size 2"
viewModel.AddRow("New size"); // Add: "New size 3"
viewModel.AddImageSize("New size"); // Add: "New size 1"
viewModel.AddImageSize("New size"); // Add: "New size 2"
viewModel.AddImageSize("New size"); // Add: "New size 3"
viewModel.DeleteImageSize(1); // Delete: "New size 2"
viewModel.AddRow("New size"); // Add: "New Size 4"
viewModel.AddImageSize("New size"); // Add: "New Size 4"
// Assert
Assert.AreEqual(viewModel.Sizes[0].Name, "New size 1");
Assert.AreEqual(viewModel.Sizes[1].Name, "New size 3");
Assert.AreEqual(viewModel.Sizes[2].Name, "New size 4");
Assert.AreEqual("New size 1", viewModel.Sizes[0].Name);
Assert.AreEqual("New size 3", viewModel.Sizes[1].Name);
Assert.AreEqual("New size 4", viewModel.Sizes[2].Name);
}
[TestMethod]

Просмотреть файл

@ -3,41 +3,38 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Converters
namespace Microsoft.PowerToys.Settings.UI.Converters;
public sealed partial class ImageResizerFitToStringConverter : IValueConverter
{
public sealed partial class ImageResizerFitToStringConverter : IValueConverter
// Maps each ResizeFit to its localized string.
private static readonly Dictionary<ResizeFit, string> FitToText = new()
{
public object Convert(object value, Type targetType, object parameter, string language)
{ ResizeFit.Fill, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fill_ThirdPersonSingular") },
{ ResizeFit.Fit, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fit_ThirdPersonSingular") },
{ ResizeFit.Stretch, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular") },
};
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is ResizeFit fit && FitToText.TryGetValue(fit, out string fitText))
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fill_ThirdPersonSingular"); break;
case 1: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fit_ThirdPersonSingular"); break;
case 2: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
return parameter is string lowerParam && lowerParam == "ToLower" ?
fitText.ToLower(CultureInfo.CurrentCulture) :
fitText;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}

Просмотреть файл

@ -0,0 +1,71 @@
// 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 System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Converters;
/// <summary>
/// Creates accessibility text for controls related to <see cref="ImageSize"/> properties.
/// </summary>
/// <example>(Name) "Edit the Small preset"</example>
/// <example>(FullDescription) "Large - Fits within 1920 × 1080 pixels"</example>"
public sealed partial class ImageResizerSizeToAccessibleTextConverter : IValueConverter
{
private const char TimesGlyph = '\u00D7'; // Unicode "MULTIPLICATION SIGN"
/// <summary>
/// Maps the supplied accessibility identifier to the format string of the localized accessible text.
/// </summary>
private static readonly Dictionary<string, string> AccessibilityFormats = new()
{
{ "Edit", Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_EditButton_Accessibility_Name") },
{ "Remove", Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_RemoveButton_Accessibility_Name") },
};
private readonly ImageResizerFitToStringConverter _fitConverter = new();
private readonly ImageResizerUnitToStringConverter _unitConverter = new();
public object Convert(object value, Type targetType, object parameter, string language)
{
return (value, parameter) switch
{
(string presetName, string nameId) => FormatNameText(presetName, nameId),
(ImageSize preset, string _) => FormatDescriptionText(preset),
_ => DependencyProperty.UnsetValue,
};
}
private object FormatNameText(string presetName, string nameId)
{
return AccessibilityFormats.TryGetValue(nameId, out string format) ?
string.Format(CultureInfo.CurrentCulture, format, presetName) :
DependencyProperty.UnsetValue;
}
private object FormatDescriptionText(ImageSize preset)
{
if (preset == null)
{
return DependencyProperty.UnsetValue;
}
string fitText = _fitConverter.Convert(preset.Fit, typeof(string), null, null) as string;
string unitText = _unitConverter.Convert(preset.Unit, typeof(string), null, null) as string;
return preset.IsHeightUsed ?
$"{preset.Name} - {fitText} {preset.Width} {TimesGlyph} {preset.Height} {unitText}" :
$"{preset.Name} - {fitText} {preset.Width} {unitText}";
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}

Просмотреть файл

@ -3,42 +3,39 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.Converters
namespace Microsoft.PowerToys.Settings.UI.Converters;
public sealed partial class ImageResizerUnitToStringConverter : IValueConverter
{
public sealed partial class ImageResizerUnitToStringConverter : IValueConverter
// Maps each ResizeUnit value to its localized string.
private static readonly Dictionary<ResizeUnit, string> UnitToText = new()
{
public object Convert(object value, Type targetType, object parameter, string language)
{ ResizeUnit.Centimeter, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Centimeter") },
{ ResizeUnit.Inch, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Inch") },
{ ResizeUnit.Percent, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Percent") },
{ ResizeUnit.Pixel, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Pixel") },
};
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is ResizeUnit unit && UnitToText.TryGetValue(unit, out string unitText))
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Centimeter"); break;
case 1: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Inch"); break;
case 2: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Percent"); break;
case 3: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Pixel"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
return parameter is string lowerParam && lowerParam == "ToLower" ?
unitText.ToLower(CultureInfo.CurrentCulture) :
unitText;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}

Просмотреть файл

@ -33,4 +33,10 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
public IntPtr Hook = IntPtr.Zero;
public string Template;
}
// https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea
public enum OpenFileNameFlags
{
OFN_NOCHANGEDIR = 0x00000008,
}
}

Просмотреть файл

@ -11,6 +11,7 @@
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml" />
<ResourceDictionary Source="/SettingsXAML/Styles/TextBlock.xaml" />
<ResourceDictionary Source="/SettingsXAML/Styles/Button.xaml" />
<ResourceDictionary Source="/SettingsXAML/Styles/InfoBadge.xaml" />
<ResourceDictionary Source="/SettingsXAML/Themes/Colors.xaml" />
<ResourceDictionary Source="/SettingsXAML/Themes/Generic.xaml" />
<!-- Other merged dictionaries here -->

Просмотреть файл

@ -35,7 +35,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard
x:Uid="MouseUtils_MouseJump_ActivationShortcut"
@ -249,4 +253,4 @@
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
</UserControl>
</UserControl>

Просмотреть файл

@ -0,0 +1,23 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="NewInfoBadge" TargetType="InfoBadge">
<Setter Property="Padding" Value="5,1,5,2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="InfoBadge">
<Border
x:Name="RootGrid"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
CornerRadius="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.InfoBadgeCornerRadius}">
<TextBlock
x:Uid="SettingsPage_NewInfoBadge"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="10" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -56,9 +56,23 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="AdvancedPaste_EnableAISettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<InfoBar
x:Uid="GPO_AdvancedPasteAi_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.ShowOnlineAIModelsGpoConfiguredInfoBar, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowOnlineAIModelsGpoConfiguredInfoBar, Mode=OneWay}"
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_EnableAISettingsCard" IsEnabled="{x:Bind ViewModel.IsOnlineAIModelsDisallowedByGPO, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<tkcontrols:SettingsCard.HeaderIcon>
<PathIcon Data="M128 766q0-42 24-77t65-48l178-57q32-11 61-30t52-42q50-50 71-114l58-179q13-40 48-65t78-26q42 0 77 24t50 65l58 177q21 66 72 117 49 50 117 72l176 58q43 14 69 48t26 80q0 41-25 76t-64 49l-178 58q-66 21-117 72-32 32-51 73t-33 84-26 83-30 73-45 51-71 20q-42 0-77-24t-49-65l-58-178q-8-25-19-47t-28-43q-34-43-77-68t-89-41-89-27-78-29-55-45-21-75zm1149 7q-76-29-145-53t-129-60-104-88-73-138l-57-176-67 176q-18 48-42 89t-60 78q-34 34-76 61t-89 43l-177 57q75 29 144 53t127 60 103 89 73 137l57 176 67-176q37-97 103-168t168-103l177-57zm-125 759q0-31 20-57t49-36l99-32q34-11 53-34t30-51 20-59 20-54 33-41 58-16q32 0 59 19t38 50q6 20 11 40t13 40 17 38 25 34q16 17 39 26t48 18 49 16 44 20 31 32 12 50q0 33-18 60t-51 38q-19 6-39 11t-41 13-39 17-34 25q-24 25-35 62t-24 73-35 61-68 25q-32 0-59-19t-38-50q-6-18-11-39t-13-41-17-40-24-33q-18-17-41-27t-47-17-49-15-43-20-30-33-12-54zm583 4q-43-13-74-30t-55-41-40-55-32-74q-12 41-29 72t-42 55-55 42-71 31q81 23 128 71t71 129q15-43 31-74t40-54 53-40 75-32z" />
@ -81,12 +95,6 @@
</StackPanel>
</tkcontrols:SettingsCard.Description>
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.ShowOnlineAIModelsGpoConfiguredInfoBar, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowOnlineAIModelsGpoConfiguredInfoBar, Mode=OneWay}"
Severity="Informational" />
<tkcontrols:SettingsCard
x:Uid="AdvancedPaste_EnableAdvancedAI"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/SemanticKernel.png}"
@ -107,8 +115,15 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.ShowClipboardHistoryIsGpoConfiguredInfoBar, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowClipboardHistoryIsGpoConfiguredInfoBar, Mode=OneWay}"
Severity="Informational" />
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_CloseAfterLosingFocus" HeaderIcon="{ui:FontIcon Glyph=&#xED1A;}">
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_CloseAfterLosingFocus">
<tkcontrols:SettingsCard.HeaderIcon>
<PathIcon Data="M 4 16.284 C 1 22.284 29 59.284 71 101.284 L 143 174.284 L 101 220.284 C 54 271.284 5 367.284 14 390.284 C 23 416.284 40 406.284 56 367.284 C 64 347.284 76 320.284 82 307.284 C 97 278.284 160 215.284 175 215.284 C 181 215.284 199 228.284 214 243.284 C 239 270.284 240 273.284 224 286.284 C 202 304.284 180 357.284 180 392.284 C 180 430.284 213 481.284 252 505.284 C 297 532.284 349 531.284 394 500.284 C 414 486.284 434 475.284 438 475.284 C 442 475.284 484 514.284 532 562.284 C 602 631.284 622 647.284 632 637.284 C 642 627.284 581 561.284 335 315.284 C 164 144.284 22 5.284 18 5.284 C 14 5.284 8 10.284 4 16.284 Z M 337 367.284 C 372 401.284 400 435.284 400 442.284 C 400 457.284 349 485.284 321 485.284 C 269 485.284 220 437.284 220 385.284 C 220 357.284 248 305.284 262 305.284 C 269 305.284 303 333.284 337 367.284 Z M 248 132.284 C 228 137.284 225 151.284 241 161.284 C 247 164.284 284 168.284 324 169.284 C 393 171.284 442 188.284 491 227.284 C 522 252.284 578 335.284 585 364.284 C 592 399.284 607 412.284 622 397.284 C 629 390.284 627 370.284 615 333.284 C 590 260.284 506 176.284 427 147.284 C 373 127.284 293 120.284 248 132.284 Z" />
</tkcontrols:SettingsCard.HeaderIcon>
<ToggleSwitch IsOn="{x:Bind ViewModel.CloseAfterLosingFocus, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_ShowCustomPreviewSettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE71E;}">

Просмотреть файл

@ -27,7 +27,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="AlwaysOnTop_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander

Просмотреть файл

@ -34,7 +34,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Awake_BehaviorSettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">

Просмотреть файл

@ -164,7 +164,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
// Get the enabled state from GPO.
ViewModel.IsEnabledGpoConfigured = true;
ViewModel.IsEnabled = enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
ViewModel.EnabledGPOConfiguration = enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{

Просмотреть файл

@ -21,16 +21,29 @@
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<InfoBar
x:Uid="GPO_SettingIsManaged"
x:Uid="GPO_CommandNotFound_ForceEnabled"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
IsOpen="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay}"
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<InfoBar
x:Uid="GPO_CommandNotFound_ForceDisabled"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay}"
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="CmdNotFound_Enable"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/CommandNotFound.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
IsExpanded="True">
<tkcontrols:SwitchPresenter TargetType="x:Boolean" Value="{x:Bind ViewModel.IsCommandNotFoundModuleInstalled, Mode=OneWay}">
<tkcontrols:Case Value="True">
@ -45,13 +58,17 @@
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource SystemFillColorSuccessBrush}"
Glyph="&#xEC61;" />
<HyperlinkButton x:Uid="CmdNotFound_UninstallButton" Command="{x:Bind ViewModel.UninstallModuleEventHandler}" />
<HyperlinkButton
x:Uid="CmdNotFound_UninstallButton"
Command="{x:Bind ViewModel.UninstallModuleEventHandler}"
IsEnabled="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
</StackPanel>
</tkcontrols:Case>
<tkcontrols:Case Value="False">
<Button
x:Uid="CmdNotFound_InstallButton"
Command="{x:Bind ViewModel.InstallModuleEventHandler}"
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
Style="{StaticResource AccentButtonStyle}" />
</tkcontrols:Case>
</tkcontrols:SwitchPresenter>
@ -98,7 +115,10 @@
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
Glyph="&#xEB90;" />
<Button x:Uid="CmdNotFound_InstallButton" Command="{x:Bind ViewModel.InstallPowerShell7EventHandler}" />
<Button
x:Uid="CmdNotFound_InstallButton"
Command="{x:Bind ViewModel.InstallPowerShell7EventHandler}"
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
</StackPanel>
</tkcontrols:Case>
</tkcontrols:SwitchPresenter>
@ -128,7 +148,10 @@
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
Glyph="&#xEB90;" />
<Button x:Uid="CmdNotFound_InstallButton" Command="{x:Bind ViewModel.InstallWinGetClientModuleEventHandler}" />
<Button
x:Uid="CmdNotFound_InstallButton"
Command="{x:Bind ViewModel.InstallWinGetClientModuleEventHandler}"
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
</StackPanel>
</tkcontrols:Case>
</tkcontrols:SwitchPresenter>
@ -142,7 +165,6 @@
<TextBox
Height="300"
FontFamily="Consolas"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
IsReadOnly="True"
Text="{x:Bind ViewModel.CommandOutputLog, Mode=OneWay}"
TextWrapping="Wrap" />

Просмотреть файл

@ -37,7 +37,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="Activation_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">

Просмотреть файл

@ -27,7 +27,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="CropAndLock_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="CropAndLock_ThumbnailActivation_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">

Просмотреть файл

@ -348,17 +348,28 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Width="20" Margin="0,0,0,0">
<Image
Grid.Column="0"
Width="20"
Margin="0,0,0,0">
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
<TextBlock
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
<InfoBadge
Margin="4,0,0,0"
Style="{StaticResource NewInfoBadge}"
Visibility="{x:Bind IsNew, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" />
</StackPanel>
<FontIcon
Grid.Column="2"
Width="20"
@ -440,17 +451,25 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Width="20">
<Image Grid.Column="0" Width="20">
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
<TextBlock
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
<InfoBadge
Margin="4,0,0,0"
Style="{StaticResource NewInfoBadge}"
Visibility="{x:Bind IsNew, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}" />
</StackPanel>
<FontIcon
Grid.Column="2"
Width="20"

Просмотреть файл

@ -23,7 +23,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="EnvironmentVariables_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="EnvironmentVariables_LaunchButtonControl"

Просмотреть файл

@ -24,7 +24,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="FancyZones_Editor_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard

Просмотреть файл

@ -25,7 +25,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="FileLocksmith_ShellIntegration" IsEnabled="{x:Bind ViewModel.IsFileLocksmithEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="FileLocksmith_Toggle_ContextMenu">

Просмотреть файл

@ -63,7 +63,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.SomeUpdateSettingsAreGpoManaged, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.SomeUpdateSettingsAreGpoManaged, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
</tkcontrols:SettingsExpander.ItemsHeader>
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard
@ -379,7 +383,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsExperimentationGpoDisallowed, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsExperimentationGpoDisallowed, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
<StackPanel>
@ -393,17 +401,24 @@
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="GeneralPage_ViewDiagnosticData"
HeaderIcon="{ui:FontIcon Glyph=&#xE7EF;}"
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
IsExpanded="True">
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard x:Uid="GeneralPage_EnableViewDiagnosticData">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsEnabled="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}"
IsOn="{x:Bind ViewModel.EnableViewDataDiagnostics, Mode=TwoWay}" />
<tkcontrols:SettingsCard x:Uid="GeneralPage_EnableViewDiagnosticData" IsEnabled="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.EnableViewDataDiagnostics, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Uid="GeneralPage_ViewDiagnosticDataViewer"
@ -422,12 +437,6 @@
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
</InfoBar.ActionButton>
</InfoBar>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
Severity="Informational" />
</StackPanel>
</controls:SettingsGroup>
@ -445,4 +454,4 @@
<controls:PageLink x:Uid="OpenSource_Notice" Link="https://github.com/microsoft/PowerToys/blob/main/NOTICE.md" />
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>
</Page>

Просмотреть файл

@ -23,7 +23,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Hosts_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="Hosts_LaunchButtonControl"

Просмотреть файл

@ -18,6 +18,7 @@
<converters:ImageResizerFitToIntConverter x:Key="ImageResizerFitToIntConverter" />
<converters:ImageResizerUnitToStringConverter x:Key="ImageResizerUnitToStringConverter" />
<converters:ImageResizerUnitToIntConverter x:Key="ImageResizerUnitToIntConverter" />
<converters:ImageResizerSizeToAccessibleTextConverter x:Key="ImageResizerSizeToAccessibleTextConverter" />
<toolkitconverters:BoolToObjectConverter
x:Key="BoolToComboBoxIndexConverter"
FalseValue="1"
@ -38,7 +39,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="ImageResizer_CustomSizes" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="ImageResizer_Presets" HeaderIcon="{ui:FontIcon Glyph=&#xE792;}">
@ -81,13 +86,13 @@
FontSize="10"
Style="{ThemeResource SecondaryTextStyle}"
Text="&#xE947;"
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock
Margin="0,0,4,0"
FontWeight="SemiBold"
Style="{ThemeResource SecondaryTextStyle}"
Text="{x:Bind Height, Mode=OneWay}"
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock
Margin="0,0,4,0"
Style="{ThemeResource SecondaryTextStyle}"
@ -100,9 +105,11 @@
Orientation="Horizontal"
Spacing="8">
<Button
x:Uid="EditButton"
x:Uid="ImageResizer_EditButton"
Width="40"
Height="36"
AutomationProperties.FullDescription="{x:Bind AccessibleTextHelper, Mode=OneWay, Converter={StaticResource ImageResizerSizeToAccessibleTextConverter}, ConverterParameter='Edit'}"
AutomationProperties.Name="{x:Bind Name, Mode=OneWay, Converter={StaticResource ImageResizerSizeToAccessibleTextConverter}, ConverterParameter='Edit'}"
Content="&#xE70F;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Style="{StaticResource SubtleButtonStyle}">
@ -141,10 +148,10 @@
Width="116"
Minimum="0"
SpinButtonPlacementMode="Compact"
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
Value="{x:Bind Height, Mode=TwoWay}" />
</StackPanel>
<ComboBox
x:Uid="ImageResizer_Size"
Width="240"
@ -160,10 +167,11 @@
</Button>
<Button
x:Name="RemoveButton"
x:Uid="RemoveButton"
x:Uid="ImageResizer_RemoveButton"
Width="40"
Height="36"
AutomationProperties.FullDescription="{x:Bind AccessibleTextHelper, Mode=OneWay, Converter={StaticResource ImageResizerSizeToAccessibleTextConverter}, ConverterParameter='Remove'}"
AutomationProperties.Name="{x:Bind Name, Mode=OneWay, Converter={StaticResource ImageResizerSizeToAccessibleTextConverter}, ConverterParameter='Remove'}"
Click="DeleteCustomSize"
CommandParameter="{Binding Id}"
Content="&#xE74D;"

Просмотреть файл

@ -22,11 +22,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
Func<string, string> loader = (string name) =>
{
return resourceLoader.GetString(name);
};
var resourceLoader = ResourceLoaderInstance.ResourceLoader;
Func<string, string> loader = resourceLoader.GetString;
ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, loader);
DataContext = ViewModel;
@ -69,7 +66,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
try
{
ViewModel.AddRow(Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_DefaultSize_NewSizePrefix"));
ViewModel.AddImageSize();
}
catch (Exception ex)
{

Просмотреть файл

@ -70,7 +70,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="KeyboardManager_Keys" IsEnabled="{x:Bind ViewModel.Enabled, Mode=OneWay}">
<tkcontrols:SettingsCard

Просмотреть файл

@ -24,7 +24,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="MeasureTool_ActivationSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="MeasureTool_ActivationShortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}" />

Просмотреть файл

@ -34,7 +34,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsFindMyMouseEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsFindMyMouseEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="MouseUtils_FindMyMouse_ActivationMethod"
HeaderIcon="{ui:FontIcon Glyph=&#xE961;}"
@ -188,7 +192,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsHighlighterEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsHighlighterEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="MouseUtils_MouseHighlighter_ActivationShortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
@ -260,7 +268,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsMousePointerCrosshairsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsMousePointerCrosshairsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="MouseUtils_MousePointerCrosshairs_ActivationShortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"

Просмотреть файл

@ -35,7 +35,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="MouseWithoutBorders_KeySettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
@ -214,9 +218,9 @@
IsOpen="{x:Bind ViewModel.ShowPolicyConfiguredInfoForBehaviorSettings, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowPolicyConfiguredInfoForBehaviorSettings, Mode=OneWay}"
Severity="Informational">
<!--InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource-->
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard x:Uid="MouseWithoutBorders_WrapMouse">
<ToggleSwitch x:Uid="MouseWithoutBorders_WrapMouse_ToggleSwitch" IsOn="{x:Bind ViewModel.WrapMouse, Mode=TwoWay}" />
@ -337,9 +341,9 @@
IsOpen="True"
IsTabStop="{x:Bind ViewModel.ShowPolicyConfiguredInfoForName2IPSetting, Mode=OneWay}"
Severity="Informational">
<!--InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource-->
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
@ -395,9 +399,9 @@
IsOpen="{x:Bind ViewModel.ShowPolicyConfiguredInfoForOriginalUiSetting, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowPolicyConfiguredInfoForOriginalUiSetting, Mode=OneWay}"
Severity="Informational">
<!--InfoBar.IconSource>
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource-->
</InfoBar.IconSource>
</InfoBar>
</controls:SettingsGroup>
</StackPanel>

Просмотреть файл

@ -22,13 +22,16 @@
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="NewPlus_Templates" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard
@ -70,9 +73,9 @@
IsOpen="{x:Bind ViewModel.IsHideFileExtSettingGPOConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsHideFileExtSettingGPOConfigured, Mode=OneWay}"
Severity="Informational">
<!-- InfoBar.IconSource>
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource-->
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard x:Uid="NewPlus_Hide_Starting_Digits_Toggle">
<ToggleSwitch x:Uid="HideStartingDigitsToggle" IsOn="{x:Bind ViewModel.HideStartingDigits, Mode=TwoWay}" />

Просмотреть файл

@ -24,7 +24,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Peek_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="Activation_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">

Просмотреть файл

@ -38,7 +38,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="QuickAccent_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander

Просмотреть файл

@ -316,7 +316,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind ViewModel.EnablePowerLauncher, Mode=OneWay}">
<tkcontrols:SettingsExpander
@ -565,7 +569,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.ShowPluginsAreGpoManagedInfo, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.ShowPluginsAreGpoManagedInfo, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<InfoBar
x:Uid="Run_AllPluginsDisabled"
IsClosable="False"

Просмотреть файл

@ -16,24 +16,29 @@
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="2">
<InfoBar
x:Uid="TextExtractor_UseSnippingToolWarning"
Margin="{x:Bind ViewModel.SnippingToolInfoBarMargin, Mode=OneWay}"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsWin11OrGreater, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsWin11OrGreater, Mode=OneWay}"
Severity="Informational" />
<tkcontrols:SettingsCard
x:Uid="TextExtractor_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/TextExtractor.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="TextExtractor_UseSnippingToolWarning"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsWin11OrGreater, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsWin11OrGreater, Mode=OneWay}"
Severity="Informational" />
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<InfoBar
x:Uid="TextExtractor_SupportedLanguages"
IsClosable="False"

Просмотреть файл

@ -26,7 +26,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.SomePreviewPaneEnabledGposConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.SomePreviewPaneEnabledGposConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsExpander
x:Uid="FileExplorerPreview_ToggleSwitch_Preview_SVG"
@ -171,7 +175,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.SomeThumbnailEnabledGposConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.SomeThumbnailEnabledGposConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<tkcontrols:SettingsCard
x:Uid="FileExplorerPreview_ToggleSwitch_Thumbnail_SVG"

Просмотреть файл

@ -27,7 +27,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="PowerRename_ShellIntegration" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander x:Uid="PowerRename_Toggle_ContextMenu" IsExpanded="False">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.EnabledOnContextExtendedMenu, Mode=TwoWay, Converter={StaticResource BoolToComboBoxIndexConverter}}">

Просмотреть файл

@ -25,7 +25,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="RegistryPreview_Launch_GroupSettings" IsEnabled="{x:Bind ViewModel.IsRegistryPreviewEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard

Просмотреть файл

@ -110,6 +110,9 @@
x:Uid="Shell_TopLevelSystemTools"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/SystemTools.png}"
SelectsOnInvoked="False">
<NavigationViewItem.InfoBadge>
<InfoBadge Style="{StaticResource NewInfoBadge}" />
</NavigationViewItem.InfoBadge>
<NavigationViewItem.MenuItems>
<NavigationViewItem
x:Uid="Shell_AdvancedPaste"
@ -142,7 +145,11 @@
<NavigationViewItem
x:Uid="Shell_ZoomIt"
helpers:NavHelper.NavigateTo="views:ZoomItPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/ZoomIt.png}" />
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/ZoomIt.png}">
<NavigationViewItem.InfoBadge>
<InfoBadge Style="{StaticResource NewInfoBadge}" />
</NavigationViewItem.InfoBadge>
</NavigationViewItem>
</NavigationViewItem.MenuItems>
</NavigationViewItem>

Просмотреть файл

@ -24,7 +24,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="ShortcutGuide_ActivationMethod">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.UseLegacyPressWinKeyBehavior, Mode=TwoWay, Converter={StaticResource BoolToComboBoxIndexConverter}}">

Просмотреть файл

@ -26,7 +26,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="Workspaces_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="Workspaces_ActivationShortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">

Просмотреть файл

@ -22,6 +22,13 @@
ModuleImageSource="ms-appx:///Assets/Settings/Modules/ZoomIt.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<InfoBar
x:Uid="ZoomIt_SimultaneousStandaloneZoomItWarning"
Margin="0,0,0,25"
IsClosable="False"
IsOpen="True"
IsTabStop="True"
Severity="Warning" />
<tkcontrols:SettingsCard
x:Uid="ZoomIt_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/ZoomIt.png}"
@ -33,13 +40,11 @@
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
<InfoBar
x:Uid="ZoomIt_SimultaneousStandaloneZoomItWarning"
IsClosable="False"
IsOpen="True"
IsTabStop="True"
Severity="Informational" />
Severity="Informational">
<InfoBar.IconSource>
<FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}" Glyph="&#xE72E;" />
</InfoBar.IconSource>
</InfoBar>
<controls:SettingsGroup x:Uid="ZoomIt_BehaviorGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="ZoomIt_Toggle_ShowTrayIcon">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.ShowTrayIcon, Mode=TwoWay}" />
@ -177,11 +182,8 @@
IsEnabled="{x:Bind ViewModel.BreakShowBackgroundFile, Mode=OneWay}">
<Button x:Uid="ZoomIt_Break_BackgroundFile_BrowseButton" Command="{x:Bind ViewModel.SelectBreakBackgroundFileCommand, Mode=OneWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="ZoomIt_Break_BackgroundStretch">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsEnabled="{x:Bind ViewModel.BreakShowBackgroundFile, Mode=OneWay}"
IsOn="{x:Bind ViewModel.BreakBackgroundStretch, Mode=TwoWay}" />
<tkcontrols:SettingsCard x:Uid="ZoomIt_Break_BackgroundStretch" IsEnabled="{x:Bind ViewModel.BreakShowBackgroundFile, Mode=OneWay}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.BreakBackgroundStretch, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>

Просмотреть файл

@ -35,6 +35,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
openFileName.Title = title;
openFileName.FilterIndex = initialFilter;
openFileName.DefExt = null;
openFileName.Flags = (int)OpenFileNameFlags.OFN_NOCHANGEDIR; // OFN_NOCHANGEDIR flag is needed, because otherwise GetOpenFileName overwrites the process working directory.
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
openFileName.Hwnd = windowHandle;

Просмотреть файл

@ -879,7 +879,7 @@
<value>Location</value>
</data>
<data name="General_SettingsBackupAndRestore_ButtonBackup.Content" xml:space="preserve">
<value>Backup</value>
<value>Back up</value>
</data>
<data name="General_SettingsBackupInfo_FileNameHeader.Text" xml:space="preserve">
<value>File name:</value>
@ -1104,10 +1104,10 @@
<value>Appearance &amp; behavior</value>
</data>
<data name="General_SettingsBackupAndRestoreTitle.Header" xml:space="preserve">
<value>Backup &amp; restore</value>
<value>Back up &amp; restore</value>
</data>
<data name="General_SettingsBackupAndRestore.Header" xml:space="preserve">
<value>Backup and restore your settings</value>
<value>Back up and restore your settings</value>
</data>
<data name="General_SettingsBackupAndRestore.Description" xml:space="preserve">
<value>PowerToys will restart automatically if needed</value>
@ -1169,10 +1169,6 @@
<data name="ImageResizer_Size.Header" xml:space="preserve">
<value>Unit</value>
</data>
<data name="RemoveButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Remove</value>
<comment>Removes a user defined setting group for Image Resizer</comment>
</data>
<data name="RemoveItem.Text" xml:space="preserve">
<value>Delete</value>
</data>
@ -2352,12 +2348,29 @@ From there, simply click on one of the supported files in the File Explorer and
<data name="ImageResizer_Unit_Pixel" xml:space="preserve">
<value>Pixels</value>
</data>
<data name="EditButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<data name="ImageResizer_EditButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Edit</value>
</data>
<data name="ImageResizer_EditSize.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Edit size</value>
</data>
<data name="ImageResizer_Presets.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>ImageResizer presets</value>
</data>
<data name="ImageResizer_AddSizeButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Add a new preset</value>
</data>
<data name="ImageResizer_RemoveButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Remove</value>
</data>
<data name="ImageResizer_EditButton_Accessibility_Name" xml:space="preserve">
<value>Edit the {0} preset</value>
<comment>Expands to the AutomationProperties.Name value for the Edit button. Example: "Edit the Small preset".</comment>
</data>
<data name="ImageResizer_RemoveButton_Accessibility_Name" xml:space="preserve">
<value>Remove the {0} preset</value>
<comment>Expands to the AutomationProperties.Name value for the Remove button. Example: "Remove the Large preset".</comment>
</data>
<data name="No" xml:space="preserve">
<value>No</value>
<comment>Label of a cancel button</comment>
@ -3330,7 +3343,7 @@ Activate by holding the key for the character you want to add an accent to, then
<value>There was an error in the settings format. Please check the settings file:</value>
</data>
<data name="General_SettingsBackupAndRestore_BackupComplete" xml:space="preserve">
<value>Backup completed.</value>
<value>Back up completed.</value>
</data>
<data name="General_SettingsBackupAndRestore_NoBackupSyncPath" xml:space="preserve">
<value>No backup location selected.</value>
@ -4277,6 +4290,9 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="GPO_SomeSettingsAreManaged.Title" xml:space="preserve">
<value>Some settings are managed by your organization.</value>
</data>
<data name="GPO_AdvancedPasteAi_SettingIsManaged.Title" xml:space="preserve">
<value>AI features are managed by your organization.</value>
</data>
<data name="GPO_SettingIsManaged_ToolTip.Text" xml:space="preserve">
<value>This setting is managed by your organization.</value>
</data>
@ -4340,6 +4356,14 @@ Activate by holding the key for the character you want to add an accent to, then
<value>Automatically close the AdvancedPaste window after it loses focus</value>
<comment>AdvancedPaste is a product name, do not loc</comment>
</data>
<data name="GPO_CommandNotFound_ForceDisabled.Title" xml:space="preserve">
<value>The Command Not Found module is disabled by your organization.</value>
<comment>"Command Not Found" is a product name</comment>
</data>
<data name="GPO_CommandNotFound_ForceEnabled.Title" xml:space="preserve">
<value>The Command Not Found module is enabled by your organization.</value>
<comment>"Command Not Found" is a product name</comment>
</data>
<data name="NewPlus.ModuleTitle" xml:space="preserve">
<value>New+</value>
<comment>New+ is the name of the utility. Localize product name in accordance with Windows New</comment>
@ -4364,7 +4388,7 @@ Activate by holding the key for the character you want to add an accent to, then
<comment>Localize product name in accordance with Windows New</comment>
</data>
<data name="NewPlus_TemplatesNotBackupAndRestoreWarning.Title" xml:space="preserve">
<value>PowerToys "Backup and Restore" feature doesn't take templates into account at this moment. If you use that feature, templates will have to be copied manually.</value>
<value>PowerToys "Back up and Restore" feature doesn't take templates into account at this moment. If you use that feature, templates will have to be copied manually.</value>
</data>
<data name="NewPlus_Templates.Header" xml:space="preserve">
<value>Templates</value>
@ -4856,4 +4880,8 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="PowerLauncher_PluginWebsite.Text" xml:space="preserve">
<value>Project website</value>
</data>
<data name="SettingsPage_NewInfoBadge.Text" xml:space="preserve">
<value>NEW</value>
<comment>Must be all caps</comment>
</data>
</root>

Просмотреть файл

@ -33,7 +33,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public bool IsEnabled
{
get => _isEnabled;
get
{
if (_enabledStateIsGPOConfigured)
{
return _enabledGPOConfiguration;
}
else
{
return _isEnabled;
}
}
set
{
if (_isEnabled != value)
@ -66,6 +77,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool EnabledGPOConfiguration
{
get => _enabledGPOConfiguration;
set
{
if (_enabledGPOConfiguration != value)
{
_enabledGPOConfiguration = value;
NotifyPropertyChanged();
}
}
}
public bool IsExpirationConfigurationEnabled => ModuleSettings.Properties.Mode == AwakeMode.EXPIRABLE && IsEnabled;
public bool IsTimeConfigurationEnabled => ModuleSettings.Properties.Mode == AwakeMode.TIMED && IsEnabled;
@ -198,6 +222,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
private bool _enabledStateIsGPOConfigured;
private bool _enabledGPOConfiguration;
private AwakeSettings _moduleSettings;
private bool _isEnabled;
}

Просмотреть файл

@ -32,7 +32,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public ButtonClickCommand UninstallModuleEventHandler => new ButtonClickCommand(UninstallModule);
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _moduleIsGpoEnabled;
private bool _moduleIsGpoDisabled;
public static string AssemblyDirectory
{
@ -53,11 +54,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredCmdNotFoundEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
}
_moduleIsGpoEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
_moduleIsGpoDisabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled;
// Update PATH environment variable to get pwsh.exe on further calls.
Environment.SetEnvironmentVariable("PATH", (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine) ?? string.Empty) + ";" + (Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User) ?? string.Empty), EnvironmentVariableTarget.Process);
@ -128,9 +126,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool IsEnabledGpoConfigured
public bool IsModuleGpoEnabled
{
get => _enabledStateIsGPOConfigured;
get => _moduleIsGpoEnabled;
}
public bool IsModuleGpoDisabled
{
get => _moduleIsGpoDisabled;
}
public string RunPowerShellOrPreviewScript(string powershellExecutable, string powershellArguments, bool hidePowerShellWindow = false)

Просмотреть файл

@ -20,6 +20,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public string Label { get; set; }
public bool IsNew { get; set; }
public string Icon { get; set; }
public string ToolTip { get; set; }

Просмотреть файл

@ -74,6 +74,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
Tag = moduleType,
Label = resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)),
IsNew = moduleType == ModuleType.ZoomIt,
IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType)),
IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
Icon = ModuleHelper.GetModuleTypeFluentIconName(moduleType),

Просмотреть файл

@ -3,431 +3,362 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
namespace Microsoft.PowerToys.Settings.UI.ViewModels;
public partial class ImageResizerViewModel : Observable
{
public class ImageResizerViewModel : Observable
private static readonly string DefaultPresetNamePrefix =
Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_DefaultSize_NewSizePrefix");
private static readonly List<string> EncoderGuids =
[
"1b7cfaf4-713f-473c-bbcd-6137425faeaf", // PNG Encoder
"0af1d87e-fcfe-4188-bdeb-a7906471cbe3", // Bitmap Encoder
"19e4a5aa-5662-4fc5-a0c0-1758028e1057", // JPEG Encoder
"163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", // TIFF Encoder
"57a37caa-367a-4540-916b-f183c5093a4b", // TIFF Encoder
"1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5", // GIF Encoder
];
/// <summary>
/// Used to skip saving settings to file during initialization.
/// </summary>
private readonly bool _isInitializing;
/// <summary>
/// Holds defaults for new presets.
/// </summary>
private readonly ImageSize _customSize;
private GeneralSettings GeneralSettingsConfig { get; set; }
private readonly ISettingsUtils _settingsUtils;
private ImageResizerSettings Settings { get; set; }
private const string ModuleName = ImageResizerSettings.ModuleName;
private Func<string, int> SendConfigMSG { get; }
public ImageResizerViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<string, string> resourceLoader)
{
private GeneralSettings GeneralSettingsConfig { get; set; }
_isInitializing = true;
private readonly ISettingsUtils _settingsUtils;
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
private ImageResizerSettings Settings { get; set; }
// To obtain the general settings configurations of PowerToys.
ArgumentNullException.ThrowIfNull(settingsRepository);
private const string ModuleName = ImageResizerSettings.ModuleName;
GeneralSettingsConfig = settingsRepository.SettingsConfig;
private Func<string, int> SendConfigMSG { get; }
public ImageResizerViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<string, string> resourceLoader)
try
{
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
// To obtain the general settings configurations of PowerToys.
ArgumentNullException.ThrowIfNull(settingsRepository);
GeneralSettingsConfig = settingsRepository.SettingsConfig;
try
{
Settings = _settingsUtils.GetSettings<ImageResizerSettings>(ModuleName);
}
catch (Exception e)
{
Logger.LogError($"Exception encountered while reading {ModuleName} settings.", e);
Settings = _settingsUtils.GetSettings<ImageResizerSettings>(ModuleName);
}
catch (Exception e)
{
Logger.LogError($"Exception encountered while reading {ModuleName} settings.", e);
#if DEBUG
if (e is ArgumentException || e is ArgumentNullException || e is PathTooLongException)
{
throw;
}
if (e is ArgumentException || e is ArgumentNullException || e is PathTooLongException)
{
throw;
}
#endif
Settings = new ImageResizerSettings(resourceLoader);
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
InitializeEnabledValue();
_advancedSizes = Settings.Properties.ImageresizerSizes.Value;
_jpegQualityLevel = Settings.Properties.ImageresizerJpegQualityLevel.Value;
_pngInterlaceOption = Settings.Properties.ImageresizerPngInterlaceOption.Value;
_tiffCompressOption = Settings.Properties.ImageresizerTiffCompressOption.Value;
_fileName = Settings.Properties.ImageresizerFileName.Value;
_keepDateModified = Settings.Properties.ImageresizerKeepDateModified.Value;
_encoderGuidId = GetEncoderIndex(Settings.Properties.ImageresizerFallbackEncoder.Value);
int i = 0;
foreach (ImageSize size in _advancedSizes)
{
size.Id = i;
i++;
size.PropertyChanged += SizePropertyChanged;
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private ObservableCollection<ImageSize> _advancedSizes = new ObservableCollection<ImageSize>();
private int _jpegQualityLevel;
private int _pngInterlaceOption;
private int _tiffCompressOption;
private string _fileName;
private bool _keepDateModified;
private int _encoderGuidId;
public bool IsListViewFocusRequested { get; set; }
public bool IsEnabled
{
get
{
return _isEnabled;
}
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (value != _isEnabled)
{
// To set the status of ImageResizer in the General PowerToys settings.
_isEnabled = value;
GeneralSettingsConfig.Enabled.ImageResizer = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public ObservableCollection<ImageSize> Sizes
{
get
{
return _advancedSizes;
}
set
{
SavesImageSizes(value);
_advancedSizes = value;
OnPropertyChanged(nameof(Sizes));
}
}
public int JPEGQualityLevel
{
get
{
return _jpegQualityLevel;
}
set
{
if (_jpegQualityLevel != value)
{
_jpegQualityLevel = value;
Settings.Properties.ImageresizerJpegQualityLevel.Value = value;
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(JPEGQualityLevel));
}
}
}
public int PngInterlaceOption
{
get
{
return _pngInterlaceOption;
}
set
{
if (_pngInterlaceOption != value)
{
_pngInterlaceOption = value;
Settings.Properties.ImageresizerPngInterlaceOption.Value = value;
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(PngInterlaceOption));
}
}
}
public int TiffCompressOption
{
get
{
return _tiffCompressOption;
}
set
{
if (_tiffCompressOption != value)
{
_tiffCompressOption = value;
Settings.Properties.ImageresizerTiffCompressOption.Value = value;
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(TiffCompressOption));
}
}
}
public string FileName
{
get
{
return _fileName;
}
set
{
if (!string.IsNullOrWhiteSpace(value))
{
_fileName = value;
Settings.Properties.ImageresizerFileName.Value = value;
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(FileName));
}
}
}
public bool KeepDateModified
{
get
{
return _keepDateModified;
}
set
{
_keepDateModified = value;
Settings.Properties.ImageresizerKeepDateModified.Value = value;
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(KeepDateModified));
}
}
public int Encoder
{
get
{
return _encoderGuidId;
}
set
{
if (_encoderGuidId != value)
{
_encoderGuidId = value;
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
Settings.Properties.ImageresizerFallbackEncoder.Value = GetEncoderGuid(value);
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
OnPropertyChanged(nameof(Encoder));
}
}
}
public string EncoderGuid
{
get
{
return ImageResizerViewModel.GetEncoderGuid(_encoderGuidId);
}
}
public void AddRow(string sizeNamePrefix)
{
/// This is a fallback validation to eliminate the warning "CA1062:Validate arguments of public methods" when using the parameter (variable) "sizeNamePrefix" in the code.
/// If the parameter is unexpectedly empty or null, we fill the parameter with a non-localized string.
/// Normally the parameter "sizeNamePrefix" can't be null or empty because it is filled with a localized string when we call this method from <see cref="UI.Views.ImageResizerPage.AddSizeButton_Click"/>.
sizeNamePrefix = string.IsNullOrEmpty(sizeNamePrefix) ? "New Size" : sizeNamePrefix;
ObservableCollection<ImageSize> imageSizes = Sizes;
int maxId = imageSizes.Count > 0 ? imageSizes.OrderBy(x => x.Id).Last().Id : -1;
string sizeName = GenerateNameForNewSize(imageSizes, sizeNamePrefix);
ImageSize newSize = new ImageSize(maxId + 1, sizeName, ResizeFit.Fit, 854, 480, ResizeUnit.Pixel);
newSize.PropertyChanged += SizePropertyChanged;
imageSizes.Add(newSize);
_advancedSizes = imageSizes;
SavesImageSizes(imageSizes);
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
IsListViewFocusRequested = true;
}
public void DeleteImageSize(int id)
{
ImageSize size = _advancedSizes.First(x => x.Id == id);
ObservableCollection<ImageSize> imageSizes = Sizes;
imageSizes.Remove(size);
_advancedSizes = imageSizes;
SavesImageSizes(imageSizes);
}
public void SavesImageSizes(ObservableCollection<ImageSize> imageSizes)
{
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
Settings.Properties.ImageresizerSizes = new ImageResizerSizes(imageSizes);
Settings = new ImageResizerSettings(resourceLoader);
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
public static string GetEncoderGuid(int value)
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
InitializeEnabledValue();
Sizes = new ObservableCollection<ImageSize>(Settings.Properties.ImageresizerSizes.Value);
JPEGQualityLevel = Settings.Properties.ImageresizerJpegQualityLevel.Value;
PngInterlaceOption = Settings.Properties.ImageresizerPngInterlaceOption.Value;
TiffCompressOption = Settings.Properties.ImageresizerTiffCompressOption.Value;
FileName = Settings.Properties.ImageresizerFileName.Value;
KeepDateModified = Settings.Properties.ImageresizerKeepDateModified.Value;
Encoder = GetEncoderIndex(Settings.Properties.ImageresizerFallbackEncoder.Value);
_customSize = Settings.Properties.ImageresizerCustomSize.Value;
_isInitializing = false;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// PNG Encoder guid
if (value == 0)
{
return "1b7cfaf4-713f-473c-bbcd-6137425faeaf";
}
// Bitmap Encoder guid
else if (value == 1)
{
return "0af1d87e-fcfe-4188-bdeb-a7906471cbe3";
}
// JPEG Encoder guid
else if (value == 2)
{
return "19e4a5aa-5662-4fc5-a0c0-1758028e1057";
}
// Tiff encoder guid.
else if (value == 3)
{
return "163bcc30-e2e9-4f0b-961d-a3e9fdb788a3";
}
// Tiff encoder guid.
else if (value == 4)
{
return "57a37caa-367a-4540-916b-f183c5093a4b";
}
// Gif encoder guid.
else if (value == 5)
{
return "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5";
}
return null;
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
public static int GetEncoderIndex(string value)
else
{
// PNG Encoder guid
if (value == "1b7cfaf4-713f-473c-bbcd-6137425faeaf")
{
return 0;
}
// Bitmap Encoder guid
else if (value == "0af1d87e-fcfe-4188-bdeb-a7906471cbe3")
{
return 1;
}
// JPEG Encoder guid
else if (value == "19e4a5aa-5662-4fc5-a0c0-1758028e1057")
{
return 2;
}
// Tiff encoder guid.
else if (value == "163bcc30-e2e9-4f0b-961d-a3e9fdb788a3")
{
return 3;
}
// Tiff encoder guid.
else if (value == "57a37caa-367a-4540-916b-f183c5093a4b")
{
return 4;
}
// Gif encoder guid.
else if (value == "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5")
{
return 5;
}
return -1;
}
public void SizePropertyChanged(object sender, PropertyChangedEventArgs e)
{
ImageSize modifiedSize = (ImageSize)sender;
ObservableCollection<ImageSize> imageSizes = Sizes;
imageSizes.First(x => x.Id == modifiedSize.Id).Update(modifiedSize);
_advancedSizes = imageSizes;
SavesImageSizes(imageSizes);
}
private static string GenerateNameForNewSize(in ObservableCollection<ImageSize> sizesList, in string namePrefix)
{
int newSizeCounter = 0;
foreach (ImageSize imgSize in sizesList)
{
string name = imgSize.Name;
if (name.StartsWith(namePrefix, StringComparison.InvariantCulture))
{
if (int.TryParse(name.AsSpan(namePrefix.Length), out int number))
{
if (newSizeCounter < number)
{
newSizeCounter = number;
}
}
}
}
return $"{namePrefix} {++newSizeCounter}";
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private ObservableCollection<ImageSize> _sizes = [];
private int _jpegQualityLevel;
private int _pngInterlaceOption;
private int _tiffCompressOption;
private string _fileName;
private bool _keepDateModified;
private int _encoderGuidId;
public bool IsListViewFocusRequested { get; set; }
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (value != _isEnabled)
{
// To set the status of ImageResizer in the General PowerToys settings.
_isEnabled = value;
GeneralSettingsConfig.Enabled.ImageResizer = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public ObservableCollection<ImageSize> Sizes
{
get => _sizes;
set
{
if (_sizes != null)
{
_sizes.CollectionChanged -= Sizes_CollectionChanged;
UnsubscribeFromItemPropertyChanged(_sizes);
}
_sizes = value;
if (_sizes != null)
{
_sizes.CollectionChanged += Sizes_CollectionChanged;
SubscribeToItemPropertyChanged(_sizes);
}
OnPropertyChanged(nameof(Sizes));
if (!_isInitializing)
{
SaveImageSizes();
}
}
}
private void Sizes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
SubscribeToItemPropertyChanged(e.NewItems?.Cast<ImageSize>());
UnsubscribeFromItemPropertyChanged(e.OldItems?.Cast<ImageSize>());
SaveImageSizes();
}
private void SubscribeToItemPropertyChanged(IEnumerable<ImageSize> items)
{
if (items != null)
{
foreach (var item in items)
{
item.PropertyChanged += SizePropertyChanged;
}
}
}
private void UnsubscribeFromItemPropertyChanged(IEnumerable<ImageSize> items)
{
if (items != null)
{
foreach (var item in items)
{
item.PropertyChanged -= SizePropertyChanged;
}
}
}
private void SetProperty<T>(ref T backingField, T value, Action<T> updateSettingsAction, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(backingField, value))
{
backingField = value;
if (!_isInitializing)
{
updateSettingsAction(value);
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
OnPropertyChanged(propertyName);
}
}
public int JPEGQualityLevel
{
get => _jpegQualityLevel;
set
{
SetProperty(ref _jpegQualityLevel, value, v => Settings.Properties.ImageresizerJpegQualityLevel.Value = v);
}
}
public int PngInterlaceOption
{
get => _pngInterlaceOption;
set
{
SetProperty(ref _pngInterlaceOption, value, v => Settings.Properties.ImageresizerPngInterlaceOption.Value = v);
}
}
public int TiffCompressOption
{
get => _tiffCompressOption;
set
{
SetProperty(ref _tiffCompressOption, value, v => Settings.Properties.ImageresizerTiffCompressOption.Value = v);
}
}
public string FileName
{
get => _fileName;
set
{
if (!string.IsNullOrWhiteSpace(value))
{
SetProperty(ref _fileName, value, v => Settings.Properties.ImageresizerFileName.Value = v);
}
}
}
public bool KeepDateModified
{
get => _keepDateModified;
set
{
SetProperty(ref _keepDateModified, value, v => Settings.Properties.ImageresizerKeepDateModified.Value = v);
}
}
public int Encoder
{
get => _encoderGuidId;
set
{
SetProperty(ref _encoderGuidId, value, v => Settings.Properties.ImageresizerFallbackEncoder.Value = GetEncoderGuid(v));
}
}
public string EncoderGuid => GetEncoderGuid(_encoderGuidId);
public static string GetEncoderGuid(int index) =>
index < 0 || index >= EncoderGuids.Count ? throw new ArgumentOutOfRangeException(nameof(index)) : EncoderGuids[index];
public static int GetEncoderIndex(string encoderGuid)
{
int index = EncoderGuids.IndexOf(encoderGuid);
return index == -1 ? throw new ArgumentException("Encoder GUID not found.", nameof(encoderGuid)) : index;
}
public void AddImageSize(string namePrefix = "")
{
if (string.IsNullOrEmpty(namePrefix))
{
namePrefix = DefaultPresetNamePrefix;
}
int maxId = Sizes.Count > 0 ? Sizes.Max(x => x.Id) : -1;
string sizeName = GenerateNameForNewSize(namePrefix);
Sizes.Add(new ImageSize(maxId + 1, GenerateNameForNewSize(namePrefix), _customSize.Fit, _customSize.Width, _customSize.Height, _customSize.Unit));
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
IsListViewFocusRequested = true;
}
public void DeleteImageSize(int id)
{
ImageSize size = _sizes.First(x => x.Id == id);
Sizes.Remove(size);
}
public void SaveImageSizes()
{
Settings.Properties.ImageresizerSizes = new ImageResizerSizes(Sizes);
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
public void SizePropertyChanged(object sender, PropertyChangedEventArgs e)
{
SaveImageSizes();
}
private string GenerateNameForNewSize(string namePrefix)
{
int newSizeCounter = 0;
foreach (var name in Sizes.Select(x => x.Name))
{
if (name.StartsWith(namePrefix, StringComparison.InvariantCulture) &&
int.TryParse(name.AsSpan(namePrefix.Length), out int number) &&
newSizeCounter < number)
{
newSizeCounter = number;
}
}
return $"{namePrefix} {++newSizeCounter}";
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}

Просмотреть файл

@ -264,6 +264,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GC.SuppressFinalize(this);
}
public string SnippingToolInfoBarMargin
{
// Workaround for wrong StackPanel behavior: On hidden controls the margin is still reserved.
get => IsWin11OrGreater ? "0,0,0,25" : "0,0,0,0";
}
private string EnsureStartUpper(string input)
{
if (string.IsNullOrEmpty(input))