diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml index 21f836bec6c..d484c722859 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml @@ -13,6 +13,7 @@ Edit Add Enabled + Tag Enabled Disabled Confirm diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs index 9eedd29a3bb..343fd7797d2 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs @@ -31,6 +31,8 @@ public string IconPath } public string Url { get; set; } + + public string Tag { get; set; } [JsonIgnore] public bool Status => Enabled; @@ -45,6 +47,7 @@ public SearchSource DeepCopy() Url = Url, Icon = Icon, CustomIcon = CustomIcon, + Tag = Tag, Enabled = Enabled }; return webSearch; diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml index 3df50b3edc8..648bc04e682 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml @@ -101,6 +101,7 @@ + + + + diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs index e53f4ec7517..f345d532c33 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs @@ -2,6 +2,9 @@ using System.Windows.Controls; using System.ComponentModel; using System.Windows.Data; +using System; +using System.Collections; +using System.Collections.Generic; namespace Flow.Launcher.Plugin.WebSearch { @@ -19,6 +22,40 @@ public SettingsControl(PluginInitContext context, SettingsViewModel viewModel) _context = context; _settings = viewModel.Settings; DataContext = viewModel; + this.Loaded += SettingsControl_Loaded; + } + + private void SettingsControl_Loaded(object sender, RoutedEventArgs e) + { + // After the ListView is loaded, sort by Tag in ascending order + if (SearchSourcesListView.ItemsSource != null) + { + // Apply initial sorting by Tag column + Sort("Tag", ListSortDirection.Ascending); + + // Display an arrow on the sorted column (optional) + var tagColumn = GetColumnByHeader("Tag"); + if (tagColumn != null) + { + tagColumn.HeaderTemplate = Resources["HeaderTemplateArrowUp"] as DataTemplate; + _lastHeaderClicked = tagColumn.Header as GridViewColumnHeader; + _lastDirection = ListSortDirection.Ascending; + } + } + } + + // Find column by header name + private GridViewColumn GetColumnByHeader(string header) + { + if (SearchSourcesListView.View is GridView gridView) + { + foreach (var column in gridView.Columns) + { + if (column.Header != null && column.Header.ToString() == header) + return column; + } + } + return null; } private void OnAddSearchSearchClick(object sender, RoutedEventArgs e) @@ -122,8 +159,23 @@ private void Sort(string sortBy, ListSortDirection direction) { ICollectionView dataView = CollectionViewSource.GetDefaultView(SearchSourcesListView.ItemsSource); dataView.SortDescriptions.Clear(); - SortDescription sd = new(sortBy, direction); - dataView.SortDescriptions.Add(sd); + + // Special handling for Tag sorting + if (sortBy == "Tag") + { + // Apply custom sorting (using TagComparer) + if (dataView is ListCollectionView listView) + { + listView.CustomSort = new TagComparer(direction); + } + } + else + { + // Normal sorting + SortDescription sd = new SortDescription(sortBy, direction); + dataView.SortDescriptions.Add(sd); + } + dataView.Refresh(); } @@ -139,5 +191,48 @@ private void MouseDoubleClickItem(object sender, System.Windows.Input.MouseButto webSearch.ShowDialog(); } } + + + public class TagComparer : IComparer + { + private readonly ListSortDirection _direction; + + public TagComparer(ListSortDirection direction) + { + _direction = direction; + } + + public int Compare(object x, object y) + { + if (x is SearchSource sourceX && y is SearchSource sourceY) + { + string tagX = sourceX.Tag; + string tagY = sourceY.Tag; + + bool isEmptyX = string.IsNullOrWhiteSpace(tagX); + bool isEmptyY = string.IsNullOrWhiteSpace(tagY); + + // If both are empty tags, they are equal + if (isEmptyX && isEmptyY) + return 0; + + // If only x is an empty tag, it always goes to the back + if (isEmptyX) + return 1; + + // If only y is an empty tag, it always goes to the front + if (isEmptyY) + return -1; + + // If both have tags, compare as normal strings + int result = string.Compare(tagX, tagY, StringComparison.OrdinalIgnoreCase); + + // Reverse the result according to the sorting direction + return _direction == ListSortDirection.Ascending ? result : -result; + } + + return 0; + } + } } }