Merge branch 'dev' into AcronymFuzzy

This commit is contained in:
Jeremy Wu 2021-01-26 15:41:58 +11:00
commit ce525b3fa0
16 changed files with 154 additions and 133 deletions

View file

@ -35,7 +35,8 @@ namespace Flow.Launcher.Core
UpdateInfo newUpdateInfo; UpdateInfo newUpdateInfo;
if (!silentUpdate) if (!silentUpdate)
api.ShowMsg("Please wait...", "Checking for new update"); api.ShowMsg(api.GetTranslation("pleaseWait"),
api.GetTranslation("update_flowlauncher_update_check"));
using var updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false); using var updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false);
@ -51,12 +52,13 @@ namespace Flow.Launcher.Core
if (newReleaseVersion <= currentVersion) if (newReleaseVersion <= currentVersion)
{ {
if (!silentUpdate) if (!silentUpdate)
MessageBox.Show("You already have the latest Flow Launcher version"); MessageBox.Show(api.GetTranslation("update_flowlauncher_already_on_latest"));
return; return;
} }
if (!silentUpdate) if (!silentUpdate)
api.ShowMsg("Update found", "Updating..."); api.ShowMsg(api.GetTranslation("update_flowlauncher_update_found"),
api.GetTranslation("update_flowlauncher_updating"));
await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false); await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false);
@ -67,8 +69,9 @@ namespace Flow.Launcher.Core
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}";
FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination); FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination);
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination)) if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination))
MessageBox.Show("Flow Launcher was not able to move your user profile data to the new update version. Please manually " + MessageBox.Show(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
$"move your profile data folder from {DataLocation.PortableDataPath} to {targetDestination}"); DataLocation.PortableDataPath,
targetDestination));
} }
else else
{ {
@ -79,7 +82,7 @@ namespace Flow.Launcher.Core
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
if (MessageBox.Show(newVersionTips, "New Update", MessageBoxButton.YesNo) == MessageBoxResult.Yes) if (MessageBox.Show(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
UpdateManager.RestartApp(Constant.ApplicationFileName); UpdateManager.RestartApp(Constant.ApplicationFileName);
} }
@ -87,7 +90,8 @@ namespace Flow.Launcher.Core
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
{ {
Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e); Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
api.ShowMsg("Update Failed", "Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com."); api.ShowMsg(api.GetTranslation("update_flowlauncher_fail"),
api.GetTranslation("update_flowlauncher_check_connection"));
return; return;
} }
} }

View file

@ -24,7 +24,7 @@ namespace Flow.Launcher.Test.Plugins
return new List<Result>(); return new List<Result>();
} }
private List<Result> MethodDirectoryInfoClassSearchReturnsTwoResults(Query dummyQuery, string dummyString) private List<Result> MethodDirectoryInfoClassSearchReturnsTwoResults(Query dummyQuery, string dummyString, CancellationToken token)
{ {
return new List<Result> return new List<Result>
{ {

View file

@ -5,7 +5,7 @@
Icon="Images\app.png" Icon="Images\app.png"
ResizeMode="NoResize" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Title="Custom Plugin Hotkey" Height="200" Width="674.766"> Title="{DynamicResource customeQueryHotkeyTitle}" Height="200" Width="674.766">
<Window.InputBindings> <Window.InputBindings>
<KeyBinding Key="Escape" Command="Close"/> <KeyBinding Key="Escape" Command="Close"/>
</Window.InputBindings> </Window.InputBindings>

View file

@ -17,6 +17,7 @@
<!--Setting General--> <!--Setting General-->
<system:String x:Key="flowlauncher_settings">Flow Launcher Settings</system:String> <system:String x:Key="flowlauncher_settings">Flow Launcher Settings</system:String>
<system:String x:Key="general">General</system:String> <system:String x:Key="general">General</system:String>
<system:String x:Key="portableMode">Portable Mode</system:String>
<system:String x:Key="startFlowLauncherOnSystemStartup">Start Flow Launcher on system startup</system:String> <system:String x:Key="startFlowLauncherOnSystemStartup">Start Flow Launcher on system startup</system:String>
<system:String x:Key="hideFlowLauncherWhenLoseFocus">Hide Flow Launcher when focus is lost</system:String> <system:String x:Key="hideFlowLauncherWhenLoseFocus">Hide Flow Launcher when focus is lost</system:String>
<system:String x:Key="dontPromptUpdateMsg">Do not show new version notifications</system:String> <system:String x:Key="dontPromptUpdateMsg">Do not show new version notifications</system:String>
@ -39,12 +40,13 @@
<!--Setting Plugin--> <!--Setting Plugin-->
<system:String x:Key="plugin">Plugin</system:String> <system:String x:Key="plugin">Plugin</system:String>
<system:String x:Key="browserMorePlugins">Find more plugins</system:String> <system:String x:Key="browserMorePlugins">Find more plugins</system:String>
<system:String x:Key="enable">Enable</system:String>
<system:String x:Key="disable">Disable</system:String> <system:String x:Key="disable">Disable</system:String>
<system:String x:Key="actionKeywords">Action keyword:</system:String> <system:String x:Key="actionKeywords">Action keyword:</system:String>
<system:String x:Key="currentActionKeywords">Current action keyword:</system:String> <system:String x:Key="currentActionKeywords">Current action keyword:</system:String>
<system:String x:Key="newActionKeyword">New action keyword:</system:String> <system:String x:Key="newActionKeyword">New action keyword:</system:String>
<system:String x:Key="currentPriority">Current Priority: </system:String> <system:String x:Key="currentPriority">Current Priority:</system:String>
<system:String x:Key="newPriority">New Priority: </system:String> <system:String x:Key="newPriority">New Priority:</system:String>
<system:String x:Key="pluginDirectory">Plugin Directory</system:String> <system:String x:Key="pluginDirectory">Plugin Directory</system:String>
<system:String x:Key="author">Author</system:String> <system:String x:Key="author">Author</system:String>
<system:String x:Key="plugin_init_time">Init time:</system:String> <system:String x:Key="plugin_init_time">Init time:</system:String>
@ -122,6 +124,7 @@
<system:String x:Key="actionkeyword_tips">Use * if you don't want to specify an action keyword</system:String> <system:String x:Key="actionkeyword_tips">Use * if you don't want to specify an action keyword</system:String>
<!--Custom Query Hotkey Dialog--> <!--Custom Query Hotkey Dialog-->
<system:String x:Key="customeQueryHotkeyTitle">Custom Plugin Hotkey</system:String>
<system:String x:Key="preview">Preview</system:String> <system:String x:Key="preview">Preview</system:String>
<system:String x:Key="hotkeyIsNotUnavailable">Hotkey is unavailable, please select a new hotkey</system:String> <system:String x:Key="hotkeyIsNotUnavailable">Hotkey is unavailable, please select a new hotkey</system:String>
<system:String x:Key="invalidPluginHotkey">Invalid plugin hotkey</system:String> <system:String x:Key="invalidPluginHotkey">Invalid plugin hotkey</system:String>
@ -146,11 +149,23 @@
<system:String x:Key="reportWindow_report_failed">Failed to send report</system:String> <system:String x:Key="reportWindow_report_failed">Failed to send report</system:String>
<system:String x:Key="reportWindow_flowlauncher_got_an_error">Flow Launcher got an error</system:String> <system:String x:Key="reportWindow_flowlauncher_got_an_error">Flow Launcher got an error</system:String>
<!--General Notice-->
<system:String x:Key="pleaseWait">Please wait...</system:String>
<!--update--> <!--update-->
<system:String x:Key="update_flowlauncher_update_check">Checking for new update</system:String>
<system:String x:Key="update_flowlauncher_already_on_latest">You already have the latest Flow Launcher version</system:String>
<system:String x:Key="update_flowlauncher_update_found">Update found</system:String>
<system:String x:Key="update_flowlauncher_updating">Updating...</system:String>
<system:String x:Key="update_flowlauncher_fail_moving_portable_user_profile_data">Flow Launcher was not able to move your user profile data to the new update version.
Please manually move your profile data folder from {0} to {1}</system:String>
<system:String x:Key="update_flowlauncher_new_update">New Update</system:String>
<system:String x:Key="update_flowlauncher_update_new_version_available">New Flow Launcher release {0} is now available</system:String> <system:String x:Key="update_flowlauncher_update_new_version_available">New Flow Launcher release {0} is now available</system:String>
<system:String x:Key="update_flowlauncher_update_error">An error occurred while trying to install software updates</system:String> <system:String x:Key="update_flowlauncher_update_error">An error occurred while trying to install software updates</system:String>
<system:String x:Key="update_flowlauncher_update">Update</system:String> <system:String x:Key="update_flowlauncher_update">Update</system:String>
<system:String x:Key="update_flowlauncher_update_cancel">Cancel</system:String> <system:String x:Key="update_flowlauncher_update_cancel">Cancel</system:String>
<system:String x:Key="update_flowlauncher_fail">Update Failed</system:String>
<system:String x:Key="update_flowlauncher_check_connection">Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com.</system:String>
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">This upgrade will restart Flow Launcher</system:String> <system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">This upgrade will restart Flow Launcher</system:String>
<system:String x:Key="update_flowlauncher_update_upadte_files">Following files will be updated</system:String> <system:String x:Key="update_flowlauncher_update_upadte_files">Following files will be updated</system:String>
<system:String x:Key="update_flowlauncher_update_files">Update files</system:String> <system:String x:Key="update_flowlauncher_update_files">Update files</system:String>

View file

@ -37,7 +37,7 @@
<ScrollViewer ui:ScrollViewerHelper.AutoHideScrollBars="True" Margin="60,30,0,30"> <ScrollViewer ui:ScrollViewerHelper.AutoHideScrollBars="True" Margin="60,30,0,30">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<ui:ToggleSwitch Margin="10" IsOn="{Binding PortableMode}"> <ui:ToggleSwitch Margin="10" IsOn="{Binding PortableMode}">
<TextBlock Text="Portable Mode" /> <TextBlock Text="{DynamicResource portableMode}" />
</ui:ToggleSwitch> </ui:ToggleSwitch>
<CheckBox Margin="10" IsChecked="{Binding Settings.StartFlowLauncherOnSystemStartup}" <CheckBox Margin="10" IsChecked="{Binding Settings.StartFlowLauncherOnSystemStartup}"
Checked="OnAutoStartupChecked" Unchecked="OnAutoStartupUncheck"> Checked="OnAutoStartupChecked" Unchecked="OnAutoStartupUncheck">
@ -166,7 +166,7 @@
</TextBlock> </TextBlock>
</ToolTipService.ToolTip> </ToolTipService.ToolTip>
</TextBlock> </TextBlock>
<ui:ToggleSwitch Grid.Column="1" OffContent="Disabled" OnContent="Enabled" <ui:ToggleSwitch Grid.Column="1" OffContent="{DynamicResource disable}" OnContent="{DynamicResource enable}"
MaxWidth="110" HorizontalAlignment="Right" MaxWidth="110" HorizontalAlignment="Right"
IsOn="{Binding PluginState}"/> IsOn="{Binding PluginState}"/>
</Grid> </Grid>

View file

@ -139,39 +139,9 @@ namespace Flow.Launcher.ViewModel
/// </summary> /// </summary>
public void AddResults(List<Result> newRawResults, string resultId) public void AddResults(List<Result> newRawResults, string resultId)
{ {
lock (_collectionLock) var newResults = NewResults(newRawResults, resultId);
{
var newResults = NewResults(newRawResults, resultId);
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf UpdateResults(newResults);
// fix selected index flow
var updateTask = Task.Run(() =>
{
// update UI in one run, so it can avoid UI flickering
Results.Update(newResults);
if (Results.Any())
SelectedItem = Results[0];
});
if (!updateTask.Wait(300))
{
updateTask.Dispose();
throw new TimeoutException("Update result use too much time.");
}
}
if (Visbility != Visibility.Visible && Results.Count > 0)
{
Margin = new Thickness { Top = 8 };
SelectedIndex = 0;
Visbility = Visibility.Visible;
}
else
{
Margin = new Thickness { Top = 0 };
Visbility = Visibility.Collapsed;
}
} }
/// <summary> /// <summary>
/// To avoid deadlock, this method should not called from main thread /// To avoid deadlock, this method should not called from main thread
@ -179,12 +149,18 @@ namespace Flow.Launcher.ViewModel
public void AddResults(IEnumerable<ResultsForUpdate> resultsForUpdates, CancellationToken token) public void AddResults(IEnumerable<ResultsForUpdate> resultsForUpdates, CancellationToken token)
{ {
var newResults = NewResults(resultsForUpdates); var newResults = NewResults(resultsForUpdates);
if (token.IsCancellationRequested) if (token.IsCancellationRequested)
return; return;
UpdateResults(newResults, token);
}
private void UpdateResults(List<ResultViewModel> newResults, CancellationToken token = default)
{
lock (_collectionLock) lock (_collectionLock)
{ {
// update UI in one run, so it can avoid UI flickering // update UI in one run, so it can avoid UI flickering
Results.Update(newResults, token); Results.Update(newResults, token);
if (Results.Any()) if (Results.Any())
SelectedItem = Results[0]; SelectedItem = Results[0];
@ -202,7 +178,6 @@ namespace Flow.Launcher.ViewModel
Visbility = Visibility.Collapsed; Visbility = Visibility.Collapsed;
break; break;
} }
} }
private List<ResultViewModel> NewResults(List<Result> newRawResults, string resultId) private List<ResultViewModel> NewResults(List<Result> newRawResults, string resultId)
@ -212,10 +187,10 @@ namespace Flow.Launcher.ViewModel
var results = Results as IEnumerable<ResultViewModel>; var results = Results as IEnumerable<ResultViewModel>;
var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList(); var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings));
return results.Where(r => r.Result.PluginID != resultId) return results.Where(r => r.Result.PluginID != resultId)
.Concat(results.Intersect(newResults).Union(newResults)) .Concat(newResults)
.OrderByDescending(r => r.Result.Score) .OrderByDescending(r => r.Result.Score)
.ToList(); .ToList();
} }
@ -228,8 +203,7 @@ namespace Flow.Launcher.ViewModel
var results = Results as IEnumerable<ResultViewModel>; var results = Results as IEnumerable<ResultViewModel>;
return results.Where(r => r != null && !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID)) return results.Where(r => r != null && !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID))
.Concat( .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings)))
resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings)))
.OrderByDescending(rv => rv.Result.Score) .OrderByDescending(rv => rv.Result.Score)
.ToList(); .ToList();
} }
@ -266,49 +240,50 @@ namespace Flow.Launcher.ViewModel
} }
#endregion #endregion
public class ResultCollection : ObservableCollection<ResultViewModel> public class ResultCollection : List<ResultViewModel>, INotifyCollectionChanged
{ {
private long editTime = 0; private long editTime = 0;
private bool _suppressNotifying = false;
private CancellationToken _token; private CancellationToken _token;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{ {
if (!_suppressNotifying) CollectionChanged?.Invoke(this, e);
{
base.OnCollectionChanged(e);
}
} }
public void BulkAddRange(IEnumerable<ResultViewModel> resultViews) public void BulkAddAll(List<ResultViewModel> resultViews)
{ {
// suppress notifying before adding all element AddRange(resultViews);
_suppressNotifying = true;
foreach (var item in resultViews) // can return because the list will be cleared next time updated, which include a reset event
{
Add(item);
}
_suppressNotifying = false;
// manually update event
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
if (_token.IsCancellationRequested) if (_token.IsCancellationRequested)
return; return;
// manually update event
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} }
public void AddRange(IEnumerable<ResultViewModel> Items) private void AddAll(List<ResultViewModel> Items)
{ {
foreach (var item in Items) for (int i = 0; i < Items.Count; i++)
{ {
var item = Items[i];
if (_token.IsCancellationRequested) if (_token.IsCancellationRequested)
return; return;
Add(item); Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
} }
} }
public void RemoveAll() public void RemoveAll(int Capacity = 512)
{ {
ClearItems(); Clear();
if (this.Capacity > 8000 && Capacity < this.Capacity)
this.Capacity = Capacity;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} }
/// <summary> /// <summary>
@ -323,15 +298,19 @@ namespace Flow.Launcher.ViewModel
if (editTime < 10 || newItems.Count < 30) if (editTime < 10 || newItems.Count < 30)
{ {
if (Count != 0) ClearItems(); if (Count != 0) RemoveAll(newItems.Count);
AddRange(newItems); AddAll(newItems);
editTime++; editTime++;
return; return;
} }
else else
{ {
Clear(); Clear();
BulkAddRange(newItems); BulkAddAll(newItems);
if (Capacity > 8000 && newItems.Count < 3000)
{
Capacity = newItems.Count;
}
editTime++; editTime++;
} }
} }

View file

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
{ {
@ -16,14 +17,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
resultManager = new ResultManager(context); resultManager = new ResultManager(context);
} }
internal List<Result> TopLevelDirectorySearch(Query query, string search) internal List<Result> TopLevelDirectorySearch(Query query, string search, CancellationToken token)
{ {
var criteria = ConstructSearchCriteria(search); var criteria = ConstructSearchCriteria(search);
if (search.LastIndexOf(Constants.AllFilesFolderSearchWildcard) > search.LastIndexOf(Constants.DirectorySeperator)) if (search.LastIndexOf(Constants.AllFilesFolderSearchWildcard) >
return DirectorySearch(SearchOption.AllDirectories, query, search, criteria); search.LastIndexOf(Constants.DirectorySeperator))
return DirectorySearch(new EnumerationOptions
{
RecurseSubdirectories = true
}, query, search, criteria, token);
return DirectorySearch(SearchOption.TopDirectoryOnly, query, search, criteria); return DirectorySearch(new EnumerationOptions(), query, search, criteria, token); // null will be passed as default
} }
public string ConstructSearchCriteria(string search) public string ConstructSearchCriteria(string search)
@ -45,7 +50,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
return incompleteName; return incompleteName;
} }
private List<Result> DirectorySearch(SearchOption searchOption, Query query, string search, string searchCriteria) private List<Result> DirectorySearch(EnumerationOptions enumerationOption, Query query, string search,
string searchCriteria, CancellationToken token)
{ {
var results = new List<Result>(); var results = new List<Result>();
@ -58,37 +64,37 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
{ {
var directoryInfo = new System.IO.DirectoryInfo(path); var directoryInfo = new System.IO.DirectoryInfo(path);
foreach (var fileSystemInfo in directoryInfo.EnumerateFileSystemInfos(searchCriteria, searchOption)) foreach (var fileSystemInfo in directoryInfo.EnumerateFileSystemInfos(searchCriteria, enumerationOption))
{ {
if ((fileSystemInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
if (fileSystemInfo is System.IO.DirectoryInfo) if (fileSystemInfo is System.IO.DirectoryInfo)
{ {
folderList.Add(resultManager.CreateFolderResult(fileSystemInfo.Name, fileSystemInfo.FullName, fileSystemInfo.FullName, query, true, false)); folderList.Add(resultManager.CreateFolderResult(fileSystemInfo.Name, fileSystemInfo.FullName,
fileSystemInfo.FullName, query, true, false));
} }
else else
{ {
fileList.Add(resultManager.CreateFileResult(fileSystemInfo.FullName, query, true, false)); fileList.Add(resultManager.CreateFileResult(fileSystemInfo.FullName, query, true, false));
} }
token.ThrowIfCancellationRequested();
} }
} }
catch (Exception e) catch (Exception e)
{ {
if (e is UnauthorizedAccessException || e is ArgumentException) if (!(e is ArgumentException))
{ throw e;
results.Add(new Result { Title = e.Message, Score = 501 });
return results; results.Add(new Result {Title = e.Message, Score = 501});
}
return results;
#if DEBUG // Please investigate and handle error from DirectoryInfo search #if DEBUG // Please investigate and handle error from DirectoryInfo search
throw e;
#else #else
Log.Exception($"|Flow.Launcher.Plugin.Explorer.DirectoryInfoSearch|Error from performing DirectoryInfoSearch", e); Log.Exception($"|Flow.Launcher.Plugin.Explorer.DirectoryInfoSearch|Error from performing DirectoryInfoSearch", e);
#endif #endif
} }
// Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection. // Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList(); return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList();
} }
} }

View file

@ -6,25 +6,31 @@ namespace Flow.Launcher.Plugin.Explorer.Search.FolderLinks
{ {
public class QuickFolderAccess public class QuickFolderAccess
{ {
internal List<Result> FolderListMatched(Query query, List<FolderLink> folderLinks, PluginInitContext context) private readonly ResultManager resultManager;
public QuickFolderAccess(PluginInitContext context)
{
resultManager = new ResultManager(context);
}
internal List<Result> FolderListMatched(Query query, List<FolderLink> folderLinks)
{ {
if (string.IsNullOrEmpty(query.Search)) if (string.IsNullOrEmpty(query.Search))
return new List<Result>(); return new List<Result>();
string search = query.Search.ToLower(); string search = query.Search.ToLower();
var queriedFolderLinks = folderLinks.Where(x => x.Nickname.StartsWith(search, StringComparison.OrdinalIgnoreCase)); var queriedFolderLinks =
folderLinks.Where(x => x.Nickname.StartsWith(search, StringComparison.OrdinalIgnoreCase));
return queriedFolderLinks.Select(item => return queriedFolderLinks.Select(item =>
new ResultManager(context) resultManager.CreateFolderResult(item.Nickname, item.Path, item.Path, query))
.CreateFolderResult(item.Nickname, item.Path, item.Path, query)) .ToList();
.ToList();
} }
internal List<Result> FolderListAll(Query query, List<FolderLink> folderLinks, PluginInitContext context) internal List<Result> FolderListAll(Query query, List<FolderLink> folderLinks)
=> folderLinks => folderLinks
.Select(item => .Select(item => resultManager.CreateFolderResult(item.Nickname, item.Path, item.Path, query))
new ResultManager(context).CreateFolderResult(item.Nickname, item.Path, item.Path, query))
.ToList(); .ToList();
} }
} }

View file

@ -16,7 +16,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
private readonly IndexSearch indexSearch; private readonly IndexSearch indexSearch;
private readonly QuickFolderAccess quickFolderAccess = new QuickFolderAccess(); private readonly QuickFolderAccess quickFolderAccess;
private readonly ResultManager resultManager; private readonly ResultManager resultManager;
@ -28,6 +28,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
indexSearch = new IndexSearch(context); indexSearch = new IndexSearch(context);
resultManager = new ResultManager(context); resultManager = new ResultManager(context);
this.settings = settings; this.settings = settings;
quickFolderAccess = new QuickFolderAccess(context);
} }
internal async Task<List<Result>> SearchAsync(Query query, CancellationToken token) internal async Task<List<Result>> SearchAsync(Query query, CancellationToken token)
@ -40,12 +41,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return await WindowsIndexFileContentSearchAsync(query, querySearch, token).ConfigureAwait(false); return await WindowsIndexFileContentSearchAsync(query, querySearch, token).ConfigureAwait(false);
// This allows the user to type the assigned action keyword and only see the list of quick folder links // This allows the user to type the assigned action keyword and only see the list of quick folder links
if (settings.QuickFolderAccessLinks.Count > 0 if (string.IsNullOrEmpty(query.Search))
&& query.ActionKeyword == settings.SearchActionKeyword return quickFolderAccess.FolderListAll(query, settings.QuickFolderAccessLinks);
&& string.IsNullOrEmpty(query.Search))
return quickFolderAccess.FolderListAll(query, settings.QuickFolderAccessLinks, context);
var quickFolderLinks = quickFolderAccess.FolderListMatched(query, settings.QuickFolderAccessLinks, context); var quickFolderLinks = quickFolderAccess.FolderListMatched(query, settings.QuickFolderAccessLinks);
if (quickFolderLinks.Count > 0) if (quickFolderLinks.Count > 0)
results.AddRange(quickFolderLinks); results.AddRange(quickFolderLinks);
@ -78,15 +77,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search
results.Add(resultManager.CreateOpenCurrentFolderResult(locationPath, useIndexSearch)); results.Add(resultManager.CreateOpenCurrentFolderResult(locationPath, useIndexSearch));
if (token.IsCancellationRequested) token.ThrowIfCancellationRequested();
return null;
results.AddRange(await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync, var directoryResult = await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync,
DirectoryInfoClassSearch, DirectoryInfoClassSearch,
useIndexSearch, useIndexSearch,
query, query,
locationPath, locationPath,
token).ConfigureAwait(false)); token).ConfigureAwait(false);
token.ThrowIfCancellationRequested();
results.AddRange(directoryResult);
return results; return results;
} }
@ -110,23 +112,23 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return actionKeyword == settings.FileContentSearchActionKeyword; return actionKeyword == settings.FileContentSearchActionKeyword;
} }
private List<Result> DirectoryInfoClassSearch(Query query, string querySearch) private List<Result> DirectoryInfoClassSearch(Query query, string querySearch, CancellationToken token)
{ {
var directoryInfoSearch = new DirectoryInfoSearch(context); var directoryInfoSearch = new DirectoryInfoSearch(context);
return directoryInfoSearch.TopLevelDirectorySearch(query, querySearch); return directoryInfoSearch.TopLevelDirectorySearch(query, querySearch, token);
} }
public async Task<List<Result>> TopLevelDirectorySearchBehaviourAsync( public async Task<List<Result>> TopLevelDirectorySearchBehaviourAsync(
Func<Query, string, CancellationToken, Task<List<Result>>> windowsIndexSearch, Func<Query, string, CancellationToken, Task<List<Result>>> windowsIndexSearch,
Func<Query, string, List<Result>> directoryInfoClassSearch, Func<Query, string, CancellationToken, List<Result>> directoryInfoClassSearch,
bool useIndexSearch, bool useIndexSearch,
Query query, Query query,
string querySearchString, string querySearchString,
CancellationToken token) CancellationToken token)
{ {
if (!useIndexSearch) if (!useIndexSearch)
return directoryInfoClassSearch(query, querySearchString); return directoryInfoClassSearch(query, querySearchString, token);
return await windowsIndexSearch(query, querySearchString, token); return await windowsIndexSearch(query, querySearchString, token);
} }

View file

@ -7,7 +7,7 @@
"Name": "Explorer", "Name": "Explorer",
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search", "Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
"Author": "Jeremy Wu", "Author": "Jeremy Wu",
"Version": "1.4.1", "Version": "1.5.0",
"Language": "csharp", "Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher", "Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll", "ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",

View file

@ -2,6 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_url_open_search_in">Open search in:</system:String>
<system:String x:Key="flowlauncher_plugin_new_window">New Window</system:String>
<system:String x:Key="flowlauncher_plugin_new_tab">New Tab</system:String>
<system:String x:Key="flowlauncher_plugin_url_open_url">Open url:{0}</system:String> <system:String x:Key="flowlauncher_plugin_url_open_url">Open url:{0}</system:String>
<system:String x:Key="flowlauncher_plugin_url_canot_open_url">Can't open url:{0}</system:String> <system:String x:Key="flowlauncher_plugin_url_canot_open_url">Can't open url:{0}</system:String>

View file

@ -10,11 +10,11 @@
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0"> <StackPanel Orientation="Horizontal" Grid.Row="0">
<Label Content="Open search in:" Margin="0 10 15 0" /> <Label Content="{DynamicResource flowlauncher_plugin_url_open_search_in}" Margin="0 10 15 0" />
<RadioButton x:Name="NewWindowBrowser" GroupName="OpenSearchBehaviour" <RadioButton x:Name="NewWindowBrowser" GroupName="OpenSearchBehaviour"
Content="New window" Click="OnNewBrowserWindowClick" /> Content="{DynamicResource flowlauncher_plugin_new_window}" Click="OnNewBrowserWindowClick" />
<RadioButton x:Name="NewTabInBrowser" GroupName="OpenSearchBehaviour" <RadioButton x:Name="NewTabInBrowser" GroupName="OpenSearchBehaviour"
Content="New tab" Click="OnNewTabClick" /> Content="{DynamicResource flowlauncher_plugin_new_tab}" Click="OnNewTabClick" />
</StackPanel> </StackPanel>
<StackPanel VerticalAlignment="Top" Grid.Row="1" Height="106" Margin="0 20 0 0"> <StackPanel VerticalAlignment="Top" Grid.Row="1" Height="106" Margin="0 20 0 0">
<Label Content="{DynamicResource flowlauncher_plugin_url_plugin_set_tip}" Height="28" Margin="0,0,155,0" <Label Content="{DynamicResource flowlauncher_plugin_url_plugin_set_tip}" Height="28" Margin="0,0,155,0"

View file

@ -4,7 +4,7 @@
"Name": "URL", "Name": "URL",
"Description": "Open the typed URL from Flow Launcher", "Description": "Open the typed URL from Flow Launcher",
"Author": "qianlifeng", "Author": "qianlifeng",
"Version": "1.1.2", "Version": "1.1.3",
"Language": "csharp", "Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher", "Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Url.dll", "ExecuteFileName": "Flow.Launcher.Plugin.Url.dll",

View file

@ -2,6 +2,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_websearch_open_search_in">Open search in:</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_new_window">New Window</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_new_tab">New Tab</system:String>
<system:String x:Key="flowlaucnher_plugin_websearch_set_browser_path">Set browser from path:</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_choose">Choose</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_delete">Delete</system:String> <system:String x:Key="flowlauncher_plugin_websearch_delete">Delete</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_edit">Edit</system:String> <system:String x:Key="flowlauncher_plugin_websearch_edit">Edit</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_add">Add</system:String> <system:String x:Key="flowlauncher_plugin_websearch_add">Add</system:String>

View file

@ -33,17 +33,17 @@
<!-- Not sure why binding IsEnabled directly to Settings.EnableWebSaerchSuggestion is not working --> <!-- Not sure why binding IsEnabled directly to Settings.EnableWebSaerchSuggestion is not working -->
</StackPanel> </StackPanel>
<StackPanel Grid.Row="1" HorizontalAlignment="Left" Orientation="Horizontal"> <StackPanel Grid.Row="1" HorizontalAlignment="Left" Orientation="Horizontal">
<Label Content="Open search in:" Margin="0 15 20 0"/> <Label Content="{DynamicResource flowlauncher_plugin_websearch_open_search_in}" Margin="0 15 20 0"/>
<RadioButton Name="NewWindowBrowser" GroupName="OpenSearchBehaviour" Content="New window" Click="OnNewBrowserWindowClick" <RadioButton Name="NewWindowBrowser" GroupName="OpenSearchBehaviour" Content="{DynamicResource flowlauncher_plugin_websearch_new_window}" Click="OnNewBrowserWindowClick"
Margin="0 0 20 0"/> Margin="0 0 20 0"/>
<RadioButton Name="NewTabInBrowser" GroupName="OpenSearchBehaviour" Content="New tab" Click="OnNewTabClick" /> <RadioButton Name="NewTabInBrowser" GroupName="OpenSearchBehaviour" Content="{DynamicResource flowlauncher_plugin_websearch_new_tab}" Click="OnNewTabClick" />
</StackPanel> </StackPanel>
<StackPanel Grid.Row="2" HorizontalAlignment="Left" Margin="0 3 0 0"> <StackPanel Grid.Row="2" HorizontalAlignment="Left" Margin="0 3 0 0">
<Label Content="Set browser from path:" Margin="0 0 350 0" HorizontalAlignment="Left" Width="140"/> <Label Content="{DynamicResource flowlaucnher_plugin_websearch_set_browser_path}" Margin="0 0 350 0" HorizontalAlignment="Left" Width="140"/>
<TextBox x:Name="browserPathBox" HorizontalAlignment="Left" Margin="160,-22,0,0" TextChanged="OnBrowserPathTextChanged" <TextBox x:Name="browserPathBox" HorizontalAlignment="Left" Margin="160,-22,0,0" TextChanged="OnBrowserPathTextChanged"
Width="214" Style="{StaticResource BrowserPathBoxStyle}"/> Width="214" Style="{StaticResource BrowserPathBoxStyle}"/>
<Button x:Name="viewButton" HorizontalAlignment="Left" Margin="400,-30,0,0" <Button x:Name="viewButton" HorizontalAlignment="Left" Margin="400,-30,0,0"
Click="OnChooseClick" FontSize="13" Content="Choose" Width="80"/> Click="OnChooseClick" FontSize="13" Content="{DynamicResource flowlauncher_plugin_websearch_choose}" Width="80"/>
</StackPanel> </StackPanel>
<ListView ItemsSource="{Binding Settings.SearchSources}" <ListView ItemsSource="{Binding Settings.SearchSources}"
SelectedItem="{Binding Settings.SelectedSearchSource}" SelectedItem="{Binding Settings.SelectedSearchSource}"

View file

@ -25,7 +25,7 @@
"Name": "Web Searches", "Name": "Web Searches",
"Description": "Provide the web search ability", "Description": "Provide the web search ability",
"Author": "qianlifeng", "Author": "qianlifeng",
"Version": "1.3.0", "Version": "1.3.1",
"Language": "csharp", "Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher", "Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll", "ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll",