Merge branch 'dev' of github.com:Flow-Launcher/Flow.Launcher into PluginStore

This commit is contained in:
Kevin Zhang 2021-10-21 12:21:00 -05:00
commit fd70326b2d
17 changed files with 169 additions and 129 deletions

View file

@ -10,35 +10,31 @@ namespace Flow.Launcher.Core.Plugin
public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalPlugins)
{
// replace multiple white spaces with one white space
var terms = text.Split(new[] { Query.TermSeperater }, StringSplitOptions.RemoveEmptyEntries);
var terms = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries);
if (terms.Length == 0)
{ // nothing was typed
return null;
}
var rawQuery = string.Join(Query.TermSeperater, terms);
var rawQuery = string.Join(Query.TermSeparator, terms);
string actionKeyword, search;
string possibleActionKeyword = terms[0];
List<string> actionParameters;
string[] searchTerms;
if (nonGlobalPlugins.TryGetValue(possibleActionKeyword, out var pluginPair) && !pluginPair.Metadata.Disabled)
{ // use non global plugin for query
actionKeyword = possibleActionKeyword;
actionParameters = terms.Skip(1).ToList();
search = actionParameters.Count > 0 ? rawQuery.Substring(actionKeyword.Length + 1) : string.Empty;
search = terms.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..] : string.Empty;
searchTerms = terms[1..];
}
else
{ // non action keyword
actionKeyword = string.Empty;
search = rawQuery;
searchTerms = terms;
}
var query = new Query
{
Terms = terms,
RawQuery = rawQuery,
ActionKeyword = actionKeyword,
Search = search
};
var query = new Query(rawQuery, search,terms, searchTerms, actionKeyword);
return query;
}

View file

@ -1,4 +1,5 @@
using System;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
@ -11,11 +12,12 @@ namespace Flow.Launcher.Plugin
/// <summary>
/// to allow unit tests for plug ins
/// </summary>
public Query(string rawQuery, string search, string[] terms, string actionKeyword = "")
public Query(string rawQuery, string search, string[] terms, string[] searchTerms, string actionKeyword = "")
{
Search = search;
RawQuery = rawQuery;
Terms = terms;
SearchTerms = searchTerms;
ActionKeyword = actionKeyword;
}
@ -23,7 +25,7 @@ namespace Flow.Launcher.Plugin
/// Raw query, this includes action keyword if it has
/// We didn't recommend use this property directly. You should always use Search property.
/// </summary>
public string RawQuery { get; internal set; }
public string RawQuery { get; internal init; }
/// <summary>
/// Search part of a query.
@ -31,45 +33,53 @@ namespace Flow.Launcher.Plugin
/// Since we allow user to switch a exclusive plugin to generic plugin,
/// so this property will always give you the "real" query part of the query
/// </summary>
public string Search { get; internal set; }
public string Search { get; internal init; }
/// <summary>
/// The raw query splited into a string array.
/// The search string split into a string array.
/// </summary>
public string[] Terms { get; set; }
public string[] SearchTerms { get; init; }
/// <summary>
/// The raw query split into a string array
/// </summary>
[Obsolete("It may or may not include action keyword, which can be confusing. Use SearchTerms instead")]
public string[] Terms { get; init; }
/// <summary>
/// Query can be splited into multiple terms by whitespace
/// </summary>
public const string TermSeperater = " ";
public const string TermSeparator = " ";
[Obsolete("Typo")]
public const string TermSeperater = TermSeparator;
/// <summary>
/// User can set multiple action keywords seperated by ';'
/// </summary>
public const string ActionKeywordSeperater = ";";
public const string ActionKeywordSeparator = ";";
[Obsolete("Typo")]
public const string ActionKeywordSeperater = ActionKeywordSeparator;
/// <summary>
/// '*' is used for System Plugin
/// </summary>
public const string GlobalPluginWildcardSign = "*";
public string ActionKeyword { get; set; }
public string ActionKeyword { get; init; }
/// <summary>
/// Return first search split by space if it has
/// </summary>
public string FirstSearch => SplitSearch(0);
private string _secondToEndSearch;
/// <summary>
/// strings from second search (including) to last search
/// </summary>
public string SecondToEndSearch
{
get
{
var index = string.IsNullOrEmpty(ActionKeyword) ? 1 : 2;
return string.Join(TermSeperater, Terms.Skip(index).ToArray());
}
}
public string SecondToEndSearch => SearchTerms.Length > 1 ? (_secondToEndSearch ??= string.Join(' ', SearchTerms[1..])) : "";
/// <summary>
/// Return second search split by space if it has
@ -83,16 +93,9 @@ namespace Flow.Launcher.Plugin
private string SplitSearch(int index)
{
try
{
return string.IsNullOrEmpty(ActionKeyword) ? Terms[index] : Terms[index + 1];
}
catch (IndexOutOfRangeException)
{
return string.Empty;
}
return index < SearchTerms.Length ? SearchTerms[index] : string.Empty;
}
public override string ToString() => RawQuery;
}
}
}

View file

@ -30,7 +30,7 @@ namespace Flow.Launcher
private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e)
{
tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeperater, plugin.Metadata.ActionKeywords.ToArray());
tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, plugin.Metadata.ActionKeywords.ToArray());
tbAction.Focus();
}

View file

@ -6,6 +6,8 @@ using NHotkey.Wpf;
using Flow.Launcher.Core.Resource;
using System.Windows;
using Flow.Launcher.ViewModel;
using System.Threading.Tasks;
using System.Threading;
namespace Flow.Launcher.Helper
{
@ -19,10 +21,15 @@ namespace Flow.Launcher.Helper
mainViewModel = mainVM;
settings = mainViewModel._settings;
SetHotkey(settings.Hotkey, OnHotkey);
SetHotkey(settings.Hotkey, OnToggleHotkey);
LoadCustomPluginHotkey();
}
internal static void OnToggleHotkey(object sender, HotkeyEventArgs args)
{
mainViewModel.ToggleFlowLauncher();
}
private static void SetHotkey(string hotkeyStr, EventHandler<HotkeyEventArgs> action)
{
var hotkey = new HotkeyModel(hotkeyStr);
@ -53,44 +60,6 @@ namespace Flow.Launcher.Helper
}
}
internal static void OnHotkey(object sender, HotkeyEventArgs e)
{
if (!ShouldIgnoreHotkeys())
{
UpdateLastQUeryMode();
mainViewModel.ToggleFlowLauncher();
e.Handled = true;
}
}
/// <summary>
/// Checks if Flow Launcher should ignore any hotkeys
/// </summary>
private static bool ShouldIgnoreHotkeys()
{
return settings.IgnoreHotkeysOnFullscreen && WindowsInteropHelper.IsWindowFullscreen();
}
private static void UpdateLastQUeryMode()
{
switch(settings.LastQueryMode)
{
case LastQueryMode.Empty:
mainViewModel.ChangeQueryText(string.Empty);
break;
case LastQueryMode.Preserved:
mainViewModel.LastQuerySelected = true;
break;
case LastQueryMode.Selected:
mainViewModel.LastQuerySelected = false;
break;
default:
throw new ArgumentException($"wrong LastQueryMode: <{settings.LastQueryMode}>");
}
}
internal static void LoadCustomPluginHotkey()
{
if (settings.CustomPluginHotkeys == null)
@ -106,7 +75,7 @@ namespace Flow.Launcher.Helper
{
SetHotkey(hotkey.Hotkey, (s, e) =>
{
if (ShouldIgnoreHotkeys())
if (mainViewModel.ShouldIgnoreHotkeys())
return;
mainViewModel.MainWindowVisibility = Visibility.Visible;

View file

@ -262,7 +262,7 @@ namespace Flow.Launcher
{
if (_settings.HideWhenDeactive)
{
Hide();
_viewModel.Hide();
}
}

View file

@ -25,6 +25,7 @@ namespace Flow.Launcher
public readonly IPublicAPI API;
private Settings settings;
private SettingWindowViewModel viewModel;
private static MainViewModel mainViewModel;
public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel)
{
@ -128,7 +129,7 @@ namespace Flow.Launcher
if (HotkeyControl.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnHotkey);
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
HotKeyMapper.RemoveHotkey(settings.Hotkey);
settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
}

View file

@ -21,6 +21,8 @@ using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
using System.Windows.Threading;
using NHotkey;
namespace Flow.Launcher.ViewModel
{
@ -108,7 +110,9 @@ namespace Flow.Launcher.ViewModel
}
Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
};
}
;
void continueAction(Task t)
{
@ -145,6 +149,24 @@ namespace Flow.Launcher.ViewModel
}
}
private void UpdateLastQUeryMode()
{
switch (_settings.LastQueryMode)
{
case LastQueryMode.Empty:
ChangeQueryText(string.Empty);
break;
case LastQueryMode.Preserved:
LastQuerySelected = true;
break;
case LastQueryMode.Selected:
LastQuerySelected = false;
break;
default:
throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>");
}
}
private void InitializeKeyCommands()
{
@ -156,7 +178,18 @@ namespace Flow.Launcher.ViewModel
}
else
{
MainWindowVisibility = Visibility.Collapsed;
Hide();
}
});
ClearQueryCommand = new RelayCommand(_ =>
{
if (!string.IsNullOrEmpty(QueryText))
{
ChangeQueryText(string.Empty);
// Push Event to UI SystemQuery has changed
//OnPropertyChanged(nameof(SystemQueryText));
}
});
@ -194,7 +227,7 @@ namespace Flow.Launcher.ViewModel
if (hideWindow)
{
MainWindowVisibility = Visibility.Collapsed;
Hide();
}
if (SelectedIsFromQueryResults())
@ -244,7 +277,7 @@ namespace Flow.Launcher.ViewModel
Owner = Application.Current.MainWindow
};
MainWindowVisibility = Visibility.Collapsed;
Hide();
PluginManager
.ReloadData()
@ -343,7 +376,6 @@ namespace Flow.Launcher.ViewModel
}
public Visibility ProgressBarVisibility { get; set; }
public Visibility MainWindowVisibility { get; set; }
public ICommand EscCommand { get; set; }
@ -357,6 +389,7 @@ namespace Flow.Launcher.ViewModel
public ICommand LoadHistoryCommand { get; set; }
public ICommand OpenResultCommand { get; set; }
public ICommand ReloadPluginDataCommand { get; set; }
public ICommand ClearQueryCommand { get; private set; }
public string OpenResultCommandModifiers { get; private set; }
@ -668,7 +701,7 @@ namespace Flow.Launcher.ViewModel
OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
}
internal void ToggleFlowLauncher()
public async void ToggleFlowLauncher()
{
if (MainWindowVisibility != Visibility.Visible)
{
@ -676,12 +709,48 @@ namespace Flow.Launcher.ViewModel
}
else
{
switch (_settings.LastQueryMode)
{
case LastQueryMode.Empty:
ChangeQueryText(string.Empty);
Application.Current.MainWindow.Opacity = 0; // Trick for no delay
await Task.Delay(100);
Application.Current.MainWindow.Opacity = 1;
break;
case LastQueryMode.Preserved:
LastQuerySelected = true;
break;
case LastQueryMode.Selected:
LastQuerySelected = false;
break;
default:
throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>");
}
MainWindowVisibility = Visibility.Collapsed;
}
}
public void Hide()
{
if (MainWindowVisibility != Visibility.Collapsed)
{
ToggleFlowLauncher();
}
}
#endregion
/// <summary>
/// Checks if Flow Launcher should ignore any hotkeys
/// </summary>
public bool ShouldIgnoreHotkeys()
{
return _settings.IgnoreHotkeysOnFullscreen && WindowsInteropHelper.IsWindowFullscreen();
}
#region Public Methods
public void Save()

View file

@ -36,7 +36,7 @@ namespace Flow.Launcher.ViewModel
public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed;
public string InitilizaTime => PluginPair.Metadata.InitTime + "ms";
public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms";
public string ActionKeywordsText => string.Join(Query.ActionKeywordSeperater, PluginPair.Metadata.ActionKeywords);
public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords);
public int Priority => PluginPair.Metadata.Priority;
public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword)

View file

@ -17,7 +17,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark
private List<Bookmark> LoadChromeBookmarks()
{
var bookmarks = new List<Bookmark>();
String platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Google\Chrome\User Data"), "Google Chrome"));
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Google\Chrome SxS\User Data"), "Google Chrome Canary"));
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Chromium\User Data"), "Chromium"));

View file

@ -10,22 +10,17 @@ namespace Flow.Launcher.Plugin.BrowserBookmark
{
public class EdgeBookmarkLoader : ChromiumBookmarkLoader
{
private readonly List<Bookmark> _bookmarks = new();
private void LoadEdgeBookmarks()
private List<Bookmark> LoadEdgeBookmarks()
{
var bookmarks = new List<Bookmark>();
var platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge\User Data"), "Microsoft Edge");
LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge Dev\User Data"), "Microsoft Edge Dev");
LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge SxS\User Data"), "Microsoft Edge Canary");
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge\User Data"), "Microsoft Edge"));
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge Dev\User Data"), "Microsoft Edge Dev"));
bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge SxS\User Data"), "Microsoft Edge Canary"));
return bookmarks;
}
public override List<Bookmark> GetBookmarks()
{
_bookmarks.Clear();
LoadEdgeBookmarks();
return _bookmarks;
}
public override List<Bookmark> GetBookmarks() => LoadEdgeBookmarks();
}
}

View file

@ -17,6 +17,6 @@
<system:String x:Key="flowlauncher_plugin_browserbookmark_loadBrowserFrom">Load Browser From:</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_browserName">Browser Name</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_browserBookmarkDataDirectory">DataDirectoryPath</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_addBrowserBookmark">Add Custom Browser Bookmark</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_removeBrowserBookmark">Delete Custom Browser Bookmark</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_addBrowserBookmark">Add</system:String>
<system:String x:Key="flowlauncher_plugin_browserbookmark_removeBrowserBookmark">Delete</system:String>
</ResourceDictionary>

View file

@ -5,7 +5,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Flow.Launcher.Plugin.BrowserBookmark.Models"
mc:Ignorable="d"
Title="CustomBrowserSetting" Height="450" Width="600"
WindowStartupLocation="CenterScreen"
Title="CustomBrowserSetting" Height="350" Width="600"
KeyDown="WindowKeyDown"
>
<Window.DataContext>
@ -13,25 +14,25 @@
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="100"/>
<RowDefinition Height="100"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Browser Name" FontSize="15"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
HorizontalAlignment="Left" VerticalAlignment="Center" Margin="80 0 0 0"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Browser Data Directory Path" FontSize="15"
HorizontalAlignment="Left" VerticalAlignment="Center"/>
HorizontalAlignment="Left" VerticalAlignment="Center" Margin="80 0 0 0"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name}"
HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="30"/>
HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="30" Margin="50 0 0 0"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding DataDirectoryPath}"
HorizontalAlignment="Left" VerticalAlignment="Center" Width="200" Height="30"/>
<StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Grid.Column="1" Height="60">
<Button Content="Confirm" Margin="15" Click="ConfirmEditCustomBrowser"/>
<Button Content="Cancel" Margin="15"/>
HorizontalAlignment="Left" VerticalAlignment="Center" Width="200" Height="30" Margin="50 0 0 0"/>
<StackPanel HorizontalAlignment="Center" Grid.Row="2" Orientation="Horizontal" Grid.Column="1" Height="70">
<Button Name="btnConfirm" Content="Confirm" Margin="15" Click="ConfirmCancelEditCustomBrowser"/>
<Button Content="Cancel" Margin="15" Click="ConfirmCancelEditCustomBrowser"/>
</StackPanel>
</Grid>
</Window>

View file

@ -31,20 +31,26 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Views
};
}
private void ConfirmEditCustomBrowser(object sender, RoutedEventArgs e)
private void ConfirmCancelEditCustomBrowser(object sender, RoutedEventArgs e)
{
if (DataContext is CustomBrowser editedBrowser)
if (DataContext is CustomBrowser editBrowser && e.Source is Button button)
{
currentCustomBrowser.Name = editedBrowser.Name;
currentCustomBrowser.DataDirectoryPath = editedBrowser.DataDirectoryPath;
if (button.Name == "btnConfirm")
{
currentCustomBrowser.Name = editBrowser.Name;
currentCustomBrowser.DataDirectoryPath = editBrowser.DataDirectoryPath;
Close();
}
}
Close();
}
private void WindowKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
ConfirmEditCustomBrowser(sender, e);
ConfirmCancelEditCustomBrowser(sender, e);
}
}
}

View file

@ -63,8 +63,10 @@
</ListView.View>
</ListView>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_addBrowserBookmark}" Margin="10" Click="NewCustomBrowser"/>
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_removeBrowserBookmark}" Margin="10" Click="DeleteCustomBrowser"/>
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_addBrowserBookmark}"
Margin="10" Click="NewCustomBrowser" Width="80" />
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_removeBrowserBookmark}"
Margin="10" Click="DeleteCustomBrowser" Width="80"/>
</StackPanel>
</StackPanel>
</Grid>

View file

@ -12,11 +12,11 @@ namespace Flow.Launcher.Plugin.PluginIndicator
{
// if query contains more than one word, eg. github tips
// user has decided to type something else rather than wanting to see the available action keywords
if (query.Terms.Length > 1)
if (query.SearchTerms.Length > 1)
return new List<Result>();
var results = from keyword in PluginManager.NonGlobalPlugins.Keys
where keyword.StartsWith(query.Terms[0])
where keyword.StartsWith(query.SearchTerms[0])
let metadata = PluginManager.NonGlobalPlugins[keyword].Metadata
where !metadata.Disabled
select new Result
@ -27,7 +27,7 @@ namespace Flow.Launcher.Plugin.PluginIndicator
IcoPath = metadata.IcoPath,
Action = c =>
{
context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeperater}");
context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}");
return false;
}
};

View file

@ -23,9 +23,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
public List<Result> Query(Query query)
{
var termToSearch = query.Terms.Length <= 1
? null
: string.Join(Plugin.Query.TermSeperater, query.Terms.Skip(1)).ToLower();
var termToSearch = query.Search;
var processlist = processHelper.GetMatchingProcesses(termToSearch);

View file

@ -325,7 +325,7 @@ namespace Flow.Launcher.Plugin.Shell
private void OnWinRPressed()
{
context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeperater}");
context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}");
// show the main window and set focus to the query box
Window mainWindow = Application.Current.MainWindow;