mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Implements comprehensive hotkey conflict detection and resolution system for PowerToys, providing real-time conflict checking and centralized management interface. ## PR Checklist - [ ] **Closes:** #xxx - [x] **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 - [x] **Localization:** All end-user-facing strings can be localized - [x] **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) - [x] **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: [Shortcut conflict detction dev spec](https://github.com/MicrosoftDocs/windows-dev-docs/pull/5519) ## TODO Lists - [x] Add real-time hotkey validation functionality to the hotkey dialog - [x] Immediately detect conflicts and update shortcut conflict status after applying new shortcuts - [x] Return conflict list from runner hotkey conflict detector for conflict checking. - [x] Implement the Tooltip for every shortcut control - [x] Add dialog UI for showing all the shortcut conflicts - [x] Support changing shortcut directly inside the shortcut conflict window/dialog, no need to nav to the settings page. - [x] Redesign the `ShortcutConflictDialogContentControl` to align with the spec - [x] Add navigating and changing hotkey auctionability to the `ShortcutConflictDialogContentControl` - [x] Add telemetry. Impemented in [another PR](https://github.com/shuaiyuanxx/PowerToys/pull/47) ## Shortcut Conflict Support Modules  <details> <summary>Demo videos</summary> https://github.com/user-attachments/assets/476d992c-c6ca-4bcd-a3f2-b26cc612d1b9 https://github.com/user-attachments/assets/1c1a2537-de54-4db2-bdbf-6f1908ff1ce7 https://github.com/user-attachments/assets/9c992254-fc2b-402c-beec-20fceef25e6b https://github.com/user-attachments/assets/d66abc1c-b8bf-45f8-a552-ec989dab310f </details> <!-- 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 Manually validation performed. --------- Signed-off-by: Shawn Yuan <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
365 lines
21 KiB
XML
365 lines
21 KiB
XML
<Page
|
|
x:Class="Microsoft.PowerToys.Settings.UI.Views.DashboardPage"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:Lib="using:Microsoft.PowerToys.Settings.UI.Library"
|
|
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
|
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
|
|
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:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
|
xmlns:viewmodels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
|
|
AutomationProperties.LandmarkType="Main"
|
|
DataContext="DashboardViewModel"
|
|
mc:Ignorable="d">
|
|
<Page.Resources>
|
|
<converters:ModuleItemTemplateSelector
|
|
x:Key="ModuleItemTemplateSelector"
|
|
ActivationTemplate="{StaticResource ModuleItemActivationTemplate}"
|
|
ShortcutTemplate="{StaticResource ModuleItemShortcutTemplate}" />
|
|
<DataTemplate x:Key="ModuleItemShortcutTemplate" x:DataType="viewmodels:DashboardModuleShortcutItem">
|
|
<Grid MinHeight="36" ColumnSpacing="12">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" MinWidth="140" />
|
|
</Grid.ColumnDefinitions>
|
|
<ItemsControl
|
|
Grid.Column="1"
|
|
HorizontalAlignment="Left"
|
|
AutomationProperties.AccessibilityView="Raw"
|
|
IsTabStop="False"
|
|
ItemsSource="{x:Bind Shortcut, Mode=OneWay}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<StackPanel Orientation="Horizontal" Spacing="4" />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate>
|
|
<controls:KeyVisual
|
|
VerticalAlignment="Center"
|
|
AutomationProperties.AccessibilityView="Raw"
|
|
Content="{Binding}"
|
|
FontSize="12"
|
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
IsTabStop="False"
|
|
RenderKeyAsGlyph="True" />
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
<TextBlock
|
|
VerticalAlignment="Center"
|
|
Text="{x:Bind Label, Mode=OneWay}"
|
|
TextWrapping="WrapWholeWords" />
|
|
</Grid>
|
|
</DataTemplate>
|
|
<DataTemplate x:Key="ModuleItemActivationTemplate" x:DataType="viewmodels:DashboardModuleActivationItem">
|
|
<Grid MinHeight="36" ColumnSpacing="12">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" MinWidth="140" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock
|
|
VerticalAlignment="Center"
|
|
Text="{x:Bind Label, Mode=OneWay}"
|
|
TextWrapping="WrapWholeWords" />
|
|
<TextBlock
|
|
Grid.Column="1"
|
|
VerticalAlignment="Center"
|
|
FontSize="12"
|
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
Text="{x:Bind Activation, Mode=OneWay}"
|
|
TextWrapping="WrapWholeWords" />
|
|
</Grid>
|
|
</DataTemplate>
|
|
</Page.Resources>
|
|
<Grid Margin="16,0,0,0" RowSpacing="12">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
</Grid.RowDefinitions>
|
|
<TextBlock
|
|
x:Uid="DashboardTitle"
|
|
MaxWidth="{StaticResource PageMaxWidth}"
|
|
Margin="1,0,0,0"
|
|
VerticalAlignment="Center"
|
|
Style="{StaticResource TitleTextBlockStyle}" />
|
|
<Grid
|
|
Grid.Row="1"
|
|
MaxWidth="{StaticResource PageMaxWidth}"
|
|
Padding="0,0,20,0"
|
|
ColumnSpacing="16">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
<Button
|
|
Padding="0,0,8,0"
|
|
AutomationProperties.Name="WhatsNewButton"
|
|
Click="WhatsNewButton_Click"
|
|
Style="{StaticResource SubtleButtonStyle}">
|
|
<Grid ColumnSpacing="16">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid CornerRadius="{StaticResource OverlayCornerRadius}">
|
|
<Image
|
|
Width="120"
|
|
AutomationProperties.AccessibilityView="Raw"
|
|
Source="ms-appx:///Assets/Settings/Modules/PT.png" />
|
|
<Grid Background="{ThemeResource SmokeFillColorDefaultBrush}" />
|
|
</Grid>
|
|
<StackPanel
|
|
Grid.Column="1"
|
|
VerticalAlignment="Center"
|
|
Orientation="Vertical">
|
|
<TextBlock x:Uid="LearnWhatsNew" FontWeight="SemiBold" />
|
|
<TextBlock
|
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
Style="{StaticResource CaptionTextBlockStyle}"
|
|
Text="{x:Bind ViewModel.PowerToysVersion, Mode=OneWay}" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</Button>
|
|
<StackPanel
|
|
x:Name="TopButtonPanel"
|
|
Grid.Column="1"
|
|
Orientation="Horizontal"
|
|
Spacing="16">
|
|
<controls:ShortcutConflictControl AllHotkeyConflictsData="{x:Bind ViewModel.AllHotkeyConflictsData, Mode=OneWay}" />
|
|
<controls:CheckUpdateControl />
|
|
</StackPanel>
|
|
</Grid>
|
|
<ScrollViewer x:Name="MainScrollViewer" Grid.Row="2">
|
|
<Grid>
|
|
<!-- This grid is required to ensure that the content is horizontally aligned -->
|
|
<Grid
|
|
MaxWidth="{StaticResource PageMaxWidth}"
|
|
Padding="0,0,20,48"
|
|
ColumnSpacing="16"
|
|
RowSpacing="16">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
<RowDefinition Height="Auto" />
|
|
</Grid.RowDefinitions>
|
|
<controls:Card x:Uid="QuickAccessTitle" VerticalAlignment="Top">
|
|
<Grid>
|
|
<ItemsControl
|
|
x:Name="QuickAccessItemsControl"
|
|
Margin="8,0,12,12"
|
|
ItemsSource="{x:Bind ViewModel.ActionModules, Mode=OneWay}"
|
|
Visibility="{x:Bind ViewModel.ActionModules.Count, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}">
|
|
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<tkcontrols:WrapPanel
|
|
Padding="12"
|
|
HorizontalSpacing="16"
|
|
VerticalSpacing="24" />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate x:DataType="viewmodels:DashboardListItem">
|
|
<ItemsControl IsTabStop="False" ItemsSource="{x:Bind DashboardModuleItems, Mode=OneWay}">
|
|
<ItemsControl.ItemTemplate>
|
|
<DataTemplate x:DataType="viewmodels:DashboardModuleButtonItem">
|
|
<controls:FlyoutMenuButton AutomationProperties.Name="{x:Bind ButtonTitle}" Click="{x:Bind ButtonClickHandler}">
|
|
<controls:FlyoutMenuButton.Content>
|
|
<TextBlock
|
|
Style="{StaticResource CaptionTextBlockStyle}"
|
|
Text="{x:Bind ButtonTitle}"
|
|
TextAlignment="Center"
|
|
TextWrapping="Wrap" />
|
|
</controls:FlyoutMenuButton.Content>
|
|
<controls:FlyoutMenuButton.Icon>
|
|
<Image Width="24">
|
|
<Image.Source>
|
|
<BitmapImage UriSource="{x:Bind ButtonGlyph}" />
|
|
</Image.Source>
|
|
</Image>
|
|
</controls:FlyoutMenuButton.Icon>
|
|
<ToolTipService.ToolTip>
|
|
<ToolTip Content="{x:Bind ButtonDescription}" />
|
|
</ToolTipService.ToolTip>
|
|
</controls:FlyoutMenuButton>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<StackPanel Spacing="0" />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
</ItemsControl>
|
|
</DataTemplate>
|
|
</ItemsControl.ItemTemplate>
|
|
</ItemsControl>
|
|
|
|
<TextBlock
|
|
x:Uid="NoActionsToShow"
|
|
Margin="12"
|
|
HorizontalAlignment="Left"
|
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
Visibility="{x:Bind ViewModel.ActionModules.Count, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" />
|
|
</Grid>
|
|
</controls:Card>
|
|
<controls:Card
|
|
x:Uid="ShortcutsOverview"
|
|
Grid.Row="1"
|
|
VerticalAlignment="Top">
|
|
<Grid>
|
|
<ItemsRepeater
|
|
Grid.Row="2"
|
|
Margin="8,0,0,0"
|
|
ItemsSource="{x:Bind ViewModel.ShortcutModules, Mode=OneWay}">
|
|
<ItemsRepeater.Layout>
|
|
<StackLayout Orientation="Vertical" Spacing="0" />
|
|
</ItemsRepeater.Layout>
|
|
<ItemsRepeater.ItemTemplate>
|
|
<DataTemplate x:DataType="viewmodels:DashboardListItem">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="32" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<Image
|
|
Width="16"
|
|
Margin="0,10,0,0"
|
|
HorizontalAlignment="Left"
|
|
VerticalAlignment="Top"
|
|
AutomationProperties.AccessibilityView="Raw"
|
|
Source="{x:Bind Icon, Mode=OneWay}"
|
|
ToolTipService.ToolTip="{x:Bind Label}" />
|
|
<ItemsControl
|
|
Grid.Column="1"
|
|
IsTabStop="False"
|
|
ItemTemplateSelector="{StaticResource ModuleItemTemplateSelector}"
|
|
ItemsSource="{x:Bind DashboardModuleItems, Mode=OneWay}">
|
|
<ItemsControl.ItemsPanel>
|
|
<ItemsPanelTemplate>
|
|
<StackPanel Spacing="0" />
|
|
</ItemsPanelTemplate>
|
|
</ItemsControl.ItemsPanel>
|
|
</ItemsControl>
|
|
</Grid>
|
|
</DataTemplate>
|
|
</ItemsRepeater.ItemTemplate>
|
|
</ItemsRepeater>
|
|
<TextBlock
|
|
x:Uid="NoShortcutsToShow"
|
|
Margin="12"
|
|
HorizontalAlignment="Left"
|
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
Visibility="{x:Bind ViewModel.ShortcutModules.Count, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" />
|
|
</Grid>
|
|
</controls:Card>
|
|
<controls:Card
|
|
x:Name="ModulesCard"
|
|
Title="Modules"
|
|
Grid.RowSpan="2"
|
|
Grid.Column="1"
|
|
MinWidth="400"
|
|
Padding="0"
|
|
VerticalAlignment="Top"
|
|
DividerVisibility="Collapsed">
|
|
<ItemsRepeater
|
|
x:Name="DashboardView"
|
|
Grid.Row="2"
|
|
ItemsSource="{x:Bind ViewModel.AllModules, Mode=OneWay}">
|
|
<ItemsRepeater.Layout>
|
|
<StackLayout Orientation="Vertical" Spacing="0" />
|
|
</ItemsRepeater.Layout>
|
|
<ItemsRepeater.ItemTemplate>
|
|
<DataTemplate x:DataType="viewmodels:DashboardListItem">
|
|
<tkcontrols:SettingsCard
|
|
MinHeight="0"
|
|
Padding="12,4,12,4"
|
|
AutomationProperties.Name="{x:Bind Label}"
|
|
Background="Transparent"
|
|
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
|
BorderThickness="0,1,0,0"
|
|
Click="DashboardListItemClick"
|
|
CornerRadius="0"
|
|
IsClickEnabled="True"
|
|
Tag="{x:Bind Tag}">
|
|
<tkcontrols:SettingsCard.Resources>
|
|
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
|
<x:Double x:Key="SettingsCardHeaderIconMaxSize">16</x:Double>
|
|
</tkcontrols:SettingsCard.Resources>
|
|
<tkcontrols:SettingsCard.Header>
|
|
<StackPanel Orientation="Horizontal">
|
|
<TextBlock Text="{x:Bind Label}" />
|
|
<InfoBadge
|
|
Margin="4,0,0,0"
|
|
Style="{StaticResource NewInfoBadge}"
|
|
Visibility="{x:Bind IsNew, Converter={StaticResource BoolToVisibilityConverter}}" />
|
|
<FontIcon
|
|
Grid.Column="2"
|
|
Width="20"
|
|
Margin="0,0,-12,0"
|
|
FontSize="16"
|
|
Glyph=""
|
|
Visibility="{x:Bind IsLocked, Converter={StaticResource ReverseBoolToVisibilityConverter}, ConverterParameter=True}">
|
|
<ToolTipService.ToolTip>
|
|
<TextBlock x:Uid="GPO_SettingIsManaged_ToolTip" TextWrapping="WrapWholeWords" />
|
|
</ToolTipService.ToolTip>
|
|
</FontIcon>
|
|
</StackPanel>
|
|
</tkcontrols:SettingsCard.Header>
|
|
<tkcontrols:SettingsCard.HeaderIcon>
|
|
<ImageIcon>
|
|
<ImageIcon.Source>
|
|
<BitmapImage UriSource="{x:Bind Icon}" />
|
|
</ImageIcon.Source>
|
|
</ImageIcon>
|
|
</tkcontrols:SettingsCard.HeaderIcon>
|
|
<ToggleSwitch
|
|
AutomationProperties.Name="{x:Bind Label}"
|
|
IsEnabled="{x:Bind IsLocked, Converter={StaticResource BoolNegationConverter}, ConverterParameter=True, Mode=OneWay}"
|
|
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
|
|
OffContent=""
|
|
OnContent="" />
|
|
</tkcontrols:SettingsCard>
|
|
</DataTemplate>
|
|
</ItemsRepeater.ItemTemplate>
|
|
</ItemsRepeater>
|
|
</controls:Card>
|
|
</Grid>
|
|
</Grid>
|
|
</ScrollViewer>
|
|
<VisualStateManager.VisualStateGroups>
|
|
<VisualStateGroup>
|
|
<VisualState>
|
|
<VisualState.StateTriggers>
|
|
<AdaptiveTrigger MinWindowWidth="840" />
|
|
</VisualState.StateTriggers>
|
|
</VisualState>
|
|
<VisualState>
|
|
<VisualState.StateTriggers>
|
|
<AdaptiveTrigger MinWindowWidth="0" />
|
|
</VisualState.StateTriggers>
|
|
<VisualState.Setters>
|
|
<Setter Target="TopButtonPanel.(Grid.Row)" Value="1" />
|
|
<Setter Target="TopButtonPanel.Margin" Value="0,16,0,0" />
|
|
<Setter Target="TopButtonPanel.(Grid.Column)" Value="0" />
|
|
<Setter Target="ModulesCard.(Grid.Column)" Value="0" />
|
|
<Setter Target="ModulesCard.(Grid.Row)" Value="2" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
</VisualStateManager.VisualStateGroups>
|
|
</Grid>
|
|
</Page> |