mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-01 01:46:50 +01:00
Compare commits
2 Commits
dev/snickl
...
user/yeela
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d4d1bf383 | ||
|
|
2a051e9c67 |
1
.github/actions/spell-check/excludes.txt
vendored
1
.github/actions/spell-check/excludes.txt
vendored
@@ -127,4 +127,3 @@
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
^src/common/CalculatorEngineCommon/exprtk\.hpp$
|
||||
|
||||
52
.github/actions/spell-check/expect.txt
vendored
52
.github/actions/spell-check/expect.txt
vendored
@@ -141,7 +141,7 @@ boxmodel
|
||||
BPBF
|
||||
bpmf
|
||||
bpp
|
||||
breadcrumb
|
||||
Breadcrumb
|
||||
Browsable
|
||||
BROWSEINFO
|
||||
bsd
|
||||
@@ -192,6 +192,7 @@ CImage
|
||||
cla
|
||||
CLASSDC
|
||||
CLASSNOTAVAILABLE
|
||||
cleanmgr
|
||||
clickable
|
||||
clickonce
|
||||
CLIENTEDGE
|
||||
@@ -203,6 +204,7 @@ CLIPSIBLINGS
|
||||
closesocket
|
||||
clp
|
||||
CLSCTX
|
||||
CLSCTXLOCALSERVER
|
||||
clsids
|
||||
Clusion
|
||||
cmder
|
||||
@@ -494,6 +496,7 @@ FFFF
|
||||
FILEEXPLORER
|
||||
FILEFLAGS
|
||||
FILEFLAGSMASK
|
||||
FILELOCKSMITH
|
||||
FILELOCKSMITHCONTEXTMENU
|
||||
FILELOCKSMITHEXT
|
||||
FILELOCKSMITHLIBINTEROP
|
||||
@@ -759,6 +762,7 @@ IUI
|
||||
IUnknown
|
||||
IUse
|
||||
IWIC
|
||||
iwr
|
||||
jfif
|
||||
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
|
||||
jjw
|
||||
@@ -1283,6 +1287,7 @@ prvpane
|
||||
psapi
|
||||
pscid
|
||||
PSECURITY
|
||||
psexec
|
||||
psfgao
|
||||
psfi
|
||||
PSMODULEPATH
|
||||
@@ -1540,6 +1545,7 @@ SLGP
|
||||
sln
|
||||
SMALLICON
|
||||
smartphone
|
||||
smileys
|
||||
SMTO
|
||||
SNAPPROCESS
|
||||
snk
|
||||
@@ -1676,6 +1682,7 @@ TESTONLY
|
||||
testprocess
|
||||
TEXCOORD
|
||||
TEXTBOXNEWLINE
|
||||
TEXTEXTRACTOR
|
||||
TEXTINCLUDE
|
||||
tfopen
|
||||
tgz
|
||||
@@ -1883,6 +1890,7 @@ WINDOWPOSCHANGING
|
||||
WINDOWSBUILDNUMBER
|
||||
windowssearch
|
||||
windowssettings
|
||||
windowsterminal
|
||||
WINDOWSTYLES
|
||||
WINDOWSTYLESICON
|
||||
winerror
|
||||
@@ -1986,6 +1994,7 @@ YStr
|
||||
YTM
|
||||
YVIRTUALSCREEN
|
||||
ZEROINIT
|
||||
Zhiwei
|
||||
zonable
|
||||
zoneset
|
||||
Zoneszonabletester
|
||||
@@ -2004,47 +2013,10 @@ culori
|
||||
Evercoder
|
||||
LCh
|
||||
CIELCh
|
||||
CLSCTXINPROCALL
|
||||
IIDI
|
||||
irow
|
||||
lcid
|
||||
ppwsz
|
||||
rguid
|
||||
VARTYPE
|
||||
advancedpaste
|
||||
appxpackage
|
||||
Ashcraft
|
||||
CDPX
|
||||
commandnotfound
|
||||
copyable
|
||||
Corpor
|
||||
cropandlock
|
||||
environmentvariables
|
||||
fileexploreraddons
|
||||
filelocksmith
|
||||
findmymouse
|
||||
fucntion
|
||||
fuzzingtesting
|
||||
hostsfileeditor
|
||||
hotfixes
|
||||
IDOn
|
||||
lcl
|
||||
LIBFUZZER
|
||||
makepri
|
||||
mikeclayton
|
||||
mousehighlighter
|
||||
mousejump
|
||||
mousepointer
|
||||
mouseutils
|
||||
MVPs
|
||||
onebranch
|
||||
PMs
|
||||
Psr
|
||||
quickaccent
|
||||
regsvr
|
||||
screenruler
|
||||
sharpfuzz
|
||||
sourced
|
||||
stuttery
|
||||
textextractor
|
||||
Windowss
|
||||
XLoc
|
||||
zonability
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
"PowerToys.ActionRunner.exe",
|
||||
"PowerToys.Update.exe",
|
||||
"PowerToys.BackgroundActivatorDLL.dll",
|
||||
|
||||
"Notifications.dll",
|
||||
"os-detection.dll",
|
||||
"PowerToys.exe",
|
||||
"PowerToys.FilePreviewCommon.dll",
|
||||
"PowerToys.Interop.dll",
|
||||
"Tools\\PowerToys.BugReportTool.exe",
|
||||
"StylesReportTool\\PowerToys.StylesReportTool.exe",
|
||||
|
||||
"Telemetry.dll",
|
||||
"CalculatorEngineCommon.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.ManagedCommon.dll",
|
||||
@@ -32,7 +33,7 @@
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
|
||||
"PowerToys.CmdNotFound.dll",
|
||||
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
@@ -53,7 +54,7 @@
|
||||
"PowerToys.Awake.exe",
|
||||
"PowerToys.Awake.dll",
|
||||
|
||||
|
||||
"fancyzones.dll",
|
||||
"PowerToys.FancyZonesEditor.exe",
|
||||
"PowerToys.FancyZonesEditor.dll",
|
||||
"PowerToys.FancyZonesEditorCommon.dll",
|
||||
@@ -135,7 +136,7 @@
|
||||
"PowerToys.PowerLauncher.dll",
|
||||
"PowerToys.PowerLauncher.exe",
|
||||
"PowerToys.PowerLauncher.Telemetry.dll",
|
||||
|
||||
"Wox.dll",
|
||||
"Wox.Infrastructure.dll",
|
||||
"Wox.Plugin.dll",
|
||||
"RunPlugins\\Calculator\\Microsoft.PowerToys.Run.Plugin.Calculator.dll",
|
||||
@@ -274,16 +275,16 @@
|
||||
"Mono.Cecil.Pdb.dll",
|
||||
"Mono.Cecil.Rocks.dll",
|
||||
"Newtonsoft.Json.dll",
|
||||
|
||||
"Newtonsoft.Json.Bson.dll",
|
||||
"NLog.dll",
|
||||
"HtmlAgilityPack.dll",
|
||||
"Markdig.Signed.dll",
|
||||
"HelixToolkit.dll",
|
||||
"HelixToolkit.Core.Wpf.dll",
|
||||
"Mages.Core.dll",
|
||||
|
||||
"JetBrains.Annotations.dll",
|
||||
"NLog.Extensions.Logging.dll",
|
||||
|
||||
"getfilesiginforedist.dll",
|
||||
"concrt140_app.dll",
|
||||
"msvcp140_1_app.dll",
|
||||
"msvcp140_2_app.dll",
|
||||
@@ -293,8 +294,22 @@
|
||||
"vcomp140_app.dll",
|
||||
"vcruntime140_1_app.dll",
|
||||
"vcruntime140_app.dll",
|
||||
|
||||
"WinUI3Apps\\CommunityToolkit.Labs.WinUI.SettingsControls.dll",
|
||||
"UnicodeInformation.dll",
|
||||
"Vanara.Core.dll",
|
||||
"Vanara.PInvoke.ComCtl32.dll",
|
||||
"Vanara.PInvoke.Cryptography.dll",
|
||||
"Vanara.PInvoke.Gdi32.dll",
|
||||
"Vanara.PInvoke.Kernel32.dll",
|
||||
"Vanara.PInvoke.Ole.dll",
|
||||
"Vanara.PInvoke.Rpc.dll",
|
||||
"Vanara.PInvoke.Security.dll",
|
||||
"Vanara.PInvoke.Shared.dll",
|
||||
"Vanara.PInvoke.Shell32.dll",
|
||||
"Vanara.PInvoke.ShlwApi.dll",
|
||||
"Vanara.PInvoke.User32.dll",
|
||||
"WinUI3Apps\\clrcompression.dll",
|
||||
"WinUI3Apps\\Microsoft.Graphics.Canvas.Interop.dll",
|
||||
"Microsoft.Web.WebView2.Core.dll",
|
||||
"Microsoft.Web.WebView2.WinForms.dll",
|
||||
"Microsoft.Web.WebView2.Wpf.dll",
|
||||
@@ -321,7 +336,7 @@
|
||||
"Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"WinUI3Apps\\Testably.Abstractions.FileSystem.Interface.dll",
|
||||
"ColorCode.Core.dll",
|
||||
|
||||
"ColorCode.UWP.dll",
|
||||
"UnitsNet.dll",
|
||||
"UtfUnknown.dll",
|
||||
"Wpf.Ui.dll"
|
||||
|
||||
@@ -32,22 +32,22 @@
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="3.1.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.6" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.7" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
@@ -75,28 +75,28 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.7" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.6" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.7" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.6" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.6" />
|
||||
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.6" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.7" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.6" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
|
||||
42
NOTICE.md
42
NOTICE.md
@@ -1517,23 +1517,23 @@ SOFTWARE.
|
||||
- Mages 3.0.0
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 3.1.3
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.7
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.6
|
||||
- Microsoft.Bot.AdaptiveExpressions.Core 4.23.0
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.7
|
||||
- Microsoft.Data.Sqlite 9.0.6
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.DotNet.ILCompiler (A)
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.7
|
||||
- Microsoft.Extensions.Hosting 9.0.7
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.7
|
||||
- Microsoft.Extensions.Logging 9.0.7
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.7
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.6
|
||||
- Microsoft.Extensions.Hosting 9.0.6
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.6
|
||||
- Microsoft.Extensions.Logging 9.0.6
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.6
|
||||
- Microsoft.NET.ILLink.Tasks (A)
|
||||
- Microsoft.SemanticKernel 1.15.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2903.40
|
||||
- Microsoft.Win32.SystemEvents 9.0.7
|
||||
- Microsoft.Windows.Compatibility 9.0.7
|
||||
- Microsoft.Win32.SystemEvents 9.0.6
|
||||
- Microsoft.Windows.Compatibility 9.0.6
|
||||
- Microsoft.Windows.CsWin32 0.3.183
|
||||
- Microsoft.Windows.CsWinRT 2.2.0
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.26100.4188
|
||||
@@ -1553,25 +1553,25 @@ SOFTWARE.
|
||||
- SkiaSharp.Views.WinUI 2.88.9
|
||||
- StreamJsonRpc 2.21.69
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.7
|
||||
- System.CodeDom 9.0.6
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
- System.ComponentModel.Composition 9.0.7
|
||||
- System.Configuration.ConfigurationManager 9.0.7
|
||||
- System.Data.OleDb 9.0.7
|
||||
- System.ComponentModel.Composition 9.0.6
|
||||
- System.Configuration.ConfigurationManager 9.0.6
|
||||
- System.Data.OleDb 9.0.6
|
||||
- System.Data.SqlClient 4.9.0
|
||||
- System.Diagnostics.EventLog 9.0.7
|
||||
- System.Diagnostics.PerformanceCounter 9.0.7
|
||||
- System.Drawing.Common 9.0.7
|
||||
- System.Diagnostics.EventLog 9.0.6
|
||||
- System.Diagnostics.PerformanceCounter 9.0.6
|
||||
- System.Drawing.Common 9.0.6
|
||||
- System.IO.Abstractions 22.0.13
|
||||
- System.IO.Abstractions.TestingHelpers 22.0.13
|
||||
- System.Management 9.0.7
|
||||
- System.Management 9.0.6
|
||||
- System.Net.Http 4.3.4
|
||||
- System.Private.Uri 4.3.2
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 9.0.7
|
||||
- System.ServiceProcess.ServiceController 9.0.7
|
||||
- System.Text.Encoding.CodePages 9.0.7
|
||||
- System.Text.Json 9.0.7
|
||||
- System.Runtime.Caching 9.0.6
|
||||
- System.ServiceProcess.ServiceController 9.0.6
|
||||
- System.Text.Encoding.CodePages 9.0.6
|
||||
- System.Text.Json 9.0.6
|
||||
- System.Text.RegularExpressions 4.3.1
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.56.0
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
## Localization on the pipeline (CDPX)
|
||||
[The localization step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L45-L52) is run on the pipeline before the solution is built. This step runs the [build-localization](https://github.com/microsoft/PowerToys/blob/main/.pipelines/build-localization.cmd) script, which generates resx files for all the projects with localization enabled using the `Localization.XLoc` package.
|
||||
|
||||
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [the loc folder in the Microsoft.Launcher module](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail in the [Lcl files section](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
|
||||
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail in the [Lcl files section](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
|
||||
|
||||
Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/main/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ This document outlines the process for preparing and publishing PowerToys releas
|
||||
- Uses semantic versioning: `MAJOR.MINOR.PATCH`
|
||||
- MINOR version increases with regular releases (e.g., 0.89.0)
|
||||
- PATCH version increases for hotfixes (e.g., 0.87.0 → 0.87.1)
|
||||
- Each release version must be greater than the previous one for proper updating
|
||||
- Each release version must be higher than the previous one for proper updating
|
||||
|
||||
## Testing Process
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define ImageResizerAssetsFiles=?>
|
||||
<?define ImageResizerAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ImageResizer\?>
|
||||
<?define ImageResizerAssetsFilesPath=$(var.BinDir)Assets\ImageResizer\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<DirectoryRef Id="BaseApplicationsAssetsFolder">
|
||||
<Directory Id="ImageResizerAssetsFolder" Name="ImageResizer" />
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<Component Id="Module_ImageResizer_Registry" Win64="yes">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\CLSID\{51B4D7E5-7568-4234-B4BB-47FB3C016A69}\InprocServer32">
|
||||
<RegistryValue Value="[WinUI3AppsInstallFolder]PowerToys.ImageResizerExt.dll" Type="string" />
|
||||
<RegistryValue Value="[INSTALLFOLDER]PowerToys.ImageResizerExt.dll" Type="string" />
|
||||
<RegistryValue Name="ThreadingModel" Value="Apartment" Type="string" />
|
||||
</RegistryKey>
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="ImageResizer_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="ImageResizer_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\WinUI3Apps\$(var.Language)\PowerToys.ImageResizer.resources.dll" />
|
||||
<File Id="ImageResizer_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)\$(var.Language)\PowerToys.ImageResizer.resources.dll" />
|
||||
</Component>
|
||||
<Component
|
||||
Id="ColorPicker_$(var.IdSafeLanguage)_Component"
|
||||
|
||||
@@ -179,7 +179,7 @@ Generate-FileList -fileDepsJson "" -fileListName HostsAssetsFiles -wxsFilePath $
|
||||
Generate-FileComponents -fileListName "HostsAssetsFiles" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot
|
||||
|
||||
#ImageResizer
|
||||
Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ImageResizer"
|
||||
Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ImageResizer"
|
||||
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs -regroot $registryroot
|
||||
|
||||
#New+
|
||||
|
||||
@@ -11,35 +11,26 @@ namespace Common.UI
|
||||
{
|
||||
public enum SettingsWindow
|
||||
{
|
||||
Dashboard = 0,
|
||||
Overview,
|
||||
AlwaysOnTop,
|
||||
Overview = 0,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdNotFound,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
Run,
|
||||
ImageResizer,
|
||||
KBM,
|
||||
MouseUtils,
|
||||
MouseWithoutBorders,
|
||||
Peek,
|
||||
PowerAccent,
|
||||
PowerLauncher,
|
||||
PowerPreview,
|
||||
PowerRename,
|
||||
FileExplorer,
|
||||
ShortcutGuide,
|
||||
Hosts,
|
||||
MeasureTool,
|
||||
PowerOCR,
|
||||
Workspaces,
|
||||
RegistryPreview,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
Dashboard,
|
||||
AdvancedPaste,
|
||||
NewPlus,
|
||||
Workspaces,
|
||||
CmdPal,
|
||||
ZoomIt,
|
||||
}
|
||||
@@ -48,22 +39,14 @@ namespace Common.UI
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case SettingsWindow.Dashboard:
|
||||
return "Dashboard";
|
||||
case SettingsWindow.Overview:
|
||||
return "Overview";
|
||||
case SettingsWindow.AlwaysOnTop:
|
||||
return "AlwaysOnTop";
|
||||
case SettingsWindow.Awake:
|
||||
return "Awake";
|
||||
case SettingsWindow.ColorPicker:
|
||||
return "ColorPicker";
|
||||
case SettingsWindow.CmdNotFound:
|
||||
return "CmdNotFound";
|
||||
case SettingsWindow.FancyZones:
|
||||
return "FancyZones";
|
||||
case SettingsWindow.FileLocksmith:
|
||||
return "FileLocksmith";
|
||||
case SettingsWindow.Run:
|
||||
return "Run";
|
||||
case SettingsWindow.ImageResizer:
|
||||
@@ -72,16 +55,6 @@ namespace Common.UI
|
||||
return "KBM";
|
||||
case SettingsWindow.MouseUtils:
|
||||
return "MouseUtils";
|
||||
case SettingsWindow.MouseWithoutBorders:
|
||||
return "MouseWithoutBorders";
|
||||
case SettingsWindow.Peek:
|
||||
return "Peek";
|
||||
case SettingsWindow.PowerAccent:
|
||||
return "PowerAccent";
|
||||
case SettingsWindow.PowerLauncher:
|
||||
return "PowerLauncher";
|
||||
case SettingsWindow.PowerPreview:
|
||||
return "PowerPreview";
|
||||
case SettingsWindow.PowerRename:
|
||||
return "PowerRename";
|
||||
case SettingsWindow.FileExplorer:
|
||||
@@ -94,18 +67,18 @@ namespace Common.UI
|
||||
return "MeasureTool";
|
||||
case SettingsWindow.PowerOCR:
|
||||
return "PowerOcr";
|
||||
case SettingsWindow.Workspaces:
|
||||
return "Workspaces";
|
||||
case SettingsWindow.RegistryPreview:
|
||||
return "RegistryPreview";
|
||||
case SettingsWindow.CropAndLock:
|
||||
return "CropAndLock";
|
||||
case SettingsWindow.EnvironmentVariables:
|
||||
return "EnvironmentVariables";
|
||||
case SettingsWindow.Dashboard:
|
||||
return "Dashboard";
|
||||
case SettingsWindow.AdvancedPaste:
|
||||
return "AdvancedPaste";
|
||||
case SettingsWindow.NewPlus:
|
||||
return "NewPlus";
|
||||
case SettingsWindow.Workspaces:
|
||||
return "Workspaces";
|
||||
case SettingsWindow.CmdPal:
|
||||
return "CmdPal";
|
||||
case SettingsWindow.ZoomIt:
|
||||
|
||||
@@ -21,7 +21,7 @@ public static partial class Kernel32
|
||||
out int pBytesReturned,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16, EntryPoint = "CreateFileW")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
public static partial int CreateFile(
|
||||
string lpFileName,
|
||||
FileAccessType dwDesiredAccess,
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using static Microsoft.PowerToys.UITest.WindowHelper;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
@@ -42,6 +41,18 @@ namespace Microsoft.PowerToys.UITest
|
||||
this.locationPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
|
||||
CheckWinAppDriverAndRoot();
|
||||
|
||||
var runnerProcessInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = locationPath + this.runnerPath,
|
||||
Verb = "runas",
|
||||
};
|
||||
|
||||
if (scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
this.ExitExe(runnerProcessInfo.FileName);
|
||||
this.runner = Process.Start(runnerProcessInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,7 +76,6 @@ namespace Microsoft.PowerToys.UITest
|
||||
public SessionHelper Init()
|
||||
{
|
||||
this.ExitExe(this.locationPath + this.sessionPath);
|
||||
|
||||
this.StartExe(this.locationPath + this.sessionPath);
|
||||
|
||||
Assert.IsNotNull(this.Driver, $"Failed to initialize the test environment. Driver is null.");
|
||||
@@ -79,6 +89,19 @@ namespace Microsoft.PowerToys.UITest
|
||||
public void Cleanup()
|
||||
{
|
||||
ExitScopeExe();
|
||||
try
|
||||
{
|
||||
if (this.scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
runner?.Kill();
|
||||
runner?.WaitForExit(); // Optional: Wait for the process to exit
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions if needed
|
||||
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,65 +135,10 @@ namespace Microsoft.PowerToys.UITest
|
||||
public void StartExe(string appPath)
|
||||
{
|
||||
var opts = new AppiumOptions();
|
||||
|
||||
// if we want to start settings, we need to use the runner exe to open settings
|
||||
if (scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
TryLaunchPowerToysSettings(opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
}
|
||||
|
||||
opts.AddAdditionalCapability("app", appPath);
|
||||
this.Driver = NewWindowsDriver(opts);
|
||||
}
|
||||
|
||||
private void TryLaunchPowerToysSettings(AppiumOptions opts)
|
||||
{
|
||||
CheckWinAppDriverAndRoot();
|
||||
|
||||
var runnerProcessInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = locationPath + this.runnerPath,
|
||||
Verb = "runas",
|
||||
Arguments = "--open-settings",
|
||||
};
|
||||
|
||||
this.ExitExe(runnerProcessInfo.FileName);
|
||||
this.runner = Process.Start(runnerProcessInfo);
|
||||
Thread.Sleep(5000);
|
||||
|
||||
if (root != null)
|
||||
{
|
||||
const int maxRetries = 3;
|
||||
const int delayMs = 5000;
|
||||
var windowName = "PowerToys Settings";
|
||||
|
||||
for (int attempt = 1; attempt <= maxRetries; attempt++)
|
||||
{
|
||||
var settingsWindow = ApiHelper.FindDesktopWindowHandler(
|
||||
new[] { windowName, AdministratorPrefix + windowName });
|
||||
|
||||
if (settingsWindow.Count > 0)
|
||||
{
|
||||
var hexHwnd = settingsWindow[0].HWnd.ToString("x");
|
||||
opts.AddAdditionalCapability("appTopLevelWindow", hexHwnd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attempt < maxRetries)
|
||||
{
|
||||
Thread.Sleep(delayMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TimeoutException("Failed to find PowerToys Settings window after multiple attempts.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new exe and takes control of it.
|
||||
/// </summary>
|
||||
@@ -208,19 +176,6 @@ namespace Microsoft.PowerToys.UITest
|
||||
public void ExitScopeExe()
|
||||
{
|
||||
ExitExe(sessionPath);
|
||||
try
|
||||
{
|
||||
if (this.scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
runner?.Kill();
|
||||
runner?.WaitForExit(); // Optional: Wait for the process to exit
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle exceptions if needed
|
||||
Debug.WriteLine($"Exception during Cleanup: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,9 +4,18 @@
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.Windows;
|
||||
using Windows.Devices.Display.Core;
|
||||
using Windows.Foundation.Metadata;
|
||||
using static Microsoft.PowerToys.UITest.UITestBase.NativeMethods;
|
||||
using static Microsoft.PowerToys.UITest.WindowHelper;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
@@ -68,6 +77,16 @@ namespace Microsoft.PowerToys.UITest
|
||||
|
||||
this.sessionHelper = new SessionHelper(scope).Init();
|
||||
this.Session = new Session(this.sessionHelper.GetRoot(), this.sessionHelper.GetDriver(), scope, size);
|
||||
|
||||
if (this.scope == PowerToysModule.PowerToysSettings)
|
||||
{
|
||||
// close Debug warning dialog if any
|
||||
// Such debug warning dialog seems only appear in PowerToys Settings
|
||||
if (this.FindAll("DEBUG").Count > 0)
|
||||
{
|
||||
this.Find("DEBUG").Find<Button>("Close").Click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.PowerToys.UITest
|
||||
{
|
||||
public static class WindowHelper
|
||||
internal static class WindowHelper
|
||||
{
|
||||
internal const string AdministratorPrefix = "Administrator: ";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Page
|
||||
<Page
|
||||
x:Class="WorkspacesEditor.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
@@ -172,7 +172,7 @@
|
||||
VerticalContentAlignment="Stretch"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Visibility="{Binding IsWorkspacesViewEmpty, Mode=OneWay, Converter={StaticResource BooleanToInvertedVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ItemsControl x:Name="WorkspacesItemsControl" ItemsSource="{Binding WorkspacesView, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ItemsControl ItemsSource="{Binding WorkspacesView, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel
|
||||
@@ -235,10 +235,7 @@
|
||||
Grid.Column="1"
|
||||
Margin="12,12,12,12"
|
||||
Orientation="Vertical">
|
||||
<StackPanel
|
||||
x:Name="WorkspaceActionGroup"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="MoreButton"
|
||||
HorizontalAlignment="Right"
|
||||
@@ -251,8 +248,7 @@
|
||||
</Button>
|
||||
<Popup
|
||||
AllowsTransparency="True"
|
||||
Closed="PopupClosed"
|
||||
IsOpen="{Binding IsPopupVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsOpen="{Binding IsPopupVisible, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Placement="Left"
|
||||
PlacementTarget="{Binding ElementName=MoreButton}"
|
||||
StaysOpen="False">
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using ManagedCommon;
|
||||
|
||||
using WorkspacesEditor.Models;
|
||||
using WorkspacesEditor.ViewModels;
|
||||
|
||||
@@ -43,28 +42,17 @@ namespace WorkspacesEditor
|
||||
e.Handled = true;
|
||||
Button button = sender as Button;
|
||||
Project selectedProject = button.DataContext as Project;
|
||||
selectedProject.IsPopupVisible = false;
|
||||
|
||||
_mainViewModel.DeleteProject(selectedProject);
|
||||
}
|
||||
|
||||
private void MoreButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_mainViewModel.CloseAllPopups();
|
||||
e.Handled = true;
|
||||
Button button = sender as Button;
|
||||
Project project = button.DataContext as Project;
|
||||
project.IsPopupVisible = true;
|
||||
}
|
||||
|
||||
private void PopupClosed(object sender, object e)
|
||||
{
|
||||
if (sender is Popup p && p.DataContext is Project proj)
|
||||
{
|
||||
proj.IsPopupVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void LaunchButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
@@ -437,11 +437,7 @@ namespace WorkspacesEditor.ViewModels
|
||||
private void RunSnapshotTool(bool isExistingProjectLaunched)
|
||||
{
|
||||
Process process = new Process();
|
||||
|
||||
var exeDir = Path.GetDirectoryName(Environment.ProcessPath);
|
||||
var snapshotUtilsPath = Path.Combine(exeDir, "PowerToys.WorkspacesSnapshotTool.exe");
|
||||
|
||||
process.StartInfo = new ProcessStartInfo(snapshotUtilsPath);
|
||||
process.StartInfo = new ProcessStartInfo(@".\PowerToys.WorkspacesSnapshotTool.exe");
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.StartInfo.Arguments = isExistingProjectLaunched ? $"{(int)InvokePoint.LaunchAndEdit}" : string.Empty;
|
||||
|
||||
|
||||
@@ -51,8 +51,6 @@
|
||||
MouseLeave="AppBorder_MouseLeave">
|
||||
<Expander
|
||||
Margin="0,0,20,0"
|
||||
AutomationProperties.AutomationId="{Binding AppName}"
|
||||
AutomationProperties.Name="{Binding AppName}"
|
||||
FlowDirection="RightToLeft"
|
||||
IsEnabled="{Binding IsIncluded, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
IsExpanded="{Binding IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
@@ -401,11 +399,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ItemsControl
|
||||
x:Name="CapturedAppList"
|
||||
AutomationProperties.Name="Captured Application List"
|
||||
ItemTemplateSelector="{StaticResource AppListDataTemplateSelector}"
|
||||
ItemsSource="{Binding ApplicationsListed, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ItemsControl ItemTemplateSelector="{StaticResource AppListDataTemplateSelector}" ItemsSource="{Binding ApplicationsListed, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -1,605 +0,0 @@
|
||||
// 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.Diagnostics;
|
||||
using Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace WorkspacesEditorUITest;
|
||||
|
||||
[TestClass]
|
||||
[Ignore("not stable")]
|
||||
public class WorkspacesEditingPageTests : WorkspacesUiAutomationBase
|
||||
{
|
||||
public WorkspacesEditingPageTests()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.RemoveApp")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestRemoveAppFromWorkspace()
|
||||
{
|
||||
// Find app list
|
||||
var appList = Find<Custom>("AppList");
|
||||
var initialAppCount = appList.FindAll<Custom>(By.ClassName("AppItem")).Count;
|
||||
|
||||
if (initialAppCount == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to remove");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove first app
|
||||
var firstApp = appList.FindAll<Custom>(By.ClassName("AppItem"))[0];
|
||||
var appName = firstApp.GetAttribute("Name");
|
||||
|
||||
var removeButton = firstApp.Find<Button>("Remove");
|
||||
removeButton.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify app removed from list
|
||||
var finalAppCount = appList.FindAll<Custom>(By.ClassName("AppItem")).Count;
|
||||
Assert.AreEqual(initialAppCount - 1, finalAppCount, "App should be removed from list");
|
||||
|
||||
// Verify preview updated
|
||||
var previewPane = Find<Pane>("Preview");
|
||||
var windowPreviews = previewPane.FindAll<Custom>(By.ClassName("WindowPreview"));
|
||||
Assert.AreEqual(finalAppCount, windowPreviews.Count, "Preview should show correct number of windows");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.RemoveAndAddBackApp")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestRemoveAndAddBackApp()
|
||||
{
|
||||
// Find app list
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to test");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstApp = apps[0];
|
||||
var appName = firstApp.GetAttribute("Name");
|
||||
|
||||
// Remove app
|
||||
var removeButton = firstApp.Find<Button>("Remove");
|
||||
removeButton.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify removed app shows in "removed apps" section
|
||||
Assert.IsTrue(Has<Button>("Add back"), "Should have 'Add back' button for removed apps");
|
||||
|
||||
// Add back the app
|
||||
var addBackButton = Find<Button>("Add back");
|
||||
addBackButton.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify app is back in the list
|
||||
var restoredApp = appList.Find<Custom>(By.Name(appName), timeoutMS: 2000);
|
||||
Assert.IsNotNull(restoredApp, "App should be restored to the list");
|
||||
|
||||
// Verify preview updated
|
||||
var previewPane = Find<Pane>("Preview");
|
||||
var windowPreviews = previewPane.FindAll<Custom>(By.ClassName("WindowPreview"));
|
||||
var currentAppCount = appList.FindAll<Custom>(By.ClassName("AppItem")).Count;
|
||||
Assert.AreEqual(currentAppCount, windowPreviews.Count, "Preview should show all windows again");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.SetAppMinimized")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestSetAppMinimized()
|
||||
{
|
||||
// Find first app
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to test");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstApp = apps[0];
|
||||
|
||||
// Find and toggle minimized checkbox
|
||||
var minimizedCheckbox = firstApp.Find<CheckBox>("Minimized");
|
||||
bool wasMinimized = minimizedCheckbox.IsChecked;
|
||||
|
||||
minimizedCheckbox.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify state changed
|
||||
Assert.AreNotEqual(wasMinimized, minimizedCheckbox.IsChecked, "Minimized state should toggle");
|
||||
|
||||
// Verify preview reflects the change
|
||||
var previewPane = Find<Pane>("Preview");
|
||||
var windowPreviews = previewPane.FindAll<Custom>(By.ClassName("WindowPreview"));
|
||||
|
||||
// The first window preview should indicate minimized state
|
||||
if (minimizedCheckbox.IsChecked && windowPreviews.Count > 0)
|
||||
{
|
||||
var firstPreview = windowPreviews[0];
|
||||
var opacity = firstPreview.GetAttribute("Opacity");
|
||||
|
||||
// Minimized windows might have reduced opacity or other visual indicator
|
||||
Assert.IsNotNull(opacity, "Minimized window should have visual indication in preview");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.SetAppMaximized")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestSetAppMaximized()
|
||||
{
|
||||
// Find first app
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to test");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstApp = apps[0];
|
||||
|
||||
// Find and toggle maximized checkbox
|
||||
var maximizedCheckbox = firstApp.Find<CheckBox>("Maximized");
|
||||
bool wasMaximized = maximizedCheckbox.IsChecked;
|
||||
|
||||
maximizedCheckbox.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify state changed
|
||||
Assert.AreNotEqual(wasMaximized, maximizedCheckbox.IsChecked, "Maximized state should toggle");
|
||||
|
||||
// Verify preview reflects the change
|
||||
var previewPane = Find<Pane>("Preview");
|
||||
if (maximizedCheckbox.IsChecked)
|
||||
{
|
||||
// Maximized window should fill the preview area
|
||||
var windowPreviews = previewPane.FindAll<Custom>(By.ClassName("WindowPreview"));
|
||||
if (windowPreviews.Count > 0)
|
||||
{
|
||||
var firstPreview = windowPreviews[0];
|
||||
|
||||
// Check if preview shows maximized state
|
||||
var width = firstPreview.GetAttribute("Width");
|
||||
var height = firstPreview.GetAttribute("Height");
|
||||
Assert.IsNotNull(width, "Maximized window should have width in preview");
|
||||
Assert.IsNotNull(height, "Maximized window should have height in preview");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.LaunchAsAdmin")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestSetLaunchAsAdmin()
|
||||
{
|
||||
// Find app that supports admin launch
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
bool foundAdminCapableApp = false;
|
||||
foreach (var app in apps)
|
||||
{
|
||||
try
|
||||
{
|
||||
var adminCheckbox = app.Find<CheckBox>("Launch as admin", timeoutMS: 1000);
|
||||
if (adminCheckbox != null && adminCheckbox.IsChecked)
|
||||
{
|
||||
foundAdminCapableApp = true;
|
||||
bool wasAdmin = adminCheckbox.IsChecked;
|
||||
|
||||
adminCheckbox.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify state changed
|
||||
Assert.AreNotEqual(wasAdmin, adminCheckbox.IsChecked, "Admin launch state should toggle");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// This app doesn't support admin launch
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAdminCapableApp)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace support admin launch");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.AddCLIArgs")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestAddCommandLineArguments()
|
||||
{
|
||||
// Find first app
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to test");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstApp = apps[0];
|
||||
|
||||
// Find CLI args textbox
|
||||
var cliArgsTextBox = firstApp.Find<TextBox>("Command line arguments", timeoutMS: 2000);
|
||||
if (cliArgsTextBox == null)
|
||||
{
|
||||
Assert.Inconclusive("App does not support command line arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add test arguments
|
||||
string testArgs = "--test-arg value";
|
||||
cliArgsTextBox.SetText(testArgs);
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify arguments were entered
|
||||
Assert.AreEqual(testArgs, cliArgsTextBox.Text, "Command line arguments should be set");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.ChangeAppPosition")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestManuallyChangeAppPosition()
|
||||
{
|
||||
// Find first app
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
if (apps.Count == 0)
|
||||
{
|
||||
Assert.Inconclusive("No apps in workspace to test");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstApp = apps[0];
|
||||
|
||||
// Find position controls
|
||||
var xPositionBox = firstApp.Find<TextBox>("X position", timeoutMS: 2000);
|
||||
var yPositionBox = firstApp.Find<TextBox>("Y position", timeoutMS: 2000);
|
||||
|
||||
if (xPositionBox == null || yPositionBox == null)
|
||||
{
|
||||
// Try alternate approach with spinners
|
||||
var positionSpinners = firstApp.FindAll<Custom>(By.ClassName("SpinBox"));
|
||||
if (positionSpinners.Count >= 2)
|
||||
{
|
||||
xPositionBox = positionSpinners[0].Find<TextBox>(By.ClassName("TextBox"));
|
||||
yPositionBox = positionSpinners[1].Find<TextBox>(By.ClassName("TextBox"));
|
||||
}
|
||||
}
|
||||
|
||||
if (xPositionBox != null && yPositionBox != null)
|
||||
{
|
||||
// Change position
|
||||
xPositionBox.SetText("200");
|
||||
Thread.Sleep(500);
|
||||
|
||||
yPositionBox.SetText("150");
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Verify preview updated
|
||||
var previewPane = Find<Pane>("Preview");
|
||||
var windowPreviews = previewPane.FindAll<Custom>(By.ClassName("WindowPreview"));
|
||||
Assert.IsTrue(windowPreviews.Count > 0, "Preview should show window at new position");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Inconclusive("Could not find position controls");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.ChangeWorkspaceName")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestChangeWorkspaceName()
|
||||
{
|
||||
// Find workspace name textbox
|
||||
var nameTextBox = Find<TextBox>("Workspace name");
|
||||
string originalName = nameTextBox.Text;
|
||||
|
||||
// Change name
|
||||
string newName = "Renamed_Workspace_" + DateTime.Now.Ticks;
|
||||
nameTextBox.SetText(newName);
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Save changes
|
||||
var saveButton = Find<Button>("Save");
|
||||
saveButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify we're back at main list
|
||||
Assert.IsTrue(Has<Custom>("WorkspacesList"), "Should return to main list after saving");
|
||||
|
||||
// Verify workspace was renamed
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var renamedWorkspace = workspacesList.Find<Custom>(By.Name(newName), timeoutMS: 2000);
|
||||
Assert.IsNotNull(renamedWorkspace, "Workspace should be renamed in the list");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.SaveAndCancelWork")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestSaveAndCancelButtons()
|
||||
{
|
||||
// Make a change
|
||||
var nameTextBox = Find<TextBox>("Workspace name");
|
||||
string originalName = nameTextBox.Text;
|
||||
string tempName = originalName + "_temp";
|
||||
|
||||
nameTextBox.SetText(tempName);
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Test Cancel button
|
||||
var cancelButton = Find<Button>("Cancel");
|
||||
cancelButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify returned to main list without saving
|
||||
Assert.IsTrue(Has<Custom>("WorkspacesList"), "Should return to main list");
|
||||
|
||||
// Go back to editing
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspace = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"))[0];
|
||||
workspace.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify name wasn't changed
|
||||
nameTextBox = Find<TextBox>("Workspace name");
|
||||
Assert.AreEqual(originalName, nameTextBox.Text, "Name should not be changed after cancel");
|
||||
|
||||
// Now test Save button
|
||||
nameTextBox.SetText(tempName);
|
||||
Thread.Sleep(500);
|
||||
|
||||
var saveButton = Find<Button>("Save");
|
||||
saveButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify saved
|
||||
workspacesList = Find<Custom>("WorkspacesList");
|
||||
var savedWorkspace = workspacesList.Find<Custom>(By.Name(tempName), timeoutMS: 2000);
|
||||
Assert.IsNotNull(savedWorkspace, "Workspace should be saved with new name");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.NavigateWithoutSaving")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestNavigateToMainPageWithoutSaving()
|
||||
{
|
||||
// Make a change
|
||||
var nameTextBox = Find<TextBox>("Workspace name");
|
||||
string originalName = nameTextBox.Text;
|
||||
|
||||
nameTextBox.SetText(originalName + "_unsaved");
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Click on "Workspaces" navigation/breadcrumb
|
||||
if (Has<NavigationViewItem>("Workspaces", timeoutMS: 1000))
|
||||
{
|
||||
var workspacesNav = Find<NavigationViewItem>("Workspaces");
|
||||
workspacesNav.Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
else if (Has<HyperlinkButton>("Workspaces", timeoutMS: 1000))
|
||||
{
|
||||
var workspacesBreadcrumb = Find<HyperlinkButton>("Workspaces");
|
||||
workspacesBreadcrumb.Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
// If there's a confirmation dialog, handle it
|
||||
if (Has<Button>("Discard", timeoutMS: 1000))
|
||||
{
|
||||
Find<Button>("Discard").Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Verify returned to main list
|
||||
Assert.IsTrue(Has<Custom>("WorkspacesList"), "Should return to main list");
|
||||
|
||||
// Verify changes weren't saved
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var unsavedWorkspace = workspacesList.Find<Custom>(By.Name(originalName + "_unsaved"), timeoutMS: 1000);
|
||||
Assert.IsNull(unsavedWorkspace, "Unsaved changes should not persist");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.CreateDesktopShortcut")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestCreateDesktopShortcut()
|
||||
{
|
||||
// Find desktop shortcut checkbox
|
||||
var shortcutCheckbox = Find<CheckBox>("Create desktop shortcut");
|
||||
|
||||
// Get desktop path
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
|
||||
// Get workspace name to check for shortcut
|
||||
var nameTextBox = Find<TextBox>("Workspace name");
|
||||
string workspaceName = nameTextBox.Text;
|
||||
string shortcutPath = Path.Combine(desktopPath, $"{workspaceName}.lnk");
|
||||
|
||||
// Clean up any existing shortcut
|
||||
if (File.Exists(shortcutPath))
|
||||
{
|
||||
File.Delete(shortcutPath);
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Check the checkbox
|
||||
if (!shortcutCheckbox.IsChecked)
|
||||
{
|
||||
shortcutCheckbox.Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Save
|
||||
var saveButton = Find<Button>("Save");
|
||||
saveButton.Click();
|
||||
Thread.Sleep(2000); // Give time for shortcut creation
|
||||
|
||||
// Verify shortcut was created
|
||||
Assert.IsTrue(File.Exists(shortcutPath), "Desktop shortcut should be created");
|
||||
|
||||
// Clean up
|
||||
if (File.Exists(shortcutPath))
|
||||
{
|
||||
File.Delete(shortcutPath);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.DesktopShortcutState")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestDesktopShortcutCheckboxState()
|
||||
{
|
||||
// Get workspace name
|
||||
var nameTextBox = Find<TextBox>("Workspace name");
|
||||
string workspaceName = nameTextBox.Text;
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
string shortcutPath = Path.Combine(desktopPath, $"{workspaceName}.lnk");
|
||||
|
||||
// Find checkbox
|
||||
var shortcutCheckbox = Find<CheckBox>("Create desktop shortcut");
|
||||
|
||||
// Test 1: When shortcut exists
|
||||
if (!File.Exists(shortcutPath))
|
||||
{
|
||||
// Create shortcut first
|
||||
if (!shortcutCheckbox.IsChecked)
|
||||
{
|
||||
shortcutCheckbox.Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
Find<Button>("Save").Click();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Navigate back to editing
|
||||
NavigateToEditingPage();
|
||||
}
|
||||
|
||||
shortcutCheckbox = Find<CheckBox>("Create desktop shortcut");
|
||||
Assert.IsTrue(shortcutCheckbox.IsChecked, "Checkbox should be checked when shortcut exists");
|
||||
|
||||
// Test 2: Remove shortcut
|
||||
if (File.Exists(shortcutPath))
|
||||
{
|
||||
File.Delete(shortcutPath);
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Re-navigate to refresh state
|
||||
Find<Button>("Cancel").Click();
|
||||
Thread.Sleep(1000);
|
||||
NavigateToEditingPage();
|
||||
|
||||
shortcutCheckbox = Find<CheckBox>("Create desktop shortcut");
|
||||
Assert.IsFalse(shortcutCheckbox.IsChecked, "Checkbox should be unchecked when shortcut doesn't exist");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditingPage.LaunchAndEdit")]
|
||||
[TestCategory("Workspaces Editing Page UI")]
|
||||
public void TestLaunchAndEditCapture()
|
||||
{
|
||||
// Find Launch and Edit button
|
||||
var launchEditButton = Find<Button>("Launch and Edit");
|
||||
launchEditButton.Click();
|
||||
Thread.Sleep(3000); // Wait for apps to launch
|
||||
|
||||
// Open a new application
|
||||
Process.Start("calc.exe");
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Click Capture
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Verify new app was added
|
||||
var appList = Find<Custom>("AppList");
|
||||
var apps = appList.FindAll<Custom>(By.ClassName("AppItem"));
|
||||
|
||||
bool foundCalculator = false;
|
||||
foreach (var app in apps)
|
||||
{
|
||||
var appName = app.GetAttribute("Name");
|
||||
if (appName.Contains("Calculator", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foundCalculator = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(foundCalculator, "Newly opened Calculator should be captured and added");
|
||||
|
||||
// Clean up
|
||||
foreach (var process in Process.GetProcessesByName("CalculatorApp"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
|
||||
foreach (var process in Process.GetProcessesByName("Calculator"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private void NavigateToEditingPage()
|
||||
{
|
||||
// Ensure we have at least one workspace
|
||||
if (!Has<Custom>("WorkspacesList", timeoutMS: 1000))
|
||||
{
|
||||
CreateTestWorkspace();
|
||||
}
|
||||
|
||||
// Click on first workspace to edit
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItems = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"));
|
||||
|
||||
if (workspaceItems.Count == 0)
|
||||
{
|
||||
CreateTestWorkspace();
|
||||
workspaceItems = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"));
|
||||
}
|
||||
|
||||
workspaceItems[0].Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
private void CreateTestWorkspace()
|
||||
{
|
||||
// Open a test app
|
||||
Process.Start("notepad.exe");
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Create workspace
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Capture
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Save with default name
|
||||
var saveButton = Find<Button>("Save");
|
||||
saveButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Close test app
|
||||
foreach (var process in Process.GetProcessesByName("notepad"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
namespace WorkspacesEditorUITest;
|
||||
|
||||
[TestClass]
|
||||
public class WorkspacesEditorTests : WorkspacesUiAutomationBase
|
||||
public class WorkspacesEditorTests : UITestBase
|
||||
{
|
||||
public WorkspacesEditorTests()
|
||||
: base()
|
||||
: base(PowerToysModule.Workspaces, WindowSize.Medium)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -21,217 +21,4 @@ public class WorkspacesEditorTests : WorkspacesUiAutomationBase
|
||||
{
|
||||
Assert.IsTrue(this.Has<Button>("Create Workspace"), "Should have create workspace button");
|
||||
}
|
||||
|
||||
/*
|
||||
[TestMethod("WorkspacesEditor.Editor.NewWorkspaceAppearsInList")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestNewWorkspaceAppearsInListAfterCapture()
|
||||
{
|
||||
// Open test application
|
||||
OpenNotepad();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Create workspace
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Capture
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Save workspace
|
||||
var saveButton = Find<Button>("Save");
|
||||
saveButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify workspace appears in list
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItems = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"));
|
||||
Assert.IsTrue(workspaceItems.Count > 0, "New workspace should appear in the list");
|
||||
|
||||
CloseNotepad();
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.CancelCaptureDoesNotAddWorkspace")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestCancelCaptureDoesNotAddWorkspace()
|
||||
{
|
||||
// Count existing workspaces
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var initialCount = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem")).Count;
|
||||
|
||||
// Create workspace
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Cancel
|
||||
var cancelButton = Find<Button>("Cancel");
|
||||
cancelButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify count hasn't changed
|
||||
var finalCount = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem")).Count;
|
||||
Assert.AreEqual(initialCount, finalCount, "Workspace count should not change after canceling");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.SearchFiltersWorkspaces")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestSearchFiltersWorkspaces()
|
||||
{
|
||||
// Create test workspaces first
|
||||
CreateTestWorkspace("TestWorkspace1");
|
||||
CreateTestWorkspace("TestWorkspace2");
|
||||
CreateTestWorkspace("DifferentName");
|
||||
|
||||
// Find search box
|
||||
var searchBox = Find<TextBox>("Search");
|
||||
searchBox.SetText("TestWorkspace");
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify filtered results
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var visibleItems = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"));
|
||||
|
||||
// Should only show items matching "TestWorkspace"
|
||||
Assert.IsTrue(visibleItems.Count >= 2, "Should show at least 2 TestWorkspace items");
|
||||
|
||||
// Clear search
|
||||
searchBox.SetText(string.Empty);
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.SortByWorks")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestSortByFunctionality()
|
||||
{
|
||||
// Find sort dropdown
|
||||
var sortDropdown = Find<ComboBox>("SortBy");
|
||||
sortDropdown.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Select different sort options
|
||||
var sortOptions = FindAll<Custom>(By.ClassName("ComboBoxItem"));
|
||||
if (sortOptions.Count > 1)
|
||||
{
|
||||
sortOptions[1].Click(); // Select second option
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify list is updated (we can't easily verify sort order in UI tests)
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
Assert.IsNotNull(workspacesList, "Workspaces list should still be visible after sorting");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.SortByPersists")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestSortByPersistsAfterRestart()
|
||||
{
|
||||
// Set sort option
|
||||
var sortDropdown = Find<ComboBox>("SortBy");
|
||||
sortDropdown.Click();
|
||||
Thread.Sleep(500);
|
||||
|
||||
var sortOptions = FindAll<Custom>(By.ClassName("ComboBoxItem"));
|
||||
string selectedOption = string.Empty;
|
||||
if (sortOptions.Count > 1)
|
||||
{
|
||||
sortOptions[1].Click(); // Select second option
|
||||
selectedOption = sortDropdown.Text;
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
// Restart editor
|
||||
RestartScopeExe();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Verify sort option persisted
|
||||
sortDropdown = Find<ComboBox>("SortBy");
|
||||
Assert.AreEqual(selectedOption, sortDropdown.Text, "Sort option should persist after restart");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.RemoveWorkspace")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestRemoveWorkspace()
|
||||
{
|
||||
// Create a test workspace
|
||||
CreateTestWorkspace("WorkspaceToRemove");
|
||||
|
||||
// Find the workspace in the list
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItem = workspacesList.Find<Custom>(By.Name("WorkspaceToRemove"));
|
||||
|
||||
// Click remove button
|
||||
var removeButton = workspaceItem.Find<Button>("Remove");
|
||||
removeButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Confirm removal if dialog appears
|
||||
if (Has<Button>("Yes"))
|
||||
{
|
||||
Find<Button>("Yes").Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
// Verify workspace is removed
|
||||
Assert.IsFalse(Has(By.Name("WorkspaceToRemove")), "Workspace should be removed from list");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.EditOpensEditingPage")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestEditOpensEditingPage()
|
||||
{
|
||||
// Create a test workspace if none exist
|
||||
if (!Has<Custom>("WorkspacesList"))
|
||||
{
|
||||
CreateTestWorkspace("TestWorkspace");
|
||||
}
|
||||
|
||||
// Find first workspace
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItem = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"))[0];
|
||||
|
||||
// Click edit button
|
||||
var editButton = workspaceItem.Find<Button>("Edit");
|
||||
editButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify editing page opened
|
||||
Assert.IsTrue(Has<Button>("Save"), "Should have Save button on editing page");
|
||||
Assert.IsTrue(Has<Button>("Cancel"), "Should have Cancel button on editing page");
|
||||
|
||||
// Go back
|
||||
Find<Button>("Cancel").Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Editor.ClickWorkspaceOpensEditingPage")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestClickWorkspaceOpensEditingPage()
|
||||
{
|
||||
// Create a test workspace if none exist
|
||||
if (!Has<Custom>("WorkspacesList"))
|
||||
{
|
||||
CreateTestWorkspace("TestWorkspace");
|
||||
}
|
||||
|
||||
// Find first workspace
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItem = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"))[0];
|
||||
|
||||
// Click on the workspace item itself
|
||||
workspaceItem.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify editing page opened
|
||||
Assert.IsTrue(Has<Button>("Save"), "Should have Save button on editing page");
|
||||
Assert.IsTrue(Has<Button>("Cancel"), "Should have Cancel button on editing page");
|
||||
|
||||
// Go back
|
||||
Find<Button>("Cancel").Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
|
||||
<ProjectReference Include="..\WorkspacesEditor\WorkspacesEditor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// 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 Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace WorkspacesEditorUITest;
|
||||
|
||||
[TestClass]
|
||||
[Ignore("NOT STABLE")]
|
||||
public class WorkspacesLauncherTest : WorkspacesUiAutomationBase
|
||||
{
|
||||
public WorkspacesLauncherTest()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Launcher.LaunchFromEditor")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestLaunchWorkspaceFromEditor()
|
||||
{
|
||||
ClearWorkspaces();
|
||||
var uuid = Guid.NewGuid().ToString("N").Substring(0, 8);
|
||||
CreateTestWorkspace(uuid);
|
||||
|
||||
CloseNotepad();
|
||||
|
||||
var launchButton = Find<Button>(By.Name("Launch"));
|
||||
launchButton.Click();
|
||||
|
||||
Task.Delay(2000).Wait();
|
||||
|
||||
var processes = System.Diagnostics.Process.GetProcessesByName("notepad");
|
||||
|
||||
Assert.IsTrue(processes?.Length > 0);
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Launcher.CancelLaunch")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestCancelLaunch()
|
||||
{
|
||||
// Create workspace with multiple apps
|
||||
CreateWorkspaceWithApps();
|
||||
|
||||
// Launch workspace
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItem = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"))[0];
|
||||
var launchButton = workspaceItem.Find<Button>("Launch");
|
||||
launchButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Cancel launch
|
||||
if (Has<Button>("Cancel launch"))
|
||||
{
|
||||
Find<Button>("Cancel launch").Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify launcher closed
|
||||
Assert.IsFalse(Has<Window>("Workspaces Launcher"), "Launcher window should close after cancel");
|
||||
}
|
||||
|
||||
// Close any apps that may have launched
|
||||
CloseTestApplications();
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesEditor.Launcher.DismissKeepsLaunching")]
|
||||
[TestCategory("Workspaces UI")]
|
||||
public void TestDismissKeepsAppsLaunching()
|
||||
{
|
||||
// Create workspace with apps
|
||||
CreateWorkspaceWithApps();
|
||||
|
||||
// Launch workspace
|
||||
var workspacesList = Find<Custom>("WorkspacesList");
|
||||
var workspaceItem = workspacesList.FindAll<Custom>(By.ClassName("WorkspaceItem"))[0];
|
||||
var launchButton = workspaceItem.Find<Button>("Launch");
|
||||
launchButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Dismiss launcher
|
||||
if (Has<Button>("Dismiss"))
|
||||
{
|
||||
Find<Button>("Dismiss").Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Verify launcher closed but apps continue launching
|
||||
Assert.IsFalse(Has<Window>("Workspaces Launcher"), "Launcher window should close after dismiss");
|
||||
|
||||
// Wait for apps to finish launching
|
||||
Thread.Sleep(3000);
|
||||
|
||||
// Verify apps launched (notepad should be open)
|
||||
Assert.IsTrue(WindowHelper.IsWindowOpen("Notepad"), "Apps should continue launching after dismiss");
|
||||
}
|
||||
|
||||
// Close launched apps
|
||||
CloseTestApplications();
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
// 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 Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace WorkspacesEditorUITest;
|
||||
|
||||
[TestClass]
|
||||
public class WorkspacesSettingsTests : UITestBase
|
||||
{
|
||||
public WorkspacesSettingsTests()
|
||||
: base(PowerToysModule.PowerToysSettings, WindowSize.Medium)
|
||||
{
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.LaunchFromSettings")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
public void TestLaunchEditorFromSettingsPage()
|
||||
{
|
||||
GoToSettingsPageAndEnable();
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.ActivationShortcut")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
public void TestActivationShortcutCustomization()
|
||||
{
|
||||
GoToSettingsPageAndEnable();
|
||||
|
||||
// Find the activation shortcut control
|
||||
var shortcutButton = Find<Button>("Activation shortcut");
|
||||
Assert.IsNotNull(shortcutButton, "Activation shortcut control should exist");
|
||||
|
||||
// Test customizing the shortcut
|
||||
shortcutButton.Click();
|
||||
|
||||
Task.Delay(1000).Wait();
|
||||
|
||||
// Send new key combination (Win+Ctrl+W)
|
||||
SendKeys(Key.Win, Key.Ctrl, Key.W);
|
||||
|
||||
var saveButton = Find<Button>("Save");
|
||||
|
||||
Assert.IsNotNull(saveButton, "Save button should exist after editing shortcut");
|
||||
|
||||
saveButton.Click();
|
||||
|
||||
var helpText = shortcutButton.HelpText;
|
||||
Assert.AreEqual("Win + Ctrl + W", helpText, "Activation shortcut should be updated to Win + Ctrl + W");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.EnableToggle")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
public void TestEnableDisableModule()
|
||||
{
|
||||
GoToSettingsPageAndEnable();
|
||||
|
||||
// Find the enable toggle
|
||||
var enableToggle = Find<ToggleSwitch>("Enable Workspaces");
|
||||
Assert.IsNotNull(enableToggle, "Enable Workspaces toggle should exist");
|
||||
|
||||
Assert.IsTrue(enableToggle.IsOn, "Enable Workspaces toggle should be in the 'on' state");
|
||||
|
||||
// Toggle the state
|
||||
enableToggle.Click();
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
// Verify state changed
|
||||
Assert.IsFalse(enableToggle.IsOn, "Toggle state should change");
|
||||
|
||||
// Verify related controls are enabled/disabled accordingly
|
||||
var launchButton = Find<Button>("Launch editor");
|
||||
Assert.IsFalse(launchButton.Enabled, "Launch editor button should be disabled when module is disabled");
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.LaunchByActivationShortcut")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
[Ignore("Wait until settings & runner can be connected in framework")]
|
||||
public void TestLaunchEditorByActivationShortcut()
|
||||
{
|
||||
// Ensure module is enabled
|
||||
var enableToggle = Find<ToggleSwitch>("Enable Workspaces");
|
||||
if (!enableToggle.IsOn)
|
||||
{
|
||||
enableToggle.Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Close settings window to test shortcut
|
||||
ExitScopeExe();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Default shortcut is Win+Ctrl+`
|
||||
SendKeys(Key.Win, Key.Ctrl, Key.W);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Verify editor opened
|
||||
Assert.IsTrue(WindowHelper.IsWindowOpen("Workspaces Editor"), "Workspaces Editor should open with activation shortcut");
|
||||
|
||||
// Reopen settings for next tests
|
||||
RestartScopeExe();
|
||||
NavigateToWorkspacesSettings();
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.DisableModuleNoLaunch")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
[Ignore("Wait until settings & runner can be connected in framework")]
|
||||
public void TestDisabledModuleDoesNotLaunchByShortcut()
|
||||
{
|
||||
// Disable the module
|
||||
var enableToggle = Find<ToggleSwitch>("Enable Workspaces");
|
||||
if (enableToggle.IsOn)
|
||||
{
|
||||
enableToggle.Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
// Close settings to test shortcut
|
||||
ExitScopeExe();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Try to launch with shortcut
|
||||
SendKeys(Key.Win, Key.Ctrl, Key.W);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Verify editor did not open
|
||||
Assert.IsFalse(WindowHelper.IsWindowOpen("Workspaces Editor"), "Workspaces Editor should not open when module is disabled");
|
||||
|
||||
// Reopen settings and re-enable the module
|
||||
RestartScopeExe();
|
||||
NavigateToWorkspacesSettings();
|
||||
|
||||
enableToggle = Find<ToggleSwitch>("Enable Workspaces");
|
||||
if (!enableToggle.IsOn)
|
||||
{
|
||||
enableToggle.Click();
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSettings.QuickAccessLaunch")]
|
||||
[TestCategory("Workspaces Settings UI")]
|
||||
[Ignore("Wait until tray icon supported is in framework")]
|
||||
public void TestLaunchFromQuickAccess()
|
||||
{
|
||||
// This test verifies the "quick access" mention in settings
|
||||
// Look for any quick access related UI elements
|
||||
var quickAccessInfo = FindAll(By.LinkText("quick access"));
|
||||
|
||||
if (quickAccessInfo.Count > 0)
|
||||
{
|
||||
Assert.IsTrue(quickAccessInfo.Count > 0, "Quick access information should be present in settings");
|
||||
}
|
||||
|
||||
// Note: Actual system tray/quick access interaction would require
|
||||
// more complex automation that might be platform-specific
|
||||
}
|
||||
|
||||
private void NavigateToWorkspacesSettings()
|
||||
{
|
||||
// Find and click Workspaces in the navigation
|
||||
var workspacesNavItem = Find<NavigationViewItem>("Workspaces");
|
||||
workspacesNavItem.Click();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
private void GoToSettingsPageAndEnable()
|
||||
{
|
||||
if (this.FindAll<NavigationViewItem>("Workspaces").Count == 0)
|
||||
{
|
||||
this.Find<NavigationViewItem>("Windowing & Layouts").Click();
|
||||
}
|
||||
|
||||
this.Find<NavigationViewItem>("Workspaces").Click();
|
||||
|
||||
var enableButton = this.Find<ToggleSwitch>("Enable Workspaces");
|
||||
Assert.IsNotNull(enableButton, "Enable Workspaces toggle should exist");
|
||||
|
||||
if (!enableButton.IsOn)
|
||||
{
|
||||
enableButton.Click();
|
||||
Task.Delay(500).Wait(); // Wait for the toggle animation and state change
|
||||
}
|
||||
|
||||
// Verify it's now enabled
|
||||
Assert.IsTrue(enableButton.IsOn, "Enable Workspaces toggle should be in the 'on' state");
|
||||
}
|
||||
|
||||
private void AttachWorkspacesEditor()
|
||||
{
|
||||
Task.Delay(200).Wait();
|
||||
this.Session.Attach(PowerToysModule.Workspaces);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
// 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 Microsoft.PowerToys.UITest;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using WorkspacesEditor.Utils;
|
||||
|
||||
namespace WorkspacesEditorUITest;
|
||||
|
||||
[TestClass]
|
||||
public class WorkspacesSnapshotTests : WorkspacesUiAutomationBase
|
||||
{
|
||||
public WorkspacesSnapshotTests()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSnapshot.CancelCapture")]
|
||||
[TestCategory("Workspaces Snapshot UI")]
|
||||
public void TestCaptureCancel()
|
||||
{
|
||||
AttachWorkspacesEditor();
|
||||
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
|
||||
Task.Delay(1000).Wait();
|
||||
|
||||
AttachSnapshotWindow();
|
||||
|
||||
var cancelButton = Find<Button>("Cancel");
|
||||
|
||||
Assert.IsNotNull(cancelButton, "Capture button should exist");
|
||||
|
||||
cancelButton.Click();
|
||||
}
|
||||
|
||||
[TestMethod("WorkspacesSnapshot.CapturePackagedApps")]
|
||||
[TestCategory("Workspaces Snapshot UI")]
|
||||
public void TestCapturePackagedApplications()
|
||||
{
|
||||
OpenCalculator();
|
||||
|
||||
// OpenWindowsSettings();
|
||||
Task.Delay(2000).Wait();
|
||||
|
||||
AttachWorkspacesEditor();
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Task.Delay(1000).Wait();
|
||||
|
||||
AttachSnapshotWindow();
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Task.Delay(3000).Wait();
|
||||
|
||||
// Verify captured windows by reading the temporary workspaces file as the ground truth.
|
||||
var editorIO = new WorkspacesEditorIO();
|
||||
var workspace = editorIO.ParseTempProject();
|
||||
|
||||
Assert.IsNotNull(workspace, "Workspace data should be deserialized.");
|
||||
Assert.IsNotNull(workspace.Applications, "Workspace should contain a list of apps.");
|
||||
|
||||
bool isCalculatorFound = workspace.Applications.Any(app => app.AppPath.Contains("Calculator", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
// bool isSettingsFound = workspace.Applications.Any(app => app.AppPath.Contains("Settings", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.IsTrue(isCalculatorFound, "Calculator should be captured in the workspace data.");
|
||||
|
||||
// Assert.IsTrue(isSettingsFound, "Settings should be captured in the workspace data.");
|
||||
|
||||
// Cancel to clean up
|
||||
AttachWorkspacesEditor();
|
||||
Find<Button>("Cancel").Click();
|
||||
Task.Delay(1000).Wait();
|
||||
|
||||
// Close test applications
|
||||
CloseCalculator();
|
||||
|
||||
// CloseWindowsSettings();
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
// 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.Diagnostics;
|
||||
using Microsoft.PowerToys.UITest;
|
||||
|
||||
namespace WorkspacesEditorUITest
|
||||
{
|
||||
public class WorkspacesUiAutomationBase : UITestBase
|
||||
{
|
||||
public WorkspacesUiAutomationBase()
|
||||
: base(PowerToysModule.Workspaces, WindowSize.Medium)
|
||||
{
|
||||
}
|
||||
|
||||
protected void CreateTestWorkspace(string name)
|
||||
{
|
||||
// Open notepad for capture
|
||||
OpenNotepad();
|
||||
Task.Delay(1000).Wait();
|
||||
|
||||
// Create workspace
|
||||
AttachWorkspacesEditor();
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
// Capture
|
||||
AttachSnapshotWindow();
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Task.Delay(5000).Wait();
|
||||
|
||||
// Set name
|
||||
var nameTextBox = Find<TextBox>("EditNameTextBox");
|
||||
nameTextBox.SetText(name);
|
||||
|
||||
// Save
|
||||
Find<Button>("Save Workspace").Click();
|
||||
|
||||
// Close notepad
|
||||
CloseNotepad();
|
||||
}
|
||||
|
||||
// DO NOT USE UNTIL FRAMEWORK AVAILABLE, CAN'T FIND BUTTON FOR SECOND LOOP
|
||||
protected void ClearWorkspaces()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var root = Find<Element>(By.AccessibilityId("WorkspacesItemsControl"));
|
||||
var buttons = root.FindAll<Button>(By.AccessibilityId("MoreButton"));
|
||||
|
||||
Debug.WriteLine($"Found {buttons.Count} button");
|
||||
|
||||
var button = buttons[^1];
|
||||
|
||||
button.Click();
|
||||
|
||||
Task.Delay(500).Wait();
|
||||
|
||||
var remove = Find<Button>(By.Name("Remove"));
|
||||
remove.Click();
|
||||
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void CreateWorkspaceWithApps()
|
||||
{
|
||||
// Open multiple test applications
|
||||
OpenTestApplications();
|
||||
Thread.Sleep(3000);
|
||||
|
||||
// Create workspace
|
||||
var createButton = Find<Button>("Create Workspace");
|
||||
createButton.Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Capture
|
||||
var captureButton = Find<Button>("Capture");
|
||||
captureButton.Click();
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Save
|
||||
Find<Button>("Save").Click();
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Close test applications
|
||||
CloseTestApplications();
|
||||
}
|
||||
|
||||
protected void OpenTestApplications()
|
||||
{
|
||||
OpenNotepad();
|
||||
|
||||
// Could add more applications here
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
|
||||
protected void CloseTestApplications()
|
||||
{
|
||||
CloseNotepad();
|
||||
}
|
||||
|
||||
protected void CloseWorkspacesEditor()
|
||||
{
|
||||
// Find and close the Workspaces Editor window
|
||||
if (WindowHelper.IsWindowOpen("Workspaces Editor"))
|
||||
{
|
||||
var editorWindow = Find<Window>("Workspaces Editor");
|
||||
editorWindow.Close();
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ResetShortcutToDefault(Custom shortcutControl)
|
||||
{
|
||||
// Right-click on the shortcut control to open context menu
|
||||
shortcutControl.Click(rightClick: true);
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Look for a "Reset to default" or similar option in the context menu
|
||||
try
|
||||
{
|
||||
// Try to find various possible menu item texts for reset option
|
||||
var resetOption = Find("Reset to default");
|
||||
resetOption?.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try alternative text
|
||||
var resetOption = Find("Reset");
|
||||
resetOption?.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try another alternative
|
||||
var resetOption = Find("Default");
|
||||
resetOption?.Click();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If context menu doesn't have reset option, try keyboard shortcut
|
||||
// ESC to close any open menus first
|
||||
SendKeys(Key.Esc);
|
||||
Thread.Sleep(200);
|
||||
|
||||
// Click on the control and try to clear it with standard shortcuts
|
||||
shortcutControl.Click();
|
||||
Thread.Sleep(200);
|
||||
|
||||
// Try Ctrl+A to select all, then Delete to clear
|
||||
SendKeys(Key.Ctrl, Key.A);
|
||||
Thread.Sleep(100);
|
||||
SendKeys(Key.Delete);
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void OpenNotepad()
|
||||
{
|
||||
var process = System.Diagnostics.Process.Start("notepad.exe");
|
||||
Task.Delay(1000).Wait();
|
||||
}
|
||||
|
||||
protected void CloseNotepad()
|
||||
{
|
||||
var processes = System.Diagnostics.Process.GetProcessesByName("notepad");
|
||||
foreach (var process in processes)
|
||||
{
|
||||
try
|
||||
{
|
||||
process.Kill();
|
||||
process.WaitForExit();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AttachPowertoySetting()
|
||||
{
|
||||
Task.Delay(200).Wait();
|
||||
this.Session.Attach(PowerToysModule.PowerToysSettings);
|
||||
}
|
||||
|
||||
protected void AttachWorkspacesEditor()
|
||||
{
|
||||
Task.Delay(200).Wait();
|
||||
this.Session.Attach(PowerToysModule.Workspaces);
|
||||
}
|
||||
|
||||
protected void AttachSnapshotWindow()
|
||||
{
|
||||
Task.Delay(5000).Wait();
|
||||
this.Session.Attach("Snapshot Creator");
|
||||
}
|
||||
|
||||
protected void OpenCalculator()
|
||||
{
|
||||
Process.Start("calc.exe");
|
||||
Task.Delay(1000).Wait();
|
||||
}
|
||||
|
||||
protected void CloseCalculator()
|
||||
{
|
||||
foreach (var process in Process.GetProcessesByName("CalculatorApp"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
|
||||
foreach (var process in Process.GetProcessesByName("Calculator"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OpenWindowsSettings()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "ms-settings:",
|
||||
UseShellExecute = true,
|
||||
});
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
|
||||
protected void CloseWindowsSettings()
|
||||
{
|
||||
foreach (var process in Process.GetProcessesByName("SystemSettings"))
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,6 @@
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
||||
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.7" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.6" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -21,7 +21,7 @@ public partial class AppStateModel : ObservableObject
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// STATE HERE
|
||||
public RecentCommandsManager RecentCommands { get; set; } = new();
|
||||
public RecentCommandsManager RecentCommands { get; private set; } = new();
|
||||
|
||||
// END SETTINGS
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -32,6 +32,22 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_title)}},
|
||||
"size": "large"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_text)}},
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_header)}},
|
||||
"weight": "bolder",
|
||||
"size": "default"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_description)}},
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"label": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_label)}},
|
||||
@@ -43,11 +59,14 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_description)}},
|
||||
"wrap": true,
|
||||
"size": "small",
|
||||
"isSubtle": true,
|
||||
"spacing": "none"
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_header)}},
|
||||
"weight": "bolder",
|
||||
"size": "default"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_description)}},
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
@@ -55,16 +74,18 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
|
||||
"isRequired": true,
|
||||
"errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_required)}},
|
||||
"id": "DisplayName",
|
||||
"placeholder": "My new extension",
|
||||
"spacing": "medium"
|
||||
"placeholder": "My new extension"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_description)}},
|
||||
"wrap": true,
|
||||
"size": "small",
|
||||
"isSubtle": true,
|
||||
"spacing": "none"
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_header)}},
|
||||
"weight": "bolder",
|
||||
"size": "default"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_description)}},
|
||||
"wrap": true
|
||||
},
|
||||
{
|
||||
"type": "Input.Text",
|
||||
@@ -72,16 +93,7 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
|
||||
"isRequired": true,
|
||||
"errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_required)}},
|
||||
"id": "OutputPath",
|
||||
"placeholder": "C:\\users\\me\\dev",
|
||||
"spacing": "medium"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_description)}},
|
||||
"wrap": true,
|
||||
"size": "small",
|
||||
"isSubtle": true,
|
||||
"spacing": "none"
|
||||
"placeholder": "C:\\users\\me\\dev"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
|
||||
@@ -264,6 +264,17 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
if (model != null)
|
||||
{
|
||||
model.ItemsChanged -= Model_ItemsChanged;
|
||||
if (model is IDisposable disposableModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposableModel.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exceptions during cleanup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,6 +571,17 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
if (model != null)
|
||||
{
|
||||
model.ItemsChanged -= Model_ItemsChanged;
|
||||
if (model is IDisposable disposableModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposableModel.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exceptions during cleanup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,6 +243,17 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
if (model != null)
|
||||
{
|
||||
model.PropChanged -= Model_PropChanged;
|
||||
if (model is IDisposable disposableModel)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposableModel.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exceptions during cleanup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select the folder where the new extension will be created. The path will be created if it doesn't exist..
|
||||
/// Looks up a localized string similar to Where should the new extension be created? This path will be created if it doesn't exist.
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_directory_description {
|
||||
get {
|
||||
@@ -78,6 +78,15 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Output path.
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_directory_header {
|
||||
get {
|
||||
return ResourceManager.GetString("builtin_create_extension_directory_header", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Output path.
|
||||
/// </summary>
|
||||
@@ -97,7 +106,7 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The name of the extension as it will appear to users..
|
||||
/// Looks up a localized string similar to The name of your extension as users will see it..
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_display_name_description {
|
||||
get {
|
||||
@@ -105,6 +114,15 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Display name.
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_display_name_header {
|
||||
get {
|
||||
return ResourceManager.GetString("builtin_create_extension_display_name_header", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Display name.
|
||||
/// </summary>
|
||||
@@ -133,7 +151,7 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Enter a valid C# class name for the new extension project. It's recommended to include the word "Extension" in the name..
|
||||
/// Looks up a localized string similar to This is the name of your new extension project. It should be a valid C# class name. Best practice is to also include the word 'Extension' in the name..
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_name_description {
|
||||
get {
|
||||
@@ -141,6 +159,15 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extension name.
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_name_header {
|
||||
get {
|
||||
return ResourceManager.GetString("builtin_create_extension_name_header", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Extension name.
|
||||
/// </summary>
|
||||
@@ -178,7 +205,16 @@ namespace Microsoft.CmdPal.UI.ViewModels.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create a new extension.
|
||||
/// Looks up a localized string similar to Use this page to create a new extension project..
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_page_text {
|
||||
get {
|
||||
return ResourceManager.GetString("builtin_create_extension_page_text", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create your new extension.
|
||||
/// </summary>
|
||||
public static string builtin_create_extension_page_title {
|
||||
get {
|
||||
|
||||
@@ -180,10 +180,16 @@
|
||||
<value>Once you're ready to test deploy the package locally with Visual Studio, then run the \"Reload\" command in the Command Palette to load your new extension.</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_page_title" xml:space="preserve">
|
||||
<value>Create a new extension</value>
|
||||
<value>Create your new extension</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_page_text" xml:space="preserve">
|
||||
<value>Use this page to create a new extension project.</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_name_header" xml:space="preserve">
|
||||
<value>Extension name</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_name_description" xml:space="preserve">
|
||||
<value>Enter a valid C# class name for the new extension project. It's recommended to include the word "Extension" in the name.</value>
|
||||
<value>This is the name of your new extension project. It should be a valid C# class name. Best practice is to also include the word 'Extension' in the name.</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_name_label" xml:space="preserve">
|
||||
<value>Extension name</value>
|
||||
@@ -191,8 +197,11 @@
|
||||
<data name="builtin_create_extension_name_required" xml:space="preserve">
|
||||
<value>Extension name is required and must be a valid C# identifier (start with a letter or underscore, followed by letters, numbers, or underscores)</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_display_name_header" xml:space="preserve">
|
||||
<value>Display name</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_display_name_description" xml:space="preserve">
|
||||
<value>The name of the extension as it will appear to users.</value>
|
||||
<value>The name of your extension as users will see it.</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_display_name_label" xml:space="preserve">
|
||||
<value>Display name</value>
|
||||
@@ -200,8 +209,11 @@
|
||||
<data name="builtin_create_extension_display_name_required" xml:space="preserve">
|
||||
<value>Display name is required</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_directory_header" xml:space="preserve">
|
||||
<value>Output path</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_directory_description" xml:space="preserve">
|
||||
<value>Select the folder where the new extension will be created. The path will be created if it doesn't exist.</value>
|
||||
<value>Where should the new extension be created? This path will be created if it doesn't exist</value>
|
||||
</data>
|
||||
<data name="builtin_create_extension_directory_label" xml:space="preserve">
|
||||
<value>Output path</value>
|
||||
|
||||
@@ -130,7 +130,7 @@ public partial class SettingsModel : ObservableObject
|
||||
{
|
||||
foreach (var item in newSettings)
|
||||
{
|
||||
savedSettings[item.Key] = item.Value?.DeepClone();
|
||||
savedSettings[item.Key] = item.Value != null ? item.Value.DeepClone() : null;
|
||||
}
|
||||
|
||||
var serialized = savedSettings.ToJsonString(JsonSerializationContext.Default.Options);
|
||||
@@ -188,8 +188,6 @@ public partial class SettingsModel : ObservableObject
|
||||
[JsonSerializable(typeof(HistoryItem))]
|
||||
[JsonSerializable(typeof(SettingsModel))]
|
||||
[JsonSerializable(typeof(AppStateModel))]
|
||||
[JsonSerializable(typeof(RecentCommandsManager))]
|
||||
[JsonSerializable(typeof(List<string>), TypeInfoPropertyName = "StringList")]
|
||||
[JsonSerializable(typeof(List<HistoryItem>), TypeInfoPropertyName = "HistoryList")]
|
||||
[JsonSerializable(typeof(Dictionary<string, object>), TypeInfoPropertyName = "Dictionary")]
|
||||
[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)]
|
||||
|
||||
@@ -18,7 +18,7 @@ using WinRT;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class ShellViewModel(IServiceProvider _serviceProvider, TaskScheduler _scheduler) : ObservableObject
|
||||
public partial class ShellViewModel(IServiceProvider _serviceProvider, TaskScheduler _scheduler) : ObservableObject, IDisposable
|
||||
{
|
||||
[ObservableProperty]
|
||||
public partial bool IsLoaded { get; set; } = false;
|
||||
@@ -31,6 +31,8 @@ public partial class ShellViewModel(IServiceProvider _serviceProvider, TaskSched
|
||||
|
||||
private PageViewModel _currentPage = new LoadingPageViewModel(null, _scheduler);
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public PageViewModel CurrentPage
|
||||
{
|
||||
get => _currentPage;
|
||||
@@ -201,6 +203,48 @@ public partial class ShellViewModel(IServiceProvider _serviceProvider, TaskSched
|
||||
SetActiveExtension(null);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose managed resources
|
||||
if (_mainListPage is IDisposable disposable)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentPage is IDisposable disposablePage)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposablePage.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
_mainListPage = null;
|
||||
_activeExtension = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// You may ask yourself, why aren't we using CsWin32 for this?
|
||||
// The CsWin32 projected version includes some object marshalling, like so:
|
||||
//
|
||||
|
||||
@@ -38,7 +38,7 @@ public sealed class AdaptiveCardsConfig
|
||||
"fontFamily": "'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
|
||||
"fontSizes": {
|
||||
"small": 12,
|
||||
"default": 14,
|
||||
"default": 12,
|
||||
"medium": 14,
|
||||
"large": 20,
|
||||
"extraLarge": 26
|
||||
@@ -199,7 +199,7 @@ public sealed class AdaptiveCardsConfig
|
||||
"fontFamily": "'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
|
||||
"fontSizes": {
|
||||
"small": 12,
|
||||
"default": 14,
|
||||
"default": 12,
|
||||
"medium": 14,
|
||||
"large": 20,
|
||||
"extraLarge": 26
|
||||
|
||||
@@ -100,16 +100,6 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<Style x:Key="HotkeyStyle" TargetType="Border">
|
||||
<Style.Setters>
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{ThemeResource ControlFillColorSecondaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="6" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
@@ -203,12 +193,17 @@
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.PrimaryCommand.Name, Mode=OneWay}" />
|
||||
<Border Style="{StaticResource HotkeyStyle}">
|
||||
<Border
|
||||
Padding="4"
|
||||
Background="{ThemeResource SubtleFillColorSecondaryBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<FontIcon
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
@@ -226,20 +221,32 @@
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.SecondaryCommand.Name, Mode=OneWay}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<Border Padding="4,2,4,2" Style="{StaticResource HotkeyStyle}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="2">
|
||||
<Border
|
||||
Padding="4,2,4,2"
|
||||
VerticalAlignment="Center"
|
||||
Background="{ThemeResource SubtleFillColorSecondaryBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<TextBlock
|
||||
CharacterSpacing="4"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="Ctrl" />
|
||||
</Border>
|
||||
<Border Style="{StaticResource HotkeyStyle}">
|
||||
<Border
|
||||
Padding="4"
|
||||
VerticalAlignment="Center"
|
||||
Background="{ThemeResource SubtleFillColorSecondaryBrush}"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<FontIcon
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
@@ -260,6 +267,7 @@
|
||||
Opened="Flyout_Opened"
|
||||
Placement="TopEdgeAlignedRight">
|
||||
<StackPanel>
|
||||
|
||||
<ListView
|
||||
x:Name="CommandsDropdown"
|
||||
MinWidth="248"
|
||||
@@ -280,6 +288,7 @@
|
||||
<TransitionCollection />
|
||||
</ListView.ItemContainerTransitions>
|
||||
</ListView>
|
||||
|
||||
<TextBox
|
||||
x:Name="ContextFilterBox"
|
||||
x:Uid="ContextFilterBox"
|
||||
@@ -287,6 +296,7 @@
|
||||
KeyDown="ContextFilterBox_KeyDown"
|
||||
PreviewKeyDown="ContextFilterBox_PreviewKeyDown"
|
||||
TextChanged="ContextFilterBox_TextChanged" />
|
||||
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
|
||||
@@ -19,5 +19,6 @@
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid x:Name="ContentGrid" />
|
||||
</UserControl>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<StaticResource x:Key="TagBackground" ResourceKey="ControlFillColorSecondaryBrush" />
|
||||
<StaticResource x:Key="TagBorderBrush" ResourceKey="DividerStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TagBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
||||
<StaticResource x:Key="TagBorderBrush" ResourceKey="ControlStrokeColorSecondaryBrush" />
|
||||
<StaticResource x:Key="TagForeground" ResourceKey="TextFillColorTertiaryBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="TagBackground" ResourceKey="ControlFillColorSecondaryBrush" />
|
||||
<StaticResource x:Key="TagBorderBrush" ResourceKey="DividerStrokeColorDefaultBrush" />
|
||||
<StaticResource x:Key="TagBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
|
||||
<StaticResource x:Key="TagBorderBrush" ResourceKey="ControlStrokeColorSecondaryBrush" />
|
||||
<StaticResource x:Key="TagForeground" ResourceKey="TextFillColorTertiaryBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
<Grid Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
|
||||
<ScrollView VerticalAlignment="Top" VerticalScrollMode="Enabled">
|
||||
<ItemsRepeater
|
||||
VerticalAlignment="Stretch"
|
||||
|
||||
@@ -380,19 +380,19 @@
|
||||
To="24,0,0"
|
||||
Duration="0:0:0.187" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
<Grid Margin="16">
|
||||
<Grid Margin="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<cpcontrols:IconBox
|
||||
x:Name="HeroImageBorder"
|
||||
Width="64"
|
||||
Margin="0,0,16,16"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="16,8,16,16"
|
||||
HorizontalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
SourceKey="{x:Bind ViewModel.Details.HeroImage, Mode=OneWay}"
|
||||
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}"
|
||||
@@ -400,15 +400,17 @@
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Text="{x:Bind ViewModel.Details.Title, Mode=OneWay}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="{x:Bind ViewModel.Details.Title, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}" />
|
||||
|
||||
<toolkit:MarkdownTextBlock
|
||||
Grid.Row="2"
|
||||
Margin="0,4,0,24"
|
||||
Margin="0,12,0,24"
|
||||
Background="Transparent"
|
||||
Header3FontSize="12"
|
||||
Header3FontWeight="Normal"
|
||||
|
||||
@@ -21,6 +21,8 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System
|
||||
|
||||
private uint _queryCookie = 10;
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public FallbackOpenFileItem()
|
||||
: base(new NoOpCommand(), Resources.Indexer_Find_Path_fallback_display_title)
|
||||
{
|
||||
@@ -120,9 +122,17 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_searchEngine.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
_searchEngine?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp
|
||||
{
|
||||
private readonly string fullPath;
|
||||
private readonly List<CommandContextItem> actions = [];
|
||||
private bool _isDisposed;
|
||||
private static readonly Lock UpdateMoreCommandsLock = new();
|
||||
private static ActionRuntime actionRuntime;
|
||||
|
||||
@@ -97,14 +98,24 @@ internal sealed partial class ActionsListContextItem : CommandContextItem, IDisp
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
if (!_isDisposed)
|
||||
{
|
||||
if (actionRuntime != null)
|
||||
_isDisposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
if (actionRuntime != null)
|
||||
{
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
|
||||
private string initialQuery = string.Empty;
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public IndexerPage()
|
||||
{
|
||||
Id = "com.microsoft.indexer.fileSearch";
|
||||
@@ -33,6 +35,7 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
|
||||
public IndexerPage(string query, SearchEngine searchEngine, uint queryCookie, IList<IListItem> firstPageData)
|
||||
{
|
||||
disposeSearchEngine = false;
|
||||
Icon = Icons.FileExplorer;
|
||||
Name = Resources.Indexer_Title;
|
||||
_searchEngine = searchEngine;
|
||||
@@ -40,7 +43,6 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
_indexerListItems.AddRange(firstPageData);
|
||||
initialQuery = query;
|
||||
SearchText = query;
|
||||
disposeSearchEngine = false;
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
@@ -76,12 +78,21 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
_searchEngine.Query(query, _queryCookie);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposeSearchEngine)
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_searchEngine.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
_isDisposed = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (disposeSearchEngine)
|
||||
{
|
||||
_searchEngine?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
|
||||
|
||||
private IEnumerable<CatalogPackage>? _results;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public static IconInfo WinGetIcon { get; } = IconHelpers.FromRelativePath("Assets\\WinGet.svg");
|
||||
|
||||
public static IconInfo ExtensionsIcon { get; } = IconHelpers.FromRelativePath("Assets\\Extension.svg");
|
||||
@@ -189,7 +191,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
|
||||
return [];
|
||||
}
|
||||
|
||||
string searchDebugText = $"{query}{(HasTag ? "+" : string.Empty)}{_tag}";
|
||||
var searchDebugText = $"{query}{(HasTag ? "+" : string.Empty)}{_tag}";
|
||||
Logger.LogDebug($"Starting search for '{searchDebugText}'");
|
||||
HashSet<CatalogPackage> results = new(new PackageIdCompare());
|
||||
|
||||
@@ -271,7 +273,19 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
|
||||
return results;
|
||||
}
|
||||
|
||||
public void Dispose() => throw new NotImplementedException();
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
_cancellationTokenSource?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "I just like it")]
|
||||
|
||||
@@ -46,21 +46,17 @@ internal sealed partial class WindowWalkerListPage : DynamicListPage, IDisposabl
|
||||
|
||||
public override IListItem[] GetItems() => Query(SearchText).ToArray();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Dispose(bool disposing)
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
if (disposing)
|
||||
{
|
||||
_cancellationTokenSource?.Dispose();
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings;
|
||||
internal static class ResultHelper
|
||||
{
|
||||
internal static List<ListItem> GetResultList(
|
||||
in IEnumerable<Classes.WindowsSetting> list)
|
||||
in IEnumerable<Classes.WindowsSetting> list,
|
||||
string query)
|
||||
{
|
||||
var resultList = new List<ListItem>(list.Count());
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
// 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.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
|
||||
|
||||
internal static class ScoringHelper
|
||||
{
|
||||
// Rank settings by how they matched the search query. Order is:
|
||||
// 1. Exact Name (10 points)
|
||||
// 2. Name Starts With (8 points)
|
||||
// 3. Name (5 points)
|
||||
// 4. Area (4 points)
|
||||
// 5. AltName (2 points)
|
||||
// 6. Settings path (1 point)
|
||||
internal static (WindowsSetting Setting, int Score) SearchScoringPredicate(string query, WindowsSetting setting)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
// If no search string is entered skip query comparison.
|
||||
return (setting, 0);
|
||||
}
|
||||
|
||||
if (string.Equals(setting.Name, query, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return (setting, 10);
|
||||
}
|
||||
|
||||
if (setting.Name.StartsWith(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 8);
|
||||
}
|
||||
|
||||
if (setting.Name.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 5);
|
||||
}
|
||||
|
||||
if (!(setting.Areas is null))
|
||||
{
|
||||
foreach (var area in setting.Areas)
|
||||
{
|
||||
// Search for areas on normal queries.
|
||||
if (area.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 4);
|
||||
}
|
||||
|
||||
// Search for Area only on queries with action char.
|
||||
if (area.Contains(query.Replace(":", string.Empty), StringComparison.CurrentCultureIgnoreCase)
|
||||
&& query.EndsWith(":", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(setting.AltNames is null))
|
||||
{
|
||||
foreach (var altName in setting.AltNames)
|
||||
{
|
||||
if (altName.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search by key char '>' for app name and settings path
|
||||
if (query.Contains('>') && ResultHelper.FilterBySettingsPath(setting, query))
|
||||
{
|
||||
return (setting, 1);
|
||||
}
|
||||
|
||||
return (setting, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Commands;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.WindowsSettings.Pages;
|
||||
|
||||
internal sealed partial class FallbackWindowsSettingsItem : FallbackCommandItem
|
||||
{
|
||||
private readonly Classes.WindowsSettings _windowsSettings;
|
||||
|
||||
private readonly string _title = Resources.settings_fallback_title;
|
||||
private readonly string _subtitle = Resources.settings_fallback_subtitle;
|
||||
|
||||
public FallbackWindowsSettingsItem(Classes.WindowsSettings windowsSettings)
|
||||
: base(new NoOpCommand(), Resources.settings_title)
|
||||
{
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WindowsSettings.svg");
|
||||
_windowsSettings = windowsSettings;
|
||||
}
|
||||
|
||||
public override void UpdateQuery(string query)
|
||||
{
|
||||
Command = new NoOpCommand();
|
||||
Title = string.Empty;
|
||||
Subtitle = string.Empty;
|
||||
Icon = null;
|
||||
MoreCommands = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(query) ||
|
||||
_windowsSettings?.Settings is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var filteredList = _windowsSettings.Settings
|
||||
.Select(setting => ScoringHelper.SearchScoringPredicate(query, setting))
|
||||
.Where(scoredSetting => scoredSetting.Score > 0)
|
||||
.OrderByDescending(scoredSetting => scoredSetting.Score);
|
||||
|
||||
if (!filteredList.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (filteredList.Count() == 1 ||
|
||||
filteredList.Any(a => a.Score == 10))
|
||||
{
|
||||
var setting = filteredList.First().Setting;
|
||||
|
||||
Title = setting.Name;
|
||||
Subtitle = setting.JoinedFullSettingsPath;
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WindowsSettings.svg");
|
||||
Command = new OpenSettingsCommand(setting)
|
||||
{
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WindowsSettings.svg"),
|
||||
Name = setting.Name,
|
||||
};
|
||||
|
||||
// There is a case with MMC snap-ins where we don't have .msc files fort them. Then we need to show the note for this results in subtitle too.
|
||||
// These results have mmc.exe as command and their note property is filled.
|
||||
if (setting.Command == "mmc.exe" && !string.IsNullOrEmpty(setting.Note))
|
||||
{
|
||||
Subtitle += $"\u0020\u0020\u002D\u0020\u0020{Resources.Note}: {setting.Note}"; // "\u0020\u0020\u002D\u0020\u0020" = "<space><space><minus><space><space>"
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We found more than one result. Make our command take
|
||||
// us to the Windows Settings search page, prepopulated with this search.
|
||||
var settingsPage = new WindowsSettingsListPage(_windowsSettings, query);
|
||||
Title = string.Format(CultureInfo.CurrentCulture, _title, query);
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WindowsSettings.svg");
|
||||
Subtitle = _subtitle;
|
||||
Command = settingsPage;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
@@ -20,17 +18,11 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage
|
||||
public WindowsSettingsListPage(Classes.WindowsSettings windowsSettings)
|
||||
{
|
||||
Icon = IconHelpers.FromRelativePath("Assets\\WindowsSettings.svg");
|
||||
Name = Resources.settings_title;
|
||||
Name = "Windows Settings";
|
||||
Id = "com.microsoft.cmdpal.windowsSettings";
|
||||
_windowsSettings = windowsSettings;
|
||||
}
|
||||
|
||||
public WindowsSettingsListPage(Classes.WindowsSettings windowsSettings, string query)
|
||||
: this(windowsSettings)
|
||||
{
|
||||
SearchText = query;
|
||||
}
|
||||
|
||||
public List<ListItem> Query(string query)
|
||||
{
|
||||
if (_windowsSettings?.Settings is null)
|
||||
@@ -39,21 +31,87 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage
|
||||
}
|
||||
|
||||
var filteredList = _windowsSettings.Settings
|
||||
.Select(setting => ScoringHelper.SearchScoringPredicate(query, setting))
|
||||
.Select(SearchScoringPredicate)
|
||||
.Where(scoredSetting => scoredSetting.Score > 0)
|
||||
.OrderByDescending(scoredSetting => scoredSetting.Score)
|
||||
.Select(scoredSetting => scoredSetting.Setting);
|
||||
|
||||
var newList = ResultHelper.GetResultList(filteredList);
|
||||
var newList = ResultHelper.GetResultList(filteredList, query);
|
||||
return newList;
|
||||
|
||||
// Rank settings by how they matched the search query. Order is:
|
||||
// 1. Exact Name (10 points)
|
||||
// 2. Name Starts With (8 points)
|
||||
// 3. Name (5 points)
|
||||
// 4. Area (4 points)
|
||||
// 5. AltName (2 points)
|
||||
// 6. Settings path (1 point)
|
||||
(WindowsSetting Setting, int Score) SearchScoringPredicate(WindowsSetting setting)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
// If no search string is entered skip query comparison.
|
||||
return (setting, 0);
|
||||
}
|
||||
|
||||
if (string.Equals(setting.Name, query, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return (setting, 10);
|
||||
}
|
||||
|
||||
if (setting.Name.StartsWith(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 8);
|
||||
}
|
||||
|
||||
if (setting.Name.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 5);
|
||||
}
|
||||
|
||||
if (!(setting.Areas is null))
|
||||
{
|
||||
foreach (var area in setting.Areas)
|
||||
{
|
||||
// Search for areas on normal queries.
|
||||
if (area.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 4);
|
||||
}
|
||||
|
||||
// Search for Area only on queries with action char.
|
||||
if (area.Contains(query.Replace(":", string.Empty), StringComparison.CurrentCultureIgnoreCase)
|
||||
&& query.EndsWith(":", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(setting.AltNames is null))
|
||||
{
|
||||
foreach (var altName in setting.AltNames)
|
||||
{
|
||||
if (altName.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search by key char '>' for app name and settings path
|
||||
if (query.Contains('>') && ResultHelper.FilterBySettingsPath(setting, query))
|
||||
{
|
||||
return (setting, 1);
|
||||
}
|
||||
|
||||
return (setting, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
if (oldSearch != newSearch)
|
||||
{
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
|
||||
@@ -3840,42 +3840,6 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Search Windows settings for this device.
|
||||
/// </summary>
|
||||
internal static string settings_fallback_subtitle {
|
||||
get {
|
||||
return ResourceManager.GetString("settings_fallback_subtitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Search for "{0}" in Windows settings.
|
||||
/// </summary>
|
||||
internal static string settings_fallback_title {
|
||||
get {
|
||||
return ResourceManager.GetString("settings_fallback_title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Navigate to specific Windows settings.
|
||||
/// </summary>
|
||||
internal static string settings_subtitle {
|
||||
get {
|
||||
return ResourceManager.GetString("settings_subtitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Windows Settings.
|
||||
/// </summary>
|
||||
internal static string settings_title {
|
||||
get {
|
||||
return ResourceManager.GetString("settings_title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Settings app.
|
||||
/// </summary>
|
||||
|
||||
@@ -2085,16 +2085,4 @@
|
||||
<data name="WindowsSettingsProvider_DisplayName" xml:space="preserve">
|
||||
<value>Windows Settings</value>
|
||||
</data>
|
||||
<data name="settings_title" xml:space="preserve">
|
||||
<value>Windows Settings</value>
|
||||
</data>
|
||||
<data name="settings_subtitle" xml:space="preserve">
|
||||
<value>Navigate to specific Windows settings</value>
|
||||
</data>
|
||||
<data name="settings_fallback_title" xml:space="preserve">
|
||||
<value>Search for "{0}" in Windows settings</value>
|
||||
</data>
|
||||
<data name="settings_fallback_subtitle" xml:space="preserve">
|
||||
<value>Search Windows settings for this device</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Pages;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
@@ -18,8 +17,6 @@ public partial class WindowsSettingsCommandsProvider : CommandProvider
|
||||
private readonly WindowsSettings.Classes.WindowsSettings? _windowsSettings;
|
||||
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||
|
||||
private readonly FallbackWindowsSettingsItem _fallback;
|
||||
|
||||
public WindowsSettingsCommandsProvider()
|
||||
{
|
||||
Id = "Windows.Settings";
|
||||
@@ -29,10 +26,9 @@ public partial class WindowsSettingsCommandsProvider : CommandProvider
|
||||
_windowsSettings = JsonSettingsListHelper.ReadAllPossibleSettings();
|
||||
_searchSettingsListItem = new CommandItem(new WindowsSettingsListPage(_windowsSettings))
|
||||
{
|
||||
Title = Resources.settings_title,
|
||||
Subtitle = Resources.settings_subtitle,
|
||||
Title = "Windows Settings",
|
||||
Subtitle = "Navigate to specific Windows settings",
|
||||
};
|
||||
_fallback = new(_windowsSettings);
|
||||
|
||||
UnsupportedSettingsHelper.FilterByBuild(_windowsSettings);
|
||||
|
||||
@@ -46,6 +42,4 @@ public partial class WindowsSettingsCommandsProvider : CommandProvider
|
||||
_searchSettingsListItem
|
||||
];
|
||||
}
|
||||
|
||||
public override IFallbackCommandItem[] FallbackCommands() => [_fallback];
|
||||
}
|
||||
|
||||
@@ -10,12 +10,39 @@ namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
// asynchronously, so as to not block the extension app while it's being
|
||||
// processed in the host app.
|
||||
// (also consider this for ItemsChanged in ListPage)
|
||||
public partial class BaseObservable : INotifyPropChanged
|
||||
public partial class BaseObservable : INotifyPropChanged, IDisposable
|
||||
{
|
||||
private bool _isDisposed;
|
||||
|
||||
public event TypedEventHandler<object, IPropChangedEventArgs>? PropChanged;
|
||||
|
||||
// Protected implementation of Dispose pattern.
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
PropChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// TODO #181 - This is dangerous! If the original host goes away,
|
||||
|
||||
@@ -6,7 +6,7 @@ using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
public partial class ListPage : Page, IListPage
|
||||
public partial class ListPage : Page, IListPage, IDisposable
|
||||
{
|
||||
private string _placeholderText = string.Empty;
|
||||
private string _searchText = string.Empty;
|
||||
@@ -15,6 +15,7 @@ public partial class ListPage : Page, IListPage
|
||||
private IFilters? _filters;
|
||||
private IGridProperties? _gridProperties;
|
||||
private ICommandItem? _emptyContent;
|
||||
private bool _isDisposed;
|
||||
|
||||
public event TypedEventHandler<object, IItemsChangedEventArgs>? ItemsChanged;
|
||||
|
||||
@@ -94,8 +95,28 @@ public partial class ListPage : Page, IListPage
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
ItemsChanged = null;
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
protected void RaiseItemsChanged(int totalItems = -1)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// TODO #181 - This is the same thing that BaseObservable has to deal with.
|
||||
|
||||
@@ -615,7 +615,7 @@ namespace UITests_FancyZones
|
||||
// test settings
|
||||
Microsoft.PowerToys.UITest.CheckBox useShiftCheckBox = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Hold Shift key to activate zones while dragging a window");
|
||||
Microsoft.PowerToys.UITest.CheckBox useNonPrimaryMouseCheckBox = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Use a non-primary mouse button to toggle zone activation");
|
||||
Microsoft.PowerToys.UITest.CheckBox makeDraggedWindowTransparent = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Make the dragged window transparent");
|
||||
Microsoft.PowerToys.UITest.CheckBox makeDraggedWindowTransparent = this.Find<Microsoft.PowerToys.UITest.CheckBox>("Make dragged window transparent");
|
||||
|
||||
Find<Microsoft.PowerToys.UITest.CheckBox>("Show zone number").SetCheck(false, 100);
|
||||
Find<Slider>("Opacity (%)").QuickSetValue(100); // make highlight color visible with opacity 100
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<TargetName>PowerToys.ImageResizerContextMenu</TargetName>
|
||||
<!-- Needs a different int dir to avoid conflicts in msix creation. -->
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\TemporaryBuild\obj\$(ProjectName)\</IntDir>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetName>PowerToys.$(ProjectName)</TargetName>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>PowerToys.ImageResizerExt</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>PowerToys.ImageResizer</AssemblyTitle>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutputPath>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
|
||||
RenamedEventArgs e = new RenamedEventArgs(WatcherChangeTypes.Renamed, directory, path, oldpath);
|
||||
|
||||
string oldFullPath = directory + "\\" + oldpath;
|
||||
string newFullPath = directory + "\\" + path;
|
||||
string fullPath = directory + "\\" + path;
|
||||
string linkingTo = Directory.GetCurrentDirectory();
|
||||
|
||||
// ShellLinkHelper must be mocked for lnk applications
|
||||
@@ -372,8 +372,19 @@ namespace Microsoft.Plugin.Program.UnitTests.Storage
|
||||
Win32Program.ShellLinkHelper = mockShellLink.Object;
|
||||
|
||||
// old item and new item are the actual items when they are in existence
|
||||
Win32Program olditem = Win32Program.GetAppFromPath(oldFullPath);
|
||||
Win32Program newitem = Win32Program.GetAppFromPath(newFullPath);
|
||||
Win32Program olditem = new Win32Program
|
||||
{
|
||||
Name = "oldpath",
|
||||
ExecutableName = oldpath,
|
||||
FullPath = linkingTo,
|
||||
};
|
||||
|
||||
Win32Program newitem = new Win32Program
|
||||
{
|
||||
Name = "path",
|
||||
ExecutableName = path,
|
||||
FullPath = linkingTo,
|
||||
};
|
||||
|
||||
win32ProgramRepository.Add(olditem);
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
std::vector<std::wstring_view> knownModules = {
|
||||
L"PowerToys.FancyZonesModuleInterface.dll",
|
||||
L"PowerToys.powerpreview.dll",
|
||||
L"WinUI3Apps/PowerToys.ImageResizerExt.dll",
|
||||
L"PowerToys.ImageResizerExt.dll",
|
||||
L"PowerToys.KeyboardManager.dll",
|
||||
L"PowerToys.Launcher.dll",
|
||||
L"WinUI3Apps/PowerToys.PowerRenameExt.dll",
|
||||
|
||||
@@ -671,22 +671,14 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case ESettingsWindowNames::Dashboard:
|
||||
return "Dashboard";
|
||||
case ESettingsWindowNames::Overview:
|
||||
return "Overview";
|
||||
case ESettingsWindowNames::AlwaysOnTop:
|
||||
return "AlwaysOnTop";
|
||||
case ESettingsWindowNames::Awake:
|
||||
return "Awake";
|
||||
case ESettingsWindowNames::ColorPicker:
|
||||
return "ColorPicker";
|
||||
case ESettingsWindowNames::CmdNotFound:
|
||||
return "CmdNotFound";
|
||||
case ESettingsWindowNames::FancyZones:
|
||||
return "FancyZones";
|
||||
case ESettingsWindowNames::FileLocksmith:
|
||||
return "FileLocksmith";
|
||||
case ESettingsWindowNames::Run:
|
||||
return "Run";
|
||||
case ESettingsWindowNames::ImageResizer:
|
||||
@@ -695,16 +687,6 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
|
||||
return "KBM";
|
||||
case ESettingsWindowNames::MouseUtils:
|
||||
return "MouseUtils";
|
||||
case ESettingsWindowNames::MouseWithoutBorders:
|
||||
return "MouseWithoutBorders";
|
||||
case ESettingsWindowNames::Peek:
|
||||
return "Peek";
|
||||
case ESettingsWindowNames::PowerAccent:
|
||||
return "PowerAccent";
|
||||
case ESettingsWindowNames::PowerLauncher:
|
||||
return "PowerLauncher";
|
||||
case ESettingsWindowNames::PowerPreview:
|
||||
return "PowerPreview";
|
||||
case ESettingsWindowNames::PowerRename:
|
||||
return "PowerRename";
|
||||
case ESettingsWindowNames::FileExplorer:
|
||||
@@ -725,6 +707,8 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
|
||||
return "CropAndLock";
|
||||
case ESettingsWindowNames::EnvironmentVariables:
|
||||
return "EnvironmentVariables";
|
||||
case ESettingsWindowNames::Dashboard:
|
||||
return "Dashboard";
|
||||
case ESettingsWindowNames::AdvancedPaste:
|
||||
return "AdvancedPaste";
|
||||
case ESettingsWindowNames::NewPlus:
|
||||
@@ -744,18 +728,10 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
|
||||
|
||||
ESettingsWindowNames ESettingsWindowNames_from_string(std::string value)
|
||||
{
|
||||
if (value == "Dashboard")
|
||||
{
|
||||
return ESettingsWindowNames::Dashboard;
|
||||
}
|
||||
else if (value == "Overview")
|
||||
if (value == "Overview")
|
||||
{
|
||||
return ESettingsWindowNames::Overview;
|
||||
}
|
||||
else if (value == "AlwaysOnTop")
|
||||
{
|
||||
return ESettingsWindowNames::AlwaysOnTop;
|
||||
}
|
||||
else if (value == "Awake")
|
||||
{
|
||||
return ESettingsWindowNames::Awake;
|
||||
@@ -764,18 +740,10 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value)
|
||||
{
|
||||
return ESettingsWindowNames::ColorPicker;
|
||||
}
|
||||
else if (value == "CmdNotFound")
|
||||
{
|
||||
return ESettingsWindowNames::CmdNotFound;
|
||||
}
|
||||
else if (value == "FancyZones")
|
||||
{
|
||||
return ESettingsWindowNames::FancyZones;
|
||||
}
|
||||
else if (value == "FileLocksmith")
|
||||
{
|
||||
return ESettingsWindowNames::FileLocksmith;
|
||||
}
|
||||
else if (value == "Run")
|
||||
{
|
||||
return ESettingsWindowNames::Run;
|
||||
@@ -792,26 +760,6 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value)
|
||||
{
|
||||
return ESettingsWindowNames::MouseUtils;
|
||||
}
|
||||
else if (value == "MouseWithoutBorders")
|
||||
{
|
||||
return ESettingsWindowNames::MouseWithoutBorders;
|
||||
}
|
||||
else if (value == "Peek")
|
||||
{
|
||||
return ESettingsWindowNames::Peek;
|
||||
}
|
||||
else if (value == "PowerAccent")
|
||||
{
|
||||
return ESettingsWindowNames::PowerAccent;
|
||||
}
|
||||
else if (value == "PowerLauncher")
|
||||
{
|
||||
return ESettingsWindowNames::PowerLauncher;
|
||||
}
|
||||
else if (value == "PowerPreview")
|
||||
{
|
||||
return ESettingsWindowNames::PowerPreview;
|
||||
}
|
||||
else if (value == "PowerRename")
|
||||
{
|
||||
return ESettingsWindowNames::PowerRename;
|
||||
@@ -852,6 +800,10 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value)
|
||||
{
|
||||
return ESettingsWindowNames::EnvironmentVariables;
|
||||
}
|
||||
else if (value == "Dashboard")
|
||||
{
|
||||
return ESettingsWindowNames::Dashboard;
|
||||
}
|
||||
else if (value == "AdvancedPaste")
|
||||
{
|
||||
return ESettingsWindowNames::AdvancedPaste;
|
||||
|
||||
@@ -6,21 +6,13 @@ enum class ESettingsWindowNames
|
||||
{
|
||||
Dashboard = 0,
|
||||
Overview,
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdNotFound,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
Run,
|
||||
ImageResizer,
|
||||
KBM,
|
||||
MouseUtils,
|
||||
MouseWithoutBorders,
|
||||
Peek,
|
||||
PowerAccent,
|
||||
PowerLauncher,
|
||||
PowerPreview,
|
||||
PowerRename,
|
||||
FileExplorer,
|
||||
ShortcutGuide,
|
||||
|
||||
@@ -436,10 +436,6 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "KBM": return typeof(KeyboardManagerPage);
|
||||
case "MouseUtils": return typeof(MouseUtilsPage);
|
||||
case "MouseWithoutBorders": return typeof(MouseWithoutBordersPage);
|
||||
case "Peek": return typeof(PeekPage);
|
||||
case "PowerAccent": return typeof(PowerAccentPage);
|
||||
case "PowerLauncher": return typeof(PowerLauncherPage);
|
||||
case "PowerPreview": return typeof(PowerPreviewPage);
|
||||
case "PowerRename": return typeof(PowerRenamePage);
|
||||
case "QuickAccent": return typeof(PowerAccentPage);
|
||||
case "FileExplorer": return typeof(PowerPreviewPage);
|
||||
@@ -448,6 +444,7 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "MeasureTool": return typeof(MeasureToolPage);
|
||||
case "Hosts": return typeof(HostsPage);
|
||||
case "RegistryPreview": return typeof(RegistryPreviewPage);
|
||||
case "Peek": return typeof(PeekPage);
|
||||
case "CropAndLock": return typeof(CropAndLockPage);
|
||||
case "EnvironmentVariables": return typeof(EnvironmentVariablesPage);
|
||||
case "NewPlus": return typeof(NewPlusPage);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
<UserControl.Resources>
|
||||
<x:Double x:Key="PageMaxWidth">1000</x:Double>
|
||||
<x:Double x:Key="PageHeaderMaxWidth">1020</x:Double>
|
||||
<tkconverters:DoubleToVisibilityConverter
|
||||
x:Name="doubleToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
@@ -27,7 +26,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
x:Name="Header"
|
||||
MaxWidth="{StaticResource PageHeaderMaxWidth}"
|
||||
MaxWidth="{StaticResource PageMaxWidth}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AutomationProperties.HeadingLevel="1"
|
||||
|
||||
@@ -88,9 +88,16 @@
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
|
||||
<tkcontrols:SettingsCard x:Uid="AlwaysOnTop_Sound" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SoundEnabled, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsExpander
|
||||
x:Uid="AlwaysOnTop_SoundTitle"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
||||
<CheckBox x:Uid="AlwaysOnTop_Sound" IsChecked="{x:Bind ViewModel.SoundEnabled, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
</controls:SettingsGroup>
|
||||
|
||||
<controls:SettingsGroup x:Uid="ExcludedApps" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
<tkcontrols:SettingsCard x:Uid="General_SettingsBackupAndRestoreLocationText">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
@@ -405,83 +405,76 @@
|
||||
</InfoBar.IconSource>
|
||||
</InfoBar>
|
||||
</controls:SettingsGroup>
|
||||
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback">
|
||||
<tkcontrols:SettingsExpander
|
||||
x:Uid="GeneralPage_EnableDataDiagnostics"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
IsExpanded="True">
|
||||
<tkcontrols:SettingsExpander.Description>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
x:Uid="GeneralPage_EnableDataDiagnosticsText"
|
||||
Style="{StaticResource SecondaryTextStyle}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<HyperlinkButton
|
||||
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
|
||||
Margin="0,2,0,0"
|
||||
FontWeight="SemiBold"
|
||||
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsExpander.Description>
|
||||
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}" />
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<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.Description>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
x:Uid="GeneralPage_EnableViewDiagnosticDataText"
|
||||
Style="{StaticResource SecondaryTextStyle}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<HyperlinkButton
|
||||
Margin="0,2,0,0"
|
||||
Click="ViewDiagnosticData_Click"
|
||||
Content="View diagnostic data"
|
||||
FontWeight="SemiBold" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsCard.Description>
|
||||
</tkcontrols:SettingsCard>
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
<tkcontrols:SettingsExpander.ItemsFooter>
|
||||
<InfoBar
|
||||
x:Uid="GeneralPage_ViewDiagnosticDataViewerInfo"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0,0,4,4"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
|
||||
Severity="Informational">
|
||||
<InfoBar.ActionButton>
|
||||
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
|
||||
</InfoBar.ActionButton>
|
||||
</InfoBar>
|
||||
</tkcontrols:SettingsExpander.ItemsFooter>
|
||||
</tkcontrols:SettingsExpander>
|
||||
<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="" />
|
||||
</InfoBar.IconSource>
|
||||
</InfoBar>
|
||||
<tkcontrols:SettingsCard x:Uid="GeneralPage_ReportBugPackage" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<HyperlinkButton
|
||||
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
|
||||
Margin="0,0,0,8"
|
||||
Padding="0"
|
||||
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="GeneralPage_EnableDataDiagnostics"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
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="" />
|
||||
</InfoBar.IconSource>
|
||||
</InfoBar>
|
||||
<tkcontrols:SettingsExpander
|
||||
x:Uid="GeneralPage_ViewDiagnosticData"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
IsExpanded="True">
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<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"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Click="ViewDiagnosticData_Click"
|
||||
IsClickEnabled="True" />
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
<InfoBar
|
||||
x:Uid="GeneralPage_ViewDiagnosticDataViewerInfo"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
|
||||
Severity="Informational">
|
||||
<InfoBar.ActionButton>
|
||||
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
|
||||
</InfoBar.ActionButton>
|
||||
</InfoBar>
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="GeneralPage_ReportBugPackage"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
Visibility="{x:Bind ViewModel.IsBugReportRunning, Converter={StaticResource ReverseBoolToVisibilityConverter}, Mode=OneWay}">
|
||||
<Button
|
||||
x:Uid="GeneralPageReportBugPackage"
|
||||
HorizontalAlignment="Right"
|
||||
Click="BugReportToolClicked"
|
||||
Visibility="{x:Bind ViewModel.IsBugReportRunning, Converter={StaticResource ReverseBoolToVisibilityConverter}, Mode=OneWay}" />
|
||||
IsEnabled="{x:Bind ViewModel.IsBugReportRunning, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="GeneralPage_ReportBugPackage"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
Visibility="{x:Bind ViewModel.IsBugReportRunning, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
|
||||
<ProgressRing
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{x:Bind ViewModel.IsBugReportRunning, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsCard>
|
||||
VerticalAlignment="Center" />
|
||||
</tkcontrols:SettingsCard>
|
||||
</StackPanel>
|
||||
</controls:SettingsGroup>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -152,10 +152,10 @@
|
||||
<comment>"Screen Ruler" is the name of the utility</comment>
|
||||
</data>
|
||||
<data name="MeasureTool_DefaultMeasureStyle.Header" xml:space="preserve">
|
||||
<value>Default mode</value>
|
||||
<value>Default measure style</value>
|
||||
</data>
|
||||
<data name="MeasureTool_DefaultMeasureStyle.Description" xml:space="preserve">
|
||||
<value>The measuring mode that is used when activated</value>
|
||||
<value>The utility will start having the selected style activated</value>
|
||||
</data>
|
||||
<data name="MeasureTool_DefaultMeasureStyle_None.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
@@ -234,7 +234,7 @@
|
||||
<value>Security key</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_SecurityKey.Description" xml:space="preserve">
|
||||
<value>To set up, generate the key on one machine, and enter it manually on other machines.</value>
|
||||
<value>The key must be auto generated in one machine by clicking on New Key, then typed in other machines</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_NewKey.Content" xml:space="preserve">
|
||||
<value>New key</value>
|
||||
@@ -274,7 +274,7 @@
|
||||
<value>Adding a firewall rule might help solve connection issues.</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_RunAsAdminText.Title" xml:space="preserve">
|
||||
<value>This setting can only be changed when running as administrator</value>
|
||||
<value>You need to run as administrator to modify this setting.</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_ServiceUserUninstallWarning.Title" xml:space="preserve">
|
||||
<value>If PowerToys is installed as a user, uninstalling/upgrading may require the Mouse Without Borders service to be removed manually later.</value>
|
||||
@@ -361,7 +361,7 @@
|
||||
<value>Hide the mouse cursor at the top edge of the screen when switching to other machine. This option also steals the focus from any full-screen app to ensure the keyboard input is redirected.</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_DrawMouseCursor.Description" xml:space="preserve">
|
||||
<value>The mouse cursor may not appear on Windows 10 and later if no physical mouse is connected.</value>
|
||||
<value>Mouse cursor may not be visible in Windows 10 and later versions of Windows when there is no physical mouse attached.</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_ValidateRemoteMachineIP.Description" xml:space="preserve">
|
||||
<value>Reverse DNS lookup to validate machine IP Address.</value>
|
||||
@@ -804,7 +804,7 @@
|
||||
<comment>launches the FancyZones layout editor application</comment>
|
||||
</data>
|
||||
<data name="FancyZones_MakeDraggedWindowTransparentCheckBoxControl.Content" xml:space="preserve">
|
||||
<value>Make the dragged window transparent</value>
|
||||
<value>Make dragged window transparent</value>
|
||||
</data>
|
||||
<data name="FancyZones_MouseDragCheckBoxControl_Header.Content" xml:space="preserve">
|
||||
<value>Use a non-primary mouse button to toggle zone activation</value>
|
||||
@@ -1304,7 +1304,7 @@
|
||||
<value>Always run as administrator</value>
|
||||
</data>
|
||||
<data name="GeneralSettings_AlwaysRunAsAdminText.Description" xml:space="preserve">
|
||||
<value>This setting can only be changed when running as administrator</value>
|
||||
<value>You need to run as administrator to use this setting</value>
|
||||
</data>
|
||||
<data name="GeneralSettings_RunningAsUserText" xml:space="preserve">
|
||||
<value>Running as user</value>
|
||||
@@ -1465,7 +1465,7 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<comment>Preview Pane and File Explorer are app/feature names in Windows. 'Alt + P' is a shortcut</comment>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_RunAsAdminRequired.Title" xml:space="preserve">
|
||||
<value>This setting can only be changed when running as administrator</value>
|
||||
<value>You need to run as administrator to modify these settings.</value>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_RebootRequired.Title" xml:space="preserve">
|
||||
<value>A reboot may be required for changes to these settings to take effect</value>
|
||||
@@ -1520,7 +1520,7 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<value>Mouse actions</value>
|
||||
</data>
|
||||
<data name="ColorPicker_MouseActions.Description" xml:space="preserve">
|
||||
<value>Customize the function of each mouse button</value>
|
||||
<value>Choose what clicking individual buttons does</value>
|
||||
</data>
|
||||
<data name="ColorPicker_PrimaryClick.Header" xml:space="preserve">
|
||||
<value>Primary click</value>
|
||||
@@ -1544,7 +1544,7 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<value>Picker behavior</value>
|
||||
</data>
|
||||
<data name="ColorPicker_CopiedColorRepresentation.Description" xml:space="preserve">
|
||||
<value>Format will be copied to your clipboard</value>
|
||||
<value>This format will be copied to your clipboard</value>
|
||||
</data>
|
||||
<data name="KBM_KeysCannotBeRemapped.Text" xml:space="preserve">
|
||||
<value>Learn more about remapping limitations</value>
|
||||
@@ -1736,7 +1736,7 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<value>Show color name</value>
|
||||
</data>
|
||||
<data name="ColorPicker_ShowColorName.Description" xml:space="preserve">
|
||||
<value>Displays the color name while picking a color</value>
|
||||
<value>This will show the name of the color when picking a color</value>
|
||||
</data>
|
||||
<data name="ImageResizer_DefaultSize_Large" xml:space="preserve">
|
||||
<value>Large</value>
|
||||
@@ -2056,7 +2056,7 @@ Take a moment to preview the various utilities listed or view our comprehensive
|
||||
<value>Diagnostic data</value>
|
||||
</data>
|
||||
<data name="Oobe_Overview_EnableDataDiagnostics.Description" xml:space="preserve">
|
||||
<value>Helps us make PowerToys faster, more stable, and better over time</value>
|
||||
<value>Helps inform bug fixes, performance, and product decisions</value>
|
||||
</data>
|
||||
<data name="Oobe_WhatsNew_DataDiagnostics_InfoBar.Header" xml:space="preserve">
|
||||
<value>Turn on diagnostic data to help us improve PowerToys?</value>
|
||||
@@ -2710,7 +2710,7 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Spotlight initial zoom</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_SpotlightInitialZoom.Description" xml:space="preserve">
|
||||
<value>Spotlight zoom factor at the start of the animation</value>
|
||||
<value>Spotlight zoom factor at animation start</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_AnimationDurationMs.Header" xml:space="preserve">
|
||||
<value>Animation duration (ms)</value>
|
||||
@@ -2724,23 +2724,23 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Animations are disabled in your system settings.</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingMinimumDistance.Header" xml:space="preserve">
|
||||
<value>Minimum shake distance</value>
|
||||
<value>Shake minimum distance</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingMinimumDistance.Description" xml:space="preserve">
|
||||
<value>The minimum distance the mouse must move to be considered a shake. Lower values increase sensitivity.</value>
|
||||
<value>The minimum distance for mouse shaking activation, for adjusting sensitivity</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingIntervalMs.Header" xml:space="preserve">
|
||||
<value>Shake detection interval (ms)</value>
|
||||
<value>Shake Interval (ms)</value>
|
||||
<comment>ms = milliseconds</comment>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingIntervalMs.Description" xml:space="preserve">
|
||||
<value>Time window used to monitor mouse movement for shake detection. Shorter intervals may detect quicker shakes.</value>
|
||||
<value>The span of time during which we track mouse movement to detect shaking, for adjusting sensitivity</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingFactor.Header" xml:space="preserve">
|
||||
<value>Shake sensitivity factor (percent)</value>
|
||||
<value>Shake factor (percent)</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_ShakingFactor.Description" xml:space="preserve">
|
||||
<value>Determines how far the pointer must move, relative to the screen diagonal, to count as a shake. Lower values make it more sensitive.</value>
|
||||
<value>Mouse shaking is detected by checking how much the mouse pointer has travelled when compared to the diagonal of the movement area. Reducing this factor increases sensitivity.</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseHighlighter.Header" xml:space="preserve">
|
||||
<value>Mouse Highlighter</value>
|
||||
@@ -2840,7 +2840,7 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Windows default</value>
|
||||
</data>
|
||||
<data name="ColorModeHeader.Header" xml:space="preserve">
|
||||
<value>Theme</value>
|
||||
<value>App theme</value>
|
||||
</data>
|
||||
<data name="FancyZones_Zone_Appearance.Description" xml:space="preserve">
|
||||
<value>Customize the way zones look</value>
|
||||
@@ -2848,6 +2848,9 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<data name="FancyZones_Zone_Appearance.Header" xml:space="preserve">
|
||||
<value>Zone appearance</value>
|
||||
</data>
|
||||
<data name="LearnMore.Content" xml:space="preserve">
|
||||
<value>Learn more</value>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_ToggleSwitch_Thumbnail_GCODE.Header" xml:space="preserve">
|
||||
<value>Geometric Code</value>
|
||||
<comment>File type, do not translate</comment>
|
||||
@@ -2903,13 +2906,13 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Reparent shortcut</value>
|
||||
</data>
|
||||
<data name="CropAndLock_ReparentActivation_Shortcut.Description" xml:space="preserve">
|
||||
<value>Creates a cropped version of an application’s window by embedding the original app into a new window. This is experimental and may cause issues due to the reparenting behavior.</value>
|
||||
<value>Shortcut to crop an application's window into a cropped window. This is experimental and can cause issues with some applications, since the cropped window will contain the original application window.</value>
|
||||
</data>
|
||||
<data name="CropAndLock_ThumbnailActivation_Shortcut.Header" xml:space="preserve">
|
||||
<value>Thumbnail shortcut</value>
|
||||
</data>
|
||||
<data name="CropAndLock_ThumbnailActivation_Shortcut.Description" xml:space="preserve">
|
||||
<value>Creates a cropped, non-interactive thumbnail of another window. Improves app compatibility.</value>
|
||||
<value>Shortcut to crop and create a thumbnail of another window. The application isn't controllable through the thumbnail but it'll have less compatibility issues. </value>
|
||||
</data>
|
||||
<data name="CropAndLock.SecondaryLinksHeader" xml:space="preserve">
|
||||
<value>Attribution</value>
|
||||
@@ -2977,6 +2980,12 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Do not activate when Game Mode is on</value>
|
||||
<comment>Game Mode is a Windows feature</comment>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_SoundTitle.Header" xml:space="preserve">
|
||||
<value>Sound</value>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_Sound.Content" xml:space="preserve">
|
||||
<value>Play a sound when pinning a window</value>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_Behavior.Header" xml:space="preserve">
|
||||
<value>Behavior</value>
|
||||
</data>
|
||||
@@ -3052,10 +3061,10 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Behavior</value>
|
||||
</data>
|
||||
<data name="Peek_AlwaysRunNotElevated.Header" xml:space="preserve">
|
||||
<value>Always run without elevation (even if PowerToys is elevated)</value>
|
||||
<value>Always run not elevated, even when PowerToys is elevated</value>
|
||||
</data>
|
||||
<data name="Peek_AlwaysRunNotElevated.Description" xml:space="preserve">
|
||||
<value>Runs Peek without admin permissions to improve access to network shares. To apply this change, you must disable and re-enable Peek.</value>
|
||||
<value>Tries to run Peek without elevated permissions, to fix access to network shares. You need to disable and re-enable Peek for changes to this value to take effect.</value>
|
||||
<comment>Peek is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="Peek_CloseAfterLosingFocus.Header" xml:space="preserve">
|
||||
@@ -3063,13 +3072,13 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<comment>Peek is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="Peek_ConfirmFileDelete.Header" xml:space="preserve">
|
||||
<value>Confirm before deleting files</value>
|
||||
<value>Ask for confirmation before deleting files</value>
|
||||
</data>
|
||||
<data name="Peek_ConfirmFileDelete.Description" xml:space="preserve">
|
||||
<value>You'll be asked to confirm before files are moved to the Recycle Bin</value>
|
||||
<value>When enabled, you will be prompted to confirm before moving files to the Recycle Bin.</value>
|
||||
</data>
|
||||
<data name="FancyZones_DisableRoundCornersOnWindowSnap.Content" xml:space="preserve">
|
||||
<value>Disable rounded corners when a window is snapped</value>
|
||||
<value>Disable round corners when window is snapped</value>
|
||||
</data>
|
||||
<data name="PowerLauncher_SearchQueryTuningEnabled.Description" xml:space="preserve">
|
||||
<value>Fine tune results ordering</value>
|
||||
@@ -3102,7 +3111,7 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<value>Global sort order score modifier</value>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_RoundCorners.Content" xml:space="preserve">
|
||||
<value>Enable rounded corners</value>
|
||||
<value>Enable round corners</value>
|
||||
</data>
|
||||
<data name="LearnMore_QuickAccent.Text" xml:space="preserve">
|
||||
<value>Learn more about Quick Accent</value>
|
||||
@@ -3155,6 +3164,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="AlwaysOnTop_ShortDescription" xml:space="preserve">
|
||||
<value>Pin a window</value>
|
||||
</data>
|
||||
<data name="Awake_ShortDescription" xml:space="preserve">
|
||||
<value>Keep your PC awake</value>
|
||||
</data>
|
||||
<data name="ColorPicker_ShortDescription" xml:space="preserve">
|
||||
<value>Pick a color</value>
|
||||
</data>
|
||||
@@ -3173,6 +3185,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="FindMyMouse_ShortDescription" xml:space="preserve">
|
||||
<value>Find the mouse</value>
|
||||
</data>
|
||||
<data name="ImageResizer_ShortDescription" xml:space="preserve">
|
||||
<value>Resize images from right-click context menu</value>
|
||||
</data>
|
||||
<data name="MouseHighlighter_ShortDescription" xml:space="preserve">
|
||||
<value>Highlight clicks</value>
|
||||
</data>
|
||||
@@ -3182,6 +3197,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="MouseCrosshairs_ShortDescription" xml:space="preserve">
|
||||
<value>Draw crosshairs centered on the mouse pointer</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_ShortDescription" xml:space="preserve">
|
||||
<value>Move your cursor across multiple devices</value>
|
||||
</data>
|
||||
<data name="AdvancedPaste_ShortDescription" xml:space="preserve">
|
||||
<value>An AI powered tool to put your clipboard content into any format you need, focused towards developer workflows.</value>
|
||||
</data>
|
||||
@@ -3194,6 +3212,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="Peek_ShortDescription" xml:space="preserve">
|
||||
<value>Quick and easy previewer</value>
|
||||
</data>
|
||||
<data name="PowerRename_ShortDescription" xml:space="preserve">
|
||||
<value>Rename files and folders from right-click context menu</value>
|
||||
</data>
|
||||
<data name="Run_ShortDescription" xml:space="preserve">
|
||||
<value>A quick launcher</value>
|
||||
</data>
|
||||
@@ -3294,7 +3315,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<comment>ms = milliseconds</comment>
|
||||
</data>
|
||||
<data name="QuickAccent_InputTimeMs.Description" xml:space="preserve">
|
||||
<value>How long a key must be held before the accent menu appears</value>
|
||||
<value>Hold the key down for this much time to make the accent menu appear (ms)</value>
|
||||
<comment>ms = milliseconds</comment>
|
||||
</data>
|
||||
<data name="QuickAccent_ExcludedApps.Description" xml:space="preserve">
|
||||
@@ -3625,7 +3646,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<comment>"Hosts File Editor" is a product name</comment>
|
||||
</data>
|
||||
<data name="Hosts_AdditionalLinesPosition.Header" xml:space="preserve">
|
||||
<value>Placement of additional content</value>
|
||||
<value>Position of additional content</value>
|
||||
</data>
|
||||
<data name="Hosts_AdditionalLinesPosition_Bottom.Content" xml:space="preserve">
|
||||
<value>Bottom</value>
|
||||
@@ -3653,7 +3674,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<comment>"Hosts File Editor" is the name of the utility</comment>
|
||||
</data>
|
||||
<data name="Hosts_Toggle_LaunchAdministrator.Description" xml:space="preserve">
|
||||
<value>Required in order to make changes to the hosts file</value>
|
||||
<value>Needs to be launched as administrator in order to make changes to the hosts file</value>
|
||||
</data>
|
||||
<data name="Hosts_Toggle_LaunchAdministrator.Header" xml:space="preserve">
|
||||
<value>Launch as administrator</value>
|
||||
@@ -3695,7 +3716,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Environment Variables</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_Toggle_LaunchAdministrator.Description" xml:space="preserve">
|
||||
<value>Required in order to make changes to the system environment variables</value>
|
||||
<value>Needs to be launched as administrator in order to make changes to the system environment variables</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_Toggle_LaunchAdministrator.Header" xml:space="preserve">
|
||||
<value>Launch as administrator</value>
|
||||
@@ -3736,7 +3757,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>This setting is managed by your organization.</value>
|
||||
</data>
|
||||
<data name="Hosts_AdditionalLinesPosition.Description" xml:space="preserve">
|
||||
<value>Includes items like the file header and any lines that can’t be parsed</value>
|
||||
<value>Additional content includes the file header and lines that can't parse</value>
|
||||
</data>
|
||||
<data name="TextExtractor_Languages.Header" xml:space="preserve">
|
||||
<value>Preferred language</value>
|
||||
@@ -3773,7 +3794,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Experimentation</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableExperimentation.Description" xml:space="preserve">
|
||||
<value>Only Windows Insider builds may be selected for experimentation</value>
|
||||
<value>Note: Only Windows Insider builds may be selected for experimentation</value>
|
||||
<comment>{Locked="Windows Insider"}</comment>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableExperimentation.Header" xml:space="preserve">
|
||||
@@ -3783,13 +3804,28 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Diagnostics & feedback</value>
|
||||
</data>
|
||||
<data name="GeneralPage_DiagnosticsAndFeedback_Link.Content" xml:space="preserve">
|
||||
<value>Learn more about the logged information and how it's used</value>
|
||||
<value>Learn more about the information we log & how it gets used</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableDataDiagnostics.Header" xml:space="preserve">
|
||||
<value>Diagnostic data</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableDataDiagnostics.Description" xml:space="preserve">
|
||||
<value>Helps inform bug fixes, performance, and improvements</value>
|
||||
</data>
|
||||
<data name="GeneralPage_ViewDiagnosticData.Header" xml:space="preserve">
|
||||
<value>View diagnostic data</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableViewDiagnosticData.Header" xml:space="preserve">
|
||||
<value>Save logs to this device</value>
|
||||
<value>Enable viewing</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableViewDiagnosticData.Description" xml:space="preserve">
|
||||
<value>Uses up to 1GB (or more) of hard drive space on your PC</value>
|
||||
</data>
|
||||
<data name="GeneralPage_ViewDiagnosticDataViewer.Header" xml:space="preserve">
|
||||
<value>Diagnostic data viewer</value>
|
||||
</data>
|
||||
<data name="GeneralPage_ViewDiagnosticDataViewer.Description" xml:space="preserve">
|
||||
<value>Generate .xml files containing readable diagnostic data. Folder may include .xml and .etl files</value>
|
||||
</data>
|
||||
<data name="Shell_AdvancedPaste.Content" xml:space="preserve">
|
||||
<value>Advanced Paste</value>
|
||||
@@ -3952,6 +3988,9 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="QuickAccessTxt.Text" xml:space="preserve">
|
||||
<value>Quick access</value>
|
||||
</data>
|
||||
<data name="UpdateAvailable.Title" xml:space="preserve">
|
||||
<value>Update available</value>
|
||||
</data>
|
||||
<data name="FileExplorerPreview_Toggle_Monaco_Max_File_Size.Header" xml:space="preserve">
|
||||
<value>Maximum file size to preview</value>
|
||||
<comment>Size refers to the disk space used by a file</comment>
|
||||
@@ -4016,7 +4055,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Activation shortcut</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_ThumbnailSize.Header" xml:space="preserve">
|
||||
<value>Thumbnail size</value>
|
||||
<value>Thumbnail Size</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_ThumbnailSize_Description_Prefix.Text" xml:space="preserve">
|
||||
<value>Constrain thumbnail image size to a maximum of</value>
|
||||
@@ -4151,7 +4190,11 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Launch Registry Preview</value>
|
||||
</data>
|
||||
<data name="RegistryPreview_DefaultRegApp.Header" xml:space="preserve">
|
||||
<value>Make Registry Preview the default app for .reg files</value>
|
||||
<value>Default app</value>
|
||||
</data>
|
||||
<data name="RegistryPreview_DefaultRegApp.Description" xml:space="preserve">
|
||||
<value>Make Registry Preview default app for opening .reg files</value>
|
||||
<comment>Registry Preview is app name. Do not localize.</comment>
|
||||
</data>
|
||||
<data name="AdvancedPaste_ShortcutWarning.Title" xml:space="preserve">
|
||||
<value>Using this shortcut may prevent non-text paste actions (e.g. images, files) or built-in paste plain text actions in other applications from functioning.</value>
|
||||
@@ -4229,6 +4272,12 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="Shell_Dashboard.Content" xml:space="preserve">
|
||||
<value>Dashboard</value>
|
||||
</data>
|
||||
<data name="DisabledModules.Text" xml:space="preserve">
|
||||
<value>Disabled modules</value>
|
||||
</data>
|
||||
<data name="EnabledModules.Text" xml:space="preserve">
|
||||
<value>Enabled modules</value>
|
||||
</data>
|
||||
<data name="Peek_Preview_GroupSettings.Header" xml:space="preserve">
|
||||
<value>Preview</value>
|
||||
</data>
|
||||
@@ -4272,7 +4321,7 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>Show the release notes after an update</value>
|
||||
</data>
|
||||
<data name="ShowSystemTrayIcon.Description" xml:space="preserve">
|
||||
<value>To access settings, run the PowerToys executable again</value>
|
||||
<value>This settings page is accessible by running the PowerToys executable again</value>
|
||||
</data>
|
||||
<data name="ShowSystemTrayIcon.Header" xml:space="preserve">
|
||||
<value>Show system tray icon</value>
|
||||
@@ -4372,6 +4421,10 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>New+</value>
|
||||
<comment>New+ is the name of the utility. Localize product name in accordance with Windows New</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Product_Description.Description" xml:space="preserve">
|
||||
<value>Create files and folders from a personalized set of templates</value>
|
||||
<comment>New+ product description</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Learn_More.Text" xml:space="preserve">
|
||||
<value>Learn more about New+</value>
|
||||
<comment>New+ learn more link. Localize product name in accordance with Windows New</comment>
|
||||
@@ -4408,15 +4461,15 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<comment>Display options label</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_File_Extension_Toggle.Header" xml:space="preserve">
|
||||
<value>Hide the file extension in template names</value>
|
||||
<value>Hide template filename extension</value>
|
||||
<comment>Template file name extension settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_Starting_Digits_Toggle.Header" xml:space="preserve">
|
||||
<value>Hide leading digits, spaces, and dots in template filenames</value>
|
||||
<value>Hide template filename starting digits, spaces, and dots</value>
|
||||
<comment>Template filename starting digits settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus_Hide_Starting_Digits_Description.Text" xml:space="preserve">
|
||||
<value>Ignores digits, spaces, and dots at the start of filenames—useful for sorting templates without showing those characters</value>
|
||||
<value>This option is useful when using digits, spaces and dots at the beginning of filenames to control the display order of templates</value>
|
||||
<comment>Template filename starting digits settings toggle</comment>
|
||||
</data>
|
||||
<data name="NewPlus_behavior.Header" xml:space="preserve">
|
||||
@@ -4803,13 +4856,13 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
||||
<value>Open settings</value>
|
||||
</data>
|
||||
<data name="LanguageHeader.Header" xml:space="preserve">
|
||||
<value>Language</value>
|
||||
<value>Application language</value>
|
||||
</data>
|
||||
<data name="LanguageHeader.Description" xml:space="preserve">
|
||||
<value>PowerToys matches your Windows language by default</value>
|
||||
<value>PowerToys will use OS language by default.</value>
|
||||
</data>
|
||||
<data name="LanguageRestartInfo.Title" xml:space="preserve">
|
||||
<value>Restart PowerToys to apply language changes</value>
|
||||
<value>Restart PowerToys for language change to take effect.</value>
|
||||
</data>
|
||||
<data name="LanguageRestartInfoButton.Content" xml:space="preserve">
|
||||
<value>Restart</value>
|
||||
@@ -5004,7 +5057,7 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
||||
<value>Generate bug report package</value>
|
||||
</data>
|
||||
<data name="GeneralPage_ReportBugPackage.Description" xml:space="preserve">
|
||||
<value>Log files will be zipped to your desktop</value>
|
||||
<value>Create zip folder with logs on the Desktop</value>
|
||||
</data>
|
||||
<data name="GeneralPageReportBugPackage.Content" xml:space="preserve">
|
||||
<value>Generate package</value>
|
||||
@@ -5027,41 +5080,4 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
||||
<data name="HighlightMode_Spotlight_Mode.Content" xml:space="preserve">
|
||||
<value>Spotlight</value>
|
||||
</data>
|
||||
<data name="LearnMore.Content" xml:space="preserve">
|
||||
<value>Learn more</value>
|
||||
</data>
|
||||
<data name="Awake_ShortDescription" xml:space="preserve">
|
||||
<value>Keep your PC awake</value>
|
||||
</data>
|
||||
<data name="ImageResizer_ShortDescription" xml:space="preserve">
|
||||
<value>Resize images from right-click context menu</value>
|
||||
</data>
|
||||
<data name="MouseWithoutBorders_ShortDescription" xml:space="preserve">
|
||||
<value>Move your cursor across multiple devices</value>
|
||||
</data>
|
||||
<data name="PowerRename_ShortDescription" xml:space="preserve">
|
||||
<value>Rename files and folders from right-click context menu</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableDataDiagnosticsText.Text" xml:space="preserve">
|
||||
<value>Helps us make PowerToys faster, more stable, and better over time</value>
|
||||
</data>
|
||||
<data name="UpdateAvailable.Title" xml:space="preserve">
|
||||
<value>Update available</value>
|
||||
</data>
|
||||
<data name="DisabledModules.Text" xml:space="preserve">
|
||||
<value>Disabled modules</value>
|
||||
</data>
|
||||
<data name="EnabledModules.Text" xml:space="preserve">
|
||||
<value>Enabled modules</value>
|
||||
</data>
|
||||
<data name="NewPlus_Product_Description.Description" xml:space="preserve">
|
||||
<value>Create files and folders from a personalized set of templates</value>
|
||||
<comment>New+ product description</comment>
|
||||
</data>
|
||||
<data name="AlwaysOnTop_Sound.Header" xml:space="preserve">
|
||||
<value>Play a sound when pinning a window</value>
|
||||
</data>
|
||||
<data name="GeneralPage_EnableViewDiagnosticDataText.Text" xml:space="preserve">
|
||||
<value>Stores diagnostic data locally in .xml format; folder may include .etl files as well. May use up 1 GB or more of disk space.</value>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user