[AP] Settings UI improvements (#43488)

## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
This commit is contained in:
Niels Laute
2025-11-13 02:32:25 +01:00
committed by GitHub
parent 2a40e1ce4d
commit 1b742ef817
3 changed files with 143 additions and 77 deletions

View File

@@ -42,8 +42,9 @@
HorizontalAlignment="Center" />
<TextBlock
x:Name="LoadingStatusTextBlock"
x:Uid="AdvancedPaste_FL_LoadingStatus"
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Loading Foundry Local status..."
TextAlignment="Center"
TextWrapping="Wrap" />
</StackPanel>
@@ -56,7 +57,6 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel
x:Name="NoModelsPanel"
Grid.Row="0"
@@ -64,24 +64,28 @@
HorizontalAlignment="Center"
Orientation="Vertical"
Spacing="4">
<FontIcon FontSize="24" Glyph="&#xE74E;" />
<FontIcon
AutomationProperties.AccessibilityView="Raw"
FontSize="24"
Glyph="&#xF158;" />
<TextBlock
x:Uid="AdvancedPaste_FL_NoModelsDownloaded."
HorizontalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}"
Text="No models downloaded"
TextAlignment="Center" />
<TextBlock
x:Uid="AdvancedPaste_FL_RunFoundryLocalText.Text"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Run Foundry Local to download or add a local model below."
TextAlignment="Center"
TextWrapping="Wrap" />
<Button
x:Name="LaunchFoundryModelListButton"
x:Uid="AdvancedPaste_FL_OpenFoundryModelList"
Margin="0,8,0,0"
HorizontalAlignment="Center"
Click="LaunchFoundryModelListButton_Click"
Content="Open Foundry model list"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
@@ -101,10 +105,10 @@
SelectionChanged="CachedModelsComboBox_SelectionChanged">
<ComboBox.Header>
<TextBlock>
<Run Text="Foundry Local model" /><LineBreak /><Run
<Run x:Uid="AdvancedPaste_FL_LocalModel" /><LineBreak /><Run
x:Uid="AdvancedPaste_FL_UseCLIToDownloadModels"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Use the Foundry Local CLI to download models that run locally on-device. They'll appear here." />
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
</ComboBox.Header>
</ComboBox>
@@ -114,9 +118,11 @@
MinHeight="32"
VerticalAlignment="Bottom"
Click="RefreshModelsButton_Click"
Style="{StaticResource SubtleButtonStyle}"
ToolTipService.ToolTip="Refresh model list">
Style="{StaticResource SubtleButtonStyle}">
<FontIcon FontSize="16" Glyph="&#xE72C;" />
<ToolTipService.ToolTip>
<TextBlock x:Uid="AdvancedPaste_FL_RefreshModelList" />
</ToolTipService.ToolTip>
</Button>
</Grid>
<StackPanel
@@ -146,24 +152,28 @@
Spacing="8">
<Image Width="36" Source="ms-appx:///Assets/Settings/Icons/Models/FoundryLocal.svg" />
<TextBlock
x:Uid="AdvancedPaste_FL_FLNotavailableYet"
HorizontalAlignment="Center"
FontWeight="SemiBold"
Text="Foundry Local is not available on this device yet."
TextAlignment="Center"
TextWrapping="Wrap" />
<TextBlock
x:Uid="AdvancedPaste_FL_StartService"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
IsTextSelectionEnabled="True"
TextAlignment="Center"
TextWrapping="Wrap">
<Run Text="Start the Foundry Local service before returning to PowerToys." />
</TextBlock>
<HyperlinkButton Content="Follow the Foundry Local CLI guide" NavigateUri="https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-local/get-started" />
TextWrapping="Wrap" />
<HyperlinkButton
x:Uid="AdvancedPaste_FL_CLIGuide"
HorizontalAlignment="Center"
NavigateUri="https://learn.microsoft.com/azure/ai-foundry/foundry-local/get-started" />
<TextBlock
x:Uid="FoundryLocal_RestartRequiredNote"
HorizontalAlignment="Center"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Note: After installing the Foundry Local CLI, restart PowerToys to use it."
TextAlignment="Center"
TextWrapping="Wrap" />
</StackPanel>

View File

@@ -103,10 +103,7 @@
</StackPanel>
</tkcontrols:SettingsExpander.Description>
<tkcontrols:SettingsExpander.ItemsHeader>
<tkcontrols:SettingsCard
Description="Add online or local models"
Header="Model providers"
Style="{StaticResource DefaultSettingsExpanderItemStyle}">
<tkcontrols:SettingsCard x:Uid="AdvancedPaste_ModelProviders" Style="{StaticResource DefaultSettingsExpanderItemStyle}">
<Button Content="Add model" Style="{StaticResource AccentButtonStyle}">
<Button.Flyout>
<MenuFlyout x:Name="AddProviderMenuFlyout" Opening="AddProviderMenuFlyout_Opening" />
@@ -130,16 +127,16 @@
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem
x:Uid="AdvancedPaste_Edit"
Click="EditPasteAIProviderButton_Click"
Icon="{ui:FontIcon Glyph=&#xE70F;}"
Tag="{x:Bind}"
Text="Edit" />
Tag="{x:Bind}" />
<MenuFlyoutSeparator />
<MenuFlyoutItem
x:Uid="AdvancedPaste_Remove"
Click="RemovePasteAIProviderButton_Click"
Icon="{ui:FontIcon Glyph=&#xE74D;}"
Tag="{x:Bind}"
Text="Remove" />
Tag="{x:Bind}" />
</MenuFlyout>
</Button.Flyout>
</Button>
@@ -496,45 +493,43 @@
Spacing="16">
<TextBox
x:Name="PasteAIModelNameTextBox"
x:Uid="AdvancedPaste_ModelName"
MinWidth="200"
HorizontalAlignment="Stretch"
Header="Model name"
PlaceholderText="gpt-4o"
Text="{x:Bind ViewModel.PasteAIProviderDraft.ModelName, Mode=TwoWay}" />
<TextBox
x:Name="PasteAIEndpointUrlTextBox"
x:Uid="AdvancedPaste_EndpointURL"
MinWidth="200"
HorizontalAlignment="Stretch"
Header="Endpoint URL"
PlaceholderText="https://your-resource.openai.azure.com/"
Text="{x:Bind ViewModel.PasteAIProviderDraft.EndpointUrl, Mode=TwoWay}" />
<PasswordBox
x:Name="PasteAIApiKeyPasswordBox"
MinWidth="200"
Header="API key"
PlaceholderText="Enter API Key" />
x:Uid="AdvancedPaste_APIKey"
MinWidth="200" />
<TextBox
x:Name="PasteAIApiVersionTextBox"
x:Uid="AdvancedPaste_APIVersion"
MinWidth="200"
HorizontalAlignment="Stretch"
Header="API version"
PlaceholderText="2024-10-01"
Text="{x:Bind ViewModel.PasteAIProviderDraft.ApiVersion, Mode=TwoWay}"
Visibility="Collapsed" />
<TextBox
x:Name="PasteAIDeploymentNameTextBox"
x:Uid="AdvancedPaste_DeploymentName"
MinWidth="200"
Header="Deployment name"
PlaceholderText="gpt-4o"
Text="{x:Bind ViewModel.PasteAIProviderDraft.DeploymentName, Mode=TwoWay}" />
<TextBox
x:Name="PasteAISystemPromptTextBox"
x:Uid="AdvancedPaste_SystemPrompt"
MinWidth="200"
MinHeight="76"
HorizontalAlignment="Stretch"
AcceptsReturn="True"
Header="System prompt"
PlaceholderText="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."
Text="{x:Bind ViewModel.PasteAIProviderDraft.SystemPrompt, Mode=TwoWay}"
TextWrapping="Wrap" />
@@ -575,13 +570,10 @@
IsOn="{x:Bind ViewModel.PasteAIProviderDraft.EnableAdvancedAI, Mode=TwoWay}"
Toggled="PasteAIEnableAdvancedAICheckBox_Toggled"
Visibility="Collapsed">
<ToolTipService.ToolTip>
<TextBlock Text="" TextWrapping="Wrap" />
</ToolTipService.ToolTip>
<ToggleSwitch.Header>
<TextBlock>
<Run Text="Enable Advanced AI" /> <LineBreak />
<Run Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Use built-in functions to handle complex tasks. Token consumption may increase." />
<Run x:Uid="AdvancedPaste_EnableAdvancedAI" /> <LineBreak />
<Run x:Uid="AdvancedPaste_EnableAdvancedAIDescription" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
</ToggleSwitch.Header>
</ToggleSwitch>

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -644,14 +644,11 @@ Please review the placeholder content that represents the final terms and usage
<data name="AdvancedPaste_EnablePasteAIModerationToggle.Header" xml:space="preserve">
<value>Enable OpenAI content moderation</value>
</data>
<data name="AdvancedPaste_EnableAdvancedAI_SettingsCard.Header" xml:space="preserve">
<value>Enable Advanced AI</value>
</data>
<data name="AdvancedPaste_EnableAdvancedAI_SettingsCard.Description" xml:space="preserve">
<data name="AdvancedPaste_EnableAdvancedAIDescription.Text" xml:space="preserve">
<value>Use built-in functions to handle complex tasks. Token consumption may increase.</value>
</data>
<data name="AdvancedPaste_Clipboard_History_Enabled_SettingsCard.Header" xml:space="preserve">
<value>Access Clipboard History</value>
<value>Show what's currently on your Clipboard and access your Clipboard history</value>
</data>
<data name="AdvancedPaste_Clipboard_History_Enabled_SettingsCard.Description" xml:space="preserve">
<value>Clipboard History shows a list of previously copied items.</value>
@@ -4058,11 +4055,8 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="AdvancedPaste_ShowCustomPreviewSettingsCard.Description" xml:space="preserve">
<value>Preview the output of AI formats and Image to text before pasting</value>
</data>
<data name="AdvancedPaste_EnableAdvancedAI.Header" xml:space="preserve">
<value>Advanced AI</value>
</data>
<data name="AdvancedPaste_EnableAdvancedAI.Description" xml:space="preserve">
<value>Supports advanced workflows by chaining transformations and working with files and images. May use additional API credits.</value>
<data name="AdvancedPaste_EnableAdvancedAI.Text" xml:space="preserve">
<value>Enable Advanced AI</value>
</data>
<data name="Oobe_AdvancedPaste.Description" xml:space="preserve">
<value>Advanced Paste is a tool to put your clipboard content into any format you need, focused towards developer workflows. It can paste as plain text, markdown, or json directly with the UX or with a direct keystroke invoke. These are fully locally executed. In addition, it has an AI powered option that is 100% opt-in and requires an Open AI key. Note: this will replace the formatted text in your clipboard with the selected format.</value>
@@ -4604,7 +4598,7 @@ Activate by holding the key for the character you want to add an accent to, then
<value>If you do not have credits you will see an 'API key quota exceeded' error</value>
</data>
<data name="AdvancedPaste_CloseAfterLosingFocus.Content" xml:space="preserve">
<value>Automatically close the Advanced Paste window after it loses focus</value>
<value>Automatically close the window after it loses focus</value>
<comment>Advanced Paste is a product name, do not loc</comment>
</data>
<data name="GPO_CommandNotFound_ForceDisabled.Title" xml:space="preserve">
@@ -5679,4 +5673,74 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="LightSwitch_SetLocationButton.Content" xml:space="preserve">
<value>Set Location</value>
</data>
<data name="AdvancedPaste_FL_OpenFoundryModelList.Content" xml:space="preserve">
<value>Open Foundry Local model list</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_RunFoundryLocalText.Text" xml:space="preserve">
<value>Run Foundry Local to download or add a local model</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_NoModelsDownloaded.Text" xml:space="preserve">
<value>No models downloaded</value>
</data>
<data name="AdvancedPaste_FL_LoadingStatus.Text" xml:space="preserve">
<value>Loading Foundry Local status..</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_LocalModel.Text" xml:space="preserve">
<value>Foundry Local model</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_UseCLIToDownloadModels.Text" xml:space="preserve">
<value>Use the Foundry Local CLI to download models that run locally on-device. They'll appear here.</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_RefreshModelList.Text" xml:space="preserve">
<value>Refresh model list</value>
</data>
<data name="AdvancedPaste_FL_FLNotavailableYet.Text" xml:space="preserve">
<value>Foundry Local is not available on this device yet.</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_StartService.Text" xml:space="preserve">
<value>Start the Foundry Local service before returning to PowerToys.</value>
</data>
<data name="AdvancedPaste_FL_CLIGuide.Content" xml:space="preserve">
<value>Follow the Foundry Local CLI guide</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_ModelProviders.Header" xml:space="preserve">
<value>Model providers</value>
</data>
<data name="AdvancedPaste_ModelProviders.Description" xml:space="preserve">
<value>Add online or local models</value>
</data>
<data name="AdvancedPaste_Edit.Text" xml:space="preserve">
<value>Edit</value>
</data>
<data name="AdvancedPaste_Remove.Text" xml:space="preserve">
<value>Remove</value>
</data>
<data name="AdvancedPaste_ModelName.Header" xml:space="preserve">
<value>Model name</value>
</data>
<data name="AdvancedPaste_EndpointURL.Header" xml:space="preserve">
<value>Endpoint URL</value>
</data>
<data name="AdvancedPaste_APIKey.Header" xml:space="preserve">
<value>API key</value>
</data>
<data name="AdvancedPaste_APIKey.PlaceholderText" xml:space="preserve">
<value>Enter API key</value>
</data>
<data name="AdvancedPaste_APIVersion.Header" xml:space="preserve">
<value>API version</value>
</data>
<data name="AdvancedPaste_DeploymentName.Header" xml:space="preserve">
<value>Deployment name</value>
</data>
<data name="AdvancedPaste_SystemPrompt.Header" xml:space="preserve">
<value>System prompt</value>
</data>
</root>