diff --git a/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml b/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml index 073558245c..43234f3812 100644 --- a/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml +++ b/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml @@ -64,45 +64,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + TabNavigation="Local" /> diff --git a/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml.cs b/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml.cs index 5aea293cca..057ce8f355 100644 --- a/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml.cs +++ b/src/settings-ui/QuickAccess.UI/QuickAccessXAML/Flyout/LaunchPage.xaml.cs @@ -44,128 +44,6 @@ public sealed partial class LaunchPage : Page } } - private void ModuleButton_Click(object sender, RoutedEventArgs e) - { - if (sender is not FlyoutMenuButton selectedModuleBtn) - { - return; - } - - if (selectedModuleBtn.Tag is not ModuleType moduleType) - { - return; - } - - bool moduleRun = true; - - switch (moduleType) - { - case ModuleType.ColorPicker: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.EnvironmentVariables: - { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; - bool isElevated = _coordinator?.IsRunnerElevated ?? false; - string eventName = !isElevated && launchAdmin - ? Constants.ShowEnvironmentVariablesAdminSharedEvent() - : Constants.ShowEnvironmentVariablesSharedEvent(); - - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName)) - { - eventHandle.Set(); - } - } - - break; - case ModuleType.FancyZones: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.Hosts: - { - bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; - bool isElevated = _coordinator?.IsRunnerElevated ?? false; - string eventName = !isElevated && launchAdmin - ? Constants.ShowHostsAdminSharedEvent() - : Constants.ShowHostsSharedEvent(); - - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName)) - { - eventHandle.Set(); - } - } - - break; - case ModuleType.PowerLauncher: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerLauncherSharedEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.PowerOCR: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.RegistryPreview: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RegistryPreviewTriggerEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.MeasureTool: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.MeasureToolTriggerEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.ShortcutGuide: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShortcutGuideTriggerEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.CmdPal: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowCmdPalEvent())) - { - eventHandle.Set(); - } - - break; - case ModuleType.Workspaces: - using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.WorkspacesLaunchEditorEvent())) - { - eventHandle.Set(); - } - - break; - default: - moduleRun = false; - break; - } - - if (moduleRun) - { - _coordinator?.OnModuleLaunched(moduleType); - } - - _coordinator?.HideFlyout(); - } - private void SettingsBtn_Click(object sender, RoutedEventArgs e) { _coordinator?.OpenSettings(); diff --git a/src/settings-ui/QuickAccess.UI/ViewModels/LauncherViewModel.cs b/src/settings-ui/QuickAccess.UI/ViewModels/LauncherViewModel.cs index 36a96a5de8..1938cec873 100644 --- a/src/settings-ui/QuickAccess.UI/ViewModels/LauncherViewModel.cs +++ b/src/settings-ui/QuickAccess.UI/ViewModels/LauncherViewModel.cs @@ -4,15 +4,19 @@ using System; using System.Collections.ObjectModel; +using System.Threading; using global::PowerToys.GPOWrapper; using ManagedCommon; using Microsoft.PowerToys.QuickAccess.Helpers; using Microsoft.PowerToys.QuickAccess.Services; +using Microsoft.PowerToys.Settings.UI.Controls; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Helpers; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; +using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands; using Microsoft.UI.Dispatching; using Microsoft.Windows.ApplicationModel.Resources; +using PowerToys.Interop; namespace Microsoft.PowerToys.QuickAccess.ViewModels; @@ -24,7 +28,7 @@ public sealed class LauncherViewModel : Observable private readonly DispatcherQueue _dispatcherQueue; private GeneralSettings _generalSettings; - public ObservableCollection FlyoutMenuItems { get; } + public ObservableCollection FlyoutMenuItems { get; } public bool IsUpdateAvailable { get; private set; } @@ -39,7 +43,7 @@ public sealed class LauncherViewModel : Observable _settingsRepository.SettingsChanged += OnSettingsChanged; _resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; - FlyoutMenuItems = new ObservableCollection(); + FlyoutMenuItems = new ObservableCollection(); AddFlyoutMenuItem(ModuleType.ColorPicker); AddFlyoutMenuItem(ModuleType.CmdPal); @@ -72,16 +76,129 @@ public sealed class LauncherViewModel : Observable return; } - FlyoutMenuItems.Add(new FlyoutMenuItem + FlyoutMenuItems.Add(new QuickAccessItem { - Label = _resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)), + Title = _resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)), Tag = moduleType, Visible = ModuleHelper.GetIsModuleEnabled(_generalSettings, moduleType), - ToolTip = GetModuleToolTip(moduleType), + Description = GetModuleToolTip(moduleType), Icon = ModuleHelper.GetModuleTypeFluentIconName(moduleType), + Command = new RelayCommand(() => LaunchModule(moduleType)), }); } + private void LaunchModule(ModuleType moduleType) + { + bool moduleRun = true; + + switch (moduleType) + { + case ModuleType.ColorPicker: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.EnvironmentVariables: + { + bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool isElevated = _coordinator?.IsRunnerElevated ?? false; + string eventName = !isElevated && launchAdmin + ? Constants.ShowEnvironmentVariablesAdminSharedEvent() + : Constants.ShowEnvironmentVariablesSharedEvent(); + + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName)) + { + eventHandle.Set(); + } + } + + break; + case ModuleType.FancyZones: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.Hosts: + { + bool launchAdmin = SettingsRepository.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator; + bool isElevated = _coordinator?.IsRunnerElevated ?? false; + string eventName = !isElevated && launchAdmin + ? Constants.ShowHostsAdminSharedEvent() + : Constants.ShowHostsSharedEvent(); + + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName)) + { + eventHandle.Set(); + } + } + + break; + case ModuleType.PowerLauncher: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerLauncherSharedEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.PowerOCR: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.RegistryPreview: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RegistryPreviewTriggerEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.MeasureTool: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.MeasureToolTriggerEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.ShortcutGuide: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShortcutGuideTriggerEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.CmdPal: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowCmdPalEvent())) + { + eventHandle.Set(); + } + + break; + case ModuleType.Workspaces: + using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.WorkspacesLaunchEditorEvent())) + { + eventHandle.Set(); + } + + break; + default: + moduleRun = false; + break; + } + + if (moduleRun) + { + _coordinator?.OnModuleLaunched(moduleType); + } + + _coordinator?.HideFlyout(); + } + private string GetModuleToolTip(ModuleType moduleType) { return moduleType switch @@ -111,7 +228,10 @@ public sealed class LauncherViewModel : Observable _generalSettings.AddEnabledModuleChangeNotification(ModuleEnabledChanged); foreach (var item in FlyoutMenuItems) { - item.Visible = ModuleHelper.GetIsModuleEnabled(_generalSettings, item.Tag); + if (item.Tag is ModuleType moduleType) + { + item.Visible = ModuleHelper.GetIsModuleEnabled(_generalSettings, moduleType); + } } } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml b/src/settings-ui/Settings.UI.Controls/Card.xaml similarity index 100% rename from src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml rename to src/settings-ui/Settings.UI.Controls/Card.xaml diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml.cs b/src/settings-ui/Settings.UI.Controls/Card.xaml.cs similarity index 100% rename from src/settings-ui/Settings.UI/SettingsXAML/Controls/Dashboard/Card.xaml.cs rename to src/settings-ui/Settings.UI.Controls/Card.xaml.cs diff --git a/src/settings-ui/Settings.UI.Controls/Converters/ModuleListSortOptionToBooleanConverter.cs b/src/settings-ui/Settings.UI.Controls/Converters/ModuleListSortOptionToBooleanConverter.cs new file mode 100644 index 0000000000..2c015f0b92 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/Converters/ModuleListSortOptionToBooleanConverter.cs @@ -0,0 +1,38 @@ +// 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 Microsoft.UI.Xaml.Data; + +namespace Microsoft.PowerToys.Settings.UI.Controls.Converters +{ + public partial class ModuleListSortOptionToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is ModuleListSortOption sortOption && parameter is string paramString) + { + if (Enum.TryParse(typeof(ModuleListSortOption), paramString, out object? result) && result != null) + { + return sortOption == (ModuleListSortOption)result; + } + } + + return false; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + if (value is bool isChecked && isChecked && parameter is string paramString) + { + if (Enum.TryParse(typeof(ModuleListSortOption), paramString, out object? result) && result != null) + { + return (ModuleListSortOption)result; + } + } + + return ModuleListSortOption.Alphabetical; + } + } +} diff --git a/src/settings-ui/Settings.UI.Controls/ModuleList.xaml b/src/settings-ui/Settings.UI.Controls/ModuleList.xaml new file mode 100644 index 0000000000..e41625e774 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/ModuleList.xaml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/settings-ui/Settings.UI.Controls/ModuleList.xaml.cs b/src/settings-ui/Settings.UI.Controls/ModuleList.xaml.cs new file mode 100644 index 0000000000..9eb28d8b6e --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/ModuleList.xaml.cs @@ -0,0 +1,59 @@ +// 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.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public sealed partial class ModuleList : UserControl + { + public ModuleList() + { + this.InitializeComponent(); + } + + public object ItemsSource + { + get => (object)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + + public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(ModuleList), new PropertyMetadata(null)); + + public ModuleListSortOption SortOption + { + get => (ModuleListSortOption)GetValue(SortOptionProperty); + set => SetValue(SortOptionProperty, value); + } + + public static readonly DependencyProperty SortOptionProperty = DependencyProperty.Register(nameof(SortOption), typeof(ModuleListSortOption), typeof(ModuleList), new PropertyMetadata(ModuleListSortOption.Alphabetical)); + + public string Title + { + get => (string)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(ModuleList), new PropertyMetadata(default(string))); + + private void SortAlphabetical_Click(object sender, RoutedEventArgs e) + { + SortOption = ModuleListSortOption.Alphabetical; + } + + private void SortByStatus_Click(object sender, RoutedEventArgs e) + { + SortOption = ModuleListSortOption.ByStatus; + } + + private void ModuleSettingsCard_Click(object sender, RoutedEventArgs e) + { + if (sender is ModuleSettingsCard card && card.DataContext is ModuleListItem item) + { + item.ClickCommand?.Execute(item.Tag); + } + } + } +} diff --git a/src/settings-ui/Settings.UI.Controls/ModuleListItem.cs b/src/settings-ui/Settings.UI.Controls/ModuleListItem.cs new file mode 100644 index 0000000000..ef92e3e592 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/ModuleListItem.cs @@ -0,0 +1,119 @@ +// 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.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows.Input; + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public class ModuleListItem : INotifyPropertyChanged + { + private bool _isEnabled; + private string _label = string.Empty; + private string _icon = string.Empty; + private bool _isNew; + private bool _isLocked; + private object? _tag; + private ICommand? _clickCommand; + + public virtual string Label + { + get => _label; + set + { + if (_label != value) + { + _label = value; + OnPropertyChanged(); + } + } + } + + public virtual string Icon + { + get => _icon; + set + { + if (_icon != value) + { + _icon = value; + OnPropertyChanged(); + } + } + } + + public virtual bool IsNew + { + get => _isNew; + set + { + if (_isNew != value) + { + _isNew = value; + OnPropertyChanged(); + } + } + } + + public virtual bool IsLocked + { + get => _isLocked; + set + { + if (_isLocked != value) + { + _isLocked = value; + OnPropertyChanged(); + } + } + } + + public virtual bool IsEnabled + { + get => _isEnabled; + set + { + if (_isEnabled != value) + { + _isEnabled = value; + OnPropertyChanged(); + } + } + } + + public virtual object? Tag + { + get => _tag; + set + { + if (_tag != value) + { + _tag = value; + OnPropertyChanged(); + } + } + } + + public virtual ICommand? ClickCommand + { + get => _clickCommand; + set + { + if (_clickCommand != value) + { + _clickCommand = value; + OnPropertyChanged(); + } + } + } + + public event PropertyChangedEventHandler? PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/src/settings-ui/Settings.UI.Controls/ModuleListSortOption.cs b/src/settings-ui/Settings.UI.Controls/ModuleListSortOption.cs new file mode 100644 index 0000000000..233c891d6b --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/ModuleListSortOption.cs @@ -0,0 +1,12 @@ +// 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. + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public enum ModuleListSortOption + { + Alphabetical, + ByStatus, + } +} diff --git a/src/settings-ui/Settings.UI.Controls/QuickAccessItem.cs b/src/settings-ui/Settings.UI.Controls/QuickAccessItem.cs new file mode 100644 index 0000000000..49023da9b7 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/QuickAccessItem.cs @@ -0,0 +1,68 @@ +// 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.Windows.Input; +using Microsoft.UI.Xaml; + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public sealed class QuickAccessItem : DependencyObject + { + public string Title + { + get => (string)GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(QuickAccessItem), new PropertyMetadata(string.Empty)); + + public string Description + { + get => (string)GetValue(DescriptionProperty); + set => SetValue(DescriptionProperty, value); + } + + public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(nameof(Description), typeof(string), typeof(QuickAccessItem), new PropertyMetadata(string.Empty)); + + public string Icon + { + get => (string)GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(string), typeof(QuickAccessItem), new PropertyMetadata(string.Empty)); + + public ICommand Command + { + get => (ICommand)GetValue(CommandProperty); + set => SetValue(CommandProperty, value); + } + + public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(QuickAccessItem), new PropertyMetadata(null)); + + public object CommandParameter + { + get => (object)GetValue(CommandParameterProperty); + set => SetValue(CommandParameterProperty, value); + } + + public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(nameof(CommandParameter), typeof(object), typeof(QuickAccessItem), new PropertyMetadata(null)); + + public bool Visible + { + get => (bool)GetValue(VisibleProperty); + set => SetValue(VisibleProperty, value); + } + + public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register(nameof(Visible), typeof(bool), typeof(QuickAccessItem), new PropertyMetadata(true)); + + public object Tag + { + get => (object)GetValue(TagProperty); + set => SetValue(TagProperty, value); + } + + public static readonly DependencyProperty TagProperty = DependencyProperty.Register(nameof(Tag), typeof(object), typeof(QuickAccessItem), new PropertyMetadata(null)); + } +} diff --git a/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml b/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml new file mode 100644 index 0000000000..21befbfd61 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml.cs b/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml.cs new file mode 100644 index 0000000000..34c4bad013 --- /dev/null +++ b/src/settings-ui/Settings.UI.Controls/QuickAccessList.xaml.cs @@ -0,0 +1,26 @@ +// 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.Collections.Generic; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public sealed partial class QuickAccessList : UserControl + { + public QuickAccessList() + { + this.InitializeComponent(); + } + + public object ItemsSource + { + get => (object)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + + public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(QuickAccessList), new PropertyMetadata(null)); + } +} diff --git a/src/settings-ui/Settings.UI/Converters/EnumToModuleListSortOptionConverter.cs b/src/settings-ui/Settings.UI/Converters/EnumToModuleListSortOptionConverter.cs new file mode 100644 index 0000000000..ab6eff7668 --- /dev/null +++ b/src/settings-ui/Settings.UI/Converters/EnumToModuleListSortOptionConverter.cs @@ -0,0 +1,44 @@ +// 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 Microsoft.PowerToys.Settings.UI.Controls; +using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.UI.Xaml.Data; + +namespace Microsoft.PowerToys.Settings.UI.Converters +{ + public partial class EnumToModuleListSortOptionConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is DashboardSortOrder sortOrder) + { + return sortOrder switch + { + DashboardSortOrder.Alphabetical => ModuleListSortOption.Alphabetical, + DashboardSortOrder.ByStatus => ModuleListSortOption.ByStatus, + _ => ModuleListSortOption.Alphabetical, + }; + } + + return ModuleListSortOption.Alphabetical; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + if (value is ModuleListSortOption sortOption) + { + return sortOption switch + { + ModuleListSortOption.Alphabetical => DashboardSortOrder.Alphabetical, + ModuleListSortOption.ByStatus => DashboardSortOrder.ByStatus, + _ => DashboardSortOrder.Alphabetical, + }; + } + + return DashboardSortOrder.Alphabetical; + } + } +} diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml index f47b823973..a5b644d420 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml @@ -21,6 +21,7 @@ ActivationTemplate="{StaticResource ModuleItemActivationTemplate}" ShortcutTemplate="{StaticResource ModuleItemShortcutTemplate}" /> + @@ -159,64 +160,18 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ItemsSource="{x:Bind ViewModel.QuickAccessItems, Mode=OneWay}" + Visibility="{x:Bind ViewModel.QuickAccessItems.Count, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}" /> + Visibility="{x:Bind ViewModel.QuickAccessItems.Count, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" /> - - - - - - - - - - - - - - - - + ItemsSource="{x:Bind ViewModel.AllModules, Mode=OneWay}" + SortOption="{x:Bind ViewModel.DashboardSortOrder, Mode=TwoWay, Converter={StaticResource EnumToModuleListSortOptionConverter}}" /> diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs index 0d7273f924..48ca759ce5 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/DashboardPage.xaml.cs @@ -48,11 +48,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views ViewModel.ModuleEnabledChangedOnSettingsPage(); } - private void DashboardListItemClick(object sender, RoutedEventArgs e) - { - ViewModel.DashboardListItemClick(sender); - } - private void WhatsNewButton_Click(object sender, RoutedEventArgs e) { if (App.GetOobeWindow() == null) @@ -66,15 +61,5 @@ namespace Microsoft.PowerToys.Settings.UI.Views App.GetOobeWindow().Activate(); } - - private void SortAlphabetical_Click(object sender, RoutedEventArgs e) - { - ViewModel.DashboardSortOrder = DashboardSortOrder.Alphabetical; - } - - private void SortByStatus_Click(object sender, RoutedEventArgs e) - { - ViewModel.DashboardSortOrder = DashboardSortOrder.ByStatus; - } } } diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs index fa6fbba97a..c292ec5011 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardListItem.cs @@ -8,44 +8,39 @@ using System.ComponentModel; using System.Runtime.CompilerServices; using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Controls; using Microsoft.UI; using Windows.UI; namespace Microsoft.PowerToys.Settings.UI.ViewModels { - public partial class DashboardListItem : INotifyPropertyChanged + public partial class DashboardListItem : ModuleListItem { private bool _visible; - private bool _isEnabled; - - public string Label { get; set; } - - public bool IsNew { get; set; } - - public string Icon { get; set; } public string ToolTip { get; set; } - public ModuleType Tag { get; set; } - - public bool IsLocked { get; set; } - - public bool IsEnabled + public new ModuleType Tag { - get => _isEnabled; + get => (ModuleType)base.Tag!; + set => base.Tag = value; + } + + public Action EnabledChangedCallback { get; set; } + + public override bool IsEnabled + { + get => base.IsEnabled; set { - if (_isEnabled != value) + if (base.IsEnabled != value) { - _isEnabled = value; - OnPropertyChanged(); + base.IsEnabled = value; EnabledChangedCallback?.Invoke(this); } } } - public Action EnabledChangedCallback { get; set; } - public bool Visible { get => _visible; @@ -59,13 +54,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } - public event PropertyChangedEventHandler PropertyChanged; - - private void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - public ObservableCollection DashboardModuleItems { get; set; } = new ObservableCollection(); } } diff --git a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs index 53e3afa525..e84b0273be 100644 --- a/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/DashboardViewModel.cs @@ -12,6 +12,7 @@ using System.Windows.Threading; using CommunityToolkit.WinUI.Controls; using global::PowerToys.GPOWrapper; using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Controls; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Helpers; @@ -40,6 +41,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels public ObservableCollection ActionModules { get; set; } = new ObservableCollection(); + public ObservableCollection QuickAccessItems { get; set; } = new ObservableCollection(); + private AllHotkeyConflictsData _allHotkeyConflictsData = new AllHotkeyConflictsData(); public AllHotkeyConflictsData AllHotkeyConflictsData @@ -158,6 +161,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels Icon = ModuleHelper.GetModuleTypeFluentIconName(moduleType), IsNew = moduleType == ModuleType.CursorWrap, DashboardModuleItems = GetModuleItems(moduleType), + ClickCommand = new RelayCommand(DashboardListItemClick), }; newItem.EnabledChangedCallback = EnabledChangedOnUI; moduleItems.Add(newItem); @@ -213,6 +217,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels { ShortcutModules.Clear(); ActionModules.Clear(); + QuickAccessItems.Clear(); foreach (var x in AllModules.Where(x => x.IsEnabled)) { @@ -257,6 +262,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels ActionModules.Add(newItem); newItem.EnabledChangedCallback = x.EnabledChangedCallback; + + foreach (DashboardModuleButtonItem item in filteredItems) + { + QuickAccessItems.Add(new QuickAccessItem + { + Title = item.ButtonTitle, + Description = item.ButtonDescription, + Icon = item.ButtonGlyph, + Command = new RelayCommand(() => item.ButtonClickHandler?.Invoke(null, null)), + Tag = x.Tag, + }); + } } } } @@ -596,7 +613,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels internal void DashboardListItemClick(object sender) { - if (sender is FrameworkElement element && element.Tag is ModuleType moduleType) + if (sender is ModuleType moduleType) { NavigationService.Navigate(ModuleHelper.GetModulePageType(moduleType)); }