CmdPal: Extension list search (#41453)

## Summary of the Pull Request

Adds a rough implementation that appears to work, but it hasn’t been
tested. Don’t rely on it yet—I’m too tired to test properly or write a
polished commit message.

Pictures? Pictures!

<img width="2720" height="1624" alt="image"
src="https://github.com/user-attachments/assets/4f9c3360-8d08-4a34-888f-c6890afd0159"
/>

<img width="2647" height="1558" alt="image"
src="https://github.com/user-attachments/assets/3d6c23bc-f26d-4e31-ae09-d91efd304048"
/>

<img width="2683" height="1536" alt="image"
src="https://github.com/user-attachments/assets/6017b2d4-ccd9-4555-b81f-e2b1f78c48e5"
/>

<img width="577" height="334" alt="image"
src="https://github.com/user-attachments/assets/987fea99-05b2-4d31-b90c-327122daa241"
/>


https://github.com/user-attachments/assets/65a8f8ce-ae09-4272-881d-0b6f56cecfae

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

- [x] Closes: #41451
- [x] Closes: #42031
- [x] Closes: #41800
- [ ] **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

---------

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Michael Jolley <mike@baldbeardedbuilder.com>
This commit is contained in:
Jiří Polášek
2025-10-28 20:36:42 +01:00
committed by GitHub
parent de00cbf20a
commit 1e40d6b15b
14 changed files with 743 additions and 2 deletions

View File

@@ -14,18 +14,204 @@
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<!-- ControlFillColorQuarternaryBrush does not exist (yet) in WinUI, only in Windows Visual Library (Figma) -->
<ResourceDictionary x:Key="Default">
<LinearGradientBrush x:Key="CardGradient2Brush" StartPoint="0,0" EndPoint="0.5, 1">
<GradientStop Offset="0" Color="#38C8AEC4" />
<GradientStop Offset="1" Color="#383286EE" />
</LinearGradientBrush>
<ImageSource x:Key="StoreLogo">ms-appx:///Assets/StoreLogo.dark.svg</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<LinearGradientBrush x:Key="CardGradient2Brush" StartPoint="0,0" EndPoint="1, 1">
<!--<GradientStop Offset="0" Color="#E6F0FC" />
<GradientStop Offset="0.4" Color="#E6F0FC" />
<GradientStop Offset="1" Color="#F0F0F7" />-->
<GradientStop Offset="0.0" Color="#FFF6F9FF" />
<!-- Light cool white -->
<GradientStop Offset="0.4" Color="#FFEFF5FF" />
<!-- Hinted lavender/blue -->
<GradientStop Offset="0.7" Color="#FFF7FAFD" />
<!-- Very soft neutral white -->
<GradientStop Offset="1.0" Color="#FFF5F8FA" />
<!-- Slight bluish-gray tint -->
<!-- Faint peach glow -->
<!-- Soft peach -->
</LinearGradientBrush>
<ImageSource x:Key="StoreLogo">ms-appx:///Assets/StoreLogo.light.svg</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="CardGradient2Brush" Color="Transparent" />
<SolidColorBrush x:Key="CardGradient1Brush" Color="Transparent" />
<ImageSource x:Key="StoreLogo">ms-appx:///Assets/StoreLogo.dark.svg</ImageSource>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<converters:BoolNegationConverter x:Key="InvertedBoolConverter" />
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</ResourceDictionary>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="1">
<ScrollViewer x:Name="RootScrollViewer" Grid.Row="1">
<Grid Padding="16">
<StackPanel
MaxWidth="1000"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<ItemsRepeater ItemsSource="{x:Bind viewModel.CommandProviders, Mode=OneWay}" Layout="{StaticResource VerticalStackLayout}">
<!-- Banner -->
<Grid
Padding="16"
Background="{ThemeResource CardGradient2Brush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="BannerDescriptionPanel" Orientation="Vertical">
<TextBlock x:Uid="Settings_ExtensionsPage_Banner_Header" FontWeight="SemiBold" />
<TextBlock
x:Uid="Settings_ExtensionsPage_Banner_Description"
Grid.Row="1"
MaxWidth="520"
HorizontalAlignment="Left"
TextWrapping="Wrap" />
<HyperlinkButton
x:Uid="Settings_ExtensionsPage_Banner_Hyperlink"
Padding="0"
Content="Learn how to create your own extensions"
NavigateUri="https://learn.microsoft.com/windows/powertoys/command-palette/overview" />
</StackPanel>
<StackPanel
x:Name="ButtonPanel"
Grid.Column="1"
Orientation="Horizontal"
Spacing="8">
<Button x:Uid="Settings_ExtensionsPage_FindExtensions_MicrosoftStore" Command="{x:Bind viewModel.Extensions.OpenStoreWithExtensionCommand}">
<StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16">
<Image AutomationProperties.AccessibilityView="Raw" Source="{ThemeResource StoreLogo}" />
</Viewbox>
<TextBlock Text="Microsoft Store" />
</StackPanel>
</Button>
<!--<Button x:Uid="Settings_ExtensionsPage_FindExtensions_WinGet" Command="{x:Bind viewModel.Extensions.OpenStoreWithExtensionCommand}">
<StackPanel Orientation="Horizontal" Spacing="8">
<Viewbox Width="16">
<Image AutomationProperties.AccessibilityView="Raw" Source="ms-appx:///Assets/WinGet.svg" />
</Viewbox>
<TextBlock Text="WinGet" />
</StackPanel>
</Button>-->
</StackPanel>
</Grid>
<!-- Search -->
<Grid Padding="0,24,0,8" ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MaxWidth="320" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<AutoSuggestBox
x:Name="SearchBox"
x:Uid="Settings_ExtensionsPage_SearchBox_Placeholder"
HorizontalAlignment="Stretch"
Text="{x:Bind viewModel.Extensions.SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<AutoSuggestBox.QueryIcon>
<SymbolIcon Symbol="Find" />
</AutoSuggestBox.QueryIcon>
<AutoSuggestBox.KeyboardAccelerators>
<KeyboardAccelerator
Key="F"
Invoked="OnFindInvoked"
Modifiers="Control" />
</AutoSuggestBox.KeyboardAccelerators>
</AutoSuggestBox>
<StackPanel
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<TextBlock
x:Name="ItemCounterTextBlock"
VerticalAlignment="Center"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind viewModel.Extensions.ItemCounterText, Mode=OneWay}" />
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8"
Visibility="{x:Bind viewModel.Extensions.ShowManualReloadOverlay, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<ProgressRing
Width="16"
Height="16"
IsActive="True" />
<TextBlock
x:Uid="Settings_ExtensionsPage_Reloading_Text"
VerticalAlignment="Center"
Style="{StaticResource BodyTextBlockStyle}" />
</StackPanel>
<Button
x:Name="MoreButton"
x:Uid="Settings_ExtensionsPage_More_Button"
Style="{StaticResource SubtleButtonStyle}">
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedRight">
<MenuFlyoutItem x:Uid="Settings_ExtensionsPage_More_Reload_MenuFlyoutItem" Command="{x:Bind viewModel.Extensions.ReloadExtensionsCommand}">
<MenuFlyoutItem.Icon>
<FontIcon Glyph="&#xE777;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
</MenuFlyout>
</Button.Flyout>
<FontIcon
AutomationProperties.AccessibilityView="Raw"
FontSize="16"
Glyph="&#xE712;" />
</Button>
</StackPanel>
</Grid>
<!-- Empty state when no results match the current search -->
<Grid
x:Name="NoResultsPanel"
Padding="48"
x:Load="{x:Bind viewModel.Extensions.ShowNoResultsPanel, Mode=OneWay}"
CornerRadius="4">
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="8">
<TextBlock
x:Uid="Settings_ExtensionsPage_NoResults_Primary"
Style="{StaticResource BodyStrongTextBlockStyle}"
TextAlignment="Center" />
<TextBlock
x:Uid="Settings_ExtensionsPage_NoResults_Secondary"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextAlignment="Center" />
</StackPanel>
</Grid>
<ItemsRepeater
x:Name="ProvidersRepeater"
x:Load="{x:Bind viewModel.Extensions.HasResults, Mode=OneWay}"
ItemsSource="{x:Bind viewModel.Extensions.FilteredProviders, Mode=OneWay}"
Layout="{StaticResource VerticalStackLayout}">
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="viewModels:ProviderSettingsViewModel">
<controls:SettingsCard
@@ -54,5 +240,25 @@
</StackPanel>
</Grid>
</ScrollViewer>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="NarrowLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ButtonPanel.(Grid.Row)" Value="1" />
<Setter Target="BannerDescriptionPanel.(Grid.ColumnSpan)" Value="2" />
<Setter Target="ButtonPanel.(Grid.Column)" Value="0" />
<Setter Target="ButtonPanel.Margin" Value="0,12,0,0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>

View File

@@ -8,6 +8,7 @@ using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace Microsoft.CmdPal.UI.Settings;
@@ -35,4 +36,10 @@ public sealed partial class ExtensionsPage : Page
}
}
}
private void OnFindInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
SearchBox?.Focus(FocusState.Keyboard);
args.Handled = true;
}
}