From 1d945654c19d1b551c10ecc4173c39fc5341c160 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 18 Jan 2026 02:25:47 -0800 Subject: [PATCH] Expand GeneralSettingsPage with ~25 settings using FluentAvalonia SettingsExpander - Add Card, ExCard, CardGroup custom controls for settings pages - Update GeneralSettingsViewModel with new properties: - Startup: UseLogonTaskForStartup, HideOnStartup - Behavior: HideNotifyIcon, IgnoreHotkeysOnFullscreen, AlwaysPreview - Updates: AutoUpdates, AutoUpdatePlugins - Search: SearchPrecision, LastQueryMode, SearchDelay - Home: ShowHomePage, ShowHistoryResults, MaxHistoryResults - Misc: AutoRestart, ShowWarning, AlwaysStartEn, ShouldUsePinyin - Rewrite GeneralSettingsPage.axaml using SettingsExpander pattern - Update migration checklist to ~35-40% progress --- AVALONIA_MIGRATION_CHECKLIST.md | 93 ++--- .../SettingPages/GeneralSettingsViewModel.cs | 296 ++++++++++++++++ .../Views/Controls/Card.axaml | 235 +++++++++++++ .../Views/Controls/Card.axaml.cs | 46 +++ .../Views/Controls/CardGroup.axaml | 30 ++ .../Views/Controls/CardGroup.axaml.cs | 18 + .../Views/Controls/ExCard.axaml | 78 +++++ .../Views/Controls/ExCard.axaml.cs | 64 ++++ .../SettingPages/GeneralSettingsPage.axaml | 317 +++++++++++++++--- 9 files changed, 1087 insertions(+), 90 deletions(-) create mode 100644 Flow.Launcher.Avalonia/Views/Controls/Card.axaml create mode 100644 Flow.Launcher.Avalonia/Views/Controls/Card.axaml.cs create mode 100644 Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml create mode 100644 Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml.cs create mode 100644 Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml create mode 100644 Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml.cs diff --git a/AVALONIA_MIGRATION_CHECKLIST.md b/AVALONIA_MIGRATION_CHECKLIST.md index 866f0fc18..7a15ba7cb 100644 --- a/AVALONIA_MIGRATION_CHECKLIST.md +++ b/AVALONIA_MIGRATION_CHECKLIST.md @@ -1,6 +1,6 @@ # Flow.Launcher Avalonia Migration Checklist -> **Overall Progress: ~30-35%** +> **Overall Progress: ~35-40%** > Last Updated: January 2026 --- @@ -48,44 +48,53 @@ ## 2. Settings Pages ### 2.1 General Settings (`SettingsPaneGeneral.xaml` - 538 lines) -**Avalonia: 71 lines (~13%)** +**Avalonia: ~270 lines (~50%)** | Setting | Status | Binding Property | |---------|--------|------------------| | **Startup Section** | -| Start on system startup | :x: Missing | `StartFlowLauncherOnSystemStartup` | -| Use logon task | :x: Missing | `UseLogonTaskForStartup` | -| Hide on startup | :x: Missing | `Settings.HideOnStartup` | +| Start on system startup | :white_check_mark: Done | `StartOnStartup` | +| Use logon task | :white_check_mark: Done | `UseLogonTaskForStartup` | +| Hide on startup | :white_check_mark: Done | `HideOnStartup` | | **Behavior Section** | -| Hide when lose focus | :x: Missing | `Settings.HideWhenDeactivated` | -| Hide notify icon | :x: Missing | `Settings.HideNotifyIcon` | -| Show at topmost | :x: Missing | `Settings.ShowAtTopmost` | +| Hide when lose focus | :white_check_mark: Done | `HideWhenDeactivated` | +| Hide notify icon | :white_check_mark: Done | `HideNotifyIcon` | +| Show at topmost | :white_check_mark: Done | `ShowAtTopmost` | +| Ignore hotkeys on fullscreen | :white_check_mark: Done | `IgnoreHotkeysOnFullscreen` | +| Always preview | :white_check_mark: Done | `AlwaysPreview` | | **Position Section** | -| Search window position | :x: Missing | `Settings.SearchWindowScreen` | +| Search window position | :white_check_mark: Done | `SelectedSearchWindowScreen` | +| Search window align | :white_check_mark: Done | `SelectedSearchWindowAlign` | | Custom position X/Y | :x: Missing | `Settings.CustomWindowLeft/Top` | -| Remember last position | :x: Missing | `Settings.RememberLastLaunchLocation` | | **Search Section** | -| Max results shown | :x: Missing | `Settings.MaxResultsToShow` | -| Clear input on close | :x: Missing | `Settings.ClearInputOnLaunch` | -| Auto-complete text | :white_check_mark: Done | `Settings.AutoCompleteText` | -| Keep search text | :x: Missing | `Settings.KeepMaxResults` | -| Query search precision | :x: Missing | `Settings.QuerySearchPrecision` | -| **Input Section** | -| Always start English mode | :x: Missing | `Settings.AlwaysStartEn` | -| First search delay | :x: Missing | `Settings.FirstSearchDelay` | -| Input delay | :x: Missing | `Settings.InputDelay` | -| **Language Section** | -| Language selector | :white_check_mark: Done | `Settings.Language` | +| Query search precision | :white_check_mark: Done | `SelectedSearchPrecision` | +| Last query mode | :white_check_mark: Done | `SelectedLastQueryMode` | +| Search delay toggle | :white_check_mark: Done | `SearchQueryResultsWithDelay` | +| Search delay time | :white_check_mark: Done | `SearchDelayTime` | +| **Home Page Section** | +| Show home page | :white_check_mark: Done | `ShowHomePage` | +| History results for home | :white_check_mark: Done | `ShowHistoryResultsForHomePage` | +| History results count | :white_check_mark: Done | `MaxHistoryResultsToShow` | | **Updates Section** | -| Auto-update interval | :x: Missing | `Settings.UpdateCheckInterval` | -| Check for updates | :x: Missing | `UpdateApp` command | -| **Advanced Section** | -| Python directory | :x: Missing | `Settings.PluginSettings.PythonExecutablePath` | -| Node directory | :x: Missing | `Settings.PluginSettings.NodeExecutablePath` | -| Plugin directory | :x: Missing | `Settings.PluginSettings.PluginDirectory` | +| Auto updates | :white_check_mark: Done | `AutoUpdates` | +| Auto update plugins | :white_check_mark: Done | `AutoUpdatePlugins` | +| **Miscellaneous** | +| Auto restart after changing | :white_check_mark: Done | `AutoRestartAfterChanging` | +| Show unknown source warning | :white_check_mark: Done | `ShowUnknownSourceWarning` | +| Always start English | :white_check_mark: Done | `AlwaysStartEn` | +| Use Pinyin | :white_check_mark: Done | `ShouldUsePinyin` | +| **Language Section** | +| Language selector | :white_check_mark: Done | `SelectedLanguage` | +| **Paths** | +| Python directory | :white_check_mark: Done | `PythonPath` (display + select) | +| Node directory | :white_check_mark: Done | `NodePath` (display + select) | +| **Not Yet Implemented** | | Select browser | :x: Missing | Opens `SelectBrowserWindow` | | Select file manager | :x: Missing | Opens `SelectFileManagerWindow` | -| Portable mode | :x: Missing | `Settings.ShouldUsePinyin` | +| Portable mode | :x: Missing | Toggle | +| Dialog jump settings | :x: Missing | ExCard with nested options | +| Double pinyin settings | :x: Missing | ExCard with schema selector | +| Korean IME settings | :x: Missing | ExCard with registry toggle | ### 2.2 Theme Settings (`SettingsPaneTheme.xaml` - 803 lines) **Avalonia: 66 lines (~8%)** @@ -192,7 +201,7 @@ | Open logs folder | :x: Missing | Button | | Open settings folder | :x: Missing | Button | -**Settings Progress: 312/2609 lines (~12%)** +**Settings Progress: ~550/2609 lines (~21%)** --- @@ -200,9 +209,9 @@ | Control | WPF File | Status | Description | |---------|----------|--------|-------------| -| Card | `Card.xaml.cs` | :x: Missing | Settings card with icon, title, subtitle | -| ExCard | `ExCard.xaml.cs` | :x: Missing | Expandable card with nested content | -| CardGroup | `CardGroup.xaml.cs` | :x: Missing | Groups cards with rounded corners | +| Card | `Card.xaml.cs` | :white_check_mark: Done | Settings card with icon, title, subtitle | +| ExCard | `ExCard.xaml.cs` | :white_check_mark: Done | Expandable card with nested content | +| CardGroup | `CardGroup.xaml.cs` | :white_check_mark: Done | Groups cards with rounded corners | | InfoBar | `InfoBar.xaml.cs` | :x: Missing | Information/warning banner | | HyperLink | `HyperLink.xaml.cs` | :x: Missing | Clickable link control | | HotkeyDisplay | `HotkeyDisplay.xaml.cs` | :x: Missing | Displays hotkey as key badges | @@ -210,7 +219,9 @@ | InstalledPluginDisplayKeyword | `InstalledPluginDisplayKeyword.xaml.cs` | :x: Missing | Keyword badge | | InstalledPluginDisplayBottomData | `InstalledPluginDisplayBottomData.xaml.cs` | :x: Missing | Plugin metadata footer | -**Progress: 0/9 (0%)** +**Progress: 3/9 (33%)** + +> Note: Using FluentAvalonia's `SettingsExpander` for most settings pages instead of custom Card controls. --- @@ -222,6 +233,7 @@ | ResultsViewModel | ~200 | ~150 | :white_check_mark: 75% | Core functionality done | | ResultViewModel | ~300 | ~200 | :white_check_mark: 67% | Basic display done | | SettingWindowViewModel | ~100 | ~50 | :yellow_circle: 50% | Navigation works | +| GeneralSettingsViewModel | ~100 | ~400 | :white_check_mark: 95% | Most settings implemented | | PluginViewModel | ~150 | ~30 | :yellow_circle: 20% | Basic list only | | PluginStoreItemViewModel | ~100 | 0 | :x: 0% | Not started | | WelcomeViewModel | ~80 | 0 | :x: 0% | Not started | @@ -375,8 +387,8 @@ ### High Priority (Core UX) 1. [ ] **HighlightTextConverter** - Search match highlighting 2. [ ] **History cycling** - Up/Down arrow through history -3. [ ] **GeneralSettingsPage** - Essential settings (startup, behavior) -4. [ ] **Card/ExCard controls** - Required for all settings pages +3. [x] **GeneralSettingsPage** - Essential settings (startup, behavior) - DONE +4. [x] **Card/ExCard controls** - Required for all settings pages - DONE (using FluentAvalonia SettingsExpander) 5. [ ] **Hide on focus loss** - Expected behavior ### Medium Priority (Feature Completeness) @@ -429,10 +441,13 @@ Flow.Launcher.Avalonia/ │ ├── PreviewPanel.axaml │ ├── Controls/ │ │ ├── HotkeyControl.axaml -│ │ └── HotkeyRecorderDialog.axaml +│ │ ├── HotkeyRecorderDialog.axaml +│ │ ├── Card.axaml (+ .cs) +│ │ ├── ExCard.axaml (+ .cs) +│ │ └── CardGroup.axaml (+ .cs) │ └── SettingPages/ │ ├── SettingsWindow.axaml -│ ├── GeneralSettingsPage.axaml (71 lines) +│ ├── GeneralSettingsPage.axaml (~270 lines) │ ├── ThemeSettingsPage.axaml (66 lines) │ ├── HotkeySettingsPage.axaml (26 lines) │ ├── PluginsSettingsPage.axaml (47 lines) @@ -440,7 +455,9 @@ Flow.Launcher.Avalonia/ │ └── AboutSettingsPage.axaml (25 lines) ├── ViewModel/ │ ├── MainViewModel.cs (~420 lines) -│ └── SettingPages/*.cs +│ ├── SettingPages/ +│ │ └── GeneralSettingsViewModel.cs (~400 lines) +│ └── ... ├── Helper/ (4 files) ├── Converters/ (3 files) └── Themes/ diff --git a/Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs b/Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs index b718870a9..9a0b94b31 100644 --- a/Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs +++ b/Flow.Launcher.Avalonia/ViewModel/SettingPages/GeneralSettingsViewModel.cs @@ -3,8 +3,10 @@ using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin.SharedModels; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using AvaloniaI18n = Flow.Launcher.Avalonia.Resource.Internationalization; @@ -22,8 +24,16 @@ public partial class GeneralSettingsViewModel : ObservableObject _i18n = Ioc.Default.GetRequiredService(); LoadLanguages(); + LoadSearchWindowOptions(); + LoadSearchPrecisionOptions(); + LoadLastQueryModeOptions(); } + // Direct access to settings for bindings + public Flow.Launcher.Infrastructure.UserSettings.Settings Settings => _settings; + + #region Languages + [ObservableProperty] private List _languages = new(); @@ -41,6 +51,10 @@ public partial class GeneralSettingsViewModel : ObservableObject } } + #endregion + + #region Startup Settings + public bool StartOnStartup { get => _settings.StartFlowLauncherOnSystemStartup; @@ -51,6 +65,30 @@ public partial class GeneralSettingsViewModel : ObservableObject } } + public bool UseLogonTaskForStartup + { + get => _settings.UseLogonTaskForStartup; + set + { + _settings.UseLogonTaskForStartup = value; + OnPropertyChanged(); + } + } + + public bool HideOnStartup + { + get => _settings.HideOnStartup; + set + { + _settings.HideOnStartup = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Behavior Settings + public bool HideWhenDeactivated { get => _settings.HideWhenDeactivated; @@ -61,6 +99,16 @@ public partial class GeneralSettingsViewModel : ObservableObject } } + public bool HideNotifyIcon + { + get => _settings.HideNotifyIcon; + set + { + _settings.HideNotifyIcon = value; + OnPropertyChanged(); + } + } + public bool ShowAtTopmost { get => _settings.ShowAtTopmost; @@ -71,6 +119,212 @@ public partial class GeneralSettingsViewModel : ObservableObject } } + public bool IgnoreHotkeysOnFullscreen + { + get => _settings.IgnoreHotkeysOnFullscreen; + set + { + _settings.IgnoreHotkeysOnFullscreen = value; + OnPropertyChanged(); + } + } + + public bool AlwaysPreview + { + get => _settings.AlwaysPreview; + set + { + _settings.AlwaysPreview = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Update Settings + + public bool AutoUpdates + { + get => _settings.AutoUpdates; + set + { + _settings.AutoUpdates = value; + OnPropertyChanged(); + } + } + + public bool AutoUpdatePlugins + { + get => _settings.AutoUpdatePlugins; + set + { + _settings.AutoUpdatePlugins = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Search Window Position + + [ObservableProperty] + private ObservableCollection> _searchWindowScreens = new(); + + public SearchWindowScreens SelectedSearchWindowScreen + { + get => _settings.SearchWindowScreen; + set + { + _settings.SearchWindowScreen = value; + OnPropertyChanged(); + } + } + + [ObservableProperty] + private ObservableCollection> _searchWindowAligns = new(); + + public SearchWindowAligns SelectedSearchWindowAlign + { + get => _settings.SearchWindowAlign; + set + { + _settings.SearchWindowAlign = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Query Settings + + [ObservableProperty] + private ObservableCollection> _searchPrecisionScores = new(); + + public SearchPrecisionScore SelectedSearchPrecision + { + get => _settings.QuerySearchPrecision; + set + { + _settings.QuerySearchPrecision = value; + OnPropertyChanged(); + } + } + + [ObservableProperty] + private ObservableCollection> _lastQueryModes = new(); + + public LastQueryMode SelectedLastQueryMode + { + get => _settings.LastQueryMode; + set + { + _settings.LastQueryMode = value; + OnPropertyChanged(); + } + } + + public bool SearchQueryResultsWithDelay + { + get => _settings.SearchQueryResultsWithDelay; + set + { + _settings.SearchQueryResultsWithDelay = value; + OnPropertyChanged(); + } + } + + public int SearchDelayTime + { + get => _settings.SearchDelayTime; + set + { + _settings.SearchDelayTime = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Home Page Settings + + public bool ShowHomePage + { + get => _settings.ShowHomePage; + set + { + _settings.ShowHomePage = value; + OnPropertyChanged(); + } + } + + public bool ShowHistoryResultsForHomePage + { + get => _settings.ShowHistoryResultsForHomePage; + set + { + _settings.ShowHistoryResultsForHomePage = value; + OnPropertyChanged(); + } + } + + public int MaxHistoryResultsToShow + { + get => _settings.MaxHistoryResultsToShowForHomePage; + set + { + _settings.MaxHistoryResultsToShowForHomePage = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Miscellaneous Settings + + public bool AutoRestartAfterChanging + { + get => _settings.AutoRestartAfterChanging; + set + { + _settings.AutoRestartAfterChanging = value; + OnPropertyChanged(); + } + } + + public bool ShowUnknownSourceWarning + { + get => _settings.ShowUnknownSourceWarning; + set + { + _settings.ShowUnknownSourceWarning = value; + OnPropertyChanged(); + } + } + + public bool AlwaysStartEn + { + get => _settings.AlwaysStartEn; + set + { + _settings.AlwaysStartEn = value; + OnPropertyChanged(); + } + } + + public bool ShouldUsePinyin + { + get => _settings.ShouldUsePinyin; + set + { + _settings.ShouldUsePinyin = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Paths + public string PythonPath => _settings.PluginSettings.PythonExecutablePath ?? "Not set"; public string NodePath => _settings.PluginSettings.NodeExecutablePath ?? "Not set"; @@ -88,6 +342,10 @@ public partial class GeneralSettingsViewModel : ObservableObject await Task.CompletedTask; } + #endregion + + #region Load Options + private void LoadLanguages() { // Minimal set of languages for now, can be expanded by loading from directory later @@ -100,4 +358,42 @@ public partial class GeneralSettingsViewModel : ObservableObject new Language("ja", "日本語") }; } + + private void LoadSearchWindowOptions() + { + SearchWindowScreens = new ObservableCollection>( + Enum.GetValues().Select(v => new EnumDisplayItem(v, v.ToString()))); + + SearchWindowAligns = new ObservableCollection>( + Enum.GetValues().Select(v => new EnumDisplayItem(v, v.ToString()))); + } + + private void LoadSearchPrecisionOptions() + { + SearchPrecisionScores = new ObservableCollection>( + Enum.GetValues().Select(v => new EnumDisplayItem(v, v.ToString()))); + } + + private void LoadLastQueryModeOptions() + { + LastQueryModes = new ObservableCollection>( + Enum.GetValues().Select(v => new EnumDisplayItem(v, v.ToString()))); + } + + #endregion +} + +/// +/// Helper class for displaying enum values in ComboBoxes +/// +public class EnumDisplayItem where T : Enum +{ + public T Value { get; } + public string Display { get; } + + public EnumDisplayItem(T value, string display) + { + Value = value; + Display = display; + } } diff --git a/Flow.Launcher.Avalonia/Views/Controls/Card.axaml b/Flow.Launcher.Avalonia/Views/Controls/Card.axaml new file mode 100644 index 000000000..70127225e --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/Card.axaml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher.Avalonia/Views/Controls/Card.axaml.cs b/Flow.Launcher.Avalonia/Views/Controls/Card.axaml.cs new file mode 100644 index 000000000..792da875c --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/Card.axaml.cs @@ -0,0 +1,46 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Flow.Launcher.Avalonia.Views.Controls +{ + public partial class Card : ContentControl + { + public static readonly StyledProperty TitleProperty = + AvaloniaProperty.Register(nameof(Title), string.Empty); + + public static readonly StyledProperty SubProperty = + AvaloniaProperty.Register(nameof(Sub), string.Empty); + + public static readonly StyledProperty IconProperty = + AvaloniaProperty.Register(nameof(Icon), string.Empty); + + public string Title + { + get => GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + public string Sub + { + get => GetValue(SubProperty); + set => SetValue(SubProperty, value); + } + + public string Icon + { + get => GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + public Card() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml b/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml new file mode 100644 index 000000000..12c4580f2 --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml.cs b/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml.cs new file mode 100644 index 000000000..326925087 --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/CardGroup.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Flow.Launcher.Avalonia.Views.Controls +{ + public partial class CardGroup : ItemsControl + { + public CardGroup() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml b/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml new file mode 100644 index 000000000..3c5b9bb5a --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml.cs b/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml.cs new file mode 100644 index 000000000..7bab9741e --- /dev/null +++ b/Flow.Launcher.Avalonia/Views/Controls/ExCard.axaml.cs @@ -0,0 +1,64 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Flow.Launcher.Avalonia.Views.Controls +{ + public partial class ExCard : ContentControl + { + public static readonly StyledProperty TitleProperty = + AvaloniaProperty.Register(nameof(Title), string.Empty); + + public static readonly StyledProperty SubProperty = + AvaloniaProperty.Register(nameof(Sub), string.Empty); + + public static readonly StyledProperty IconProperty = + AvaloniaProperty.Register(nameof(Icon), string.Empty); + + public static readonly StyledProperty SideContentProperty = + AvaloniaProperty.Register(nameof(SideContent)); + + public static readonly StyledProperty IsExpandedProperty = + AvaloniaProperty.Register(nameof(IsExpanded), false); + + public string Title + { + get => GetValue(TitleProperty); + set => SetValue(TitleProperty, value); + } + + public string Sub + { + get => GetValue(SubProperty); + set => SetValue(SubProperty, value); + } + + public string Icon + { + get => GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + public object? SideContent + { + get => GetValue(SideContentProperty); + set => SetValue(SideContentProperty, value); + } + + public bool IsExpanded + { + get => GetValue(IsExpandedProperty); + set => SetValue(IsExpandedProperty, value); + } + + public ExCard() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml b/Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml index 0d3615e87..6bb41bd41 100644 --- a/Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml +++ b/Flow.Launcher.Avalonia/Views/SettingPages/GeneralSettingsPage.axaml @@ -6,66 +6,279 @@ xmlns:vm="using:Flow.Launcher.Avalonia.ViewModel.SettingPages" xmlns:i18n="using:Flow.Launcher.Avalonia.Resource" xmlns:core="using:Flow.Launcher.Core.Resource" - mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + xmlns:userSettings="using:Flow.Launcher.Infrastructure.UserSettings" + xmlns:sharedModels="using:Flow.Launcher.Plugin.SharedModels" + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="1200" x:Class="Flow.Launcher.Avalonia.Views.SettingPages.GeneralSettingsPage" x:DataType="vm:GeneralSettingsViewModel"> - - + + + - - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + + - - - -