[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>
This commit is contained in:
Craig Loewen
2024-05-09 10:32:03 -04:00
committed by Jaime Bernardo
parent c601a3e3e2
commit 483f7aa464
143 changed files with 5557 additions and 755 deletions

View File

@@ -0,0 +1,49 @@
// 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 System.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AdvancedPasteProperties
{
public static readonly HotkeySettings DefaultAdvancedPasteUIShortcut = new HotkeySettings(true, false, false, true, 0x56); // Win+Shift+V
public static readonly HotkeySettings DefaultPasteAsPlainTextShortcut = new HotkeySettings(true, true, true, false, 0x56); // Ctrl+Win+Alt+V
public AdvancedPasteProperties()
{
AdvancedPasteUIShortcut = DefaultAdvancedPasteUIShortcut;
PasteAsPlainTextShortcut = DefaultPasteAsPlainTextShortcut;
PasteAsMarkdownShortcut = new();
PasteAsJsonShortcut = new();
ShowCustomPreview = true;
SendPasteKeyCombination = true;
}
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowCustomPreview { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
[CmdConfigureIgnore]
public bool SendPasteKeyCombination { get; set; }
[JsonPropertyName("advanced-paste-ui-hotkey")]
public HotkeySettings AdvancedPasteUIShortcut { get; set; }
[JsonPropertyName("paste-as-plain-hotkey")]
public HotkeySettings PasteAsPlainTextShortcut { get; set; }
[JsonPropertyName("paste-as-markdown-hotkey")]
public HotkeySettings PasteAsMarkdownShortcut { get; set; }
[JsonPropertyName("paste-as-json-hotkey")]
public HotkeySettings PasteAsJsonShortcut { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this);
}
}

View File

@@ -9,9 +9,9 @@ using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class PastePlainSettings : BasePTModuleSettings, ISettingsConfig
public class AdvancedPasteSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "PastePlain";
public const string ModuleName = "AdvancedPaste";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
@@ -19,11 +19,11 @@ namespace Microsoft.PowerToys.Settings.UI.Library
};
[JsonPropertyName("properties")]
public PastePlainProperties Properties { get; set; }
public AdvancedPasteProperties Properties { get; set; }
public PastePlainSettings()
public AdvancedPasteSettings()
{
Properties = new PastePlainProperties();
Properties = new AdvancedPasteProperties();
Version = "1";
Name = ModuleName;
}

View File

@@ -330,18 +330,18 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool pastePlain = true;
private bool advancedPaste = true;
[JsonPropertyName("PastePlain")]
public bool PastePlain
[JsonPropertyName("AdvancedPaste")]
public bool AdvancedPaste
{
get => pastePlain;
get => advancedPaste;
set
{
if (pastePlain != value)
if (advancedPaste != value)
{
LogTelemetryEvent(value);
pastePlain = value;
advancedPaste = value;
NotifyChange();
}
}

View File

@@ -1,25 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class PastePlainProperties
{
[CmdConfigureIgnore]
public HotkeySettings DefaultActivationShortcut => new HotkeySettings(true, true, true, false, 0x56); // Ctrl+Win+Alt+V
public PastePlainProperties()
{
ActivationShortcut = DefaultActivationShortcut;
}
public HotkeySettings ActivationShortcut { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -30,8 +30,8 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
switch (moduleType)
{
case ModuleType.AdvancedPaste: return "ms-appx:///Assets/Settings/Icons/AdvancedPaste.png";
case ModuleType.PowerOCR: return "ms-appx:///Assets/Settings/Icons/TextExtractor.png";
case ModuleType.PastePlain: return "ms-appx:///Assets/Settings/Icons/PasteAsPlainText.png";
case ModuleType.PowerAccent: return "ms-appx:///Assets/Settings/Icons/QuickAccent.png";
case ModuleType.MousePointerCrosshairs: return "ms-appx:///Assets/Settings/Icons/MouseCrosshairs.png";
case ModuleType.MeasureTool: return "ms-appx:///Assets/Settings/Icons/ScreenRuler.png";
@@ -44,6 +44,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
switch (moduleType)
{
case ModuleType.AdvancedPaste: return generalSettingsConfig.Enabled.AdvancedPaste;
case ModuleType.AlwaysOnTop: return generalSettingsConfig.Enabled.AlwaysOnTop;
case ModuleType.Awake: return generalSettingsConfig.Enabled.Awake;
case ModuleType.ColorPicker: return generalSettingsConfig.Enabled.ColorPicker;
@@ -59,7 +60,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
case ModuleType.MouseJump: return generalSettingsConfig.Enabled.MouseJump;
case ModuleType.MousePointerCrosshairs: return generalSettingsConfig.Enabled.MousePointerCrosshairs;
case ModuleType.MouseWithoutBorders: return generalSettingsConfig.Enabled.MouseWithoutBorders;
case ModuleType.PastePlain: return generalSettingsConfig.Enabled.PastePlain;
case ModuleType.Peek: return generalSettingsConfig.Enabled.Peek;
case ModuleType.PowerRename: return generalSettingsConfig.Enabled.PowerRename;
case ModuleType.PowerLauncher: return generalSettingsConfig.Enabled.PowerLauncher;
@@ -76,6 +76,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
switch (moduleType)
{
case ModuleType.AdvancedPaste: generalSettingsConfig.Enabled.AdvancedPaste = isEnabled; break;
case ModuleType.AlwaysOnTop: generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break;
case ModuleType.Awake: generalSettingsConfig.Enabled.Awake = isEnabled; break;
case ModuleType.ColorPicker: generalSettingsConfig.Enabled.ColorPicker = isEnabled; break;
@@ -91,7 +92,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
case ModuleType.MouseJump: generalSettingsConfig.Enabled.MouseJump = isEnabled; break;
case ModuleType.MousePointerCrosshairs: generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
case ModuleType.MouseWithoutBorders: generalSettingsConfig.Enabled.MouseWithoutBorders = isEnabled; break;
case ModuleType.PastePlain: generalSettingsConfig.Enabled.PastePlain = isEnabled; break;
case ModuleType.Peek: generalSettingsConfig.Enabled.Peek = isEnabled; break;
case ModuleType.PowerRename: generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
case ModuleType.PowerLauncher: generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
@@ -107,6 +107,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
switch (moduleType)
{
case ModuleType.AdvancedPaste: return GPOWrapper.GetConfiguredAdvancedPasteEnabledValue();
case ModuleType.AlwaysOnTop: return GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
case ModuleType.Awake: return GPOWrapper.GetConfiguredAwakeEnabledValue();
case ModuleType.ColorPicker: return GPOWrapper.GetConfiguredColorPickerEnabledValue();
@@ -122,7 +123,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
case ModuleType.MouseJump: return GPOWrapper.GetConfiguredMouseJumpEnabledValue();
case ModuleType.MousePointerCrosshairs: return GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
case ModuleType.MouseWithoutBorders: return GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue();
case ModuleType.PastePlain: return GPOWrapper.GetConfiguredPastePlainEnabledValue();
case ModuleType.Peek: return GPOWrapper.GetConfiguredPeekEnabledValue();
case ModuleType.PowerRename: return GPOWrapper.GetConfiguredPowerRenameEnabledValue();
case ModuleType.PowerLauncher: return GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
@@ -139,6 +139,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
return moduleType switch
{
ModuleType.AdvancedPaste => typeof(AdvancedPastePage),
ModuleType.AlwaysOnTop => typeof(AlwaysOnTopPage),
ModuleType.Awake => typeof(AwakePage),
ModuleType.ColorPicker => typeof(ColorPickerPage),
@@ -154,7 +155,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
ModuleType.MouseJump => typeof(MouseUtilsPage),
ModuleType.MousePointerCrosshairs => typeof(MouseUtilsPage),
ModuleType.MouseWithoutBorders => typeof(MouseWithoutBordersPage),
ModuleType.PastePlain => typeof(PastePlainPage),
ModuleType.Peek => typeof(PeekPage),
ModuleType.PowerRename => typeof(PowerRenamePage),
ModuleType.PowerLauncher => typeof(PowerLauncherPage),

View File

@@ -7,6 +7,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
public enum PowerToysModules
{
Overview = 0,
AdvancedPaste,
AlwaysOnTop,
Awake,
CmdNotFound,
@@ -29,7 +30,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
VideoConference,
MeasureTool,
Hosts,
PastePlain,
WhatsNew,
RegistryPreview,
}

View File

@@ -21,6 +21,10 @@
<!-- 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.Settings.pri</ProjectPriFileName>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\Settings\Modules\APDialog.dark.png" />
<None Remove="Assets\Settings\Modules\APDialog.light.png" />
</ItemGroup>
<ItemGroup>
<Page Remove="SettingsXAML\App.xaml" />

View File

@@ -393,6 +393,7 @@ namespace Microsoft.PowerToys.Settings.UI
{
case "Dashboard": return typeof(DashboardPage);
case "Overview": return typeof(GeneralPage);
case "AdvancedPaste": return typeof(AdvancedPastePage);
case "AlwaysOnTop": return typeof(AlwaysOnTopPage);
case "Awake": return typeof(AwakePage);
case "CmdNotFound": return typeof(CmdNotFoundPage);
@@ -413,7 +414,6 @@ namespace Microsoft.PowerToys.Settings.UI
case "MeasureTool": return typeof(MeasureToolPage);
case "Hosts": return typeof(HostsPage);
case "RegistryPreview": return typeof(RegistryPreviewPage);
case "PastePlain": return typeof(PastePlainPage);
case "Peek": return typeof(PeekPage);
case "CropAndLock": return typeof(CropAndLockPage);
case "EnvironmentVariables": return typeof(EnvironmentVariablesPage);

View File

@@ -0,0 +1,36 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeAdvancedPaste"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_AdvancedPaste" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/AdvancedPaste.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl x:Name="AdvancedPasteUIHotkeyControl" x:Uid="Oobe_AdvancedPasteUI_HowToUse" />
<controls:ShortcutWithTextLabelControl x:Name="PasteAsPlainTextHotkeyControl" x:Uid="Oobe_AdvancedPastePlain_HowToUse" />
<controls:ShortcutWithTextLabelControl
x:Name="PasteAsMarkdownHotkeyControl"
x:Uid="Oobe_AdvancedPasteMarkdown_HowToUse"
Visibility="Collapsed" />
<controls:ShortcutWithTextLabelControl
x:Name="PasteAsJsonHotkeyControl"
x:Uid="Oobe_AdvancedPasteJson_HowToUse"
Visibility="Collapsed" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_AdvancedPaste" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_AdvancedPaste" TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,60 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeAdvancedPaste : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeAdvancedPaste()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.AdvancedPaste]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(AdvancedPastePage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
AdvancedPasteUIHotkeyControl.Keys = SettingsRepository<AdvancedPasteSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList();
PasteAsPlainTextHotkeyControl.Keys = SettingsRepository<AdvancedPasteSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsPlainTextShortcut.GetKeysList();
PasteAsMarkdownHotkeyControl.Keys = SettingsRepository<AdvancedPasteSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList();
// TODO(stefan): Check how to remove additional space if item is set to Collapsed.
if (PasteAsMarkdownHotkeyControl.Keys.Count > 0)
{
PasteAsMarkdownHotkeyControl.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
PasteAsJsonHotkeyControl.Keys = SettingsRepository<AdvancedPasteSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList();
if (PasteAsJsonHotkeyControl.Keys.Count > 0)
{
PasteAsJsonHotkeyControl.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -1,27 +0,0 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePastePlain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_PastePlain" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PasteAsPlainText.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical" Spacing="12">
<TextBlock x:Uid="Oobe_HowToUse" Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_PastePlain_HowToUse" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Uid="OOBE_Settings" Click="SettingsLaunchButton_Click" />
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_PastePlain" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_PastePlain" TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -1,46 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobePastePlain : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePastePlain()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.PastePlain]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PastePlainPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PastePlainSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -61,6 +61,10 @@
x:Uid="Shell_General"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/PowerToys.png}"
Tag="Overview" />
<NavigationViewItem
x:Uid="Shell_AdvancedPaste"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/AdvancedPaste.png}"
Tag="AdvancedPaste" />
<NavigationViewItem
x:Uid="Shell_AlwaysOnTop"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/AlwaysOnTop.png}"
@@ -117,10 +121,6 @@
x:Uid="Shell_MouseWithoutBorders"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseWithoutBorders.png}"
Tag="MouseWithoutBorders" />
<NavigationViewItem
x:Uid="Shell_PastePlain"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/PasteAsPlainText.png}"
Tag="PastePlain" />
<NavigationViewItem
x:Uid="Shell_Peek"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/Peek.png}"

View File

@@ -69,6 +69,11 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ModuleName = "Overview",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.AdvancedPaste, new OobePowerToysModule()
{
ModuleName = "AdvancedPaste",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.AlwaysOnTop, new OobePowerToysModule()
{
ModuleName = "AlwaysOnTop",
@@ -183,12 +188,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PastePlain, new OobePowerToysModule()
{
ModuleName = "PastePlain",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.WhatsNew, new OobePowerToysModule()
{
ModuleName = "WhatsNew",
@@ -253,6 +252,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
}
case "WhatsNew": NavigationFrame.Navigate(typeof(OobeWhatsNew)); break;
case "AdvancedPaste": NavigationFrame.Navigate(typeof(OobeAdvancedPaste)); break;
case "AlwaysOnTop": NavigationFrame.Navigate(typeof(OobeAlwaysOnTop)); break;
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
case "CmdNotFound": NavigationFrame.Navigate(typeof(OobeCmdNotFound)); break;
@@ -275,7 +275,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
case "MeasureTool": NavigationFrame.Navigate(typeof(OobeMeasureTool)); break;
case "Hosts": NavigationFrame.Navigate(typeof(OobeHosts)); break;
case "RegistryPreview": NavigationFrame.Navigate(typeof(OobeRegistryPreview)); break;
case "PastePlain": NavigationFrame.Navigate(typeof(OobePastePlain)); break;
case "Peek": NavigationFrame.Navigate(typeof(OobePeek)); break;
}
}

View File

@@ -0,0 +1,188 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.AdvancedPastePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<ImageSource x:Key="DialogHeaderImage">ms-appx:///Assets/Settings/Modules/APDialog.dark.png</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<ImageSource x:Key="DialogHeaderImage">ms-appx:///Assets/Settings/Modules/APDialog.light.png</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<ImageSource x:Key="DialogHeaderImage">ms-appx:///Assets/Settings/Modules/APDialog.light.png</ImageSource>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid>
<controls:SettingsPageControl x:Uid="AdvancedPaste" ModuleImageSource="ms-appx:///Assets/Settings/Modules/AdvancedPaste.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="2">
<tkcontrols:SettingsCard
x:Uid="AdvancedPaste_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/AdvancedPaste.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
<controls:SettingsGroup x:Uid="AdvancedPaste_EnableAISettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_EnableAISettingsCard">
<tkcontrols:SettingsCard.HeaderIcon>
<PathIcon Data="M128 766q0-42 24-77t65-48l178-57q32-11 61-30t52-42q50-50 71-114l58-179q13-40 48-65t78-26q42 0 77 24t50 65l58 177q21 66 72 117 49 50 117 72l176 58q43 14 69 48t26 80q0 41-25 76t-64 49l-178 58q-66 21-117 72-32 32-51 73t-33 84-26 83-30 73-45 51-71 20q-42 0-77-24t-49-65l-58-178q-8-25-19-47t-28-43q-34-43-77-68t-89-41-89-27-78-29-55-45-21-75zm1149 7q-76-29-145-53t-129-60-104-88-73-138l-57-176-67 176q-18 48-42 89t-60 78q-34 34-76 61t-89 43l-177 57q75 29 144 53t127 60 103 89 73 137l57 176 67-176q37-97 103-168t168-103l177-57zm-125 759q0-31 20-57t49-36l99-32q34-11 53-34t30-51 20-59 20-54 33-41 58-16q32 0 59 19t38 50q6 20 11 40t13 40 17 38 25 34q16 17 39 26t48 18 49 16 44 20 31 32 12 50q0 33-18 60t-51 38q-19 6-39 11t-41 13-39 17-34 25q-24 25-35 62t-24 73-35 61-68 25q-32 0-59-19t-38-50q-6-18-11-39t-13-41-17-40-24-33q-18-17-41-27t-47-17-49-15-43-20-30-33-12-54zm583 4q-43-13-74-30t-55-41-40-55-32-74q-12 41-29 72t-42 55-55 42-71 31q81 23 128 71t71 129q15-43 31-74t40-54 53-40 75-32z" />
</tkcontrols:SettingsCard.HeaderIcon>
<tkcontrols:SwitchPresenter TargetType="x:Boolean" Value="{x:Bind ViewModel.IsOpenAIEnabled, Mode=OneWay}">
<tkcontrols:Case Value="True">
<Button x:Uid="AdvancedPaste_DisableAIButton" Click="AdvancedPaste_DisableAIButton_Click" />
</tkcontrols:Case>
<tkcontrols:Case Value="False">
<Button
x:Uid="AdvancedPaste_EnableAIButton"
Click="AdvancedPaste_EnableAIButton_Click"
Style="{StaticResource AccentButtonStyle}" />
</tkcontrols:Case>
</tkcontrols:SwitchPresenter>
<tkcontrols:SettingsCard.Description>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="AdvancedPaste_EnableAISettingsCardDescription" />
<HyperlinkButton x:Uid="AdvancedPaste_EnableAISettingsCardDescriptionLearnMore" NavigateUri="https://learn.microsoft.com/windows/powertoys/advanced-paste" />
</StackPanel>
</tkcontrols:SettingsCard.Description>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Uid="AdvancedPaste_ShowCustomPreviewSettingsCard"
HeaderIcon="{ui:FontIcon Glyph=&#xE71E;}"
IsEnabled="{x:Bind ViewModel.IsOpenAIEnabled, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowCustomPreview, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="AdvancedPaste_ClipboardHistorySettingsGroup" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_Clipboard_History_Enabled_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xF0E3;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.ClipboardHistoryEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="AdvancedPaste_Direct_Access_Hotkeys_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="AdvancedPasteUI_Shortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
IsExpanded="True">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.AdvancedPasteUIShortcut, Mode=TwoWay}" />
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard Visibility="Collapsed">
<!-- There's a bug that makes it so that the first shortcut control inside an expander doesn't work. We add this dummy one so the other entries aren't affected. -->
<TextBox />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PasteAsPlainText_Shortcut">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.PasteAsPlainTextShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PasteAsMarkdown_Shortcut">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
AllowDisable="True"
HotkeySettings="{x:Bind Path=ViewModel.PasteAsMarkdownShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PasteAsJson_Shortcut">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
AllowDisable="True"
HotkeySettings="{x:Bind Path=ViewModel.PasteAsJsonShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
<InfoBar
x:Uid="AdvancedPaste_ShortcutWarning"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsConflictingCopyShortcut, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsConflictingCopyShortcut, Mode=OneWay}"
Severity="Warning" />
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_AdvancedPaste" Link="https://aka.ms/PowerToysOverview_AdvancedPaste" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
<ContentDialog
x:Name="EnableAIDialog"
x:Uid="EnableAIDialog"
IsPrimaryButtonEnabled="False"
IsSecondaryButtonEnabled="True"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
<Grid RowSpacing="24">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Margin="-24,-24,-24,0" Source="{ThemeResource DialogHeaderImage}" />
<TextBlock
Grid.Row="1"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap">
<Run x:Uid="AdvancedPaste_EnableAIDialog_Description" />
<Hyperlink NavigateUri="https://openai.com/policies/terms-of-use" TabIndex="3">
<Run x:Uid="TermsLink" />
</Hyperlink>
<Run x:Uid="AIFooterSeparator" Foreground="{ThemeResource TextFillColorSecondaryBrush}">|</Run>
<Hyperlink NavigateUri="https://openai.com/policies/privacy-policy" TabIndex="3">
<Run x:Uid="PrivacyLink" />
</Hyperlink>
</TextBlock>
<StackPanel Grid.Row="2" Orientation="Vertical">
<TextBlock FontWeight="SemiBold" Text="Configure OpenAI key" />
<TextBlock Grid.Row="2" TextWrapping="Wrap">
<Run x:Uid="AdvancedPaste_EnableAIDialog_LoginIntoText" />
<Hyperlink NavigateUri="https://platform.openai.com/api-keys">
<Run x:Uid="AdvancedPaste_EnableAIDialog_OpenAIApiKeysOverviewText" />
</Hyperlink>
<LineBreak />
<Run x:Uid="AdvancedPaste_EnableAIDialog_CreateNewKeyText" />
<LineBreak />
<Run x:Uid="AdvancedPaste_EnableAIDialog_NoteAICreditsText" />
</TextBlock>
</StackPanel>
<Grid Grid.Row="3" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
x:Uid="AdvancedPaste_EnableAIDialogOpenAIApiKey"
VerticalAlignment="Center"
TextWrapping="Wrap" />
<TextBox
x:Name="AdvancedPaste_EnableAIDialogOpenAIApiKey"
Grid.Column="1"
MinWidth="248"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
TextChanged="AdvancedPaste_EnableAIDialogOpenAIApiKey_TextChanged" />
</Grid>
</Grid>
</ContentDialog>
</Grid>
</Page>

View File

@@ -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.Threading.Tasks;
using System.Windows.Input;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Security.Credentials;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class AdvancedPastePage : Page, IRefreshablePage
{
private AdvancedPasteViewModel ViewModel { get; set; }
public ICommand SaveOpenAIKeyCommand => new RelayCommand(SaveOpenAIKey);
public AdvancedPastePage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new AdvancedPasteViewModel(
settingsUtils,
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
SettingsRepository<AdvancedPasteSettings>.GetInstance(settingsUtils),
ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
private void SaveOpenAIKey()
{
if (!string.IsNullOrEmpty(AdvancedPaste_EnableAIDialogOpenAIApiKey.Text))
{
ViewModel.EnableAI(AdvancedPaste_EnableAIDialogOpenAIApiKey.Text);
}
}
private async void AdvancedPaste_EnableAIButton_Click(object sender, RoutedEventArgs e)
{
var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
EnableAIDialog.PrimaryButtonText = resourceLoader.GetString("EnableAIDialog_SaveBtnText");
EnableAIDialog.SecondaryButtonText = resourceLoader.GetString("EnableAIDialog_CancelBtnText");
EnableAIDialog.PrimaryButtonCommand = SaveOpenAIKeyCommand;
AdvancedPaste_EnableAIDialogOpenAIApiKey.Text = string.Empty;
await ShowEnableDialogAsync();
}
private async Task ShowEnableDialogAsync()
{
await EnableAIDialog.ShowAsync();
}
private void AdvancedPaste_DisableAIButton_Click(object sender, RoutedEventArgs e)
{
ViewModel.DisableAI();
}
private void AdvancedPaste_EnableAIDialogOpenAIApiKey_TextChanged(object sender, TextChangedEventArgs e)
{
if (AdvancedPaste_EnableAIDialogOpenAIApiKey.Text.Length > 0)
{
EnableAIDialog.IsPrimaryButtonEnabled = true;
}
else
{
EnableAIDialog.IsPrimaryButtonEnabled = false;
}
}
}
}

View File

@@ -1,50 +0,0 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.PastePlainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<controls:SettingsPageControl x:Uid="PastePlain" ModuleImageSource="ms-appx:///Assets/Settings/Modules/PasteAsPlainText.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="2">
<tkcontrols:SettingsCard
x:Uid="PastePlain_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/PasteAsPlainText.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}"
Severity="Informational" />
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="Activation_Shortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="PastePlain_ShortcutWarning"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsConflictingCopyShortcut, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsConflictingCopyShortcut, Mode=OneWay}"
Severity="Warning" />
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_PastePlain" Link="https://aka.ms/PowerToysOverview_PastePlain" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@@ -1,33 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PastePlainPage : Page, IRefreshablePage
{
private PastePlainViewModel ViewModel { get; set; }
public PastePlainPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new PastePlainViewModel(
settingsUtils,
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
SettingsRepository<PastePlainSettings>.GetInstance(settingsUtils),
ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@@ -105,6 +105,11 @@
</NavigationViewItem>
<NavigationViewItemSeparator />
<NavigationViewItem
x:Uid="Shell_AdvancedPaste"
helpers:NavHelper.NavigateTo="views:AdvancedPastePage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/AdvancedPaste.png}" />
<NavigationViewItem
x:Uid="Shell_AlwaysOnTop"
helpers:NavHelper.NavigateTo="views:AlwaysOnTopPage"
@@ -175,11 +180,6 @@
helpers:NavHelper.NavigateTo="views:MouseWithoutBordersPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseWithoutBorders.png}" />
<NavigationViewItem
x:Uid="Shell_PastePlain"
helpers:NavHelper.NavigateTo="views:PastePlainPage"
Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/PasteAsPlainText.png}" />
<NavigationViewItem
x:Uid="Shell_Peek"
helpers:NavHelper.NavigateTo="views:PeekPage"

View File

@@ -59,10 +59,7 @@
: 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>
@@ -707,6 +704,24 @@
<data name="Shortcut.Header" xml:space="preserve">
<value>Shortcut</value>
</data>
<data name="AdvancedPaste_EnableAIButton.Content" xml:space="preserve">
<value>Enable</value>
</data>
<data name="AdvancedPaste_DisableAIButton.Content" xml:space="preserve">
<value>Disable</value>
</data>
<data name="AdvancedPaste_EnableAISettingsCard.Header" xml:space="preserve">
<value>Enable Paste with AI</value>
</data>
<data name="AdvancedPaste_Clipboard_History_Enabled_SettingsCard.Header" xml:space="preserve">
<value>Clipboard history</value>
</data>
<data name="AdvancedPaste_Clipboard_History_Enabled_SettingsCard.Description" xml:space="preserve">
<value>Save multiple items to your clipboard. This is an OS feature.</value>
</data>
<data name="AdvancedPaste_Direct_Access_Hotkeys_GroupSettings.Header" xml:space="preserve">
<value>Shortcuts</value>
</data>
<data name="RemapKeysList.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Current Key Remappings</value>
</data>
@@ -1978,6 +1993,30 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
<data name="Activation_Shortcut.Description" xml:space="preserve">
<value>Customize the shortcut to activate this module</value>
</data>
<data name="PasteAsPlainText_Shortcut.Header" xml:space="preserve">
<value>Paste as plain text directly</value>
</data>
<data name="AdvancedPasteUI_Shortcut.Header" xml:space="preserve">
<value>Open Advanced Paste window</value>
</data>
<data name="PasteAsMarkdown_Shortcut.Header" xml:space="preserve">
<value>Paste as Markdown directly</value>
</data>
<data name="PasteAsJson_Shortcut.Header" xml:space="preserve">
<value>Paste as JSON directly</value>
</data>
<data name="PasteAsCustom_Shortcut.Header" xml:space="preserve">
<value>Paste as Custom with AI directly</value>
</data>
<data name="AdvancedPaste_EnableAIDialogOpenAIApiKey.Text" xml:space="preserve">
<value>OpenAI API key:</value>
</data>
<data name="EnableAIDialog_SaveBtnText" xml:space="preserve">
<value>Save</value>
</data>
<data name="EnableAIDialog_CancelBtnText" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Oobe_GetStarted.Text" xml:space="preserve">
<value>Let's get started!</value>
</data>
@@ -2422,9 +2461,9 @@ From there, simply click on one of the supported files in the File Explorer and
<value>Learn more about Mouse utilities</value>
<comment>Mouse utilities is a product name, do not loc</comment>
</data>
<data name="LearnMore_PastePlain.Text" xml:space="preserve">
<value>Learn more about Paste as Plain Text</value>
<comment> Paste as Plain Text is the name of the module. </comment>
<data name="LearnMore_AdvancedPaste.Text" xml:space="preserve">
<value>Learn more about Advanced Paste</value>
<comment> Advanced Paste is the name of the module. </comment>
</data>
<data name="LearnMore_MouseWithoutBorders.Text" xml:space="preserve">
<value>Learn more about Mouse Without Borders</value>
@@ -3122,8 +3161,14 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="MouseWithoutBorders_ShortDescription" xml:space="preserve">
<value>Move your cursor across multiple devices</value>
</data>
<data name="PastePlain_ShortDescription" xml:space="preserve">
<value>Paste clipboard content without formatting</value>
<data name="AdvancedPaste_ShortDescription" xml:space="preserve">
<value>An AI powered tool to put your clipboard content into any format you need, focused towards developer workflows.</value>
</data>
<data name="AdvancedPaste_EnableAISettingsCardDescription.Text" xml:space="preserve">
<value>This feature allows you to format your clipboard content with the power of AI. An OpenAI API key is required.</value>
</data>
<data name="AdvancedPaste_EnableAISettingsCardDescriptionLearnMore.Content" xml:space="preserve">
<value>Learn more</value>
</data>
<data name="Peek_ShortDescription" xml:space="preserve">
<value>Quick and easy previewer</value>
@@ -3688,30 +3733,54 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="GeneralPage_EnableExperimentation.Header" xml:space="preserve">
<value>Allow experimentation with new features</value>
</data>
<data name="Shell_PastePlain.Content" xml:space="preserve">
<value>Paste As Plain Text</value>
<comment>Product name: Navigation view item name for Paste as Plain Text</comment>
<data name="Shell_AdvancedPaste.Content" xml:space="preserve">
<value>Advanced Paste</value>
<comment>Product name: Navigation view item name for Advanced Paste</comment>
</data>
<data name="PastePlain.ModuleDescription" xml:space="preserve">
<value>Paste As Plain Text is a quick shortcut for pasting the text contents of your clipboard without formatting. Note: the formatted text in the clipboard is replaced with the unformatted text.</value>
<data name="AdvancedPaste.ModuleDescription" xml:space="preserve">
<value>Advanced Paste is an AI powered tool to put your clipboard content into any format you need</value>
</data>
<data name="PastePlain.ModuleTitle" xml:space="preserve">
<value>Paste As Plain Text</value>
<data name="AdvancedPaste.ModuleTitle" xml:space="preserve">
<value>Advanced Paste</value>
</data>
<data name="PastePlain_Cancel" xml:space="preserve">
<data name="AdvancedPaste_Cancel" xml:space="preserve">
<value>cancel</value>
</data>
<data name="PastePlain_EnableToggleControl_HeaderText.Header" xml:space="preserve">
<value>Enable Paste As Plain Text</value>
<data name="AdvancedPaste_EnableToggleControl_HeaderText.Header" xml:space="preserve">
<value>Enable Advanced Paste</value>
</data>
<data name="Oobe_PastePlain.Description" xml:space="preserve">
<value>Paste As Plain Text strips rich formatting from your clipboard data and pastes it as non-formatted text.</value>
<data name="AdvancedPaste_EnableAISettingsGroup.Header" xml:space="preserve">
<value>Paste with AI</value>
</data>
<data name="Oobe_PastePlain.Title" xml:space="preserve">
<value>Paste As Plain Text</value>
<data name="AdvancedPaste_ClipboardHistorySettingsGroup.Header" xml:space="preserve">
<value>Clipboard history</value>
</data>
<data name="Oobe_PastePlain_HowToUse.Text" xml:space="preserve">
<value>to paste your clipboard data as plain text. Note: this will replace the formatted text in your clipboard with the plain text.</value>
<data name="AdvancedPaste_ShowCustomPreviewSettingsCard.Header" xml:space="preserve">
<value>Custom format preview</value>
</data>
<data name="AdvancedPaste_ShowCustomPreviewSettingsCard.Description" xml:space="preserve">
<value>Preview the output of the custom format before pasting</value>
</data>
<data name="Oobe_AdvancedPaste.Description" xml:space="preserve">
<value>Advanced Paste is An AI powered tool to put your clipboard content into any format you need, focused towards developer workflows. Note: this will replace the formatted text in your clipboard with the selected format.</value>
</data>
<data name="Oobe_AdvancedPaste.Title" xml:space="preserve">
<value>Advanced Paste</value>
</data>
<data name="Oobe_AdvancedPasteUI_HowToUse.Text" xml:space="preserve">
<value>to open UI to select the format you want to paste your data as.</value>
</data>
<data name="Oobe_AdvancedPastePlain_HowToUse.Text" xml:space="preserve">
<value>to paste your clipboard data as plain text.</value>
</data>
<data name="Oobe_AdvancedPasteMarkdown_HowToUse.Text" xml:space="preserve">
<value>to paste your clipboard data as Markdown. Note: Clipboard content type has to be HTML.</value>
</data>
<data name="Oobe_AdvancedPasteJson_HowToUse.Text" xml:space="preserve">
<value>to paste your clipboard data as JSON. Note: Clipboard content data has to contain XML or CSV text.</value>
</data>
<data name="Oobe_AdvancedPasteCustom_HowToUse.Text" xml:space="preserve">
<value>to open AI-powered dialog to enter query and convert your data to any format you need.</value>
</data>
<data name="Shell_CmdNotFound.Content" xml:space="preserve">
<value>Command Not Found</value>
@@ -3908,7 +3977,7 @@ Activate by holding the key for the character you want to add an accent to, then
<value>Make Registry Preview default app for opening .reg files</value>
<comment>Registry Preview is app name. Do not localize.</comment>
</data>
<data name="PastePlain_ShortcutWarning.Title" xml:space="preserve">
<data name="AdvancedPaste_ShortcutWarning.Title" xml:space="preserve">
<value>Using this shortcut may prevent non-text paste actions (e.g. images, files) or built-in paste plain text actions in other applications from functioning.</value>
</data>
<data name="MouseUtils_MouseJump_ThumbnailSize.Header" xml:space="preserve">
@@ -4071,6 +4140,24 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="Peek_SourceCode_StickyScroll.Content" xml:space="preserve">
<value>Enable sticky scroll</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>
<data name="AdvancedPaste_EnableAIDialog_Description.Text" xml:space="preserve">
<value>Paste with AI allows you to format your clipboard content into any format you need. Learn more about the terms of conditions while using OpenAI and privacy at Microsoft:</value>
</data>
<data name="AdvancedPaste_EnableAIDialog_LoginIntoText.Text" xml:space="preserve">
<value>• Login into your</value>
</data>
<data name="AdvancedPaste_EnableAIDialog_OpenAIApiKeysOverviewText.Text" xml:space="preserve">
<value>OpenAI API keys overview</value>
</data>
<data name="AdvancedPaste_EnableAIDialog_CreateNewKeyText.Text" xml:space="preserve">
<value>• Create a new secret key and paste it in the field below</value>
</data>
<data name="FileExplorerPreview_Toggle_Monaco_Font_Size.Description" xml:space="preserve">
<value>Font size of the editor in pt. Recommended: 14pt</value>
<comment>{Locked="pt"}</comment>
@@ -4085,4 +4172,10 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="Peek_SourceCode_FontSize.Header" xml:space="preserve">
<value>Font size</value>
</data>
<data name="AdvancedPaste_EnableAIDialog_NoteAICreditsText.Text" xml:space="preserve">
<value>• NOTE: You need to have available paid credits in your OpenAI account to use this feature. If you do not have credits you will see an 'API key quota exceeded' error</value>
</data>
<data name="AdvancedPaste_EnableAIDialog_NoteAICreditsErrorText.Text" xml:space="preserve">
<value>If you do not have credits you will see an 'API key quota exceeded' error</value>
</data>
</root>

View File

@@ -0,0 +1,325 @@
// 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.Text.Json;
using System.Timers;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.Win32;
using Windows.Security.Credentials;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class AdvancedPasteViewModel : Observable, IDisposable
{
private bool disposedValue;
// Delay saving of settings in order to avoid calling save multiple times and hitting file in use exception. If there is no other request to save settings in given interval, we proceed to save it, otherwise we schedule saving it after this interval
private const int SaveSettingsDelayInMs = 500;
private GeneralSettings GeneralSettingsConfig { get; set; }
private readonly ISettingsUtils _settingsUtils;
private readonly object _delayedActionLock = new object();
private readonly AdvancedPasteSettings _advancedPasteSettings;
private Timer _delayedTimer;
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private Func<string, int> SendConfigMSG { get; }
public AdvancedPasteViewModel(
ISettingsUtils settingsUtils,
ISettingsRepository<GeneralSettings> settingsRepository,
ISettingsRepository<AdvancedPasteSettings> advancedPasteSettingsRepository,
Func<string, int> ipcMSGCallBackFunc)
{
// To obtain the general settings configurations of PowerToys Settings.
ArgumentNullException.ThrowIfNull(settingsRepository);
GeneralSettingsConfig = settingsRepository.SettingsConfig;
// To obtain the settings configurations of Fancy zones.
ArgumentNullException.ThrowIfNull(settingsRepository);
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
ArgumentNullException.ThrowIfNull(advancedPasteSettingsRepository);
_advancedPasteSettings = advancedPasteSettingsRepository.SettingsConfig;
InitializeEnabledValue();
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
_delayedTimer = new Timer();
_delayedTimer.Interval = SaveSettingsDelayInMs;
_delayedTimer.Elapsed += DelayedTimer_Tick;
_delayedTimer.AutoReset = false;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredAdvancedPasteEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.AdvancedPaste;
}
}
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (_isEnabled != value)
{
_isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
// Set the status of AdvancedPaste in the general settings
GeneralSettingsConfig.Enabled.AdvancedPaste = value;
var outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(outgoing.ToString());
}
}
}
private bool OpenAIKeyExists()
{
PasswordVault vault = new PasswordVault();
PasswordCredential cred = null;
try
{
cred = vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey");
}
catch (Exception)
{
return false;
}
return cred is not null;
}
public bool IsOpenAIEnabled => OpenAIKeyExists();
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
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;
}
}
private void SetClipboardHistoryEnabled(bool value)
{
string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Clipboard\";
try
{
Registry.SetValue(registryKey, "EnableClipboardHistory", value ? 1 : 0);
}
catch (Exception)
{
}
}
public bool ClipboardHistoryEnabled
{
get => IsClipboardHistoryEnabled();
set
{
if (IsClipboardHistoryEnabled() != value)
{
SetClipboardHistoryEnabled(value);
}
}
}
public HotkeySettings AdvancedPasteUIShortcut
{
get => _advancedPasteSettings.Properties.AdvancedPasteUIShortcut;
set
{
if (_advancedPasteSettings.Properties.AdvancedPasteUIShortcut != value)
{
_advancedPasteSettings.Properties.AdvancedPasteUIShortcut = value ?? AdvancedPasteProperties.DefaultAdvancedPasteUIShortcut;
OnPropertyChanged(nameof(AdvancedPasteUIShortcut));
OnPropertyChanged(nameof(IsConflictingCopyShortcut));
_settingsUtils.SaveSettings(_advancedPasteSettings.ToJsonString(), AdvancedPasteSettings.ModuleName);
NotifySettingsChanged();
}
}
}
public HotkeySettings PasteAsPlainTextShortcut
{
get => _advancedPasteSettings.Properties.PasteAsPlainTextShortcut;
set
{
if (_advancedPasteSettings.Properties.PasteAsPlainTextShortcut != value)
{
_advancedPasteSettings.Properties.PasteAsPlainTextShortcut = value ?? AdvancedPasteProperties.DefaultPasteAsPlainTextShortcut;
OnPropertyChanged(nameof(PasteAsPlainTextShortcut));
OnPropertyChanged(nameof(IsConflictingCopyShortcut));
_settingsUtils.SaveSettings(_advancedPasteSettings.ToJsonString(), AdvancedPasteSettings.ModuleName);
NotifySettingsChanged();
}
}
}
public HotkeySettings PasteAsMarkdownShortcut
{
get => _advancedPasteSettings.Properties.PasteAsMarkdownShortcut;
set
{
if (_advancedPasteSettings.Properties.PasteAsMarkdownShortcut != value)
{
_advancedPasteSettings.Properties.PasteAsMarkdownShortcut = value ?? new HotkeySettings();
OnPropertyChanged(nameof(PasteAsMarkdownShortcut));
OnPropertyChanged(nameof(IsConflictingCopyShortcut));
_settingsUtils.SaveSettings(_advancedPasteSettings.ToJsonString(), AdvancedPasteSettings.ModuleName);
NotifySettingsChanged();
}
}
}
public HotkeySettings PasteAsJsonShortcut
{
get => _advancedPasteSettings.Properties.PasteAsJsonShortcut;
set
{
if (_advancedPasteSettings.Properties.PasteAsJsonShortcut != value)
{
_advancedPasteSettings.Properties.PasteAsJsonShortcut = value ?? new HotkeySettings();
OnPropertyChanged(nameof(PasteAsJsonShortcut));
OnPropertyChanged(nameof(IsConflictingCopyShortcut));
_settingsUtils.SaveSettings(_advancedPasteSettings.ToJsonString(), AdvancedPasteSettings.ModuleName);
NotifySettingsChanged();
}
}
}
public bool ShowCustomPreview
{
get => _advancedPasteSettings.Properties.ShowCustomPreview;
set
{
if (value != _advancedPasteSettings.Properties.ShowCustomPreview)
{
_advancedPasteSettings.Properties.ShowCustomPreview = value;
NotifySettingsChanged();
}
}
}
public bool IsConflictingCopyShortcut
{
get
{
return PasteAsPlainTextShortcut.ToString() == "Ctrl + V" || PasteAsPlainTextShortcut.ToString() == "Ctrl + Shift + V" ||
AdvancedPasteUIShortcut.ToString() == "Ctrl + V" || AdvancedPasteUIShortcut.ToString() == "Ctrl + Shift + V" ||
PasteAsMarkdownShortcut.ToString() == "Ctrl + V" || PasteAsMarkdownShortcut.ToString() == "Ctrl + Shift + V" ||
PasteAsJsonShortcut.ToString() == "Ctrl + V" || PasteAsJsonShortcut.ToString() == "Ctrl + Shift + V";
}
}
private void DelayedTimer_Tick(object sender, EventArgs e)
{
lock (_delayedActionLock)
{
_delayedTimer.Stop();
NotifySettingsChanged();
}
}
private void NotifySettingsChanged()
{
// Using InvariantCulture as this is an IPC message
SendConfigMSG(
string.Format(
CultureInfo.InvariantCulture,
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
AdvancedPasteSettings.ModuleName,
JsonSerializer.Serialize(_advancedPasteSettings)));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_delayedTimer.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
internal void DisableAI()
{
PasswordVault vault = new PasswordVault();
PasswordCredential cred = vault.Retrieve("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey");
vault.Remove(cred);
OnPropertyChanged(nameof(IsOpenAIEnabled));
}
internal void EnableAI(string password)
{
PasswordVault vault = new PasswordVault();
PasswordCredential cred = new PasswordCredential("https://platform.openai.com/api-keys", "PowerToys_AdvancedPaste_OpenAIKey", password);
vault.Add(cred);
OnPropertyChanged(nameof(IsOpenAIEnabled));
}
}
}

View File

@@ -146,6 +146,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
return moduleType switch
{
ModuleType.AdvancedPaste => GetModuleItemsAdvancedPaste(),
ModuleType.AlwaysOnTop => GetModuleItemsAlwaysOnTop(),
ModuleType.Awake => GetModuleItemsAwake(),
ModuleType.ColorPicker => GetModuleItemsColorPicker(),
@@ -161,7 +162,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ModuleType.MouseJump => GetModuleItemsMouseJump(),
ModuleType.MousePointerCrosshairs => GetModuleItemsMousePointerCrosshairs(),
ModuleType.MouseWithoutBorders => GetModuleItemsMouseWithoutBorders(),
ModuleType.PastePlain => GetModuleItemsPastePlain(),
ModuleType.Peek => GetModuleItemsPeek(),
ModuleType.PowerRename => GetModuleItemsPowerRename(),
ModuleType.PowerLauncher => GetModuleItemsPowerLauncher(),
@@ -359,13 +359,25 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return new ObservableCollection<DashboardModuleItem>(list);
}
private ObservableCollection<DashboardModuleItem> GetModuleItemsPastePlain()
private ObservableCollection<DashboardModuleItem> GetModuleItemsAdvancedPaste()
{
ISettingsRepository<PastePlainSettings> moduleSettingsRepository = SettingsRepository<PastePlainSettings>.GetInstance(new SettingsUtils());
ISettingsRepository<AdvancedPasteSettings> moduleSettingsRepository = SettingsRepository<AdvancedPasteSettings>.GetInstance(new SettingsUtils());
var list = new List<DashboardModuleItem>
{
new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PastePlain_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AdvancedPasteUI_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList() },
new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsPlainText_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsPlainTextShortcut.GetKeysList() },
};
if (moduleSettingsRepository.SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList().Count > 0)
{
list.Add(new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsMarkdown_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList() });
}
if (moduleSettingsRepository.SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList().Count > 0)
{
list.Add(new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsJson_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList() });
}
return new ObservableCollection<DashboardModuleItem>(list);
}

View File

@@ -1,196 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Text.Json;
using System.Timers;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class PastePlainViewModel : Observable, IDisposable
{
private bool disposedValue;
// Delay saving of settings in order to avoid calling save multiple times and hitting file in use exception. If there is no other request to save settings in given interval, we proceed to save it, otherwise we schedule saving it after this interval
private const int SaveSettingsDelayInMs = 500;
private GeneralSettings GeneralSettingsConfig { get; set; }
private readonly ISettingsUtils _settingsUtils;
private readonly object _delayedActionLock = new object();
private readonly PastePlainSettings _pastePlainSettings;
private Timer _delayedTimer;
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private Func<string, int> SendConfigMSG { get; }
public PastePlainViewModel(
ISettingsUtils settingsUtils,
ISettingsRepository<GeneralSettings> settingsRepository,
ISettingsRepository<PastePlainSettings> pastePlainSettingsRepository,
Func<string, int> ipcMSGCallBackFunc)
{
// To obtain the general settings configurations of PowerToys Settings.
ArgumentNullException.ThrowIfNull(settingsRepository);
GeneralSettingsConfig = settingsRepository.SettingsConfig;
// To obtain the settings configurations of Fancy zones.
ArgumentNullException.ThrowIfNull(settingsRepository);
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
ArgumentNullException.ThrowIfNull(pastePlainSettingsRepository);
_pastePlainSettings = pastePlainSettingsRepository.SettingsConfig;
InitializeEnabledValue();
// set the callback functions value to handle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
_delayedTimer = new Timer();
_delayedTimer.Interval = SaveSettingsDelayInMs;
_delayedTimer.Elapsed += DelayedTimer_Tick;
_delayedTimer.AutoReset = false;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredPastePlainEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.PastePlain;
}
}
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (_isEnabled != value)
{
_isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
// Set the status of PastePlain in the general settings
GeneralSettingsConfig.Enabled.PastePlain = value;
var outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(outgoing.ToString());
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public HotkeySettings ActivationShortcut
{
get => _pastePlainSettings.Properties.ActivationShortcut;
set
{
if (_pastePlainSettings.Properties.ActivationShortcut != value)
{
_pastePlainSettings.Properties.ActivationShortcut = value ?? _pastePlainSettings.Properties.DefaultActivationShortcut;
OnPropertyChanged(nameof(ActivationShortcut));
OnPropertyChanged(nameof(IsConflictingCopyShortcut));
_settingsUtils.SaveSettings(_pastePlainSettings.ToJsonString(), PastePlainSettings.ModuleName);
NotifySettingsChanged();
}
}
}
public bool IsConflictingCopyShortcut
{
get
{
return ActivationShortcut.ToString() == "Ctrl + V" || ActivationShortcut.ToString() == "Ctrl + Shift + V";
}
}
private void ScheduleSavingOfSettings()
{
lock (_delayedActionLock)
{
if (_delayedTimer.Enabled)
{
_delayedTimer.Stop();
}
_delayedTimer.Start();
}
}
private void DelayedTimer_Tick(object sender, EventArgs e)
{
lock (_delayedActionLock)
{
_delayedTimer.Stop();
NotifySettingsChanged();
}
}
private void NotifySettingsChanged()
{
// Using InvariantCulture as this is an IPC message
SendConfigMSG(
string.Format(
CultureInfo.InvariantCulture,
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
PastePlainSettings.ModuleName,
JsonSerializer.Serialize(_pastePlainSettings)));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_delayedTimer.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}