mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[AdvancedPaste]Additional actions - Image to text, Paste as file (txt, png, html) (#35167)
* [AdvancedPaste] Additional actions, including Image to text * Spellcheck issue * [AdvancedPaste] Paste as file and many other improvements * Fixed typo * Fixed typo * [AdvancedPaste] Improved paste window menu layout * [AdvancedPaste] Improved settings window layout * [AdvancedPaste] Removed AudioToText for the moment * Code cleanup * Minor fixes * Changed log-line with potentially sensitive info * Extra telemetry for AdvancedPaste * Added 'Hotkey' suffix to AdvancedPaste_Settings telemetry event
This commit is contained in:
@@ -24,6 +24,18 @@
|
||||
<ImageSource x:Key="DialogHeaderImage">ms-appx:///Assets/Settings/Modules/APDialog.light.png</ImageSource>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
<DataTemplate x:Key="AdditionalActionTemplate" x:DataType="models:AdvancedPasteAdditionalAction">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<controls:ShortcutControl
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
AllowDisable="True"
|
||||
HotkeySettings="{x:Bind Shortcut, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsShown, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
@@ -129,6 +141,7 @@
|
||||
AllowDisable="True"
|
||||
HotkeySettings="{x:Bind Path=ViewModel.PasteAsJsonShortcut, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
|
||||
<ItemsControl
|
||||
x:Name="CustomActions"
|
||||
x:Uid="CustomActions"
|
||||
@@ -155,7 +168,7 @@
|
||||
HotkeySettings="{x:Bind Path=Shortcut, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
x:Uid="Enable_CustomAction"
|
||||
AutomationProperties.HelpText="{x:Bind Name}"
|
||||
AutomationProperties.HelpText="{x:Bind Name, Mode=OneWay}"
|
||||
IsOn="{x:Bind IsShown, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
@@ -202,6 +215,56 @@
|
||||
IsTabStop="{x:Bind ViewModel.IsConflictingCopyShortcut, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
</controls:SettingsGroup>
|
||||
|
||||
<controls:SettingsGroup x:Uid="AdvancedPaste_Additional_Actions_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard x:Uid="ImageToText" DataContext="{x:Bind ViewModel.AdditionalActions.ImageToText, Mode=OneWay}">
|
||||
<ContentControl ContentTemplate="{StaticResource AdditionalActionTemplate}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
|
||||
<tkcontrols:SettingsExpander
|
||||
x:Uid="PasteAsFile"
|
||||
DataContext="{x:Bind ViewModel.AdditionalActions.PasteAsFile, Mode=OneWay}"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsExpanded="{Binding IsShown, Mode=OneWay}">
|
||||
<tkcontrols:SettingsExpander.Content>
|
||||
<ToggleSwitch
|
||||
IsOn="{Binding IsShown, Mode=TwoWay}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
</tkcontrols:SettingsExpander.Content>
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<!-- HACK: For some weird reason, a ShortcutControl does not work correctly if it's the first or last item in the expander, so we add an invisible card. -->
|
||||
<tkcontrols:SettingsCard Visibility="Collapsed" />
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="PasteAsTxtFile"
|
||||
DataContext="{Binding PasteAsTxtFile, Mode=TwoWay}"
|
||||
IsEnabled="{x:Bind ViewModel.AdditionalActions.PasteAsFile.IsShown, Mode=OneWay}">
|
||||
<ContentControl ContentTemplate="{StaticResource AdditionalActionTemplate}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="PasteAsPngFile"
|
||||
DataContext="{Binding PasteAsPngFile, Mode=TwoWay}"
|
||||
IsEnabled="{x:Bind ViewModel.AdditionalActions.PasteAsFile.IsShown, Mode=OneWay}">
|
||||
<ContentControl ContentTemplate="{StaticResource AdditionalActionTemplate}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard
|
||||
x:Uid="PasteAsHtmlFile"
|
||||
DataContext="{Binding PasteAsHtmlFile, Mode=TwoWay}"
|
||||
IsEnabled="{x:Bind ViewModel.AdditionalActions.PasteAsFile.IsShown, Mode=OneWay}">
|
||||
<ContentControl ContentTemplate="{StaticResource AdditionalActionTemplate}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<!-- HACK: For some weird reason, a ShortcutControl does not work correctly if it's the first or last item in the expander, so we add an invisible card. -->
|
||||
<tkcontrols:SettingsCard Visibility="Collapsed" />
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
|
||||
<InfoBar
|
||||
x:Uid="AdvancedPaste_ShortcutWarning"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind ViewModel.IsAdditionalActionConflictingCopyShortcut, Mode=OneWay}"
|
||||
IsTabStop="{x:Bind ViewModel.IsAdditionalActionConflictingCopyShortcut, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
</controls:SettingsGroup>
|
||||
</StackPanel>
|
||||
</controls:SettingsPageControl.ModuleContent>
|
||||
<controls:SettingsPageControl.PrimaryLinks>
|
||||
|
||||
@@ -725,6 +725,9 @@
|
||||
<data name="AdvancedPaste_Direct_Access_Hotkeys_GroupSettings.Header" xml:space="preserve">
|
||||
<value>Actions</value>
|
||||
</data>
|
||||
<data name="AdvancedPaste_Additional_Actions_GroupSettings.Header" xml:space="preserve">
|
||||
<value>Additional actions</value>
|
||||
</data>
|
||||
<data name="RemapKeysList.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Current Key Remappings</value>
|
||||
</data>
|
||||
@@ -2046,6 +2049,21 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<data name="PasteAsCustom_Shortcut.Header" xml:space="preserve">
|
||||
<value>Paste as Custom with AI directly</value>
|
||||
</data>
|
||||
<data name="ImageToText.Header" xml:space="preserve">
|
||||
<value>Image to text</value>
|
||||
</data>
|
||||
<data name="PasteAsFile.Header" xml:space="preserve">
|
||||
<value>Paste as file</value>
|
||||
</data>
|
||||
<data name="PasteAsTxtFile.Header" xml:space="preserve">
|
||||
<value>Paste as .txt file</value>
|
||||
</data>
|
||||
<data name="PasteAsPngFile.Header" xml:space="preserve">
|
||||
<value>Paste as .png file</value>
|
||||
</data>
|
||||
<data name="PasteAsHtmlFile.Header" xml:space="preserve">
|
||||
<value>Paste as .html file</value>
|
||||
</data>
|
||||
<data name="AdvancedPaste_EnableAIDialogOpenAIApiKey.Text" xml:space="preserve">
|
||||
<value>OpenAI API key:</value>
|
||||
</data>
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private readonly object _delayedActionLock = new object();
|
||||
|
||||
private readonly AdvancedPasteSettings _advancedPasteSettings;
|
||||
private readonly AdvancedPasteAdditionalActions _additionalActions;
|
||||
private readonly ObservableCollection<AdvancedPasteCustomAction> _customActions;
|
||||
private Timer _delayedTimer;
|
||||
|
||||
@@ -69,6 +70,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
_advancedPasteSettings = advancedPasteSettingsRepository.SettingsConfig;
|
||||
|
||||
_additionalActions = _advancedPasteSettings.Properties.AdditionalActions;
|
||||
_customActions = _advancedPasteSettings.Properties.CustomActions.Value;
|
||||
|
||||
InitializeEnabledValue();
|
||||
@@ -81,6 +83,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
_delayedTimer.Elapsed += DelayedTimer_Tick;
|
||||
_delayedTimer.AutoReset = false;
|
||||
|
||||
foreach (var action in _additionalActions.AllActions)
|
||||
{
|
||||
action.PropertyChanged += OnAdditionalActionPropertyChanged;
|
||||
}
|
||||
|
||||
foreach (var customAction in _customActions)
|
||||
{
|
||||
customAction.PropertyChanged += OnCustomActionPropertyChanged;
|
||||
@@ -143,6 +150,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
public ObservableCollection<AdvancedPasteCustomAction> CustomActions => _customActions;
|
||||
|
||||
public AdvancedPasteAdditionalActions AdditionalActions => _additionalActions;
|
||||
|
||||
private bool OpenAIKeyExists()
|
||||
{
|
||||
PasswordVault vault = new PasswordVault();
|
||||
@@ -336,12 +345,16 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsConflictingCopyShortcut
|
||||
{
|
||||
get => _customActions.Select(customAction => customAction.Shortcut)
|
||||
.Concat([PasteAsPlainTextShortcut, AdvancedPasteUIShortcut, PasteAsMarkdownShortcut, PasteAsJsonShortcut])
|
||||
.Any(hotkey => WarnHotkeys.Contains(hotkey.ToString()));
|
||||
}
|
||||
public bool IsConflictingCopyShortcut =>
|
||||
_customActions.Select(customAction => customAction.Shortcut)
|
||||
.Concat([PasteAsPlainTextShortcut, AdvancedPasteUIShortcut, PasteAsMarkdownShortcut, PasteAsJsonShortcut])
|
||||
.Any(hotkey => WarnHotkeys.Contains(hotkey.ToString()));
|
||||
|
||||
public bool IsAdditionalActionConflictingCopyShortcut =>
|
||||
_additionalActions.AllActions
|
||||
.OfType<AdvancedPasteAdditionalAction>()
|
||||
.Select(additionalAction => additionalAction.Shortcut)
|
||||
.Any(hotkey => WarnHotkeys.Contains(hotkey.ToString()));
|
||||
|
||||
private void DelayedTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
@@ -461,6 +474,16 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
|
||||
private void OnAdditionalActionPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
SaveAndNotifySettings();
|
||||
|
||||
if (e.PropertyName == nameof(AdvancedPasteAdditionalAction.Shortcut))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsAdditionalActionConflictingCopyShortcut));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCustomActionPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (typeof(AdvancedPasteCustomAction).GetProperty(e.PropertyName).GetCustomAttribute<JsonIgnoreAttribute>() == null)
|
||||
|
||||
Reference in New Issue
Block a user