diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
index 3e7c3cb83..2ec69e81a 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs
@@ -89,9 +89,12 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
if (window.ShowDialog() is not true) return;
var index = Settings.CustomPluginHotkeys.IndexOf(settingItem);
- Settings.CustomPluginHotkeys[index] = new CustomPluginHotkey(window.Hotkey, window.ActionKeyword);
- HotKeyMapper.RemoveHotkey(settingItem.Hotkey); // remove origin hotkey
- HotKeyMapper.SetCustomQueryHotkey(Settings.CustomPluginHotkeys[index]); // set new hotkey
+ if (index >= 0 && index < Settings.CustomPluginHotkeys.Count)
+ {
+ Settings.CustomPluginHotkeys[index] = new CustomPluginHotkey(window.Hotkey, window.ActionKeyword);
+ HotKeyMapper.RemoveHotkey(settingItem.Hotkey); // remove origin hotkey
+ HotKeyMapper.SetCustomQueryHotkey(Settings.CustomPluginHotkeys[index]); // set new hotkey
+ }
}
[RelayCommand]
@@ -150,7 +153,10 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
if (window.ShowDialog() is not true) return;
var index = Settings.CustomShortcuts.IndexOf(settingItem);
- Settings.CustomShortcuts[index] = new CustomShortcutModel(window.Key, window.Value);
+ if (index >= 0 && index < Settings.CustomShortcuts.Count)
+ {
+ Settings.CustomShortcuts[index] = new CustomShortcutModel(window.Key, window.Value);
+ }
}
[RelayCommand]
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
index c6a74a047..5d65e4462 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
@@ -47,6 +47,7 @@
Please enter a URL
Action keyword already exists, please enter a different one
Success
+ Failed to update search source. The item may have been removed.
Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location.
Web Searches
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
index acc2c1e5c..9508d61a0 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
@@ -108,9 +108,19 @@ namespace Flow.Launcher.Plugin.WebSearch
_context.API.AddActionKeyword(id, newKeyword);
var index = _searchSources.IndexOf(_oldSearchSource);
- _searchSources[index] = _searchSource;
-
- Close();
+
+ // Only update if we found the item in the collection
+ if (index >= 0 && index < _searchSources.Count)
+ {
+ _searchSources[index] = _searchSource;
+ Close();
+ }
+ else
+ {
+ var warning = _api.GetTranslation("flowlauncher_plugin_websearch_edit_failed");
+ _context.API.ShowMsgBox(warning);
+ Close();
+ }
}
else
{
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml
index d1f48212b..152558e81 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml
@@ -52,6 +52,10 @@
MouseDoubleClick="MouseDoubleClickItem"
SelectedItem="{Binding Settings.SelectedSearchSource}"
SizeChanged="ListView_SizeChanged"
+ PreviewMouseLeftButtonDown="ListView_PreviewMouseLeftButtonDown"
+ PreviewMouseMove="ListView_PreviewMouseMove"
+ AllowDrop="True"
+ Drop="ListView_Drop"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs
index 55fe99824..6dc766fff 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs
@@ -1,7 +1,10 @@
-using System.Windows;
-using System.Windows.Controls;
+using System;
using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media;
namespace Flow.Launcher.Plugin.WebSearch
{
@@ -12,6 +15,7 @@ namespace Flow.Launcher.Plugin.WebSearch
{
private readonly Settings _settings;
private readonly PluginInitContext _context;
+ private Point _dragStartPoint;
public SettingsControl(PluginInitContext context, SettingsViewModel viewModel)
{
@@ -163,5 +167,78 @@ namespace Flow.Launcher.Plugin.WebSearch
gView.Columns[3].Width = workingWidth * col4;
gView.Columns[4].Width = workingWidth * col5;
}
+
+ private void ListView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ _dragStartPoint = e.GetPosition(null);
+ }
+
+ private void ListView_PreviewMouseMove(object sender, MouseEventArgs e)
+ {
+ Point mousePos = e.GetPosition(null);
+ Vector diff = _dragStartPoint - mousePos;
+
+ if (e.LeftButton == MouseButtonState.Pressed &&
+ (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
+ Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
+ {
+ var listView = (ListView)sender;
+ ListViewItem listViewItem = FindAncestor((DependencyObject)e.OriginalSource);
+
+ if (listViewItem == null) return;
+
+ SearchSource item = (SearchSource)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
+ if (item == null) return;
+
+ DragDrop.DoDragDrop(listViewItem, item, DragDropEffects.Move);
+ }
+ }
+
+ private void ListView_Drop(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(typeof(SearchSource)))
+ {
+ SearchSource droppedData = e.Data.GetData(typeof(SearchSource)) as SearchSource;
+ var listView = (ListView)sender;
+ var target = GetNearestContainer(e.OriginalSource);
+
+ if (target == null)
+ return;
+
+ SearchSource targetData = (SearchSource)listView.ItemContainerGenerator.ItemFromContainer(target);
+
+ if (targetData == null)
+ return;
+
+ var items = _settings.SearchSources;
+ int removedIdx = items.IndexOf(droppedData);
+ int targetIdx = items.IndexOf(targetData);
+
+ if (removedIdx == targetIdx)
+ return;
+
+ items.Move(removedIdx, targetIdx);
+ }
+ }
+
+ private ListViewItem GetNearestContainer(object source)
+ {
+ var element = source as UIElement;
+ while (element != null && !(element is ListViewItem))
+ element = VisualTreeHelper.GetParent(element) as UIElement;
+
+ return element as ListViewItem;
+ }
+
+ private static T FindAncestor(DependencyObject current) where T : DependencyObject
+ {
+ while (current != null)
+ {
+ if (current is T)
+ return (T)current;
+ current = VisualTreeHelper.GetParent(current);
+ }
+ return null;
+ }
}
}