[NewUtility]Advanced Paste (#23)
Advanced Paste V1 implementation --------- Co-authored-by: Stefan Markovic <stefan@janeasystems.com> Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Jordi Adoumie <98557455+joadoumie@users.noreply.github.com> Co-authored-by: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -47,6 +47,7 @@ body:
|
||||
multiple: true
|
||||
options:
|
||||
- General
|
||||
- Advanced Paste
|
||||
- Always on Top
|
||||
- Awake
|
||||
- ColorPicker
|
||||
@ -64,7 +65,6 @@ body:
|
||||
- Keyboard Manager
|
||||
- Mouse Utilities
|
||||
- Mouse Without Borders
|
||||
- Paste as Plain Text
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
|
2
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
@ -21,6 +21,7 @@ body:
|
||||
label: Utility with translation issue
|
||||
options:
|
||||
- General
|
||||
- Advanced Paste
|
||||
- Always on Top
|
||||
- Awake
|
||||
- ColorPicker
|
||||
@ -38,7 +39,6 @@ body:
|
||||
- Keyboard Manager
|
||||
- Mouse Utilities
|
||||
- Mouse Without Borders
|
||||
- Paste as Plain Text
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
|
1
.github/actions/spell-check/allow/code.txt
vendored
@ -25,6 +25,7 @@ WHITEONBLACK
|
||||
|
||||
AYUV
|
||||
bak
|
||||
Bcl
|
||||
exa
|
||||
exabyte
|
||||
Gbits
|
||||
|
3
.github/actions/spell-check/allow/names.txt
vendored
@ -10,7 +10,6 @@ markdownpreviewhandler
|
||||
mousewithoutborders
|
||||
mwb
|
||||
oobe
|
||||
pasteplain
|
||||
poweraccent
|
||||
powerlauncher
|
||||
POWEROCR
|
||||
@ -144,6 +143,7 @@ Controlz
|
||||
cortana
|
||||
fancymouse
|
||||
firefox
|
||||
gpt
|
||||
Inkscape
|
||||
Markdig
|
||||
modernwpf
|
||||
@ -152,6 +152,7 @@ mozilla
|
||||
mspaint
|
||||
Newtonsoft
|
||||
onenote
|
||||
openai
|
||||
Quickime
|
||||
regedit
|
||||
roslyn
|
||||
|
1
.github/actions/spell-check/expect.txt
vendored
@ -894,6 +894,7 @@ MINIMIZEBOX
|
||||
MINIMIZEEND
|
||||
MINIMIZESTART
|
||||
miniz
|
||||
Mip
|
||||
Miracast
|
||||
mjpg
|
||||
mkdn
|
||||
|
@ -45,7 +45,9 @@
|
||||
"PowerToys.PowerOCR.dll",
|
||||
"PowerToys.PowerOCR.exe",
|
||||
|
||||
"PowerToys.PastePlainModuleInterface.dll",
|
||||
"PowerToys.AdvancedPasteModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
|
||||
|
||||
"PowerToys.AwakeModuleInterface.dll",
|
||||
"PowerToys.Awake.exe",
|
||||
@ -303,6 +305,7 @@
|
||||
"MessagePack.Annotations.dll",
|
||||
"MessagePack.dll",
|
||||
"Nerdbank.Streams.dll",
|
||||
"WinUI3Apps\\ReverseMarkdown.dll",
|
||||
"WinUI3Apps\\SharpCompress.dll",
|
||||
"WinUI3Apps\\ZstdSharp.dll",
|
||||
"ColorCode.Core.dll",
|
||||
|
@ -4,6 +4,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
|
||||
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.12" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.0.240109" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.0.240109" />
|
||||
@ -20,6 +21,7 @@
|
||||
<PackageVersion Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" />
|
||||
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
||||
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.11.57" />
|
||||
<PackageVersion Include="hyjiacan.pinyin4net" Version="4.1.1" />
|
||||
<PackageVersion Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0.2" />
|
||||
<PackageVersion Include="LazyCache" Version="2.4.0" />
|
||||
@ -56,6 +58,7 @@
|
||||
<PackageVersion Include="NLog" Version="5.0.4" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.14.24" />
|
||||
|
@ -1297,6 +1297,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
- Appium.WebDriver 4.4.5
|
||||
- Azure.AI.OpenAI 1.0.0-beta.12
|
||||
- CommunityToolkit.Mvvm 8.2.2
|
||||
- CommunityToolkit.WinUI.Animations 8.0.240109
|
||||
- CommunityToolkit.WinUI.Collections 8.0.240109
|
||||
@ -1341,6 +1342,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- MSTest.TestFramework 3.2.0
|
||||
- NLog.Extensions.Logging 5.3.8
|
||||
- NLog.Schema 5.2.8
|
||||
- ReverseMarkdown 4.1.0
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.37.2
|
||||
- StreamJsonRpc 2.14.24
|
||||
|
@ -512,9 +512,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI.UnitTests", "src\modules\MouseUtils\MouseJumpUI.UnitTests\MouseJumpUI.UnitTests.csproj", "{D9C5DE64-6849-4278-91AD-9660AECF2876}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pasteplain", "pasteplain", "{9873BA05-4C41-4819-9283-CF45D795431B}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdvancedPaste", "AdvancedPaste", "{9873BA05-4C41-4819-9283-CF45D795431B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PastePlainModuleInterface", "src\modules\pasteplain\PastePlainModuleInterface\PastePlainModuleInterface.vcxproj", "{FC373B24-3293-453C-AAF5-CF2909DCEE6A}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvancedPasteModuleInterface", "src\modules\AdvancedPaste\AdvancedPasteModuleInterface\AdvancedPasteModuleInterface.vcxproj", "{FC373B24-3293-453C-AAF5-CF2909DCEE6A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}"
|
||||
EndProject
|
||||
@ -566,6 +566,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithContextMenu",
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLib", "src\modules\FileLocksmith\FileLocksmithLib\FileLocksmithLib.vcxproj", "{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdvancedPaste", "src\modules\AdvancedPaste\AdvancedPaste\AdvancedPaste.csproj", "{C32D254F-7597-4CBE-BF74-D922D81CDF29}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hosts", "src\modules\Hosts\Hosts\Hosts.csproj", "{02DD46D3-F761-47D9-8894-2D6DA0124650}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreview", "src\modules\registrypreview\RegistryPreview\RegistryPreview.csproj", "{8E23E173-7127-4A5F-9F93-3049F2B68047}"
|
||||
@ -2499,6 +2501,24 @@ Global
|
||||
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x64.Build.0 = Release|x64
|
||||
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.ActiveCfg = Release|x64
|
||||
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.Build.0 = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.Build.0 = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x86.Build.0 = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Debug|x86.Deploy.0 = Debug|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.ActiveCfg = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.Build.0 = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x64.Deploy.0 = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x86.ActiveCfg = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x86.Build.0 = Release|x64
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29}.Release|x86.Deploy.0 = Release|x64
|
||||
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@ -2791,6 +2811,7 @@ Global
|
||||
{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}
|
||||
{C32D254F-7597-4CBE-BF74-D922D81CDF29} = {9873BA05-4C41-4819-9283-CF45D795431B}
|
||||
{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}
|
||||
|
BIN
doc/images/icons/AdvancedPaste.png
Normal file
After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 26 KiB |
BIN
doc/images/overview/AdvancedPaste_large.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
doc/images/overview/AdvancedPaste_small.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
doc/images/overview/Original/AdvancedPaste.png
Normal file
After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 13 KiB |
29
installer/PowerToysSetup/AdvancedPaste.wxs
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define AdvancedPasteAssetsFiles=?>
|
||||
<?define AdvancedPasteAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\AdvancedPaste\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="AdvancedPasteAssetsFolder" Name="AdvancedPaste" />
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="AdvancedPasteAssetsFolder" FileSource="$(var.AdvancedPasteAssetsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--AdvancedPasteAssetsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="AdvancedPasteComponentGroup">
|
||||
<Component Id="RemoveAdvancedPasteFolder" Guid="55AFE81D-F6BD-439A-A229-66AF5C360AB0" Directory="AdvancedPasteAssetsFolder" >
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveAdvancedPasteFolder" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderAdvancedPasteAssetsFolder" Directory="AdvancedPasteAssetsFolder" On="uninstall"/>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
@ -15,7 +15,7 @@
|
||||
<?define MeasureToolProjectName="MeasureTool"?>
|
||||
<?define HostsProjectName="Hosts"?>
|
||||
<?define MouseWithoutBordersProjectName="MouseWithoutBorders"?>
|
||||
<?define PastePlainProjectName="PastePlain"?>
|
||||
<?define AdvancedPasteProjectName="AdvancedPaste"?>
|
||||
<?define RegistryPreviewProjectName="RegistryPreview"?>
|
||||
<?define PeekProjectName="Peek"?>
|
||||
|
||||
|
@ -31,6 +31,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
<PostBuildEvent>
|
||||
call move /Y ..\..\..\AdvancedPaste.wxs.bk ..\..\..\AdvancedPaste.wxs
|
||||
call move /Y ..\..\..\Awake.wxs.bk ..\..\..\Awake.wxs
|
||||
call move /Y ..\..\..\BaseApplications.wxs.bk ..\..\..\BaseApplications.wxs
|
||||
call move /Y ..\..\..\ColorPicker.wxs.bk ..\..\..\ColorPicker.wxs
|
||||
@ -102,6 +103,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Compile Include="CustomDialogs\WixUI_PTInstallDir.wxs" />
|
||||
<Compile Include="Product.wxs" />
|
||||
|
||||
<Compile Include="AdvancedPaste.wxs" />
|
||||
<Compile Include="Awake.wxs" />
|
||||
<Compile Include="BaseApplications.wxs" />
|
||||
<Compile Include="ColorPicker.wxs" />
|
||||
|
@ -72,7 +72,7 @@
|
||||
<ComponentGroupRef Id="VideoConferenceComponentGroup" />
|
||||
<ComponentGroupRef Id="MouseWithoutBordersComponentGroup" />
|
||||
<ComponentGroupRef Id="EnvironmentVariablesComponentGroup" />
|
||||
|
||||
<ComponentGroupRef Id="AdvancedPasteComponentGroup" />
|
||||
<ComponentGroupRef Id="ResourcesComponentGroup" />
|
||||
<ComponentGroupRef Id="WindowsAppSDKComponentGroup" />
|
||||
<ComponentGroupRef Id="ToolComponentGroup" />
|
||||
@ -161,6 +161,9 @@
|
||||
<Custom Action="UnRegisterContextMenuPackages" Before="RemoveFiles">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UnsetAdvancedPasteAPIKey" Before="RemoveFiles">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UninstallCommandNotFound" Before="RemoveFiles">
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
@ -285,6 +288,14 @@
|
||||
DllEntry="UpgradeCommandNotFoundModuleCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="UnsetAdvancedPasteAPIKey"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UnsetAdvancedPasteAPIKeyCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="TelemetryLogInstallSuccess"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
|
@ -24,6 +24,10 @@ Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListNa
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WinUI3ApplicationsFiles -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps"""
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinUI3ApplicationsFiles"" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -regroot $registryroot"
|
||||
|
||||
#AdvancedPaste
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName AdvancedPasteAssetsFiles -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\AdvancedPaste"""
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""AdvancedPasteAssetsFiles"" -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -regroot $registryroot"
|
||||
|
||||
#AwakeFiles
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName AwakeImagesFiles -wxsFilePath $PSScriptRoot\Awake.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\Assets\Awake"""
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""AwakeImagesFiles"" -wxsFilePath $PSScriptRoot\Awake.wxs -regroot $registryroot"
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
#include <winrt/Windows.Security.Credentials.h>
|
||||
|
||||
#include <wtsapi32.h>
|
||||
#include <processthreadsapi.h>
|
||||
@ -433,6 +434,31 @@ UINT __stdcall RemoveWindowsServiceByName(std::wstring serviceName)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
UINT __stdcall UnsetAdvancedPasteAPIKeyCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
|
||||
try
|
||||
{
|
||||
winrt::Windows::Security::Credentials::PasswordVault vault;
|
||||
winrt::Windows::Security::Credentials::PasswordCredential cred;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UnsetAdvancedPasteAPIKey");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
cred = vault.Retrieve(L"https://platform.openai.com/api-keys", L"PowerToys_AdvancedPaste_OpenAIKey");
|
||||
vault.Remove(cred);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UninstallCommandNotFoundModuleCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
@ -1051,9 +1077,10 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
processes.resize(bytes / sizeof(processes[0]));
|
||||
|
||||
std::array<std::wstring_view, 31> processesToTerminate = {
|
||||
std::array<std::wstring_view, 32> processesToTerminate = {
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.Settings.exe",
|
||||
L"PowerToys.AdvancedPaste.exe",
|
||||
L"PowerToys.Awake.exe",
|
||||
L"PowerToys.FancyZones.exe",
|
||||
L"PowerToys.FancyZonesEditor.exe",
|
||||
|
@ -24,4 +24,5 @@ EXPORTS
|
||||
UninstallEmbeddedMSIXCA
|
||||
UninstallServicesCA
|
||||
UninstallCommandNotFoundModuleCA
|
||||
UpgradeCommandNotFoundModuleCA
|
||||
UpgradeCommandNotFoundModuleCA
|
||||
UnsetAdvancedPasteAPIKeyCA
|
||||
|
@ -48,6 +48,7 @@
|
||||
<PreBuildEvent>
|
||||
<Command>
|
||||
call cmd /C "copy ""$(ProjectDir)DepsFilesLists.h"" ""$(ProjectDir)DepsFilesLists.h.bk"""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\AdvancedPaste.wxs"" ""$(ProjectDir)..\PowerToysSetup\AdvancedPaste.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Awake.wxs"" ""$(ProjectDir)..\PowerToysSetup\Awake.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\BaseApplications.wxs"" ""$(ProjectDir)..\PowerToysSetup\BaseApplications.wxs.bk""""
|
||||
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs"" ""$(ProjectDir)..\PowerToysSetup\ColorPicker.wxs.bk""""
|
||||
|
@ -30,6 +30,7 @@ namespace Common.UI
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
Dashboard,
|
||||
AdvancedPaste,
|
||||
}
|
||||
|
||||
private static string SettingsWindowNameToString(SettingsWindow value)
|
||||
@ -74,6 +75,8 @@ namespace Common.UI
|
||||
return "EnvironmentVariables";
|
||||
case SettingsWindow.Dashboard:
|
||||
return "Dashboard";
|
||||
case SettingsWindow.AdvancedPaste:
|
||||
return "AdvancedPaste";
|
||||
default:
|
||||
{
|
||||
return string.Empty;
|
||||
|
@ -124,9 +124,9 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredTextExtractorEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredPastePlainEnabledValue()
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredAdvancedPasteEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredPastePlainEnabledValue());
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredAdvancedPasteEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredVideoConferenceMuteEnabledValue()
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAdvancedPasteEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPeekEnabledValue();
|
||||
static GpoRuleConfigured GetDisableNewUpdateToastValue();
|
||||
|
@ -42,7 +42,7 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredAdvancedPasteEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPeekEnabledValue();
|
||||
static GpoRuleConfigured GetDisableNewUpdateToastValue();
|
||||
|
@ -47,9 +47,9 @@ namespace PowerToys.GPOWrapperProjection
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredTextExtractorEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredPastePlainEnabledValue()
|
||||
public static GpoRuleConfigured GetConfiguredAdvancedPasteEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredPastePlainEnabledValue();
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredAdvancedPasteEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredPeekEnabledValue()
|
||||
|
@ -6,6 +6,7 @@ namespace ManagedCommon
|
||||
{
|
||||
public enum ModuleType
|
||||
{
|
||||
AdvancedPaste,
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
@ -21,7 +22,6 @@ namespace ManagedCommon
|
||||
MouseJump,
|
||||
MousePointerCrosshairs,
|
||||
MouseWithoutBorders,
|
||||
PastePlain,
|
||||
Peek,
|
||||
PowerRename,
|
||||
PowerLauncher,
|
||||
|
@ -204,6 +204,18 @@ public
|
||||
return gcnew String(CommonSharedConstants::SHOW_COLOR_PICKER_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowAdvancedPasteSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_ADVANCED_PASTE_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ AdvancedPasteMarkdownEvent() {
|
||||
return gcnew String(CommonSharedConstants::ADVANCED_PASTE_MARKDOWN_EVENT);
|
||||
}
|
||||
|
||||
static String ^ AdvancedPasteJsonEvent() {
|
||||
return gcnew String(CommonSharedConstants::ADVANCED_PASTE_JSON_EVENT);
|
||||
}
|
||||
|
||||
static String ^ ShowPowerOCRSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::SHOW_POWEROCR_SHARED_EVENT);
|
||||
}
|
||||
|
@ -25,6 +25,13 @@ namespace CommonSharedConstants
|
||||
|
||||
const wchar_t COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\ColorPickerSettingsTelemetryEvent-6c7071d8-4014-46ec-b687-913bd8a422f1";
|
||||
|
||||
// Path to the event used to show Advanced Paste UI
|
||||
const wchar_t SHOW_ADVANCED_PASTE_SHARED_EVENT[] = L"Local\\ShowAdvancedPasteEvent-9a46be2a-3e05-4186-b56b-4ae986ef2526";
|
||||
|
||||
const wchar_t ADVANCED_PASTE_MARKDOWN_EVENT[] = L"Local\\AdvancedPasteJsonEvent-a18c0798-3ee6-4fc5-bb9f-114c57ac0d47";
|
||||
|
||||
const wchar_t ADVANCED_PASTE_JSON_EVENT[] = L"Local\\AdvancedPasteJsonEvent-9ed021ab-b711-4cf3-9f33-135a698a9d21";
|
||||
|
||||
// Path to the event used to show Color Picker
|
||||
const wchar_t SHOW_COLOR_PICKER_SHARED_EVENT[] = L"Local\\ShowColorPickerEvent-8c46be2a-3e05-4186-b56b-4ae986ef2525";
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SCREEN_RULER = L"ConfigureEnabledUtilityScreenRuler";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SHORTCUT_GUIDE = L"ConfigureEnabledUtilityShortcutGuide";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_PASTE_PLAIN = L"ConfigureEnabledUtilityPastePlain";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE = L"ConfigureEnabledUtilityAdvancedPaste";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE = L"ConfigureEnabledUtilityVideoConferenceMute";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_REGISTRY_PREVIEW = L"ConfigureEnabledUtilityRegistryPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_WITHOUT_BORDERS = L"ConfigureEnabledUtilityMouseWithoutBorders";
|
||||
@ -361,9 +361,9 @@ namespace powertoys_gpo {
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredPastePlainEnabledValue()
|
||||
inline gpo_rule_configured_t getConfiguredAdvancedPasteEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_PASTE_PLAIN);
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredVideoConferenceMuteEnabledValue()
|
||||
|
@ -5,6 +5,8 @@ properties:
|
||||
directives:
|
||||
description: Configure PowerToys
|
||||
settings:
|
||||
AdvancedPaste:
|
||||
Enabled: false
|
||||
AlwaysOnTop:
|
||||
Enabled: false
|
||||
Awake:
|
||||
@ -63,8 +65,6 @@ properties:
|
||||
Enabled: false
|
||||
Hosts:
|
||||
Enabled: false
|
||||
PastePlain:
|
||||
Enabled: false
|
||||
RegistryPreview:
|
||||
Enabled: false
|
||||
|
||||
|
@ -5,6 +5,8 @@ properties:
|
||||
directives:
|
||||
description: Configure PowerToys
|
||||
settings:
|
||||
AdvancedPaste:
|
||||
Enabled: true
|
||||
AlwaysOnTop:
|
||||
Enabled: true
|
||||
Awake:
|
||||
@ -63,8 +65,6 @@ properties:
|
||||
Enabled: true
|
||||
Hosts:
|
||||
Enabled: true
|
||||
PastePlain:
|
||||
Enabled: true
|
||||
RegistryPreview:
|
||||
Enabled: true
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.8" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.9" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.8"/><!-- Last changed with PowerToys v0.78.0 -->
|
||||
<resources minRequiredRevision="1.9"/><!-- Last changed with PowerToys v0.81.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@ -17,20 +17,21 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_76_0" displayName="$(string.SUPPORTED_POWERTOYS_0_76_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_77_0" displayName="$(string.SUPPORTED_POWERTOYS_0_77_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_78_0" displayName="$(string.SUPPORTED_POWERTOYS_0_78_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_81_0" displayName="$(string.SUPPORTED_POWERTOYS_0_81_0)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
<categories>
|
||||
<category name="PowerToys" displayName="$(string.PowerToys)" />
|
||||
<category name="InstallerUpdates" displayName="$(string.InstallerUpdates)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<category name="InstallerUpdates" displayName="$(string.InstallerUpdates)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
<category name="PowerToysRun" displayName="$(string.PowerToysRun)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<category name="PowerToysRun" displayName="$(string.PowerToysRun)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
</categories>
|
||||
<policies>
|
||||
|
||||
<policy name="ConfigureGlobalUtilityEnabledState" class="Both" displayName="$(string.ConfigureGlobalUtilityEnabledState)" explainText="$(string.ConfigureGlobalUtilityEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="ConfigureGlobalUtilityEnabledState">
|
||||
|
||||
<policy name="ConfigureGlobalUtilityEnabledState" class="Both" displayName="$(string.ConfigureGlobalUtilityEnabledState)" explainText="$(string.ConfigureGlobalUtilityEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="ConfigureGlobalUtilityEnabledState">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
<enabledValue>
|
||||
@ -40,7 +41,17 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
|
||||
|
||||
<policy name="ConfigureEnabledUtilityAdvancedPaste" class="Both" displayName="$(string.ConfigureEnabledUtilityAdvancedPaste)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityAdvancedPaste">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_81_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityAlwaysOnTop" class="Both" displayName="$(string.ConfigureEnabledUtilityAlwaysOnTop)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityAlwaysOnTop">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
@ -311,16 +322,6 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityPastePlain" class="Both" displayName="$(string.ConfigureEnabledUtilityPastePlain)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPastePlain">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityPeek" class="Both" displayName="$(string.ConfigureEnabledUtilityPeek)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPeek">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_70_0" />
|
||||
@ -361,17 +362,17 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityRegistryPreview" class="Both" displayName="$(string.ConfigureEnabledUtilityRegistryPreview)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityRegistryPreview">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_69_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityScreenRuler" class="Both" displayName="$(string.ConfigureEnabledUtilityScreenRuler)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityScreenRuler">
|
||||
<policy name="ConfigureEnabledUtilityRegistryPreview" class="Both" displayName="$(string.ConfigureEnabledUtilityRegistryPreview)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityRegistryPreview">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_69_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityScreenRuler" class="Both" displayName="$(string.ConfigureEnabledUtilityScreenRuler)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityScreenRuler">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
<enabledValue>
|
||||
@ -411,7 +412,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="DisablePerUserInstallation" class="Machine" displayName="$(string.DisablePerUserInstallation)" explainText="$(string.DisablePerUserInstallationDescription)" key="Software\Policies\PowerToys" valueName="PerUserInstallationDisabled">
|
||||
<policy name="DisablePerUserInstallation" class="Machine" displayName="$(string.DisablePerUserInstallation)" explainText="$(string.DisablePerUserInstallationDescription)" key="Software\Policies\PowerToys" valueName="PerUserInstallationDisabled">
|
||||
<parentCategory ref="InstallerUpdates" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_69_0" />
|
||||
<enabledValue>
|
||||
@ -421,7 +422,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="DisableAutomaticUpdateDownload" class="Both" displayName="$(string.DisableAutomaticUpdateDownload)" explainText="$(string.DisableAutomaticUpdateDownloadDescription)" key="Software\Policies\PowerToys" valueName="AutomaticUpdateDownloadDisabled">
|
||||
<policy name="DisableAutomaticUpdateDownload" class="Both" displayName="$(string.DisableAutomaticUpdateDownload)" explainText="$(string.DisableAutomaticUpdateDownloadDescription)" key="Software\Policies\PowerToys" valueName="AutomaticUpdateDownloadDisabled">
|
||||
<parentCategory ref="InstallerUpdates" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
<enabledValue>
|
||||
@ -431,7 +432,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="SuspendNewUpdateToast" class="Both" displayName="$(string.SuspendNewUpdateToast)" explainText="$(string.SuspendNewUpdateToastDescription)" key="Software\Policies\PowerToys" valueName="SuspendNewUpdateAvailableToast">
|
||||
<policy name="SuspendNewUpdateToast" class="Both" displayName="$(string.SuspendNewUpdateToast)" explainText="$(string.SuspendNewUpdateToastDescription)" key="Software\Policies\PowerToys" valueName="SuspendNewUpdateAvailableToast">
|
||||
<parentCategory ref="InstallerUpdates" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
<enabledValue>
|
||||
@ -441,7 +442,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="DisableNewUpdateToast" class="Both" displayName="$(string.DisableNewUpdateToast)" explainText="$(string.DisableNewUpdateToastDescription)" key="Software\Policies\PowerToys" valueName="DisableNewUpdateAvailableToast">
|
||||
<policy name="DisableNewUpdateToast" class="Both" displayName="$(string.DisableNewUpdateToast)" explainText="$(string.DisableNewUpdateToastDescription)" key="Software\Policies\PowerToys" valueName="DisableNewUpdateAvailableToast">
|
||||
<parentCategory ref="InstallerUpdates" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_78_0" />
|
||||
<enabledValue>
|
||||
@ -451,7 +452,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="DoNotShowWhatsNewAfterUpdates" class="Both" displayName="$(string.DoNotShowWhatsNewAfterUpdates)" explainText="$(string.DoNotShowWhatsNewAfterUpdatesDescription)" key="Software\Policies\PowerToys" valueName="DoNotShowWhatsNewAfterUpdates">
|
||||
<policy name="DoNotShowWhatsNewAfterUpdates" class="Both" displayName="$(string.DoNotShowWhatsNewAfterUpdates)" explainText="$(string.DoNotShowWhatsNewAfterUpdatesDescription)" key="Software\Policies\PowerToys" valueName="DoNotShowWhatsNewAfterUpdates">
|
||||
<parentCategory ref="InstallerUpdates" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_78_0" />
|
||||
<enabledValue>
|
||||
@ -471,7 +472,7 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="PowerToysRunAllPluginsEnabledState" class="Both" displayName="$(string.PowerToysRunAllPluginsEnabledState)" explainText="$(string.PowerToysRunAllPluginsEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="PowerLauncherAllPluginsEnabledState">
|
||||
<policy name="PowerToysRunAllPluginsEnabledState" class="Both" displayName="$(string.PowerToysRunAllPluginsEnabledState)" explainText="$(string.PowerToysRunAllPluginsEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="PowerLauncherAllPluginsEnabledState">
|
||||
<parentCategory ref="PowerToysRun" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
<enabledValue>
|
||||
@ -481,12 +482,12 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="PowerToysRunIndividualPluginEnabledState" class="Both" displayName="$(string.PowerToysRunIndividualPluginEnabledState)" explainText="$(string.PowerToysRunIndividualPluginEnabledStateDescription)" presentation="$(presentation.PowerToysRunIndividualPluginEnabledState)" key="Software\Policies\PowerToys\PowerLauncherIndividualPluginEnabledList">
|
||||
<policy name="PowerToysRunIndividualPluginEnabledState" class="Both" displayName="$(string.PowerToysRunIndividualPluginEnabledState)" explainText="$(string.PowerToysRunIndividualPluginEnabledStateDescription)" presentation="$(presentation.PowerToysRunIndividualPluginEnabledState)" key="Software\Policies\PowerToys\PowerLauncherIndividualPluginEnabledList">
|
||||
<parentCategory ref="PowerToysRun" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0"/>
|
||||
<elements>
|
||||
<list id="PowerToysRunIndividualPluginEnabledList" explicitValue="true" />
|
||||
</elements>
|
||||
<elements>
|
||||
<list id="PowerToysRunIndividualPluginEnabledList" explicitValue="true" />
|
||||
</elements>
|
||||
</policy>
|
||||
</policies>
|
||||
</policyDefinitions>
|
||||
|
@ -1,14 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.8" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.9" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
<stringTable>
|
||||
<string id="PowerToys">Microsoft PowerToys</string>
|
||||
<string id="InstallerUpdates">Installer and Updates</string>
|
||||
<string id="PowerToysRun">PowerToys Run</string>
|
||||
<string id="InstallerUpdates">Installer and Updates</string>
|
||||
<string id="PowerToysRun">PowerToys Run</string>
|
||||
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0">PowerToys version 0.64.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_68_0">PowerToys version 0.68.0 or later</string>
|
||||
@ -19,8 +19,9 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_76_0">PowerToys version 0.76.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_77_0">PowerToys version 0.77.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_78_0">PowerToys version 0.78.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_81_0">PowerToys version 0.81.0 or later</string>
|
||||
|
||||
<string id="ConfigureGlobalUtilityEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
<string id="ConfigureGlobalUtilityEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
|
||||
If you enable this setting, all utilities will be always enabled and the user won't be able to disable it.
|
||||
|
||||
@ -31,7 +32,7 @@ If you don't configure this setting, users are able to enable or disable the uti
|
||||
The individual enabled state policies for the utilities will override this policy.
|
||||
</string>
|
||||
|
||||
<string id="ConfigureEnabledUtilityDescription">This policy configures the enabled state for a PowerToys utility.
|
||||
<string id="ConfigureEnabledUtilityDescription">This policy configures the enabled state for a PowerToys utility.
|
||||
|
||||
If you enable this setting, the utility will be always enabled and the user won't be able to disable it.
|
||||
|
||||
@ -119,6 +120,7 @@ You can set the enabled state for all plugins not configured by this policy usin
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="ConfigureGlobalUtilityEnabledState">Configure global utility enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAdvancedPaste">Advanced Paste: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAlwaysOnTop">Always On Top: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityColorPicker">Color Picker: Configure enabled state</string>
|
||||
@ -144,12 +146,11 @@ Note: Changes require a restart of PowerToys Run.
|
||||
<string id="ConfigureEnabledUtilityMouseJump">Mouse Jump: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMousePointerCrosshairs">Mouse Pointer Crosshairs: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMouseWithoutBorders">Mouse Without Borders: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPastePlain">Paste as Plain Text: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPeek">Peek: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPowerRename">Power Rename: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPowerLauncher">PowerToys Run: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityQuickAccent">Quick Accent: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityRegistryPreview">Registry Preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityRegistryPreview">Registry Preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityScreenRuler">Screen Ruler: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityShortcutGuide">Shortcut Guide: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityTextExtractor">Text Extractor: Configure enabled state</string>
|
||||
@ -165,13 +166,13 @@ Note: Changes require a restart of PowerToys Run.
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIPreview">QOI file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIThumbnails">QOI file thumbnail: Configure enabled state</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
<presentation id="PowerToysRunIndividualPluginEnabledState">
|
||||
|
||||
<presentationTable>
|
||||
<presentation id="PowerToysRunIndividualPluginEnabledState">
|
||||
<listBox refId="PowerToysRunIndividualPluginEnabledList">List of managed plugins:</listBox>
|
||||
</presentation>
|
||||
</presentationTable>
|
||||
|
||||
</presentationTable>
|
||||
|
||||
</resources>
|
||||
</policyDefinitionResources>
|
||||
|
||||
|
118
src/modules/AdvancedPaste/AdvancedPaste/AdvancedPaste.csproj
Normal file
@ -0,0 +1,118 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<ApplicationIcon>Assets\AdvancedPaste\AdvancedPaste.ico</ApplicationIcon>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<SelfContained>true</SelfContained>
|
||||
<AssemblyName>PowerToys.AdvancedPaste</AssemblyName>
|
||||
<AssemblyDescription>PowerToys AdvancedPaste</AssemblyDescription>
|
||||
<RootNamespace>AdvancedPaste</RootNamespace>
|
||||
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
|
||||
<ProjectPriFileName>PowerToys.AdvancedPaste.pri</ProjectPriFileName>
|
||||
<DefineConstants>DISABLE_XAML_GENERATED_MAIN,TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="AdvancedPasteXAML\Controls\PromptBox.xaml" />
|
||||
<None Remove="Assets\AdvancedPaste\AIIcon.png" />
|
||||
<None Remove="Assets\AdvancedPaste\Gradient.png" />
|
||||
<None Remove="AdvancedPasteXAML\Controls\AnimatedContentControl\AnimatedBorderBrush.xaml" />
|
||||
<None Remove="AdvancedPasteXAML\Views\MainPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Remove="AdvancedPasteXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="AdvancedPasteXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="ReverseMarkdown" />
|
||||
<!-- HACK: To align Microsoft.Bcl.AsyncInterfaces.dll version with PowerToys.Settings.csproj. -->
|
||||
<PackageReference Include="StreamJsonRpc" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- TODO: fix issues and reenable -->
|
||||
<!-- These are caused by streamjsonrpc dependency on Microsoft.VisualStudio.Threading.Analyzers -->
|
||||
<!-- We might want to add that to the project and fix the issues as well -->
|
||||
<NoWarn>VSTHRD002;VSTHRD110;VSTHRD100;VSTHRD200;VSTHRD101</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||
package has not yet been restored.
|
||||
-->
|
||||
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- HACK: Common.UI is referenced, even if it is not used, to force dll versions to be the same as in other projects that use it. It's still unclear why this is the case, but this is need for flattening the install directory. -->
|
||||
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
||||
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
||||
the Windows App SDK Nuget package has not yet been restored.
|
||||
-->
|
||||
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="AdvancedPasteXAML\Controls\PromptBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application
|
||||
x:Class="AdvancedPaste.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:AdvancedPaste">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="ms-appx:///AdvancedPasteXAML/Controls/AnimatedContentControl/AnimatedContentControl.xaml" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Style x:Key="SubtleButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="FocusVisualMargin" Value="-3" />
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AnimatedIcon.State="Normal"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Foreground="{TemplateBinding Foreground}">
|
||||
<ContentPresenter.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</ContentPresenter.BackgroundTransition>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</ContentPresenter>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
@ -0,0 +1,169 @@
|
||||
// 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.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Graphics;
|
||||
using WinUIEx;
|
||||
using static AdvancedPaste.Helpers.NativeMethods;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
namespace AdvancedPaste
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : Application, IDisposable
|
||||
{
|
||||
public IHost Host { get; private set; }
|
||||
|
||||
private MainWindow window;
|
||||
|
||||
private nint windowHwnd;
|
||||
|
||||
private OptionsViewModel viewModel;
|
||||
|
||||
private bool disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="App"/> class.
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder().UseContentRoot(AppContext.BaseDirectory).ConfigureServices((context, services) =>
|
||||
{
|
||||
services.AddSingleton<OptionsViewModel>();
|
||||
}).Build();
|
||||
|
||||
viewModel = GetService<OptionsViewModel>();
|
||||
|
||||
UnhandledException += App_UnhandledException;
|
||||
}
|
||||
|
||||
public MainWindow GetMainWindow()
|
||||
{
|
||||
return window;
|
||||
}
|
||||
|
||||
public static T GetService<T>()
|
||||
where T : class
|
||||
{
|
||||
if ((App.Current as App)!.Host.Services.GetService(typeof(T)) is not T service)
|
||||
{
|
||||
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched.
|
||||
/// </summary>
|
||||
/// <param name="args">Details about the launch request and process.</param>
|
||||
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
||||
{
|
||||
var cmdArgs = Environment.GetCommandLineArgs();
|
||||
if (cmdArgs?.Length > 1)
|
||||
{
|
||||
if (int.TryParse(cmdArgs[1], out int powerToysRunnerPid))
|
||||
{
|
||||
RunnerHelper.WaitForPowerToysRunner(powerToysRunnerPid, () =>
|
||||
{
|
||||
Environment.Exit(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
NativeEventWaiter.WaitForEventLoop(interop.Constants.ShowAdvancedPasteSharedEvent(), OnAdvancedPasteHotkey);
|
||||
NativeEventWaiter.WaitForEventLoop(interop.Constants.AdvancedPasteMarkdownEvent(), OnAdvancedPasteMarkdownHotkey);
|
||||
NativeEventWaiter.WaitForEventLoop(interop.Constants.AdvancedPasteJsonEvent(), OnAdvancedPasteJsonHotkey);
|
||||
}
|
||||
|
||||
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Logger.LogError("Unhandled exception", e.Exception);
|
||||
}
|
||||
|
||||
private void OnAdvancedPasteJsonHotkey()
|
||||
{
|
||||
viewModel.GetClipboardData();
|
||||
viewModel.ToJsonFunction(true);
|
||||
}
|
||||
|
||||
private void OnAdvancedPasteMarkdownHotkey()
|
||||
{
|
||||
viewModel.GetClipboardData();
|
||||
viewModel.ToMarkdownFunction(true);
|
||||
}
|
||||
|
||||
private void OnAdvancedPasteHotkey()
|
||||
{
|
||||
viewModel.OnShow();
|
||||
|
||||
if (window is null)
|
||||
{
|
||||
window = new MainWindow();
|
||||
windowHwnd = window.GetWindowHandle();
|
||||
|
||||
MoveWindowToActiveMonitor();
|
||||
|
||||
window.Activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveWindowToActiveMonitor();
|
||||
|
||||
Windows.Win32.PInvoke.ShowWindow((Windows.Win32.Foundation.HWND)windowHwnd, Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_SHOW);
|
||||
WindowHelpers.BringToForeground(windowHwnd);
|
||||
}
|
||||
|
||||
window.SetFocus();
|
||||
}
|
||||
|
||||
private void MoveWindowToActiveMonitor()
|
||||
{
|
||||
if (GetCursorPos(out PointInter cursorPosition))
|
||||
{
|
||||
DisplayArea displayArea = DisplayArea.GetFromPoint(new PointInt32(cursorPosition.X, cursorPosition.Y), DisplayAreaFallback.Nearest);
|
||||
|
||||
var x = displayArea.WorkArea.X + (displayArea.WorkArea.Width / 2) - (window.Width / 2);
|
||||
var y = displayArea.WorkArea.Y + (displayArea.WorkArea.Height / 2) - (window.Height / 2);
|
||||
|
||||
window.MoveAndResize(x, y, window.Width, window.Height);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
window.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
// 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.Numerics;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace AdvancedPaste.Controls
|
||||
{
|
||||
public partial class AnimatedBorderBrush : XamlCompositionBrushBase
|
||||
{
|
||||
public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register(
|
||||
nameof(IsLoading),
|
||||
typeof(bool),
|
||||
typeof(AnimatedBorderBrush),
|
||||
new PropertyMetadata(defaultValue: false, OnIsLoadingChanged));
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => (bool)GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
|
||||
nameof(Duration),
|
||||
typeof(int),
|
||||
typeof(AnimatedBorderBrush),
|
||||
new PropertyMetadata(defaultValue: 400, OnDurationChanged));
|
||||
|
||||
public int Duration
|
||||
{
|
||||
get => (int)GetValue(DurationProperty);
|
||||
set => SetValue(DurationProperty, value);
|
||||
}
|
||||
|
||||
private static void OnIsLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs newValue)
|
||||
{
|
||||
var selectionRectangle = (AnimatedBorderBrush)d;
|
||||
selectionRectangle.IsLoadingChanged();
|
||||
}
|
||||
|
||||
private static void OnDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs newValue)
|
||||
{
|
||||
var selectionRectangle = (AnimatedBorderBrush)d;
|
||||
selectionRectangle.DurationChanged();
|
||||
}
|
||||
|
||||
private Compositor compositor;
|
||||
private bool isConnected;
|
||||
private double centerWidth;
|
||||
private double centerHeight;
|
||||
private CompositionAnimationGroup animationGroup;
|
||||
private CompositionSurfaceBrush gradientBrush;
|
||||
|
||||
public AnimatedBorderBrush()
|
||||
{
|
||||
compositor = CompositionTarget.GetCompositorForCurrentThread();
|
||||
}
|
||||
|
||||
private void DurationChanged()
|
||||
{
|
||||
if (!isConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsLoading)
|
||||
{
|
||||
PlayAnimation(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
animationGroup = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConnected()
|
||||
{
|
||||
isConnected = true;
|
||||
IsLoadingChanged();
|
||||
}
|
||||
|
||||
protected override void OnDisconnected()
|
||||
{
|
||||
isConnected = false;
|
||||
CompositionBrush = null;
|
||||
gradientBrush = null;
|
||||
}
|
||||
|
||||
private void IsLoadingChanged()
|
||||
{
|
||||
if (!isConnected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsLoading)
|
||||
{
|
||||
if (CompositionBrush == null)
|
||||
{
|
||||
var brush = compositor.CreateSurfaceBrush();
|
||||
var loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///Assets/AdvancedPaste/Gradient.png"));
|
||||
brush.Surface = loadedSurface;
|
||||
brush.HorizontalAlignmentRatio = 0.5f;
|
||||
brush.VerticalAlignmentRatio = 0.5f;
|
||||
brush.Stretch = CompositionStretch.UniformToFill;
|
||||
brush.BitmapInterpolationMode = CompositionBitmapInterpolationMode.MagLinearMinLinearMipLinear;
|
||||
brush.Scale = new Vector2(1.4f, 1.4f);
|
||||
CompositionBrush = brush;
|
||||
gradientBrush = brush;
|
||||
gradientBrush.CenterPoint = new Vector2((float)centerWidth / 2, (float)centerHeight / 2);
|
||||
}
|
||||
|
||||
PlayAnimation(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animationGroup != null && gradientBrush != null)
|
||||
{
|
||||
gradientBrush.StopAnimationGroup(animationGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSize(double width, double height)
|
||||
{
|
||||
centerWidth = width;
|
||||
centerHeight = height;
|
||||
|
||||
if (gradientBrush != null)
|
||||
{
|
||||
gradientBrush.CenterPoint = new Vector2((float)width / 2, (float)height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayAnimation(bool reset)
|
||||
{
|
||||
if (reset || animationGroup == null)
|
||||
{
|
||||
InitializeAnimation();
|
||||
}
|
||||
|
||||
gradientBrush.StopAnimationGroup(animationGroup);
|
||||
gradientBrush.StartAnimationGroup(animationGroup);
|
||||
}
|
||||
|
||||
private void InitializeAnimation()
|
||||
{
|
||||
animationGroup = compositor.CreateAnimationGroup();
|
||||
var animation = compositor.CreateScalarKeyFrameAnimation();
|
||||
animation.Duration = TimeSpan.FromMilliseconds(Duration);
|
||||
animation.IterationBehavior = AnimationIterationBehavior.Forever;
|
||||
var easing = compositor.CreateLinearEasingFunction();
|
||||
animation.InsertKeyFrame(0, 0, easing);
|
||||
animation.InsertKeyFrame(1, 360, easing);
|
||||
animation.Target = "RotationAngleInDegrees";
|
||||
animationGroup.Add(animation);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<XamlCompositionBrushBase
|
||||
x:Class="AdvancedPaste.Controls.AnimatedBorderBrush"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" />
|
@ -0,0 +1,91 @@
|
||||
// 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.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace AdvancedPaste.Controls
|
||||
{
|
||||
[TemplatePart(Name = LoadingGrid, Type = typeof(Grid))]
|
||||
[TemplatePart(Name = LoadingBrush, Type = typeof(AnimatedBorderBrush))]
|
||||
public class AnimatedContentControl : ContentControl
|
||||
{
|
||||
internal const string LoadingGrid = "PART_LoadingGrid";
|
||||
internal const string LoadingBrush = "PART_LoadingBrush";
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
|
||||
nameof(Text),
|
||||
typeof(string),
|
||||
typeof(AnimatedContentControl),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => (bool)GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register(
|
||||
nameof(IsLoading),
|
||||
typeof(bool),
|
||||
typeof(AnimatedContentControl),
|
||||
new PropertyMetadata(defaultValue: false, (d, e) => ((AnimatedContentControl)d).OnIsLoadingPropertyChanged((bool)e.OldValue, (bool)e.NewValue)));
|
||||
|
||||
public AnimatedContentControl()
|
||||
{
|
||||
this.DefaultStyleKey = typeof(AnimatedContentControl);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
this.SizeChanged -= AICard_SizeChanged;
|
||||
OnIsLoadingChanged();
|
||||
UpdateSize(Width, Height);
|
||||
this.SizeChanged += AICard_SizeChanged;
|
||||
}
|
||||
|
||||
private void AICard_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (GetTemplateChild(LoadingBrush) is AnimatedBorderBrush loadingBrush)
|
||||
{
|
||||
UpdateSize(e.NewSize.Width, e.NewSize.Height);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSize(double width, double height)
|
||||
{
|
||||
if (GetTemplateChild(LoadingBrush) is AnimatedBorderBrush loadingBrush)
|
||||
{
|
||||
loadingBrush.UpdateSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnIsLoadingPropertyChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
OnIsLoadingChanged();
|
||||
}
|
||||
|
||||
private void OnIsLoadingChanged()
|
||||
{
|
||||
if (GetTemplateChild(LoadingBrush) is AnimatedBorderBrush loadingBrush)
|
||||
{
|
||||
UpdateSize(ActualWidth, ActualHeight);
|
||||
|
||||
loadingBrush.IsLoading = IsLoading;
|
||||
}
|
||||
|
||||
if (GetTemplateChild(LoadingGrid) is Grid loadingGrid)
|
||||
{
|
||||
loadingGrid.Visibility = IsLoading ? Visibility.Visible : Visibility.Collapsed;
|
||||
UpdateSize(ActualWidth, ActualHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
||||
xmlns:local="using:AdvancedPaste.Controls">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultAnimatedContentControlStyle}" TargetType="local:AnimatedContentControl" />
|
||||
|
||||
<Style x:Key="DefaultAnimatedContentControlStyle" TargetType="local:AnimatedContentControl">
|
||||
<Style.Setters>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:AnimatedContentControl">
|
||||
<Grid
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ContentPresenter Content="{TemplateBinding Content}" />
|
||||
<Grid
|
||||
x:Name="PART_LoadingGrid"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="4"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Visibility="Collapsed">
|
||||
<!-- CornerRadius needs to be > 0 -->
|
||||
<Grid.BorderBrush>
|
||||
<local:AnimatedBorderBrush
|
||||
x:Name="PART_LoadingBrush"
|
||||
IsLoading="True"
|
||||
Duration="900" />
|
||||
</Grid.BorderBrush>
|
||||
<animations:Implicit.ShowAnimations>
|
||||
<animations:OpacityAnimation
|
||||
From="0"
|
||||
To="1.0"
|
||||
Duration="0:0:0.4" />
|
||||
</animations:Implicit.ShowAnimations>
|
||||
<animations:Implicit.HideAnimations>
|
||||
<animations:OpacityAnimation
|
||||
From="1.0"
|
||||
To="0"
|
||||
Duration="0:0:0.2" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
@ -0,0 +1,662 @@
|
||||
<UserControl
|
||||
x:Class="AdvancedPaste.Controls.PromptBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:AdvancedPaste.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<Color x:Key="AccentGradientColor">#65C8F2</Color>
|
||||
<LinearGradientBrush x:Key="AccentGradientBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0.0" Color="#98EFFE" />
|
||||
<GradientStop Offset="0.25" Color="#48B1E9" />
|
||||
<GradientStop Offset="1.0" Color="{StaticResource AccentGradientColor}" />
|
||||
</LinearGradientBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="AccentGradientColor">#005FB8</Color>
|
||||
<LinearGradientBrush x:Key="AccentGradientBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0.0" Color="#4992C7" />
|
||||
<GradientStop Offset="0.25" Color="#1353A0" />
|
||||
<GradientStop Offset="1.0" Color="{StaticResource AccentGradientColor}" />
|
||||
</LinearGradientBrush>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<Color x:Key="AccentGradientColor">#48B1E9</Color>
|
||||
<SolidColorBrush x:Key="AccentGradientBrush" Color="{StaticResource AccentGradientColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Style x:Key="CustomTextBoxStyle" TargetType="TextBox">
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
|
||||
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
|
||||
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
|
||||
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
|
||||
<Setter Property="ContextFlyout" Value="{StaticResource TextControlCommandBarContextFlyout}" />
|
||||
<Setter Property="SelectionFlyout" Value="{StaticResource TextControlCommandBarSelectionFlyout}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="TextBox">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style x:Name="DeleteButtonStyle" TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid
|
||||
x:Name="ButtonLayoutGrid"
|
||||
Margin="{ThemeResource TextBoxInnerButtonMargin}"
|
||||
Background="{ThemeResource TextControlButtonBackground}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock
|
||||
x:Name="GlyphElement"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="{ThemeResource TextBoxIconFontSize}"
|
||||
FontStyle="Normal"
|
||||
Foreground="{ThemeResource TextControlButtonForeground}"
|
||||
Text="" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetName="ButtonLayoutGrid"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0"
|
||||
Duration="0" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="0" />
|
||||
<ColumnDefinition Width="32" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter
|
||||
x:Name="HeaderContentPresenter"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{ThemeResource TextBoxTopHeaderMargin}"
|
||||
VerticalAlignment="Top"
|
||||
x:DeferLoadStrategy="Lazy"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
FontWeight="Normal"
|
||||
Foreground="{ThemeResource TextControlHeaderForeground}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="Collapsed" />
|
||||
<Border
|
||||
x:Name="BorderElement"
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="4"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Control.IsTemplateFocusTarget="True"
|
||||
CornerRadius="{TemplateBinding CornerRadius}" />
|
||||
<Viewbox
|
||||
Grid.Row="1"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="8,0,0,0">
|
||||
<PathIcon
|
||||
x:Name="AIGlyph"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Data="M128 766q0-42 24-77t65-48l178-57q32-11 61-30t52-42q50-50 71-114l58-179q13-40 48-65t78-26q42 0 77 24t50 65l58 177q21 66 72 117 49 50 117 72l176 58q43 14 69 48t26 80q0 41-25 76t-64 49l-178 58q-66 21-117 72-32 32-51 73t-33 84-26 83-30 73-45 51-71 20q-42 0-77-24t-49-65l-58-178q-8-25-19-47t-28-43q-34-43-77-68t-89-41-89-27-78-29-55-45-21-75zm1149 7q-76-29-145-53t-129-60-104-88-73-138l-57-176-67 176q-18 48-42 89t-60 78q-34 34-76 61t-89 43l-177 57q75 29 144 53t127 60 103 89 73 137l57 176 67-176q37-97 103-168t168-103l177-57zm-125 759q0-31 20-57t49-36l99-32q34-11 53-34t30-51 20-59 20-54 33-41 58-16q32 0 59 19t38 50q6 20 11 40t13 40 17 38 25 34q16 17 39 26t48 18 49 16 44 20 31 32 12 50q0 33-18 60t-51 38q-19 6-39 11t-41 13-39 17-34 25q-24 25-35 62t-24 73-35 61-68 25q-32 0-59-19t-38-50q-6-18-11-39t-13-41-17-40-24-33q-18-17-41-27t-47-17-49-15-43-20-30-33-12-54zm583 4q-43-13-74-30t-55-41-40-55-32-74q-12 41-29 72t-42 55-55 42-71 31q81 23 128 71t71 129q15-43 31-74t40-54 53-40 75-32z"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</Viewbox>
|
||||
<ScrollViewer
|
||||
x:Name="ContentElement"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
|
||||
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||
IsTabStop="False"
|
||||
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||
ZoomMode="Disabled" />
|
||||
<TextBlock
|
||||
x:Name="PlaceholderTextContentPresenter"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}"
|
||||
IsHitTestVisible="False"
|
||||
Text="{TemplateBinding PlaceholderText}"
|
||||
TextAlignment="{TemplateBinding TextAlignment}"
|
||||
TextWrapping="{TemplateBinding TextWrapping}" />
|
||||
<Button
|
||||
x:Name="DeleteButton"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Width="30"
|
||||
Padding="{ThemeResource HelperButtonThemePadding}"
|
||||
VerticalAlignment="Stretch"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource DeleteButtonStyle}"
|
||||
Visibility="Collapsed" />
|
||||
<ContentPresenter
|
||||
x:Name="DescriptionPresenter"
|
||||
Grid.Row="2"
|
||||
Grid.ColumnSpan="3"
|
||||
x:Load="False"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Description}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="AIGlyph" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundDisabled}}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Focused">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundFocused}}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<LinearGradientBrush MappingMode="Absolute" StartPoint="0,0" EndPoint="0,2">
|
||||
<LinearGradientBrush.RelativeTransform>
|
||||
<ScaleTransform CenterY="0.5" ScaleY="-1" />
|
||||
</LinearGradientBrush.RelativeTransform>
|
||||
<LinearGradientBrush.GradientStops>
|
||||
<GradientStop Offset="1.0" Color="{ThemeResource AccentGradientColor}" />
|
||||
<GradientStop Offset="1.0" Color="{ThemeResource ControlStrokeColorDefault}" />
|
||||
</LinearGradientBrush.GradientStops>
|
||||
</LinearGradientBrush>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderThemeThicknessFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ButtonStates">
|
||||
<VisualState x:Name="ButtonVisible">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="ButtonCollapsed" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid x:Name="PromptBoxGrid" Loaded="Grid_Loaded">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
<local:AnimatedContentControl
|
||||
x:Name="Loader"
|
||||
MinHeight="48"
|
||||
CornerRadius="8">
|
||||
<Grid>
|
||||
<TextBox
|
||||
x:Name="InputTxtBox"
|
||||
HorizontalAlignment="Stretch"
|
||||
x:FieldModifier="public"
|
||||
IsEnabled="{x:Bind ViewModel.IsCustomAIEnabled, Mode=OneWay}"
|
||||
KeyDown="InputTxtBox_KeyDown"
|
||||
PlaceholderText="{x:Bind ViewModel.InputTxtBoxPlaceholderText, Mode=OneWay}"
|
||||
Style="{StaticResource CustomTextBoxStyle}"
|
||||
TabIndex="0"
|
||||
Text="{x:Bind Prompt, Mode=TwoWay}"
|
||||
TextChanging="InputTxtBox_TextChanging">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="InputTxtBoxTooltip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<FlyoutBase.AttachedFlyout>
|
||||
<Flyout
|
||||
x:Name="PreviewFlyout"
|
||||
AreOpenCloseAnimationsEnabled="False"
|
||||
Opened="PreviewFlyout_Opened"
|
||||
Placement="Bottom"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style BasedOn="{StaticResource DefaultFlyoutPresenterStyle}" TargetType="FlyoutPresenter">
|
||||
<Style.Setters>
|
||||
<Setter Property="MaxWidth" Value="3000" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<Grid x:Name="PreviewGrid" Background="{ThemeResource SolidBackgroundFillColorBaseBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid
|
||||
Padding="12,8,12,8"
|
||||
Background="{ThemeResource LayerFillColorAltBrush}"
|
||||
CornerRadius="8,8,0,0"
|
||||
RowSpacing="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Uid="ResultTitleTxt" VerticalAlignment="Center" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="2">
|
||||
<Button
|
||||
Padding="4"
|
||||
Click="ThumbUpDown_Click"
|
||||
CommandParameter="True"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="ThumbsUpFeedback" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<Button
|
||||
Padding="4"
|
||||
Click="ThumbUpDown_Click"
|
||||
CommandParameter="False"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="ThumbsDownFeedback" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<ScrollViewer
|
||||
Grid.Row="1"
|
||||
MinHeight="104"
|
||||
MaxHeight="320">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.CustomFormatResult, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Height="1"
|
||||
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Margin="12"
|
||||
ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel
|
||||
Margin="-4,0,0,0"
|
||||
Orientation="Horizontal"
|
||||
Spacing="2"
|
||||
Visibility="{x:Bind ViewModel.HasMultipleResponses, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<Button
|
||||
x:Uid="PreviousResultBtnAutomation"
|
||||
Padding="4"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.PreviousCustomFormatCommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="PreviousResultBtnToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<TextBlock
|
||||
Margin="0,-2,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind ViewModel.CurrentIndexDisplay, Mode=OneWay}" />
|
||||
<Button
|
||||
x:Uid="NextResultBtnAutomation"
|
||||
Padding="4"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.NextCustomFormatCommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="NextResultBtnToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Button
|
||||
x:Uid="RegenerateBtnAutomation"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{x:Bind GenerateCustomCommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=16}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="RegenerateBtnToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="PreviewPasteBtn"
|
||||
x:Uid="PasteButtonAutomation"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
Click="PreviewPasteBtn_Click"
|
||||
Style="{StaticResource AccentButtonStyle}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<FontIcon FontSize="16" Glyph="" />
|
||||
<TextBlock x:Uid="PasteText" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Flyout>
|
||||
</FlyoutBase.AttachedFlyout>
|
||||
</TextBox>
|
||||
|
||||
<!--<StackPanel
|
||||
Margin="0,0,4,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Stretch"
|
||||
Orientation="Horizontal">-->
|
||||
<!--<Button
|
||||
x:Name="RecallBtn"
|
||||
x:Uid="RecallButtonAutomation"
|
||||
Width="32"
|
||||
Height="32"
|
||||
Padding="0"
|
||||
Command="{x:Bind RecallCommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=12}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
TabIndex="2"
|
||||
Visibility="Collapsed">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="RecallBtnToolTip" TextWrapping="WrapWholeWords" />
|
||||
</ToolTipService.ToolTip>
|
||||
<animations:Implicit.Animations>
|
||||
<animations:TranslationAnimation Duration="0:0:1" />
|
||||
<animations:ScaleAnimation Duration="0:0:1" />
|
||||
<animations:OffsetAnimation Duration="0:0:1" />
|
||||
</animations:Implicit.Animations>
|
||||
</Button>-->
|
||||
<Button
|
||||
x:Name="SendBtn"
|
||||
x:Uid="SendButtonAutomation"
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="0,0,4,0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Stretch"
|
||||
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
|
||||
Command="{x:Bind GenerateCustomCommand}"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=16}"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
TabIndex="1"
|
||||
Visibility="Collapsed">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="SendBtnToolTip" TextWrapping="WrapWholeWords" />
|
||||
</ToolTipService.ToolTip>
|
||||
<animations:Implicit.ShowAnimations>
|
||||
<animations:ScaleAnimation
|
||||
From="0.4"
|
||||
To="1"
|
||||
Duration="0:0:0.167" />
|
||||
<animations:OpacityAnimation
|
||||
From="0.0"
|
||||
To="1.0"
|
||||
Duration="0:0:0.167" />
|
||||
</animations:Implicit.ShowAnimations>
|
||||
<animations:Implicit.HideAnimations>
|
||||
<animations:ScaleAnimation
|
||||
From="1"
|
||||
To="0.4"
|
||||
Duration="0:0:0.167" />
|
||||
<animations:OpacityAnimation
|
||||
From="1.0"
|
||||
To="0.0"
|
||||
Duration="0:0:0.167" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
</Button>
|
||||
<!--</StackPanel>-->
|
||||
</Grid>
|
||||
</local:AnimatedContentControl>
|
||||
<ContentPresenter
|
||||
x:Name="DisclaimerPresenter"
|
||||
Grid.Row="1"
|
||||
Margin="8,8,12,0"
|
||||
VerticalAlignment="Top"
|
||||
Content="{x:Bind Footer, Mode=OneWay}">
|
||||
<animations:Implicit.ShowAnimations>
|
||||
<animations:OpacityAnimation To="1.0" Duration="0:0:0.4" />
|
||||
</animations:Implicit.ShowAnimations>
|
||||
<animations:Implicit.HideAnimations>
|
||||
<animations:OpacityAnimation To="0.0" Duration="0:0:0.167" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
</ContentPresenter>
|
||||
<TextBlock
|
||||
x:Name="LoadingText"
|
||||
x:Uid="LoadingText"
|
||||
Grid.Row="1"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource AccentGradientBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Visibility="Collapsed">
|
||||
<animations:Implicit.ShowAnimations>
|
||||
<animations:OpacityAnimation To="1.0" Duration="0:0:0.6" />
|
||||
</animations:Implicit.ShowAnimations>
|
||||
<animations:Implicit.HideAnimations>
|
||||
<animations:OpacityAnimation To="0.0" Duration="0:0:0.167" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
</TextBlock>
|
||||
<Grid
|
||||
x:Name="ErrorMessageGrid"
|
||||
x:Uid="ErrorMessageGrid"
|
||||
Grid.Row="1"
|
||||
Margin="8,8,0,0"
|
||||
ColumnSpacing="8"
|
||||
Visibility="Collapsed">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.InputTxtBoxErrorText, Mode=OneWay}" />
|
||||
<HyperlinkButton
|
||||
x:Uid="SettingsBtn"
|
||||
Grid.Column="1"
|
||||
Margin="0,-1,0,0"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Command="{x:Bind ViewModel.OpenSettingsCommand}"
|
||||
FontSize="12" />
|
||||
<animations:Implicit.ShowAnimations>
|
||||
<animations:OpacityAnimation To="1.0" Duration="0:0:0.6" />
|
||||
</animations:Implicit.ShowAnimations>
|
||||
<animations:Implicit.HideAnimations>
|
||||
<animations:OpacityAnimation To="0.0" Duration="0:0:0.167" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="DefaultState" />
|
||||
<VisualState x:Name="LoadingState">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="Loader.IsLoading" Value="True" />
|
||||
<Setter Target="InputTxtBox.IsEnabled" Value="False" />
|
||||
<!--<Setter Target="RecallBtn.IsEnabled" Value="False" />-->
|
||||
<Setter Target="SendBtn.IsEnabled" Value="False" />
|
||||
<Setter Target="DisclaimerPresenter.Visibility" Value="Collapsed" />
|
||||
<Setter Target="LoadingText.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="ErrorState">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="InputTxtBox.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
<Setter Target="DisclaimerPresenter.Visibility" Value="Collapsed" />
|
||||
<Setter Target="ErrorMessageGrid.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -0,0 +1,178 @@
|
||||
// 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.Net;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Settings;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace AdvancedPaste.Controls
|
||||
{
|
||||
public sealed partial class PromptBox : Microsoft.UI.Xaml.Controls.UserControl
|
||||
{
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
private UserSettings _userSettings;
|
||||
|
||||
public static readonly DependencyProperty PromptProperty = DependencyProperty.Register(
|
||||
nameof(Prompt),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
|
||||
public OptionsViewModel ViewModel { get; private set; }
|
||||
|
||||
public string Prompt
|
||||
{
|
||||
get => (string)GetValue(PromptProperty);
|
||||
set => SetValue(PromptProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
|
||||
nameof(PlaceholderText),
|
||||
typeof(string),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: string.Empty));
|
||||
|
||||
public string PlaceholderText
|
||||
{
|
||||
get => (string)GetValue(PlaceholderTextProperty);
|
||||
set => SetValue(PlaceholderTextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(
|
||||
nameof(Footer),
|
||||
typeof(object),
|
||||
typeof(PromptBox),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
public object Footer
|
||||
{
|
||||
get => (object)GetValue(FooterProperty);
|
||||
set => SetValue(FooterProperty, value);
|
||||
}
|
||||
|
||||
public PromptBox()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
_userSettings = new UserSettings();
|
||||
|
||||
ViewModel = App.GetService<OptionsViewModel>();
|
||||
}
|
||||
|
||||
private void Grid_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
InputTxtBox.Focus(FocusState.Programmatic);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void GenerateCustom()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteGenerateCustomFormatEvent());
|
||||
|
||||
VisualStateManager.GoToState(this, "LoadingState", true);
|
||||
string inputInstructions = InputTxtBox.Text;
|
||||
ViewModel.SaveQuery(inputInstructions);
|
||||
|
||||
var customFormatTask = ViewModel.GenerateCustomFunction(inputInstructions);
|
||||
|
||||
customFormatTask.ContinueWith(
|
||||
t =>
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ViewModel.CustomFormatResult = t.Result;
|
||||
|
||||
if (ViewModel.ApiRequestStatus == (int)HttpStatusCode.OK)
|
||||
{
|
||||
VisualStateManager.GoToState(this, "DefaultState", true);
|
||||
if (_userSettings.ShowCustomPreview)
|
||||
{
|
||||
PreviewGrid.Width = InputTxtBox.ActualWidth;
|
||||
PreviewFlyout.ShowAt(InputTxtBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewModel.PasteCustom();
|
||||
InputTxtBox.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(this, "ErrorState", true);
|
||||
}
|
||||
});
|
||||
},
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Recall()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
InputTxtBox.IsEnabled = true;
|
||||
|
||||
var lastQuery = ViewModel.RecallPreviousCustomQuery();
|
||||
if (lastQuery != null)
|
||||
{
|
||||
InputTxtBox.Text = lastQuery.Query;
|
||||
}
|
||||
|
||||
ClipboardHelper.SetClipboardTextContent(lastQuery.ClipboardData);
|
||||
}
|
||||
|
||||
private void InputTxtBox_TextChanging(Microsoft.UI.Xaml.Controls.TextBox sender, TextBoxTextChangingEventArgs args)
|
||||
{
|
||||
SendBtn.Visibility = InputTxtBox.Text.Length > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void InputTxtBox_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key == Windows.System.VirtualKey.Enter && InputTxtBox.Text.Length > 0)
|
||||
{
|
||||
GenerateCustom();
|
||||
}
|
||||
}
|
||||
|
||||
private void PreviewPasteBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.PasteCustom();
|
||||
InputTxtBox.Text = string.Empty;
|
||||
}
|
||||
|
||||
private void ThumbUpDown_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn)
|
||||
{
|
||||
bool result;
|
||||
if (bool.TryParse(btn.CommandParameter as string, out result))
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteCustomFormatOutputThumbUpDownEvent(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PreviewFlyout_Opened(object sender, object e)
|
||||
{
|
||||
PreviewPasteBtn.Focus(FocusState.Programmatic);
|
||||
}
|
||||
|
||||
internal void IsLoading(bool loading)
|
||||
{
|
||||
Loader.IsLoading = loading;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// 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.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace AdvancedPaste.Converters
|
||||
{
|
||||
public sealed class ListViewIndexConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var presenter = value as ListViewItemPresenter;
|
||||
var item = VisualTreeHelper.GetParent(presenter) as ListViewItem;
|
||||
|
||||
var listView = ItemsControl.ItemsControlFromItemContainer(item);
|
||||
int index = listView.IndexFromContainer(item) + 1;
|
||||
#pragma warning disable CA1305 // Specify IFormatProvider
|
||||
return index.ToString();
|
||||
#pragma warning restore CA1305 // Specify IFormatProvider
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<winuiex:WindowEx
|
||||
x:Class="AdvancedPaste.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="using:AdvancedPaste.Pages"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
Width="420"
|
||||
Height="308"
|
||||
MinWidth="420"
|
||||
MinHeight="308"
|
||||
Closed="WindowEx_Closed"
|
||||
IsAlwaysOnTop="True"
|
||||
IsMaximizable="False"
|
||||
IsMinimizable="False"
|
||||
IsResizable="true"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.SystemBackdrop>
|
||||
<DesktopAcrylicBackdrop />
|
||||
</winuiex:WindowEx.SystemBackdrop>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="titleBar">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Width="16"
|
||||
Margin="12,0,0,0"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Source="/Assets/AdvancedPaste/AdvancedPaste.ico" />
|
||||
<Rectangle
|
||||
Grid.ColumnSpan="2"
|
||||
Width="30"
|
||||
Height="3"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="{ThemeResource ControlStrongFillColorDefaultBrush}"
|
||||
RadiusX="2"
|
||||
RadiusY="2" />
|
||||
</Grid>
|
||||
|
||||
<pages:MainPage
|
||||
x:Name="MainPage"
|
||||
Grid.Row="1"
|
||||
x:FieldModifier="public" />
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
@ -0,0 +1,99 @@
|
||||
// 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.Runtime.CompilerServices;
|
||||
using AdvancedPaste.Helpers;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.Graphics;
|
||||
using WinUIEx;
|
||||
using WinUIEx.Messaging;
|
||||
using static AdvancedPaste.Helpers.NativeMethods;
|
||||
|
||||
namespace AdvancedPaste
|
||||
{
|
||||
public sealed partial class MainWindow : WindowEx, IDisposable
|
||||
{
|
||||
private WindowMessageMonitor _msgMonitor;
|
||||
|
||||
private bool _disposedValue;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
AppWindow.SetIcon("Assets/AdvancedPaste/AdvancedPaste.ico");
|
||||
this.ExtendsContentIntoTitleBar = true;
|
||||
this.SetTitleBar(titleBar);
|
||||
|
||||
var loader = ResourceLoaderInstance.ResourceLoader;
|
||||
Title = loader.GetString("WindowTitle");
|
||||
|
||||
_msgMonitor = new WindowMessageMonitor(this);
|
||||
_msgMonitor.WindowMessageReceived += (_, e) =>
|
||||
{
|
||||
const int WM_NCLBUTTONDBLCLK = 0x00A3;
|
||||
if (e.Message.MessageId == WM_NCLBUTTONDBLCLK)
|
||||
{
|
||||
// Disable double click on title bar to maximize window
|
||||
e.Result = 0;
|
||||
e.Handled = true;
|
||||
}
|
||||
};
|
||||
|
||||
WindowHelpers.BringToForeground(this.GetWindowHandle());
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
_msgMonitor?.Dispose();
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void WindowEx_Closed(object sender, Microsoft.UI.Xaml.WindowEventArgs args)
|
||||
{
|
||||
Windows.Win32.PInvoke.ShowWindow((Windows.Win32.Foundation.HWND)this.GetWindowHandle(), Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
public void SetFocus()
|
||||
{
|
||||
MainPage.CustomFormatTextBox.InputTxtBox.Focus(FocusState.Programmatic);
|
||||
}
|
||||
|
||||
public void ClearInputText()
|
||||
{
|
||||
MainPage.CustomFormatTextBox.InputTxtBox.Text = string.Empty;
|
||||
}
|
||||
|
||||
internal void StartLoading()
|
||||
{
|
||||
MainPage.CustomFormatTextBox.IsLoading(true);
|
||||
}
|
||||
|
||||
internal void FinishLoading(bool success)
|
||||
{
|
||||
MainPage.CustomFormatTextBox.IsLoading(false);
|
||||
|
||||
if (success)
|
||||
{
|
||||
VisualStateManager.GoToState(MainPage.CustomFormatTextBox, "DefaultState", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
<Page
|
||||
x:Class="AdvancedPaste.Pages.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:AdvancedPaste.Controls"
|
||||
xmlns:converters="using:AdvancedPaste.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:AdvancedPaste.Models"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
KeyDown="Page_KeyDown"
|
||||
KeyboardAcceleratorPlacementMode="Hidden"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:ListViewIndexConverter x:Name="listViewIndexConverter" />
|
||||
<Style
|
||||
x:Key="PaddingLessFlyoutPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}"
|
||||
TargetType="FlyoutPresenter">
|
||||
<Style.Setters>
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</Page.Resources>
|
||||
<Page.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Escape" Invoked="KeyboardAccelerator_Invoked" />
|
||||
<KeyboardAccelerator
|
||||
Key="Number1"
|
||||
Invoked="KeyboardAccelerator_Invoked"
|
||||
Modifiers="Control" />
|
||||
<KeyboardAccelerator
|
||||
Key="Number2"
|
||||
Invoked="KeyboardAccelerator_Invoked"
|
||||
Modifiers="Control" />
|
||||
<KeyboardAccelerator
|
||||
Key="Number3"
|
||||
Invoked="KeyboardAccelerator_Invoked"
|
||||
Modifiers="Control" />
|
||||
</Page.KeyboardAccelerators>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<controls:PromptBox
|
||||
x:Name="CustomFormatTextBox"
|
||||
x:Uid="CustomFormatTextBox"
|
||||
Margin="8,4,8,0"
|
||||
x:FieldModifier="public"
|
||||
TabIndex="0">
|
||||
<controls:PromptBox.Footer>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Run x:Uid="AIMistakeNote" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="4,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Hyperlink
|
||||
x:Name="TermsHyperlink"
|
||||
NavigateUri="https://openai.com/policies/terms-of-use"
|
||||
TabIndex="3">
|
||||
<Run x:Uid="TermsLink" />
|
||||
</Hyperlink>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="https://openai.com/policies/terms-of-use" />
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
ToolTipService.ToolTip="">
|
||||
<Run x:Uid="AIFooterSeparator" Foreground="{ThemeResource TextFillColorSecondaryBrush}">|</Run>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Hyperlink NavigateUri="https://openai.com/policies/privacy-policy" TabIndex="3">
|
||||
<Run x:Uid="PrivacyLink" />
|
||||
</Hyperlink>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="https://openai.com/policies/privacy-policy" />
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</controls:PromptBox.Footer>
|
||||
</controls:PromptBox>
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
RowSpacing="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListView
|
||||
x:Name="PasteOptionsListView"
|
||||
VerticalAlignment="Bottom"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="PasteOptionsListView_ItemClick"
|
||||
ItemContainerTransitions="{x:Null}"
|
||||
ItemsSource="{x:Bind pasteFormats, Mode=OneWay}"
|
||||
SelectionMode="None"
|
||||
TabIndex="1">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:PasteFormat">
|
||||
<Grid>
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock>
|
||||
<Run Text="{x:Bind Name}" />
|
||||
<Run Text="(" /><Run Text="Ctrl" /><Run Text="+" /><Run Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource listViewIndexConverter}}" /><Run Text=")" />
|
||||
</TextBlock>
|
||||
</ToolTipService.ToolTip>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="26" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Viewbox
|
||||
x:Name="IconHolderBox"
|
||||
MaxWidth="16"
|
||||
MaxHeight="16"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center">
|
||||
<ContentPresenter
|
||||
x:Name="IconHolder"
|
||||
x:Phase="2"
|
||||
Content="{x:Bind Icon}" />
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Text="{x:Bind Name}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Margin="0,0,8,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}">
|
||||
<Run Text="Ctrl" /><Run Text="+" /><Run Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource listViewIndexConverter}}" />
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<Rectangle
|
||||
Grid.Row="1"
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
<!-- x:Uid="ClipboardHistoryButton" -->
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Height="32"
|
||||
Margin="4,0,4,4"
|
||||
Padding="{StaticResource ButtonPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
IsEnabled="{x:Bind ViewModel.ClipboardHistoryEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Grid
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="16"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
x:Uid="ClipboardHistoryButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center" />
|
||||
<FontIcon
|
||||
Grid.Column="2"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
FlyoutPresenterStyle="{StaticResource PaddingLessFlyoutPresenterStyle}"
|
||||
Placement="Right"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
|
||||
<ListView
|
||||
Width="320"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ClipboardHistory_ItemClick"
|
||||
ItemsSource="{x:Bind clipboardHistory, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.Transitions />
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:ClipboardItem">
|
||||
<Grid
|
||||
Height="40"
|
||||
HorizontalAlignment="Stretch"
|
||||
ColumnSpacing="8"
|
||||
ToolTipService.ToolTip="{x:Bind Content}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" MaxWidth="240" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
x:Phase="2"
|
||||
Source="{x:Bind Image}"
|
||||
Visibility="Visible" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
x:Phase="1"
|
||||
Text="{x:Bind Content}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Visibility="Visible" />
|
||||
<Button
|
||||
x:Name="moreInfo"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="16" Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ClipboardHistoryItemDeleteButton"
|
||||
Click="ClipboardHistoryItemDeleteButton_Click"
|
||||
CommandParameter="{x:Bind (local:ClipboardItem)}"
|
||||
Icon="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
@ -0,0 +1,241 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.ViewModels;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.System;
|
||||
|
||||
namespace AdvancedPaste.Pages
|
||||
{
|
||||
public sealed partial class MainPage : Page
|
||||
{
|
||||
private readonly ObservableCollection<ClipboardItem> clipboardHistory;
|
||||
private readonly ObservableCollection<PasteFormat> pasteFormats;
|
||||
private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
public OptionsViewModel ViewModel { get; private set; }
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
pasteFormats =
|
||||
[
|
||||
new PasteFormat { Icon = new FontIcon() { Glyph = "\uE8E9" }, Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsPlainText"), Format = PasteFormats.PlainText },
|
||||
new PasteFormat { Icon = new FontIcon() { Glyph = "\ue8a5" }, Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsMarkdown"), Format = PasteFormats.Markdown },
|
||||
new PasteFormat { Icon = new FontIcon() { Glyph = "\uE943" }, Name = ResourceLoaderInstance.ResourceLoader.GetString("PasteAsJson"), Format = PasteFormats.Json },
|
||||
];
|
||||
|
||||
ViewModel = App.GetService<OptionsViewModel>();
|
||||
|
||||
clipboardHistory = new ObservableCollection<ClipboardItem>();
|
||||
|
||||
LoadClipboardHistoryEvent(null, null);
|
||||
Clipboard.HistoryChanged += LoadClipboardHistoryEvent;
|
||||
}
|
||||
|
||||
private void LoadClipboardHistoryEvent(object sender, object e)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
LoadClipboardHistoryAsync();
|
||||
});
|
||||
}
|
||||
|
||||
public async void LoadClipboardHistoryAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
List<ClipboardItem> items = new();
|
||||
|
||||
if (Clipboard.IsHistoryEnabled())
|
||||
{
|
||||
var historyItems = await Clipboard.GetHistoryItemsAsync();
|
||||
if (historyItems.Status == ClipboardHistoryItemsResultStatus.Success)
|
||||
{
|
||||
foreach (var item in historyItems.Items)
|
||||
{
|
||||
if (item.Content.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
string text = await item.Content.GetTextAsync();
|
||||
items.Add(new ClipboardItem { Content = text, Item = item });
|
||||
}
|
||||
else if (item.Content.Contains(StandardDataFormats.Bitmap))
|
||||
{
|
||||
items.Add(new ClipboardItem { Item = item });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_dispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
clipboardHistory.Clear();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item.Item.Content.Contains(StandardDataFormats.Bitmap))
|
||||
{
|
||||
IRandomAccessStreamReference imageReceived = null;
|
||||
imageReceived = await item.Item.Content.GetBitmapAsync();
|
||||
if (imageReceived != null)
|
||||
{
|
||||
using (var imageStream = await imageReceived.OpenReadAsync())
|
||||
{
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.SetSource(imageStream);
|
||||
item.Image = bitmapImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clipboardHistory.Add(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Loading clipboard history failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClipboardHistoryItemDeleteButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (sender is MenuFlyoutItem btn)
|
||||
{
|
||||
ClipboardItem item = btn.CommandParameter as ClipboardItem;
|
||||
Clipboard.DeleteItemFromHistory(item.Item);
|
||||
clipboardHistory.Remove(item);
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteClipboardItemDeletedEvent());
|
||||
}
|
||||
}
|
||||
|
||||
private void PasteAsPlain()
|
||||
{
|
||||
ViewModel.ToPlainTextFunction();
|
||||
}
|
||||
|
||||
private void PasteAsMarkdown()
|
||||
{
|
||||
ViewModel.ToMarkdownFunction();
|
||||
}
|
||||
|
||||
private void PasteAsJson()
|
||||
{
|
||||
ViewModel.ToJsonFunction();
|
||||
}
|
||||
|
||||
private void PasteOptionsListView_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
if (e.ClickedItem is PasteFormat format)
|
||||
{
|
||||
switch (format.Format)
|
||||
{
|
||||
case PasteFormats.PlainText:
|
||||
{
|
||||
PasteAsPlain();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteFormatClickedEvent(PasteFormats.PlainText));
|
||||
break;
|
||||
}
|
||||
|
||||
case PasteFormats.Markdown:
|
||||
{
|
||||
PasteAsMarkdown();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteFormatClickedEvent(PasteFormats.Markdown));
|
||||
break;
|
||||
}
|
||||
|
||||
case PasteFormats.Json:
|
||||
{
|
||||
PasteAsJson();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteFormatClickedEvent(PasteFormats.Json));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void KeyboardAccelerator_Invoked(Microsoft.UI.Xaml.Input.KeyboardAccelerator sender, Microsoft.UI.Xaml.Input.KeyboardAcceleratorInvokedEventArgs args)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
switch (sender.Key)
|
||||
{
|
||||
case VirtualKey.Escape:
|
||||
{
|
||||
(App.Current as App).GetMainWindow().Close();
|
||||
break;
|
||||
}
|
||||
|
||||
case VirtualKey.Number1:
|
||||
{
|
||||
PasteAsPlain();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteInAppKeyboardShortcutEvent(PasteFormats.PlainText));
|
||||
break;
|
||||
}
|
||||
|
||||
case VirtualKey.Number2:
|
||||
{
|
||||
PasteAsMarkdown();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteInAppKeyboardShortcutEvent(PasteFormats.Markdown));
|
||||
break;
|
||||
}
|
||||
|
||||
case VirtualKey.Number3:
|
||||
{
|
||||
PasteAsJson();
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteInAppKeyboardShortcutEvent(PasteFormats.Json));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Page_KeyDown(object sender, Microsoft.UI.Xaml.Input.KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key == VirtualKey.Escape)
|
||||
{
|
||||
(App.Current as App).GetMainWindow().Close();
|
||||
}
|
||||
}
|
||||
|
||||
private async void ClipboardHistory_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
var item = e.ClickedItem as ClipboardItem;
|
||||
if (item is not null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Content))
|
||||
{
|
||||
ClipboardHelper.SetClipboardTextContent(item.Content);
|
||||
}
|
||||
else if (item.Image is not null)
|
||||
{
|
||||
RandomAccessStreamReference image = null;
|
||||
image = await item.Item.Content.GetBitmapAsync();
|
||||
ClipboardHelper.SetClipboardImageContent(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:AdvancedPaste">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///AdvancedPasteXAML/Controls/AnimatedContentControl/AnimatedContentControl.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 468 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 432 B |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 637 B |
After Width: | Height: | Size: 283 B |
After Width: | Height: | Size: 456 B |
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,133 @@
|
||||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Azure;
|
||||
using Azure.AI.OpenAI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Windows.Security.Credentials;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
public class AICompletionsHelper
|
||||
{
|
||||
// Return Response and Status code from the request.
|
||||
public struct AICompletionsResponse
|
||||
{
|
||||
public AICompletionsResponse(string response, int apiRequestStatus)
|
||||
{
|
||||
Response = response;
|
||||
ApiRequestStatus = apiRequestStatus;
|
||||
}
|
||||
|
||||
public string Response { get; }
|
||||
|
||||
public int ApiRequestStatus { get; }
|
||||
}
|
||||
|
||||
private string _openAIKey;
|
||||
|
||||
public bool IsAIEnabled => !string.IsNullOrEmpty(this._openAIKey);
|
||||
|
||||
public AICompletionsHelper()
|
||||
{
|
||||
this._openAIKey = LoadOpenAIKey();
|
||||
}
|
||||
|
||||
public void SetOpenAIKey(string openAIKey)
|
||||
{
|
||||
this._openAIKey = openAIKey;
|
||||
}
|
||||
|
||||
public string GetKey()
|
||||
{
|
||||
return _openAIKey;
|
||||
}
|
||||
|
||||
public static string LoadOpenAIKey()
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
|
||||
try
|
||||
{
|
||||
PasswordCredential cred = vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey");
|
||||
if (cred is not null)
|
||||
{
|
||||
return cred.Password.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public string GetAICompletion(string systemInstructions, string userMessage)
|
||||
{
|
||||
OpenAIClient azureAIClient = new OpenAIClient(_openAIKey);
|
||||
|
||||
var response = azureAIClient.GetCompletions(
|
||||
new CompletionsOptions()
|
||||
{
|
||||
DeploymentName = "gpt-3.5-turbo-instruct",
|
||||
Prompts =
|
||||
{
|
||||
systemInstructions + "\n\n" + userMessage,
|
||||
},
|
||||
Temperature = 0.01F,
|
||||
MaxTokens = 2000,
|
||||
});
|
||||
|
||||
if (response.Value.Choices[0].FinishReason == "length")
|
||||
{
|
||||
Console.WriteLine("Cut off due to length constraints");
|
||||
}
|
||||
|
||||
return response.Value.Choices[0].Text;
|
||||
}
|
||||
|
||||
public AICompletionsResponse AIFormatString(string inputInstructions, string inputString)
|
||||
{
|
||||
string systemInstructions = $@"You are tasked with reformatting user's clipboard data. Use the user's instructions, and the content of their clipboard below to edit their clipboard content as they have requested it.
|
||||
|
||||
Do not output anything else besides the reformatted clipboard content.";
|
||||
|
||||
string userMessage = $@"User instructions:
|
||||
{inputInstructions}
|
||||
|
||||
Clipboard Content:
|
||||
{inputString}
|
||||
|
||||
Output:
|
||||
";
|
||||
|
||||
string aiResponse = null;
|
||||
int apiRequestStatus = (int)HttpStatusCode.OK;
|
||||
try
|
||||
{
|
||||
aiResponse = this.GetAICompletion(systemInstructions, userMessage);
|
||||
}
|
||||
catch (Azure.RequestFailedException error)
|
||||
{
|
||||
Logger.LogError("GetAICompletion failed", error);
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteGenerateCustomErrorEvent(error.Message));
|
||||
apiRequestStatus = error.Status;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Logger.LogError("GetAICompletion failed", error);
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AdvancedPasteGenerateCustomErrorEvent(error.Message));
|
||||
apiRequestStatus = -1;
|
||||
}
|
||||
|
||||
return new AICompletionsResponse(aiResponse, apiRequestStatus);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.System;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class ClipboardHelper
|
||||
{
|
||||
internal static void SetClipboardTextContent(string text)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
DataPackage output = new();
|
||||
output.SetText(text);
|
||||
Clipboard.SetContentWithOptions(output, null);
|
||||
|
||||
// TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
|
||||
// Calling inside a loop makes it work.
|
||||
bool flushed = false;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (flushed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Clipboard.Flush();
|
||||
}).Wait();
|
||||
|
||||
flushed = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Clipboard.Flush() failed", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetClipboardImageContent(RandomAccessStreamReference image)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (image is not null)
|
||||
{
|
||||
DataPackage output = new();
|
||||
output.SetBitmap(image);
|
||||
Clipboard.SetContentWithOptions(output, null);
|
||||
|
||||
// TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
|
||||
// Calling inside a loop makes it work.
|
||||
bool flushed = false;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (flushed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
Clipboard.Flush();
|
||||
}).Wait();
|
||||
|
||||
flushed = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Clipboard.Flush() failed", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to send a single key event
|
||||
private static void SendSingleKeyboardInput(short keyCode, uint keyStatus)
|
||||
{
|
||||
UIntPtr ignoreKeyEventFlag = (UIntPtr)0x5555;
|
||||
|
||||
NativeMethods.INPUT inputShift = new NativeMethods.INPUT
|
||||
{
|
||||
type = NativeMethods.INPUTTYPE.INPUT_KEYBOARD,
|
||||
data = new NativeMethods.InputUnion
|
||||
{
|
||||
ki = new NativeMethods.KEYBDINPUT
|
||||
{
|
||||
wVk = keyCode,
|
||||
dwFlags = keyStatus,
|
||||
|
||||
// Any keyevent with the extraInfo set to this value will be ignored by the keyboard hook and sent to the system instead.
|
||||
dwExtraInfo = ignoreKeyEventFlag,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[] { inputShift };
|
||||
_ = NativeMethods.SendInput(1, inputs, NativeMethods.INPUT.Size);
|
||||
}
|
||||
|
||||
internal static void SendPasteKeyCombination()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftControl, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.RightControl, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftWindows, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.RightWindows, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftShift, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.RightShift, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.LeftMenu, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.RightMenu, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
|
||||
// Send Ctrl + V
|
||||
SendSingleKeyboardInput((short)VirtualKey.Control, (uint)NativeMethods.KeyEventF.KeyDown);
|
||||
SendSingleKeyboardInput((short)VirtualKey.V, (uint)NativeMethods.KeyEventF.KeyDown);
|
||||
SendSingleKeyboardInput((short)VirtualKey.V, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
SendSingleKeyboardInput((short)VirtualKey.Control, (uint)NativeMethods.KeyEventF.KeyUp);
|
||||
|
||||
Logger.LogInfo("Paste sent");
|
||||
}
|
||||
}
|
||||
}
|
12
src/modules/AdvancedPaste/AdvancedPaste/Helpers/Constants.cs
Normal file
@ -0,0 +1,12 @@
|
||||
// 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 AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
internal static readonly string AdvancedPasteModuleName = "AdvancedPaste";
|
||||
internal static readonly string LastQueryJsonFileName = "lastQuery.json";
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// 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 AdvancedPaste.Settings
|
||||
{
|
||||
public interface IUserSettings
|
||||
{
|
||||
public bool ShowCustomPreview { get; }
|
||||
|
||||
public bool SendPasteKeyCombination { get; }
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using ManagedCommon;
|
||||
using Newtonsoft.Json;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class JsonHelper
|
||||
{
|
||||
internal static string ToJsonFromXmlOrCsv(DataPackageView clipboardData)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (clipboardData == null || !clipboardData.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
Logger.LogWarning("Clipboard does not contain text data");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
|
||||
string text = Task.Run(async () =>
|
||||
{
|
||||
string plainText = await clipboardData.GetTextAsync() as string;
|
||||
return plainText;
|
||||
}).Result;
|
||||
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
|
||||
|
||||
string jsonText = string.Empty;
|
||||
|
||||
// Try convert XML
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(text);
|
||||
jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed parsing input as xml", ex);
|
||||
}
|
||||
|
||||
// Try convert CSV
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonText))
|
||||
{
|
||||
var csv = new List<string[]>();
|
||||
|
||||
foreach (var line in text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
csv.Add(line.Split(","));
|
||||
}
|
||||
|
||||
jsonText = JsonConvert.SerializeObject(csv, Newtonsoft.Json.Formatting.Indented);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed parsing input as csv", ex);
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(jsonText) ? text : jsonText;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
// 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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using HtmlAgilityPack;
|
||||
using ManagedCommon;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class MarkdownHelper
|
||||
{
|
||||
public static string ToMarkdown(DataPackageView clipboardData)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (clipboardData == null)
|
||||
{
|
||||
Logger.LogWarning("Clipboard does not contain data");
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string data = string.Empty;
|
||||
|
||||
if (clipboardData.Contains(StandardDataFormats.Html))
|
||||
{
|
||||
data = Task.Run(async () =>
|
||||
{
|
||||
string data = await clipboardData.GetHtmlFormatAsync() as string;
|
||||
return data;
|
||||
}).Result;
|
||||
}
|
||||
else if (clipboardData.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
data = Task.Run(async () =>
|
||||
{
|
||||
string plainText = await clipboardData.GetTextAsync() as string;
|
||||
return plainText;
|
||||
}).Result;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(data))
|
||||
{
|
||||
string cleanedHtml = CleanHtml(data);
|
||||
|
||||
return ConvertHtmlToMarkdown(cleanedHtml);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static string PasteAsPlainTextFromClipboard(DataPackageView clipboardData)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (clipboardData != null)
|
||||
{
|
||||
if (!clipboardData.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
Logger.LogWarning("Clipboard does not contain text data");
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
string plainText = await clipboardData.GetTextAsync() as string;
|
||||
return plainText;
|
||||
}).Result;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static string CleanHtml(string html)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
// Remove the "StartFragment" and "EndFragment" comments
|
||||
html = Regex.Replace(html, @"<!--StartFragment-->|<!--EndFragment-->", string.Empty);
|
||||
|
||||
HtmlDocument document = new HtmlDocument();
|
||||
document.LoadHtml(html);
|
||||
|
||||
// Remove unwanted HTML elements
|
||||
RemoveUnwantedElements(document.DocumentNode);
|
||||
|
||||
// Remove inline styles
|
||||
RemoveInlineStyles(document.DocumentNode);
|
||||
|
||||
// Clean up line breaks and whitespace
|
||||
CleanUpWhitespace(document.DocumentNode);
|
||||
|
||||
// Serialize the cleaned HTML back to string
|
||||
using (var writer = new System.IO.StringWriter())
|
||||
{
|
||||
document.Save(writer);
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveUnwantedElements(HtmlNode node)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
// Remove specific elements by tag name, CSS class, or other attributes
|
||||
// Example: Remove all <script> elements
|
||||
foreach (var scriptNode in node.DescendantsAndSelf("script").ToArray())
|
||||
{
|
||||
scriptNode.Remove();
|
||||
}
|
||||
|
||||
// Ignore specific elements like <sup> elements
|
||||
foreach (var ignoredElement in node.DescendantsAndSelf("sup").ToArray())
|
||||
{
|
||||
ignoredElement.Remove();
|
||||
}
|
||||
|
||||
// Ignore specific elements like <o:p> element added by MS Word
|
||||
foreach (var ignoredElement in node.DescendantsAndSelf("o:p").ToArray())
|
||||
{
|
||||
ignoredElement.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveInlineStyles(HtmlNode node)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
// Remove inline styles from elements
|
||||
foreach (var elementNode in node.DescendantsAndSelf())
|
||||
{
|
||||
elementNode.Attributes.Remove("style");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CleanUpWhitespace(HtmlNode node)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
// Clean up line breaks and excessive whitespace
|
||||
if (node.NodeType == HtmlNodeType.Text)
|
||||
{
|
||||
node.InnerHtml = Regex.Replace(node.InnerHtml, @"\s{2,}", " ");
|
||||
node.InnerHtml = Regex.Replace(node.InnerHtml, @"[\r\n]+", string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var childNode in node.ChildNodes.ToArray())
|
||||
{
|
||||
CleanUpWhitespace(childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertHtmlToMarkdown(string html)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
// Perform the conversion from HTML to Markdown using your chosen library or method
|
||||
var converter = new ReverseMarkdown.Converter();
|
||||
string markdown = converter.Convert(html);
|
||||
return markdown;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// 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.Threading;
|
||||
using Microsoft.UI.Dispatching;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
public static class NativeEventWaiter
|
||||
{
|
||||
public static void WaitForEventLoop(string eventName, Action callback)
|
||||
{
|
||||
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
new Thread(() =>
|
||||
{
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
||||
while (true)
|
||||
{
|
||||
if (eventHandle.WaitOne())
|
||||
{
|
||||
dispatcherQueue.TryEnqueue(() => callback());
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
}
|
104
src/modules/AdvancedPaste/AdvancedPaste/Helpers/NativeMethods.cs
Normal file
@ -0,0 +1,104 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
internal struct INPUT
|
||||
{
|
||||
internal INPUTTYPE type;
|
||||
internal InputUnion data;
|
||||
|
||||
internal static int Size
|
||||
{
|
||||
get { return Marshal.SizeOf(typeof(INPUT)); }
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
internal struct InputUnion
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal MOUSEINPUT mi;
|
||||
[FieldOffset(0)]
|
||||
internal KEYBDINPUT ki;
|
||||
[FieldOffset(0)]
|
||||
internal HARDWAREINPUT hi;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
internal struct MOUSEINPUT
|
||||
{
|
||||
internal int dx;
|
||||
internal int dy;
|
||||
internal int mouseData;
|
||||
internal uint dwFlags;
|
||||
internal uint time;
|
||||
internal UIntPtr dwExtraInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
internal struct KEYBDINPUT
|
||||
{
|
||||
internal short wVk;
|
||||
internal short wScan;
|
||||
internal uint dwFlags;
|
||||
internal int time;
|
||||
internal UIntPtr dwExtraInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
internal struct HARDWAREINPUT
|
||||
{
|
||||
internal int uMsg;
|
||||
internal short wParamL;
|
||||
internal short wParamH;
|
||||
}
|
||||
|
||||
internal enum INPUTTYPE : uint
|
||||
{
|
||||
INPUT_MOUSE = 0,
|
||||
INPUT_KEYBOARD = 1,
|
||||
INPUT_HARDWARE = 2,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum KeyEventF
|
||||
{
|
||||
KeyDown = 0x0000,
|
||||
ExtendedKey = 0x0001,
|
||||
KeyUp = 0x0002,
|
||||
Unicode = 0x0004,
|
||||
Scancode = 0x0008,
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
internal static extern short GetAsyncKeyState(int vKey);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct PointInter
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
|
||||
public static explicit operator System.Windows.Point(PointInter point) => new System.Windows.Point(point.X, point.Y);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern bool GetCursorPos(out PointInter lpPoint);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// 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.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace AdvancedPaste.Helpers
|
||||
{
|
||||
internal static class ResourceLoaderInstance
|
||||
{
|
||||
internal static ResourceLoader ResourceLoader { get; private set; }
|
||||
|
||||
static ResourceLoaderInstance()
|
||||
{
|
||||
ResourceLoader = new ResourceLoader("PowerToys.AdvancedPaste.pri");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
// 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.Abstractions;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
|
||||
namespace AdvancedPaste.Settings
|
||||
{
|
||||
internal sealed class UserSettings : IUserSettings
|
||||
{
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
|
||||
private const string AdvancedPasteModuleName = "AdvancedPaste";
|
||||
private const int MaxNumberOfRetry = 5;
|
||||
|
||||
public bool ShowCustomPreview { get; private set; }
|
||||
|
||||
public bool SendPasteKeyCombination { get; private set; }
|
||||
|
||||
public UserSettings()
|
||||
{
|
||||
_settingsUtils = new SettingsUtils();
|
||||
|
||||
ShowCustomPreview = true;
|
||||
SendPasteKeyCombination = true;
|
||||
|
||||
LoadSettingsFromJson();
|
||||
|
||||
_watcher = Helper.GetFileWatcher(AdvancedPasteModuleName, "settings.json", () => LoadSettingsFromJson());
|
||||
}
|
||||
|
||||
private void LoadSettingsFromJson()
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
var retry = true;
|
||||
var retryCount = 0;
|
||||
|
||||
while (retry)
|
||||
{
|
||||
try
|
||||
{
|
||||
retryCount++;
|
||||
|
||||
if (!_settingsUtils.SettingsExists(AdvancedPasteModuleName))
|
||||
{
|
||||
Logger.LogInfo("AdvancedPaste settings.json was missing, creating a new one");
|
||||
var defaultSettings = new AdvancedPasteSettings();
|
||||
defaultSettings.Save(_settingsUtils);
|
||||
}
|
||||
|
||||
var settings = _settingsUtils.GetSettingsOrDefault<AdvancedPasteSettings>(AdvancedPasteModuleName);
|
||||
if (settings != null)
|
||||
{
|
||||
ShowCustomPreview = settings.Properties.ShowCustomPreview;
|
||||
SendPasteKeyCombination = settings.Properties.SendPasteKeyCombination;
|
||||
}
|
||||
|
||||
retry = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (retryCount > MaxNumberOfRetry)
|
||||
{
|
||||
retry = false;
|
||||
}
|
||||
|
||||
Logger.LogError("Failed to read changed settings", ex);
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// 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.UI.Xaml.Media.Imaging;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace AdvancedPaste.Models
|
||||
{
|
||||
public class ClipboardItem
|
||||
{
|
||||
public string Content { get; set; }
|
||||
|
||||
public ClipboardHistoryItem Item { get; set; }
|
||||
|
||||
public BitmapImage Image { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json;
|
||||
using AdvancedPaste.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace AdvancedPaste.Models
|
||||
{
|
||||
internal sealed class CustomQuery : ISettingsConfig
|
||||
{
|
||||
public string Query { get; set; }
|
||||
|
||||
public string ClipboardData { get; set; }
|
||||
|
||||
public string GetModuleName() => Constants.AdvancedPasteModuleName;
|
||||
|
||||
public string ToJsonString() => JsonSerializer.Serialize(this);
|
||||
|
||||
public override string ToString()
|
||||
=> JsonSerializer.Serialize(this);
|
||||
|
||||
public bool UpgradeSettingsConfiguration() => false;
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// 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.UI.Xaml.Controls;
|
||||
|
||||
namespace AdvancedPaste.Models
|
||||
{
|
||||
public class PasteFormat
|
||||
{
|
||||
public IconElement Icon { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public PasteFormats Format { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// 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 AdvancedPaste.Models
|
||||
{
|
||||
public enum PasteFormats
|
||||
{
|
||||
PlainText,
|
||||
Markdown,
|
||||
Json,
|
||||
Custom,
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
ShowWindow
|
45
src/modules/AdvancedPaste/AdvancedPaste/Program.cs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
|
||||
namespace AdvancedPaste
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Logger.InitializeLogger("\\AdvancedPaste\\Logs");
|
||||
|
||||
WinRT.ComWrappersSupport.InitializeComWrappers();
|
||||
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredAdvancedPasteEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
return;
|
||||
}
|
||||
|
||||
var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_AdvancedPaste_Instance");
|
||||
|
||||
if (instanceKey.IsCurrent)
|
||||
{
|
||||
Microsoft.UI.Xaml.Application.Start((p) =>
|
||||
{
|
||||
var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread());
|
||||
SynchronizationContext.SetSynchronizationContext(context);
|
||||
_ = new App();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Another instance of AdvancedPasteUI is running. Exiting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root"
|
||||
xmlns=""
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AIMistakeNote.Text" xml:space="preserve">
|
||||
<value>AI can make mistakes.</value>
|
||||
</data>
|
||||
<data name="ClipboardDataTypeMismatchWarning" xml:space="preserve">
|
||||
<value>Clipboard data is not text</value>
|
||||
</data>
|
||||
<data name="OpenAINotConfigured" xml:space="preserve">
|
||||
<value>To custom with AI not enabled</value>
|
||||
</data>
|
||||
<data name="OpenAIApiKeyUnauthorized" xml:space="preserve">
|
||||
<value>Invalid API key or endpoint</value>
|
||||
</data>
|
||||
<data name="OpenAIApiKeyTooManyRequests" xml:space="preserve">
|
||||
<value>API key quota exceeded</value>
|
||||
</data>
|
||||
<data name="OpenAIApiKeyError" xml:space="preserve">
|
||||
<value>OpenAI request failed with status code: </value>
|
||||
</data>
|
||||
<data name="ClipboardHistoryButton.Text" xml:space="preserve">
|
||||
<value>Clipboard history</value>
|
||||
</data>
|
||||
<data name="ClipboardHistoryItemDeleteButton.Text" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<data name="CustomFormatTextBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Describe what format you want..</value>
|
||||
</data>
|
||||
<data name="InputTxtBoxTooltip.Text" xml:space="preserve">
|
||||
<value>Describe what format you want..</value>
|
||||
</data>
|
||||
<data name="LearnMoreLink.Text" xml:space="preserve">
|
||||
<value>Privacy</value>
|
||||
</data>
|
||||
<data name="LoadingText.Text" xml:space="preserve">
|
||||
<value>Connecting to AI services and generating output..</value>
|
||||
</data>
|
||||
<data name="PasteAsJson" xml:space="preserve">
|
||||
<value>Paste as JSON</value>
|
||||
</data>
|
||||
<data name="PasteAsMarkdown" xml:space="preserve">
|
||||
<value>Paste as markdown</value>
|
||||
</data>
|
||||
<data name="PasteAsPlainText" xml:space="preserve">
|
||||
<value>Paste as plain text</value>
|
||||
</data>
|
||||
<data name="PasteButtonAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Paste</value>
|
||||
</data>
|
||||
<data name="PasteText.Text" xml:space="preserve">
|
||||
<value>Paste</value>
|
||||
</data>
|
||||
<data name="ResultTitleTxt.Text" xml:space="preserve">
|
||||
<value>Result</value>
|
||||
</data>
|
||||
<data name="RecallBtnToolTip.Text" xml:space="preserve">
|
||||
<value>Revert to the last prompt and clipboard data</value>
|
||||
</data>
|
||||
<data name="RecallButtonAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Revert to the last prompt and clipboard data</value>
|
||||
</data>
|
||||
<data name="SendBtnToolTip.Text" xml:space="preserve">
|
||||
<value>Generate and paste data</value>
|
||||
</data>
|
||||
<data name="RegenerateBtnToolTip.Text" xml:space="preserve">
|
||||
<value>Regenerate</value>
|
||||
</data>
|
||||
<data name="RegenerateBtnAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Regenerate</value>
|
||||
</data>
|
||||
<data name="SendButtonAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Generate and paste data</value>
|
||||
</data>
|
||||
<data name="SettingsBtn.Content" xml:space="preserve">
|
||||
<value>Open settings</value>
|
||||
</data>
|
||||
<data name="SettingsBtn.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Open settings</value>
|
||||
</data>
|
||||
<data name="ThumbsDownFeedback.Text" xml:space="preserve">
|
||||
<value>Thumbs down feedback</value>
|
||||
</data>
|
||||
<data name="ThumbsUpFeedback.Text" xml:space="preserve">
|
||||
<value>Thumbs up feedback</value>
|
||||
</data>
|
||||
<data name="WindowTitle" xml:space="preserve">
|
||||
<value>Advanced Paste</value>
|
||||
</data>
|
||||
<data name="PreviousResultBtnToolTip.Text" xml:space="preserve">
|
||||
<value>Previous result</value>
|
||||
</data>
|
||||
<data name="PreviousResultBtnAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Previous result</value>
|
||||
</data>
|
||||
<data name="NextResultBtnToolTip.Text" xml:space="preserve">
|
||||
<value>Next result</value>
|
||||
</data>
|
||||
<data name="NextResultBtnAutomation.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Next result</value>
|
||||
</data>
|
||||
<data name="PrivacyLink.Text" xml:space="preserve">
|
||||
<value>OpenAI Privacy</value>
|
||||
</data>
|
||||
<data name="TermsLink.Text" xml:space="preserve">
|
||||
<value>OpenAI Terms</value>
|
||||
</data>
|
||||
</root>
|
@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteClipboardItemDeletedEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// 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.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteCustomFormatOutputThumbUpDownEvent : EventBase, IEvent
|
||||
{
|
||||
public bool PositiveFeedback { get; set; }
|
||||
|
||||
public AdvancedPasteCustomFormatOutputThumbUpDownEvent(bool positiveFeedback)
|
||||
{
|
||||
PositiveFeedback = positiveFeedback;
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// 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.Tracing;
|
||||
using AdvancedPaste.Models;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteFormatClickedEvent : EventBase, IEvent
|
||||
{
|
||||
public PasteFormats PasteFormat { get; set; }
|
||||
|
||||
public AdvancedPasteFormatClickedEvent(PasteFormats format)
|
||||
{
|
||||
this.PasteFormat = format;
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// 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.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteGenerateCustomErrorEvent : EventBase, IEvent
|
||||
{
|
||||
public string Error { get; set; }
|
||||
|
||||
public AdvancedPasteGenerateCustomErrorEvent(string error)
|
||||
{
|
||||
this.Error = error;
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteGenerateCustomFormatEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
// 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.Tracing;
|
||||
using AdvancedPaste.Models;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace AdvancedPaste.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class AdvancedPasteInAppKeyboardShortcutEvent : EventBase, IEvent
|
||||
{
|
||||
public PasteFormats PasteFormat { get; set; }
|
||||
|
||||
public AdvancedPasteInAppKeyboardShortcutEvent(PasteFormats format)
|
||||
{
|
||||
this.PasteFormat = format;
|
||||
}
|
||||
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,410 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using AdvancedPaste.Helpers;
|
||||
using AdvancedPaste.Models;
|
||||
using AdvancedPaste.Settings;
|
||||
using Common.UI;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Win32;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using WinUIEx;
|
||||
|
||||
namespace AdvancedPaste.ViewModels
|
||||
{
|
||||
public partial class OptionsViewModel : ObservableObject
|
||||
{
|
||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
private App app = App.Current as App;
|
||||
|
||||
private AICompletionsHelper aiHelper;
|
||||
|
||||
private UserSettings _userSettings;
|
||||
|
||||
public DataPackageView ClipboardData { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(InputTxtBoxPlaceholderText))]
|
||||
[NotifyPropertyChangedFor(nameof(IsCustomAIEnabled))]
|
||||
private bool _isClipboardDataText;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(InputTxtBoxPlaceholderText))]
|
||||
private bool _isCustomAIEnabled;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _clipboardHistoryEnabled;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(InputTxtBoxErrorText))]
|
||||
private int _apiRequestStatus;
|
||||
|
||||
public OptionsViewModel()
|
||||
{
|
||||
aiHelper = new AICompletionsHelper();
|
||||
_userSettings = new UserSettings();
|
||||
|
||||
IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled;
|
||||
|
||||
ApiRequestStatus = (int)HttpStatusCode.OK;
|
||||
|
||||
GeneratedResponses = new ObservableCollection<string>();
|
||||
GeneratedResponses.CollectionChanged += (s, e) =>
|
||||
{
|
||||
OnPropertyChanged(nameof(HasMultipleResponses));
|
||||
OnPropertyChanged(nameof(CurrentIndexDisplay));
|
||||
};
|
||||
|
||||
ClipboardHistoryEnabled = IsClipboardHistoryEnabled();
|
||||
GetClipboardData();
|
||||
}
|
||||
|
||||
public void GetClipboardData()
|
||||
{
|
||||
ClipboardData = Clipboard.GetContent();
|
||||
IsClipboardDataText = ClipboardData.Contains(StandardDataFormats.Text);
|
||||
}
|
||||
|
||||
public void OnShow()
|
||||
{
|
||||
GetClipboardData();
|
||||
|
||||
var openAIKey = AICompletionsHelper.LoadOpenAIKey();
|
||||
var currentKey = aiHelper.GetKey();
|
||||
bool keyChanged = openAIKey != currentKey;
|
||||
|
||||
if (keyChanged)
|
||||
{
|
||||
app.GetMainWindow().StartLoading();
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
aiHelper.SetOpenAIKey(openAIKey);
|
||||
}).ContinueWith(
|
||||
(t) =>
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
app.GetMainWindow().FinishLoading(aiHelper.IsAIEnabled);
|
||||
OnPropertyChanged(nameof(InputTxtBoxPlaceholderText));
|
||||
IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled;
|
||||
});
|
||||
},
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsCustomAIEnabled = IsClipboardDataText && aiHelper.IsAIEnabled;
|
||||
}
|
||||
|
||||
ClipboardHistoryEnabled = IsClipboardHistoryEnabled();
|
||||
GeneratedResponses.Clear();
|
||||
}
|
||||
|
||||
// List to store generated responses
|
||||
public ObservableCollection<string> GeneratedResponses { get; set; } = new ObservableCollection<string>();
|
||||
|
||||
// Index to keep track of the current response
|
||||
private int _currentResponseIndex;
|
||||
|
||||
public int CurrentResponseIndex
|
||||
{
|
||||
get => _currentResponseIndex;
|
||||
set
|
||||
{
|
||||
if (value >= 0 && value < GeneratedResponses.Count)
|
||||
{
|
||||
SetProperty(ref _currentResponseIndex, value);
|
||||
CustomFormatResult = GeneratedResponses[_currentResponseIndex];
|
||||
OnPropertyChanged(nameof(CurrentIndexDisplay));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasMultipleResponses
|
||||
{
|
||||
get => GeneratedResponses.Count > 1;
|
||||
}
|
||||
|
||||
public string CurrentIndexDisplay => $"{CurrentResponseIndex + 1}/{GeneratedResponses.Count}";
|
||||
|
||||
public string InputTxtBoxPlaceholderText
|
||||
{
|
||||
get
|
||||
{
|
||||
app.GetMainWindow().ClearInputText();
|
||||
|
||||
if (!aiHelper.IsAIEnabled)
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAINotConfigured");
|
||||
}
|
||||
else if (!IsClipboardDataText)
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("ClipboardDataTypeMismatchWarning");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("CustomFormatTextBox/PlaceholderText");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string InputTxtBoxErrorText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ApiRequestStatus != (int)HttpStatusCode.OK)
|
||||
{
|
||||
if (ApiRequestStatus == (int)HttpStatusCode.TooManyRequests)
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyTooManyRequests");
|
||||
}
|
||||
else if (ApiRequestStatus == (int)HttpStatusCode.Unauthorized)
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyUnauthorized");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResourceLoaderInstance.ResourceLoader.GetString("OpenAIApiKeyError") + ApiRequestStatus.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string _customFormatResult;
|
||||
|
||||
[RelayCommand]
|
||||
public void PasteCustom()
|
||||
{
|
||||
PasteCustomFunction(GeneratedResponses[CurrentResponseIndex]);
|
||||
}
|
||||
|
||||
// Command to select the previous custom format
|
||||
[RelayCommand]
|
||||
public void PreviousCustomFormat()
|
||||
{
|
||||
if (CurrentResponseIndex > 0)
|
||||
{
|
||||
CurrentResponseIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
// Command to select the next custom format
|
||||
[RelayCommand]
|
||||
public void NextCustomFormat()
|
||||
{
|
||||
if (CurrentResponseIndex < GeneratedResponses.Count - 1)
|
||||
{
|
||||
CurrentResponseIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Command to open the Settings window.
|
||||
[RelayCommand]
|
||||
public void OpenSettings()
|
||||
{
|
||||
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.AdvancedPaste, true);
|
||||
(App.Current as App).GetMainWindow().Close();
|
||||
}
|
||||
|
||||
private void SetClipboardContentAndHideWindow(string content)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
ClipboardHelper.SetClipboardTextContent(content);
|
||||
}
|
||||
|
||||
if (app.GetMainWindow() != null)
|
||||
{
|
||||
Windows.Win32.Foundation.HWND hwnd = (Windows.Win32.Foundation.HWND)app.GetMainWindow().GetWindowHandle();
|
||||
Windows.Win32.PInvoke.ShowWindow(hwnd, Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ToPlainTextFunction()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
string outputString = MarkdownHelper.PasteAsPlainTextFromClipboard(ClipboardData);
|
||||
|
||||
SetClipboardContentAndHideWindow(outputString);
|
||||
|
||||
if (_userSettings.SendPasteKeyCombination)
|
||||
{
|
||||
ClipboardHelper.SendPasteKeyCombination();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal void ToMarkdownFunction(bool pasteAlways = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
string outputString = MarkdownHelper.ToMarkdown(ClipboardData);
|
||||
|
||||
SetClipboardContentAndHideWindow(outputString);
|
||||
|
||||
if (pasteAlways || _userSettings.SendPasteKeyCombination)
|
||||
{
|
||||
ClipboardHelper.SendPasteKeyCombination();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal void ToJsonFunction(bool pasteAlways = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
string jsonText = JsonHelper.ToJsonFromXmlOrCsv(ClipboardData);
|
||||
|
||||
SetClipboardContentAndHideWindow(jsonText);
|
||||
|
||||
if (pasteAlways || _userSettings.SendPasteKeyCombination)
|
||||
{
|
||||
ClipboardHelper.SendPasteKeyCombination();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<string> GenerateCustomFunction(string inputInstructions)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(inputInstructions))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (ClipboardData == null || !ClipboardData.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
Logger.LogWarning("Clipboard does not contain text data");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string currentClipboardText = await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string text = await ClipboardData.GetTextAsync() as string;
|
||||
return text;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Couldn't get text from the clipboard. Resume with empty text.
|
||||
return string.Empty;
|
||||
}
|
||||
});
|
||||
|
||||
if (string.IsNullOrWhiteSpace(currentClipboardText))
|
||||
{
|
||||
Logger.LogWarning("Clipboard has no usable text data");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var aiResponse = await Task.Run(() => aiHelper.AIFormatString(inputInstructions, currentClipboardText));
|
||||
|
||||
string aiOutput = aiResponse.Response;
|
||||
ApiRequestStatus = aiResponse.ApiRequestStatus;
|
||||
|
||||
GeneratedResponses.Add(aiOutput);
|
||||
CurrentResponseIndex = GeneratedResponses.Count - 1;
|
||||
return aiOutput;
|
||||
}
|
||||
|
||||
internal void PasteCustomFunction(string text)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
SetClipboardContentAndHideWindow(text);
|
||||
|
||||
if (_userSettings.SendPasteKeyCombination)
|
||||
{
|
||||
ClipboardHelper.SendPasteKeyCombination();
|
||||
}
|
||||
}
|
||||
|
||||
internal CustomQuery RecallPreviousCustomQuery()
|
||||
{
|
||||
return LoadPreviousQuery();
|
||||
}
|
||||
|
||||
internal void SaveQuery(string inputQuery)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
DataPackageView clipboardData = Clipboard.GetContent();
|
||||
|
||||
if (clipboardData == null || !clipboardData.Contains(StandardDataFormats.Text))
|
||||
{
|
||||
Logger.LogWarning("Clipboard does not contain text data");
|
||||
return;
|
||||
}
|
||||
|
||||
string currentClipboardText = Task.Run(async () =>
|
||||
{
|
||||
string text = await clipboardData.GetTextAsync() as string;
|
||||
return text;
|
||||
}).Result;
|
||||
|
||||
var queryData = new CustomQuery
|
||||
{
|
||||
Query = inputQuery,
|
||||
ClipboardData = currentClipboardText,
|
||||
};
|
||||
|
||||
SettingsUtils utils = new SettingsUtils();
|
||||
utils.SaveSettings(queryData.ToString(), Constants.AdvancedPasteModuleName, Constants.LastQueryJsonFileName);
|
||||
}
|
||||
|
||||
internal CustomQuery LoadPreviousQuery()
|
||||
{
|
||||
SettingsUtils utils = new SettingsUtils();
|
||||
var query = utils.GetSettings<CustomQuery>(Constants.AdvancedPasteModuleName, Constants.LastQueryJsonFileName);
|
||||
return query;
|
||||
}
|
||||
|
||||
private bool IsClipboardHistoryEnabled()
|
||||
{
|
||||
string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Clipboard\";
|
||||
try
|
||||
{
|
||||
int enableClipboardHistory = (int)Registry.GetValue(registryKey, "EnableClipboardHistory", false);
|
||||
return enableClipboardHistory != 0;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
22
src/modules/AdvancedPaste/AdvancedPaste/app.manifest
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0"
|
||||
xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="AdvancedPaste.app"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace AdvancedPasteConstants
|
||||
{
|
||||
// Name of the powertoy module.
|
||||
inline const std::wstring ModuleKey = L"AdvancedPaste";
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h PastePlain.base.rc PastePlain.rc" />
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h AdvancedPaste.base.rc AdvancedPaste.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{FC373B24-3293-453C-AAF5-CF2909DCEE6A}</ProjectGuid>
|
||||
<RootNamespace>PastePlain</RootNamespace>
|
||||
<ProjectName>PastePlainModuleInterface</ProjectName>
|
||||
<TargetName>PowerToys.PastePlainModuleInterface</TargetName>
|
||||
<RootNamespace>AdvancedPaste</RootNamespace>
|
||||
<ProjectName>AdvancedPasteModuleInterface</ProjectName>
|
||||
<TargetName>PowerToys.AdvancedPasteModuleInterface</TargetName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
@ -39,7 +40,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="PastePlainConstants.h" />
|
||||
<ClInclude Include="AdvancedPasteConstants.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="resource.base.h" />
|
||||
@ -62,8 +63,8 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PastePlain.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\PastePlain.rc" />
|
||||
<None Include="AdvancedPaste.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\AdvancedPaste.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources.resx">
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
@ -24,7 +25,7 @@
|
||||
<ClInclude Include="Generated Files\resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PastePlainConstants.h">
|
||||
<ClInclude Include="AdvancedPasteConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
@ -50,12 +51,12 @@
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="PastePlain.base.rc">
|
||||
<None Include="AdvancedPaste.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\PastePlain.rc">
|
||||
<ResourceCompile Include="Generated Files\AdvancedPaste.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
@ -59,7 +59,10 @@
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:schema id="root"
|
||||
xmlns=""
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
@ -117,10 +120,10 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="PastePlain_Name" xml:space="preserve">
|
||||
<value>Paste As Plain Text</value>
|
||||
<data name="Advanced_Paste_Name" xml:space="preserve">
|
||||
<value>Advanced Paste</value>
|
||||
</data>
|
||||
<data name="PastePlain_Settings_Desc" xml:space="preserve">
|
||||
<value>PowerToys integration to paste clipboard contents as plain text</value>
|
||||
<data name="Advanced_Paste_Settings_Desc" xml:space="preserve">
|
||||
<value>An AI powered tool to put your clipboard content into any format you need, focused towards developer workflows.</value>
|
||||
</data>
|
||||
</root>
|
@ -1,21 +1,20 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
#include "AdvancedPasteConstants.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include "trace.h"
|
||||
#include "Generated Files/resource.h"
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
#include "PastePlainConstants.h"
|
||||
#include <common/interop/shared_constants.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID /*lpReserved*/)
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
@ -30,7 +29,6 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/,
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -42,14 +40,15 @@ namespace
|
||||
const wchar_t JSON_KEY_CTRL[] = L"ctrl";
|
||||
const wchar_t JSON_KEY_SHIFT[] = L"shift";
|
||||
const wchar_t JSON_KEY_CODE[] = L"code";
|
||||
const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"ActivationShortcut";
|
||||
const wchar_t JSON_KEY_PASTE_AS_PLAIN_HOTKEY[] = L"paste-as-plain-hotkey";
|
||||
const wchar_t JSON_KEY_ADVANCED_PASTE_UI_HOTKEY[] = L"advanced-paste-ui-hotkey";
|
||||
const wchar_t JSON_KEY_PASTE_AS_MARKDOWN_HOTKEY[] = L"paste-as-markdown-hotkey";
|
||||
const wchar_t JSON_KEY_PASTE_AS_JSON_HOTKEY[] = L"paste-as-json-hotkey";
|
||||
const wchar_t JSON_KEY_SHOW_CUSTOM_PREVIEW[] = L"ShowCustomPreview";
|
||||
const wchar_t JSON_KEY_VALUE[] = L"value";
|
||||
}
|
||||
|
||||
struct ModuleSettings
|
||||
{
|
||||
} g_settings;
|
||||
|
||||
class PastePlain : public PowertoyModuleIface
|
||||
class AdvancedPaste : public PowertoyModuleIface
|
||||
{
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
@ -64,43 +63,128 @@ private:
|
||||
// Time to wait for process to close after sending WM_CLOSE signal
|
||||
static const int MAX_WAIT_MILLISEC = 10000;
|
||||
|
||||
Hotkey m_hotkey;
|
||||
Hotkey m_paste_as_plain_hotkey = { .win = true, .ctrl = true, .shift = false, .alt = true, .key = 'V' };
|
||||
Hotkey m_advanced_paste_ui_hotkey = { .win = true, .ctrl = false, .shift = true, .alt = false, .key = 'V' };
|
||||
Hotkey m_paste_as_markdown_hotkey{};
|
||||
Hotkey m_paste_as_json_hotkey{};
|
||||
|
||||
// Handle to event used to invoke PastePlain
|
||||
HANDLE m_hInvokeEvent;
|
||||
bool m_preview_custom_format_output = true;
|
||||
|
||||
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
|
||||
// Handle to event used to invoke AdvancedPaste
|
||||
HANDLE m_hShowUIEvent;
|
||||
HANDLE m_hPasteMarkdownEvent;
|
||||
HANDLE m_hPasteJsonEvent;
|
||||
|
||||
Hotkey parse_single_hotkey(const wchar_t* hotkey, const winrt::Windows::Data::Json::JsonObject& settingsObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
Hotkey _temp_paste_as_plain;
|
||||
auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(hotkey);
|
||||
_temp_paste_as_plain.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN);
|
||||
_temp_paste_as_plain.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT);
|
||||
_temp_paste_as_plain.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT);
|
||||
_temp_paste_as_plain.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL);
|
||||
_temp_paste_as_plain.key = static_cast<unsigned char>(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE));
|
||||
return _temp_paste_as_plain;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::error("Failed to initialize AdvancedPaste shortcut from settings. Value will keep unchanged.");
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool migrate_data_and_remove_data_file(Hotkey& old_paste_as_plain_hotkey)
|
||||
{
|
||||
const wchar_t OLD_JSON_KEY_ACTIVATION_SHORTCUT[] = L"ActivationShortcut";
|
||||
const wchar_t OLD_MODULE_KEY[] = L"PastePlain";
|
||||
|
||||
try
|
||||
{
|
||||
const std::wstring save_file_location = PTSettingsHelper::get_module_save_file_location(OLD_MODULE_KEY);
|
||||
if (std::filesystem::exists(save_file_location))
|
||||
{
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(OLD_MODULE_KEY);
|
||||
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size())
|
||||
{
|
||||
old_paste_as_plain_hotkey = parse_single_hotkey(OLD_JSON_KEY_ACTIVATION_SHORTCUT, settingsObject);
|
||||
|
||||
std::filesystem::remove(save_file_location);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception)
|
||||
{
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void parse_hotkeys(PowerToysSettings::PowerToyValues& settings)
|
||||
{
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size())
|
||||
|
||||
// Migrate Paste As PLain text shortcut
|
||||
Hotkey old_paste_as_plain_hotkey;
|
||||
bool old_data_migrated = migrate_data_and_remove_data_file(old_paste_as_plain_hotkey);
|
||||
if (old_data_migrated)
|
||||
{
|
||||
try
|
||||
m_paste_as_plain_hotkey = old_paste_as_plain_hotkey;
|
||||
|
||||
// override settings file
|
||||
json::JsonObject new_hotkey_value;
|
||||
new_hotkey_value.SetNamedValue(JSON_KEY_WIN, json::value(old_paste_as_plain_hotkey.win));
|
||||
new_hotkey_value.SetNamedValue(JSON_KEY_ALT, json::value(old_paste_as_plain_hotkey.alt));
|
||||
new_hotkey_value.SetNamedValue(JSON_KEY_SHIFT, json::value(old_paste_as_plain_hotkey.shift));
|
||||
new_hotkey_value.SetNamedValue(JSON_KEY_CTRL, json::value(old_paste_as_plain_hotkey.ctrl));
|
||||
new_hotkey_value.SetNamedValue(JSON_KEY_CODE, json::value(old_paste_as_plain_hotkey.key));
|
||||
|
||||
if (!settingsObject.HasKey(JSON_KEY_PROPERTIES))
|
||||
{
|
||||
auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
|
||||
m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN);
|
||||
m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT);
|
||||
m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT);
|
||||
m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL);
|
||||
m_hotkey.key = static_cast<unsigned char>(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::error("Failed to initialize PastePlain start shortcut");
|
||||
settingsObject.SetNamedValue(JSON_KEY_PROPERTIES, json::JsonObject{});
|
||||
}
|
||||
|
||||
settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).SetNamedValue(JSON_KEY_PASTE_AS_PLAIN_HOTKEY, new_hotkey_value);
|
||||
|
||||
|
||||
json::JsonObject ui_hotkey;
|
||||
ui_hotkey.SetNamedValue(JSON_KEY_WIN, json::value(m_advanced_paste_ui_hotkey.win));
|
||||
ui_hotkey.SetNamedValue(JSON_KEY_ALT, json::value(m_advanced_paste_ui_hotkey.alt));
|
||||
ui_hotkey.SetNamedValue(JSON_KEY_SHIFT, json::value(m_advanced_paste_ui_hotkey.shift));
|
||||
ui_hotkey.SetNamedValue(JSON_KEY_CTRL, json::value(m_advanced_paste_ui_hotkey.ctrl));
|
||||
ui_hotkey.SetNamedValue(JSON_KEY_CODE, json::value(m_advanced_paste_ui_hotkey.key));
|
||||
settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).SetNamedValue(JSON_KEY_ADVANCED_PASTE_UI_HOTKEY, ui_hotkey);
|
||||
|
||||
settings.save_to_settings_file();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("PastePlain settings are empty");
|
||||
}
|
||||
|
||||
if (!m_hotkey.key)
|
||||
{
|
||||
Logger::info("PastePlain is going to use default shortcut");
|
||||
m_hotkey.win = true;
|
||||
m_hotkey.alt = true;
|
||||
m_hotkey.shift = false;
|
||||
m_hotkey.ctrl = true;
|
||||
m_hotkey.key = 'V';
|
||||
if (settingsObject.GetView().Size())
|
||||
{
|
||||
if (settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_PASTE_AS_PLAIN_HOTKEY))
|
||||
{
|
||||
m_paste_as_plain_hotkey = parse_single_hotkey(JSON_KEY_PASTE_AS_PLAIN_HOTKEY, settingsObject);
|
||||
}
|
||||
if (settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_ADVANCED_PASTE_UI_HOTKEY))
|
||||
{
|
||||
m_advanced_paste_ui_hotkey = parse_single_hotkey(JSON_KEY_ADVANCED_PASTE_UI_HOTKEY, settingsObject);
|
||||
}
|
||||
if (settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_PASTE_AS_MARKDOWN_HOTKEY))
|
||||
{
|
||||
m_paste_as_markdown_hotkey = parse_single_hotkey(JSON_KEY_PASTE_AS_MARKDOWN_HOTKEY, settingsObject);
|
||||
}
|
||||
if (settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_PASTE_AS_JSON_HOTKEY))
|
||||
{
|
||||
m_paste_as_json_hotkey = parse_single_hotkey(JSON_KEY_PASTE_AS_JSON_HOTKEY, settingsObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,28 +193,31 @@ private:
|
||||
return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
void launch_process()
|
||||
void launch_process(const std::wstring& arg = L"")
|
||||
{
|
||||
Logger::trace(L"Starting PastePlain process");
|
||||
Logger::trace(L"Starting AdvancedPaste process");
|
||||
unsigned long powertoys_pid = GetCurrentProcessId();
|
||||
|
||||
std::wstring executable_args = L"";
|
||||
executable_args.append(std::to_wstring(powertoys_pid));
|
||||
|
||||
executable_args += L" " + arg;
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = L"PowerToys.PastePlain.exe";
|
||||
sei.lpFile = L"WinUI3Apps\\PowerToys.AdvancedPaste.exe";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = executable_args.data();
|
||||
if (ShellExecuteExW(&sei))
|
||||
{
|
||||
Logger::trace("Successfully started the PastePlain process");
|
||||
Logger::trace("Successfully started the Advanced Paste process");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"PastePlain failed to start. {}", get_last_error_or_default(GetLastError()));
|
||||
Logger::error(L"AdvancedPaste failed to start. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
m_hProcess = sei.hProcess;
|
||||
}
|
||||
|
||||
@ -143,7 +230,13 @@ private:
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(get_key());
|
||||
|
||||
parse_hotkey(settings);
|
||||
parse_hotkeys(settings);
|
||||
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size() && settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_SHOW_CUSTOM_PREVIEW))
|
||||
{
|
||||
m_preview_custom_format_output = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHOW_CUSTOM_PREVIEW).GetNamedBoolean(JSON_KEY_VALUE);
|
||||
}
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
@ -189,7 +282,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't open the clipboard to get the text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.OpenClipboard");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.OpenClipboard");
|
||||
return;
|
||||
}
|
||||
HANDLE h_clipboard_data = GetClipboardData(CF_UNICODETEXT);
|
||||
@ -199,7 +292,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Failed to get clipboard data. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GetClipboardData");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GetClipboardData");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
@ -211,7 +304,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't lock the buffer to get the unformatted text from the clipboard. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GlobalLock");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GlobalLock");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
@ -234,7 +327,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't get the clipboard data format type that would allow excluding the data from the clipboard history / roaming. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.RegisterClipboardFormat");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.RegisterClipboardFormat");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -243,7 +336,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't open the clipboard to copy the unformatted text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.OpenClipboard");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.OpenClipboard");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -254,7 +347,7 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't allocate a buffer for the unformatted text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalAlloc");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalAlloc");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
@ -267,7 +360,7 @@ private:
|
||||
Logger::error(L"Couldn't lock the buffer to send the unformatted text to the clipboard. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
GlobalFree(h_clipboard_data);
|
||||
CloseClipboard();
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalLock");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalLock");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -283,7 +376,7 @@ private:
|
||||
GlobalUnlock(h_clipboard_data);
|
||||
GlobalFree(h_clipboard_data);
|
||||
CloseClipboard();
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.SetClipboardData");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.SetClipboardData");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -368,25 +461,45 @@ private:
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"SendInput failed. Expected to send {} inputs and sent only {}. {}", inputs.size(), uSent, errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"input.SendInput");
|
||||
Trace::AdvancedPaste_Error(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"input.SendInput");
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear kb state and send Ctrl+V end
|
||||
}
|
||||
Trace::PastePlainSuccess();
|
||||
}
|
||||
|
||||
void bring_process_to_front()
|
||||
{
|
||||
auto enum_windows = [](HWND hwnd, LPARAM param) -> BOOL {
|
||||
HANDLE process_handle = reinterpret_cast<HANDLE>(param);
|
||||
DWORD window_process_id = 0;
|
||||
|
||||
GetWindowThreadProcessId(hwnd, &window_process_id);
|
||||
if (GetProcessId(process_handle) == window_process_id)
|
||||
{
|
||||
SetForegroundWindow(hwnd);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
EnumWindows(enum_windows, (LPARAM)m_hProcess);
|
||||
}
|
||||
|
||||
public:
|
||||
PastePlain()
|
||||
AdvancedPaste()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_PASTEPLAIN_NAME);
|
||||
app_key = PastePlainConstants::ModuleKey;
|
||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "PastePlain");
|
||||
app_name = GET_RESOURCE_STRING(IDS_ADVANCED_PASTE_NAME);
|
||||
app_key = AdvancedPasteConstants::ModuleKey;
|
||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "AdvancedPaste");
|
||||
m_hShowUIEvent = CreateDefaultEvent(CommonSharedConstants::SHOW_ADVANCED_PASTE_SHARED_EVENT);
|
||||
m_hPasteMarkdownEvent = CreateDefaultEvent(CommonSharedConstants::ADVANCED_PASTE_MARKDOWN_EVENT);
|
||||
m_hPasteJsonEvent = CreateDefaultEvent(CommonSharedConstants::ADVANCED_PASTE_JSON_EVENT);
|
||||
init_settings();
|
||||
}
|
||||
|
||||
~PastePlain()
|
||||
~AdvancedPaste()
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
@ -397,7 +510,7 @@ public:
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
Logger::trace("PastePlain::destroy()");
|
||||
Logger::trace("AdvancedPaste::destroy()");
|
||||
delete this;
|
||||
}
|
||||
|
||||
@ -416,7 +529,7 @@ public:
|
||||
// Return the configured status for the gpo policy for the module
|
||||
virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
|
||||
{
|
||||
return powertoys_gpo::getConfiguredPastePlainEnabledValue();
|
||||
return powertoys_gpo::getConfiguredAdvancedPasteEnabledValue();
|
||||
}
|
||||
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
@ -425,9 +538,9 @@ public:
|
||||
|
||||
// Create a Settings object.
|
||||
PowerToysSettings::Settings settings(hinstance, get_name());
|
||||
settings.set_description(GET_RESOURCE_STRING(IDS_PASTEPLAIN_SETTINGS_DESC));
|
||||
settings.set_description(GET_RESOURCE_STRING(IDS_ADVANCED_PASTE_SETTINGS_DESC));
|
||||
|
||||
settings.set_overview_link(L"https://aka.ms/PowerToysOverview_PastePlain");
|
||||
settings.set_overview_link(L"https://aka.ms/PowerToysOverview_AdvancedPaste");
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
@ -444,7 +557,21 @@ public:
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
parse_hotkey(values);
|
||||
parse_hotkeys(values);
|
||||
|
||||
auto settingsObject = values.get_raw_json();
|
||||
if (settingsObject.GetView().Size() && settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).HasKey(JSON_KEY_SHOW_CUSTOM_PREVIEW))
|
||||
{
|
||||
m_preview_custom_format_output = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHOW_CUSTOM_PREVIEW).GetNamedBoolean(JSON_KEY_VALUE);
|
||||
}
|
||||
|
||||
// order of args matter
|
||||
Trace::AdvancedPaste_SettingsTelemetry(m_paste_as_plain_hotkey,
|
||||
m_advanced_paste_ui_hotkey,
|
||||
m_paste_as_markdown_hotkey,
|
||||
m_paste_as_json_hotkey,
|
||||
m_preview_custom_format_output);
|
||||
|
||||
// If you don't need to do any custom processing of the settings, proceed
|
||||
// to persists the values calling:
|
||||
values.save_to_settings_file();
|
||||
@ -459,32 +586,78 @@ public:
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
Logger::trace("PastePlain::enable()");
|
||||
Logger::trace("AdvancedPaste::enable()");
|
||||
Trace::AdvancedPaste_Enable(true);
|
||||
ResetEvent(m_hShowUIEvent);
|
||||
ResetEvent(m_hPasteMarkdownEvent);
|
||||
ResetEvent(m_hPasteJsonEvent);
|
||||
m_enabled = true;
|
||||
Trace::EnablePastePlain(true);
|
||||
|
||||
launch_process();
|
||||
};
|
||||
|
||||
virtual void disable()
|
||||
{
|
||||
Logger::trace("PastePlain::disable()");
|
||||
m_enabled = false;
|
||||
Trace::EnablePastePlain(false);
|
||||
}
|
||||
|
||||
virtual bool on_hotkey(size_t /*hotkeyId*/) override
|
||||
{
|
||||
Logger::trace("AdvancedPaste::disable()");
|
||||
if (m_enabled)
|
||||
{
|
||||
Logger::trace(L"PastePlain hotkey pressed");
|
||||
ResetEvent(m_hShowUIEvent);
|
||||
ResetEvent(m_hPasteMarkdownEvent);
|
||||
ResetEvent(m_hPasteJsonEvent);
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
Trace::AdvancedPaste_Enable(false);
|
||||
|
||||
std::thread([=]() {
|
||||
// hotkey work should be kept to a minimum, or Windows might deregister our low level keyboard hook.
|
||||
// Move work to another thread.
|
||||
try_to_paste_as_plain_text();
|
||||
}).detach();
|
||||
CloseHandle(m_hProcess);
|
||||
m_hProcess = 0;
|
||||
}
|
||||
|
||||
Trace::PastePlainInvoked();
|
||||
return true;
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
virtual bool on_hotkey(size_t hotkeyId) override
|
||||
{
|
||||
Logger::trace(L"AdvancedPaste hotkey pressed");
|
||||
if (m_enabled)
|
||||
{
|
||||
if (!is_process_running())
|
||||
{
|
||||
Logger::trace(L"Launching new process");
|
||||
launch_process();
|
||||
|
||||
Trace::AdvancedPaste_Invoked(L"AdvancedPasteUI");
|
||||
}
|
||||
|
||||
// hotkeyId in same order as set by get_hotkeys
|
||||
if (hotkeyId == 0) { // m_paste_as_plain_hotkey
|
||||
Logger::trace(L"Paste as plain text hotkey pressed");
|
||||
|
||||
std::thread([=]() {
|
||||
// hotkey work should be kept to a minimum, or Windows might deregister our low level keyboard hook.
|
||||
// Move work to another thread.
|
||||
try_to_paste_as_plain_text();
|
||||
}).detach();
|
||||
|
||||
Trace::AdvancedPaste_Invoked(L"PastePlainTextDirect");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hotkeyId == 1) { // m_advanced_paste_ui_hotkey
|
||||
Logger::trace(L"Setting start up event");
|
||||
|
||||
bring_process_to_front();
|
||||
SetEvent(m_hShowUIEvent);
|
||||
return true;
|
||||
}
|
||||
if (hotkeyId == 2) { // m_paste_as_markdown_hotkey
|
||||
Logger::trace(L"Starting paste as markdown directly");
|
||||
SetEvent(m_hPasteMarkdownEvent);
|
||||
return true;
|
||||
}
|
||||
if (hotkeyId == 3) { // m_paste_as_json_hotkey
|
||||
Logger::trace(L"Starting paste as json directly");
|
||||
SetEvent(m_hPasteJsonEvent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -492,34 +665,23 @@ public:
|
||||
|
||||
virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
|
||||
{
|
||||
if (m_hotkey.key)
|
||||
if (hotkeys && buffer_size >= 4)
|
||||
{
|
||||
if (hotkeys && buffer_size >= 1)
|
||||
{
|
||||
hotkeys[0] = m_hotkey;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
hotkeys[0] = m_paste_as_plain_hotkey;
|
||||
hotkeys[1] = m_advanced_paste_ui_hotkey;
|
||||
hotkeys[2] = m_paste_as_markdown_hotkey;
|
||||
hotkeys[3] = m_paste_as_json_hotkey;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual void send_settings_telemetry() override
|
||||
{
|
||||
Logger::info("Send settings telemetry");
|
||||
Trace::SettingsTelemetry(m_hotkey);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new PastePlain();
|
||||
return new AdvancedPaste();
|
||||
}
|
@ -4,4 +4,5 @@
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <filesystem>
|
@ -5,9 +5,9 @@
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys PastePlain"
|
||||
#define INTERNAL_NAME "PowerToys.PastePlainModuleInterface"
|
||||
#define ORIGINAL_FILENAME "PowerToys.PastePlainModuleInterface.dll"
|
||||
#define FILE_DESCRIPTION "PowerToys AdvancedPaste"
|
||||
#define INTERNAL_NAME "PowerToys.AdvancedPasteModuleInterface"
|
||||
#define ORIGINAL_FILENAME "PowerToys.AdvancedPasteModuleInterface.dll"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
102
src/modules/AdvancedPaste/AdvancedPasteModuleInterface/trace.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "pch.h"
|
||||
#include "trace.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider()
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider()
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
// Log if the user has AdvancedPaste enabled or disabled
|
||||
void Trace::AdvancedPaste_Enable(const bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"AdvancedPaste_EnableAdvancedPaste",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
||||
|
||||
// Log if the user has invoked AdvancedPaste
|
||||
void Trace::AdvancedPaste_Invoked(std::wstring mode) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"AdvancedPaste_InvokeAdvancedPaste",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingValue(mode.c_str(), "Mode"));
|
||||
}
|
||||
|
||||
// Log if an error occurs in AdvancedPaste
|
||||
void Trace::AdvancedPaste_Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"AdvancedPaste_Error",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingValue(methodName.c_str(), "MethodName"),
|
||||
TraceLoggingValue(errorCode, "ErrorCode"),
|
||||
TraceLoggingValue(errorMessage.c_str(), "ErrorMessage"));
|
||||
}
|
||||
|
||||
// Event to send settings telemetry.
|
||||
void Trace::AdvancedPaste_SettingsTelemetry(const PowertoyModuleIface::Hotkey& pastePlainHotkey,
|
||||
const PowertoyModuleIface::Hotkey& advancedPasteUIHotkey,
|
||||
const PowertoyModuleIface::Hotkey& pasteMarkdownHotkey,
|
||||
const PowertoyModuleIface::Hotkey& pasteJsonHotkey,
|
||||
const bool preview_custom_format_output) noexcept
|
||||
{
|
||||
std::wstring pastePlainHotkeyStr =
|
||||
std::wstring(pastePlainHotkey.win ? L"Win + " : L"") +
|
||||
std::wstring(pastePlainHotkey.ctrl ? L"Ctrl + " : L"") +
|
||||
std::wstring(pastePlainHotkey.shift ? L"Shift + " : L"") +
|
||||
std::wstring(pastePlainHotkey.alt ? L"Alt + " : L"") +
|
||||
std::wstring(L"VK ") + std::to_wstring(pastePlainHotkey.key);
|
||||
|
||||
std::wstring advancedPasteUIHotkeyStr =
|
||||
std::wstring(advancedPasteUIHotkey.win ? L"Win + " : L"") +
|
||||
std::wstring(advancedPasteUIHotkey.ctrl ? L"Ctrl + " : L"") +
|
||||
std::wstring(advancedPasteUIHotkey.shift ? L"Shift + " : L"") +
|
||||
std::wstring(advancedPasteUIHotkey.alt ? L"Alt + " : L"") +
|
||||
std::wstring(L"VK ") + std::to_wstring(advancedPasteUIHotkey.key);
|
||||
|
||||
std::wstring pasteMarkdownHotkeyStr =
|
||||
std::wstring(pasteMarkdownHotkey.win ? L"Win + " : L"") +
|
||||
std::wstring(pasteMarkdownHotkey.ctrl ? L"Ctrl + " : L"") +
|
||||
std::wstring(pasteMarkdownHotkey.shift ? L"Shift + " : L"") +
|
||||
std::wstring(pasteMarkdownHotkey.alt ? L"Alt + " : L"") +
|
||||
std::wstring(L"VK ") + std::to_wstring(pasteMarkdownHotkey.key);
|
||||
|
||||
std::wstring pasteJsonHotkeyStr =
|
||||
std::wstring(pasteJsonHotkey.win ? L"Win + " : L"") +
|
||||
std::wstring(pasteJsonHotkey.ctrl ? L"Ctrl + " : L"") +
|
||||
std::wstring(pasteJsonHotkey.shift ? L"Shift + " : L"") +
|
||||
std::wstring(pasteJsonHotkey.alt ? L"Alt + " : L"") +
|
||||
std::wstring(L"VK ") + std::to_wstring(pasteJsonHotkey.key);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"AdvancedPaste_Settings",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingWideString(pastePlainHotkeyStr.c_str(), "PastePlainHotkey"),
|
||||
TraceLoggingWideString(advancedPasteUIHotkeyStr.c_str(), "AdvancedPasteUIHotkey"),
|
||||
TraceLoggingWideString(pasteMarkdownHotkeyStr.c_str(), "PasteMarkdownHotkey"),
|
||||
TraceLoggingWideString(pasteJsonHotkeyStr.c_str(), "PasteJsonHotkey"),
|
||||
TraceLoggingBoolean(preview_custom_format_output, "ShowCustomPreview")
|
||||
);
|
||||
}
|