Compare commits

..

1 Commits

Author SHA1 Message Date
Leilei Zhang
d6b3baae96 fix Bgcode official build error 2025-07-11 11:12:30 +08:00
575 changed files with 2770 additions and 12361 deletions

View File

@@ -282,9 +282,3 @@ xef
xes
PACKAGEVERSIONNUMBER
APPXMANIFESTVERSION
# MRU lists
CACHEWRITE
MRUCMPPROC
MRUINFO
REGSTR

View File

@@ -38,7 +38,6 @@ ALLAPPS
ALLCHILDREN
ALLINPUT
Allman
Allmodule
ALLOWUNDO
ALLVIEW
ALPHATYPE
@@ -219,7 +218,6 @@ coclass
CODENAME
codereview
Codespaces
Coen
COINIT
colid
colorconv
@@ -247,7 +245,6 @@ CONTEXTMENUHANDLER
contractversion
CONTROLPARENT
copiedcolorrepresentation
coppied
copyable
COPYPEN
COREWINDOW
@@ -446,7 +443,6 @@ ERRORIMAGE
ERRORTITLE
ESettings
esrp
etd
ETDT
etl
etw
@@ -531,8 +527,8 @@ frm
FROMTOUCH
fsanitize
fsmgmt
fuzzingtesting
fxf
fuzzingtesting
FZE
gacutil
Gaeilge
@@ -737,7 +733,6 @@ INSTALLSTARTMENUSHORTCUT
INSTALLSTATE
Inste
Interlop
intput
INTRESOURCE
INVALIDARG
invalidoperatioexception
@@ -820,7 +815,6 @@ LMEM
LMENU
LOADFROMFILE
LOBYTE
localappdata
localpackage
LOCALSYSTEM
LOCATIONCHANGE
@@ -1123,7 +1117,6 @@ oldtheme
oleaut
OLECHAR
onebranch
OOBEUI
openas
opencode
OPENFILENAME
@@ -1389,7 +1382,6 @@ RIDEV
RIGHTSCROLLBAR
riid
RKey
Rns
RNumber
rop
ROUNDSMALL
@@ -1401,7 +1393,6 @@ Rsp
rstringalnum
rstringalpha
rstringdigit
rtb
RTB
RTLREADING
rtm
@@ -1536,7 +1527,6 @@ SLGP
sln
SMALLICON
smartphone
smileys
SMTO
SNAPPROCESS
snk
@@ -1623,8 +1613,6 @@ svgz
SVSI
SWFO
SWP
SWPNOSIZE
SWPNOZORDER
SWRESTORE
symbolrequestprod
SYMCACHE
@@ -1764,8 +1752,8 @@ Uptool
urld
Usb
USEDEFAULT
USEFILEATTRIBUTES
USEINSTALLERFORTEST
USEFILEATTRIBUTES
USESHOWWINDOW
USESTDHANDLES
USRDLL

View File

@@ -4,7 +4,7 @@
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
- [ ] Closes: #xxx
- [ ] **Closes:** #xxx
- [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized

View File

@@ -43,7 +43,6 @@ stages:
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
runTests: true
useVSPreview: ${{ parameters.useVSPreview }}
timeoutInMinutes: 90
- stage: OneFuzz
displayName: Fuzz ${{ parameters.platform }}

View File

@@ -38,11 +38,6 @@ parameters:
displayName: "Build Using Visual Studio Preview"
default: false
- name: enableAOT
type: boolean
displayName: "Enable AOT (Ahead-of-Time) Compilation for CmdPal"
default: true
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
variables:
@@ -100,7 +95,7 @@ extends:
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
# Have msbuild use the release nuget config profile
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=${{ parameters.enableAOT }}
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
beforeBuildSteps:
# Sets versions for all PowerToy created DLLs
- pwsh: |-

View File

@@ -81,12 +81,6 @@ parameters:
- 'src/modules/previewpane/SvgPreviewHandler/SvgPreviewHandler.csproj'
- 'src/modules/previewpane/SvgThumbnailProvider/SvgThumbnailProvider.csproj'
- 'src/modules/FileLocksmith/FileLocksmithUI/FileLocksmithUI.csproj'
- name: timeoutInMinutes
type: number
default: 240
- name: cancelTimeoutInMinutes
type: number
default: 1
jobs:
- job: ${{ parameters.jobName }}
@@ -129,8 +123,8 @@ jobs:
${{ else }}:
RestoreAdditionalProjectSourcesArg: ''
displayName: Build
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }}
timeoutInMinutes: 240
cancelTimeoutInMinutes: 1
templateContext: # Required when this template is hosted in 1ES PT
outputs:
- output: pipelineArtifact

View File

@@ -160,7 +160,6 @@ jobs:
vsTestVersion: 'toolsInstaller'
uiTests: true
rerunFailedTests: true
testRunTitle: 'UITests_${{ parameters.platform }}_${{ parameters.installMode }}'
# Since UITests-FancyZonesEditor.dll is generated in both UITests-FancyZonesEditor and UITests-FancyZones, removed one to avoid duplicate test runs
testAssemblyVer2: |
**\*UITest*.dll
@@ -183,7 +182,6 @@ jobs:
vsTestVersion: 'toolsInstaller'
uiTests: true
rerunFailedTests: true
testRunTitle: 'UITests_${{ parameters.platform }}_${{ parameters.installMode }}'
testAssemblyVer2: |
**\*${{ module }}*.dll
!**\obj\**

View File

@@ -57,5 +57,4 @@ stages:
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
${{ if eq(parameters.useLatestWinAppSDK, true) }}:
winAppSDKVersionNumber: ${{ parameters.winAppSDKVersionNumber }}
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}
timeoutInMinutes: 90
useExperimentalVersion: ${{ parameters.useExperimentalVersion }}

View File

@@ -56,7 +56,6 @@ stages:
runTests: false
buildTests: true
useVSPreview: ${{ parameters.useVSPreview }}
timeoutInMinutes: 90
- ${{ if eq(parameters.useLatestOfficialBuild, true) }}:
- stage: BuildUITests_${{ platform }}

View File

@@ -19,7 +19,7 @@ Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude *UITest*,MouseJum
# Temporarily exclude All UI-Test, Fuzzer-Test projects because of Appium.WebDriver dependencies
$depsJsonFullFileName = $_.FullName
if ($depsJsonFullFileName -like "*CmdPal*" -or $depsJsonFullFileName -like "*CommandPalette*") {
if ($depsJsonFullFileName -like "*CmdPal*") {
return
}

View File

@@ -9,7 +9,6 @@
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.17" />
<PackageVersion Include="CoenM.ImageSharp.ImageHash" Version="1.3.6" />
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.250402" />
@@ -22,7 +21,6 @@
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250703-build.2173" />
<PackageVersion Include="ControlzEx" Version="6.0.0" />
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
@@ -70,7 +68,6 @@
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
<PackageVersion Include="OpenAI" Version="2.0.0" />
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
<PackageVersion Include="SharpCompress" Version="0.37.2" />
<!-- Don't update SkiaSharp.Views.WinUI to version 3.* branch as this brakes the HexBox control in Registry Preview. -->

View File

@@ -1496,9 +1496,7 @@ SOFTWARE.
- AdaptiveCards.Templating 2.0.5
- Appium.WebDriver 4.4.5
- Azure.AI.OpenAI 1.0.0-beta.17
- CoenM.ImageSharp.ImageHash 1.3.6
- CommunityToolkit.Common 8.4.0
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock 0.1.250703-build.2173
- CommunityToolkit.Mvvm 8.4.0
- CommunityToolkit.WinUI.Animations 8.2.250402
- CommunityToolkit.WinUI.Collections 8.2.250402
@@ -1581,3 +1579,4 @@ SOFTWARE.
- WinUIEx 2.2.0
- WPF-UI 3.0.5
- WyHash 1.0.5

View File

@@ -39,14 +39,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fancyzones", "fancyzones",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesLib", "src\modules\fancyzones\FancyZonesLib\FancyZonesLib.vcxproj", "{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones.UnitTests", "src\modules\fancyzones\FancyZonesTests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests-FancyZones", "src\modules\fancyzones\FancyZonesTests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}"
ProjectSection(ProjectDependencies) = postProject
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{1AFB6476-670D-4E80-A464-657E01DFF482}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common.Lib.UnitTests", "src\common\UnitTests-CommonLib\UnitTests-CommonLib.vcxproj", "{1A066C63-64B3-45F8-92FE-664E1CCE8077}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests-CommonLib", "src\common\UnitTests-CommonLib\UnitTests-CommonLib.vcxproj", "{1A066C63-64B3-45F8-92FE-664E1CCE8077}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditor", "src\modules\fancyzones\editor\FancyZonesEditor\FancyZonesEditor.csproj", "{5CCC8468-DEC8-4D36-99D4-5C891BEBD481}"
EndProject
@@ -60,8 +60,11 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modules\powerrename\lib\PowerRenameLib.vcxproj", "{51920F1F-C28C-4ADF-8660-4238766796C2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}"
ProjectSection(ProjectDependencies) = postProject
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.UnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
ProjectSection(ProjectDependencies) = postProject
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670}
@@ -77,7 +80,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResizerUI", "src\modul
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerExt", "src\modules\imageresizer\dll\ImageResizerExt.vcxproj", "{0B43679E-EDFA-4DA0-AD30-F4628B308B1B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResizer.UnitTests", "src\modules\imageresizer\tests\ImageResizer.UnitTests.csproj", "{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResizerUITest", "src\modules\imageresizer\tests\ImageResizerUITest.csproj", "{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.ActionRunner", "src\ActionRunner\ActionRunner.vcxproj", "{D29DDD63-E2CF-4657-9FD5-2AEDE4257E5D}"
ProjectSection(ProjectDependencies) = postProject
@@ -149,13 +152,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PreviewHandlerCommon", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkdownPreviewHandler", "src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj", "{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.MarkdownPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-MarkdownPreviewHandler\Preview.MarkdownPreviewHandler.UnitTests.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-MarkdownPreviewHandler", "src\modules\previewpane\UnitTests-MarkdownPreviewHandler\UnitTests-MarkdownPreviewHandler.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgPreviewHandler", "src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj", "{DA425894-6E13-404F-8DCB-78584EC0557A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.SvgPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-SvgPreviewHandler\Preview.SvgPreviewHandler.UnitTests.csproj", "{060D75DA-2D1C-48E6-A4A1-6F0718B64661}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-SvgPreviewHandler", "src\modules\previewpane\UnitTests-SvgPreviewHandler\UnitTests-SvgPreviewHandler.csproj", "{060D75DA-2D1C-48E6-A4A1-6F0718B64661}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PreviewHandlerCommon.UnitTests", "src\modules\previewpane\UnitTests-PreviewHandlerCommon\Preview.PreviewHandlerCommon.UnitTests.csproj", "{748417CA-F17E-487F-9411-CAFB6D3F4877}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PreviewHandlerCommon", "src\modules\previewpane\UnitTests-PreviewHandlerCommon\UnitTests-PreviewHandlerCommon.csproj", "{748417CA-F17E-487F-9411-CAFB6D3F4877}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "powerpreview", "src\modules\previewpane\powerpreview\powerpreview.vcxproj", "{217DF501-135C-4E38-BFC8-99D4821032EA}"
ProjectSection(ProjectDependencies) = postProject
@@ -192,7 +195,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ManagedCommon", "src\common
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Program.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.Program.UnitTests\Microsoft.Plugin.Program.UnitTests.csproj", "{42851751-CBC8-45A6-97F5-7A0753F7B4D1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.SvgThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-SvgThumbnailProvider\Preview.SvgThumbnailProvider.UnitTests.csproj", "{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-SvgThumbnailProvider", "src\modules\previewpane\UnitTests-SvgThumbnailProvider\UnitTests-SvgThumbnailProvider.csproj", "{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgThumbnailProvider", "src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj", "{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD}"
EndProject
@@ -213,6 +216,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Settings.UI.UnitTests", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest\Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest.csproj", "{632BBE62-5421-49EA-835A-7FFA4F499BD6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Folder.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj", "{4FA206A5-F69F-4193-BF8F-F6EEB496734C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest-ColorPickerUI", "src\modules\colorPicker\UnitTest-ColorPickerUI\UnitTest-ColorPickerUI.csproj", "{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.System", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.System\Microsoft.PowerToys.Run.Plugin.System.csproj", "{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B}"
@@ -228,7 +235,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "src\common\logger
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SettingsAPI", "src\common\SettingsAPI\SettingsAPI.vcxproj", "{6955446D-23F7-4023-9BB3-8657F904AF99}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.Interop.UnitTests", "src\common\interop\interop-tests\Common.Interop.UnitTests.csproj", "{58736667-1027-4AD7-BFDF-7A3A6474103A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.Tests", "src\common\interop\interop-tests\Microsoft.Interop.Tests.csproj", "{58736667-1027-4AD7-BFDF-7A3A6474103A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "notifications", "notifications", "{D92131D6-7610-4D60-A7DB-1C169783F83B}"
EndProject
@@ -300,7 +307,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.UI", "src\common\Com
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfPreviewHandler", "src\modules\previewpane\PdfPreviewHandler\PdfPreviewHandler.csproj", "{69E1EE8D-143A-4060-9129-4658ACF14AAF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PdfPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-PdfPreviewHandler\Preview.PdfPreviewHandler.UnitTests.csproj", "{ECC20689-002A-4354-95A6-B58DF089C6FF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfPreviewHandler", "src\modules\previewpane\UnitTests-PdfPreviewHandler\UnitTests-PdfPreviewHandler.csproj", "{ECC20689-002A-4354-95A6-B58DF089C6FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.csproj", "{4BABF3FE-3451-42FD-873F-3C332E18DCEF}"
EndProject
@@ -310,13 +317,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngine", "sr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngineLibrary", "src\modules\keyboardmanager\KeyboardManagerEngineLibrary\KeyboardManagerEngineLibrary.vcxproj", "{E496B7FC-1E99-4BAB-849B-0E8367040B02}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Engine.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEngineTest\KeyboardManagerEngineTest.vcxproj", "{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngineTest", "src\modules\keyboardmanager\KeyboardManagerEngineTest\KeyboardManagerEngineTest.vcxproj", "{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditor", "src\modules\keyboardmanager\KeyboardManagerEditor\KeyboardManagerEditor.vcxproj", "{8DF78B53-200E-451F-9328-01EB907193AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibrary", "src\modules\keyboardmanager\KeyboardManagerEditorLibrary\KeyboardManagerEditorLibrary.vcxproj", "{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Editor.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEditorTest\KeyboardManagerEditorTest.vcxproj", "{62173D9A-6724-4C00-A1C8-FB646480A9EC}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorTest", "src\modules\keyboardmanager\KeyboardManagerEditorTest\KeyboardManagerEditorTest.vcxproj", "{62173D9A-6724-4C00-A1C8-FB646480A9EC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "awake", "awake", "{127F38E0-40AA-4594-B955-5616BF206882}"
EndProject
@@ -344,7 +351,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfThumbnailProvider", "src\modules\previewpane\PdfThumbnailProvider\PdfThumbnailProvider.csproj", "{11491FD8-F921-48BF-880C-7FEA185B80A1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.PdfThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\Preview.PdfThumbnailProvider.UnitTests.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfThumbnailProvider", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\UnitTests-PdfThumbnailProvider.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.csproj", "{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}"
EndProject
@@ -358,11 +365,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseHighlighter", "src\mod
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GcodeThumbnailProvider", "src\modules\previewpane\GcodeThumbnailProvider\GcodeThumbnailProvider.csproj", "{809AA252-E17A-4FA2-B0A1-0450976B763F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.GcodeThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-GcodeThumbnailProvider\Preview.GcodeThumbnailProvider.UnitTests.csproj", "{133281D8-1BCE-4D07-B31E-796612A9609E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-GcodeThumbnailProvider", "src\modules\previewpane\UnitTests-GcodeThumbnailProvider\UnitTests-GcodeThumbnailProvider.csproj", "{133281D8-1BCE-4D07-B31E-796612A9609E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GcodePreviewHandler", "src\modules\previewpane\GcodePreviewHandler\GcodePreviewHandler.csproj", "{805306FF-A562-4415-8DEF-E493BDC45918}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.GcodePreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-GcodePreviewHandler\Preview.GcodePreviewHandler.UnitTests.csproj", "{FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-GcodePreviewHandler", "src\modules\previewpane\UnitTests-GcodePreviewHandler\UnitTests-GcodePreviewHandler.csproj", "{FCF3E52D-B80A-4FC3-98FD-6391354F0EE3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AlwaysOnTop", "AlwaysOnTop", "{60CD2D4F-C3B9-4897-9821-FCA5098B41CE}"
EndProject
@@ -376,7 +383,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MousePointerCrosshairs", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StlThumbnailProvider", "src\modules\previewpane\StlThumbnailProvider\StlThumbnailProvider.csproj", "{F7C8C0F1-5431-4347-89D0-8E5354F93CF2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.StlThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-StlThumbnailProvider\Preview.StlThumbnailProvider.UnitTests.csproj", "{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-StlThumbnailProvider", "src\modules\previewpane\UnitTests-StlThumbnailProvider\UnitTests-StlThumbnailProvider.csproj", "{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonacoPreviewHandler", "src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj", "{04B193D7-3E21-46B8-A958-89B63A8A69DE}"
EndProject
@@ -412,8 +419,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerOCR", "src\modules\Pow
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerOCRModuleInterface", "src\modules\PowerOCR\PowerOCRModuleInterface\PowerOCRModuleInterface.vcxproj", "{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B1234567-1234-1234-1234-123456789ABC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.History", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.History\Microsoft.PowerToys.Run.Plugin.History.csproj", "{212AD910-8488-4036-BE20-326931B75FB2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MeasureTool", "MeasureTool", "{7AC943C9-52E8-44CF-9083-744D8049667B}"
@@ -435,7 +440,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsUILib", "src\modules\H
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosts", "Hosts", "{F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsEditor.UnitTests", "src\modules\Hosts\Hosts.Tests\HostsEditor.UnitTests.csproj", "{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hosts.Tests", "src\modules\Hosts\Hosts.Tests\Hosts.Tests.csproj", "{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HostsModuleInterface", "src\modules\Hosts\HostsModuleInterface\HostsModuleInterface.vcxproj", "{B41B888C-7DB8-4747-B262-4062E05A230D}"
EndProject
@@ -525,6 +530,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CropAndLockModuleInterface"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cmdNotFound", "cmdNotFound", "{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-FancyZonesEditor", "src\modules\fancyzones\UnitTests-FancyZonesEditor\UnitTests-FancyZonesEditor.csproj", "{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EnvironmentVariables", "EnvironmentVariables", "{538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentVariablesUILib", "src\modules\EnvironmentVariables\EnvironmentVariablesUILib\EnvironmentVariablesUILib.csproj", "{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}"
@@ -539,9 +546,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QoiPreviewHandlerCpp", "src
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QoiPreviewHandler", "src\modules\previewpane\QoiPreviewHandler\QoiPreviewHandler.csproj", "{6B04803D-B418-4833-A67E-B0FC966636A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.QoiPreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-QoiPreviewHandler\Preview.QoiPreviewHandler.UnitTests.csproj", "{3940AD4D-F748-4BE4-9083-85769CD553EF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-QoiPreviewHandler", "src\modules\previewpane\UnitTests-QoiPreviewHandler\UnitTests-QoiPreviewHandler.csproj", "{3940AD4D-F748-4BE4-9083-85769CD553EF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preview.QoiThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-QoiThumbnailProvider\Preview.QoiThumbnailProvider.UnitTests.csproj", "{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-QoiThumbnailProvider", "src\modules\previewpane\UnitTests-QoiThumbnailProvider\UnitTests-QoiThumbnailProvider.csproj", "{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdNotFoundModuleInterface", "src\modules\cmdNotFound\CmdNotFoundModuleInterface\CmdNotFoundModuleInterface.vcxproj", "{0014D652-901F-4456-8D65-06FC5F997FB0}"
EndProject
@@ -557,6 +564,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreview", "src\modu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentVariables", "src\modules\EnvironmentVariables\EnvironmentVariables\EnvironmentVariables.csproj", "{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITests-FancyZones", "src\modules\fancyzones\UITests-FancyZones\UITests-FancyZones.csproj", "{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UITests-FancyZonesEditor", "src\modules\fancyzones\UITests-FancyZonesEditor\UITests-FancyZonesEditor.csproj", "{3A9A791E-94A9-49F8-8401-C11CE288D5FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FancyZonesEditorCommon", "src\modules\fancyzones\FancyZonesEditorCommon\FancyZonesEditorCommon.csproj", "{C0974915-8A1D-4BF0-977B-9587D3807AB7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DSC", "DSC", "{557C4636-D7E1-4838-A504-7D19B725EE95}"
@@ -593,7 +604,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowProperties", "WindowP
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLib", "src\modules\Workspaces\WorkspacesLib\WorkspacesLib.vcxproj", "{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Workspaces.Lib.UnitTests", "src\modules\Workspaces\WorkspacesLib.UnitTests\WorkspacesLibUnitTests.vcxproj", "{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLibUnitTests", "src\modules\Workspaces\WorkspacesLib.UnitTests\WorkspacesLibUnitTests.vcxproj", "{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkspacesLauncherUI", "src\modules\Workspaces\WorkspacesLauncherUI\WorkspacesLauncherUI.csproj", "{9C53CC25-0623-4569-95BC-B05410675EE3}"
EndProject
@@ -669,6 +680,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSea
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{7F5B9557-5878-4438-A721-3E28296BA193}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ZoomIt", "ZoomIt", "{DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomIt", "src\modules\ZoomIt\ZoomIt\ZoomIt.vcxproj", "{0A84F764-3A88-44CD-AA96-41BDBD48627B}"
@@ -685,17 +700,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyboardManagerEditorUI", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibraryWrapper", "src\modules\keyboardmanager\KeyboardManagerEditorLibraryWrapper\KeyboardManagerEditorLibraryWrapper.vcxproj", "{4382A954-179A-4078-92AF-715187DFFF50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostsEditor.FuzzTests", "src\modules\Hosts\Hosts.FuzzTests\HostsEditor.FuzzTests.csproj", "{EBED240C-8702-452D-B764-6DB9DA9179AF}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.FuzzTests", "src\modules\Hosts\Hosts.FuzzTests\Hosts.FuzzTests.csproj", "{EBED240C-8702-452D-B764-6DB9DA9179AF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HostsEditor.UITests", "src\modules\Hosts\Hosts.UITests\HostsEditor.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.UITests", "src\modules\Hosts\Hosts.UITests\Hosts.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests", "src\modules\registrypreview\RegistryPreview.FuzzTests\RegistryPreview.FuzzTests.csproj", "{5702B3CC-8575-48D5-83D8-15BB42269CD3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.FuzzTests", "src\modules\fancyzones\FancyZones.FuzzTests\FancyZones.FuzzTests.csproj", "{0217E86E-3476-9946-DE8E-9D200CEBD47A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzTests", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BgcodePreviewHandler", "src\modules\previewpane\BgcodePreviewHandler\BgcodePreviewHandler.csproj", "{9E0CBC06-F29A-4810-B93C-97D53863B95E}"
EndProject
@@ -705,84 +722,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BgcodeThumbnailProviderCpp"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BgcodeThumbnailProvider", "src\modules\previewpane\BgcodeThumbnailProvider\BgcodeThumbnailProvider.csproj", "{9BC1C986-1E97-4D07-A7B1-CE226C239EFA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preview.BgcodePreviewHandler.UnitTests", "src\modules\previewpane\UnitTests-BgcodePreviewHandler\Preview.BgcodePreviewHandler.UnitTests.csproj", "{99CA1509-FB73-456E-AFAF-AB89C017BD72}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-BgcodePreviewHandler", "src\modules\previewpane\UnitTests-BgcodePreviewHandler\UnitTests-BgcodePreviewHandler.csproj", "{99CA1509-FB73-456E-AFAF-AB89C017BD72}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Preview.BgcodeThumbnailProvider.UnitTests", "src\modules\previewpane\UnitTests-BgcodeThumbnailProvider\Preview.BgcodeThumbnailProvider.UnitTests.csproj", "{61CBF221-9452-4934-B685-146285E080D7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-BgcodeThumbnailProvider", "src\modules\previewpane\UnitTests-BgcodeThumbnailProvider\UnitTests-BgcodeThumbnailProvider.csproj", "{61CBF221-9452-4934-B685-146285E080D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseUtils.UITests", "src\modules\MouseUtils\MouseUtils.UITests\MouseUtils.UITests.csproj", "{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Workspaces.Editor.UITests", "src\modules\Workspaces\WorkspacesEditorUITest\Workspaces.Editor.UITests.csproj", "{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesEditorUITest", "src\modules\Workspaces\WorkspacesEditorUITest\WorkspacesEditorUITest.csproj", "{43E779F3-D83C-48B1-BA8D-1912DBD76FC9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorEngineCommon", "src\common\CalculatorEngineCommon\CalculatorEngineCommon.vcxproj", "{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedCsWin32", "src\common\ManagedCsWin32\ManagedCsWin32.csproj", "{14AFD976-B4D2-49D0-9E6C-AA93CC061B8A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerRename.UITests", "src\modules\powerrename\PowerRenameUITest\PowerRename.UITests.csproj", "{9D3F3793-EFE3-4525-8782-238015DABA62}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Core.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.Core.ViewModels\Microsoft.CmdPal.Core.ViewModels.csproj", "{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0E556541-6A45-42CB-AE49-EE5A9BE05E7C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{27D9CB3A-46D1-402C-9273-F88CB8AC42F7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B9617A31-0F0A-4397-851D-BF2FBEE32D7F}"
ProjectSection(SolutionItems) = preProject
src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj = src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1C48CD47-D610-463A-A53C-AF82DD6C47E7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D9BD324E-1D80-44AA-8E7B-73EB00944434}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{8EF25507-2575-4ADE-BF7E-D23376903AB8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerOCR.UITests", "src\modules\PowerOCR\PowerOCR-UITests\PowerOCR.UITests.csproj", "{070AC093-C9F2-20AD-0BCD-F318FC2761EA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{2C318EC3-BA86-4372-B1BC-DB0F33C208B2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BFFB607F-7C78-434B-86B9-DA4C8196A1B5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{66E1534A-1587-42B2-912F-45C994D32904}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E885E71F-0B34-4A03-B13B-20F4E05E90BB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{264B412F-DB8B-4CF8-A74B-96998B183045}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3527BF37-DFC5-4309-A032-29278CA21328}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{68328142-5B31-4715-BCBB-7B6345EE0971}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{4122388B-59E4-CDB0-0338-EA6881DF86F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UITests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UITests\Microsoft.CmdPal.UITests.csproj", "{6748A29D-DA6A-033A-825B-752295FF6AA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.FuzzTests", "src\modules\fancyzones\FancyZones.FuzzTests\FancyZones.FuzzTests.csproj", "{6EABCF9A-6526-441F-932F-658B1DC3E403}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZones.UITests", "src\modules\fancyzones\FancyZones.UITests\FancyZones.UITests.csproj", "{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZonesEditor.UITests", "src\modules\fancyzones\FancyZonesEditor.UITests\FancyZonesEditor.UITests.csproj", "{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FancyZonesEditor.UnitTests", "src\modules\fancyzones\FancyZonesEditor.UnitTests\FancyZonesEditor.UnitTests.csproj", "{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPickerUI.UnitTests", "src\modules\colorPicker\ColorPickerUI.UnitTests\ColorPickerUI.UnitTests.csproj", "{F93C2817-C846-4259-84D8-B39A6B57C8DE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{8131151D-B0E9-4E18-84A5-E5F946C4480A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Calc.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Calc.UnitTests\Microsoft.CmdPal.Ext.Calc.UnitTests.csproj", "{E816D7AC-4688-4ECB-97CC-3D8E798F3825}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Registry.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.Registry.UnitTests\Microsoft.CmdPal.Ext.Registry.UnitTests.csproj", "{E816D7AD-4688-4ECB-97CC-3D8E798F3826}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.System.UnitTests\Microsoft.CmdPal.Ext.System.UnitTests.csproj", "{E816D7AE-4688-4ECB-97CC-3D8E798F3827}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.TimeDate.UnitTests\Microsoft.CmdPal.Ext.TimeDate.UnitTests.csproj", "{E816D7AF-4688-4ECB-97CC-3D8E798F3828}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WindowWalker.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.Ext.WindowWalker.UnitTests\Microsoft.CmdPal.Ext.WindowWalker.UnitTests.csproj", "{E816D7B0-4688-4ECB-97CC-3D8E798F3829}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerRenameUITest", "src\modules\powerrename\PowerRenameUITest\PowerRenameUITest.csproj", "{9D3F3793-EFE3-4525-8782-238015DABA62}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1184,6 +1136,22 @@ Global
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|ARM64.Build.0 = Release|ARM64
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.ActiveCfg = Release|x64
{632BBE62-5421-49EA-835A-7FFA4F499BD6}.Release|x64.Build.0 = Release|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|ARM64.ActiveCfg = Debug|ARM64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|ARM64.Build.0 = Debug|ARM64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.ActiveCfg = Debug|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.Build.0 = Debug|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|ARM64.ActiveCfg = Release|ARM64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|ARM64.Build.0 = Release|ARM64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.ActiveCfg = Release|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.Build.0 = Release|x64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|ARM64.ActiveCfg = Debug|ARM64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|ARM64.Build.0 = Debug|ARM64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.ActiveCfg = Debug|x64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.Build.0 = Debug|x64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|ARM64.ActiveCfg = Release|ARM64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|ARM64.Build.0 = Release|ARM64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.ActiveCfg = Release|x64
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.Build.0 = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.Build.0 = Debug|ARM64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
@@ -2068,6 +2036,14 @@ Global
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|ARM64.Build.0 = Release|ARM64
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.ActiveCfg = Release|x64
{3157FA75-86CF-4EE2-8F62-C43F776493C6}.Release|x64.Build.0 = Release|x64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|ARM64.Build.0 = Debug|ARM64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|x64.ActiveCfg = Debug|x64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Debug|x64.Build.0 = Debug|x64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Release|ARM64.ActiveCfg = Release|ARM64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Release|ARM64.Build.0 = Release|ARM64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Release|x64.ActiveCfg = Release|x64
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B}.Release|x64.Build.0 = Release|x64
{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|ARM64.Build.0 = Debug|Any CPU
{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -2192,6 +2168,22 @@ Global
{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|ARM64.Build.0 = Release|ARM64
{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|x64.ActiveCfg = Release|x64
{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8}.Release|x64.Build.0 = Release|x64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|ARM64.Build.0 = Debug|ARM64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x64.ActiveCfg = Debug|x64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Debug|x64.Build.0 = Debug|x64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|ARM64.ActiveCfg = Release|ARM64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|ARM64.Build.0 = Release|ARM64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x64.ActiveCfg = Release|x64
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52}.Release|x64.Build.0 = Release|x64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|ARM64.ActiveCfg = Debug|ARM64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|ARM64.Build.0 = Debug|ARM64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x64.ActiveCfg = Debug|x64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Debug|x64.Build.0 = Debug|x64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|ARM64.ActiveCfg = Release|ARM64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|ARM64.Build.0 = Release|ARM64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x64.ActiveCfg = Release|x64
{3A9A791E-94A9-49F8-8401-C11CE288D5FB}.Release|x64.Build.0 = Release|x64
{C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.ActiveCfg = Debug|ARM64
{C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|ARM64.Build.0 = Debug|ARM64
{C0974915-8A1D-4BF0-977B-9587D3807AB7}.Debug|x64.ActiveCfg = Debug|x64
@@ -2516,6 +2508,22 @@ Global
{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.ActiveCfg = Release|x64
{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.Build.0 = Release|x64
{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}.Release|x64.Deploy.0 = Release|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|ARM64.Build.0 = Debug|ARM64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|x64.ActiveCfg = Debug|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Debug|x64.Build.0 = Debug|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|ARM64.ActiveCfg = Release|ARM64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|ARM64.Build.0 = Release|ARM64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|x64.ActiveCfg = Release|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|x64.Build.0 = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|ARM64.Build.0 = Debug|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x64.ActiveCfg = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x64.Build.0 = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|ARM64.ActiveCfg = Release|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|ARM64.Build.0 = Release|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x64.ActiveCfg = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x64.Build.0 = Release|x64
{0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.Build.0 = Debug|ARM64
{0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x64.ActiveCfg = Debug|x64
@@ -2608,6 +2616,14 @@ Global
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.Build.0 = Debug|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.ActiveCfg = Debug|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.Build.0 = Debug|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.ActiveCfg = Release|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.Build.0 = Release|ARM64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.ActiveCfg = Release|x64
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.Build.0 = Release|x64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64
@@ -2710,126 +2726,6 @@ Global
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|ARM64.Build.0 = Release|ARM64
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.ActiveCfg = Release|x64
{9D3F3793-EFE3-4525-8782-238015DABA62}.Release|x64.Build.0 = Release|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.ActiveCfg = Debug|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|ARM64.Build.0 = Debug|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.ActiveCfg = Debug|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Debug|x64.Build.0 = Debug|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.ActiveCfg = Release|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|ARM64.Build.0 = Release|ARM64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.ActiveCfg = Release|x64
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027}.Release|x64.Build.0 = Release|x64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|ARM64.ActiveCfg = Debug|ARM64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|ARM64.Build.0 = Debug|ARM64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|x64.ActiveCfg = Debug|x64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Debug|x64.Build.0 = Debug|x64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|ARM64.ActiveCfg = Release|ARM64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|ARM64.Build.0 = Release|ARM64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|x64.ActiveCfg = Release|x64
{070AC093-C9F2-20AD-0BCD-F318FC2761EA}.Release|x64.Build.0 = Release|x64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|ARM64.ActiveCfg = Debug|ARM64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|ARM64.Build.0 = Debug|ARM64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|x64.ActiveCfg = Debug|x64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Debug|x64.Build.0 = Debug|x64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|ARM64.ActiveCfg = Release|ARM64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|ARM64.Build.0 = Release|ARM64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|x64.ActiveCfg = Release|x64
{4122388B-59E4-CDB0-0338-EA6881DF86F0}.Release|x64.Build.0 = Release|x64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|ARM64.ActiveCfg = Debug|ARM64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|ARM64.Build.0 = Debug|ARM64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|x64.ActiveCfg = Debug|x64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Debug|x64.Build.0 = Debug|x64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|ARM64.ActiveCfg = Release|ARM64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|ARM64.Build.0 = Release|ARM64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|x64.ActiveCfg = Release|x64
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55}.Release|x64.Build.0 = Release|x64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|ARM64.Build.0 = Debug|ARM64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|x64.ActiveCfg = Debug|x64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Debug|x64.Build.0 = Debug|x64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|ARM64.ActiveCfg = Release|ARM64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|ARM64.Build.0 = Release|ARM64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|x64.ActiveCfg = Release|x64
{6748A29D-DA6A-033A-825B-752295FF6AA0}.Release|x64.Build.0 = Release|x64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|ARM64.Build.0 = Debug|ARM64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|x64.ActiveCfg = Debug|x64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Debug|x64.Build.0 = Debug|x64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|ARM64.ActiveCfg = Release|ARM64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|ARM64.Build.0 = Release|ARM64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|x64.ActiveCfg = Release|x64
{6EABCF9A-6526-441F-932F-658B1DC3E403}.Release|x64.Build.0 = Release|x64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|ARM64.ActiveCfg = Debug|ARM64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|ARM64.Build.0 = Debug|ARM64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|x64.ActiveCfg = Debug|x64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Debug|x64.Build.0 = Debug|x64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|ARM64.ActiveCfg = Release|ARM64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|ARM64.Build.0 = Release|ARM64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|x64.ActiveCfg = Release|x64
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15}.Release|x64.Build.0 = Release|x64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|ARM64.ActiveCfg = Debug|ARM64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|ARM64.Build.0 = Debug|ARM64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|x64.ActiveCfg = Debug|x64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Debug|x64.Build.0 = Debug|x64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|ARM64.ActiveCfg = Release|ARM64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|ARM64.Build.0 = Release|ARM64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|x64.ActiveCfg = Release|x64
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83}.Release|x64.Build.0 = Release|x64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|ARM64.ActiveCfg = Debug|ARM64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|ARM64.Build.0 = Debug|ARM64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|x64.ActiveCfg = Debug|x64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Debug|x64.Build.0 = Debug|x64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|ARM64.ActiveCfg = Release|ARM64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|ARM64.Build.0 = Release|ARM64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|x64.ActiveCfg = Release|x64
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9}.Release|x64.Build.0 = Release|x64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|ARM64.Build.0 = Debug|ARM64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|x64.ActiveCfg = Debug|x64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Debug|x64.Build.0 = Debug|x64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|ARM64.ActiveCfg = Release|ARM64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|ARM64.Build.0 = Release|ARM64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|x64.ActiveCfg = Release|x64
{F93C2817-C846-4259-84D8-B39A6B57C8DE}.Release|x64.Build.0 = Release|x64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|ARM64.Build.0 = Debug|ARM64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.ActiveCfg = Debug|x64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Debug|x64.Build.0 = Debug|x64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.ActiveCfg = Release|ARM64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|ARM64.Build.0 = Release|ARM64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.ActiveCfg = Release|x64
{E816D7AC-4688-4ECB-97CC-3D8E798F3825}.Release|x64.Build.0 = Release|x64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|ARM64.Build.0 = Debug|ARM64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|x64.ActiveCfg = Debug|x64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Debug|x64.Build.0 = Debug|x64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|ARM64.ActiveCfg = Release|ARM64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|ARM64.Build.0 = Release|ARM64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|x64.ActiveCfg = Release|x64
{E816D7AD-4688-4ECB-97CC-3D8E798F3826}.Release|x64.Build.0 = Release|x64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|ARM64.Build.0 = Debug|ARM64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|x64.ActiveCfg = Debug|x64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Debug|x64.Build.0 = Debug|x64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|ARM64.ActiveCfg = Release|ARM64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|ARM64.Build.0 = Release|ARM64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|x64.ActiveCfg = Release|x64
{E816D7AE-4688-4ECB-97CC-3D8E798F3827}.Release|x64.Build.0 = Release|x64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|ARM64.Build.0 = Debug|ARM64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|x64.ActiveCfg = Debug|x64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Debug|x64.Build.0 = Debug|x64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|ARM64.ActiveCfg = Release|ARM64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|ARM64.Build.0 = Release|ARM64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|x64.ActiveCfg = Release|x64
{E816D7AF-4688-4ECB-97CC-3D8E798F3828}.Release|x64.Build.0 = Release|x64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|ARM64.ActiveCfg = Debug|ARM64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|ARM64.Build.0 = Debug|ARM64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|x64.ActiveCfg = Debug|x64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Debug|x64.Build.0 = Debug|x64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|ARM64.ActiveCfg = Release|ARM64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|ARM64.Build.0 = Release|ARM64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.ActiveCfg = Release|x64
{E816D7B0-4688-4ECB-97CC-3D8E798F3829}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2838,26 +2734,26 @@ Global
{3BB8493E-D18E-4485-A320-CB40F90F55AE} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{1A066C63-64B3-45F8-92FE-664E1CCE8077} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {66E1534A-1587-42B2-912F-45C994D32904}
{2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{89F34AF7-1C34-4A72-AA6E-534BCF972BD9} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{6C7F47CC-2151-44A3-A546-41C70025132C} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{0B43679E-EDFA-4DA0-AD30-F4628B308B1B} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8} = {0E556541-6A45-42CB-AE49-EE5A9BE05E7C}
{E0CC7526-D85E-43AC-844F-D5DF0D2F5AB8} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{17DA04DF-E393-4397-9CF0-84DABE11032E} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{38BDB927-829B-4C65-9CD9-93FB05D66D65} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{8AFFA899-0B73-49EC-8C50-0FADDA57B2FC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{FF742965-9A80-41A5-B042-D6C7D3A21708} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{FF742965-9A80-41A5-B042-D6C7D3A21708} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{4AFC9975-2456-4C70-94A4-84073C1CED93} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{59BD9891-3837-438A-958D-ADC7F91F6F7E} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{4D971245-7A70-41D5-BAA0-DDB5684CAF51} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
@@ -2870,29 +2766,31 @@ Global
{2F305555-C296-497E-AC20-5FA1B237996A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{AF2349B8-E5B6-4004-9502-687C1C7730B1} = {2F305555-C296-497E-AC20-5FA1B237996A}
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {2F305555-C296-497E-AC20-5FA1B237996A}
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A} = {2F305555-C296-497E-AC20-5FA1B237996A}
{DA425894-6E13-404F-8DCB-78584EC0557A} = {2F305555-C296-497E-AC20-5FA1B237996A}
{060D75DA-2D1C-48E6-A4A1-6F0718B64661} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{748417CA-F17E-487F-9411-CAFB6D3F4877} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{060D75DA-2D1C-48E6-A4A1-6F0718B64661} = {2F305555-C296-497E-AC20-5FA1B237996A}
{748417CA-F17E-487F-9411-CAFB6D3F4877} = {2F305555-C296-497E-AC20-5FA1B237996A}
{217DF501-135C-4E38-BFC8-99D4821032EA} = {2F305555-C296-497E-AC20-5FA1B237996A}
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{787B8AA6-CA93-4C84-96FE-DF31110AD1C4} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{08C8C05F-0362-41BC-818C-724572DF8B06} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{5D00D290-4016-4CFE-9E41-1E7C724509BA} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{4AED67B6-55FD-486F-B917-E543DEE2CB3C} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{42851751-CBC8-45A6-97F5-7A0753F7B4D1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{42851751-CBC8-45A6-97F5-7A0753F7B4D1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{1EF1EEF0-10F0-4F2E-8550-39B6D8044D3E} = {2F305555-C296-497E-AC20-5FA1B237996A}
{8FFE09DA-FA4F-4EE1-B3A2-AD5497FBD1AD} = {2F305555-C296-497E-AC20-5FA1B237996A}
{655C9AF2-18D3-4DA6-80E4-85504A7722BA} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{BA58206B-1493-4C75-BFEA-A85768A1E156} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{1D78B84B-CA39-406C-98F4-71F7EC266CC0} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{03276A39-D4E9-417C-8FFD-200B0EE5E871} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{B81FB7B6-D30E-428F-908A-41422EFC1172} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{0F85E674-34AE-443D-954C-8321EB8B93B1} = {E885E71F-0B34-4A03-B13B-20F4E05E90BB}
{632BBE62-5421-49EA-835A-7FFA4F499BD6} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{B81FB7B6-D30E-428F-908A-41422EFC1172} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{0F85E674-34AE-443D-954C-8321EB8B93B1} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{632BBE62-5421-49EA-835A-7FFA4F499BD6} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{4FA206A5-F69F-4193-BF8F-F6EEB496734C} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} = {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3}
{FD8EB419-FF9C-4D88-BB6F-BF6CED37747B} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{DA5A6FE9-0040-40CC-83CC-764AE5306590} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{DA5A6FE9-0040-40CC-83CC-764AE5306590} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{0351ADA4-0C32-4652-9BA0-41F7B602372B} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD} = {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3}
{6955446D-23F7-4023-9BB3-8657F904AF99} = {1AFB6476-670D-4E80-A464-657E01DFF482}
@@ -2911,20 +2809,20 @@ Global
{8F62026A-294B-41C6-8839-87463613F216} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{C3A17DCA-217B-462C-BB0C-BE086AF80081} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{69E1EE8D-143A-4060-9129-4658ACF14AAF} = {2F305555-C296-497E-AC20-5FA1B237996A}
{ECC20689-002A-4354-95A6-B58DF089C6FF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{ECC20689-002A-4354-95A6-B58DF089C6FF} = {2F305555-C296-497E-AC20-5FA1B237996A}
{4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{BA661F5B-1D5A-4FFC-9BF1-FC39DF280BDD} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{E496B7FC-1E99-4BAB-849B-0E8367040B02} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466} = {D9BD324E-1D80-44AA-8E7B-73EB00944434}
{7F4B3A60-BC27-45A7-8000-68B0B6EA7466} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{8DF78B53-200E-451F-9328-01EB907193AE} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{23D2070D-E4AD-4ADD-85A7-083D9C76AD49} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{62173D9A-6724-4C00-A1C8-FB646480A9EC} = {D9BD324E-1D80-44AA-8E7B-73EB00944434}
{62173D9A-6724-4C00-A1C8-FB646480A9EC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{127F38E0-40AA-4594-B955-5616BF206882} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882}
{D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882}
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
{2EDB3EB4-FA92-4BFF-B2D8-566584837231} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
@@ -2932,27 +2830,27 @@ Global
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{11491FD8-F921-48BF-880C-7FEA185B80A1} = {2F305555-C296-497E-AC20-5FA1B237996A}
{F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A}
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{809AA252-E17A-4FA2-B0A1-0450976B763F} = {2F305555-C296-497E-AC20-5FA1B237996A}
{133281D8-1BCE-4D07-B31E-796612A9609E} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{133281D8-1BCE-4D07-B31E-796612A9609E} = {2F305555-C296-497E-AC20-5FA1B237996A}
{805306FF-A562-4415-8DEF-E493BDC45918} = {2F305555-C296-497E-AC20-5FA1B237996A}
{FCF3E52D-B80A-4FC3-98FD-6391354F0EE3} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{FCF3E52D-B80A-4FC3-98FD-6391354F0EE3} = {2F305555-C296-497E-AC20-5FA1B237996A}
{60CD2D4F-C3B9-4897-9821-FCA5098B41CE} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{1DC3BE92-CE89-43FB-8110-9C043A2FE7A2} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE}
{48A0A19E-A0BE-4256-ACF8-CC3B80291AF9} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE}
{9F94B303-5E21-4364-9362-64426F8DB932} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{F7C8C0F1-5431-4347-89D0-8E5354F93CF2} = {2F305555-C296-497E-AC20-5FA1B237996A}
{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{F1F6B6B6-9F18-4A17-8B5C-97DF552C53DC} = {2F305555-C296-497E-AC20-5FA1B237996A}
{04B193D7-3E21-46B8-A958-89B63A8A69DE} = {2F305555-C296-497E-AC20-5FA1B237996A}
{5BDBD6C9-A31F-4CEB-871A-5E9E709197EF} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{FD464B4C-2F68-4D06-91E7-4208146C41F5} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{FD464B4C-2F68-4D06-91E7-4208146C41F5} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{8FE5A5EE-1B59-401C-9FB3-B04ECD3E29C1} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{020A7474-3601-4160-A159-D7B70B77B15F} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{27718999-C175-450A-861C-89F911E16A88} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{1DBBB112-4BB1-444B-8EBB-E66555C76BA6} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
@@ -2966,7 +2864,6 @@ Global
{A50C70A6-2DA0-4027-B90E-B1A40755A8A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{B1234567-1234-1234-1234-123456789ABC} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{212AD910-8488-4036-BE20-326931B75FB2} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{7AC943C9-52E8-44CF-9083-744D8049667B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B}
@@ -2975,7 +2872,7 @@ Global
{C97D9A5D-206C-454E-997E-009E227D7F02} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
{31D1C81D-765F-4446-AA62-E743F6325049} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7}
{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{B41B888C-7DB8-4747-B262-4062E05A230D} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{AB82E5DD-C32D-4F28-9746-2C780846188E} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
@@ -3004,7 +2901,7 @@ Global
{A663E672-B26D-4EC0-BEAB-FE2E424AC46F} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
{8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{923DF87C-CA99-4D1C-B1D2-959174E95BFA} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {2C318EC3-BA86-4372-B1BC-DB0F33C208B2}
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B}
@@ -3015,11 +2912,12 @@ Global
{9EBAA524-0EDA-470B-95D4-39383285CBB2} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{500DED3E-CFB5-4ED5-ACC6-02B3D6DC336D} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{D095BE44-1F2E-463E-A494-121892A75EA2} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{90F9FA90-2C20-4004-96E6-F3B78151F5A5} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
{90F9FA90-2C20-4004-96E6-F3B78151F5A5} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{3B227528-4BA6-4CAF-B44A-A10C78A64849} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{F5E1146E-B7B3-4E11-85FD-270A500BD78C} = {3B227528-4BA6-4CAF-B44A-A10C78A64849}
{3157FA75-86CF-4EE2-8F62-C43F776493C6} = {3B227528-4BA6-4CAF-B44A-A10C78A64849}
{4C0D0746-BE5B-49EE-BD5D-A7811628AE8B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{FC8EB78F-F061-4BD9-A3F6-507BEA965E2B} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{538ED0BB-B863-4B20-98CC-BCDF7FA0B68A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{51465DA1-C18B-4B99-93E1-ECF8E0FA0CBA} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}
{B9420661-B0E4-4241-ABD4-4A27A1F64250} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}
@@ -3027,8 +2925,8 @@ Global
{D949EC7D-48A9-4279-95D5-078E7FD1F048} = {2F305555-C296-497E-AC20-5FA1B237996A}
{3BAF9C81-A194-4925-A035-5E24A5D1E542} = {2F305555-C296-497E-AC20-5FA1B237996A}
{6B04803D-B418-4833-A67E-B0FC966636A5} = {2F305555-C296-497E-AC20-5FA1B237996A}
{3940AD4D-F748-4BE4-9083-85769CD553EF} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{3940AD4D-F748-4BE4-9083-85769CD553EF} = {2F305555-C296-497E-AC20-5FA1B237996A}
{F8FFFC12-A31A-4AFA-B3DF-14DCF42B5E38} = {2F305555-C296-497E-AC20-5FA1B237996A}
{0014D652-901F-4456-8D65-06FC5F997FB0} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}
{799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
@@ -3036,6 +2934,8 @@ Global
{02DD46D3-F761-47D9-8894-2D6DA0124650} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{8E23E173-7127-4A5F-9F93-3049F2B68047} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{DFF88D16-D36F-40A4-A955-CDCAA76EF7B8} = {538ED0BB-B863-4B20-98CC-BCDF7FA0B68A}
{FE38FC07-1C05-4B57-ADA3-2FE2F53C6A52} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{3A9A791E-94A9-49F8-8401-C11CE288D5FB} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{C0974915-8A1D-4BF0-977B-9587D3807AB7} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{1D6893CB-BC0C-46A8-A76C-9728706CA51A} = {557C4636-D7E1-4838-A504-7D19B725EE95}
{8ACB33D9-C95B-47D4-8363-9731EE0930A0} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}
@@ -3045,7 +2945,7 @@ Global
{BE126CBB-AE12-406A-9837-A05ACFCA57A7} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{14CB58B7-D280-4A7A-95DE-4B2DF14EA000} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C} = {68328142-5B31-4715-BCBB-7B6345EE0971}
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{9C53CC25-0623-4569-95BC-B05410675EE3} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{45285DF2-9742-4ECA-9AC9-58951FC26489} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{3D63307B-9D27-44FD-B033-B26F39245B85} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
@@ -3053,7 +2953,7 @@ Global
{2CAC093E-5FCF-4102-9C2C-AC7DD5D9EB96} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{37D07516-4185-43A4-924F-3C7A5D95ECF6} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{8F021B46-362B-485C-BFBA-CCF83E820CBD} = {8F62026A-294B-41C6-8839-87463613F216}
{66614C26-314C-4B91-9071-76133422CFEF} = {BFFB607F-7C78-434B-86B9-DA4C8196A1B5}
{66614C26-314C-4B91-9071-76133422CFEF} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
{3846508C-77EB-4034-A702-F8BB263C4F79} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{6CE438DF-C245-4997-A360-0A0939E4BA34} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
@@ -3083,6 +2983,8 @@ Global
{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{605E914B-7232-4789-AF46-BF5D3DDFC14E} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE} = {9873BA05-4C41-4819-9283-CF45D795431B}
{7F5B9557-5878-4438-A721-3E28296BA193} = {9873BA05-4C41-4819-9283-CF45D795431B}
{DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{0A84F764-3A88-44CD-AA96-41BDBD48627B} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}
{E4585179-2AC1-4D5F-A3FF-CFC5392F694C} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}
@@ -3091,54 +2993,24 @@ Global
{A558C25D-2007-498E-8B6F-43405AFAE9E2} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{08F9155D-B6DC-46E5-9C83-AF60B655898B} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{4382A954-179A-4078-92AF-715187DFFF50} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{EBED240C-8702-452D-B764-6DB9DA9179AF} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7}
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7}
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {8131151D-B0E9-4E18-84A5-E5F946C4480A}
{EBED240C-8702-452D-B764-6DB9DA9179AF} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{0217E86E-3476-9946-DE8E-9D200CEBD47A} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {66E1534A-1587-42B2-912F-45C994D32904}
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{9E0CBC06-F29A-4810-B93C-97D53863B95E} = {2F305555-C296-497E-AC20-5FA1B237996A}
{F6088A11-1C9E-4420-AA90-CF7E78DD7F1C} = {2F305555-C296-497E-AC20-5FA1B237996A}
{47B0678C-806B-4FE1-9F50-46BA88989532} = {2F305555-C296-497E-AC20-5FA1B237996A}
{9BC1C986-1E97-4D07-A7B1-CE226C239EFA} = {2F305555-C296-497E-AC20-5FA1B237996A}
{99CA1509-FB73-456E-AFAF-AB89C017BD72} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{61CBF221-9452-4934-B685-146285E080D7} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704}
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1} = {2C318EC3-BA86-4372-B1BC-DB0F33C208B2}
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9} = {68328142-5B31-4715-BCBB-7B6345EE0971}
{99CA1509-FB73-456E-AFAF-AB89C017BD72} = {2F305555-C296-497E-AC20-5FA1B237996A}
{61CBF221-9452-4934-B685-146285E080D7} = {2F305555-C296-497E-AC20-5FA1B237996A}
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A1} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{43E779F3-D83C-48B1-BA8D-1912DBD76FC9} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{14AFD976-B4D2-49D0-9E6C-AA93CC061B8A} = {1AFB6476-670D-4E80-A464-657E01DFF482}
{9D3F3793-EFE3-4525-8782-238015DABA62} = {66E1534A-1587-42B2-912F-45C994D32904}
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{24133F7F-C1D1-DE04-EFA8-F5D5467FE027} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{0E556541-6A45-42CB-AE49-EE5A9BE05E7C} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{27D9CB3A-46D1-402C-9273-F88CB8AC42F7} = {9873BA05-4C41-4819-9283-CF45D795431B}
{B9617A31-0F0A-4397-851D-BF2FBEE32D7F} = {C140A3EF-6DBF-4084-9D4C-4EB5A99FEE68}
{1C48CD47-D610-463A-A53C-AF82DD6C47E7} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{D9BD324E-1D80-44AA-8E7B-73EB00944434} = {38BDB927-829B-4C65-9CD9-93FB05D66D65}
{8EF25507-2575-4ADE-BF7E-D23376903AB8} = {3846508C-77EB-4034-A702-F8BB263C4F79}
{070AC093-C9F2-20AD-0BCD-F318FC2761EA} = {B1234567-1234-1234-1234-123456789ABC}
{E816D7AC-4688-4ECB-97CC-3D8E798F3825} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{E816D7AD-4688-4ECB-97CC-3D8E798F3826} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{E816D7AE-4688-4ECB-97CC-3D8E798F3827} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{E816D7AF-4688-4ECB-97CC-3D8E798F3828} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{E816D7B0-4688-4ECB-97CC-3D8E798F3829} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{2C318EC3-BA86-4372-B1BC-DB0F33C208B2} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{BFFB607F-7C78-434B-86B9-DA4C8196A1B5} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
{66E1534A-1587-42B2-912F-45C994D32904} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{E885E71F-0B34-4A03-B13B-20F4E05E90BB} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{264B412F-DB8B-4CF8-A74B-96998B183045} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
{3527BF37-DFC5-4309-A032-29278CA21328} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} = {2F305555-C296-497E-AC20-5FA1B237996A}
{68328142-5B31-4715-BCBB-7B6345EE0971} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{4122388B-59E4-CDB0-0338-EA6881DF86F0} = {27D9CB3A-46D1-402C-9273-F88CB8AC42F7}
{988C9FAF-5AEC-EB15-578D-FED0DF52BF55} = {27D9CB3A-46D1-402C-9273-F88CB8AC42F7}
{6748A29D-DA6A-033A-825B-752295FF6AA0} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
{6EABCF9A-6526-441F-932F-658B1DC3E403} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{69D76A76-6EF6-4846-94CD-EAAF0CAC9F15} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{9BAFFC28-E1EF-4C14-A101-EEBFC0A50D83} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{806BF185-8B89-5BE1-9AA1-DA5BC9487DB9} = {264B412F-DB8B-4CF8-A74B-96998B183045}
{F93C2817-C846-4259-84D8-B39A6B57C8DE} = {3527BF37-DFC5-4309-A032-29278CA21328}
{8131151D-B0E9-4E18-84A5-E5F946C4480A} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{9D3F3793-EFE3-4525-8782-238015DABA62} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

View File

@@ -68,7 +68,7 @@ The PowerToys UI test pipeline provides flexible options for building and testin
- Pipeline: https://microsoft.visualstudio.com/Dart/_build?definitionId=161438&_a=summary
## How to add the first UI tests for your modules
- Follow the naming convention: ![{ModuleFolder}/Tests/{ModuleName}-{TestType(Fuzz/UI/Unit)}Tests](images/uitests/naming.png)
- Create a new project and add the following references to the project file. Change the OutputPath to your own module's path.
```
<Project Sdk="Microsoft.NET.Sdk">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -67,7 +67,10 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an
- When you'd like the team to take a look (even if the work is not yet fully complete) mark the PR as 'Ready For Review' so that the team can review your work and provide comments, suggestions, and request changes. It may take several cycles, but the end result will be solid, testable, conformant code that is safe for us to merge.
- When the PR is approved, let the owner of the PR merge it. For community contributions, the reviewer who approved the PR can also merge it.
- Use the `Squash and merge` option to merge a PR. If you don't want to squash it because there are logically different commits, use `Rebase and merge`.
- Close issues automatically when referenced in a PR. You can use [closing keywords](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) in the body of the PR to have GitHub automatically link your PR to the issue.
- We don't close issues automatically when referenced in a PR, so after the PR is merged:
- mark the issue(s) that the PR solved with the `Resolution-Fix-Committed` label, remove the `In progress` label and if the issue is assigned to a project, move the item to the `Done` status.
- don't close the issue if it's a bug in the current released version; since users tend to not search for closed issues, we will close the resolved issues when a new version is released.
- if it's not a code fix that effects the end user, the issue can be closed (for example a fix in the build or a code refactoring and so on).
## Compiling PowerToys

View File

@@ -47,8 +47,6 @@ Contact the developers of a plugin directly for assistance with a specific plugi
| [Weather](https://github.com/ruslanlap/PowerToysRun-Weather) | [ruslanlap](https://github.com/ruslanlap) | Get real-time weather information directly from PowerToys Run. |
| [Pomodoro](https://github.com/ruslanlap/PowerToysRun-Pomodoro) | [ruslanlap](https://github.com/ruslanlap) | Manage Pomodoro productivity sessions directly from PowerToys Run. |
| [Definition](https://github.com/ruslanlap/PowerToysRun-Definition) | [ruslanlap](https://github.com/ruslanlap) | Lookup word definitions, phonetics, and synonyms directly in PowerToys Run. |
| [Hotkeys](https://github.com/ruslanlap/PowerToysRun-Hotkeys) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and trigger custom keyboard shortcuts directly from PowerToys Run. |
| [RandomGen](https://github.com/ruslanlap/PowerToysRun-RandomGen) | [ruslanlap](https://github.com/ruslanlap) | 🎲 Generate random data instantly with a single keystroke. Perfect for developers, testers, designers, and anyone who needs quick access to random data. Features include secure passwords, PINs, names, business data, dates, numbers, GUIDs, color codes, and more. Especially useful for designers who need random color codes and placeholder content. |
## Extending software plugins

View File

@@ -2,10 +2,10 @@
<configuration>
<packageSources>
<clear />
<add key="PowerToysPublicDependencies" value="https://pkgs.dev.azure.com/shine-oss/PowerToys/_packaging/PowerToysPublicDependencies/nuget/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="PowerToysPublicDependencies">
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
</packageSourceMapping>

View File

@@ -7,7 +7,6 @@
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
<!-- Suppress CA1416 for Windows-specific APIs that are used in PowerToys which only runs on Windows 10.0.19041.0+ -->
<WarningsNotAsErrors>IL2081;CsWinRT1028;CA1416;$(WarningsNotAsErrors)</WarningsNotAsErrors>
<WarningsNotAsErrors>IL2081;CsWinRT1028;$(WarningsNotAsErrors)</WarningsNotAsErrors>
</PropertyGroup>
</Project>

View File

@@ -24,16 +24,5 @@ namespace Microsoft.PowerToys.UITest
{
this.Find<NavigationViewItem>(value).Click();
}
/// <summary>
/// Select a text item from the ComboBox.
/// </summary>
/// <param name="value">The text to select from the ComboBox.</param>
public void SelectTxt(string value)
{
this.Click(); // First click to expand the ComboBox
Thread.Sleep(100); // Wait for the dropdown to appear
this.Find<Element>(value).Click(); // Find and click the text item using basic Element type
}
}
}

View File

@@ -364,7 +364,7 @@ namespace Microsoft.PowerToys.UITest
/// Save UI Element to a PNG file.
/// </summary>
/// <param name="path">the full path</param>
public void SaveToPngFile(string path)
internal void SaveToPngFile(string path)
{
Assert.IsNotNull(this.windowsElement, $"WindowsElement is null in method SaveToPngFile with parameter: path = {path}");
this.windowsElement.GetScreenshot().SaveAsFile(path);

View File

@@ -1,38 +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.
namespace Microsoft.PowerToys.UITest
{
/// <summary>
/// Represents a radio button UI element in the application.
/// </summary>
public class RadioButton : Element
{
private static readonly string ExpectedControlType = "ControlType.RadioButton";
/// <summary>
/// Initializes a new instance of the <see cref="RadioButton"/> class.
/// </summary>
public RadioButton()
{
this.TargetControlType = RadioButton.ExpectedControlType;
}
/// <summary>
/// Gets a value indicating whether the RadioButton is selected.
/// </summary>
public bool IsSelected => this.Selected;
/// <summary>
/// Select the RadioButton.
/// </summary>
public void Select()
{
if (!this.IsSelected)
{
this.Click();
}
}
}
}

View File

@@ -32,7 +32,6 @@ namespace Microsoft.PowerToys.UITest
Runner,
Workspaces,
PowerRename,
CommandPalette,
}
/// <summary>
@@ -105,7 +104,6 @@ namespace Microsoft.PowerToys.UITest
[PowerToysModule.Runner] = new ModuleInfo("PowerToys.exe", "PowerToys"),
[PowerToysModule.Workspaces] = new ModuleInfo("PowerToys.WorkspacesEditor.exe", "Workspaces Editor"),
[PowerToysModule.PowerRename] = new ModuleInfo("PowerToys.PowerRename.exe", "PowerRename", "WinUI3Apps"),
[PowerToysModule.CommandPalette] = new ModuleInfo("Microsoft.CmdPal.UI.exe", "PowerToys Command Palette", "WinUI3Apps\\CmdPal"),
};
}

View File

@@ -91,12 +91,15 @@ namespace Microsoft.PowerToys.UITest
}
/// <summary>
/// Exit a exe by Name.
/// Exit a exe.
/// </summary>
/// <param name="processName">The path to the application executable.</param>
public void ExitExeByName(string processName)
/// <param name="appPath">The path to the application executable.</param>
public void ExitExe(string appPath)
{
Process[] processes = Process.GetProcessesByName(processName);
// Exit Exe
string exeName = Path.GetFileNameWithoutExtension(appPath);
Process[] processes = Process.GetProcessesByName(exeName);
foreach (Process process in processes)
{
try
@@ -111,18 +114,6 @@ namespace Microsoft.PowerToys.UITest
}
}
/// <summary>
/// Exit a exe.
/// </summary>
/// <param name="appPath">The path to the application executable.</param>
public void ExitExe(string appPath)
{
// Exit Exe
string exeName = Path.GetFileNameWithoutExtension(appPath);
ExitExeByName(exeName);
}
/// <summary>
/// Starts a new exe and takes control of it.
/// </summary>
@@ -131,34 +122,26 @@ namespace Microsoft.PowerToys.UITest
public void StartExe(string appPath, string[]? args = null)
{
var opts = new AppiumOptions();
opts.AddAdditionalCapability("app", appPath);
if (scope == PowerToysModule.PowerToysSettings)
if (args != null && args.Length > 0)
{
TryLaunchPowerToysSettings(opts);
}
else
{
opts.AddAdditionalCapability("app", appPath);
if (args != null && args.Length > 0)
// Build command line arguments string
string argsString = string.Join(" ", args.Select(arg =>
{
// Build command line arguments string
string argsString = string.Join(" ", args.Select(arg =>
// Quote arguments that contain spaces
if (arg.Contains(' '))
{
// Quote arguments that contain spaces
if (arg.Contains(' '))
{
return $"\"{arg}\"";
}
return $"\"{arg}\"";
}
return arg;
}));
return arg;
}));
opts.AddAdditionalCapability("appArguments", argsString);
}
opts.AddAdditionalCapability("appArguments", argsString);
}
Driver = NewWindowsDriver(opts);
this.Driver = NewWindowsDriver(opts);
}
private void TryLaunchPowerToysSettings(AppiumOptions opts)
@@ -167,18 +150,15 @@ namespace Microsoft.PowerToys.UITest
var runnerProcessInfo = new ProcessStartInfo
{
FileName = locationPath + runnerPath,
FileName = locationPath + this.runnerPath,
Verb = "runas",
Arguments = "--open-settings",
};
ExitExe(runnerProcessInfo.FileName);
runner = Process.Start(runnerProcessInfo);
this.ExitExe(runnerProcessInfo.FileName);
this.runner = Process.Start(runnerProcessInfo);
Thread.Sleep(5000);
// Exit CmdPal UI before launching new process if use installer for test
ExitExeByName("Microsoft.CmdPal.UI");
if (root != null)
{
const int maxRetries = 5;
@@ -188,7 +168,7 @@ namespace Microsoft.PowerToys.UITest
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
var settingsWindow = ApiHelper.FindDesktopWindowHandler(
[windowName, AdministratorPrefix + windowName]);
new[] { windowName, AdministratorPrefix + windowName });
if (settingsWindow.Count > 0)
{

View File

@@ -20,7 +20,6 @@
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.RegularExpressions" />
<PackageReference Include="CoenM.ImageSharp.ImageHash" />
</ItemGroup>
</Project>

View File

@@ -22,8 +22,6 @@ namespace Microsoft.PowerToys.UITest
public bool IsInPipeline { get; }
public string? ScreenshotDirectory { get; set; }
public static MonitorInfoData.ParamsWrapper MonitorInfoData { get; set; } = new MonitorInfoData.ParamsWrapper() { Monitors = new List<MonitorInfoData.MonitorInfoDataWrapper>() };
private readonly PowerToysModule scope;
@@ -31,6 +29,7 @@ namespace Microsoft.PowerToys.UITest
private readonly string[]? commandLineArgs;
private SessionHelper? sessionHelper;
private System.Threading.Timer? screenshotTimer;
private string? screenshotDirectory;
public UITestBase(PowerToysModule scope = PowerToysModule.PowerToysSettings, WindowSize size = WindowSize.UnSpecified, string[]? commandLineArgs = null)
{
@@ -59,11 +58,11 @@ namespace Microsoft.PowerToys.UITest
CloseOtherApplications();
if (IsInPipeline)
{
ScreenshotDirectory = Path.Combine(this.TestContext.TestResultsDirectory ?? string.Empty, "UITestScreenshots_" + Guid.NewGuid().ToString());
Directory.CreateDirectory(ScreenshotDirectory);
screenshotDirectory = Path.Combine(this.TestContext.TestResultsDirectory ?? string.Empty, "UITestScreenshots_" + Guid.NewGuid().ToString());
Directory.CreateDirectory(screenshotDirectory);
// Take screenshot every 1 second
screenshotTimer = new System.Threading.Timer(ScreenCapture.TimerCallback, ScreenshotDirectory, TimeSpan.Zero, TimeSpan.FromMilliseconds(1000));
screenshotTimer = new System.Threading.Timer(ScreenCapture.TimerCallback, screenshotDirectory, TimeSpan.Zero, TimeSpan.FromMilliseconds(1000));
// Escape Popups before starting
System.Windows.Forms.SendKeys.SendWait("{ESC}");
@@ -416,9 +415,9 @@ namespace Microsoft.PowerToys.UITest
protected void AddScreenShotsToTestResultsDirectory()
{
if (ScreenshotDirectory != null)
if (screenshotDirectory != null)
{
foreach (string file in Directory.GetFiles(ScreenshotDirectory))
foreach (string file in Directory.GetFiles(screenshotDirectory))
{
this.TestContext.AddResultFile(file);
}
@@ -628,23 +627,6 @@ namespace Microsoft.PowerToys.UITest
Console.WriteLine($"Failed to change display resolution. Error code: {result}");
}
}
// Windows API for moving windows
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
private const uint SWPNOSIZE = 0x0001;
private const uint SWPNOZORDER = 0x0004;
public static void MoveWindow(Element window, int x, int y)
{
var windowHandle = IntPtr.Parse(window.GetAttribute("NativeWindowHandle") ?? "0", System.Globalization.CultureInfo.InvariantCulture);
if (windowHandle != IntPtr.Zero)
{
SetWindowPos(windowHandle, IntPtr.Zero, x, y, 0, 0, SWPNOSIZE | SWPNOZORDER);
Task.Delay(500).Wait();
}
}
}
}
}

View File

@@ -6,11 +6,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.IO;
using CoenM.ImageHash;
using CoenM.ImageHash.HashAlgorithms;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace Microsoft.PowerToys.UITest
{
@@ -131,75 +127,34 @@ namespace Microsoft.PowerToys.UITest
}
/// <summary>
/// Test if two images are equal using ImageHash comparison
/// Test if two images are equal bit-by-bit
/// </summary>
/// <param name="baselineImage">baseline image</param>
/// <param name="testImage">test image</param>
/// <returns>true if are equal,otherwise false</returns>
private static bool AreEqual(Bitmap baselineImage, Bitmap testImage)
{
try
if (baselineImage.Width != testImage.Width || baselineImage.Height != testImage.Height)
{
// Define a threshold for similarity percentage
const int SimilarityThreshold = 95;
// Use CoenM.ImageHash for perceptual hash comparison
var hashAlgorithm = new AverageHash();
// Convert System.Drawing.Bitmap to SixLabors.ImageSharp.Image
using var baselineImageSharp = ConvertBitmapToImageSharp(baselineImage);
using var testImageSharp = ConvertBitmapToImageSharp(testImage);
// Calculate hashes for both images
var baselineHash = hashAlgorithm.Hash(baselineImageSharp);
var testHash = hashAlgorithm.Hash(testImageSharp);
// Compare hashes using CompareHash method
// Returns similarity percentage (0-100, where 100 is identical)
var similarity = CompareHash.Similarity(baselineHash, testHash);
// Consider images equal if similarity is very high
// Allow for minor rendering differences (threshold can be adjusted)
return similarity >= SimilarityThreshold; // 95% similarity threshold
return false;
}
catch
// WinAppDriver sometimes adds a border to the screenshot (around 2 pix width), and it is not always consistent.
// So we exclude the border when comparing the images, and usually it is the edge of the windows, won't affect the comparison.
int excludeBorderWidth = 5, excludeBorderHeight = 5;
for (int x = excludeBorderWidth; x < baselineImage.Width - excludeBorderWidth; x++)
{
// Fallback to pixel-by-pixel comparison if hash comparison fails
if (baselineImage.Width != testImage.Width || baselineImage.Height != testImage.Height)
for (int y = excludeBorderHeight; y < baselineImage.Height - excludeBorderHeight; y++)
{
return false;
}
// WinAppDriver sometimes adds a border to the screenshot (around 2 pix width), and it is not always consistent.
// So we exclude the border when comparing the images, and usually it is the edge of the windows, won't affect the comparison.
int excludeBorderWidth = 5, excludeBorderHeight = 5;
for (int x = excludeBorderWidth; x < baselineImage.Width - excludeBorderWidth; x++)
{
for (int y = excludeBorderHeight; y < baselineImage.Height - excludeBorderHeight; y++)
if (!VisualHelper.PixIsSame(baselineImage.GetPixel(x, y), testImage.GetPixel(x, y)))
{
if (!VisualHelper.PixIsSame(baselineImage.GetPixel(x, y), testImage.GetPixel(x, y)))
{
return false;
}
return false;
}
}
return true;
}
}
/// <summary>
/// Convert System.Drawing.Bitmap to SixLabors.ImageSharp.Image
/// </summary>
/// <param name="bitmap">The bitmap to convert</param>
/// <returns>ImageSharp Image</returns>
private static Image<Rgba32> ConvertBitmapToImageSharp(Bitmap bitmap)
{
using var memoryStream = new MemoryStream();
bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
memoryStream.Position = 0;
return SixLabors.ImageSharp.Image.Load<Rgba32>(memoryStream);
return true;
}
}
}

View File

@@ -7,7 +7,6 @@
<Keyword>Win32Proj</Keyword>
<RootNamespace>UnitTestsCommonLib</RootNamespace>
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
<ProjectName>Common.Lib.UnitTests</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">

View File

@@ -1,38 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Look at Directory.Build.props in root for common stuff as well -->
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<ProjectGuid>{2B1505FA-132A-460B-B22B-7CC3FFAB0C5D}</ProjectGuid>
<RootNamespace>Microsoft.AdvancedPaste.UITests</RootNamespace>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<!-- This is a UI test, so don't run as part of MSBuild -->
<RunVSTest>false</RunVSTest>
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\UITests-AdvancedPaste\</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Appium.WebDriver" />
<PackageReference Include="MSTest" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.RegularExpressions" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="TestFiles\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -1,791 +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.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using Microsoft.AdvancedPaste.UITests.Helper;
using Microsoft.CodeCoverage.Core.Reports.Coverage;
using Microsoft.PowerToys.UITest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using Windows.ApplicationModel.DataTransfer;
using static System.Net.Mime.MediaTypeNames;
using static System.Resources.ResXFileRef;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
namespace Microsoft.AdvancedPaste.UITests
{
[TestClass]
public class AdvancedPasteUITest : UITestBase
{
private readonly string testFilesFolderPath;
private readonly string tempRTFFileName = "TempFile.rtf";
private readonly string pasteAsPlainTextRawFileName = "PasteAsPlainTextFileRaw.rtf";
private readonly string pasteAsPlainTextPlainFileName = "PasteAsPlainTextFilePlain.rtf";
private readonly string pasteAsPlainTextPlainNoRepeatFileName = "PasteAsPlainTextFilePlainNoRepeat.rtf";
private readonly string wordpadPath = @"C:\Program Files\wordpad\wordpad.exe";
private readonly string tempTxtFileName = "TempFile.txt";
private readonly string pasteAsMarkdownSrcFile = "PasteAsMarkdownFile.html";
private readonly string pasteAsMarkdownResultFile = "PasteAsMarkdownResultFile.txt";
private readonly string pasteAsJsonFileName = "PasteAsJsonFile.xml";
private readonly string pasteAsJsonResultFile = "PasteAsJsonResultFile.txt";
private bool _notepadSettingsChanged;
// Static constructor - runs before any instance is created
static AdvancedPasteUITest()
{
// Using the predefined settings.
// paste as plain text: win + ctrl + alt + o
// paste as markdown text: win + ctrl + alt + m
// paste as json text: win + ctrl + alt + j
CopySettingsFileBeforeTests();
}
public AdvancedPasteUITest()
: base(PowerToysModule.PowerToysSettings, size: WindowSize.Small)
{
Type currentTestType = typeof(AdvancedPasteUITest);
string? dirName = Path.GetDirectoryName(currentTestType.Assembly.Location);
Assert.IsNotNull(dirName, "Failed to get directory name of the current test assembly.");
string testFilesFolder = Path.Combine(dirName, "TestFiles");
Assert.IsTrue(Directory.Exists(testFilesFolder), $"Test files directory not found at: {testFilesFolder}");
testFilesFolderPath = testFilesFolder;
// ignore the notepad settings in pipeline
_notepadSettingsChanged = true;
}
[TestInitialize]
public void TestInitialize()
{
Session.CloseMainWindow();
SendKeys(Key.Win, Key.M);
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsPlainText")]
[Ignore("Temporarily disabled due to wordpad.exe is missing in pipeline.")]
public void TestCasePasteAsPlainText()
{
// Copy some rich text(e.g word of the text is different color, another work is bold, underlined, etd.).
// Paste the text using standard Windows Ctrl + V shortcut and ensure that rich text is pasted(with all colors, formatting, etc.)
DeleteAndCopyFile(pasteAsPlainTextRawFileName, tempRTFFileName);
ContentCopyAndPasteDirectly(tempRTFFileName, isRTF: true);
var resultWithFormatting = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempRTFFileName),
Path.Combine(testFilesFolderPath, pasteAsPlainTextRawFileName),
compareFormatting: true);
Assert.IsTrue(resultWithFormatting.IsConsistent, "RTF files should be identical including formatting");
// Paste the text using Paste As Plain Text activation shortcut and ensure that plain text without any formatting is pasted.
// Paste again the text using standard Windows Ctrl + V shortcut and ensure the text is now pasted plain without formatting as well.
DeleteAndCopyFile(pasteAsPlainTextRawFileName, tempRTFFileName);
ContentCopyAndPasteWithShortcutThenPasteAgain(tempRTFFileName, isRTF: true);
resultWithFormatting = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempRTFFileName),
Path.Combine(testFilesFolderPath, pasteAsPlainTextPlainFileName),
compareFormatting: true);
Assert.IsTrue(resultWithFormatting.IsConsistent, "RTF files should be identical without formatting");
// Copy some rich text again.
// Open Advanced Paste window using hotkey, click Paste as Plain Text button and confirm that plain text without any formatting is pasted.
DeleteAndCopyFile(pasteAsPlainTextRawFileName, tempRTFFileName);
ContentCopyAndPasteCase3(tempRTFFileName, isRTF: true);
resultWithFormatting = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempRTFFileName),
Path.Combine(testFilesFolderPath, pasteAsPlainTextPlainNoRepeatFileName),
compareFormatting: true);
Assert.IsTrue(resultWithFormatting.IsConsistent, "RTF files should be identical without formatting");
// Copy some rich text again.
// Open Advanced Paste window using hotkey, press Ctrl + 1 and confirm that plain text without any formatting is pasted.
DeleteAndCopyFile(pasteAsPlainTextRawFileName, tempRTFFileName);
ContentCopyAndPasteCase4(tempRTFFileName, isRTF: true);
resultWithFormatting = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempRTFFileName),
Path.Combine(testFilesFolderPath, pasteAsPlainTextPlainNoRepeatFileName),
compareFormatting: true);
Assert.IsTrue(resultWithFormatting.IsConsistent, "RTF files should be identical without formatting");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsMarkdownCase1")]
public void TestCasePasteAsMarkdownCase1()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some text(e.g.some HTML text - convertible to Markdown)
// Paste the text using set hotkey and confirm that pasted text is converted to markdown
DeleteAndCopyFile(pasteAsMarkdownSrcFile, tempTxtFileName);
ContentCopyAndPasteAsMarkdownCase1(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsMarkdownResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as markdown using shortcut failed.");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsMarkdownCase2")]
public void TestCasePasteAsMarkdownCase2()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some text(same as in the previous step or different.If nothing is coppied between steps, previously pasted Markdown text will be picked up from clipboard and converted again to nested Markdown).
// Open Advanced Paste window using hotkey, click Paste as markdown button and confirm that pasted text is converted to markdown
DeleteAndCopyFile(pasteAsMarkdownSrcFile, tempTxtFileName);
ContentCopyAndPasteAsMarkdownCase2(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsMarkdownResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as markdown using shortcut failed.");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsMarkdownCase3")]
public void TestCasePasteAsMarkdownCase3()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some text(same as in the previous step or different.If nothing is coppied between steps, previously pasted Markdown text will be picked up from clipboard and converted again to nested Markdown).
// Open Advanced Paste window using hotkey, press Ctrl + 2 and confirm that pasted text is converted to markdown
DeleteAndCopyFile(pasteAsMarkdownSrcFile, tempTxtFileName);
ContentCopyAndPasteAsMarkdownCase3(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsMarkdownResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as markdown using shortcut failed.");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsJSONCase1")]
public void TestCasePasteAsJSONCase1()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some XML or CSV text(or any other text, it will be converted to simple JSON object)
// Paste the text using set hotkey and confirm that pasted text is converted to JSON
DeleteAndCopyFile(pasteAsJsonFileName, tempTxtFileName);
ContentCopyAndPasteAsJsonCase1(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsJsonResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as Json using shortcut failed.");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsJSONCase2")]
public void TestCasePasteAsJSONCase2()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some text(same as in the previous step or different.If nothing is coppied between steps, previously pasted JSON text will be picked up from clipboard and converted again to nested JSON).
// Open Advanced Paste window using hotkey, click Paste as markdown button and confirm that pasted text is converted to markdown
DeleteAndCopyFile(pasteAsJsonFileName, tempTxtFileName);
ContentCopyAndPasteAsJsonCase2(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsJsonResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as Json using shortcut failed.");
}
[TestMethod]
[TestCategory("AdvancedPasteUITest")]
[TestCategory("PasteAsJSONCase3")]
public void TestCasePasteAsJSONCase3()
{
if (_notepadSettingsChanged == false)
{
ChangeNotePadSettings();
}
// Copy some text(same as in the previous step or different.If nothing is coppied between steps, previously pasted JSON text will be picked up from clipboard and converted again to nested JSON).
// Open Advanced Paste window using hotkey, press Ctrl + 3 and confirm that pasted text is converted to markdown
DeleteAndCopyFile(pasteAsJsonFileName, tempTxtFileName);
ContentCopyAndPasteAsJsonCase3(tempTxtFileName);
var result = FileReader.CompareRtfFiles(
Path.Combine(testFilesFolderPath, tempTxtFileName),
Path.Combine(testFilesFolderPath, pasteAsJsonResultFile),
compareFormatting: true);
Assert.IsTrue(result.IsConsistent, "Paste as Json using shortcut failed.");
}
/*
* Clipboard History
- [] Open Settings and Enable clipboard history (if not enabled already). Open Advanced Paste window with hotkey, click Clipboard history and try deleting some entry. Check OS clipboard history (Win+V), and confirm that the same entry no longer exist.
- [] Open Advanced Paste window with hotkey, click Clipboard history, and click any entry (but first). Observe that entry is put on top of clipboard history. Check OS clipboard history (Win+V), and confirm that the same entry is on top of the clipboard.
- [] Open Settings and Disable clipboard history. Open Advanced Paste window with hotkey and observe that Clipboard history button is disabled.
* Disable Advanced Paste, try different Advanced Paste hotkeys and confirm that it's disabled and nothing happens.
*/
private void TestCaseClipboardHistory()
{
}
private void ContentCopyAndPasteDirectly(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.V);
Thread.Sleep(1000);
this.SendKeys(Key.Backspace);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
process.Kill(true);
}
private void ContentCopyAndPasteWithShortcutThenPasteAgain(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
this.SendKeys(Key.Win, Key.LCtrl, Key.Alt, Key.O);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.V);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
process.Kill(true);
}
private void ContentCopyAndPasteCase3(string fileName, bool isRTF = false)
{
// Copy some rich text again.
// Open Advanced Paste window using hotkey, click Paste as Plain Text button and confirm that plain text without any formatting is pasted.
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(15000);
// Click Paste as Plain Text button and confirm that plain text without any formatting is pasted.
var apWind = this.Find<Window>("Advanced Paste", global: true);
apWind.Find<TextBlock>("Paste as plain text").Click();
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
process.Kill(true);
}
private void ContentCopyAndPasteCase4(string fileName, bool isRTF = false)
{
// Copy some rich text again.
// Open Advanced Paste window using hotkey, press Ctrl + 1 and confirm that plain text without any formatting is pasted.
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(1000);
// press Ctrl + 1 and confirm that plain text without any formatting is pasted.
this.SendKeys(Key.LCtrl, Key.Num1);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
process.Kill(true);
}
private void ContentCopyAndPasteAsMarkdownCase1(string fileName, bool isRTF = false)
{
// Copy some rich text again.
// Open Advanced Paste window using hotkey, press Ctrl + 1 and confirm that plain text without any formatting is pasted.
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
this.SendKeys(Key.Win, Key.LCtrl, Key.Alt, Key.M);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private void ContentCopyAndPasteAsMarkdownCase2(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(15000);
// click Paste as markdown button and confirm that pasted text is converted to markdown
var apWind = this.Find<Window>("Advanced Paste", global: true);
apWind.Find<TextBlock>("Paste as markdown").Click();
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private void ContentCopyAndPasteAsMarkdownCase3(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(15000);
this.SendKeys(Key.LCtrl, Key.Num2);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private void ContentCopyAndPasteAsJsonCase1(string fileName, bool isRTF = false)
{
// Copy some rich text again.
// Open Advanced Paste window using hotkey, press Ctrl + 1 and confirm that plain text without any formatting is pasted.
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
this.SendKeys(Key.Win, Key.LCtrl, Key.Alt, Key.J);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private void ContentCopyAndPasteAsJsonCase2(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(15000);
// click Paste as markdown button and confirm that pasted text is converted to markdown
var apWind = this.Find<Window>("Advanced Paste", global: true);
apWind.Find<TextBlock>("Paste as JSON").Click();
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private void ContentCopyAndPasteAsJsonCase3(string fileName, bool isRTF = false)
{
string tempFile = Path.Combine(testFilesFolderPath, fileName);
Process process = Process.Start(isRTF ? wordpadPath : "notepad.exe", tempFile);
if (process == null)
{
throw new InvalidOperationException($"Failed to start {(isRTF ? "WordPad" : "Notepad")}.");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle(Path.GetFileName(tempFile), isRTF);
window.Click();
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.A);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.C);
Thread.Sleep(1000);
this.SendKeys(Key.Delete);
Thread.Sleep(1000);
// Open Advanced Paste window using hotkey
this.SendKeys(Key.Win, Key.Shift, Key.V);
Thread.Sleep(15000);
this.SendKeys(Key.LCtrl, Key.Num3);
Thread.Sleep(1000);
this.SendKeys(Key.LCtrl, Key.S);
Thread.Sleep(1000);
window.Close();
}
private string DeleteAndCopyFile(string sourceFileName, string destinationFileName)
{
string sourcePath = Path.Combine(testFilesFolderPath, sourceFileName);
string destinationPath = Path.Combine(testFilesFolderPath, destinationFileName);
// Check if source file exists
if (!File.Exists(sourcePath))
{
throw new FileNotFoundException($"Source file not found: {sourcePath}");
}
// Delete destination file if it exists
if (File.Exists(destinationPath))
{
try
{
File.Delete(destinationPath);
}
catch (IOException ex)
{
throw new IOException($"Failed to delete file {destinationPath}. The file may be in use: {ex.Message}", ex);
}
}
// Copy the source file to the destination
try
{
File.Copy(sourcePath, destinationPath);
}
catch (IOException ex)
{
throw new IOException($"Failed to copy file from {sourcePath} to {destinationPath}: {ex.Message}", ex);
}
return destinationPath;
}
private void ChangeNotePadSettings()
{
Process process = Process.Start("notepad.exe");
if (process == null)
{
throw new InvalidOperationException($"Failed to start Notepad.exe");
}
Thread.Sleep(15000);
var window = FindWindowWithFlexibleTitle("Untitled", false);
window.Find<PowerToys.UITest.Button>("Settings").Click();
var combobox = window.Find<PowerToys.UITest.ComboBox>("Opening files");
combobox.SelectTxt("Open in a new window");
window.Find<Group>("When Notepad starts").Click();
window.Find<PowerToys.UITest.RadioButton>("Open a new window").Select();
_notepadSettingsChanged = true;
window.Close();
}
/// <summary>
/// Finds a window with flexible title matching, trying multiple title variations
/// </summary>
/// <param name="baseTitle">The base title to search for</param>
/// <param name="isRTF">Whether the window is a WordPad window</param>
/// <returns>The found Window element or throws an exception if not found</returns>
private Window FindWindowWithFlexibleTitle(string baseTitle, bool isRTF)
{
Window? window = null;
string appType = isRTF ? "WordPad" : "Notepad";
// Try different title variations
string[] titleVariations = new string[]
{
baseTitle + (isRTF ? " - WordPad" : " - Notepad"), // With suffix
baseTitle, // Without suffix
Path.GetFileNameWithoutExtension(baseTitle) + (isRTF ? " - WordPad" : " - Notepad"), // Without extension, with suffix
Path.GetFileNameWithoutExtension(baseTitle), // Without extension, without suffix
};
Exception? lastException = null;
foreach (string title in titleVariations)
{
try
{
window = this.Find<Window>(title, global: true);
if (window != null)
{
return window;
}
}
catch (Exception ex)
{
// Save the exception, but continue trying other variations
lastException = ex;
}
}
// If we couldn't find the window with any variation, throw an exception with details
throw new InvalidOperationException(
$"Failed to find {appType} window with title containing '{baseTitle}'. ");
}
private static void CopySettingsFileBeforeTests()
{
try
{
// Determine the assembly location and test files path
string? assemblyLocation = Path.GetDirectoryName(typeof(AdvancedPasteUITest).Assembly.Location);
if (assemblyLocation == null)
{
Debug.WriteLine("ERROR: Failed to get assembly location");
return;
}
string testFilesFolder = Path.Combine(assemblyLocation, "TestFiles");
if (!Directory.Exists(testFilesFolder))
{
Debug.WriteLine($"ERROR: Test files directory not found at: {testFilesFolder}");
return;
}
// Settings file source path
string settingsFileName = "settings.json";
string sourceSettingsPath = Path.Combine(testFilesFolder, settingsFileName);
// Make sure the source file exists
if (!File.Exists(sourceSettingsPath))
{
Debug.WriteLine($"ERROR: Settings file not found at: {sourceSettingsPath}");
return;
}
// Determine the target directory in %LOCALAPPDATA%
string targetDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Microsoft",
"PowerToys",
"AdvancedPaste");
// Create the directory if it doesn't exist
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
}
string targetSettingsPath = Path.Combine(targetDirectory, settingsFileName);
// Copy the file and overwrite if it exists
File.Copy(sourceSettingsPath, targetSettingsPath, true);
Debug.WriteLine($"Successfully copied settings file from {sourceSettingsPath} to {targetSettingsPath}");
}
catch (Exception ex)
{
Debug.WriteLine($"ERROR copying settings file: {ex.Message}");
}
}
}
}

View File

@@ -1,85 +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.IO;
using System.Text;
using System.Windows.Forms;
namespace Microsoft.AdvancedPaste.UITests.Helper;
public class FileReader
{
public static string ReadContent(string filePath)
{
try
{
return File.ReadAllText(filePath);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to read file: {ex.Message}", ex);
}
}
public static string ReadRTFPlainText(string filePath)
{
try
{
using (var rtb = new System.Windows.Forms.RichTextBox())
{
rtb.Rtf = File.ReadAllText(filePath);
return rtb.Text;
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to read plain text from file: {ex.Message}", ex);
}
}
/// <summary>
/// Compares the contents of two RTF files to check if they are consistent.
/// </summary>
/// <param name="firstFilePath">Path to the first RTF file</param>
/// <param name="secondFilePath">Path to the second RTF file</param>
/// <param name="compareFormatting">If true, compares the raw RTF content (including formatting).
/// If false, compares only the plain text content.</param>
/// <returns>
/// A tuple containing: (bool isConsistent, string firstContent, string secondContent)
/// - isConsistent: true if the files are consistent according to the comparison method
/// - firstContent: the content of the first file
/// - secondContent: the content of the second file
/// </returns>
public static (bool IsConsistent, string FirstContent, string SecondContent) CompareRtfFiles(
string firstFilePath,
string secondFilePath,
bool compareFormatting = false)
{
try
{
string firstContent, secondContent;
if (compareFormatting)
{
// Compare raw RTF content (including formatting)
firstContent = ReadContent(firstFilePath);
secondContent = ReadContent(secondFilePath);
}
else
{
// Compare only the plain text content
firstContent = ReadRTFPlainText(firstFilePath);
secondContent = ReadRTFPlainText(secondFilePath);
}
bool isConsistent = string.Equals(firstContent, secondContent, StringComparison.Ordinal);
return (isConsistent, firstContent, secondContent);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to compare RTF files: {ex.Message}", ex);
}
}
}

View File

@@ -1,6 +0,0 @@
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

View File

@@ -1,8 +0,0 @@
{
"note": {
"to": "Tove",
"from": "Jani",
"heading": "Reminder",
"body": "Don't forget me this weekend!"
}
}

View File

@@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<h2 title="I'm a header">The title Attribute</h2>
<p title="I'm a tooltip">Mouse over this paragraph, to display the title attribute as a tooltip.</p>
</body>
</html>

View File

@@ -1,3 +0,0 @@
## The title Attribute
Mouse over this paragraph, to display the title attribute as a tooltip.

View File

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

View File

@@ -1,41 +0,0 @@
## [Advanced Paste](tests-checklist-template-advanced-paste-section.md)
NOTES:
When using Advanced Paste, make sure that window focused while starting/using Advanced paste is text editor or has text input field focused (e.g. Word).
* Paste As Plain Text
- [x] Copy some rich text (e.g word of the text is different color, another work is bold, underlined, etd.).
- [x] Paste the text using standard Windows Ctrl + V shortcut and ensure that rich text is pasted (with all colors, formatting, etc.)
- [x] Paste the text using Paste As Plain Text activation shortcut and ensure that plain text without any formatting is pasted.
- [x] Paste again the text using standard Windows Ctrl + V shortcut and ensure the text is now pasted plain without formatting as well.
- [x] Copy some rich text again.
- [x] Open Advanced Paste window using hotkey, click Paste as Plain Text button and confirm that plain text without any formatting is pasted.
- [x] Copy some rich text again.
- [x] Open Advanced Paste window using hotkey, press Ctrl + 1 and confirm that plain text without any formatting is pasted.
* Paste As Markdown
- [] Open Settings and set Paste as Markdown directly hotkey
- [x] Copy some text (e.g. some HTML text - convertible to Markdown)
- [x] Paste the text using set hotkey and confirm that pasted text is converted to markdown
- [x] Copy some text (same as in the previous step or different. If nothing is coppied between steps, previously pasted Markdown text will be picked up from clipboard and converted again to nested Markdown).
- [x] Open Advanced Paste window using hotkey, click Paste as markdown button and confirm that pasted text is converted to markdown
- [x] Copy some text (same as in the previous step or different. If nothing is coppied between steps, previously pasted Markdown text will be picked up from clipboard and converted again to nested Markdown).
- [x] Open Advanced Paste window using hotkey, press Ctrl + 2 and confirm that pasted text is converted to markdown
* Paste As JSON
- [] Open Settings and set Paste as JSON directly hotkey
- [x] Copy some XML or CSV text (or any other text, it will be converted to simple JSON object)
- [x] Paste the text using set hotkey and confirm that pasted text is converted to JSON
- [x] Copy some text (same as in the previous step or different. If nothing is coppied between steps, previously pasted JSON text will be picked up from clipboard and converted again to nested JSON).
- [x] Open Advanced Paste window using hotkey, click Paste as markdown button and confirm that pasted text is converted to markdown
- [x] Copy some text (same as in the previous step or different. If nothing is coppied between steps, previously pasted JSON text will be picked up from clipboard and converted again to nested JSON).
- [x] Open Advanced Paste window using hotkey, press Ctrl + 3 and confirm that pasted text is converted to markdown
* Paste as custom format using AI
- [] Open Settings, navigate to Enable Paste with AI and set OpenAI key.
- [] Copy some text to clipboard. Any text.
- [] Open Advanced Paste window using hotkey, and confirm that Custom intput text box is now enabled. Write "Insert smiley after every word" and press Enter. Observe that result preview shows coppied text with smileys between words. Press Enter to paste the result and observe that it is pasted.
- [] Open Advanced Paste window using hotkey. Input some query (any, feel free to play around) and press Enter. When result is shown, click regenerate button, to see if new result is generated. Select one of the results and paste. Observe that correct result is pasted.
- [] Create few custom actions. Set up hotkey for custom actions and confirm they work. Enable/disable custom actions and confirm that the change is reflected in Advanced Paste UI - custom action is not listed. Try different ctrl + <num> in-app shortcuts for custom actions. Try moving custom actions up/down and confirm that the change is reflected in Advanced Paste UI.
- [] Open Settings and disable Custom format preview. Open Advanced Paste window with hotkey, enter some query and press enter. Observe that result is now pasted right away, without showing the preview first.
- [] Open Settings and Disable Enable Paste with AI. Open Advanced Paste window with hotkey and observe that Custom Input text box is now disabled.
* Clipboard History
- [] Open Settings and Enable clipboard history (if not enabled already). Open Advanced Paste window with hotkey, click Clipboard history and try deleting some entry. Check OS clipboard history (Win+V), and confirm that the same entry no longer exist.
- [] Open Advanced Paste window with hotkey, click Clipboard history, and click any entry (but first). Observe that entry is put on top of clipboard history. Check OS clipboard history (Win+V), and confirm that the same entry is on top of the clipboard.
- [] Open Settings and Disable clipboard history. Open Advanced Paste window with hotkey and observe that Clipboard history button is disabled.
* Disable Advanced Paste, try different Advanced Paste hotkeys and confirm that it's disabled and nothing happens.

View File

@@ -4,8 +4,8 @@
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "HostsEditor.FuzzTests.dll",
"class": "HostsEditor.FuzzTests.FuzzTests",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidIPv4",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
@@ -35,8 +35,8 @@
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"HostsEditor.FuzzTests.dll",
"HostsEditor.FuzzTests.pdb",
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
@@ -45,8 +45,8 @@
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "HostsEditor.FuzzTests.dll",
"class": "HostsEditor.FuzzTests.FuzzTests",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidIPv6",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
@@ -76,8 +76,8 @@
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"HostsEditor.FuzzTests.dll",
"HostsEditor.FuzzTests.pdb",
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
@@ -86,8 +86,8 @@
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "HostsEditor.FuzzTests.dll",
"class": "HostsEditor.FuzzTests.FuzzTests",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidHosts",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
@@ -117,8 +117,8 @@
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"HostsEditor.FuzzTests.dll",
"HostsEditor.FuzzTests.pdb",
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
@@ -127,8 +127,8 @@
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "HostsEditor.FuzzTests.dll",
"class": "HostsEditor.FuzzTests.FuzzTests",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzWriteAsync",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
@@ -160,8 +160,8 @@
// (globs are supported)
"Castle.Core.dll",
"CommunityToolkit.Mvvm.dll",
"HostsEditor.FuzzTests.dll",
"HostsEditor.FuzzTests.pdb",
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"Moq.dll",
"System.IO.Abstractions.dll",

View File

@@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<PropertyGroup>
<RootNamespace>PowerOCR.UITests</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<RunVSTest>false</RunVSTest>
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\PowerOCR.UITests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MSTest" />
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,59 +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 static Microsoft.PowerToys.UITest.UITestBase;
namespace PowerOCR.UITests;
[TestClass]
public class PowerOCRTests : UITestBase
{
public PowerOCRTests()
: base(PowerToysModule.PowerToysSettings, WindowSize.Medium)
{
}
[TestInitialize]
public void TestInitialize()
{
if (FindAll<NavigationViewItem>("Text Extractor").Count == 0)
{
// Expand Advanced list-group if needed
Find<NavigationViewItem>("System Tools").Click();
}
Find<NavigationViewItem>("Text Extractor").Click();
Find<ToggleSwitch>("Enable Text Extractor").Toggle(true);
SendKeys(Key.Win, Key.D);
}
[TestMethod("PowerOCR.DetectTextExtractor")]
[TestCategory("PowerOCR Detection")]
public void DetectTextExtractorTest()
{
try
{
SendKeys(Key.Win, Key.Shift, Key.T);
Thread.Sleep(5000);
var textExtractorWindow = Find("TextExtractor", 10000, true);
Assert.IsNotNull(textExtractorWindow, "TextExtractor window should be found after hotkey activation");
Console.WriteLine("✓ TextExtractor window detected successfully after hotkey activation");
SendKeys(Key.Esc);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to detect TextExtractor window: {ex.Message}");
Assert.Fail("TextExtractor window was not found after hotkey activation");
}
}
}

View File

@@ -5,7 +5,7 @@
<ProjectGuid>{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WorkspacesLibUnitTests</RootNamespace>
<ProjectName>Workspaces.Lib.UnitTests</ProjectName>
<ProjectName>WorkspacesLibUnitTests</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">

View File

@@ -1,583 +1,209 @@
# editorconfig: http://editorconfig.org/
# Help developers standardize spaces, tabs, encoding, end-line characters across editors
# Rules in this file were initially inferred by Visual Studio IntelliCode from the Template Studio codebase.
# You can modify the rules from these initially generated values to suit your own policies.
# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference.
# top-most .editorconfig file
root = true
# defaults for all files
[*]
charset = utf-8
end_of_line = crlf
tab_width = 4
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.cs]
file_header_template = Copyright (c) Microsoft Corporation\r\nThe Microsoft Corporation licenses this file to you under the MIT license.\r\nSee the LICENSE file in the project root for more information.
# markdown, diff overrides
# two trailing spaces are required for <br/> and hard line-breaks in markdown files
# see: (https://daringfireball.net/projects/markdown/syntax#p) and (http://spec.commonmark.org/0.27/#hard-line-break)
[*.{md,diff}]
trim_trailing_whitespace = false
#Core editorconfig formatting - indentation
[*.{md,xml,xsd,gprops,man,natvis}]
indent_size = 2
#use soft tabs (spaces) for indentation
indent_style = space
# manifest validation tool requires BOM
[*.man]
charset = utf-8-bom
#Formatting - new line options
# XML-based MSBuild and Visual Studio files
[*.{props,targets,settings,*proj,vcxitems,filters,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
# Exceptions to the above *proj wildcard
[*.vdproj]
indent_size = 4
# Visual Studio uses hard tabs for SLN files, so don't fight it
[*.sln]
indent_style = tab
# Visual Studio removes the last empty line, so don't fight it
[*.{vcxproj}]
insert_final_newline = false
# YAML overrides
[*.{yml,yaml}]
indent_size = 2
# package.json overrides
# Updating package.json with NPM will revert indentation to 2 spaces so to
# reduce churn, let's align to NPM and specify indent size 2
[package.json]
indent_size = 2
# HTML5 content (*.html, *.js) included in the AppX package should properly encoded with the UTF-8 byte order mark (BOM) as this is a Store requirement.
[*.{html,js,css}]
charset = utf-8-bom
# JSON formats
[{*.{json,testlist,testpasses,testenv,pluginlist},testmd.definition}]
indent_size = 2
[*.{rc,rc2}]
trim_trailing_whitespace = true
insert_final_newline = true
[*.{c,w}]
trim_trailing_whitespace = true
insert_final_newline = true
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli,idl}]
trim_trailing_whitespace = true
insert_final_newline = true
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = innermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = false
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = true
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = ignore
cpp_new_line_before_open_brace_type = ignore
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = new_line
cpp_new_line_before_open_brace_lambda = new_line
cpp_new_line_scope_braces_on_separate_lines = true
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = true
cpp_new_line_before_else = true
cpp_new_line_before_while_in_do_while = true
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = false
cpp_space_between_empty_parameter_list_parentheses = false
cpp_space_after_keywords_in_control_flow_statements = true
cpp_space_within_control_flow_statement_parentheses = false
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = false
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = false
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = left
cpp_space_around_ternary_operator = insert
cpp_wrap_preserve_blocks = one_liners
# C# overrides
# Rules explanation: https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
[*.cs]
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:silent
# Indent settings
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_case_contents_when_block = false
csharp_indent_labels = one_less_than_current
# Newline settings
csharp_new_line_before_catch = true
#place else statements on a new line
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
#require braces to be on a new line for lambdas, methods, control_blocks, types, properties, and accessors (also known as "Allman" style)
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
# Braces settings
csharp_prefer_braces = when_multiline:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
#Formatting - organize using options
# Space settings
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Code-block preferences
csharp_prefer_simple_using_statement = true:silent
csharp_style_namespace_declarations = file_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_primary_constructors = true:silent
csharp_style_prefer_top_level_statements = false:silent
# Expression-level preferences
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:silent
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_local_over_anonymous_function = true:suggestion
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_style_prefer_range_operator = true:silent
csharp_style_prefer_tuple_swap = true:suggestion
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:silent
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# Suggest more modern language features when available
csharp_style_conditional_delegate_call = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_prefer_extended_property_pattern = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_prefer_switch_expression = true:suggestion
csharp_prefer_static_anonymous_function = true:suggestion
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
csharp_style_expression_bodied_indexers = when_on_single_line:suggestion
csharp_style_expression_bodied_properties = when_on_single_line:suggestion
csharp_style_expression_bodied_lambdas = when_on_single_line:silent
csharp_style_expression_bodied_constructors = when_on_single_line:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = when_on_single_line:silent
csharp_style_expression_bodied_operators = when_on_single_line:silent
# Don't suggest "var" when type is apparent, as "new()" is better
csharp_style_var_when_type_is_apparent = false:silent
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
# Modifier preferences
csharp_prefer_static_local_function = true:suggestion
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_prefer_readonly_struct_member = true:suggestion
### dotnet ###
# Sort using directives with System.* appearing first
#sort System.* using directives alphabetically, and place them before other usings
dotnet_sort_system_directives_first = true
# Suggest more modern language features when available
dotnet_style_coalesce_expression = true:silent
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_object_initializer = true:suggestion
#Formatting - spacing options
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
#require NO space between a cast and the value
csharp_space_after_cast = false
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_after_colon_in_inheritance_clause = true
#require a space after a keyword in a control flow statement such as a for loop
csharp_space_after_keywords_in_control_flow_statements = true
#require a space before the colon for bases or interfaces in a type declaration
csharp_space_before_colon_in_inheritance_clause = true
#remove space within empty argument list parentheses
csharp_space_between_method_call_empty_parameter_list_parentheses = false
#remove space between method call name and opening parenthesis
csharp_space_between_method_call_name_and_opening_parenthesis = false
#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
csharp_space_between_method_call_parameter_list_parentheses = false
#remove space within empty parameter list parentheses for a method declaration
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
csharp_space_between_method_declaration_parameter_list_parentheses = false
#Formatting - wrapping options
#leave code block on separate lines
csharp_preserve_single_line_blocks = true
#Style - Code block preferences
#prefer curly braces even for one line of code
csharp_prefer_braces = true:suggestion
#Style - expression bodied member options
#prefer expression bodies for accessors
csharp_style_expression_bodied_accessors = true:warning
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
#prefer expression bodies for methods
csharp_style_expression_bodied_methods = when_on_single_line:silent
#prefer expression-bodied members for properties
csharp_style_expression_bodied_properties = true:warning
#Style - expression level options
#prefer out variables to be declared before the method call
csharp_style_inlined_variable_declaration = false:suggestion
#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_member_access = true:suggestion
# Other style
#Style - Expression-level preferences
#prefer default over default(T)
csharp_prefer_simple_default_expression = true:suggestion
#prefer objects to be initialized using object initializers when possible
dotnet_style_object_initializer = true:suggestion
#Style - implicit and explicit types
#prefer var over explicit type in all cases, unless overridden by another code style rule
csharp_style_var_elsewhere = true:suggestion
#prefer var is used to declare variables with built-in system types such as int
csharp_style_var_for_built_in_types = true:suggestion
#prefer var when the type is already mentioned on the right-hand side of a declaration expression
csharp_style_var_when_type_is_apparent = true:suggestion
#Style - language keyword and framework type options
#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
#Style - Language rules
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_var_for_built_in_types = true:warning
#Style - modifier options
#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
#Style - Modifier preferences
#when this rule is set to a list of modifiers, prefer the specified ordering.
csharp_preferred_modifier_order = public,private,protected,internal,static,async,readonly,override,sealed,abstract,virtual:warning
dotnet_style_readonly_field = true:warning
#Style - Pattern matching
#prefer pattern matching instead of is expression with type casts
csharp_style_pattern_matching_over_as_with_null_check = true:warning
#Style - qualification options
#prefer events not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_event = false:suggestion
#prefer fields not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_field = false:suggestion
#prefer methods not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_method = false:suggestion
#prefer properties not to be prefaced with this. or Me. in Visual Basic
dotnet_style_qualification_for_property = false:suggestion
csharp_indent_labels = one_less_than_current
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:warning
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
[*.{cs,vb}]
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
dotnet_style_prefer_auto_properties = false:silent
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_collection_expression = never
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:silent
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_allow_multiple_blank_lines_experimental = false:suggestion
dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
dotnet_code_quality_unused_parameters = all:suggestion
[*.{cs,vb}]
# Field preferences
dotnet_style_readonly_field = true:suggestion
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
# Avoid "this."
dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_property = false:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
#Style - Unnecessary code rules
csharp_style_unused_value_assignment_preference = discard_variable:warning
#### Naming styles ####
# Naming rules
dotnet_naming_rule.const_variables_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.const_variables_should_be_pascal_case.symbols = const_variables
dotnet_naming_rule.const_variables_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.static_readonly_field_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.static_readonly_field_should_be_pascal_case.symbols = static_readonly_field
dotnet_naming_rule.static_readonly_field_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.fields__locals__params_should_be_camelcase.severity = suggestion
dotnet_naming_rule.fields__locals__params_should_be_camelcase.symbols = fields__locals__params
dotnet_naming_rule.fields__locals__params_should_be_camelcase.style = camelcase
dotnet_naming_rule.type_parameter_should_be_type_parameter.severity = suggestion
dotnet_naming_rule.type_parameter_should_be_type_parameter.symbols = type_parameter
dotnet_naming_rule.type_parameter_should_be_type_parameter.style = type_parameter
dotnet_naming_rule.all_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.all_should_be_pascal_case.symbols = all
dotnet_naming_rule.all_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.fields__locals__params.applicable_kinds = field, parameter, local
dotnet_naming_symbols.fields__locals__params.applicable_accessibilities = *
dotnet_naming_symbols.fields__locals__params.required_modifiers =
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.type_parameter.applicable_kinds = type_parameter
dotnet_naming_symbols.type_parameter.applicable_accessibilities = *
dotnet_naming_symbols.type_parameter.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.const_variables.applicable_kinds = field, local
dotnet_naming_symbols.const_variables.applicable_accessibilities = *
dotnet_naming_symbols.const_variables.required_modifiers = const
dotnet_naming_symbols.all.applicable_kinds = *
dotnet_naming_symbols.all.applicable_accessibilities = *
dotnet_naming_symbols.all.required_modifiers =
dotnet_naming_symbols.static_readonly_field.applicable_kinds = field
dotnet_naming_symbols.static_readonly_field.applicable_accessibilities = *
dotnet_naming_symbols.static_readonly_field.required_modifiers = readonly, static
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.camelcase.required_prefix =
dotnet_naming_style.camelcase.required_suffix =
dotnet_naming_style.camelcase.word_separator =
dotnet_naming_style.camelcase.capitalization = camel_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_naming_style.type_parameter.required_prefix = T
dotnet_naming_style.type_parameter.required_suffix =
dotnet_naming_style.type_parameter.word_separator =
dotnet_naming_style.type_parameter.capitalization = pascal_case
### Dotnet diagnostics ###
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/categories
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-options#severity-level
# The rule for assigning severity is:
# error (build break) - this is always incorrect code; e.g., recursively assigning a property to itself
# warning (build break) - this is possibly correct, but too error-prone to be used without calling it out; e.g., testing for NaN correctly, or hidden perf costs
# suggestion (IDE squiggles and IDE message) - this violates (or is very very very likely to violate) a CoreGuideline
# silent (no squiggles or message, but refactoring may be avaliable) - this violates a CoreGuideline, but with a non-neglagable but not large false-positive rate
# none (no user notification) - this violates a CoreGuideline, but with high false-positive rate; is inconsistent with the CoreGuidelines; or is otherwise incorrect
# Default diagnostics
# https://github.com/dotnet/roslyn-analyzers/blob/main/src/NetAnalyzers/Core/AnalyzerReleases.Shipped.md
# Note that in this list "info" = suggestion, "hidden" = silent, and "disabled" = none in terms of the severity field:
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-options
# We can only enable the "Default" set of diagnostics automatically and not the "Recommended" set,
# as we'd get warnings for non-breaking issues, so we have to manually adjust a bunch of severities.
# "hidden" issues still may appear in IDE refactorings, so a rule must be disabled with "none" explicitly if not needed.
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/design-warnings
dotnet_diagnostic.CA1001.severity = warning
dotnet_diagnostic.CA1003.severity = suggestion
dotnet_diagnostic.CA1005.severity = suggestion
dotnet_diagnostic.CA1008.severity = suggestion
dotnet_diagnostic.CA1010.severity = suggestion
dotnet_diagnostic.CA1012.severity = warning
dotnet_diagnostic.CA1016.severity = none
dotnet_diagnostic.CA1019.severity = suggestion
dotnet_diagnostic.CA1024.severity = suggestion
dotnet_diagnostic.CA1027.severity = suggestion
dotnet_diagnostic.CA1028.severity = suggestion
dotnet_diagnostic.CA1030.severity = suggestion
dotnet_diagnostic.CA1032.severity = suggestion
dotnet_diagnostic.CA1033.severity = suggestion
dotnet_diagnostic.CA1034.severity = silent
dotnet_diagnostic.CA1036.severity = suggestion
dotnet_diagnostic.CA1040.severity = suggestion
dotnet_diagnostic.CA1052.severity = suggestion
dotnet_diagnostic.CA1054.severity = suggestion
dotnet_diagnostic.CA1055.severity = suggestion
dotnet_diagnostic.CA1056.severity = suggestion
dotnet_diagnostic.CA1058.severity = warning
dotnet_diagnostic.CA1060.severity = silent
dotnet_diagnostic.CA1063.severity = suggestion
dotnet_diagnostic.CA1064.severity = suggestion
dotnet_diagnostic.CA1065.severity = suggestion
dotnet_diagnostic.CA1066.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/globalization-warnings
dotnet_diagnostic.CA1303.severity = suggestion
dotnet_diagnostic.CA1307.severity = suggestion
dotnet_diagnostic.CA1308.severity = suggestion
dotnet_diagnostic.CA1309.severity = suggestion
dotnet_diagnostic.CA1310.severity = suggestion
dotnet_diagnostic.CA1311.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/interoperability-warnings
dotnet_diagnostic.CA1419.severity = warning
dotnet_diagnostic.CA1421.severity = warning
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/maintainability-warnings
dotnet_diagnostic.CA1501.severity = suggestion
dotnet_diagnostic.CA1502.severity = suggestion
dotnet_diagnostic.CA1505.severity = suggestion
dotnet_diagnostic.CA1506.severity = suggestion
dotnet_diagnostic.CA1508.severity = suggestion
dotnet_diagnostic.CA1509.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/naming-warnings
dotnet_diagnostic.CA1700.severity = suggestion
dotnet_diagnostic.CA1707.severity = suggestion
dotnet_diagnostic.CA1710.severity = suggestion
dotnet_diagnostic.CA1711.severity = suggestion
dotnet_diagnostic.CA1712.severity = suggestion
dotnet_diagnostic.CA1713.severity = suggestion
dotnet_diagnostic.CA1715.severity = suggestion
dotnet_diagnostic.CA1716.severity = warning
dotnet_diagnostic.CA1721.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/performance-warnings
dotnet_diagnostic.CA1802.severity = suggestion
dotnet_diagnostic.CA1805.severity = suggestion
dotnet_diagnostic.CA1806.severity = warning
# Flag any accidental use of static Equals without checking the return value, scenarios like "StringAssert.Equals" are falling through to a method
# that doesn't do what the caller expects.
dotnet_code_quality.CA1806.additional_use_results_methods = Equals
dotnet_diagnostic.CA1810.severity = suggestion
dotnet_diagnostic.CA1812.severity = suggestion
dotnet_diagnostic.CA1813.severity = suggestion
dotnet_diagnostic.CA1815.severity = suggestion
dotnet_diagnostic.CA1820.severity = suggestion
dotnet_diagnostic.CA1823.severity = suggestion
dotnet_diagnostic.CA1838.severity = suggestion
dotnet_diagnostic.CA1849.severity = suggestion
dotnet_diagnostic.CA1851.severity = suggestion
dotnet_diagnostic.CA1852.severity = suggestion
dotnet_diagnostic.CA1867.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/reliability-warnings
dotnet_diagnostic.CA2000.severity = warning
dotnet_diagnostic.CA2002.severity = warning
dotnet_diagnostic.CA2008.severity = warning
dotnet_diagnostic.CA2011.severity = warning
dotnet_diagnostic.CA2012.severity = warning
dotnet_diagnostic.CA2019.severity = warning
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/security-warnings
dotnet_diagnostic.CA2100.severity = warning
dotnet_diagnostic.CA2119.severity = warning
dotnet_diagnostic.CA2153.severity = warning
dotnet_diagnostic.CA2300.severity = warning
dotnet_diagnostic.CA2301.severity = warning
dotnet_diagnostic.CA2302.severity = warning
dotnet_diagnostic.CA2305.severity = warning
dotnet_diagnostic.CA2310.severity = warning
dotnet_diagnostic.CA2311.severity = warning
dotnet_diagnostic.CA2312.severity = warning
dotnet_diagnostic.CA2315.severity = warning
dotnet_diagnostic.CA2321.severity = warning
dotnet_diagnostic.CA2322.severity = warning
dotnet_diagnostic.CA2326.severity = warning
dotnet_diagnostic.CA2327.severity = warning
dotnet_diagnostic.CA2328.severity = warning
dotnet_diagnostic.CA2329.severity = warning
dotnet_diagnostic.CA2330.severity = warning
dotnet_diagnostic.CA2350.severity = warning
dotnet_diagnostic.CA2351.severity = warning
dotnet_diagnostic.CA2352.severity = warning
dotnet_diagnostic.CA2353.severity = warning
dotnet_diagnostic.CA2354.severity = warning
dotnet_diagnostic.CA2355.severity = warning
dotnet_diagnostic.CA2356.severity = warning
dotnet_diagnostic.CA2361.severity = warning
dotnet_diagnostic.CA2362.severity = warning
dotnet_diagnostic.CA3001.severity = warning
dotnet_diagnostic.CA3002.severity = warning
dotnet_diagnostic.CA3003.severity = warning
dotnet_diagnostic.CA3004.severity = warning
dotnet_diagnostic.CA3005.severity = warning
dotnet_diagnostic.CA3006.severity = warning
dotnet_diagnostic.CA3007.severity = warning
dotnet_diagnostic.CA3008.severity = warning
dotnet_diagnostic.CA3009.severity = warning
dotnet_diagnostic.CA3010.severity = warning
dotnet_diagnostic.CA3011.severity = warning
dotnet_diagnostic.CA3012.severity = warning
dotnet_diagnostic.CA3061.severity = warning
dotnet_diagnostic.CA3075.severity = warning
dotnet_diagnostic.CA3076.severity = warning
dotnet_diagnostic.CA3077.severity = warning
dotnet_diagnostic.CA3147.severity = warning
dotnet_diagnostic.CA5350.severity = warning
dotnet_diagnostic.CA5351.severity = warning
dotnet_diagnostic.CA5358.severity = warning
dotnet_diagnostic.CA5359.severity = warning
dotnet_diagnostic.CA5360.severity = warning
dotnet_diagnostic.CA5361.severity = warning
dotnet_diagnostic.CA5362.severity = warning
dotnet_diagnostic.CA5363.severity = warning
dotnet_diagnostic.CA5364.severity = warning
dotnet_diagnostic.CA5365.severity = warning
dotnet_diagnostic.CA5366.severity = warning
dotnet_diagnostic.CA5367.severity = warning
dotnet_diagnostic.CA5368.severity = warning
dotnet_diagnostic.CA5369.severity = warning
dotnet_diagnostic.CA5370.severity = warning
dotnet_diagnostic.CA5371.severity = warning
dotnet_diagnostic.CA5372.severity = warning
dotnet_diagnostic.CA5373.severity = warning
dotnet_diagnostic.CA5374.severity = warning
dotnet_diagnostic.CA5375.severity = warning
dotnet_diagnostic.CA5376.severity = warning
dotnet_diagnostic.CA5377.severity = warning
dotnet_diagnostic.CA5378.severity = warning
dotnet_diagnostic.CA5379.severity = warning
dotnet_diagnostic.CA5380.severity = warning
dotnet_diagnostic.CA5381.severity = warning
dotnet_diagnostic.CA5382.severity = warning
dotnet_diagnostic.CA5383.severity = warning
dotnet_diagnostic.CA5384.severity = warning
dotnet_diagnostic.CA5385.severity = warning
dotnet_diagnostic.CA5386.severity = warning
dotnet_diagnostic.CA5387.severity = warning
dotnet_diagnostic.CA5388.severity = warning
dotnet_diagnostic.CA5389.severity = warning
dotnet_diagnostic.CA5390.severity = warning
dotnet_diagnostic.CA5391.severity = warning
dotnet_diagnostic.CA5392.severity = silent
dotnet_diagnostic.CA5393.severity = warning
dotnet_diagnostic.CA5394.severity = warning
dotnet_diagnostic.CA5395.severity = warning
dotnet_diagnostic.CA5396.severity = warning
dotnet_diagnostic.CA5397.severity = warning
dotnet_diagnostic.CA5398.severity = warning
dotnet_diagnostic.CA5399.severity = warning
dotnet_diagnostic.CA5400.severity = warning
dotnet_diagnostic.CA5401.severity = warning
dotnet_diagnostic.CA5402.severity = warning
dotnet_diagnostic.CA5403.severity = warning
dotnet_diagnostic.CA5404.severity = warning
dotnet_diagnostic.CA5405.severity = warning
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/usage-warnings
dotnet_diagnostic.CA2201.severity = warning
dotnet_diagnostic.CA2207.severity = suggestion
dotnet_diagnostic.CA2211.severity = warning
dotnet_diagnostic.CA2213.severity = warning
dotnet_diagnostic.CA2215.severity = suggestion
dotnet_diagnostic.CA2217.severity = warning
dotnet_diagnostic.CA2219.severity = warning
dotnet_diagnostic.CA2226.severity = suggestion
dotnet_diagnostic.CA2234.severity = suggestion
dotnet_diagnostic.CA2242.severity = warning
dotnet_diagnostic.CA2243.severity = suggestion
dotnet_diagnostic.CA2245.severity = warning
dotnet_diagnostic.CA2251.severity = suggestion
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
# required by CELA
dotnet_diagnostic.IDE0073.severity = suggestion
# Diagnostic configuration
# CS8305: Type is for evaluation purposes only and is subject to change or removal in future updates.
dotnet_diagnostic.CS8305.severity = suggestion

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -13,10 +13,10 @@ public static partial class NativeEventWaiter
{
public static void WaitForEventLoop(string eventName, Action callback)
{
DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();
Thread t = new Thread(() =>
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
var t = new Thread(() =>
{
EventWaitHandle eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
while (true)
{
if (eventHandle.WaitOne())
@@ -24,10 +24,9 @@ public static partial class NativeEventWaiter
dispatcherQueue.TryEnqueue(() => callback());
}
}
})
{
IsBackground = true,
};
});
t.IsBackground = true;
t.Start();
}
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.

View File

@@ -19,13 +19,13 @@ public interface IExtensionService
Task SignalStopExtensionsAsync();
event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;
public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;
event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionRemoved;
public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionRemoved;
void EnableExtension(string extensionUniqueId);
public void EnableExtension(string extensionUniqueId);
void DisableExtension(string extensionUniqueId);
public void DisableExtension(string extensionUniqueId);
///// <summary>
///// Gets a boolean indicating whether the extension was disabled due to the corresponding Windows optional feature

View File

@@ -55,7 +55,7 @@ public interface IExtensionWrapper
/// <summary>
/// Gets the Unique Id for the extension
/// </summary>
string ExtensionUniqueId { get; }
public string ExtensionUniqueId { get; }
/// <summary>
/// Checks whether we have a reference to the extension process and we are able to call methods on the interface.

View File

@@ -1,27 +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;
namespace Microsoft.CmdPal.Common.Services;
public interface IRunHistoryService
{
/// <summary>
/// Gets the run history.
/// </summary>
/// <returns>A list of run history items.</returns>
IReadOnlyList<string> GetRunHistory();
/// <summary>
/// Clears the run history.
/// </summary>
void ClearRunHistory();
/// <summary>
/// Adds a run history item.
/// </summary>
/// <param name="item">The run history item to add.</param>
void AddRunHistoryItem(string item);
}

View File

@@ -1,168 +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.ObjectModel;
using System.Diagnostics;
using ManagedCommon;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class AppExtensionHost : IExtensionHost
{
private static readonly GlobalLogPageContext _globalLogPageContext = new();
private static ulong _hostingHwnd;
public static ObservableCollection<LogMessageViewModel> LogMessages { get; } = [];
public ulong HostingHwnd => _hostingHwnd;
public string LanguageOverride => string.Empty;
public ObservableCollection<StatusMessageViewModel> StatusMessages { get; } = [];
public static void SetHostHwnd(ulong hostHwnd) => _hostingHwnd = hostHwnd;
public void DebugLog(string message)
{
#if DEBUG
this.ProcessLogMessage(new LogMessage(message));
#endif
}
public IAsyncAction HideStatus(IStatusMessage? message)
{
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
_ = Task.Run(() =>
{
ProcessHideStatusMessage(message);
});
return Task.CompletedTask.AsAsyncAction();
}
public void Log(string message)
{
this.ProcessLogMessage(new LogMessage(message));
}
public IAsyncAction LogMessage(ILogMessage? message)
{
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
Logger.LogDebug(message.Message);
_ = Task.Run(() =>
{
ProcessLogMessage(message);
});
// We can't just make a LogMessageViewModel : ExtensionObjectViewModel
// because we don't necessarily know the page context. Butts.
return Task.CompletedTask.AsAsyncAction();
}
public void ProcessHideStatusMessage(IStatusMessage message)
{
Task.Factory.StartNew(
() =>
{
try
{
StatusMessageViewModel? vm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
if (vm != null)
{
StatusMessages.Remove(vm);
}
}
catch
{
}
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public void ProcessLogMessage(ILogMessage message)
{
LogMessageViewModel vm = new LogMessageViewModel(message, _globalLogPageContext);
vm.SafeInitializePropertiesSynchronous();
Task.Factory.StartNew(
() =>
{
LogMessages.Add(vm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public void ProcessStatusMessage(IStatusMessage message, StatusContext context)
{
// If this message is already in the list of messages, just bring it to the top
StatusMessageViewModel? oldVm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
if (oldVm != null)
{
Task.Factory.StartNew(
() =>
{
StatusMessages.Remove(oldVm);
StatusMessages.Add(oldVm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
return;
}
StatusMessageViewModel vm = new StatusMessageViewModel(message, new(_globalLogPageContext));
vm.SafeInitializePropertiesSynchronous();
Task.Factory.StartNew(
() =>
{
StatusMessages.Add(vm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public IAsyncAction ShowStatus(IStatusMessage? message, StatusContext context)
{
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
Debug.WriteLine(message.Message);
_ = Task.Run(() =>
{
ProcessStatusMessage(message, context);
});
return Task.CompletedTask.AsAsyncAction();
}
public abstract string? GetExtensionDisplayName();
}
public interface IAppHostService
{
AppExtensionHost GetDefaultHost();
AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost);
}

View File

@@ -1,9 +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.
namespace Microsoft.CmdPal.Core.ViewModels;
public interface IContextItemViewModel
{
}

View File

@@ -1,37 +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.
namespace Microsoft.CmdPal.Core.ViewModels;
public interface IRootPageService
{
/// <summary>
/// Gets the root page of the command palette. Return any IPage implementation that
/// represents the root view of this instance of the command palette.
/// </summary>
Microsoft.CommandPalette.Extensions.IPage GetRootPage();
/// <summary>
/// Pre-loads any necessary data or state before the root page is loaded.
/// This will be awaited before the root page and the user can do anything,
/// so ideally it should be quick and not block the UI thread for long.
/// </summary>
Task PreLoadAsync();
/// <summary>
/// Do any loading work that can be done after the root page is loaded and
/// displayed to the user.
/// This is run asynchronously, on a background thread.
/// </summary>
Task PostLoadRootPageAsync();
/// <summary>
/// Called when a command is performed. The context is the
/// sender context for the invoked command. This is typically the IListItem
/// or ICommandContextItem that was used to invoke the command.
/// </summary>
void OnPerformCommand(object? context, bool topLevel, AppExtensionHost? currentHost);
void GoHome();
}

View File

@@ -1,9 +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.
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record HideDetailsMessage()
{
}

View File

@@ -1,9 +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.
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record OpenSettingsMessage()
{
}

View File

@@ -1,9 +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.
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record UpdateSuggestionMessage(string TextToSuggest)
{
}

View File

@@ -1,48 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\Common.Dotnet.AotCompatibility.props" />
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
<!-- For MVVM Toolkit Partial Properties/AOT support -->
<LangVersion>preview</LangVersion>
<!-- Disable SA1313 for Primary Constructor fields conflict https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/instance-constructors#primary-constructors -->
<NoWarn>SA1313;</NoWarn>
</PropertyGroup>
<PropertyGroup>
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Common" />
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="Microsoft.Windows.CsWin32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="WyHash" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
</Project>

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false
}

View File

@@ -1,19 +0,0 @@
GetPhysicallyInstalledSystemMemory
GlobalMemoryStatusEx
GetSystemInfo
CoCreateInstance
SetForegroundWindow
IsIconic
RegisterHotKey
SetWindowLongPtr
CallWindowProc
ShowWindow
SetForegroundWindow
SetFocus
SetActiveWindow
MonitorFromWindow
GetMonitorInfo
SHCreateStreamOnFileEx
CoAllowSetForegroundWindow
SHCreateStreamOnFileEx
SHLoadIndirectString

View File

@@ -1,27 +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.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
public class PageViewModelFactory : IPageViewModelFactoryService
{
private readonly TaskScheduler _scheduler;
public PageViewModelFactory(TaskScheduler scheduler)
{
_scheduler = scheduler;
}
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host)
{
return page switch
{
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
IContentPage contentPage => new ContentPageViewModel(contentPage, _scheduler, host),
_ => null,
};
}
}

View File

@@ -4,7 +4,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
namespace Microsoft.CmdPal.UI.ViewModels;
@@ -30,16 +30,15 @@ public partial class AliasManager : ObservableObject
public bool CheckAlias(string searchText)
{
if (_aliases.TryGetValue(searchText, out CommandAlias? alias))
if (_aliases.TryGetValue(searchText, out var alias))
{
try
{
TopLevelViewModel? topLevelCommand = _topLevelCommandManager.LookupCommand(alias.CommandId);
var topLevelCommand = _topLevelCommandManager.LookupCommand(alias.CommandId);
if (topLevelCommand != null)
{
WeakReferenceMessenger.Default.Send<ClearSearchMessage>();
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(topLevelCommand.GetPerformCommandMessage());
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(topLevelCommand));
return true;
}
}
@@ -89,7 +88,7 @@ public partial class AliasManager : ObservableObject
// If we already have _this exact alias_, do nothing
if (newAlias != null &&
_aliases.TryGetValue(newAlias.SearchPrefix, out CommandAlias? existingAlias))
_aliases.TryGetValue(newAlias.SearchPrefix, out var existingAlias))
{
if (existingAlias.CommandId == commandId)
{
@@ -99,7 +98,7 @@ public partial class AliasManager : ObservableObject
// Look for the old alias, and remove it
List<CommandAlias> toRemove = [];
foreach (KeyValuePair<string, CommandAlias> kv in _aliases)
foreach (var kv in _aliases)
{
if (kv.Value.CommandId == commandId)
{
@@ -107,7 +106,7 @@ public partial class AliasManager : ObservableObject
}
}
foreach (CommandAlias alias in toRemove)
foreach (var alias in toRemove)
{
// REMEMBER, SearchPrefix is what we use as keys
_aliases.Remove(alias.SearchPrefix);

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -21,12 +21,8 @@ public partial class AppStateModel : ObservableObject
///////////////////////////////////////////////////////////////////////////
// STATE HERE
// Make sure that you make the setters public (JsonSerializer.Deserialize will fail silently otherwise)!
// Make sure that any new types you add are added to JsonSerializationContext!
public RecentCommandsManager RecentCommands { get; set; } = new();
public List<string> RunHistory { get; set; } = [];
// END SETTINGS
///////////////////////////////////////////////////////////////////////////
@@ -51,9 +47,9 @@ public partial class AppStateModel : ObservableObject
try
{
// Read the JSON content from the file
string jsonContent = File.ReadAllText(FilePath);
var jsonContent = File.ReadAllText(FilePath);
AppStateModel? loaded = JsonSerializer.Deserialize<AppStateModel>(jsonContent, JsonSerializationContext.Default.AppStateModel);
var loaded = JsonSerializer.Deserialize<AppStateModel>(jsonContent, JsonSerializationContext.Default.AppStateModel);
Debug.WriteLine(loaded != null ? "Loaded settings file" : "Failed to parse");
@@ -77,23 +73,23 @@ public partial class AppStateModel : ObservableObject
try
{
// Serialize the main dictionary to JSON and save it to the file
string settingsJson = JsonSerializer.Serialize(model, JsonSerializationContext.Default.AppStateModel);
var settingsJson = JsonSerializer.Serialize(model, JsonSerializationContext.Default.AppStateModel);
// Is it valid JSON?
if (JsonNode.Parse(settingsJson) is JsonObject newSettings)
{
// Now, read the existing content from the file
string oldContent = File.Exists(FilePath) ? File.ReadAllText(FilePath) : "{}";
var oldContent = File.Exists(FilePath) ? File.ReadAllText(FilePath) : "{}";
// Is it valid JSON?
if (JsonNode.Parse(oldContent) is JsonObject savedSettings)
{
foreach (KeyValuePair<string, JsonNode?> item in newSettings)
foreach (var item in newSettings)
{
savedSettings[item.Key] = item.Value?.DeepClone();
savedSettings[item.Key] = item.Value != null ? item.Value.DeepClone() : null;
}
string serialized = savedSettings.ToJsonString(JsonSerializationContext.Default.AppStateModel.Options);
var serialized = savedSettings.ToJsonString(JsonSerializationContext.Default.AppStateModel.Options);
File.WriteAllText(FilePath, serialized);
// TODO: Instead of just raising the event here, we should
@@ -119,10 +115,26 @@ public partial class AppStateModel : ObservableObject
internal static string StateJsonPath()
{
string directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
Directory.CreateDirectory(directory);
// now, the settings is just next to the exe
return Path.Combine(directory, "state.json");
}
// [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
// private static readonly JsonSerializerOptions _serializerOptions = new()
// {
// WriteIndented = true,
// Converters = { new JsonStringEnumConverter() },
// };
// private static readonly JsonSerializerOptions _deserializerOptions = new()
// {
// PropertyNameCaseInsensitive = true,
// IncludeFields = true,
// AllowTrailingCommas = true,
// PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate,
// ReadCommentHandling = JsonCommentHandling.Skip,
// };
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -31,8 +31,8 @@ public class CommandAlias
public static CommandAlias FromSearchText(string text, string commandId)
{
bool trailingSpace = text.EndsWith(' ');
string realAlias = trailingSpace ? text.Substring(0, text.Length - 1) : text;
var trailingSpace = text.EndsWith(' ');
var realAlias = trailingSpace ? text.Substring(0, text.Length - 1) : text;
return new CommandAlias(realAlias, commandId, !trailingSpace);
}
}

View File

@@ -1,14 +1,15 @@
// Copyright (c) Microsoft Corporation
// 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.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.System;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandBarViewModel : ObservableObject,
IRecipient<UpdateCommandBarMessage>
@@ -125,12 +126,12 @@ public partial class CommandBarViewModel : ObservableObject,
public ContextKeybindingResult CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key)
{
Dictionary<CommandPalette.Extensions.KeyChord, CommandContextItemViewModel>? keybindings = SelectedItem?.Keybindings();
var keybindings = SelectedItem?.Keybindings();
if (keybindings != null)
{
// Does the pressed key match any of the keybindings?
CommandPalette.Extensions.KeyChord pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out CommandContextItemViewModel? matchedItem))
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out var matchedItem))
{
return matchedItem != null ? PerformCommand(matchedItem) : ContextKeybindingResult.Unhandled;
}
@@ -148,7 +149,6 @@ public partial class CommandBarViewModel : ObservableObject,
if (command.HasMoreCommands)
{
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(command.Command.Model, command.Model));
return ContextKeybindingResult.KeepOpen;
}
else

View File

@@ -1,11 +1,13 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Models;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context) : CommandItemViewModel(new(contextItem), context), IContextItemViewModel
{
@@ -28,7 +30,7 @@ public partial class CommandContextItemViewModel(ICommandContextItem contextItem
base.InitializeProperties();
ICommandContextItem? contextItem = Model.Unsafe;
var contextItem = Model.Unsafe;
if (contextItem == null)
{
return; // throw?

View File

@@ -1,13 +1,13 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBarContext
{
@@ -97,7 +97,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
return;
}
ICommandItem? model = _commandItemModel.Unsafe;
var model = _commandItemModel.Unsafe;
if (model == null)
{
return;
@@ -125,7 +125,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
FastInitializeProperties();
}
ICommandItem? model = _commandItemModel.Unsafe;
var model = _commandItemModel.Unsafe;
if (model == null)
{
return;
@@ -133,7 +133,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
Command.InitializeProperties();
IIconInfo listIcon = model.Icon;
var listIcon = model.Icon;
if (listIcon != null)
{
_listItemIcon = new(listIcon);
@@ -169,25 +169,25 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
InitializeProperties();
}
ICommandItem? model = _commandItemModel.Unsafe;
var model = _commandItemModel.Unsafe;
if (model == null)
{
return;
}
IContextItem[] more = model.MoreCommands;
var more = model.MoreCommands;
if (more != null)
{
MoreCommands = more
.Select<IContextItem, IContextItemViewModel>(item =>
.Select(item =>
{
if (item is ICommandContextItem contextItem)
{
return new CommandContextItemViewModel(contextItem, PageContext);
return new CommandContextItemViewModel(contextItem, PageContext) as IContextItemViewModel;
}
else
{
return new SeparatorContextItemViewModel();
return new SeparatorContextItemViewModel() as IContextItemViewModel;
}
})
.ToList();
@@ -297,7 +297,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
protected virtual void FetchProperty(string propertyName)
{
ICommandItem? model = this._commandItemModel.Unsafe;
var model = this._commandItemModel.Unsafe;
if (model == null)
{
return; // throw?
@@ -332,19 +332,19 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
break;
case nameof(model.MoreCommands):
IContextItem[] more = model.MoreCommands;
var more = model.MoreCommands;
if (more != null)
{
List<IContextItemViewModel> newContextMenu = more
.Select<IContextItem, IContextItemViewModel>(item =>
var newContextMenu = more
.Select(item =>
{
if (item is CommandContextItem contextItem)
{
return new CommandContextItemViewModel(contextItem, PageContext);
return new CommandContextItemViewModel(contextItem, PageContext) as IContextItemViewModel;
}
else
{
return new SeparatorContextItemViewModel();
return new SeparatorContextItemViewModel() as IContextItemViewModel;
}
})
.ToList();
@@ -381,7 +381,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
private void Command_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
string? propertyName = e.PropertyName;
var propertyName = e.PropertyName;
switch (propertyName)
{
case nameof(Command.Name):
@@ -415,7 +415,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
Command.PropertyChanged -= Command_PropertyChanged;
Command.SafeCleanup();
ICommandItem? model = _commandItemModel.Unsafe;
var model = _commandItemModel.Unsafe;
if (model != null)
{
model.PropChanged -= Model_PropChanged;

View File

@@ -1,28 +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.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandPaletteContentPageViewModel : ContentPageViewModel
{
public CommandPaletteContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
: base(model, scheduler, host)
{
}
public override ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
{
ContentViewModel? viewModel = content switch
{
IFormContent form => new ContentFormViewModel(form, context),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
ITreeContent tree => new ContentTreeViewModel(tree, context),
_ => null,
};
return viewModel;
}
}

View File

@@ -1,19 +1,35 @@
// Copyright (c) Microsoft Corporation
// 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.ObjectModel;
using System.Diagnostics;
using ManagedCommon;
using Microsoft.CmdPal.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
namespace Microsoft.CmdPal.UI.ViewModels;
public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHost
public sealed partial class CommandPaletteHost : IExtensionHost
{
// Static singleton, so that we can access this from anywhere
// Post MVVM - this should probably be like, a dependency injection thing.
public static CommandPaletteHost Instance { get; } = new();
private static readonly GlobalLogPageContext _globalLogPageContext = new();
private static ulong _hostingHwnd;
public ulong HostingHwnd => _hostingHwnd;
public string LanguageOverride => string.Empty;
public static ObservableCollection<LogMessageViewModel> LogMessages { get; } = [];
public ObservableCollection<StatusMessageViewModel> StatusMessages { get; } = [];
public IExtensionWrapper? Extension { get; }
private readonly ICommandProvider? _builtInProvider;
@@ -32,8 +48,145 @@ public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHos
_builtInProvider = builtInProvider;
}
public override string? GetExtensionDisplayName()
public IAsyncAction ShowStatus(IStatusMessage? message, StatusContext context)
{
return Extension?.ExtensionDisplayName;
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
Debug.WriteLine(message.Message);
_ = Task.Run(() =>
{
ProcessStatusMessage(message, context);
});
return Task.CompletedTask.AsAsyncAction();
}
public IAsyncAction HideStatus(IStatusMessage? message)
{
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
_ = Task.Run(() =>
{
ProcessHideStatusMessage(message);
});
return Task.CompletedTask.AsAsyncAction();
}
public IAsyncAction LogMessage(ILogMessage? message)
{
if (message == null)
{
return Task.CompletedTask.AsAsyncAction();
}
Logger.LogDebug(message.Message);
_ = Task.Run(() =>
{
ProcessLogMessage(message);
});
// We can't just make a LogMessageViewModel : ExtensionObjectViewModel
// because we don't necessarily know the page context. Butts.
return Task.CompletedTask.AsAsyncAction();
}
public void ProcessLogMessage(ILogMessage message)
{
var vm = new LogMessageViewModel(message, _globalLogPageContext);
vm.SafeInitializePropertiesSynchronous();
if (Extension != null)
{
vm.ExtensionPfn = Extension.PackageFamilyName;
}
Task.Factory.StartNew(
() =>
{
LogMessages.Add(vm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public void ProcessStatusMessage(IStatusMessage message, StatusContext context)
{
// If this message is already in the list of messages, just bring it to the top
var oldVm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
if (oldVm != null)
{
Task.Factory.StartNew(
() =>
{
StatusMessages.Remove(oldVm);
StatusMessages.Add(oldVm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
return;
}
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext));
vm.SafeInitializePropertiesSynchronous();
if (Extension != null)
{
vm.ExtensionPfn = Extension.PackageFamilyName;
}
Task.Factory.StartNew(
() =>
{
StatusMessages.Add(vm);
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public void ProcessHideStatusMessage(IStatusMessage message)
{
Task.Factory.StartNew(
() =>
{
try
{
var vm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
if (vm != null)
{
StatusMessages.Remove(vm);
}
}
catch
{
}
},
CancellationToken.None,
TaskCreationOptions.None,
_globalLogPageContext.Scheduler);
}
public static void SetHostHwnd(ulong hostHwnd) => _hostingHwnd = hostHwnd;
public void DebugLog(string message)
{
#if DEBUG
this.ProcessLogMessage(new LogMessage(message));
#endif
}
public void Log(string message)
{
this.ProcessLogMessage(new LogMessage(message));
}
}

View File

@@ -1,29 +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.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
public class CommandPalettePageViewModelFactory
: IPageViewModelFactoryService
{
private readonly TaskScheduler _scheduler;
public CommandPalettePageViewModelFactory(TaskScheduler scheduler)
{
_scheduler = scheduler;
}
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host)
{
return page switch
{
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
IContentPage contentPage => new CommandPaletteContentPageViewModel(contentPage, _scheduler, host),
_ => null,
};
}
}

View File

@@ -1,11 +1,10 @@
// Copyright (c) Microsoft Corporation
// 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 ManagedCommon;
using Microsoft.CmdPal.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
@@ -43,7 +42,13 @@ public sealed class CommandProviderWrapper
public bool IsActive { get; private set; }
public string ProviderId => string.IsNullOrEmpty(Extension?.ExtensionUniqueId) ? Id : Extension.ExtensionUniqueId;
public string ProviderId
{
get
{
return string.IsNullOrEmpty(Extension?.ExtensionUniqueId) ? Id : Extension.ExtensionUniqueId;
}
}
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread)
{
@@ -81,8 +86,8 @@ public sealed class CommandProviderWrapper
throw new ArgumentException("You forgot to start the extension. This is a CmdPal error - we need to make sure to call StartExtensionAsync");
}
IExtension? extensionImpl = extension.GetExtensionObject();
object? providerObject = extensionImpl?.GetProvider(ProviderType.Commands);
var extensionImpl = extension.GetExtensionObject();
var providerObject = extensionImpl?.GetProvider(ProviderType.Commands);
if (providerObject is not ICommandProvider provider)
{
throw new ArgumentException("extension didn't actually implement ICommandProvider");
@@ -92,7 +97,7 @@ public sealed class CommandProviderWrapper
try
{
ICommandProvider model = _commandProvider.Unsafe!;
var model = _commandProvider.Unsafe!;
// Hook the extension back into us
model.InitializeWithHost(ExtensionHost);
@@ -125,7 +130,7 @@ public sealed class CommandProviderWrapper
return;
}
SettingsModel settings = serviceProvider.GetService<SettingsModel>()!;
var settings = serviceProvider.GetService<SettingsModel>()!;
IsActive = GetProviderSettings(settings).IsEnabled;
if (!IsActive)
@@ -138,7 +143,7 @@ public sealed class CommandProviderWrapper
try
{
ICommandProvider model = _commandProvider.Unsafe!;
var model = _commandProvider.Unsafe!;
Task<ICommandItem[]> t = new(model.TopLevelCommands);
t.Start();
@@ -171,29 +176,28 @@ public sealed class CommandProviderWrapper
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
{
SettingsModel settings = serviceProvider.GetService<SettingsModel>()!;
ProviderSettings providerSettings = GetProviderSettings(settings);
var settings = serviceProvider.GetService<SettingsModel>()!;
var providerSettings = GetProviderSettings(settings);
TopLevelViewModel MakeAndAdd(ICommandItem? i, bool fallback)
Func<ICommandItem?, bool, TopLevelViewModel> makeAndAdd = (ICommandItem? i, bool fallback) =>
{
CommandItemViewModel commandItemViewModel = new(new(i), pageContext);
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settings, providerSettings, serviceProvider);
topLevelViewModel.InitializeProperties();
return topLevelViewModel;
}
};
if (commands != null)
{
TopLevelItems = commands
.Select(c => MakeAndAdd(c, false))
.Select(c => makeAndAdd(c, false))
.ToArray();
}
if (fallbacks != null)
{
FallbackItems = fallbacks
.Select(c => MakeAndAdd(c, true))
.Select(c => makeAndAdd(c, true))
.ToArray();
}
}

View File

@@ -1,13 +1,12 @@
// Copyright (c) Microsoft Corporation
// 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 ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread)
{
@@ -23,7 +22,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
private void UnsafeInitializeProperties()
{
ICommandSettings? model = _model.Unsafe;
var model = _model.Unsafe;
if (model == null)
{
return;

View File

@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandViewModel : ExtensionObjectViewModel
{
@@ -43,7 +43,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel
return;
}
ICommand? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return;
@@ -66,13 +66,13 @@ public partial class CommandViewModel : ExtensionObjectViewModel
FastInitializeProperties();
}
ICommand? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return;
}
IIconInfo ico = model.Icon;
var ico = model.Icon;
if (ico != null)
{
Icon = new(ico);
@@ -97,7 +97,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel
protected void FetchProperty(string propertyName)
{
ICommand? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return; // throw?
@@ -109,7 +109,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel
Name = model.Name;
break;
case nameof(Icon):
IIconInfo iconInfo = model.Icon;
var iconInfo = model.Icon;
Icon = new(iconInfo);
Icon.InitializeProperties();
break;
@@ -124,7 +124,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel
Icon = new(null); // necessary?
ICommand? model = Model.Unsafe;
var model = Model.Unsafe;
if (model != null)
{
model.PropChanged -= Model_PropChanged;

View File

@@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

View File

@@ -1,8 +1,16 @@
// Copyright (c) Microsoft Corporation
// 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.CodeAnalysis;
using System.IO.Compression;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.CmdPal.Common;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -13,13 +13,13 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase
{
public CreatedExtensionForm(string name, string displayName, string path)
{
static string SerializeString(string? s) => JsonSerializer.Serialize(s, JsonSerializationContext.Default.String);
var serializeString = (string? s) => JsonSerializer.Serialize(s, JsonSerializationContext.Default.String);
TemplateJson = CardTemplate;
DataJson = $$"""
{
"name": {{SerializeString(name)}},
"directory": {{SerializeString(path)}},
"displayName": {{SerializeString(displayName)}}
"name": {{serializeString(name)}},
"directory": {{serializeString(path)}},
"displayName": {{serializeString(displayName)}}
}
""";
_name = name;
@@ -29,13 +29,13 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase
public override ICommandResult SubmitForm(string inputs, string data)
{
JsonObject? dataInput = JsonNode.Parse(data)?.AsObject();
var dataInput = JsonNode.Parse(data)?.AsObject();
if (dataInput == null)
{
return CommandResult.KeepOpen();
}
string verb = dataInput["x"]?.AsValue()?.ToString() ?? string.Empty;
var verb = dataInput["x"]?.AsValue()?.ToString() ?? string.Empty;
return verb switch
{
"sln" => OpenSolution(),
@@ -45,23 +45,23 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase
};
}
private CommandResult OpenSolution()
private ICommandResult OpenSolution()
{
string[] parts = [_path, _name, $"{_name}.sln"];
string pathToSolution = Path.Combine(parts);
var pathToSolution = Path.Combine(parts);
ShellHelpers.OpenInShell(pathToSolution);
return CommandResult.Hide();
}
private CommandResult OpenDirectory()
private ICommandResult OpenDirectory()
{
string[] parts = [_path, _name];
string pathToDir = Path.Combine(parts);
var pathToDir = Path.Combine(parts);
ShellHelpers.OpenInShell(pathToDir);
return CommandResult.Hide();
}
private CommandResult CreateNew()
private ICommandResult CreateNew()
{
RaiseFormSubmit(null);
return CommandResult.KeepOpen();

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.

View File

@@ -1,7 +1,8 @@
// Copyright (c) Microsoft Corporation
// 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 Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;

View File

@@ -1,9 +1,8 @@
// Copyright (c) Microsoft Corporation
// 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.Specialized;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -11,7 +10,7 @@ namespace Microsoft.CmdPal.UI.ViewModels.Commands;
public partial class LogMessagesPage : ListPage
{
private readonly List<IListItem> _listItems = [];
private readonly List<IListItem> _listItems = new();
public LogMessagesPage()
{
@@ -25,13 +24,14 @@ public partial class LogMessagesPage : ListPage
{
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
{
foreach (object? item in e.NewItems)
foreach (var item in e.NewItems)
{
if (item is LogMessageViewModel logMessageViewModel)
{
ListItem li = new ListItem(new NoOpCommand())
var li = new ListItem(new NoOpCommand())
{
Title = logMessageViewModel.Message,
Subtitle = logMessageViewModel.ExtensionPfn,
};
_listItems.Insert(0, li);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -6,8 +6,8 @@ using System.Collections.Immutable;
using System.Collections.Specialized;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Ext.Apps;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.DependencyInjection;
@@ -40,7 +40,7 @@ public partial class MainListPage : DynamicListPage,
// The all apps page will kick off a BG thread to start loading apps.
// We just want to know when it is done.
AllAppsPage allApps = AllAppsCommandProvider.Page;
var allApps = AllAppsCommandProvider.Page;
allApps.PropChanged += (s, p) =>
{
if (p.PropertyName == nameof(allApps.IsLoading))
@@ -52,7 +52,7 @@ public partial class MainListPage : DynamicListPage,
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
WeakReferenceMessenger.Default.Register<UpdateFallbackItemsMessage>(this);
SettingsModel settings = _serviceProvider.GetService<SettingsModel>()!;
var settings = _serviceProvider.GetService<SettingsModel>()!;
settings.SettingsChanged += SettingsChangedHandler;
HotReloadSettings(settings);
@@ -86,7 +86,7 @@ public partial class MainListPage : DynamicListPage,
{
try
{
string currentSearchText = SearchText;
var currentSearchText = SearchText;
UpdateSearchText(currentSearchText, currentSearchText);
}
catch (Exception e)
@@ -122,14 +122,14 @@ public partial class MainListPage : DynamicListPage,
// Handle changes to the filter text here
if (!string.IsNullOrEmpty(SearchText))
{
AliasManager aliases = _serviceProvider.GetService<AliasManager>()!;
var aliases = _serviceProvider.GetService<AliasManager>()!;
if (aliases.CheckAlias(newSearch))
{
return;
}
}
System.Collections.ObjectModel.ObservableCollection<TopLevelViewModel> commands = _tlcManager.TopLevelCommands;
var commands = _tlcManager.TopLevelCommands;
lock (commands)
{
UpdateFallbacks(newSearch, commands.ToImmutableArray());
@@ -179,11 +179,11 @@ public partial class MainListPage : DynamicListPage,
// fire and forget
_ = Task.Run(() =>
{
bool needsToUpdate = false;
var needsToUpdate = false;
foreach (TopLevelViewModel command in commands)
foreach (var command in commands)
{
bool changedVisibility = command.SafeUpdateFallbackTextSynchronous(newSearch);
var changedVisibility = command.SafeUpdateFallbackTextSynchronous(newSearch);
needsToUpdate = needsToUpdate || changedVisibility;
}
@@ -196,8 +196,8 @@ public partial class MainListPage : DynamicListPage,
private bool ActuallyLoading()
{
TopLevelCommandManager tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
AllAppsPage allApps = AllAppsCommandProvider.Page;
var tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
var allApps = AllAppsCommandProvider.Page;
return allApps.IsLoading || tlcManager.IsLoading;
}
@@ -206,26 +206,26 @@ public partial class MainListPage : DynamicListPage,
// _always_ show up first.
private int ScoreTopLevelItem(string query, IListItem topLevelOrAppItem)
{
string title = topLevelOrAppItem.Title;
var title = topLevelOrAppItem.Title;
if (string.IsNullOrWhiteSpace(title))
{
return 0;
}
bool isWhiteSpace = string.IsNullOrWhiteSpace(query);
var isWhiteSpace = string.IsNullOrWhiteSpace(query);
bool isFallback = false;
bool isAliasSubstringMatch = false;
bool isAliasMatch = false;
string id = IdForTopLevelOrAppItem(topLevelOrAppItem);
var isFallback = false;
var isAliasSubstringMatch = false;
var isAliasMatch = false;
var id = IdForTopLevelOrAppItem(topLevelOrAppItem);
string extensionDisplayName = string.Empty;
var extensionDisplayName = string.Empty;
if (topLevelOrAppItem is TopLevelViewModel topLevel)
{
isFallback = topLevel.IsFallback;
if (topLevel.HasAlias)
{
string alias = topLevel.AliasText;
var alias = topLevel.AliasText;
isAliasMatch = alias == query;
isAliasSubstringMatch = isAliasMatch || alias.StartsWith(query, StringComparison.CurrentCultureIgnoreCase);
}
@@ -243,48 +243,49 @@ public partial class MainListPage : DynamicListPage,
// Title:
// * whitespace query: 1 point
// * otherwise full weight match
int nameMatch = isWhiteSpace ?
var nameMatch = isWhiteSpace ?
(title.Contains(query) ? 1 : 0) :
StringMatcher.FuzzySearch(query, title).Score;
// Subtitle:
// * whitespace query: 1/2 point
// * otherwise ~half weight match. Minus a bit, because subtitles tend to be longer
double descriptionMatch = isWhiteSpace ?
var descriptionMatch = isWhiteSpace ?
(topLevelOrAppItem.Subtitle.Contains(query) ? .5 : 0) :
(StringMatcher.FuzzySearch(query, topLevelOrAppItem.Subtitle).Score - 4) / 2.0;
// Extension title: despite not being visible, give the extension name itself some weight
// * whitespace query: 0 points
// * otherwise more weight than a subtitle, but not much
double extensionTitleMatch = isWhiteSpace ? 0 : StringMatcher.FuzzySearch(query, extensionDisplayName).Score / 1.5;
var extensionTitleMatch = isWhiteSpace ? 0 : StringMatcher.FuzzySearch(query, extensionDisplayName).Score / 1.5;
double[] scores = new[]
var scores = new[]
{
nameMatch,
descriptionMatch,
isFallback ? 1 : 0, // Always give fallbacks a chance
isFallback ? 1 : 0, // Always give fallbacks a chance...
};
double max = scores.Max();
var max = scores.Max();
// _Add_ the extension name. This will bubble items that match both
// title and extension name up above ones that just match title.
// e.g. "git" will up-weight "GitHub searches" from the GitHub extension
// above "git" from "whatever"
max += extensionTitleMatch;
max = max + extensionTitleMatch;
double matchSomething = max
// ... but downweight them
var matchSomething = (max / (isFallback ? 3 : 1))
+ (isAliasMatch ? 9001 : (isAliasSubstringMatch ? 1 : 0));
// If we matched title, subtitle, or alias (something real), then
// here we add the recent command weight boost
//
// Otherwise something like `x` will still match everything you've run before
double finalScore = matchSomething;
var finalScore = matchSomething;
if (matchSomething > 0)
{
RecentCommandsManager history = _serviceProvider.GetService<AppStateModel>()!.RecentCommands;
int recentWeightBoost = history.GetCommandHistoryWeight(id);
var history = _serviceProvider.GetService<AppStateModel>()!.RecentCommands;
var recentWeightBoost = history.GetCommandHistoryWeight(id);
finalScore += recentWeightBoost;
}
@@ -293,9 +294,9 @@ public partial class MainListPage : DynamicListPage,
public void UpdateHistory(IListItem topLevelOrAppItem)
{
string id = IdForTopLevelOrAppItem(topLevelOrAppItem);
AppStateModel state = _serviceProvider.GetService<AppStateModel>()!;
RecentCommandsManager history = state.RecentCommands;
var id = IdForTopLevelOrAppItem(topLevelOrAppItem);
var state = _serviceProvider.GetService<AppStateModel>()!;
var history = state.RecentCommands;
history.AddHistoryItem(id);
AppStateModel.SaveState(state);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -97,15 +97,15 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
public override CommandResult SubmitForm(string payload)
{
JsonObject? formInput = JsonNode.Parse(payload)?.AsObject();
var formInput = JsonNode.Parse(payload)?.AsObject();
if (formInput == null)
{
return CommandResult.KeepOpen();
}
string extensionName = formInput["ExtensionName"]?.AsValue()?.ToString() ?? string.Empty;
string displayName = formInput["DisplayName"]?.AsValue()?.ToString() ?? string.Empty;
string outputPath = formInput["OutputPath"]?.AsValue()?.ToString() ?? string.Empty;
var extensionName = formInput["ExtensionName"]?.AsValue()?.ToString() ?? string.Empty;
var displayName = formInput["DisplayName"]?.AsValue()?.ToString() ?? string.Empty;
var outputPath = formInput["OutputPath"]?.AsValue()?.ToString() ?? string.Empty;
_creatingMessage.State = MessageState.Info;
_creatingMessage.Message = _creatingText;
@@ -133,10 +133,10 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
private void CreateExtension(string extensionName, string newDisplayName, string outputPath)
{
string newGuid = Guid.NewGuid().ToString();
var newGuid = Guid.NewGuid().ToString();
// Unzip `template.zip` to a temp dir:
string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
var tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
// Does the output path exist?
if (!Directory.Exists(outputPath))
@@ -144,13 +144,13 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
Directory.CreateDirectory(outputPath);
}
string assetsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), "Microsoft.CmdPal.UI.ViewModels\\Assets\\template.zip");
var assetsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), "Microsoft.CmdPal.UI.ViewModels\\Assets\\template.zip");
ZipFile.ExtractToDirectory(assetsPath, tempDir);
string[] files = Directory.GetFiles(tempDir, "*", SearchOption.AllDirectories);
foreach (string file in files)
var files = Directory.GetFiles(tempDir, "*", SearchOption.AllDirectories);
foreach (var file in files)
{
string text = File.ReadAllText(file);
var text = File.ReadAllText(file);
// Replace all the instances of `FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF` with a new random guid:
text = text.Replace("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", newGuid);
@@ -162,9 +162,9 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
text = text.Replace("TemplateDisplayName", newDisplayName);
// We're going to write the file to the same relative location in the output path
string relativePath = Path.GetRelativePath(tempDir, file);
var relativePath = Path.GetRelativePath(tempDir, file);
string newFileName = Path.Combine(outputPath, relativePath);
var newFileName = Path.Combine(outputPath, relativePath);
// if the file name had `TemplateCmdPalExtension` in it, replace it with `extensionName`
newFileName = newFileName.Replace("TemplateCmdPalExtension", extensionName);

View File

@@ -1,7 +1,13 @@
// Copyright (c) Microsoft Corporation
// 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.CodeAnalysis;
using System.IO.Compression;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.

View File

@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation
// 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 CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

View File

@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation
// 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 CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

View File

@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation
// 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 CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;

View File

@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReference<IPageContext> context) :
ExtensionObjectViewModel(context)
@@ -24,7 +24,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen
public override void InitializeProperties()
{
IConfirmationArgs? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return;

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -7,9 +7,8 @@ using AdaptiveCards.ObjectModel.WinUI3;
using AdaptiveCards.Templating;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Windows.Data.Json;
@@ -44,8 +43,8 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
try
{
AdaptiveCardTemplate template = new AdaptiveCardTemplate(templateJson);
string cardJson = template.Expand(dataJson);
var template = new AdaptiveCardTemplate(templateJson);
var cardJson = template.Expand(dataJson);
card = AdaptiveCard.FromJsonString(cardJson);
return true;
}
@@ -59,7 +58,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
public override void InitializeProperties()
{
IFormContent? model = _formModel.Unsafe;
var model = _formModel.Unsafe;
if (model is null)
{
return;
@@ -69,14 +68,14 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
StateJson = model.StateJson;
DataJson = model.DataJson;
if (TryBuildCard(TemplateJson, DataJson, out AdaptiveCardParseResult? builtCard, out Exception? renderingError))
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError))
{
Card = builtCard;
UpdateProperty(nameof(Card));
return;
}
string errorPayload = $$"""
var errorPayload = $$"""
{
"error_message": {{Serialize(renderingError!.Message)}},
"error_stack": {{Serialize(renderingError.StackTrace)}},
@@ -86,7 +85,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
}
""";
if (TryBuildCard(ErrorCardJson, errorPayload, out AdaptiveCardParseResult? errorCard, out Exception? _))
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _))
{
Card = errorCard;
UpdateProperty(nameof(Card));
@@ -107,17 +106,17 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
if (action is AdaptiveSubmitAction or AdaptiveExecuteAction)
{
// Get the data and inputs
string dataString = (action as AdaptiveSubmitAction)?.DataJson.Stringify() ?? string.Empty;
string inputString = inputs.Stringify();
var dataString = (action as AdaptiveSubmitAction)?.DataJson.Stringify() ?? string.Empty;
var inputString = inputs.Stringify();
_ = Task.Run(() =>
{
try
{
IFormContent model = _formModel.Unsafe!;
var model = _formModel.Unsafe!;
if (model != null)
{
ICommandResult result = model.SubmitForm(inputString, dataString);
var result = model.SubmitForm(inputString, dataString);
WeakReferenceMessenger.Default.Send<HandleCommandResultMessage>(new(new(result)));
}
}

View File

@@ -1,9 +1,8 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
@@ -19,7 +18,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe
public override void InitializeProperties()
{
IMarkdownContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return;
@@ -35,7 +34,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe
{
try
{
string propName = args.PropertyName;
var propName = args.PropertyName;
FetchProperty(propName);
}
catch (Exception ex)
@@ -46,7 +45,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe
protected void FetchProperty(string propertyName)
{
IMarkdownContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return; // throw?
@@ -65,7 +64,7 @@ public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakRe
protected override void UnsafeCleanup()
{
base.UnsafeCleanup();
IMarkdownContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model != null)
{
model.PropChanged -= Model_PropChanged;

View File

@@ -7,12 +7,12 @@ using System.Diagnostics.CodeAnalysis;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
@@ -47,7 +47,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
public ContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
public ContentPageViewModel(IContentPage model, TaskScheduler scheduler, CommandPaletteHost host)
: base(model, scheduler, host)
{
_model = new(model);
@@ -62,11 +62,11 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
List<ContentViewModel> newContent = [];
try
{
IContent[] newItems = _model.Unsafe!.GetContent();
var newItems = _model.Unsafe!.GetContent();
foreach (IContent? item in newItems)
foreach (var item in newItems)
{
ContentViewModel? viewModel = ViewModelFromContent(item, PageContext);
var viewModel = ViewModelFromContent(item, PageContext);
if (viewModel != null)
{
viewModel.InitializeProperties();
@@ -80,7 +80,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
throw;
}
bool oneContent = newContent.Count == 1;
var oneContent = newContent.Count == 1;
newContent.ForEach(c => c.OnlyControlOnPage = oneContent);
// Now, back to a UI thread to update the observable collection
@@ -91,19 +91,23 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
});
}
public virtual ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
public static ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
{
// The core ContentPageViewModel doesn't actually handle any content,
// so we just return null here.
// The real content is handled by the derived class CommandPaletteContentPageViewModel
return null;
ContentViewModel? viewModel = content switch
{
IFormContent form => new ContentFormViewModel(form, context),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
ITreeContent tree => new ContentTreeViewModel(tree, context),
_ => null,
};
return viewModel;
}
public override void InitializeProperties()
{
base.InitializeProperties();
IContentPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model == null)
{
return; // throw?
@@ -111,15 +115,15 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
Commands = model.Commands
.ToList()
.Select<IContextItem, IContextItemViewModel>(item =>
.Select(item =>
{
if (item is CommandContextItem contextItem)
{
return new CommandContextItemViewModel(contextItem, PageContext);
return new CommandContextItemViewModel(contextItem, PageContext) as IContextItemViewModel;
}
else
{
return new SeparatorContextItemViewModel();
return new SeparatorContextItemViewModel() as IContextItemViewModel;
}
})
.ToList();
@@ -132,7 +136,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
contextItem.InitializeProperties();
});
IDetails extensionDetails = model.Details;
var extensionDetails = model.Details;
if (extensionDetails != null)
{
Details = new(extensionDetails, PageContext);
@@ -155,7 +159,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
base.FetchProperty(propertyName);
IContentPage? model = this._model.Unsafe;
var model = this._model.Unsafe;
if (model == null)
{
return; // throw?
@@ -165,10 +169,10 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
case nameof(Commands):
IContextItem[] more = model.Commands;
var more = model.Commands;
if (more != null)
{
List<IContextItemViewModel> newContextMenu = more
var newContextMenu = more
.ToList()
.Select(item =>
{
@@ -178,7 +182,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
}
else
{
return new SeparatorContextItemViewModel();
return new SeparatorContextItemViewModel() as IContextItemViewModel;
}
})
.ToList();
@@ -215,7 +219,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
break;
case nameof(Details):
IDetails extensionDetails = model.Details;
var extensionDetails = model.Details;
Details = extensionDetails != null ? new(extensionDetails, PageContext) : null;
UpdateDetails();
break;
@@ -277,14 +281,14 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
Commands.Clear();
foreach (ContentViewModel item in Content)
foreach (var item in Content)
{
item.SafeCleanup();
}
Content.Clear();
IContentPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model != null)
{
model.ItemsChanged -= Model_ItemsChanged;

View File

@@ -1,10 +1,9 @@
// Copyright (c) Microsoft Corporation
// 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.ObjectModel;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -29,16 +28,16 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
public override void InitializeProperties()
{
ITreeContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return;
}
IContent root = model.RootContent;
var root = model.RootContent;
if (root != null)
{
RootContent = ViewModelFromContent(root, PageContext);
RootContent = ContentPageViewModel.ViewModelFromContent(root, PageContext);
RootContent?.InitializeProperties();
UpdateProperty(nameof(RootContent));
UpdateProperty(nameof(Root));
@@ -49,20 +48,6 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
model.ItemsChanged += Model_ItemsChanged;
}
// Theoretically, we should unify this with the one in CommandPalettePageViewModelFactory
// and maybe just have a ContentViewModelFactory or something
public ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
{
ContentViewModel? viewModel = content switch
{
IFormContent form => new ContentFormViewModel(form, context),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
ITreeContent tree => new ContentTreeViewModel(tree, context),
_ => null,
};
return viewModel;
}
// TODO: Does this need to hop to a _different_ thread, so that we don't block the extension while we're fetching?
private void Model_ItemsChanged(object sender, IItemsChangedEventArgs args) => FetchContent();
@@ -70,7 +55,7 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
{
try
{
string propName = args.PropertyName;
var propName = args.PropertyName;
FetchProperty(propName);
}
catch (Exception ex)
@@ -81,7 +66,7 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
protected void FetchProperty(string propertyName)
{
ITreeContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model == null)
{
return; // throw?
@@ -90,10 +75,10 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
switch (propertyName)
{
case nameof(RootContent):
IContent? root = model.RootContent;
var root = model.RootContent;
if (root != null)
{
RootContent = ViewModelFromContent(root, PageContext);
RootContent = ContentPageViewModel.ViewModelFromContent(root, PageContext);
}
else
{
@@ -114,11 +99,11 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
List<ContentViewModel> newContent = [];
try
{
IContent[] newItems = Model.Unsafe!.GetChildren();
var newItems = Model.Unsafe!.GetChildren();
foreach (IContent? item in newItems)
foreach (var item in newItems)
{
ContentViewModel? viewModel = ViewModelFromContent(item, PageContext);
var viewModel = ContentPageViewModel.ViewModelFromContent(item, PageContext);
if (viewModel != null)
{
viewModel.InitializeProperties();
@@ -146,13 +131,13 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
{
base.UnsafeCleanup();
RootContent?.SafeCleanup();
foreach (ContentViewModel item in Children)
foreach (var item in Children)
{
item.SafeCleanup();
}
Children.Clear();
ITreeContent? model = Model.Unsafe;
var model = Model.Unsafe;
if (model != null)
{
model.PropChanged -= Model_PropChanged;

View File

@@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation
// 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.
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public abstract partial class ContentViewModel(WeakReference<IPageContext> context) :
ExtensionObjectViewModel(context)

View File

@@ -1,16 +1,17 @@
// Copyright (c) Microsoft Corporation
// 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.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Diagnostics.Utilities;
using Windows.System;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ContextMenuViewModel : ObservableObject,
IRecipient<UpdateCommandBarMessage>,
@@ -21,8 +22,15 @@ public partial class ContextMenuViewModel : ObservableObject,
get => field;
set
{
if (field != null)
{
field.PropertyChanged -= SelectedItemPropertyChanged;
}
field = value;
UpdateContextItems();
SetSelectedItem(value);
OnPropertyChanged(nameof(SelectedItem));
}
}
@@ -60,6 +68,33 @@ public partial class ContextMenuViewModel : ObservableObject,
OnPropertyChanged(nameof(FilterOnTop));
}
private void SetSelectedItem(ICommandBarContext? value)
{
if (value != null)
{
value.PropertyChanged += SelectedItemPropertyChanged;
}
else
{
if (SelectedItem != null)
{
SelectedItem.PropertyChanged -= SelectedItemPropertyChanged;
}
}
UpdateContextItems();
}
private void SelectedItemPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(SelectedItem.HasMoreCommands):
UpdateContextItems();
break;
}
}
public void UpdateContextItems()
{
if (SelectedItem != null)
@@ -98,11 +133,11 @@ public partial class ContextMenuViewModel : ObservableObject,
return;
}
IEnumerable<CommandContextItemViewModel> commands = CurrentContextMenu
var commands = CurrentContextMenu
.OfType<CommandContextItemViewModel>()
.Where(c => c.ShouldBeVisible);
IEnumerable<CommandContextItemViewModel> newResults = ListHelpers.FilterList<CommandContextItemViewModel>(commands, searchText, ScoreContextCommand);
var newResults = ListHelpers.FilterList<CommandContextItemViewModel>(commands, searchText, ScoreContextCommand);
ListHelpers.InPlaceUpdateList(FilteredItems, newResults);
}
@@ -118,9 +153,9 @@ public partial class ContextMenuViewModel : ObservableObject,
return 0;
}
MatchResult nameMatch = StringMatcher.FuzzySearch(query, item.Title);
var nameMatch = StringMatcher.FuzzySearch(query, item.Title);
MatchResult descriptionMatch = StringMatcher.FuzzySearch(query, item.Subtitle);
var descriptionMatch = StringMatcher.FuzzySearch(query, item.Subtitle);
return new[] { nameMatch.Score, (descriptionMatch.Score - 4) / 2, 0 }.Max();
}
@@ -150,12 +185,12 @@ public partial class ContextMenuViewModel : ObservableObject,
public ContextKeybindingResult? CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key)
{
Dictionary<KeyChord, CommandContextItemViewModel> keybindings = Keybindings();
var keybindings = Keybindings();
if (keybindings != null)
{
// Does the pressed key match any of the keybindings?
KeyChord pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out CommandContextItemViewModel? item))
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (keybindings.TryGetValue(pressedKeyChord, out var item))
{
return InvokeCommand(item);
}

View File

@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class DetailsCommandsViewModel(
IDetailsElement _detailsElement,
@@ -21,7 +21,7 @@ public partial class DetailsCommandsViewModel(
public override void InitializeProperties()
{
base.InitializeProperties();
IDetailsCommands? model = _dataModel.Unsafe;
var model = _dataModel.Unsafe;
if (model == null)
{
return;
@@ -31,7 +31,7 @@ public partial class DetailsCommandsViewModel(
.Commands?
.Select(c =>
{
CommandViewModel vm = new CommandViewModel(c, PageContext);
var vm = new CommandViewModel(c, PageContext);
vm.InitializeProperties();
return vm;
})

View File

@@ -1,8 +1,11 @@
// Copyright (c) Microsoft Corporation
// 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.
namespace Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
public abstract partial class DetailsDataViewModel(IPageContext context) : ExtensionObjectViewModel(context)
{

View File

@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation
// 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.CmdPal.Core.ViewModels.Models;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
namespace Microsoft.CmdPal.UI.ViewModels;
public abstract partial class DetailsElementViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
{
@@ -15,7 +15,7 @@ public abstract partial class DetailsElementViewModel(IDetailsElement _detailsEl
public override void InitializeProperties()
{
IDetailsElement? model = _model.Unsafe;
var model = _model.Unsafe;
if (model == null)
{
return;

Some files were not shown because too many files have changed in this diff Show More