From c63c98645cde289842ecabbc39b92ae2ddb3b277 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 18 Oct 2020 21:17:29 +0800
Subject: [PATCH 001/308] Add Acronym Support for Fuzzy Search
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 48 ++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 2a4270fb4..f15e22494 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -54,9 +54,55 @@ namespace Flow.Launcher.Infrastructure
stringToCompare = _alphabet.Translate(stringToCompare);
}
+ // This also can be done by spliting the query
+
+ //(var spaceSplit, var upperSplit) = stringToCompare switch
+ //{
+ // string s when s.Contains(' ') => (s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(w => w.First()),
+ // default(IEnumerable)),
+ // string s when s.Any(c => char.IsUpper(c)) && s.Any(c => char.IsLower(c)) =>
+ // (null, Regex.Split(s, @"(? w.First())),
+ // _ => ((IEnumerable)null, (IEnumerable)null)
+ //};
+
+ var currentQueryIndex = 0;
+ var acronymMatchData = new List();
+ var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
+
+ int acronymScore = 100;
+
+ for (int compareIndex = 0; compareIndex < stringToCompare.Length; compareIndex++)
+ {
+ if (currentQueryIndex >= queryWithoutCase.Length)
+ break;
+
+ if (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
+ {
+ acronymMatchData.Add(compareIndex);
+ currentQueryIndex++;
+ continue;
+ }
+
+ switch (stringToCompare[compareIndex])
+ {
+ case char c when (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
+ || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex]):
+ acronymMatchData.Add(compareIndex);
+ currentQueryIndex++;
+ continue;
+
+ case char c when char.IsWhiteSpace(c):
+ compareIndex++;
+ acronymScore -= 10;
+ break;
+ case char c when char.IsUpper(c):
+ acronymScore -= 10;
+ break;
+ }
+ }
+
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
- var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int currentQuerySubstringIndex = 0;
From e264af500fa129e74e6f22c6a2a283bf7d11560c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 18 Oct 2020 21:24:59 +0800
Subject: [PATCH 002/308] merge one extra condition to the switch case
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index f15e22494..cca6388f9 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -76,16 +76,11 @@ namespace Flow.Launcher.Infrastructure
if (currentQueryIndex >= queryWithoutCase.Length)
break;
- if (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
- {
- acronymMatchData.Add(compareIndex);
- currentQueryIndex++;
- continue;
- }
switch (stringToCompare[compareIndex])
{
- case char c when (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
+ case char c when compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex])
+ || (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
|| (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex]):
acronymMatchData.Add(compareIndex);
currentQueryIndex++;
From 9ad78387293b2b3574487d32edabadd50cce055a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 18 Oct 2020 21:24:59 +0800
Subject: [PATCH 003/308] merge one extra condition to the switch case
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index f15e22494..6d70fff30 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -76,16 +76,11 @@ namespace Flow.Launcher.Infrastructure
if (currentQueryIndex >= queryWithoutCase.Length)
break;
- if (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
- {
- acronymMatchData.Add(compareIndex);
- currentQueryIndex++;
- continue;
- }
switch (stringToCompare[compareIndex])
{
- case char c when (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
+ case char c when (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
+ || (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
|| (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex]):
acronymMatchData.Add(compareIndex);
currentQueryIndex++;
From 468f8899b95d40764a941afd0eecff251ee5dc2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 18 Oct 2020 21:31:08 +0800
Subject: [PATCH 004/308] Add return statement....
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 6d70fff30..d09bcaf26 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -96,6 +96,9 @@ namespace Flow.Launcher.Infrastructure
}
}
+ if (acronymMatchData.Count == query.Length && acronymScore >= 60)
+ return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
+
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
From 4d06187fa561bad1e126d513bce15b67d1d3d114 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 20 Oct 2020 08:28:05 +0800
Subject: [PATCH 005/308] use ?. and ?? instead of if == null
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index d09bcaf26..7b44b09c9 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -48,11 +48,7 @@ namespace Flow.Launcher.Infrastructure
query = query.Trim();
- if (_alphabet != null)
- {
- query = _alphabet.Translate(query);
- stringToCompare = _alphabet.Translate(stringToCompare);
- }
+ stringToCompare = _alphabet?.Translate(stringToCompare) ?? stringToCompare;
// This also can be done by spliting the query
From 706f30a3a2c3b0aa74b67c30c0c42a41fe1fcd5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 24 Oct 2020 17:45:31 +0800
Subject: [PATCH 006/308] Add number support (treat number as part of acronuym)
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 7b44b09c9..96391f1d6 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -44,8 +44,8 @@ namespace Flow.Launcher.Infrastructure
///
public MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt)
{
- if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult (false, UserSettingSearchPrecision);
-
+ if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult(false, UserSettingSearchPrecision);
+
query = query.Trim();
stringToCompare = _alphabet?.Translate(stringToCompare) ?? stringToCompare;
@@ -77,7 +77,8 @@ namespace Flow.Launcher.Infrastructure
{
case char c when (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
|| (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
- || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex]):
+ || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex])
+ || (char.IsNumber(c) && c == queryWithoutCase[currentQueryIndex]):
acronymMatchData.Add(compareIndex);
currentQueryIndex++;
continue;
@@ -86,7 +87,7 @@ namespace Flow.Launcher.Infrastructure
compareIndex++;
acronymScore -= 10;
break;
- case char c when char.IsUpper(c):
+ case char c when char.IsUpper(c) || char.IsNumber(c):
acronymScore -= 10;
break;
}
@@ -97,7 +98,7 @@ namespace Flow.Launcher.Infrastructure
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
-
+
var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int currentQuerySubstringIndex = 0;
var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
@@ -180,7 +181,7 @@ namespace Flow.Launcher.Infrastructure
currentQuerySubstringCharacterIndex = 0;
}
}
-
+
// proceed to calculate score if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
{
@@ -223,7 +224,7 @@ namespace Flow.Launcher.Infrastructure
return allMatch;
}
-
+
private static List GetUpdatedIndexList(int startIndexToVerify, int currentQuerySubstringCharacterIndex, int firstMatchIndexInWord, List indexList)
{
var updatedList = new List();
From 9d2164962292104aa9f33bdaef74fb8871208549 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 10 Nov 2020 17:13:45 +0800
Subject: [PATCH 007/308] Change UI rendering logic
Co-authored-by: Bao-Qian
---
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/ViewModel/MainViewModel.cs | 24 +++++-
Flow.Launcher/ViewModel/ResultsForUpdate.cs | 36 +++++++++
Flow.Launcher/ViewModel/ResultsViewModel.cs | 89 ++++++++-------------
4 files changed, 92 insertions(+), 59 deletions(-)
create mode 100644 Flow.Launcher/ViewModel/ResultsForUpdate.cs
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 3280dc457..60d94a37b 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -42,7 +42,7 @@
+ Source="{Binding Image}" />
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index f18b74022..ac2cc79d5 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -21,6 +21,7 @@ using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Storage;
using System.Windows.Media;
using Flow.Launcher.Infrastructure.Image;
+using System.Collections.Concurrent;
namespace Flow.Launcher.ViewModel
{
@@ -47,6 +48,8 @@ namespace Flow.Launcher.ViewModel
private bool _saved;
private readonly Internationalization _translator = InternationalizationManager.Instance;
+ private BlockingCollection _resultsUpdateQueue;
+
#endregion
@@ -76,6 +79,8 @@ namespace Flow.Launcher.ViewModel
InitializeKeyCommands();
RegisterResultsUpdatedEvent();
+ RegisterResultUpdate();
+
SetHotkey(_settings.Hotkey, OnHotkey);
SetCustomPluginHotkey();
SetOpenResultModifiers();
@@ -91,12 +96,27 @@ namespace Flow.Launcher.ViewModel
Task.Run(() =>
{
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
- UpdateResultView(e.Results, pair.Metadata, e.Query);
+ _resultsUpdateQueue.Add(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken));
}, _updateToken);
};
}
}
+ private void RegisterResultUpdate()
+ {
+ _resultsUpdateQueue = new BlockingCollection();
+
+ Task.Run(() =>
+ {
+ while (true)
+ {
+ var resultToUpdate = _resultsUpdateQueue.Take();
+ if (!resultToUpdate.Token.IsCancellationRequested)
+ UpdateResultView(resultToUpdate.Results, resultToUpdate.Metadata, resultToUpdate.Query);
+ }
+ });
+ }
+
private void InitializeKeyCommands()
{
@@ -415,7 +435,7 @@ namespace Flow.Launcher.ViewModel
if (!plugin.Metadata.Disabled)
{
var results = PluginManager.QueryForPlugin(plugin, query);
- UpdateResultView(results, plugin.Metadata, query);
+ _resultsUpdateQueue.Add(new ResultsForUpdate(results, plugin.Metadata, query, _updateToken));
}
});
}
diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs
new file mode 100644
index 000000000..29f626285
--- /dev/null
+++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs
@@ -0,0 +1,36 @@
+using Flow.Launcher.Plugin;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace Flow.Launcher.ViewModel
+{
+ class ResultsForUpdate
+ {
+ public List Results { get; }
+
+ public PluginMetadata Metadata { get; }
+ public string ID { get; }
+
+ public Query Query { get; }
+ public CancellationToken Token { get; }
+
+ public ResultsForUpdate(List results, string resultID, CancellationToken token)
+ {
+ Results = results;
+ ID = resultID;
+ Token = token;
+ }
+
+
+ public ResultsForUpdate(List results, PluginMetadata metadata, Query query, CancellationToken token)
+ {
+ Results = results;
+ Metadata = metadata;
+ Query = query;
+ Token = token;
+ ID = metadata.ID;
+ }
+ }
+}
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index d30854180..ac435c494 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -17,7 +17,6 @@ namespace Flow.Launcher.ViewModel
public ResultCollection Results { get; }
- private readonly object _addResultsLock = new object();
private readonly object _collectionLock = new object();
private readonly Settings _settings;
private int MaxResults => _settings?.MaxResultsToShow ?? 6;
@@ -134,70 +133,37 @@ namespace Flow.Launcher.ViewModel
///
public void AddResults(List newRawResults, string resultId)
{
- lock (_addResultsLock)
+ var newResults = NewResults(newRawResults, resultId);
+
+ // update UI in one run, so it can avoid UI flickering
+ Results.Update(newResults);
+
+ if (Results.Count > 0)
{
- var newResults = NewResults(newRawResults, resultId);
-
- // update UI in one run, so it can avoid UI flickering
- Results.Update(newResults);
-
- if (Results.Count > 0)
- {
- Margin = new Thickness { Top = 8 };
- SelectedIndex = 0;
- }
- else
- {
- Margin = new Thickness { Top = 0 };
- }
+ Margin = new Thickness { Top = 8 };
+ SelectedIndex = 0;
+ }
+ else
+ {
+ Margin = new Thickness { Top = 0 };
}
}
private List NewResults(List newRawResults, string resultId)
{
- var results = Results.ToList();
+ if (newRawResults.Count == 0)
+ return Results.ToList();
+
+ var results = Results as IEnumerable;
+
var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList();
- var oldResults = results.Where(r => r.Result.PluginID == resultId).ToList();
- // Find the same results in A (old results) and B (new newResults)
- var sameResults = oldResults
- .Where(t1 => newResults.Any(x => x.Result.Equals(t1.Result)))
- .ToList();
- // remove result of relative complement of B in A
- foreach (var result in oldResults.Except(sameResults))
- {
- results.Remove(result);
- }
-
- // update result with B's score and index position
- foreach (var sameResult in sameResults)
- {
- int oldIndex = results.IndexOf(sameResult);
- int oldScore = results[oldIndex].Result.Score;
- var newResult = newResults[newResults.IndexOf(sameResult)];
- int newScore = newResult.Result.Score;
- if (newScore != oldScore)
- {
- var oldResult = results[oldIndex];
-
- oldResult.Result.Score = newScore;
- oldResult.Result.OriginQuery = newResult.Result.OriginQuery;
-
- results.RemoveAt(oldIndex);
- int newIndex = InsertIndexOf(newScore, results);
- results.Insert(newIndex, oldResult);
- }
- }
-
- // insert result in relative complement of A in B
- foreach (var result in newResults.Except(sameResults))
- {
- int newIndex = InsertIndexOf(result.Result.Score, results);
- results.Insert(newIndex, result);
- }
-
- return results;
+ return results.Where(r => r.Result.PluginID != resultId)
+ .Concat(newResults)
+ .OrderByDescending(r => r.Result.Score)
+ .Take(MaxResults * 2)
+ .ToList();
}
#endregion
@@ -254,6 +220,17 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems)
{
+ ClearItems();
+
+ foreach (var item in newItems)
+ {
+ Add(item);
+ }
+
+
+
+ return;
+
int newCount = newItems.Count;
int oldCount = Items.Count;
int location = newCount > oldCount ? oldCount : newCount;
From 0e0f24f635bcbe4723692fe649c6ae475da34786 Mon Sep 17 00:00:00 2001
From: Qian Bao
Date: Fri, 23 Oct 2020 10:45:22 +0800
Subject: [PATCH 008/308] Lazy Load Image
---
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/ViewModel/ResultViewModel.cs | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 60d94a37b..072196605 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -42,7 +42,7 @@
+ Source="{Binding Image.Value}" />
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index a4fe2ede4..a64836285 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -18,6 +18,7 @@ namespace Flow.Launcher.ViewModel
if (result != null)
{
Result = result;
+ Image = new Lazy(() => SetImage);
}
Settings = settings;
@@ -36,8 +37,10 @@ namespace Flow.Launcher.ViewModel
public string ShowSubTitleToolTip => string.IsNullOrEmpty(Result.SubTitleToolTip)
? Result.SubTitle
: Result.SubTitleToolTip;
+
+ public Lazy Image { get; set; }
- public ImageSource Image
+ private ImageSource SetImage
{
get
{
@@ -75,6 +78,7 @@ namespace Flow.Launcher.ViewModel
}
}
+
public override int GetHashCode()
{
return Result.GetHashCode();
From 52887aacf04e2f98de33e7caf21d2226924a0535 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 11 Nov 2020 18:36:01 +0800
Subject: [PATCH 009/308] Batch process ui change with interval 50ms
---
Flow.Launcher/ViewModel/MainViewModel.cs | 46 +++++++--
Flow.Launcher/ViewModel/ResultsForUpdate.cs | 2 +-
Flow.Launcher/ViewModel/ResultsViewModel.cs | 107 ++++++++++----------
3 files changed, 93 insertions(+), 62 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index ac2cc79d5..0a1ef8d81 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -106,13 +106,25 @@ namespace Flow.Launcher.ViewModel
{
_resultsUpdateQueue = new BlockingCollection();
- Task.Run(() =>
+ Task.Run(async () =>
{
while (true)
{
- var resultToUpdate = _resultsUpdateQueue.Take();
- if (!resultToUpdate.Token.IsCancellationRequested)
- UpdateResultView(resultToUpdate.Results, resultToUpdate.Metadata, resultToUpdate.Query);
+ List queue = new List() { _resultsUpdateQueue.Take() };
+ await Task.Delay(50);
+
+ while (_resultsUpdateQueue.TryTake(out var resultsForUpdate))
+ {
+ queue.Add(resultsForUpdate);
+ }
+
+ //foreach (var update in queue)
+ //{
+ // UpdateResultView(update.Results, update.Metadata, update.Query);
+ //}
+
+ UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested));
+
}
});
}
@@ -412,7 +424,7 @@ namespace Flow.Launcher.ViewModel
if (query != null)
{
// handle the exclusiveness of plugin using action keyword
- RemoveOldQueryResults(query);
+ // RemoveOldQueryResults(query);
_lastQuery = query;
Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
@@ -443,7 +455,7 @@ namespace Flow.Launcher.ViewModel
{
// nothing to do here
}
-
+
// this should happen once after all queries are done so progress bar should continue
// until the end of all querying
@@ -459,6 +471,7 @@ namespace Flow.Launcher.ViewModel
{
Results.Clear();
Results.Visbility = Visibility.Collapsed;
+
}
}
@@ -683,6 +696,23 @@ namespace Flow.Launcher.ViewModel
}
}
+ public void UpdateResultView(IEnumerable resultsForUpdates)
+ {
+ foreach (var result in resultsForUpdates.SelectMany(u => u.Results))
+ {
+ if (_topMostRecord.IsTopMost(result))
+ {
+ result.Score = int.MaxValue;
+ }
+ else
+ {
+ result.Score += _userSelectedRecord.GetSelectedCount(result) * 5;
+ }
+ }
+
+ Results.AddResults(resultsForUpdates);
+ }
+
///
/// To avoid deadlock, this method should not called from main thread
///
@@ -705,10 +735,6 @@ namespace Flow.Launcher.ViewModel
Results.AddResults(list, metadata.ID);
}
- if (Results.Visbility != Visibility.Visible && list.Count > 0)
- {
- Results.Visbility = Visibility.Visible;
- }
}
#endregion
diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs
index 29f626285..2257d35b0 100644
--- a/Flow.Launcher/ViewModel/ResultsForUpdate.cs
+++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs
@@ -6,7 +6,7 @@ using System.Threading;
namespace Flow.Launcher.ViewModel
{
- class ResultsForUpdate
+ public class ResultsForUpdate
{
public List Results { get; }
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index ac435c494..d06a390c5 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@@ -115,19 +116,20 @@ namespace Flow.Launcher.ViewModel
public void Clear()
{
- Results.Clear();
+ Results.RemoveAll();
}
public void RemoveResultsExcept(PluginMetadata metadata)
{
- Results.RemoveAll(r => r.Result.PluginID != metadata.ID);
+ //Results.RemoveAll(r => r.Result.PluginID != metadata.ID);
}
public void RemoveResultsFor(PluginMetadata metadata)
{
- Results.RemoveAll(r => r.Result.PluginID == metadata.ID);
+ //Results.RemoveAll(r => r.Result.PluginID == metadata.ID);
}
+
///
/// To avoid deadlock, this method should not called from main thread
///
@@ -138,16 +140,44 @@ namespace Flow.Launcher.ViewModel
// update UI in one run, so it can avoid UI flickering
Results.Update(newResults);
- if (Results.Count > 0)
+ 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;
}
}
+ ///
+ /// To avoid deadlock, this method should not called from main thread
+ ///
+ public void AddResults(IEnumerable resultsForUpdates)
+ {
+ var newResults = NewResults(resultsForUpdates);
+ lock (_collectionLock)
+ {
+ Results.Update(newResults);
+ }
+
+ switch (Visbility)
+ {
+ case Visibility.Collapsed when Results.Count > 0:
+ Margin = new Thickness { Top = 8 };
+ SelectedIndex = 0;
+ Visbility = Visibility.Visible;
+ break;
+ case Visibility.Visible when Results.Count == 0:
+ Margin = new Thickness { Top = 0 };
+ Visbility = Visibility.Collapsed;
+ break;
+
+ }
+ }
+
private List NewResults(List newRawResults, string resultId)
{
@@ -165,8 +195,25 @@ namespace Flow.Launcher.ViewModel
.Take(MaxResults * 2)
.ToList();
}
+
+ private List NewResults(IEnumerable resultsForUpdates)
+ {
+ if (!resultsForUpdates.Any())
+ return Results.ToList();
+
+ var results = Results as IEnumerable;
+
+ return results.Where(r => !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID))
+ .Concat(resultsForUpdates
+ .SelectMany(u => u.Results)
+ .Select(r => new ResultViewModel(r, _settings)))
+ .OrderByDescending(rv => rv.Result.Score)
+ .Take(MaxResults * 2)
+ .ToList();
+ }
#endregion
+
#region FormattedText Dependency Property
public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
"FormattedText",
@@ -198,20 +245,12 @@ namespace Flow.Launcher.ViewModel
}
#endregion
- public class ResultCollection : ObservableCollection
+ public class ResultCollection : ObservableCollection, INotifyCollectionChanged
{
-
- public void RemoveAll(Predicate predicate)
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+ public void RemoveAll()
{
- CheckReentrancy();
-
- for (int i = Count - 1; i >= 0; i--)
- {
- if (predicate(this[i]))
- {
- RemoveAt(i);
- }
- }
+ ClearItems();
}
///
@@ -226,44 +265,10 @@ namespace Flow.Launcher.ViewModel
{
Add(item);
}
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
-
return;
- int newCount = newItems.Count;
- int oldCount = Items.Count;
- int location = newCount > oldCount ? oldCount : newCount;
-
- for (int i = 0; i < location; i++)
- {
- ResultViewModel oldResult = this[i];
- ResultViewModel newResult = newItems[i];
- if (!oldResult.Equals(newResult))
- { // result is not the same update it in the current index
- this[i] = newResult;
- }
- else if (oldResult.Result.Score != newResult.Result.Score)
- {
- this[i].Result.Score = newResult.Result.Score;
- }
- }
-
-
- if (newCount >= oldCount)
- {
- for (int i = oldCount; i < newCount; i++)
- {
- Add(newItems[i]);
- }
- }
- else
- {
- for (int i = oldCount - 1; i >= newCount; i--)
- {
- RemoveAt(i);
- }
- }
}
}
}
From ebddf19ba21beccd961c3ad245640053e50fda3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 11 Nov 2020 19:06:05 +0800
Subject: [PATCH 010/308] Fix not canceled token and adding comment
Co-authored-by: bao-qian
---
Flow.Launcher/ViewModel/MainViewModel.cs | 6 ++++--
Flow.Launcher/ViewModel/ResultsViewModel.cs | 7 +++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 0a1ef8d81..f71674774 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -469,9 +469,9 @@ namespace Flow.Launcher.ViewModel
}
else
{
+ _updateSource?.Cancel();
Results.Clear();
Results.Visbility = Visibility.Collapsed;
-
}
}
@@ -695,7 +695,9 @@ namespace Flow.Launcher.ViewModel
_saved = true;
}
}
-
+ ///
+ /// To avoid deadlock, this method should not called from main thread
+ ///
public void UpdateResultView(IEnumerable resultsForUpdates)
{
foreach (var result in resultsForUpdates.SelectMany(u => u.Results))
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index d06a390c5..635b20ec6 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -174,7 +174,6 @@ namespace Flow.Launcher.ViewModel
Margin = new Thickness { Top = 0 };
Visbility = Visibility.Collapsed;
break;
-
}
}
@@ -247,7 +246,7 @@ namespace Flow.Launcher.ViewModel
public class ResultCollection : ObservableCollection, INotifyCollectionChanged
{
- public event NotifyCollectionChangedEventHandler CollectionChanged;
+ public override event NotifyCollectionChangedEventHandler CollectionChanged;
public void RemoveAll()
{
ClearItems();
@@ -259,12 +258,16 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems)
{
+
+
ClearItems();
foreach (var item in newItems)
{
Add(item);
}
+
+ // wpf use directx / double buffered already, so just reset all won't cause ui flickering
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return;
From 1b76da175fa210e77dfc178e7007ea7aa2bf5721 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Thu, 12 Nov 2020 15:37:04 +0800
Subject: [PATCH 011/308] Add remove previous query result back to keep
different action word distinct
---
Flow.Launcher/ViewModel/MainViewModel.cs | 8 ++++----
Flow.Launcher/ViewModel/ResultsViewModel.cs | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index f71674774..cd2913570 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -424,7 +424,7 @@ namespace Flow.Launcher.ViewModel
if (query != null)
{
// handle the exclusiveness of plugin using action keyword
- // RemoveOldQueryResults(query);
+ RemoveOldQueryResults(query);
_lastQuery = query;
Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
@@ -483,18 +483,18 @@ namespace Flow.Launcher.ViewModel
{
if (!string.IsNullOrEmpty(keyword))
{
- Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
+ Results.KeepResultsFor(PluginManager.NonGlobalPlugins[keyword].Metadata);
}
}
else
{
if (string.IsNullOrEmpty(keyword))
{
- Results.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword].Metadata);
+ Results.KeepResultsExcept(PluginManager.NonGlobalPlugins[lastKeyword].Metadata);
}
else if (lastKeyword != keyword)
{
- Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
+ Results.KeepResultsFor(PluginManager.NonGlobalPlugins[keyword].Metadata);
}
}
}
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 635b20ec6..3b48c2d32 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -119,14 +119,14 @@ namespace Flow.Launcher.ViewModel
Results.RemoveAll();
}
- public void RemoveResultsExcept(PluginMetadata metadata)
+ public void KeepResultsFor(PluginMetadata metadata)
{
- //Results.RemoveAll(r => r.Result.PluginID != metadata.ID);
+ Results.Update(Results.Where(r => r.Result.PluginID == metadata.ID).ToList());
}
- public void RemoveResultsFor(PluginMetadata metadata)
+ public void KeepResultsExcept(PluginMetadata metadata)
{
- //Results.RemoveAll(r => r.Result.PluginID == metadata.ID);
+ Results.Update(Results.Where(r => r.Result.PluginID != metadata.ID).ToList());
}
From f51d2c57c75dd77fbf30e3c3a26922f906fed792 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Thu, 12 Nov 2020 15:46:24 +0800
Subject: [PATCH 012/308] keep all result in result list view
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 3b48c2d32..038cfb4e3 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -191,7 +191,6 @@ namespace Flow.Launcher.ViewModel
return results.Where(r => r.Result.PluginID != resultId)
.Concat(newResults)
.OrderByDescending(r => r.Result.Score)
- .Take(MaxResults * 2)
.ToList();
}
@@ -207,7 +206,6 @@ namespace Flow.Launcher.ViewModel
.SelectMany(u => u.Results)
.Select(r => new ResultViewModel(r, _settings)))
.OrderByDescending(rv => rv.Result.Score)
- .Take(MaxResults * 2)
.ToList();
}
#endregion
From 4b2abfc7082764325c9fcee407ef7a202cba84a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 13 Nov 2020 13:41:59 +0800
Subject: [PATCH 013/308] Reduce batch time to speed up view update change
selected index update place to fix not first selection issue
---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
Flow.Launcher/ViewModel/ResultsViewModel.cs | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index cd2913570..48e621126 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -111,7 +111,7 @@ namespace Flow.Launcher.ViewModel
while (true)
{
List queue = new List() { _resultsUpdateQueue.Take() };
- await Task.Delay(50);
+ await Task.Delay(30);
while (_resultsUpdateQueue.TryTake(out var resultsForUpdate))
{
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 038cfb4e3..3e464afe1 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -158,6 +158,11 @@ namespace Flow.Launcher.ViewModel
public void AddResults(IEnumerable resultsForUpdates)
{
var newResults = NewResults(resultsForUpdates);
+
+ // https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
+ // fix selected index flow
+ SelectedIndex = 0;
+
lock (_collectionLock)
{
Results.Update(newResults);
@@ -167,7 +172,6 @@ namespace Flow.Launcher.ViewModel
{
case Visibility.Collapsed when Results.Count > 0:
Margin = new Thickness { Top = 8 };
- SelectedIndex = 0;
Visbility = Visibility.Visible;
break;
case Visibility.Visible when Results.Count == 0:
@@ -175,6 +179,7 @@ namespace Flow.Launcher.ViewModel
Visbility = Visibility.Collapsed;
break;
}
+
}
From e625c192ee5b64acba3195a6f7e0b16f0d6f7800 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 13 Nov 2020 19:49:11 +0800
Subject: [PATCH 014/308] remove unused code
---
Flow.Launcher/ViewModel/MainViewModel.cs | 5 -----
1 file changed, 5 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 48e621126..c093495e3 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -118,11 +118,6 @@ namespace Flow.Launcher.ViewModel
queue.Add(resultsForUpdate);
}
- //foreach (var update in queue)
- //{
- // UpdateResultView(update.Results, update.Metadata, update.Query);
- //}
-
UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested));
}
From e34a52c74e778d06e1e538f1cd585c73142bf84e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 12:04:10 +0800
Subject: [PATCH 015/308] Don't change selected index unless collection is not
empty
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 23 +++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 3e464afe1..d62e0d0c3 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -137,8 +137,16 @@ namespace Flow.Launcher.ViewModel
{
var newResults = NewResults(newRawResults, resultId);
- // update UI in one run, so it can avoid UI flickering
- Results.Update(newResults);
+ lock (_collectionLock)
+ {
+ // https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
+ // fix selected index flow
+ if (Results.Count > 0)
+ SelectedIndex = 0;
+
+ // update UI in one run, so it can avoid UI flickering
+ Results.Update(newResults);
+ }
if (Visbility != Visibility.Visible && Results.Count > 0)
{
@@ -159,12 +167,14 @@ namespace Flow.Launcher.ViewModel
{
var newResults = NewResults(resultsForUpdates);
- // https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
- // fix selected index flow
- SelectedIndex = 0;
-
lock (_collectionLock)
{
+ // https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
+ // fix selected index flow
+ if (Results.Count > 0)
+ SelectedIndex = 0;
+
+
Results.Update(newResults);
}
@@ -172,6 +182,7 @@ namespace Flow.Launcher.ViewModel
{
case Visibility.Collapsed when Results.Count > 0:
Margin = new Thickness { Top = 8 };
+ SelectedIndex = 0;
Visbility = Visibility.Visible;
break;
case Visibility.Visible when Results.Count == 0:
From a4147f52c93d8ecd5af31f1b7e8e5130ff26693d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 12:36:29 +0800
Subject: [PATCH 016/308] Block Notifychange unless all the element is added
into the observablecollection This should improve the response speed.
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 36 ++++++++++++++-------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index d62e0d0c3..6210dc54f 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -260,7 +260,30 @@ namespace Flow.Launcher.ViewModel
public class ResultCollection : ObservableCollection, INotifyCollectionChanged
{
+ private bool _suppressNotification = false;
+ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ if (!_suppressNotification)
+ base.OnCollectionChanged(e);
+ }
+
public override event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public void AddRange(IEnumerable Items)
+ {
+ _suppressNotification = true;
+
+ foreach (var item in Items)
+ {
+ Add(item);
+ }
+
+
+ // wpf use directx / double buffered already, so just reset all won't cause ui flickering
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ return;
+
+ }
public void RemoveAll()
{
ClearItems();
@@ -272,20 +295,9 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems)
{
-
-
ClearItems();
- foreach (var item in newItems)
- {
- Add(item);
- }
-
- // wpf use directx / double buffered already, so just reset all won't cause ui flickering
- CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
- return;
-
+ AddRange(newItems);
}
}
}
From dab8c5da957b3d3ad2b34f65ee6c0dcb35b106d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 12:36:29 +0800
Subject: [PATCH 017/308] Block Notifychange unless all the element is added
into the observablecollection This should improve the response speed.
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 37 ++++++++++++++-------
1 file changed, 25 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index d62e0d0c3..4acf71edd 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -260,7 +260,31 @@ namespace Flow.Launcher.ViewModel
public class ResultCollection : ObservableCollection, INotifyCollectionChanged
{
+ private bool _suppressNotification = false;
+ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ {
+ if (!_suppressNotification)
+ base.OnCollectionChanged(e);
+ }
+
public override event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ // https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
+ public void AddRange(IEnumerable Items)
+ {
+ _suppressNotification = true;
+
+ foreach (var item in Items)
+ {
+ Add(item);
+ }
+
+
+ // wpf use directx / double buffered already, so just reset all won't cause ui flickering
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ return;
+
+ }
public void RemoveAll()
{
ClearItems();
@@ -272,20 +296,9 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems)
{
-
-
ClearItems();
- foreach (var item in newItems)
- {
- Add(item);
- }
-
- // wpf use directx / double buffered already, so just reset all won't cause ui flickering
- CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
- return;
-
+ AddRange(newItems);
}
}
}
From 4cf143d435eeaabe61cfe64ade7e47bcbc352a17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 15:07:56 +0800
Subject: [PATCH 018/308] Don't notify change until finishing up adding new
result
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 4acf71edd..438b64d92 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -296,7 +296,7 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems)
{
- ClearItems();
+ Clear();
AddRange(newItems);
}
From 3076e501bfe629e10f96532d4a957187c7a3bb01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 17:09:37 +0800
Subject: [PATCH 019/308] add null check when processing result update
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 438b64d92..5d6887a3f 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -217,10 +217,9 @@ namespace Flow.Launcher.ViewModel
var results = Results as IEnumerable;
- return results.Where(r => !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID))
- .Concat(resultsForUpdates
- .SelectMany(u => u.Results)
- .Select(r => new ResultViewModel(r, _settings)))
+ return results.Where(r => r != null && !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID))
+ .Concat(
+ resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings)))
.OrderByDescending(rv => rv.Result.Score)
.ToList();
}
From 7dc247333ce6fece537e99912f7210b4f453cc54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 14 Nov 2020 17:20:48 +0800
Subject: [PATCH 020/308] remove check of empty of Results when change selected
index
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 5d6887a3f..1db6ac624 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -171,9 +171,7 @@ namespace Flow.Launcher.ViewModel
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
- if (Results.Count > 0)
- SelectedIndex = 0;
-
+ SelectedIndex = 0;
Results.Update(newResults);
}
From c89ee33c5b6c72fab2aee25f6584b83c776dec03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 15 Nov 2020 20:39:02 +0800
Subject: [PATCH 021/308] Use Virtualizing StackPanel instead of GridView to
greatly reduce the loading resources.
---
Flow.Launcher/ResultListBox.xaml | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 072196605..350ef018e 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -16,6 +16,7 @@
Style="{DynamicResource BaseListboxStyle}" Focusable="False"
KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single"
VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard"
+ ScrollViewer.IsDeferredScrollingEnabled="True"
SelectionChanged="OnSelectionChanged"
IsSynchronizedWithCurrentItem="True"
PreviewMouseDown="ListBox_PreviewMouseDown">
@@ -29,26 +30,20 @@
-
-
+
+
-
-
-
-
-
-
+
-
+
-
+
@@ -60,7 +55,7 @@
-
+
@@ -81,7 +76,7 @@
-
+
From dc982e277f3c7beff59a71675cde74853e7e0420 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 15 Nov 2020 20:45:00 +0800
Subject: [PATCH 022/308] Use a default image to list when the image hasn't
been loaded in cache.
Co-authored-by: Bao-Qian
---
.../Image/ImageCache.cs | 13 +++++----
.../Image/ImageLoader.cs | 11 +++++++-
Flow.Launcher/ViewModel/ResultViewModel.cs | 28 +++++++++++++------
Flow.Launcher/ViewModel/ResultsViewModel.cs | 3 +-
4 files changed, 39 insertions(+), 16 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
index 80c6684f5..7482ac1cf 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
@@ -26,7 +26,7 @@ namespace Flow.Launcher.Infrastructure.Image
private const int MaxCached = 50;
public ConcurrentDictionary Data { get; private set; } = new ConcurrentDictionary();
private const int permissibleFactor = 2;
-
+
public void Initialization(Dictionary usage)
{
foreach (var key in usage.Keys)
@@ -44,14 +44,14 @@ namespace Flow.Launcher.Infrastructure.Image
value.usage++;
return value.imageSource;
}
-
+
return null;
}
set
{
Data.AddOrUpdate(
- path,
- new ImageUsage(0, value),
+ path,
+ new ImageUsage(0, value),
(k, v) =>
{
v.imageSource = value;
@@ -67,7 +67,8 @@ namespace Flow.Launcher.Infrastructure.Image
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary.
- foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
+ foreach (var key in Data.Where(x => x.Key != Constant.MissingImgIcon)
+ .OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
{
if (!(key.Equals(Constant.ErrorIcon) || key.Equals(Constant.DefaultIcon)))
{
@@ -80,7 +81,7 @@ namespace Flow.Launcher.Infrastructure.Image
public bool ContainsKey(string key)
{
- var contains = Data.ContainsKey(key);
+ var contains = Data.ContainsKey(key) && Data[key] != null;
return contains;
}
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index edfb88cbf..bc924926c 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -61,7 +61,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
lock (_storage)
{
- _storage.Save(ImageCache.Data.Select(x => (x.Key, x.Value.usage)).ToDictionary(x => x.Key, y => y.usage));
+ _storage.Save(ImageCache.Data.Select(x => (x.Key, x.Value.usage)).ToDictionary(x => x.Key, x => x.usage));
}
}
@@ -211,6 +211,15 @@ namespace Flow.Launcher.Infrastructure.Image
option);
}
+ public static bool CacheContainImage(string path)
+ {
+ return ImageCache.ContainsKey(path);
+ }
+ public static ImageSource LoadDefault(bool loadFullImage = false)
+ {
+ return LoadInternal(Constant.MissingImgIcon, loadFullImage).ImageSource;
+ }
+
public static ImageSource Load(string path, bool loadFullImage = false)
{
var imageResult = LoadInternal(path, loadFullImage);
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index a64836285..76c2a3e48 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
@@ -26,18 +27,18 @@ namespace Flow.Launcher.ViewModel
public Settings Settings { get; private set; }
- public Visibility ShowOpenResultHotkey => Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Hidden;
+ public Visibility ShowOpenResultHotkey => Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Hidden;
public string OpenResultModifiers => Settings.OpenResultModifiers;
public string ShowTitleToolTip => string.IsNullOrEmpty(Result.TitleToolTip)
- ? Result.Title
+ ? Result.Title
: Result.TitleToolTip;
public string ShowSubTitleToolTip => string.IsNullOrEmpty(Result.SubTitleToolTip)
- ? Result.SubTitle
+ ? Result.SubTitle
: Result.SubTitleToolTip;
-
+
public Lazy Image { get; set; }
private ImageSource SetImage
@@ -57,9 +58,20 @@ namespace Flow.Launcher.ViewModel
imagePath = Constant.MissingImgIcon;
}
}
-
- // will get here either when icoPath has value\icon delegate is null\when had exception in delegate
- return ImageLoader.Load(imagePath);
+
+ if (ImageLoader.CacheContainImage(imagePath))
+ // will get here either when icoPath has value\icon delegate is null\when had exception in delegate
+ return ImageLoader.Load(imagePath);
+ else
+ {
+ Task.Run(() =>
+ {
+ Image = new Lazy(() => ImageLoader.Load(imagePath));
+ OnPropertyChanged(nameof(Image));
+ });
+
+ return ImageLoader.LoadDefault();
+ }
}
}
@@ -78,7 +90,7 @@ namespace Flow.Launcher.ViewModel
}
}
-
+
public override int GetHashCode()
{
return Result.GetHashCode();
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 1db6ac624..eb40e75de 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -201,9 +201,10 @@ namespace Flow.Launcher.ViewModel
var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList();
+
return results.Where(r => r.Result.PluginID != resultId)
- .Concat(newResults)
+ .Concat(results.Intersect(newResults).Union(newResults))
.OrderByDescending(r => r.Result.Score)
.ToList();
}
From 4dd4cdafbf24c7437785cf01407aa7f6ce4086c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 15 Nov 2020 21:00:31 +0800
Subject: [PATCH 023/308] Revert "Use Virtualizing StackPanel instead of
GridView to greatly reduce the loading resources."
This reverts commit c89ee33c5b6c72fab2aee25f6584b83c776dec03.
Revert it because it is not useful so just keep the original code.
---
Flow.Launcher/ResultListBox.xaml | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 350ef018e..072196605 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -16,7 +16,6 @@
Style="{DynamicResource BaseListboxStyle}" Focusable="False"
KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single"
VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard"
- ScrollViewer.IsDeferredScrollingEnabled="True"
SelectionChanged="OnSelectionChanged"
IsSynchronizedWithCurrentItem="True"
PreviewMouseDown="ListBox_PreviewMouseDown">
@@ -30,20 +29,26 @@
-
-
+
+
-
+
+
+
+
+
+
-
+
-
+
@@ -55,7 +60,7 @@
-
+
@@ -76,7 +81,7 @@
-
+
From b1dd7b418136c791e0331ec7711421f285a2a54c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 15 Nov 2020 21:03:39 +0800
Subject: [PATCH 024/308] Move Image Cache filtering earlier
---
Flow.Launcher.Infrastructure/Image/ImageCache.cs | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
index 7482ac1cf..cce0aaace 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
@@ -26,7 +26,7 @@ namespace Flow.Launcher.Infrastructure.Image
private const int MaxCached = 50;
public ConcurrentDictionary Data { get; private set; } = new ConcurrentDictionary();
private const int permissibleFactor = 2;
-
+
public void Initialization(Dictionary usage)
{
foreach (var key in usage.Keys)
@@ -65,15 +65,13 @@ namespace Flow.Launcher.Infrastructure.Image
if (Data.Count > permissibleFactor * MaxCached)
{
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary.
-
-
- foreach (var key in Data.Where(x => x.Key != Constant.MissingImgIcon)
+ foreach (var key in Data
+ .Where(x => x.Key != Constant.MissingImgIcon
+ && x.Key != Constant.ErrorIcon
+ && x.Key != Constant.DefaultIcon)
.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
{
- if (!(key.Equals(Constant.ErrorIcon) || key.Equals(Constant.DefaultIcon)))
- {
- Data.TryRemove(key, out _);
- }
+ Data.TryRemove(key, out _);
}
}
}
From 2161f27a88180c74ffc13046e8557a94b498a426 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 08:32:11 +0800
Subject: [PATCH 025/308] fix unintended token argument pass
---
Flow.Launcher/ViewModel/MainViewModel.cs | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index c093495e3..21243a793 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -22,6 +22,7 @@ using Flow.Launcher.Storage;
using System.Windows.Media;
using Flow.Launcher.Infrastructure.Image;
using System.Collections.Concurrent;
+using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.ViewModel
{
@@ -442,7 +443,7 @@ namespace Flow.Launcher.ViewModel
if (!plugin.Metadata.Disabled)
{
var results = PluginManager.QueryForPlugin(plugin, query);
- _resultsUpdateQueue.Add(new ResultsForUpdate(results, plugin.Metadata, query, _updateToken));
+ _resultsUpdateQueue.Add(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken));
}
});
}
@@ -695,6 +696,20 @@ namespace Flow.Launcher.ViewModel
///
public void UpdateResultView(IEnumerable resultsForUpdates)
{
+ if (!resultsForUpdates.Any())
+ return;
+
+ try
+ {
+ var token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
+ }
+ catch (Exception e)
+ {
+ Log.Debug("Illegal token information");
+ }
+
+
+
foreach (var result in resultsForUpdates.SelectMany(u => u.Results))
{
if (_topMostRecord.IsTopMost(result))
From e7c02dac7201c347ae9aa03ce2d100b29f3e2ca5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 10:12:32 +0800
Subject: [PATCH 026/308] change SetImage to method instead of property to
avoid unintended use
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 49 ++++++++++------------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 76c2a3e48..8ce35227f 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -19,7 +19,7 @@ namespace Flow.Launcher.ViewModel
if (result != null)
{
Result = result;
- Image = new Lazy(() => SetImage);
+ Image = new Lazy(SetImage);
}
Settings = settings;
@@ -41,38 +41,35 @@ namespace Flow.Launcher.ViewModel
public Lazy Image { get; set; }
- private ImageSource SetImage
+ private ImageSource SetImage()
{
- get
+ var imagePath = Result.IcoPath;
+ if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
{
- var imagePath = Result.IcoPath;
- if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
+ try
{
- try
- {
- return Result.Icon();
- }
- catch (Exception e)
- {
- Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e);
- imagePath = Constant.MissingImgIcon;
- }
+ return Result.Icon();
}
-
- if (ImageLoader.CacheContainImage(imagePath))
- // will get here either when icoPath has value\icon delegate is null\when had exception in delegate
- return ImageLoader.Load(imagePath);
- else
+ catch (Exception e)
{
- Task.Run(() =>
- {
- Image = new Lazy(() => ImageLoader.Load(imagePath));
- OnPropertyChanged(nameof(Image));
- });
-
- return ImageLoader.LoadDefault();
+ Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e);
+ imagePath = Constant.MissingImgIcon;
}
}
+
+ if (ImageLoader.CacheContainImage(imagePath))
+ // will get here either when icoPath has value\icon delegate is null\when had exception in delegate
+ return ImageLoader.Load(imagePath);
+ else
+ {
+ Task.Run(() =>
+ {
+ Image = new Lazy(() => ImageLoader.Load(imagePath));
+ OnPropertyChanged(nameof(Image));
+ });
+
+ return ImageLoader.LoadDefault();
+ }
}
public Result Result { get; }
From 0a9bad3ffa25a2069f4e736e65b8a65a37ae44b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 12:46:39 +0800
Subject: [PATCH 027/308] Use Customized LazyAsync class to load image instead
of the weird way of updating lazy class async
---
.../Image/ImageLoader.cs | 12 ++--
Flow.Launcher/ViewModel/ResultViewModel.cs | 56 +++++++++++++++----
2 files changed, 51 insertions(+), 17 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index bc924926c..f61d4615a 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -18,6 +18,8 @@ namespace Flow.Launcher.Infrastructure.Image
private static readonly ConcurrentDictionary GuidToKey = new ConcurrentDictionary();
private static IImageHashGenerator _hashGenerator;
private static bool EnableImageHash = true;
+ public static ImageSource defaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon));
+
private static readonly string[] ImageExtensions =
{
@@ -37,6 +39,7 @@ namespace Flow.Launcher.Infrastructure.Image
var usage = LoadStorageToConcurrentDictionary();
+
foreach (var icon in new[] { Constant.DefaultIcon, Constant.MissingImgIcon })
{
ImageSource img = new BitmapImage(new Uri(icon));
@@ -213,13 +216,10 @@ namespace Flow.Launcher.Infrastructure.Image
public static bool CacheContainImage(string path)
{
- return ImageCache.ContainsKey(path);
- }
- public static ImageSource LoadDefault(bool loadFullImage = false)
- {
- return LoadInternal(Constant.MissingImgIcon, loadFullImage).ImageSource;
+ return ImageCache.ContainsKey(path) && ImageCache[path] != null;
}
+
public static ImageSource Load(string path, bool loadFullImage = false)
{
var imageResult = LoadInternal(path, loadFullImage);
@@ -230,7 +230,7 @@ namespace Flow.Launcher.Infrastructure.Image
string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null;
if (hash != null)
{
-
+
if (GuidToKey.TryGetValue(hash, out string key))
{ // image already exists
img = ImageCache[key] ?? img;
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 8ce35227f..511df5e59 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -8,18 +8,57 @@ using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
-
+using Microsoft.FSharp.Core;
namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
+ public class LazyAsync : Lazy>
+ {
+ private T defaultValue;
+
+
+ private readonly Action _updateCallback;
+ public T Value
+ {
+ get
+ {
+ if (!IsValueCreated)
+ {
+ base.Value.ContinueWith(_ =>
+ {
+ _updateCallback();
+ });
+ return defaultValue;
+ }
+ else if (!base.Value.IsCompleted)
+ {
+ return defaultValue;
+ }
+ else return base.Value.Result;
+ }
+ }
+ public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory)
+ {
+ if (defaultValue != null)
+ {
+ this.defaultValue = defaultValue;
+ }
+ _updateCallback = updateCallback;
+
+ }
+ }
+
public ResultViewModel(Result result, Settings settings)
{
if (result != null)
{
Result = result;
- Image = new Lazy(SetImage);
+ Image = new LazyAsync(SetImage, ImageLoader.defaultImage, () =>
+ {
+ OnPropertyChanged(nameof(Image));
+ });
}
Settings = settings;
@@ -39,9 +78,9 @@ namespace Flow.Launcher.ViewModel
? Result.SubTitle
: Result.SubTitleToolTip;
- public Lazy Image { get; set; }
+ public LazyAsync Image { get; set; }
- private ImageSource SetImage()
+ private async Task SetImage()
{
var imagePath = Result.IcoPath;
if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
@@ -62,14 +101,9 @@ namespace Flow.Launcher.ViewModel
return ImageLoader.Load(imagePath);
else
{
- Task.Run(() =>
- {
- Image = new Lazy(() => ImageLoader.Load(imagePath));
- OnPropertyChanged(nameof(Image));
- });
-
- return ImageLoader.LoadDefault();
+ return await Task.Run(() => ImageLoader.Load(imagePath));
}
+
}
public Result Result { get; }
From d9ef68272b1b98d727d00096203ddd3fea1abfbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 12:58:53 +0800
Subject: [PATCH 028/308] change default image property name
---
Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 2 +-
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index f61d4615a..fb2f426a0 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -18,7 +18,7 @@ namespace Flow.Launcher.Infrastructure.Image
private static readonly ConcurrentDictionary GuidToKey = new ConcurrentDictionary();
private static IImageHashGenerator _hashGenerator;
private static bool EnableImageHash = true;
- public static ImageSource defaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon));
+ public static ImageSource DefaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon));
private static readonly string[] ImageExtensions =
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 511df5e59..f4a51070f 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -55,7 +55,7 @@ namespace Flow.Launcher.ViewModel
if (result != null)
{
Result = result;
- Image = new LazyAsync(SetImage, ImageLoader.defaultImage, () =>
+ Image = new LazyAsync(SetImage, ImageLoader.DefaultImage, () =>
{
OnPropertyChanged(nameof(Image));
});
From 71cac9cb2335bdd409a08bd8a2c0b30459889a6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 13:04:16 +0800
Subject: [PATCH 029/308] change the way of checking whether cache exist
---
Flow.Launcher.Infrastructure/Image/ImageCache.cs | 3 +--
Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
index cce0aaace..c3d7e5cfa 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
@@ -79,8 +79,7 @@ namespace Flow.Launcher.Infrastructure.Image
public bool ContainsKey(string key)
{
- var contains = Data.ContainsKey(key) && Data[key] != null;
- return contains;
+ return Data.ContainsKey(key) && Data[key].imageSource != null;
}
public int CacheSize()
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index fb2f426a0..92cf9ac3f 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -216,7 +216,7 @@ namespace Flow.Launcher.Infrastructure.Image
public static bool CacheContainImage(string path)
{
- return ImageCache.ContainsKey(path) && ImageCache[path] != null;
+ return ImageCache.ContainsKey(path);
}
From 23d9e253baed19786806f9236c5b74db7cdc56ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 16 Nov 2020 19:20:52 +0800
Subject: [PATCH 030/308] Add some cancellationtoken check
---
Flow.Launcher/ViewModel/MainViewModel.cs | 15 +++------------
Flow.Launcher/ViewModel/ResultsViewModel.cs | 19 ++++++++++++++-----
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 21243a793..ccc351cd3 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -698,16 +698,7 @@ namespace Flow.Launcher.ViewModel
{
if (!resultsForUpdates.Any())
return;
-
- try
- {
- var token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
- }
- catch (Exception e)
- {
- Log.Debug("Illegal token information");
- }
-
+ CancellationToken token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
foreach (var result in resultsForUpdates.SelectMany(u => u.Results))
@@ -722,10 +713,10 @@ namespace Flow.Launcher.ViewModel
}
}
- Results.AddResults(resultsForUpdates);
+ Results.AddResults(resultsForUpdates, token);
}
- ///
+ /// U
/// To avoid deadlock, this method should not called from main thread
///
public void UpdateResultView(List list, PluginMetadata metadata, Query originQuery)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index eb40e75de..cce532965 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
+using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
@@ -136,7 +137,6 @@ namespace Flow.Launcher.ViewModel
public void AddResults(List newRawResults, string resultId)
{
var newResults = NewResults(newRawResults, resultId);
-
lock (_collectionLock)
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
@@ -163,9 +163,11 @@ namespace Flow.Launcher.ViewModel
///
/// To avoid deadlock, this method should not called from main thread
///
- public void AddResults(IEnumerable resultsForUpdates)
+ public void AddResults(IEnumerable resultsForUpdates, CancellationToken token)
{
var newResults = NewResults(resultsForUpdates);
+ if (token.IsCancellationRequested)
+ return;
lock (_collectionLock)
{
@@ -173,7 +175,7 @@ namespace Flow.Launcher.ViewModel
// fix selected index flow
SelectedIndex = 0;
- Results.Update(newResults);
+ Results.Update(newResults, token);
}
switch (Visbility)
@@ -201,7 +203,7 @@ namespace Flow.Launcher.ViewModel
var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList();
-
+
return results.Where(r => r.Result.PluginID != resultId)
.Concat(results.Intersect(newResults).Union(newResults))
@@ -292,10 +294,17 @@ namespace Flow.Launcher.ViewModel
/// Update the results collection with new results, try to keep identical results
///
///
+ public void Update(List newItems, CancellationToken token)
+ {
+ Clear();
+ if (token.IsCancellationRequested)
+ return;
+ AddRange(newItems);
+ }
+
public void Update(List newItems)
{
Clear();
-
AddRange(newItems);
}
}
From 2b423d9d80b3c6ced13c78feeec7d867eb3e3b8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 17 Nov 2020 16:46:36 +0800
Subject: [PATCH 031/308] Use single add notify for each element when the new
Item is small or the collection hasn't been buffer a lot. This seems solve
the startup stunt and potentially make render faster. (Need Testing)
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 47 ++++++++++++++++-----
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index cce532965..3a4b07fd6 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Configuration;
using System.Linq;
using System.Threading;
using System.Windows;
@@ -137,6 +139,7 @@ namespace Flow.Launcher.ViewModel
public void AddResults(List newRawResults, string resultId)
{
var newResults = NewResults(newRawResults, resultId);
+
lock (_collectionLock)
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
@@ -258,30 +261,38 @@ namespace Flow.Launcher.ViewModel
}
#endregion
- public class ResultCollection : ObservableCollection, INotifyCollectionChanged
+ public class ResultCollection : ObservableCollection
{
private bool _suppressNotification = false;
+
+ private long editTime = 0;
+
+ // https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
- public override event NotifyCollectionChangedEventHandler CollectionChanged;
-
- // https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
- public void AddRange(IEnumerable Items)
+ public void BulkAddRange(IEnumerable resultViews)
{
_suppressNotification = true;
+ foreach (var item in resultViews)
+ {
+ Add(item);
+ }
+ _suppressNotification = false;
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+ public void AddRange(IEnumerable Items)
+ {
foreach (var item in Items)
{
Add(item);
}
-
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
- CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return;
}
@@ -296,16 +307,32 @@ namespace Flow.Launcher.ViewModel
///
public void Update(List newItems, CancellationToken token)
{
- Clear();
+
if (token.IsCancellationRequested)
return;
- AddRange(newItems);
+ Update(newItems);
}
public void Update(List newItems)
{
+ if (editTime == 0)
+ {
+ AddRange(newItems);
+ editTime++;
+ return;
+ }
+ else if (editTime < 15 || newItems.Count < 50)
+ {
+ ClearItems();
+ AddRange(newItems);
+ editTime++;
+ return;
+ }
Clear();
- AddRange(newItems);
+
+ BulkAddRange(newItems);
+ editTime++;
+
}
}
}
From 6863b412e3060f3ff1d69a08c40891fb5d5182ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 20 Nov 2020 22:45:33 +0800
Subject: [PATCH 032/308] Use TPL's BufferBlock instead of BlockingCollection,
which will block the current Thread. This should make the Task.Run works
better.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index ccc351cd3..b6bb6703a 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -23,6 +23,7 @@ using System.Windows.Media;
using Flow.Launcher.Infrastructure.Image;
using System.Collections.Concurrent;
using Flow.Launcher.Infrastructure.Logger;
+using System.Threading.Tasks.Dataflow;
namespace Flow.Launcher.ViewModel
{
@@ -49,7 +50,7 @@ namespace Flow.Launcher.ViewModel
private bool _saved;
private readonly Internationalization _translator = InternationalizationManager.Instance;
- private BlockingCollection _resultsUpdateQueue;
+ private BufferBlock _resultsUpdateQueue;
#endregion
@@ -94,10 +95,10 @@ namespace Flow.Launcher.ViewModel
var plugin = (IResultUpdated)pair.Plugin;
plugin.ResultsUpdated += (s, e) =>
{
- Task.Run(() =>
+ Task.Run(async () =>
{
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
- _resultsUpdateQueue.Add(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken));
+ await _resultsUpdateQueue.SendAsync(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken));
}, _updateToken);
};
}
@@ -105,20 +106,14 @@ namespace Flow.Launcher.ViewModel
private void RegisterResultUpdate()
{
- _resultsUpdateQueue = new BlockingCollection();
+ _resultsUpdateQueue = new BufferBlock();
Task.Run(async () =>
{
- while (true)
+ while (await _resultsUpdateQueue.OutputAvailableAsync())
{
- List queue = new List() { _resultsUpdateQueue.Take() };
await Task.Delay(30);
-
- while (_resultsUpdateQueue.TryTake(out var resultsForUpdate))
- {
- queue.Add(resultsForUpdate);
- }
-
+ _resultsUpdateQueue.TryReceiveAll(out var queue);
UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested));
}
@@ -443,7 +438,7 @@ namespace Flow.Launcher.ViewModel
if (!plugin.Metadata.Disabled)
{
var results = PluginManager.QueryForPlugin(plugin, query);
- _resultsUpdateQueue.Add(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken));
+ _resultsUpdateQueue.Post(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken));
}
});
}
From ea5e9a0fae49a9e9bdeee4791509764ffe07452e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 20 Nov 2020 23:05:12 +0800
Subject: [PATCH 033/308] Use New keyword for customized lazyAsync Value
property
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index f4a51070f..0909b342f 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -20,7 +20,7 @@ namespace Flow.Launcher.ViewModel
private readonly Action _updateCallback;
- public T Value
+ public new T Value
{
get
{
From 4fb884cf570da817d6286883050308b31313f505 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 20 Nov 2020 23:21:04 +0800
Subject: [PATCH 034/308] Wait 50 ms for query staying same when updating view.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index b6bb6703a..6f67ffcf5 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -229,6 +229,7 @@ namespace Flow.Launcher.ViewModel
public ResultsViewModel Results { get; private set; }
public ResultsViewModel ContextMenu { get; private set; }
public ResultsViewModel History { get; private set; }
+ private string _lastQueryText;
private string _queryText;
public string QueryText
@@ -427,8 +428,14 @@ namespace Flow.Launcher.ViewModel
}, currentCancellationToken);
var plugins = PluginManager.ValidPluginsForQuery(query);
- Task.Run(() =>
+ Task.Run(async () =>
{
+ // Wait 50 millisecond for query change
+ // if query stay the same, update the view
+ await Task.Delay(50);
+ if (!(_lastQuery.RawQuery == QueryText))
+ return;
+
// so looping will stop once it was cancelled
var parallelOptions = new ParallelOptions { CancellationToken = currentCancellationToken };
try
From f11b302c37381c65ed50aa95ac07dc54b383ce7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 21 Nov 2020 12:01:57 +0800
Subject: [PATCH 035/308] slighly reduce the delay time
---
Flow.Launcher/ViewModel/MainViewModel.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 6f67ffcf5..fe1062cbb 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -112,7 +112,7 @@ namespace Flow.Launcher.ViewModel
{
while (await _resultsUpdateQueue.OutputAvailableAsync())
{
- await Task.Delay(30);
+ await Task.Delay(20);
_resultsUpdateQueue.TryReceiveAll(out var queue);
UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested));
@@ -430,9 +430,9 @@ namespace Flow.Launcher.ViewModel
var plugins = PluginManager.ValidPluginsForQuery(query);
Task.Run(async () =>
{
- // Wait 50 millisecond for query change
+ // Wait 45 millisecond for query change
// if query stay the same, update the view
- await Task.Delay(50);
+ await Task.Delay(45);
if (!(_lastQuery.RawQuery == QueryText))
return;
From 34dc0d0220e73c9ebe59a6efc1cf232828f68bad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 21 Nov 2020 16:42:15 +0800
Subject: [PATCH 036/308] move progressbar task position and change the way of
comparison
---
Flow.Launcher/ViewModel/MainViewModel.cs | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index fe1062cbb..4e0285d9e 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -419,13 +419,6 @@ namespace Flow.Launcher.ViewModel
RemoveOldQueryResults(query);
_lastQuery = query;
- Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
- { // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
- if (currentUpdateSource == _updateSource && _isQueryRunning)
- {
- ProgressBarVisibility = Visibility.Visible;
- }
- }, currentCancellationToken);
var plugins = PluginManager.ValidPluginsForQuery(query);
Task.Run(async () =>
@@ -433,9 +426,18 @@ namespace Flow.Launcher.ViewModel
// Wait 45 millisecond for query change
// if query stay the same, update the view
await Task.Delay(45);
- if (!(_lastQuery.RawQuery == QueryText))
+ if (!(_lastQuery.Search == query.Search))
return;
+ _ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
+ {
+ // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
+ if (currentUpdateSource == _updateSource && _isQueryRunning)
+ {
+ ProgressBarVisibility = Visibility.Visible;
+ }
+ }, currentCancellationToken);
+
// so looping will stop once it was cancelled
var parallelOptions = new ParallelOptions { CancellationToken = currentCancellationToken };
try
From 9bc58fe9dacfd5b78e2c75be53e3ad2bd72dfe21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 22 Nov 2020 18:24:27 +0800
Subject: [PATCH 037/308] Only stop querying for global query
---
Flow.Launcher/ViewModel/MainViewModel.cs | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 4e0285d9e..1f8e72b8c 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -79,9 +79,10 @@ namespace Flow.Launcher.ViewModel
_selectedResults = Results;
InitializeKeyCommands();
- RegisterResultsUpdatedEvent();
RegisterResultUpdate();
+ RegisterResultsUpdatedEvent();
+
SetHotkey(_settings.Hotkey, OnHotkey);
SetCustomPluginHotkey();
@@ -423,11 +424,14 @@ namespace Flow.Launcher.ViewModel
var plugins = PluginManager.ValidPluginsForQuery(query);
Task.Run(async () =>
{
- // Wait 45 millisecond for query change
- // if query stay the same, update the view
- await Task.Delay(45);
- if (!(_lastQuery.Search == query.Search))
- return;
+ if (plugins.Count > 1)
+ {
+ // Wait 45 millisecond for query change in global query
+ // if query changes, return so that it won't be calculated
+ await Task.Delay(45);
+ if (!(_lastQuery.Search == query.Search))
+ return;
+ }
_ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
{
From 81a02c6e64ed67825b547d64393b83911cefdf08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 24 Nov 2020 17:38:24 +0800
Subject: [PATCH 038/308] Don't add result to queue unless the query match
(plugin event driven update) Remove the Task.Run because updating result
metadata and adding result to queue should not be time wasted.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 3d3792c54..f398df92b 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -96,11 +96,9 @@ namespace Flow.Launcher.ViewModel
var plugin = (IResultUpdated)pair.Plugin;
plugin.ResultsUpdated += (s, e) =>
{
- Task.Run(async () =>
- {
- PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
- await _resultsUpdateQueue.SendAsync(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken));
- }, _updateToken);
+ PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
+ if (e.Query.Search == _lastQuery.Search)
+ _resultsUpdateQueue.Post(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken));
};
}
}
@@ -428,13 +426,13 @@ namespace Flow.Launcher.ViewModel
{
// Wait 45 millisecond for query change in global query
// if query changes, return so that it won't be calculated
- await Task.Delay(45);
+ await Task.Delay(45, currentCancellationToken);
if (!(_lastQuery.Search == query.Search))
return;
}
_ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
- {
+ {
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
if (currentUpdateSource == _updateSource && _isQueryRunning)
{
From c1107494344977f51865dbfba96ec5dd13b4ee5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 24 Nov 2020 17:41:57 +0800
Subject: [PATCH 039/308] Add more cancellation
---
Flow.Launcher/ViewModel/MainViewModel.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index f398df92b..fdae8ecd4 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -449,7 +449,8 @@ namespace Flow.Launcher.ViewModel
if (!plugin.Metadata.Disabled)
{
var results = PluginManager.QueryForPlugin(plugin, query);
- _resultsUpdateQueue.Post(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken));
+ if (!currentCancellationToken.IsCancellationRequested)
+ _resultsUpdateQueue.Post(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken));
}
});
}
From 69e11e2861622d85b957e983e6c736ff745eb5d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 24 Nov 2020 18:59:16 +0800
Subject: [PATCH 040/308] Use CancellationToken.IsCancellationRequested
wherever is possible to use, check equality of query whererever token is
unaccessiable. Dispose CancellationTokenSourse manually
---
Flow.Launcher/ViewModel/MainViewModel.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index fdae8ecd4..9316cd62e 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -404,6 +404,8 @@ namespace Flow.Launcher.ViewModel
if (!string.IsNullOrEmpty(QueryText))
{
_updateSource?.Cancel();
+ _updateSource?.Dispose();
+
var currentUpdateSource = new CancellationTokenSource();
_updateSource = currentUpdateSource;
var currentCancellationToken = _updateSource.Token;
@@ -427,14 +429,14 @@ namespace Flow.Launcher.ViewModel
// Wait 45 millisecond for query change in global query
// if query changes, return so that it won't be calculated
await Task.Delay(45, currentCancellationToken);
- if (!(_lastQuery.Search == query.Search))
+ if (currentCancellationToken.IsCancellationRequested)
return;
}
_ = Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
{
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
- if (currentUpdateSource == _updateSource && _isQueryRunning)
+ if (!currentCancellationToken.IsCancellationRequested && _isQueryRunning)
{
ProgressBarVisibility = Visibility.Visible;
}
@@ -463,7 +465,7 @@ namespace Flow.Launcher.ViewModel
// this should happen once after all queries are done so progress bar should continue
// until the end of all querying
_isQueryRunning = false;
- if (currentUpdateSource == _updateSource)
+ if (!currentCancellationToken.IsCancellationRequested)
{ // update to hidden if this is still the current query
ProgressBarVisibility = Visibility.Hidden;
}
From 1c6769cbcc78b2988ded5f7b22e60a1590d1b382 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 27 Nov 2020 07:43:03 +1100
Subject: [PATCH 041/308] fix merge
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 6805f31aa..3a1b7fee4 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -100,17 +100,10 @@ namespace Flow.Launcher.ViewModel
}
if (ImageLoader.CacheContainImage(imagePath))
- {
// will get here either when icoPath has value\icon delegate is null\when had exception in delegate
return ImageLoader.Load(imagePath);
- else
- {
- return await Task.Run(() => ImageLoader.Load(imagePath));
- }
- else
- {
- return await Task.Run(() => ImageLoader.Load(imagePath));
- }
+
+ return await Task.Run(() => ImageLoader.Load(imagePath));
}
public Result Result { get; }
From 05aa7062d7104b6d2bbb900ad26607f5f5db8a49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 27 Nov 2020 08:46:59 +0800
Subject: [PATCH 042/308] Change ErrorIcon to MissingImgIcon in ImageCache
check since we don't use ErrorIcon anymore
---
Flow.Launcher.Infrastructure/Image/ImageCache.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
index fdbdddb2d..b8da3b030 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
@@ -66,7 +66,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary.
foreach (var key in Data
- .Where(x => x.Key != Constant.ErrorIcon
+ .Where(x => x.Key != Constant.MissingImgIcon
&& x.Key != Constant.DefaultIcon)
.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
{
From 813e9b5439592fb3057bf5ff8af76d50d2df8f6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 28 Nov 2020 13:25:49 +0800
Subject: [PATCH 043/308] fix selected item doesn't always be the first item
issue. Method: Not only update selected index, but also update selected item
when adding results.
---
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/ViewModel/ResultsViewModel.cs | 14 ++++----------
2 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 072196605..2f9d06d81 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -9,7 +9,7 @@
d:DataContext="{d:DesignInstance vm:ResultsViewModel}"
MaxHeight="{Binding MaxHeight}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
- SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}"
+ SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
HorizontalContentAlignment="Stretch" ItemsSource="{Binding Results}"
Margin="{Binding Margin}"
Visibility="{Binding Visbility}"
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 3a4b07fd6..384647395 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -144,11 +144,10 @@ namespace Flow.Launcher.ViewModel
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
- if (Results.Count > 0)
- SelectedIndex = 0;
// update UI in one run, so it can avoid UI flickering
Results.Update(newResults);
+ SelectedItem = newResults[0];
}
if (Visbility != Visibility.Visible && Results.Count > 0)
@@ -176,9 +175,11 @@ namespace Flow.Launcher.ViewModel
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
- SelectedIndex = 0;
Results.Update(newResults, token);
+ SelectedItem = newResults[0];
+
+
}
switch (Visbility)
@@ -321,13 +322,6 @@ namespace Flow.Launcher.ViewModel
editTime++;
return;
}
- else if (editTime < 15 || newItems.Count < 50)
- {
- ClearItems();
- AddRange(newItems);
- editTime++;
- return;
- }
Clear();
BulkAddRange(newItems);
From a640eadf1b99fd53787a32c5b4921cac38870914 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 29 Nov 2020 14:56:08 +0800
Subject: [PATCH 044/308] Use List instead of ObservableCollection as base
class for resultcollection for better customized control of event
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 62 +++++++++++----------
1 file changed, 32 insertions(+), 30 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 384647395..6d476ec63 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -12,6 +12,7 @@ using System.Windows.Data;
using System.Windows.Documents;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
+using Microsoft.FSharp.Control;
namespace Flow.Launcher.ViewModel
{
@@ -177,6 +178,8 @@ namespace Flow.Launcher.ViewModel
// fix selected index flow
Results.Update(newResults, token);
+ if (token.IsCancellationRequested)
+ return;
SelectedItem = newResults[0];
@@ -262,35 +265,33 @@ namespace Flow.Launcher.ViewModel
}
#endregion
- public class ResultCollection : ObservableCollection
+ public class ResultCollection : List, INotifyCollectionChanged
{
- private bool _suppressNotification = false;
+
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
private long editTime = 0;
+
// https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
- protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
- if (!_suppressNotification)
- base.OnCollectionChanged(e);
+ if (CollectionChanged != null && CollectionChanged.GetInvocationList().Length == 1)
+ CollectionChanged.Invoke(this, e);
}
- public void BulkAddRange(IEnumerable resultViews)
+ public void BulkAddRange(IEnumerable resultViews, CancellationToken? token)
{
- _suppressNotification = true;
- foreach (var item in resultViews)
- {
- Add(item);
- }
- _suppressNotification = false;
+ AddRange(resultViews);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
}
- public void AddRange(IEnumerable Items)
+ public void AddAll(IEnumerable Items, CancellationToken? token)
{
foreach (var item in Items)
{
+ if (token?.IsCancellationRequested ?? false) return;
Add(item);
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
@@ -299,33 +300,34 @@ namespace Flow.Launcher.ViewModel
}
public void RemoveAll()
{
- ClearItems();
+ Clear();
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
///
/// Update the results collection with new results, try to keep identical results
///
- ///
- public void Update(List newItems, CancellationToken token)
+ /// New Items to add into the list view
+ /// Cancellation Token
+ public void Update(List newItems, CancellationToken? token = null)
{
-
- if (token.IsCancellationRequested)
+ if (newItems.Count == 0 || (token?.IsCancellationRequested ?? false))
return;
- Update(newItems);
- }
+
- public void Update(List newItems)
- {
- if (editTime == 0)
+ if (editTime < 5 || newItems.Count < 30)
{
- AddRange(newItems);
+ if (Count > 0) RemoveAll();
+ if (token?.IsCancellationRequested ?? false) return;
+ AddAll(newItems, token);
+ editTime++;
+ }
+ else
+ {
+ Clear();
+ BulkAddRange(newItems, token);
editTime++;
- return;
}
- Clear();
-
- BulkAddRange(newItems);
- editTime++;
}
}
From 1ddf83fc86d4b9a54ed93fdc8f5a359f8fb0e0b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 30 Nov 2020 11:33:31 +0800
Subject: [PATCH 045/308] Update to DotNet5
---
Flow.Launcher.Core/Flow.Launcher.Core.csproj | 4 ++--
.../Flow.Launcher.Infrastructure.csproj | 5 ++---
Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj | 6 +++---
Flow.Launcher.Test/Flow.Launcher.Test.csproj | 3 +--
Flow.Launcher/Flow.Launcher.csproj | 4 ++--
.../NetCore3.1-SelfContained.pubxml | 2 +-
.../Flow.Launcher.Plugin.BrowserBookmark.csproj | 14 ++++----------
.../Flow.Launcher.Plugin.Calculator.csproj | 4 ++--
.../Flow.Launcher.Plugin.Color.csproj | 4 ++--
.../Flow.Launcher.Plugin.ControlPanel.csproj | 4 ++--
.../Flow.Launcher.Plugin.Explorer.csproj | 4 ++--
.../Flow.Launcher.Plugin.PluginIndicator.csproj | 4 ++--
.../Flow.Launcher.Plugin.PluginManagement.csproj | 4 ++--
.../Flow.Launcher.Plugin.ProcessKiller.csproj | 2 +-
.../Flow.Launcher.Plugin.Program.csproj | 5 ++---
.../Flow.Launcher.Plugin.Shell.csproj | 5 ++---
.../Flow.Launcher.Plugin.Sys.csproj | 4 ++--
.../Flow.Launcher.Plugin.Url.csproj | 4 ++--
.../Flow.Launcher.Plugin.WebSearch.csproj | 14 +++-----------
Scripts/flowlauncher.nuspec | 2 +-
global.json | 2 +-
21 files changed, 41 insertions(+), 59 deletions(-)
diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
index 9f146a457..370f2015b 100644
--- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj
+++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
@@ -1,7 +1,7 @@
-
+
- netcoreapp3.1
+ net5.0-windows
true
true
Library
diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
index 28d4c0e1f..48d9486cf 100644
--- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
+++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
@@ -1,7 +1,6 @@
-
-
+
- netcoreapp3.1
+ net5.0-windows
{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}
Library
true
diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
index 0f6450d18..38ae6898f 100644
--- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
+++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
@@ -1,7 +1,7 @@
-
-
+
+
- netcoreapp3.1
+ net5.0-windows
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}
true
Library
diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
index e970c47b9..fb972d7d4 100644
--- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj
+++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
@@ -1,7 +1,7 @@
- netcoreapp3.1
+ net5.0-windows10.0.19041.0
{FF742965-9A80-41A5-B042-D6C7D3A21708}
Library
Properties
@@ -54,7 +54,6 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
\ No newline at end of file
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 8548ba39e..f959f3aa1 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -1,8 +1,8 @@
-
+
WinExe
- netcoreapp3.1
+ net5.0-windows10.0.19041.0
true
true
Flow.Launcher.App
diff --git a/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml b/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
index 2794a0cea..cad0fd462 100644
--- a/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
+++ b/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
@@ -7,7 +7,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
FileSystem
Release
Any CPU
- netcoreapp3.1
+ net5.0-windows
..\Output\Release\
win-x64
true
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
index 85b745a6b..ee78f78c4 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
@@ -1,8 +1,9 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
+ true
{9B130CC5-14FB-41FF-B310-0A95B6894C37}
Properties
Flow.Launcher.Plugin.BrowserBookmark
@@ -68,14 +69,7 @@
PreserveNewest
-
-
-
- MSBuild:Compile
- Designer
-
-
-
+
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
index 9e1fefdb3..bc637be54 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{59BD9891-3837-438A-958D-ADC7F91F6F7E}
Properties
Flow.Launcher.Plugin.Caculator
diff --git a/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj b/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj
index c7fe8271a..18f81e3ff 100644
--- a/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{F35190AA-4758-4D9E-A193-E3BDF6AD3567}
Properties
Flow.Launcher.Plugin.Color
diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
index 699737634..be62c31cd 100644
--- a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}
Properties
Flow.Launcher.Plugin.ControlPanel
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
index a1a08843a..99e9c784b 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
true
true
true
diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
index e6bfa7aa3..a904a9272 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{FDED22C8-B637-42E8-824A-63B5B6E05A3A}
Properties
Flow.Launcher.Plugin.PluginIndicator
diff --git a/Plugins/Flow.Launcher.Plugin.PluginManagement/Flow.Launcher.Plugin.PluginManagement.csproj b/Plugins/Flow.Launcher.Plugin.PluginManagement/Flow.Launcher.Plugin.PluginManagement.csproj
index 08e89d861..4a5df0b3a 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginManagement/Flow.Launcher.Plugin.PluginManagement.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginManagement/Flow.Launcher.Plugin.PluginManagement.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{049490F0-ECD2-4148-9B39-2135EC346EBE}
Properties
Flow.Launcher.Plugin.PluginManagement
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
index cf9c96294..1aef8f58e 100644
--- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
@@ -2,7 +2,7 @@
Library
- netcoreapp3.1
+ net5.0-windows
Flow.Launcher.Plugin.ProcessKiller
Flow.Launcher.Plugin.ProcessKiller
Flow-Launcher
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index 3802297c7..61d8b7b6c 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows10.0.19041.0
{FDB3555B-58EF-4AE6-B5F1-904719637AB4}
Properties
Flow.Launcher.Plugin.Program
@@ -109,7 +109,6 @@
-
diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
index 178d95010..12ee6833e 100644
--- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
@@ -1,8 +1,7 @@
-
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}
Properties
Flow.Launcher.Plugin.Shell
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
index bdab40457..6618ca775 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{0B9DE348-9361-4940-ADB6-F5953BFFCCEC}
Properties
Flow.Launcher.Plugin.Sys
diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
index 7d802d815..d5a056825 100644
--- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
@@ -1,8 +1,8 @@
-
+
Library
- netcoreapp3.1
+ net5.0-windows
{A3DCCBCA-ACC1-421D-B16E-210896234C26}
true
Properties
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
index 431ca9ce8..ed2c5107c 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
@@ -1,8 +1,8 @@
-
-
+
Library
- netcoreapp3.1
+ net5.0-windows
+ true
{403B57F2-1856-4FC7-8A24-36AB346B763E}
Properties
Flow.Launcher.Plugin.WebSearch
@@ -119,14 +119,6 @@
Designer
PreserveNewest
-
- MSBuild:Compile
- Designer
-
-
- MSBuild:Compile
- Designer
-
diff --git a/Scripts/flowlauncher.nuspec b/Scripts/flowlauncher.nuspec
index 6c5deb86b..f1f58f2d1 100644
--- a/Scripts/flowlauncher.nuspec
+++ b/Scripts/flowlauncher.nuspec
@@ -11,6 +11,6 @@
Flow Launcher - a launcher for windows
-
+
diff --git a/global.json b/global.json
index c3efffd40..2ad4d9100 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "3.1.201",
+ "version": "5.0.100",
"rollForward": "latestFeature"
}
}
\ No newline at end of file
From 3607bfde078af0f08dc4666fa1adede255e26f30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 1 Dec 2020 10:37:05 +0800
Subject: [PATCH 046/308] Change name for publish file
---
.../NetCore3.1-SelfContained.pubxml | 18 ------------------
1 file changed, 18 deletions(-)
delete mode 100644 Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
diff --git a/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml b/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
deleted file mode 100644
index cad0fd462..000000000
--- a/Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- FileSystem
- Release
- Any CPU
- net5.0-windows
- ..\Output\Release\
- win-x64
- true
- False
- False
- False
-
-
\ No newline at end of file
From e973e1d0bb6b97c4e86fcac380b536bfc9464fcb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 2 Dec 2020 13:26:05 +0800
Subject: [PATCH 047/308] Update ModernWPF so that the app can run
---
Flow.Launcher/Flow.Launcher.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index f959f3aa1..2f58abab0 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -72,7 +72,7 @@
-
+
all
From 19c7446552f6242cc43981948ea5eb24783f5dd9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 2 Dec 2020 13:56:50 +0800
Subject: [PATCH 048/308] Add Lock to the place we directly update the
ResultCollection
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 6d476ec63..d373b0fda 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -120,17 +120,20 @@ namespace Flow.Launcher.ViewModel
public void Clear()
{
- Results.RemoveAll();
+ lock (_collectionLock)
+ Results.RemoveAll();
}
public void KeepResultsFor(PluginMetadata metadata)
{
- Results.Update(Results.Where(r => r.Result.PluginID == metadata.ID).ToList());
+ lock (_collectionLock)
+ Results.Update(Results.Where(r => r.Result.PluginID == metadata.ID).ToList());
}
public void KeepResultsExcept(PluginMetadata metadata)
{
- Results.Update(Results.Where(r => r.Result.PluginID != metadata.ID).ToList());
+ lock (_collectionLock)
+ Results.Update(Results.Where(r => r.Result.PluginID != metadata.ID).ToList());
}
@@ -148,7 +151,8 @@ namespace Flow.Launcher.ViewModel
// update UI in one run, so it can avoid UI flickering
Results.Update(newResults);
- SelectedItem = newResults[0];
+ if (newResults.Any())
+ SelectedItem = newResults[0];
}
if (Visbility != Visibility.Visible && Results.Count > 0)
@@ -304,6 +308,9 @@ namespace Flow.Launcher.ViewModel
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
+
+
+
///
/// Update the results collection with new results, try to keep identical results
///
@@ -311,9 +318,9 @@ namespace Flow.Launcher.ViewModel
/// Cancellation Token
public void Update(List newItems, CancellationToken? token = null)
{
- if (newItems.Count == 0 || (token?.IsCancellationRequested ?? false))
+ if (token?.IsCancellationRequested ?? false)
return;
-
+
if (editTime < 5 || newItems.Count < 30)
{
From 98e6a1ab8a203201d08de9a8f1bc5273c81a7789 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 2 Dec 2020 20:57:23 +0800
Subject: [PATCH 049/308] Revert using List instead of observablecollection
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 66 ++++++++++-----------
1 file changed, 32 insertions(+), 34 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index d373b0fda..5a9043c23 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -12,7 +12,6 @@ using System.Windows.Data;
using System.Windows.Documents;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
-using Microsoft.FSharp.Control;
namespace Flow.Launcher.ViewModel
{
@@ -182,8 +181,6 @@ namespace Flow.Launcher.ViewModel
// fix selected index flow
Results.Update(newResults, token);
- if (token.IsCancellationRequested)
- return;
SelectedItem = newResults[0];
@@ -269,33 +266,35 @@ namespace Flow.Launcher.ViewModel
}
#endregion
- public class ResultCollection : List, INotifyCollectionChanged
+ public class ResultCollection : ObservableCollection
{
-
- public event NotifyCollectionChangedEventHandler CollectionChanged;
+ private bool _suppressNotification = false;
private long editTime = 0;
-
// https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
- protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
- if (CollectionChanged != null && CollectionChanged.GetInvocationList().Length == 1)
- CollectionChanged.Invoke(this, e);
+ if (!_suppressNotification)
+ base.OnCollectionChanged(e);
}
- public void BulkAddRange(IEnumerable resultViews, CancellationToken? token)
+ public void BulkAddRange(IEnumerable resultViews)
{
- AddRange(resultViews);
+ _suppressNotification = true;
+ foreach (var item in resultViews)
+ {
+ Add(item);
+ }
+ _suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
}
- public void AddAll(IEnumerable Items, CancellationToken? token)
+ public void AddRange(IEnumerable Items)
{
foreach (var item in Items)
{
- if (token?.IsCancellationRequested ?? false) return;
Add(item);
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
@@ -304,8 +303,7 @@ namespace Flow.Launcher.ViewModel
}
public void RemoveAll()
{
- Clear();
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ ClearItems();
}
@@ -314,27 +312,27 @@ namespace Flow.Launcher.ViewModel
///
/// Update the results collection with new results, try to keep identical results
///
- /// New Items to add into the list view
- /// Cancellation Token
- public void Update(List newItems, CancellationToken? token = null)
+ ///
+ public void Update(List newItems, CancellationToken token)
{
- if (token?.IsCancellationRequested ?? false)
+
+ if (token.IsCancellationRequested)
return;
+ Update(newItems);
+ }
+ public void Update(List newItems)
+ {
+ if (editTime == 0)
+ {
+ AddRange(newItems);
+ editTime++;
+ return;
+ }
+ Clear();
- if (editTime < 5 || newItems.Count < 30)
- {
- if (Count > 0) RemoveAll();
- if (token?.IsCancellationRequested ?? false) return;
- AddAll(newItems, token);
- editTime++;
- }
- else
- {
- Clear();
- BulkAddRange(newItems, token);
- editTime++;
- }
+ BulkAddRange(newItems);
+ editTime++;
}
}
From e7dd8676ec247f3a670867f4cb75a4263228cb4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 2 Dec 2020 23:37:23 +0800
Subject: [PATCH 050/308] Change some code and check out what cause those error
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 65 ++++++++++++---------
1 file changed, 36 insertions(+), 29 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 5a9043c23..e05e3c153 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -141,17 +141,18 @@ namespace Flow.Launcher.ViewModel
///
public void AddResults(List newRawResults, string resultId)
{
- var newResults = NewResults(newRawResults, resultId);
lock (_collectionLock)
{
+ 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
// fix selected index flow
// update UI in one run, so it can avoid UI flickering
Results.Update(newResults);
- if (newResults.Any())
- SelectedItem = newResults[0];
+ if (Results.Any())
+ SelectedItem = Results[0];
}
if (Visbility != Visibility.Visible && Results.Count > 0)
@@ -171,17 +172,20 @@ namespace Flow.Launcher.ViewModel
///
public void AddResults(IEnumerable resultsForUpdates, CancellationToken token)
{
- var newResults = NewResults(resultsForUpdates);
- if (token.IsCancellationRequested)
- return;
-
lock (_collectionLock)
{
+ var newResults = NewResults(resultsForUpdates);
+ if (token.IsCancellationRequested)
+ return;
+
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
Results.Update(newResults, token);
- SelectedItem = newResults[0];
+ if (token.IsCancellationRequested)
+ return;
+ if (Results.Any())
+ SelectedItem = Results[0];
}
@@ -268,33 +272,38 @@ namespace Flow.Launcher.ViewModel
public class ResultCollection : ObservableCollection
{
- private bool _suppressNotification = false;
private long editTime = 0;
- // https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
+ private bool _suppressNotifying = false;
+
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
- if (!_suppressNotification)
- base.OnCollectionChanged(e);
+ if (_suppressNotifying)
+ return;
+ base.OnCollectionChanged(e);
}
public void BulkAddRange(IEnumerable resultViews)
{
- _suppressNotification = true;
+ _suppressNotifying = true;
+
foreach (var item in resultViews)
{
Add(item);
}
- _suppressNotification = false;
+ _suppressNotifying = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
}
- public void AddRange(IEnumerable Items)
+ public void AddRange(IEnumerable Items, CancellationToken? token)
{
foreach (var item in Items)
{
+ if (token?.IsCancellationRequested ?? false)
+ return;
+
Add(item);
+
}
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
@@ -313,27 +322,25 @@ namespace Flow.Launcher.ViewModel
/// Update the results collection with new results, try to keep identical results
///
///
- public void Update(List newItems, CancellationToken token)
+ public void Update(List newItems, CancellationToken? token = null)
{
- if (token.IsCancellationRequested)
+ if (token?.IsCancellationRequested ?? false)
return;
- Update(newItems);
- }
- public void Update(List newItems)
- {
- if (editTime == 0)
+ if (editTime < 5 || newItems.Count < 30)
{
- AddRange(newItems);
+ if (Count != 0) ClearItems();
+ AddRange(newItems, token);
editTime++;
return;
}
- Clear();
-
- BulkAddRange(newItems);
- editTime++;
-
+ else
+ {
+ Clear();
+ BulkAddRange(newItems);
+ editTime++;
+ }
}
}
}
From 25bc2a70e3091de08f1a4a74050151c008c97bc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Thu, 3 Dec 2020 10:33:19 +0800
Subject: [PATCH 051/308] Add timeout for waiting collectionchange event,
although seems the deadlock isn't caused by this.
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 51 ++++++++++++---------
1 file changed, 29 insertions(+), 22 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index e05e3c153..40021690b 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -6,10 +6,12 @@ using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
+using System.Windows.Forms;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@@ -172,12 +174,11 @@ namespace Flow.Launcher.ViewModel
///
public void AddResults(IEnumerable resultsForUpdates, CancellationToken token)
{
+ var newResults = NewResults(resultsForUpdates);
+ if (token.IsCancellationRequested)
+ return;
lock (_collectionLock)
{
- var newResults = NewResults(resultsForUpdates);
- if (token.IsCancellationRequested)
- return;
-
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
@@ -186,8 +187,6 @@ namespace Flow.Launcher.ViewModel
return;
if (Results.Any())
SelectedItem = Results[0];
-
-
}
switch (Visbility)
@@ -277,38 +276,46 @@ namespace Flow.Launcher.ViewModel
private bool _suppressNotifying = false;
+ private CancellationToken _token;
+
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
- if (_suppressNotifying)
- return;
- base.OnCollectionChanged(e);
+ if (!_suppressNotifying)
+ {
+ var notifyChangeTask = Task.Run(() => base.OnCollectionChanged(e));
+ if (notifyChangeTask.Wait(300))
+ return;
+ else
+ {
+ notifyChangeTask.Dispose();
+ throw new TimeoutException();
+ }
+ }
}
public void BulkAddRange(IEnumerable resultViews)
{
+ // suppress notifying before adding all element
_suppressNotifying = true;
-
foreach (var item in resultViews)
{
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)
+ return;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
- public void AddRange(IEnumerable Items, CancellationToken? token)
+ public void AddRange(IEnumerable Items)
{
foreach (var item in Items)
{
- if (token?.IsCancellationRequested ?? false)
+ if (_token.IsCancellationRequested)
return;
-
Add(item);
-
}
-
- // wpf use directx / double buffered already, so just reset all won't cause ui flickering
- return;
-
}
public void RemoveAll()
{
@@ -322,16 +329,16 @@ namespace Flow.Launcher.ViewModel
/// Update the results collection with new results, try to keep identical results
///
///
- public void Update(List newItems, CancellationToken? token = null)
+ public void Update(List newItems, CancellationToken token = default)
{
-
- if (token?.IsCancellationRequested ?? false)
+ _token = token;
+ if (_token.IsCancellationRequested)
return;
if (editTime < 5 || newItems.Count < 30)
{
if (Count != 0) ClearItems();
- AddRange(newItems, token);
+ AddRange(newItems);
editTime++;
return;
}
From eb13a18d52d1e0659e8896d3bfc4dc3961fad445 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Thu, 3 Dec 2020 15:38:00 +0800
Subject: [PATCH 052/308] Use task.run in addresult instead of CollectionChange
event.
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 45 +++++++++++++--------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 40021690b..924fd7ffc 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -150,11 +150,20 @@ namespace Flow.Launcher.ViewModel
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// 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.");
+ }
- // update UI in one run, so it can avoid UI flickering
- Results.Update(newResults);
- if (Results.Any())
- SelectedItem = Results[0];
}
if (Visbility != Visibility.Visible && Results.Count > 0)
@@ -179,14 +188,23 @@ namespace Flow.Launcher.ViewModel
return;
lock (_collectionLock)
{
+
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
// fix selected index flow
+ var updateTask = Task.Run(() =>
+ {
+ // update UI in one run, so it can avoid UI flickering
+
+ Results.Update(newResults, token);
+ if (Results.Any())
+ SelectedItem = Results[0];
+ });
+ if (!updateTask.Wait(300))
+ {
+ updateTask.Dispose();
+ throw new TimeoutException("Update result use too much time.");
+ }
- Results.Update(newResults, token);
- if (token.IsCancellationRequested)
- return;
- if (Results.Any())
- SelectedItem = Results[0];
}
switch (Visbility)
@@ -282,14 +300,7 @@ namespace Flow.Launcher.ViewModel
{
if (!_suppressNotifying)
{
- var notifyChangeTask = Task.Run(() => base.OnCollectionChanged(e));
- if (notifyChangeTask.Wait(300))
- return;
- else
- {
- notifyChangeTask.Dispose();
- throw new TimeoutException();
- }
+ base.OnCollectionChanged(e);
}
}
From 01158fdc66bff9b8a64ff132e50807d4e317cc95 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 21:53:34 +0800
Subject: [PATCH 053/308] Add error handling for the resultUpdateTask to make
sure result update can continue when error throw.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 41 ++++++++++++++++++++----
1 file changed, 35 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 9316cd62e..dd790a98b 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -24,6 +24,7 @@ using Flow.Launcher.Infrastructure.Image;
using System.Collections.Concurrent;
using Flow.Launcher.Infrastructure.Logger;
using System.Threading.Tasks.Dataflow;
+using NLog;
namespace Flow.Launcher.ViewModel
{
@@ -51,6 +52,7 @@ namespace Flow.Launcher.ViewModel
private readonly Internationalization _translator = InternationalizationManager.Instance;
private BufferBlock _resultsUpdateQueue;
+ private Task _resultsViewUpdateTask;
#endregion
@@ -80,7 +82,7 @@ namespace Flow.Launcher.ViewModel
InitializeKeyCommands();
- RegisterResultUpdate();
+ RegisterViewUpdate();
RegisterResultsUpdatedEvent();
@@ -103,20 +105,31 @@ namespace Flow.Launcher.ViewModel
}
}
- private void RegisterResultUpdate()
+ private void RegisterViewUpdate()
{
_resultsUpdateQueue = new BufferBlock();
+ _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted);
- Task.Run(async () =>
+
+ async Task updateAction()
{
while (await _resultsUpdateQueue.OutputAvailableAsync())
{
await Task.Delay(20);
_resultsUpdateQueue.TryReceiveAll(out var queue);
UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested));
-
}
- });
+ };
+
+ void continueAction(Task t)
+ {
+#if DEBUG
+ throw t.Exception;
+#else
+ Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}");
+ _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continuationAction, TaskContinuationOptions.OnlyOnFaulted);
+#endif
+ }
}
@@ -707,7 +720,23 @@ namespace Flow.Launcher.ViewModel
{
if (!resultsForUpdates.Any())
return;
- CancellationToken token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
+ CancellationToken token;
+
+ try
+ {
+ token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
+ }
+#if DEBUG
+ catch
+ {
+ throw new ArgumentException("Unacceptable token");
+ }
+#else
+ catch
+ {
+
+ }
+#endif
foreach (var result in resultsForUpdates.SelectMany(u => u.Results))
From aa20d505fe5b42fe198461fa7f77513ec9e36138 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 21:54:22 +0800
Subject: [PATCH 054/308] Revert creating a new task when adding result.
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 924fd7ffc..f12ea23e9 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -188,22 +188,12 @@ namespace Flow.Launcher.ViewModel
return;
lock (_collectionLock)
{
+ // update UI in one run, so it can avoid UI flickering
- // https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
- // fix selected index flow
- var updateTask = Task.Run(() =>
- {
- // update UI in one run, so it can avoid UI flickering
+ Results.Update(newResults, token);
+ if (Results.Any())
+ SelectedItem = Results[0];
- Results.Update(newResults, token);
- if (Results.Any())
- SelectedItem = Results[0];
- });
- if (!updateTask.Wait(300))
- {
- updateTask.Dispose();
- throw new TimeoutException("Update result use too much time.");
- }
}
From 6267fa9a50f9454e9bdd85ed3dc4015f95822874 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 22:18:51 +0800
Subject: [PATCH 055/308] fix typo.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index dd790a98b..3e1580e38 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -127,7 +127,7 @@ namespace Flow.Launcher.ViewModel
throw t.Exception;
#else
Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}");
- _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continuationAction, TaskContinuationOptions.OnlyOnFaulted);
+ _resultsViewUpdateTask = Task.Run(updateAction).ContinueWith(continueAction, TaskContinuationOptions.OnlyOnFaulted);
#endif
}
}
From c3d5d4c0cecddc41a5fcdf7b18c1ccd7de87df84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 22:24:25 +0800
Subject: [PATCH 056/308] Don't update collection when both newItems and
collection is empty
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index f12ea23e9..fc77327cc 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -333,7 +333,7 @@ namespace Flow.Launcher.ViewModel
public void Update(List newItems, CancellationToken token = default)
{
_token = token;
- if (_token.IsCancellationRequested)
+ if (Count == 0 && newItems.Count == 0 || _token.IsCancellationRequested)
return;
if (editTime < 5 || newItems.Count < 30)
From 756c5bce3deb3af5df9e9554e930e20609083e33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 22:30:14 +0800
Subject: [PATCH 057/308] fix using unintialized variable in release.
---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 3e1580e38..1329421c3 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -734,7 +734,7 @@ namespace Flow.Launcher.ViewModel
#else
catch
{
-
+ token = default;
}
#endif
From 4ea40ab9aa7907b6648315cf42e4813b96df491d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Fri, 4 Dec 2020 22:46:23 +0800
Subject: [PATCH 058/308] Add the new publish profile file
---
.../PublishProfiles/Net5-SelfContained.pubxml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Flow.Launcher/Properties/PublishProfiles/Net5-SelfContained.pubxml
diff --git a/Flow.Launcher/Properties/PublishProfiles/Net5-SelfContained.pubxml b/Flow.Launcher/Properties/PublishProfiles/Net5-SelfContained.pubxml
new file mode 100644
index 000000000..124792e3e
--- /dev/null
+++ b/Flow.Launcher/Properties/PublishProfiles/Net5-SelfContained.pubxml
@@ -0,0 +1,18 @@
+
+
+
+
+ FileSystem
+ Release
+ Any CPU
+ net5.0-windows10.0.19041.0
+ ..\Output\Release\
+ win-x64
+ true
+ False
+ False
+ False
+
+
\ No newline at end of file
From b8d3b42295d557784e5ab990a927e612f7fd4872 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 5 Dec 2020 15:48:36 +0800
Subject: [PATCH 059/308] use singleordefault instead of single since sometims
the queue may be empty but method doesn't return
---
Flow.Launcher/ViewModel/MainViewModel.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 1329421c3..25768a25e 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -724,7 +724,8 @@ namespace Flow.Launcher.ViewModel
try
{
- token = resultsForUpdates.Select(r => r.Token).Distinct().Single();
+ // Don't know why sometimes even resultsForUpdates is empty, the method won't return;
+ token = resultsForUpdates.Select(r => r.Token).Distinct().SingleOrDefault();
}
#if DEBUG
catch
From b67f5de4c57f5a7ce3a2bdb1d9cd283a8665e411 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 5 Dec 2020 16:55:06 +0800
Subject: [PATCH 060/308] Port StringMatcher.FuzzySearch to IPublicAPI
---
Flow.Launcher.Plugin/IPublicAPI.cs | 2 ++
Flow.Launcher/PublicAPIInstance.cs | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/Flow.Launcher.Plugin/IPublicAPI.cs b/Flow.Launcher.Plugin/IPublicAPI.cs
index 681973905..b6f3f0680 100644
--- a/Flow.Launcher.Plugin/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/IPublicAPI.cs
@@ -88,5 +88,7 @@ namespace Flow.Launcher.Plugin
/// if you want to hook something like Ctrl+R, you should use this event
///
event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent;
+
+ public (List MatchedData, int Score, bool Success) MatchString(string query, string stringToCompare);
}
}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 0cc5a0e5d..5d1ea7f24 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -132,6 +132,12 @@ namespace Flow.Launcher
public event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent;
+ public (List MatchedData, int Score, bool Success) MatchString(string query, string stringToCompare)
+ {
+ var result = StringMatcher.FuzzySearch(query, stringToCompare);
+ return (result.MatchData, result.Score, result.Success);
+ }
+
#endregion
#region Private Methods
@@ -144,6 +150,7 @@ namespace Flow.Launcher
}
return true;
}
+
#endregion
}
}
From 968931e4a07246f0f15d3878dc50c535d193fdd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Tue, 22 Dec 2020 13:45:11 +0800
Subject: [PATCH 061/308] return if cancellation requested before changing
_isQueryRunning state
---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 25768a25e..a8a8ec1d7 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -474,6 +474,8 @@ namespace Flow.Launcher.ViewModel
// nothing to do here
}
+ if (currentCancellationToken.IsCancellationRequested)
+ return;
// this should happen once after all queries are done so progress bar should continue
// until the end of all querying
From b7a0ada60b72b2d5c619e455d1b615ff713776d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Tue, 22 Dec 2020 21:53:59 +0800
Subject: [PATCH 062/308] Add Mapping to original string after translation. Not
sure about the performance, but seems satisfying. It requires at most n times
loop (n: number of translated charater) mapping once.
---
.../PinyinAlphabet.cs | 81 +++++++++++++++----
Flow.Launcher.Infrastructure/StringMatcher.cs | 78 +++++++++---------
2 files changed, 108 insertions(+), 51 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
index 80fd12820..4f1aedd4a 100644
--- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
+++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
@@ -1,21 +1,77 @@
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Flow.Launcher.Infrastructure.UserSettings;
+using Microsoft.AspNetCore.Localization;
using ToolGood.Words.Pinyin;
namespace Flow.Launcher.Infrastructure
{
+ public class TranslationMapping
+ {
+ private bool constructed;
+
+ private List originalIndexs = new List();
+ private List translatedIndexs = new List();
+ private int translaedLength = 0;
+
+ public void AddNewIndex(int originalIndex, int translatedIndex, int length)
+ {
+ if (constructed)
+ throw new InvalidOperationException("Mapping shouldn't be changed after constructed");
+
+ originalIndexs.Add(originalIndex);
+ translatedIndexs.Add(translatedIndex);
+ translatedIndexs.Add(translatedIndex + length);
+ translaedLength += length - 1;
+ }
+
+ public int? MapToOriginalIndex(int translatedIndex)
+ {
+ if (translatedIndex > translatedIndexs.Last())
+ return translatedIndex - translaedLength - 1;
+
+ for (var i = 0; i < originalIndexs.Count; i++)
+ {
+ if (translatedIndex >= translatedIndexs[i * 2] && translatedIndex < translatedIndexs[i * 2 + 1])
+ return originalIndexs[i];
+ if (translatedIndex < translatedIndexs[i * 2])
+ {
+ int indexDiff = 0;
+ for (int j = 0; j < i; j++)
+ {
+ indexDiff += translatedIndexs[i * 2 + 1] - translatedIndexs[i * 2] - 1;
+ }
+
+ return translatedIndex - indexDiff;
+ }
+ }
+
+ return translatedIndex;
+ }
+
+ public void endConstruct()
+ {
+ if (constructed)
+ throw new InvalidOperationException("Mapping has already been constructed");
+ constructed = true;
+ }
+ }
+
public interface IAlphabet
{
- string Translate(string stringToTranslate);
+ public (string translation, TranslationMapping map) Translate(string stringToTranslate);
}
public class PinyinAlphabet : IAlphabet
{
- private ConcurrentDictionary _pinyinCache = new ConcurrentDictionary();
+ private ConcurrentDictionary _pinyinCache =
+ new ConcurrentDictionary();
+
+
private Settings _settings;
public void Initialize([NotNull] Settings settings)
@@ -23,7 +79,7 @@ namespace Flow.Launcher.Infrastructure
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
- public string Translate(string content)
+ public (string translation, TranslationMapping map) Translate(string content)
{
if (_settings.ShouldUsePinyin)
{
@@ -34,14 +90,7 @@ namespace Flow.Launcher.Infrastructure
var resultList = WordsHelper.GetPinyinList(content);
StringBuilder resultBuilder = new StringBuilder();
-
- for (int i = 0; i < resultList.Length; i++)
- {
- if (content[i] >= 0x3400 && content[i] <= 0x9FD5)
- resultBuilder.Append(resultList[i].First());
- }
-
- resultBuilder.Append(' ');
+ TranslationMapping map = new TranslationMapping();
bool pre = false;
@@ -49,6 +98,7 @@ namespace Flow.Launcher.Infrastructure
{
if (content[i] >= 0x3400 && content[i] <= 0x9FD5)
{
+ map.AddNewIndex(i, resultBuilder.Length, resultList[i].Length + 1);
resultBuilder.Append(' ');
resultBuilder.Append(resultList[i]);
pre = true;
@@ -60,15 +110,18 @@ namespace Flow.Launcher.Infrastructure
pre = false;
resultBuilder.Append(' ');
}
+
resultBuilder.Append(resultList[i]);
}
}
- return _pinyinCache[content] = resultBuilder.ToString();
+ map.endConstruct();
+
+ return _pinyinCache[content] = (resultBuilder.ToString(), map);
}
else
{
- return content;
+ return (content, null);
}
}
else
@@ -78,7 +131,7 @@ namespace Flow.Launcher.Infrastructure
}
else
{
- return content;
+ return (content, null);
}
}
}
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 96391f1d6..e885798b7 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -44,22 +44,12 @@ namespace Flow.Launcher.Infrastructure
///
public MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt)
{
- if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult(false, UserSettingSearchPrecision);
+ if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query))
+ return new MatchResult(false, UserSettingSearchPrecision);
query = query.Trim();
-
- stringToCompare = _alphabet?.Translate(stringToCompare) ?? stringToCompare;
-
- // This also can be done by spliting the query
-
- //(var spaceSplit, var upperSplit) = stringToCompare switch
- //{
- // string s when s.Contains(' ') => (s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(w => w.First()),
- // default(IEnumerable)),
- // string s when s.Any(c => char.IsUpper(c)) && s.Any(c => char.IsLower(c)) =>
- // (null, Regex.Split(s, @"(? w.First())),
- // _ => ((IEnumerable)null, (IEnumerable)null)
- //};
+ TranslationMapping map;
+ (stringToCompare, map) = _alphabet?.Translate(stringToCompare) ?? (stringToCompare, null);
var currentQueryIndex = 0;
var acronymMatchData = new List();
@@ -75,19 +65,21 @@ namespace Flow.Launcher.Infrastructure
switch (stringToCompare[compareIndex])
{
- case char c when (compareIndex == 0 && queryWithoutCase[currentQueryIndex] == char.ToLower(stringToCompare[compareIndex]))
- || (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
- || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) == queryWithoutCase[currentQueryIndex])
- || (char.IsNumber(c) && c == queryWithoutCase[currentQueryIndex]):
- acronymMatchData.Add(compareIndex);
+ case var c when (compareIndex == 0 && queryWithoutCase[currentQueryIndex] ==
+ char.ToLower(stringToCompare[compareIndex]))
+ || (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
+ || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) ==
+ queryWithoutCase[currentQueryIndex])
+ || (char.IsNumber(c) && c == queryWithoutCase[currentQueryIndex]):
+ acronymMatchData.Add(map?.MapToOriginalIndex(compareIndex) ?? compareIndex);
currentQueryIndex++;
continue;
- case char c when char.IsWhiteSpace(c):
+ case var c when char.IsWhiteSpace(c):
compareIndex++;
acronymScore -= 10;
break;
- case char c when char.IsUpper(c) || char.IsNumber(c):
+ case var c when char.IsUpper(c) || char.IsNumber(c):
acronymScore -= 10;
break;
}
@@ -99,7 +91,7 @@ namespace Flow.Launcher.Infrastructure
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
- var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ var querySubstrings = queryWithoutCase.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
int currentQuerySubstringIndex = 0;
var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
var currentQuerySubstringCharacterIndex = 0;
@@ -114,9 +106,10 @@ namespace Flow.Launcher.Infrastructure
var indexList = new List();
List spaceIndices = new List();
- for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
+ for (var compareStringIndex = 0;
+ compareStringIndex < fullStringToCompareWithoutCase.Length;
+ compareStringIndex++)
{
-
// To maintain a list of indices which correspond to spaces in the string to compare
// To populate the list only for the first query substring
if (fullStringToCompareWithoutCase[compareStringIndex].Equals(' ') && currentQuerySubstringIndex == 0)
@@ -124,7 +117,8 @@ namespace Flow.Launcher.Infrastructure
spaceIndices.Add(compareStringIndex);
}
- if (fullStringToCompareWithoutCase[compareStringIndex] != currentQuerySubstring[currentQuerySubstringCharacterIndex])
+ if (fullStringToCompareWithoutCase[compareStringIndex] !=
+ currentQuerySubstring[currentQuerySubstringCharacterIndex])
{
matchFoundInPreviousLoop = false;
continue;
@@ -148,14 +142,16 @@ namespace Flow.Launcher.Infrastructure
// in order to do so we need to verify all previous chars are part of the pattern
var startIndexToVerify = compareStringIndex - currentQuerySubstringCharacterIndex;
- if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex, fullStringToCompareWithoutCase, currentQuerySubstring))
+ if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex,
+ fullStringToCompareWithoutCase, currentQuerySubstring))
{
matchFoundInPreviousLoop = true;
// if it's the beginning character of the first query substring that is matched then we need to update start index
firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
- indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
+ indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex,
+ firstMatchIndexInWord, indexList);
}
}
@@ -168,11 +164,13 @@ namespace Flow.Launcher.Infrastructure
if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
{
// if any of the substrings was not matched then consider as all are not matched
- allSubstringsContainedInCompareString = matchFoundInPreviousLoop && allSubstringsContainedInCompareString;
+ allSubstringsContainedInCompareString =
+ matchFoundInPreviousLoop && allSubstringsContainedInCompareString;
currentQuerySubstringIndex++;
- allQuerySubstringsMatched = AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
+ allQuerySubstringsMatched =
+ AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
if (allQuerySubstringsMatched)
break;
@@ -182,13 +180,16 @@ namespace Flow.Launcher.Infrastructure
}
}
+
// proceed to calculate score if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
{
var nearestSpaceIndex = CalculateClosestSpaceIndex(spaceIndices, firstMatchIndex);
- var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex - nearestSpaceIndex - 1, lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
+ var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex - nearestSpaceIndex - 1,
+ lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
- return new MatchResult(true, UserSettingSearchPrecision, indexList, score);
+ var resultList = indexList.Distinct().Select(x => map?.MapToOriginalIndex(x) ?? x).ToList();
+ return new MatchResult(true, UserSettingSearchPrecision, resultList, score);
}
return new MatchResult(false, UserSettingSearchPrecision);
@@ -203,14 +204,15 @@ namespace Flow.Launcher.Infrastructure
}
else
{
- int? ind = spaceIndices.OrderBy(item => (firstMatchIndex - item)).Where(item => firstMatchIndex > item).FirstOrDefault();
+ int? ind = spaceIndices.OrderBy(item => (firstMatchIndex - item))
+ .FirstOrDefault(item => firstMatchIndex > item);
int closestSpaceIndex = ind ?? -1;
return closestSpaceIndex;
}
}
private static bool AllPreviousCharsMatched(int startIndexToVerify, int currentQuerySubstringCharacterIndex,
- string fullStringToCompareWithoutCase, string currentQuerySubstring)
+ string fullStringToCompareWithoutCase, string currentQuerySubstring)
{
var allMatch = true;
for (int indexToCheck = 0; indexToCheck < currentQuerySubstringCharacterIndex; indexToCheck++)
@@ -225,7 +227,8 @@ namespace Flow.Launcher.Infrastructure
return allMatch;
}
- private static List GetUpdatedIndexList(int startIndexToVerify, int currentQuerySubstringCharacterIndex, int firstMatchIndexInWord, List indexList)
+ private static List GetUpdatedIndexList(int startIndexToVerify, int currentQuerySubstringCharacterIndex,
+ int firstMatchIndexInWord, List indexList)
{
var updatedList = new List();
@@ -246,7 +249,8 @@ namespace Flow.Launcher.Infrastructure
return currentQuerySubstringIndex >= querySubstringsLength;
}
- private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen, bool allSubstringsContainedInCompareString)
+ private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
+ bool allSubstringsContainedInCompareString)
{
// A match found near the beginning of a string is scored more than a match found near the end
// A match is scored more if the characters in the patterns are closer to each other,
@@ -341,7 +345,7 @@ namespace Flow.Launcher.Infrastructure
private bool IsSearchPrecisionScoreMet(int rawScore)
{
- return rawScore >= (int)SearchPrecision;
+ return rawScore >= (int) SearchPrecision;
}
private int ScoreAfterSearchPrecisionFilter(int rawScore)
@@ -354,4 +358,4 @@ namespace Flow.Launcher.Infrastructure
{
public bool IgnoreCase { get; set; } = true;
}
-}
+}
\ No newline at end of file
From 2c9f4149b7cbd0d86fd46e07f2fa2509917e67f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Tue, 22 Dec 2020 22:58:27 +0800
Subject: [PATCH 063/308] optimize use
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index e885798b7..22334c4bd 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -71,7 +71,7 @@ namespace Flow.Launcher.Infrastructure
|| (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) ==
queryWithoutCase[currentQueryIndex])
|| (char.IsNumber(c) && c == queryWithoutCase[currentQueryIndex]):
- acronymMatchData.Add(map?.MapToOriginalIndex(compareIndex) ?? compareIndex);
+ acronymMatchData.Add(compareIndex);
currentQueryIndex++;
continue;
@@ -86,7 +86,10 @@ namespace Flow.Launcher.Infrastructure
}
if (acronymMatchData.Count == query.Length && acronymScore >= 60)
+ {
+ acronymMatchData = acronymMatchData.Select(x => map?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
+ }
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
@@ -188,7 +191,7 @@ namespace Flow.Launcher.Infrastructure
var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex - nearestSpaceIndex - 1,
lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
- var resultList = indexList.Distinct().Select(x => map?.MapToOriginalIndex(x) ?? x).ToList();
+ var resultList = indexList.Select(x => map?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
return new MatchResult(true, UserSettingSearchPrecision, resultList, score);
}
From 75b99415eb90f4ee7f8c5a30fedef4f785480cb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Sat, 26 Dec 2020 00:29:35 +0800
Subject: [PATCH 064/308] Use Binary Search instead of Linear search to reduce
time complexity.
Add Key Property for debugging.
---
.../PinyinAlphabet.cs | 78 +++++++++++++++----
1 file changed, 62 insertions(+), 16 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
index 4f1aedd4a..be3c58f66 100644
--- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
+++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs
@@ -18,6 +18,13 @@ namespace Flow.Launcher.Infrastructure
private List translatedIndexs = new List();
private int translaedLength = 0;
+ public string key { get; private set; }
+
+ public void setKey(string key)
+ {
+ this.key = key;
+ }
+
public void AddNewIndex(int originalIndex, int translatedIndex, int length)
{
if (constructed)
@@ -29,28 +36,64 @@ namespace Flow.Launcher.Infrastructure
translaedLength += length - 1;
}
- public int? MapToOriginalIndex(int translatedIndex)
+ public int MapToOriginalIndex(int translatedIndex)
{
if (translatedIndex > translatedIndexs.Last())
return translatedIndex - translaedLength - 1;
-
- for (var i = 0; i < originalIndexs.Count; i++)
- {
- if (translatedIndex >= translatedIndexs[i * 2] && translatedIndex < translatedIndexs[i * 2 + 1])
- return originalIndexs[i];
- if (translatedIndex < translatedIndexs[i * 2])
- {
- int indexDiff = 0;
- for (int j = 0; j < i; j++)
- {
- indexDiff += translatedIndexs[i * 2 + 1] - translatedIndexs[i * 2] - 1;
- }
- return translatedIndex - indexDiff;
+ int lowerBound = 0;
+ int upperBound = originalIndexs.Count - 1;
+
+ int count = 0;
+
+
+ // Corner case handle
+ if (translatedIndex < translatedIndexs[0])
+ return translatedIndex;
+ if (translatedIndex > translatedIndexs.Last())
+ {
+ int indexDef = 0;
+ for (int k = 0; k < originalIndexs.Count; k++)
+ {
+ indexDef += translatedIndexs[k * 2 + 1] - translatedIndexs[k * 2];
}
+
+ return translatedIndex - indexDef - 1;
}
- return translatedIndex;
+ // Binary Search with Range
+ for (int i = originalIndexs.Count / 2;; count++)
+ {
+ if (translatedIndex < translatedIndexs[i * 2])
+ {
+ // move to lower middle
+ upperBound = i;
+ i = (i + lowerBound) / 2;
+ }
+ else if (translatedIndex > translatedIndexs[i * 2 + 1] - 1)
+ {
+ lowerBound = i;
+ // move to upper middle
+ // due to floor of integer division, move one up on corner case
+ i = (i + upperBound + 1) / 2;
+ }
+ else
+ return originalIndexs[i];
+
+ if (upperBound - lowerBound <= 1 &&
+ translatedIndex > translatedIndexs[lowerBound * 2 + 1] &&
+ translatedIndex < translatedIndexs[upperBound * 2])
+ {
+ int indexDef = 0;
+
+ for (int j = 0; j < upperBound; j++)
+ {
+ indexDef += translatedIndexs[j * 2 + 1] - translatedIndexs[j * 2];
+ }
+
+ return translatedIndex - indexDef - 1;
+ }
+ }
}
public void endConstruct()
@@ -117,7 +160,10 @@ namespace Flow.Launcher.Infrastructure
map.endConstruct();
- return _pinyinCache[content] = (resultBuilder.ToString(), map);
+ var key = resultBuilder.ToString();
+ map.setKey(key);
+
+ return _pinyinCache[content] = (key, map);
}
else
{
From 7ceb08071c6086f39911f1ff2c920e160267d41e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Sun, 27 Dec 2020 20:16:20 +0800
Subject: [PATCH 065/308] Use inner loop to evaluate acronym match (Big Change)
Don't end loop before acronym match end since if acronym match exist, we will use that one.
---
Flow.Launcher.Infrastructure/StringMatcher.cs | 99 ++++++++++++-------
1 file changed, 61 insertions(+), 38 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 22334c4bd..7ade76cdf 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -51,46 +51,13 @@ namespace Flow.Launcher.Infrastructure
TranslationMapping map;
(stringToCompare, map) = _alphabet?.Translate(stringToCompare) ?? (stringToCompare, null);
- var currentQueryIndex = 0;
+ var currentAcronymQueryIndex = 0;
var acronymMatchData = new List();
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
+ // preset acronymScore
int acronymScore = 100;
- for (int compareIndex = 0; compareIndex < stringToCompare.Length; compareIndex++)
- {
- if (currentQueryIndex >= queryWithoutCase.Length)
- break;
-
-
- switch (stringToCompare[compareIndex])
- {
- case var c when (compareIndex == 0 && queryWithoutCase[currentQueryIndex] ==
- char.ToLower(stringToCompare[compareIndex]))
- || (char.IsUpper(c) && char.ToLower(c) == queryWithoutCase[currentQueryIndex])
- || (char.IsWhiteSpace(c) && char.ToLower(stringToCompare[++compareIndex]) ==
- queryWithoutCase[currentQueryIndex])
- || (char.IsNumber(c) && c == queryWithoutCase[currentQueryIndex]):
- acronymMatchData.Add(compareIndex);
- currentQueryIndex++;
- continue;
-
- case var c when char.IsWhiteSpace(c):
- compareIndex++;
- acronymScore -= 10;
- break;
- case var c when char.IsUpper(c) || char.IsNumber(c):
- acronymScore -= 10;
- break;
- }
- }
-
- if (acronymMatchData.Count == query.Length && acronymScore >= 60)
- {
- acronymMatchData = acronymMatchData.Select(x => map?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
- return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
- }
-
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
@@ -109,24 +76,72 @@ namespace Flow.Launcher.Infrastructure
var indexList = new List();
List spaceIndices = new List();
+ bool spaceMet = false;
+
for (var compareStringIndex = 0;
compareStringIndex < fullStringToCompareWithoutCase.Length;
compareStringIndex++)
{
+ if (currentAcronymQueryIndex >= queryWithoutCase.Length
+ || allQuerySubstringsMatched && acronymScore < (int) UserSettingSearchPrecision)
+ break;
+
+
// To maintain a list of indices which correspond to spaces in the string to compare
// To populate the list only for the first query substring
- if (fullStringToCompareWithoutCase[compareStringIndex].Equals(' ') && currentQuerySubstringIndex == 0)
+ if (fullStringToCompareWithoutCase[compareStringIndex] == ' ' && currentQuerySubstringIndex == 0)
{
spaceIndices.Add(compareStringIndex);
}
- if (fullStringToCompareWithoutCase[compareStringIndex] !=
+ // Acronym check
+ if (char.IsUpper(stringToCompare[compareStringIndex]) ||
+ char.IsNumber(stringToCompare[compareStringIndex]) ||
+ char.IsWhiteSpace(stringToCompare[compareStringIndex]) ||
+ spaceMet)
+ {
+ if (fullStringToCompareWithoutCase[compareStringIndex] ==
+ queryWithoutCase[currentAcronymQueryIndex])
+ {
+ currentAcronymQueryIndex++;
+
+ if (!spaceMet)
+ {
+ char currentCompareChar = stringToCompare[compareStringIndex];
+ spaceMet = char.IsWhiteSpace(currentCompareChar);
+ // if is space, no need to check whether upper or digit, though insignificant
+ if (!spaceMet && compareStringIndex == 0 || char.IsUpper(currentCompareChar) ||
+ char.IsDigit(currentCompareChar))
+ {
+ acronymMatchData.Add(compareStringIndex);
+ }
+ }
+ else if (!(spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex])))
+ {
+ acronymMatchData.Add(compareStringIndex);
+ }
+ }
+ else
+ {
+ spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex]);
+ // Acronym Penalty
+ if (!spaceMet)
+ {
+ acronymScore -= 10;
+ }
+ }
+ }
+ // Acronym end
+
+ if (allQuerySubstringsMatched || fullStringToCompareWithoutCase[compareStringIndex] !=
currentQuerySubstring[currentQuerySubstringCharacterIndex])
{
matchFoundInPreviousLoop = false;
+
continue;
}
+
if (firstMatchIndex < 0)
{
// first matched char will become the start of the compared string
@@ -174,8 +189,9 @@ namespace Flow.Launcher.Infrastructure
allQuerySubstringsMatched =
AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
+
if (allQuerySubstringsMatched)
- break;
+ continue;
// otherwise move to the next query substring
currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
@@ -183,6 +199,12 @@ namespace Flow.Launcher.Infrastructure
}
}
+ // return acronym Match if possible
+ if (acronymMatchData.Count == query.Length && acronymScore >= (int) UserSettingSearchPrecision)
+ {
+ acronymMatchData = acronymMatchData.Select(x => map?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
+ return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
+ }
// proceed to calculate score if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
@@ -249,6 +271,7 @@ namespace Flow.Launcher.Infrastructure
private static bool AllQuerySubstringsMatched(int currentQuerySubstringIndex, int querySubstringsLength)
{
+ // Acronym won't utilize the substring to match
return currentQuerySubstringIndex >= querySubstringsLength;
}
From d28b14ff2d4cb9a8d58d926f9d2542fd22941758 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 30 Dec 2020 13:40:42 +0800
Subject: [PATCH 066/308] Replace All use of Json.Net with System.Text.Json
---
Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs | 6 ++--
Flow.Launcher.Core/Plugin/PluginConfig.cs | 4 +--
Flow.Launcher.Core/Updater.cs | 1 -
Flow.Launcher.Infrastructure/Helper.cs | 28 +++++++++++++------
Flow.Launcher.Infrastructure/Logger/Log.cs | 2 +-
.../Storage/JsonStorage.cs | 16 +++++------
.../UserSettings/Settings.cs | 16 ++++++-----
Flow.Launcher.Plugin/PluginMetadata.cs | 3 +-
Flow.Launcher/Storage/QueryHistory.cs | 1 -
Flow.Launcher/Storage/TopMostRecord.cs | 3 +-
Flow.Launcher/Storage/UserSelectedRecord.cs | 2 --
.../Search/FolderLinks/FolderLink.cs | 8 +++---
.../Flow.Launcher.Plugin.Explorer/Settings.cs | 8 +-----
.../SearchSource.cs | 2 +-
.../Settings.cs | 2 +-
.../SuggestionSources/Baidu.cs | 20 +++++--------
.../SuggestionSources/Google.cs | 22 ++++++---------
17 files changed, 67 insertions(+), 77 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
index 31bf04286..3d4522498 100644
--- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
+++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
@@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
-using Newtonsoft.Json;
using Flow.Launcher.Infrastructure.Exception;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin;
@@ -65,7 +65,7 @@ namespace Flow.Launcher.Core.Plugin
{
List results = new List();
- JsonRPCQueryResponseModel queryResponseModel = JsonConvert.DeserializeObject(output);
+ JsonRPCQueryResponseModel queryResponseModel = JsonSerializer.Deserialize(output);
if (queryResponseModel.Result == null) return null;
foreach (JsonRPCResult result in queryResponseModel.Result)
@@ -84,7 +84,7 @@ namespace Flow.Launcher.Core.Plugin
else
{
string actionReponse = ExecuteCallback(result1.JsonRPCAction);
- JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject(actionReponse);
+ JsonRPCRequestModel jsonRpcRequestModel = JsonSerializer.Deserialize(actionReponse);
if (jsonRpcRequestModel != null
&& !String.IsNullOrEmpty(jsonRpcRequestModel.Method)
&& jsonRpcRequestModel.Method.StartsWith("Flow.Launcher."))
diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs
index b946fa44d..46f79c60c 100644
--- a/Flow.Launcher.Core/Plugin/PluginConfig.cs
+++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs
@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.Linq;
using System.IO;
-using Newtonsoft.Json;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin;
+using System.Text.Json;
namespace Flow.Launcher.Core.Plugin
{
@@ -61,7 +61,7 @@ namespace Flow.Launcher.Core.Plugin
PluginMetadata metadata;
try
{
- metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath));
+ metadata = JsonSerializer.Deserialize(File.ReadAllText(configPath));
metadata.PluginDirectory = pluginDirectory;
// for plugins which doesn't has ActionKeywords key
metadata.ActionKeywords = metadata.ActionKeywords ?? new List { metadata.ActionKeyword };
diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs
index 1e4b0453c..e1aa42730 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -13,7 +13,6 @@ using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
-using System.IO;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using System.Text.Json.Serialization;
diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs
index fa7e18533..331b3a823 100644
--- a/Flow.Launcher.Infrastructure/Helper.cs
+++ b/Flow.Launcher.Infrastructure/Helper.cs
@@ -1,12 +1,19 @@
-using System;
+using Newtonsoft.Json.Converters;
+using System;
using System.IO;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
+using System.Runtime.CompilerServices;
+using System.Text.Json;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Infrastructure
{
public static class Helper
{
+ static Helper()
+ {
+ jsonFormattedSerializerOptions.Converters.Add(new JsonStringEnumConverter());
+ }
+
///
/// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy
///
@@ -65,13 +72,18 @@ namespace Flow.Launcher.Infrastructure
}
}
+ private static readonly JsonSerializerOptions jsonFormattedSerializerOptions = new JsonSerializerOptions
+ {
+ WriteIndented = true
+ };
+
public static string Formatted(this T t)
{
- var formatted = JsonConvert.SerializeObject(
- t,
- Formatting.Indented,
- new StringEnumConverter()
- );
+ var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions
+ {
+ WriteIndented = true
+ });
+
return formatted;
}
}
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 289ec5d68..91eeb183d 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -128,7 +128,7 @@ namespace Flow.Launcher.Infrastructure.Logger
public static void Exception(string message, System.Exception e)
{
#if DEBUG
- throw e;
+ throw e;
#else
if (FormatValid(message))
{
diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
index 784c11110..268dc20b8 100644
--- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
@@ -1,7 +1,7 @@
using System;
using System.Globalization;
using System.IO;
-using Newtonsoft.Json;
+using System.Text.Json;
using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.Infrastructure.Storage
@@ -11,7 +11,7 @@ namespace Flow.Launcher.Infrastructure.Storage
///
public class JsonStrorage
{
- private readonly JsonSerializerSettings _serializerSettings;
+ private readonly JsonSerializerOptions _serializerSettings;
private T _data;
// need a new directory name
public const string DirectoryName = "Settings";
@@ -24,10 +24,9 @@ namespace Flow.Launcher.Infrastructure.Storage
{
// use property initialization instead of DefaultValueAttribute
// easier and flexible for default value of object
- _serializerSettings = new JsonSerializerSettings
+ _serializerSettings = new JsonSerializerOptions
{
- ObjectCreationHandling = ObjectCreationHandling.Replace,
- NullValueHandling = NullValueHandling.Ignore
+ IgnoreNullValues = false
};
}
@@ -56,7 +55,7 @@ namespace Flow.Launcher.Infrastructure.Storage
{
try
{
- _data = JsonConvert.DeserializeObject(searlized, _serializerSettings);
+ _data = JsonSerializer.Deserialize(searlized, _serializerSettings);
}
catch (JsonException e)
{
@@ -77,7 +76,7 @@ namespace Flow.Launcher.Infrastructure.Storage
BackupOriginFile();
}
- _data = JsonConvert.DeserializeObject("{}", _serializerSettings);
+ _data = JsonSerializer.Deserialize("{}", _serializerSettings);
Save();
}
@@ -94,7 +93,8 @@ namespace Flow.Launcher.Infrastructure.Storage
public void Save()
{
- string serialized = JsonConvert.SerializeObject(_data, Formatting.Indented);
+ string serialized = JsonSerializer.Serialize(_data, new JsonSerializerOptions() { WriteIndented = true });
+
File.WriteAllText(FilePath, serialized);
}
}
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index 832b6fbfa..bcfe298a9 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.ObjectModel;
using System.Drawing;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Converters;
+using System.Text.Json.Serialization;
using Flow.Launcher.Plugin;
namespace Flow.Launcher.Infrastructure.UserSettings
@@ -16,7 +15,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool ShowOpenResultHotkey { get; set; } = true;
public string Language
{
- get => language; set {
+ get => language; set
+ {
language = value;
OnPropertyChanged();
}
@@ -73,9 +73,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public int MaxResultsToShow { get; set; } = 5;
public int ActivateTimes { get; set; }
- // Order defaults to 0 or -1, so 1 will let this property appear last
- [JsonProperty(Order = 1)]
- public PluginsSettings PluginSettings { get; set; } = new PluginsSettings();
+
public ObservableCollection CustomPluginHotkeys { get; set; } = new ObservableCollection();
public bool DontPromptUpdateMsg { get; set; }
@@ -100,8 +98,12 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public HttpProxy Proxy { get; set; } = new HttpProxy();
- [JsonConverter(typeof(StringEnumConverter))]
+ [JsonConverter(typeof(JsonStringEnumConverter))]
public LastQueryMode LastQueryMode { get; set; } = LastQueryMode.Selected;
+
+
+ // Order defaults to 0 or -1, so 1 will let this property appear last
+ public PluginsSettings PluginSettings { get; set; } = new PluginsSettings();
}
public enum LastQueryMode
diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs
index d81b442e2..4c40be53c 100644
--- a/Flow.Launcher.Plugin/PluginMetadata.cs
+++ b/Flow.Launcher.Plugin/PluginMetadata.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Plugin
{
- [JsonObject(MemberSerialization.OptOut)]
public class PluginMetadata : BaseModel
{
private string _pluginDirectory;
diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs
index de3bcaa22..2b2103605 100644
--- a/Flow.Launcher/Storage/QueryHistory.cs
+++ b/Flow.Launcher/Storage/QueryHistory.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Newtonsoft.Json;
using Flow.Launcher.Plugin;
namespace Flow.Launcher.Storage
diff --git a/Flow.Launcher/Storage/TopMostRecord.cs b/Flow.Launcher/Storage/TopMostRecord.cs
index c110bdf92..09e69f6d8 100644
--- a/Flow.Launcher/Storage/TopMostRecord.cs
+++ b/Flow.Launcher/Storage/TopMostRecord.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
-using Newtonsoft.Json;
+using System.Text.Json;
using Flow.Launcher.Plugin;
namespace Flow.Launcher.Storage
@@ -8,7 +8,6 @@ namespace Flow.Launcher.Storage
// todo this class is not thread safe.... but used from multiple threads.
public class TopMostRecord
{
- [JsonProperty]
private Dictionary records = new Dictionary();
internal bool IsTopMost(Result result)
diff --git a/Flow.Launcher/Storage/UserSelectedRecord.cs b/Flow.Launcher/Storage/UserSelectedRecord.cs
index 1fda04e9b..c7ffe1a1d 100644
--- a/Flow.Launcher/Storage/UserSelectedRecord.cs
+++ b/Flow.Launcher/Storage/UserSelectedRecord.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using Newtonsoft.Json;
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Plugin;
@@ -7,7 +6,6 @@ namespace Flow.Launcher.Storage
{
public class UserSelectedRecord
{
- [JsonProperty]
private Dictionary records = new Dictionary();
public void Add(Result result)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs
index 379b5848f..43ecdad97 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs
@@ -1,15 +1,15 @@
-using Newtonsoft.Json;
-using System;
+using System;
using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Plugin.Explorer.Search.FolderLinks
{
- [JsonObject(MemberSerialization.OptIn)]
public class FolderLink
{
- [JsonProperty]
public string Path { get; set; }
+ [JsonIgnore]
public string Nickname
{
get
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
index 5b12870c8..e62ea93fc 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
@@ -1,28 +1,22 @@
using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.FolderLinks;
-using Newtonsoft.Json;
using System.Collections.Generic;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Plugin.Explorer
{
public class Settings
{
- [JsonProperty]
public int MaxResult { get; set; } = 100;
- [JsonProperty]
public List QuickFolderAccessLinks { get; set; } = new List();
- [JsonProperty]
public bool UseWindowsIndexForDirectorySearch { get; set; } = true;
- [JsonProperty]
public List IndexSearchExcludedSubdirectoryPaths { get; set; } = new List();
- [JsonProperty]
public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
- [JsonProperty]
public string FileContentSearchActionKeyword { get; set; } = Constants.DefaultContentSearchActionKeyword;
}
}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
index c7ccb4d51..98e9376fb 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
@@ -1,10 +1,10 @@
using System.IO;
using System.Windows.Media;
using JetBrains.Annotations;
-using Newtonsoft.Json;
using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure;
using System.Reflection;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Plugin.WebSearch
{
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs
index 555ee4647..e8881aae9 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.ObjectModel;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
using Flow.Launcher.Plugin.WebSearch.SuggestionSources;
namespace Flow.Launcher.Plugin.WebSearch
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
index 6772acf82..2e385510f 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
@@ -2,10 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
+using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
@@ -35,25 +34,20 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
Match match = _reg.Match(result);
if (match.Success)
{
- JContainer json;
+ JsonDocument json;
try
{
- json = JsonConvert.DeserializeObject(match.Groups[1].Value) as JContainer;
+ json = JsonDocument.Parse(match.Groups[1].Value);
}
- catch (JsonSerializationException e)
+ catch(JsonException e)
{
Log.Exception("|Baidu.Suggestions|can't parse suggestions", e);
return new List();
}
- if (json != null)
- {
- var results = json["s"] as JArray;
- if (results != null)
- {
- return results.OfType().Select(o => o.Value).OfType().ToList();
- }
- }
+ var results = json?.RootElement.GetProperty("s");
+
+ return results?.EnumerateArray().Select(o => o.GetString()).ToList() ?? new List();
}
return new List();
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
index 5b9538091..ff0906b87 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
@@ -3,11 +3,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
+using System.Text.Json;
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
@@ -27,25 +26,20 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
return new List();
}
if (string.IsNullOrEmpty(result)) return new List();
- JContainer json;
+ JsonDocument json;
try
{
- json = JsonConvert.DeserializeObject(result) as JContainer;
+ json = JsonDocument.Parse(result);
}
- catch (JsonSerializationException e)
+ catch (JsonException e)
{
Log.Exception("|Google.Suggestions|can't parse suggestions", e);
return new List();
}
- if (json != null)
- {
- var results = json[1] as JContainer;
- if (results != null)
- {
- return results.OfType().Select(o => o.Value).OfType().ToList();
- }
- }
- return new List();
+
+ var results = json?.RootElement.EnumerateArray().ElementAt(1);
+
+ return results?.EnumerateArray().Select(o => o.GetString()).ToList() ?? new List();
}
public override string ToString()
From 557842e8d797c3ca0146ed77d0a45906f5c6f3d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 30 Dec 2020 13:48:06 +0800
Subject: [PATCH 067/308] remove dependency
---
Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj | 1 -
Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj | 1 -
2 files changed, 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
index 28d4c0e1f..8153de6c8 100644
--- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
+++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
@@ -49,7 +49,6 @@
-
diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
index 70013c274..b7b52ac35 100644
--- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
+++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
@@ -62,7 +62,6 @@
-
\ No newline at end of file
From 7bbd8c6069ef038186482b50d731cec90396b987 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 30 Dec 2020 19:05:02 +0800
Subject: [PATCH 068/308] remove using from Helper.cs
---
Flow.Launcher.Infrastructure/Helper.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs
index 331b3a823..faa4c93b5 100644
--- a/Flow.Launcher.Infrastructure/Helper.cs
+++ b/Flow.Launcher.Infrastructure/Helper.cs
@@ -1,5 +1,4 @@
-using Newtonsoft.Json.Converters;
-using System;
+using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text.Json;
From a0c4cc35756c42d7351bee37c795e063fd933dd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 30 Dec 2020 19:09:52 +0800
Subject: [PATCH 069/308] use ParseAsync in Google
---
.../SuggestionSources/Google.cs | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
index ff0906b87..f23cb66ff 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
@@ -7,6 +7,7 @@ using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
using System.Text.Json;
+using System.IO;
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
@@ -14,22 +15,22 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public override async Task> Suggestions(string query)
{
- string result;
+ Stream resultStream;
try
{
const string api = "https://www.google.com/complete/search?output=chrome&q=";
- result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false);
+ resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false);
}
catch (HttpRequestException e)
{
Log.Exception("|Google.Suggestions|Can't get suggestion from google", e);
return new List();
}
- if (string.IsNullOrEmpty(result)) return new List();
+ if (resultStream.Length == 0) return new List();
JsonDocument json;
try
{
- json = JsonDocument.Parse(result);
+ json = await JsonDocument.ParseAsync(resultStream);
}
catch (JsonException e)
{
From 27a0b934c612b8d3a482722c53910b7487a973d7 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 18:39:41 +1100
Subject: [PATCH 070/308] update maintenance badge
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 02f488758..654877f3a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
-
+
[](https://ci.appveyor.com/project/JohnTheGr8/flow-launcher/branch/dev)
[](https://github.com/Flow-Launcher/Flow.Launcher/releases)
[](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest)
From a65e17dba00830c32c746d7dea3b737fc518fa7a Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 18:57:58 +1100
Subject: [PATCH 071/308] fix wrong error message
---
Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml | 4 +++-
Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 4 ++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
index 8d24c145c..eaea9783b 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
@@ -1,4 +1,4 @@
-
@@ -6,6 +6,8 @@
Downloading plugin
Please wait...
Successfully downloaded
+ Error downloading plugin
+ Error occured while trying to download the plugin
{0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart.
{0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart.
Plugin Install
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index ac15618ca..a378a9046 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -134,8 +134,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
}
catch (Exception e)
{
- Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
- Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"),
+ Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"));
Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload");
}
From 54f6858937fdf3445e8503e7da398bafd0efa4b5 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 19:03:06 +1100
Subject: [PATCH 072/308] add plugin name to error msg popup
---
Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml | 2 +-
Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
index eaea9783b..d0370ddc3 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
@@ -7,7 +7,7 @@
Please wait...
Successfully downloaded
Error downloading plugin
- Error occured while trying to download the plugin
+ Error occured while trying to download {0}
{0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart.
{0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart.
Plugin Install
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index a378a9046..9d9d50902 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -135,7 +135,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
catch (Exception e)
{
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"),
- Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"));
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"), plugin.Name));
Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload");
}
From cab1b93183d4a8170f3b589354e1159b8e92cd7c Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 19:13:14 +1100
Subject: [PATCH 073/308] move install method into try catch
---
.../Languages/en.xaml | 4 ++--
.../PluginsManager.cs | 9 +++++----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
index d0370ddc3..3017f39c3 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
@@ -6,13 +6,13 @@
Downloading plugin
Please wait...
Successfully downloaded
- Error downloading plugin
- Error occured while trying to download {0}
{0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart.
{0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart.
Plugin Install
Plugin Uninstall
Install failed: unable to find the plugin.json metadata file from the new plugin
+ Error installing plugin
+ Error occured while trying to install {0}
No update available
All plugins are up to date
{0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart.
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 9d9d50902..db0327111 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -131,16 +131,17 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
+
+ Install(plugin, filePath);
}
catch (Exception e)
{
- Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"),
- string.Format(Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"), plugin.Name));
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name));
- Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload");
+ Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate");
}
- Install(plugin, filePath);
Context.API.RestartApp();
}
From 878f7bf5dfb154a2bf663deaf9256ce73ba3de1d Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 19:49:19 +1100
Subject: [PATCH 074/308] version bump for PluginsManager
---
Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
index d94af71a1..7e78d65d6 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
@@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
- "Version": "1.3.1",
+ "Version": "1.3.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
From 81cb20bf91edb292eb35445861a25acec31a2445 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 1 Jan 2021 21:54:34 +1100
Subject: [PATCH 075/308] add return to continue
---
Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index db0327111..880157a77 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -140,6 +140,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name));
Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate");
+
+ return;
}
Context.API.RestartApp();
From 6d66aa3f4415f114f44bb6b962651f5d269783f6 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 00:06:55 +1100
Subject: [PATCH 076/308] fix script to delete with condition dll version is
same
---
Scripts/post_build.ps1 | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1
index 59036842a..b20393b02 100644
--- a/Scripts/post_build.ps1
+++ b/Scripts/post_build.ps1
@@ -44,8 +44,9 @@ function Delete-Unused ($path, $config) {
$target = "$path\Output\$config"
$included = Get-ChildItem $target -Filter "*.dll"
foreach ($i in $included){
- Remove-Item -Path $target\Plugins -Include $i -Recurse
- Write-Host "Deleting duplicated $i"
+ $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion}
+ $deleteList | foreach-object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName }
+ $deleteList | Remove-Item
}
Remove-Item -Path $target -Include "*.xml" -Recurse
}
From 29a382085fde4f5ac5ea173b5ccf338258d0c029 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 00:09:02 +1100
Subject: [PATCH 077/308] method name update
---
Scripts/post_build.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1
index b20393b02..e0868f3bb 100644
--- a/Scripts/post_build.ps1
+++ b/Scripts/post_build.ps1
@@ -45,7 +45,7 @@ function Delete-Unused ($path, $config) {
$included = Get-ChildItem $target -Filter "*.dll"
foreach ($i in $included){
$deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion}
- $deleteList | foreach-object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName }
+ $deleteList | ForEach-Object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName }
$deleteList | Remove-Item
}
Remove-Item -Path $target -Include "*.xml" -Recurse
From f1badd6ae20466ab720b516d544a4b5f58b64dff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Fri, 1 Jan 2021 21:19:05 +0800
Subject: [PATCH 078/308] Add Exception Handling for Querying plugins results
---
Flow.Launcher/ViewModel/MainViewModel.cs | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 7a3aa9f2f..2a69635bb 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -21,6 +21,7 @@ using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Storage;
using System.Windows.Media;
using Flow.Launcher.Infrastructure.Image;
+using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.ViewModel
{
@@ -414,8 +415,15 @@ namespace Flow.Launcher.ViewModel
{
if (!plugin.Metadata.Disabled)
{
- var results = PluginManager.QueryForPlugin(plugin, query);
- UpdateResultView(results, plugin.Metadata, query);
+ try
+ {
+ var results = PluginManager.QueryForPlugin(plugin, query);
+ UpdateResultView(results, plugin.Metadata, query);
+ }
+ catch(Exception e)
+ {
+ Log.Exception($"|MainViewModel|Exception when querying {plugin.Metadata.Name}", e);
+ }
}
});
}
@@ -432,7 +440,10 @@ namespace Flow.Launcher.ViewModel
{ // update to hidden if this is still the current query
ProgressBarVisibility = Visibility.Hidden;
}
- }, currentCancellationToken);
+ }, currentCancellationToken).ContinueWith(t =>
+ {
+ Log.Exception("|MainViewModel|Error when querying plugin", t.Exception?.InnerException);
+ }, TaskContinuationOptions.OnlyOnFaulted);
}
}
else
From f3355c525dfbdaa46ece70cb5197826c1bf354e9 Mon Sep 17 00:00:00 2001
From: Ioannis G
Date: Fri, 1 Jan 2021 23:15:37 +0200
Subject: [PATCH 079/308] fix: properly include all plugin translation files
---
...low.Launcher.Plugin.BrowserBookmark.csproj | 9 +---
.../Flow.Launcher.Plugin.Calculator.csproj | 44 +-----------------
.../Flow.Launcher.Plugin.ControlPanel.csproj | 45 +------------------
.../Flow.Launcher.Plugin.Explorer.csproj | 32 +------------
...low.Launcher.Plugin.PluginIndicator.csproj | 42 +----------------
.../Flow.Launcher.Plugin.ProcessKiller.csproj | 2 +-
.../Flow.Launcher.Plugin.Program.csproj | 27 +----------
.../Flow.Launcher.Plugin.Shell.csproj | 39 ++--------------
.../Flow.Launcher.Plugin.Sys.csproj | 27 +----------
.../Flow.Launcher.Plugin.Url.csproj | 36 +--------------
.../Flow.Launcher.Plugin.WebSearch.csproj | 27 +----------
11 files changed, 17 insertions(+), 313 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
index 85b745a6b..f308aa49a 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
@@ -43,11 +43,6 @@
Always
-
- Designer
- MSBuild:Compile
- PreserveNewest
-
Always
@@ -60,9 +55,9 @@
-
+
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
index 9e1fefdb3..983ac160e 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
@@ -49,49 +49,9 @@
PreserveNewest
-
+
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
index 699737634..dce54cb52 100644
--- a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
@@ -48,50 +48,7 @@
PreserveNewest
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
index a1a08843a..a9f675be8 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
@@ -62,37 +62,7 @@
PreserveNewest
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
index e6bfa7aa3..6abfc8469 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
@@ -52,47 +52,7 @@
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
index cf9c96294..a393d8510 100644
--- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
@@ -39,7 +39,7 @@
PreserveNewest
-
+
Designer
MSBuild:Compile
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index 3802297c7..7e1b36fc1 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -68,35 +68,10 @@
Always
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
index 178d95010..316742bf6 100644
--- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
@@ -33,32 +33,6 @@
4
false
-
-
-
- Always
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
@@ -72,18 +46,13 @@
+
+ Always
+
PreserveNewest
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
index bdab40457..61635dd08 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
@@ -52,32 +52,7 @@
PreserveNewest
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
index 7d802d815..fb40c1e17 100644
--- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
@@ -50,41 +50,9 @@
PreserveNewest
-
+
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
-
-
-
+
MSBuild:Compile
Designer
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
index 431ca9ce8..e3bb4b408 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
@@ -89,32 +89,7 @@
PreserveNewest
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
- MSBuild:Compile
- Designer
- PreserveNewest
-
-
+
MSBuild:Compile
Designer
PreserveNewest
From 8ab528c380acd0515b6576e74f76300763bd3bd6 Mon Sep 17 00:00:00 2001
From: Ioannis G
Date: Sat, 2 Jan 2021 00:00:12 +0200
Subject: [PATCH 080/308] fix slovak translation
---
Flow.Launcher/Languages/sk.xaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml
index bf001d507..85fc1462c 100644
--- a/Flow.Launcher/Languages/sk.xaml
+++ b/Flow.Launcher/Languages/sk.xaml
@@ -45,8 +45,8 @@
Nová akcia skratky:
Priečinok s pluginmi
Autor
- Príprava: {0}ms
- Čas dopytu: {0}ms
+ Príprava:
+ Čas dopytu:
Motív
From 75f5a81a31ead865464f6a11f61f4c8fcf8d7cb6 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 11:55:06 +1100
Subject: [PATCH 081/308] update exception message
---
Flow.Launcher/ViewModel/MainViewModel.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 2a69635bb..eed30f377 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -422,7 +422,7 @@ namespace Flow.Launcher.ViewModel
}
catch(Exception e)
{
- Log.Exception($"|MainViewModel|Exception when querying {plugin.Metadata.Name}", e);
+ Log.Exception("MainViewModel", $"Exception when querying the plugin {plugin.Metadata.Name}", e, "QueryResults");
}
}
});
@@ -442,7 +442,7 @@ namespace Flow.Launcher.ViewModel
}
}, currentCancellationToken).ContinueWith(t =>
{
- Log.Exception("|MainViewModel|Error when querying plugin", t.Exception?.InnerException);
+ Log.Exception("MainViewModel", "Error when querying plugins", t.Exception?.InnerException, "QueryResults");
}, TaskContinuationOptions.OnlyOnFaulted);
}
}
From 041bf4e9c4860b9114a95741fcb036d2f969d208 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 12:10:06 +1100
Subject: [PATCH 082/308] add condition to match name also
---
Scripts/post_build.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1
index e0868f3bb..836e27380 100644
--- a/Scripts/post_build.ps1
+++ b/Scripts/post_build.ps1
@@ -44,7 +44,7 @@ function Delete-Unused ($path, $config) {
$target = "$path\Output\$config"
$included = Get-ChildItem $target -Filter "*.dll"
foreach ($i in $included){
- $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion}
+ $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where { $_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion -And $_.Name -eq "$i" }
$deleteList | ForEach-Object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName }
$deleteList | Remove-Item
}
From be1776fd2153f6bc9fbefbce71b313ea9ab9789e Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 12:47:20 +1100
Subject: [PATCH 083/308] version bump for plugins
---
Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Calculator/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Explorer/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json | 2 +-
.../Flow.Launcher.Plugin.PluginsManager.csproj | 2 +-
Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Program/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Sys/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.Url/plugin.json | 2 +-
Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json | 2 +-
13 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json
index de4f3849b..b0c3d2e29 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json
@@ -4,7 +4,7 @@
"Name": "Browser Bookmarks",
"Description": "Search your browser bookmarks",
"Author": "qianlifeng, Ioannis G.",
- "Version": "1.3.1",
+ "Version": "1.3.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.BrowserBookmark.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json
index 709757d1a..7d9ca58d5 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json
@@ -4,7 +4,7 @@
"Name": "Calculator",
"Description": "Provide mathematical calculations.(Try 5*3-2 in Flow Launcher)",
"Author": "cxfksword",
- "Version": "1.1.3",
+ "Version": "1.1.4",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Caculator.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json b/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json
index 4f552a014..23f35e9ac 100644
--- a/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json
@@ -4,7 +4,7 @@
"Name": "Control Panel",
"Description": "Search within the Control Panel.",
"Author": "CoenraadS",
- "Version": "1.1.1",
+ "Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.ControlPanel.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
index 2c57ac668..aa44c4413 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
@@ -7,7 +7,7 @@
"Name": "Explorer",
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
"Author": "Jeremy Wu",
- "Version": "1.2.5",
+ "Version": "1.2.6",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json
index 80900a445..7f73263a8 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json
@@ -4,7 +4,7 @@
"Name": "Plugin Indicator",
"Description": "Provide plugin actionword suggestion",
"Author": "qianlifeng",
- "Version": "1.1.1",
+ "Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginIndicator.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
index cc1a931ce..7beb8308b 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
@@ -35,7 +35,7 @@
-
+
PreserveNewest
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
index d94af71a1..7e78d65d6 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
@@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
- "Version": "1.3.1",
+ "Version": "1.3.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json
index d769397a8..2bb40c644 100644
--- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json
@@ -4,7 +4,7 @@
"Name":"Process Killer",
"Description":"kill running processes from Flow",
"Author":"Flow-Launcher",
- "Version":"1.2.1",
+ "Version":"1.2.2",
"Language":"csharp",
"Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller",
"IcoPath":"Images\\app.png",
diff --git a/Plugins/Flow.Launcher.Plugin.Program/plugin.json b/Plugins/Flow.Launcher.Plugin.Program/plugin.json
index 7d7a42e03..6c2c18e47 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Program/plugin.json
@@ -4,7 +4,7 @@
"Name": "Program",
"Description": "Search programs in Flow.Launcher",
"Author": "qianlifeng",
- "Version": "1.2.2",
+ "Version": "1.2.3",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Program.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json
index 63e74d678..4ad572cf6 100644
--- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json
@@ -4,7 +4,7 @@
"Name": "Shell",
"Description": "Provide executing commands from Flow Launcher. Commands should start with >",
"Author": "qianlifeng",
- "Version": "1.1.1",
+ "Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json
index 8d4b9a238..cf8ed6041 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json
@@ -4,7 +4,7 @@
"Name": "System Commands",
"Description": "Provide System related commands. e.g. shutdown,lock,setting etc.",
"Author": "qianlifeng",
- "Version": "1.1.1",
+ "Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.Url/plugin.json b/Plugins/Flow.Launcher.Plugin.Url/plugin.json
index be64f6708..89dc20a33 100644
--- a/Plugins/Flow.Launcher.Plugin.Url/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Url/plugin.json
@@ -4,7 +4,7 @@
"Name": "URL",
"Description": "Open the typed URL from Flow Launcher",
"Author": "qianlifeng",
- "Version": "1.1.1",
+ "Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Url.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
index 99fd2210a..c036fbf8b 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
@@ -25,7 +25,7 @@
"Name": "Web Searches",
"Description": "Provide the web search ability",
"Author": "qianlifeng",
- "Version": "1.2.0",
+ "Version": "1.2.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll",
From 08f97f0ef9236e4572d7a707741488cddb568d38 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 12:57:13 +1100
Subject: [PATCH 084/308] change csproj images folder to use wildcard
---
...low.Launcher.Plugin.BrowserBookmark.csproj | 6 +-
.../Flow.Launcher.Plugin.Calculator.csproj | 9 +--
.../Flow.Launcher.Plugin.ControlPanel.csproj | 4 +-
.../Flow.Launcher.Plugin.Explorer.csproj | 35 +----------
...low.Launcher.Plugin.PluginIndicator.csproj | 9 +--
...Flow.Launcher.Plugin.PluginsManager.csproj | 9 +--
.../Flow.Launcher.Plugin.ProcessKiller.csproj | 6 +-
.../Flow.Launcher.Plugin.Program.csproj | 21 +------
.../Flow.Launcher.Plugin.Shell.csproj | 9 +--
.../Flow.Launcher.Plugin.Sys.csproj | 50 +--------------
.../Flow.Launcher.Plugin.Url.csproj | 9 +--
.../Flow.Launcher.Plugin.WebSearch.csproj | 63 +------------------
12 files changed, 33 insertions(+), 197 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
index f308aa49a..d2a8736a6 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj
@@ -40,9 +40,6 @@
-
- Always
-
Always
@@ -62,6 +59,9 @@
Designer
PreserveNewest
+
+ PreserveNewest
+
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
index 983ac160e..06d8dea7d 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
@@ -43,12 +43,6 @@
-
-
-
- PreserveNewest
-
-
@@ -56,6 +50,9 @@
Designer
PreserveNewest
+
+ PreserveNewest
+
diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
index dce54cb52..06969a135 100644
--- a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj
@@ -45,9 +45,9 @@
-
+
PreserveNewest
-
+
MSBuild:Compile
Designer
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
index a9f675be8..9d9c09a93 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
@@ -26,42 +26,9 @@
-
- PreserveNewest
-
-
-
- PreserveNewest
-
-
-
- PreserveNewest
-
-
-
- PreserveNewest
-
-
-
- Always
-
-
-
+
PreserveNewest
-
-
- PreserveNewest
-
-
-
- PreserveNewest
-
-
-
- PreserveNewest
-
-
MSBuild:Compile
Designer
diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
index 6abfc8469..0140444e1 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
@@ -45,18 +45,15 @@
-
-
- PreserveNewest
-
-
-
MSBuild:Compile
Designer
PreserveNewest
+
+ PreserveNewest
+
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
index 7beb8308b..2e352d832 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj
@@ -27,17 +27,14 @@
PreserveNewest
-
-
-
- PreserveNewest
-
-
PreserveNewest
+
+ PreserveNewest
+
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
index a393d8510..a643ebf86 100644
--- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj
@@ -36,14 +36,14 @@
-
- PreserveNewest
-
Designer
MSBuild:Compile
PreserveNewest
+
+ PreserveNewest
+
Always
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index 7e1b36fc1..12e113855 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -52,30 +52,15 @@
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- Always
-
-
-
MSBuild:Compile
Designer
PreserveNewest
+
+ PreserveNewest
+
diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
index 316742bf6..c542dc89b 100644
--- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj
@@ -46,17 +46,14 @@
-
- Always
-
-
- PreserveNewest
-
MSBuild:Compile
Designer
PreserveNewest
+
+ PreserveNewest
+
MSBuild:Compile
Designer
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
index 61635dd08..8ef4dc0fb 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj
@@ -40,23 +40,14 @@
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
MSBuild:Compile
Designer
PreserveNewest
+
+ PreserveNewest
+
MSBuild:Compile
Designer
@@ -68,39 +59,4 @@
PreserveNewest
-
-
-
- PreserveNewest
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
index fb40c1e17..671a8b1c2 100644
--- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj
@@ -44,12 +44,6 @@
-
-
-
- PreserveNewest
-
-
@@ -57,6 +51,9 @@
Designer
PreserveNewest
+
+ PreserveNewest
+
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
index e3bb4b408..af86af842 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
@@ -35,65 +35,14 @@
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
MSBuild:Compile
Designer
PreserveNewest
+
+ PreserveNewest
+
MSBuild:Compile
Designer
@@ -109,12 +58,6 @@
PreserveNewest
-
-
-
- PreserveNewest
-
-
From 482988c288392af9b1bf2a911a6eb798c54f11ff Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 12:59:58 +1100
Subject: [PATCH 085/308] use wild card to include images for main project
---
Flow.Launcher/Flow.Launcher.csproj | 108 +----------------------------
1 file changed, 3 insertions(+), 105 deletions(-)
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 8548ba39e..39b2087aa 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -60,6 +60,9 @@
Designer
PreserveNewest
+
+ PreserveNewest
+
@@ -87,111 +90,6 @@
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
-
From 97ac42751717121f5db1c695b81d5aed98df191f Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 16:58:23 +1100
Subject: [PATCH 086/308] add manual reload of PluginsManifest data
---
Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
index d700b9dfd..7c1eda3aa 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.PluginsManager
{
- public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n
+ public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n, IReloadable
{
internal PluginInitContext Context { get; set; }
@@ -87,5 +87,14 @@ namespace Flow.Launcher.Plugin.PluginsManager
{
return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description");
}
+
+ public void ReloadData()
+ {
+ Task.Run(async () =>
+ {
+ await pluginManager.UpdateManifest();
+ lastUpdateTime = DateTime.Now;
+ });
+ }
}
}
From 661c64b1c21b5e744ac4029b68e70d095a2074e2 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 17:00:10 +1100
Subject: [PATCH 087/308] version bump for PluginsManager
---
Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
index 7e78d65d6..f5bbf3f6b 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
@@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
- "Version": "1.3.2",
+ "Version": "1.4.0",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
From b4b30dd34da9426a6f512966fca780c5d5ef1437 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Sat, 2 Jan 2021 18:06:44 +1100
Subject: [PATCH 088/308] wait manifest update before proceeding
---
Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
index 7c1eda3aa..f10f022d7 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
@@ -90,11 +90,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
public void ReloadData()
{
- Task.Run(async () =>
- {
- await pluginManager.UpdateManifest();
- lastUpdateTime = DateTime.Now;
- });
+ Task.Run(() => pluginManager.UpdateManifest()).Wait();
+ lastUpdateTime = DateTime.Now;
}
}
}
From 3cd609377e7402669c8dbbf67140bb58551d8ae9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Sat, 2 Jan 2021 15:52:41 +0800
Subject: [PATCH 089/308] Plugin Async ModelAdd Full Async model, including
AsyncPlugin and AsyncReloadable
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 150 ++++++++++++------
Flow.Launcher.Infrastructure/Stopwatch.cs | 32 +++-
Flow.Launcher.Plugin/IAsyncPlugin.cs | 12 ++
Flow.Launcher.Plugin/IPlugin.cs | 1 +
Flow.Launcher.Plugin/IPublicAPI.cs | 3 +-
.../Interfaces/IAsyncReloadable.cs | 9 ++
Flow.Launcher.Plugin/PluginPair.cs | 2 +-
Flow.Launcher/PublicAPIInstance.cs | 4 +-
Flow.Launcher/ViewModel/MainViewModel.cs | 38 ++---
.../ControlPanelList.cs | 2 +-
Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 41 +++--
11 files changed, 210 insertions(+), 84 deletions(-)
create mode 100644 Flow.Launcher.Plugin/IAsyncPlugin.cs
create mode 100644 Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 3b697a1ee..239f0499d 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
@@ -32,7 +33,7 @@ namespace Flow.Launcher.Core.Plugin
///
/// Directories that will hold Flow Launcher plugin directory
///
- private static readonly string[] Directories = { Constant.PreinstalledDirectory, DataLocation.PluginsDirectory };
+ private static readonly string[] Directories = {Constant.PreinstalledDirectory, DataLocation.PluginsDirectory};
private static void DeletePythonBinding()
{
@@ -52,12 +53,19 @@ namespace Flow.Launcher.Core.Plugin
}
}
- public static void ReloadData()
+ public static async Task ReloadData()
{
foreach(var plugin in AllPlugins)
{
- var reloadablePlugin = plugin.Plugin as IReloadable;
- reloadablePlugin?.ReloadData();
+ switch (plugin.Plugin)
+ {
+ case IReloadable p:
+ p.ReloadData();
+ break;
+ case IAsyncReloadable p:
+ await p.ReloadDataAsync();
+ break;
+ }
}
}
@@ -86,24 +94,50 @@ namespace Flow.Launcher.Core.Plugin
/// Call initialize for all plugins
///
/// return the list of failed to init plugins or null for none
- public static void InitializePlugins(IPublicAPI api)
+ public static async Task InitializePlugins(IPublicAPI api)
{
API = api;
var failedPlugins = new ConcurrentQueue();
- Parallel.ForEach(AllPlugins, pair =>
+
+ var InitTasks = AllPlugins.Select(pair => Task.Run(async delegate
{
try
{
- var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
+ long milliseconds;
+
+ switch (pair.Plugin)
{
- pair.Plugin.Init(new PluginInitContext
- {
- CurrentPluginMetadata = pair.Metadata,
- API = API
- });
- });
+ case IAsyncPlugin plugin:
+ milliseconds = await Stopwatch.DebugAsync(
+ $"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>",
+ async delegate
+ {
+ await plugin.InitAsync(new PluginInitContext
+ {
+ CurrentPluginMetadata = pair.Metadata,
+ API = API
+ });
+ });
+ break;
+ case IPlugin plugin:
+ milliseconds = Stopwatch.Debug(
+ $"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>",
+ () =>
+ {
+ plugin.Init(new PluginInitContext
+ {
+ CurrentPluginMetadata = pair.Metadata,
+ API = API
+ });
+ });
+ break;
+ default:
+ throw new ArgumentException();
+ }
+
pair.Metadata.InitTime += milliseconds;
- Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
+ Log.Info(
+ $"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
}
catch (Exception e)
{
@@ -111,25 +145,33 @@ namespace Flow.Launcher.Core.Plugin
pair.Metadata.Disabled = true;
failedPlugins.Enqueue(pair);
}
- });
+ }));
+
+ await Task.WhenAll(InitTasks);
_contextMenuPlugins = GetPluginsForInterface();
foreach (var plugin in AllPlugins)
{
- if (IsGlobalPlugin(plugin.Metadata))
- GlobalPlugins.Add(plugin);
-
- // Plugins may have multiple ActionKeywords, eg. WebSearch
- plugin.Metadata.ActionKeywords
- .Where(x => x != Query.GlobalPluginWildcardSign)
- .ToList()
- .ForEach(x => NonGlobalPlugins[x] = plugin);
+ foreach (var actionKeyword in plugin.Metadata.ActionKeywords)
+ {
+ switch (actionKeyword)
+ {
+ case Query.GlobalPluginWildcardSign:
+ GlobalPlugins.Add(plugin);
+ break;
+ default:
+ NonGlobalPlugins[actionKeyword] = plugin;
+ break;
+ }
+ }
}
if (failedPlugins.Any())
{
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
- API.ShowMsg($"Fail to Init Plugins", $"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help", "", false);
+ API.ShowMsg($"Fail to Init Plugins",
+ $"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help",
+ "", false);
}
}
@@ -138,7 +180,7 @@ namespace Flow.Launcher.Core.Plugin
if (NonGlobalPlugins.ContainsKey(query.ActionKeyword))
{
var plugin = NonGlobalPlugins[query.ActionKeyword];
- return new List { plugin };
+ return new List {plugin};
}
else
{
@@ -146,25 +188,42 @@ namespace Flow.Launcher.Core.Plugin
}
}
- public static List QueryForPlugin(PluginPair pair, Query query)
+ public static async Task> QueryForPlugin(PluginPair pair, Query query, CancellationToken token)
{
var results = new List();
try
{
var metadata = pair.Metadata;
- var milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", () =>
- {
- results = pair.Plugin.Query(query) ?? new List();
- UpdatePluginMetadata(results, metadata, query);
- });
+ var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}",
+ async () =>
+ {
+ switch (pair.Plugin)
+ {
+ case IAsyncPlugin plugin:
+ results = await plugin.QueryAsync(query, token).ConfigureAwait(false) ??
+ new List();
+ UpdatePluginMetadata(results, metadata, query);
+ break;
+ case IPlugin plugin:
+ results = await Task.Run(() => plugin.Query(query), token).ConfigureAwait(false) ??
+ new List();
+ UpdatePluginMetadata(results, metadata, query);
+ break;
+ }
+ });
metadata.QueryCount += 1;
- metadata.AvgQueryTime = metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
+ metadata.AvgQueryTime =
+ metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
}
catch (Exception e)
{
- Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e);
+ Log.Exception(
+ $"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>",
+ e);
}
- return results;
+
+ // null will be fine since the results will only be added into queue if the token hasn't been cancelled
+ return token.IsCancellationRequested ? results = null : results;
}
public static void UpdatePluginMetadata(List results, PluginMetadata metadata, Query query)
@@ -182,11 +241,6 @@ namespace Flow.Launcher.Core.Plugin
}
}
- private static bool IsGlobalPlugin(PluginMetadata metadata)
- {
- return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
- }
-
///
/// get specified plugin, return null if not found
///
@@ -208,7 +262,7 @@ namespace Flow.Launcher.Core.Plugin
var pluginPair = _contextMenuPlugins.FirstOrDefault(o => o.Metadata.ID == result.PluginID);
if (pluginPair != null)
{
- var plugin = (IContextMenu)pluginPair.Plugin;
+ var plugin = (IContextMenu) pluginPair.Plugin;
try
{
@@ -222,16 +276,19 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>", e);
+ Log.Exception(
+ $"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>",
+ e);
}
}
+
return results;
}
public static bool ActionKeywordRegistered(string actionKeyword)
{
return actionKeyword != Query.GlobalPluginWildcardSign
- && NonGlobalPlugins.ContainsKey(actionKeyword);
+ && NonGlobalPlugins.ContainsKey(actionKeyword);
}
///
@@ -249,6 +306,7 @@ namespace Flow.Launcher.Core.Plugin
{
NonGlobalPlugins[newActionKeyword] = plugin;
}
+
plugin.Metadata.ActionKeywords.Add(newActionKeyword);
}
@@ -262,9 +320,9 @@ namespace Flow.Launcher.Core.Plugin
if (oldActionkeyword == Query.GlobalPluginWildcardSign
&& // Plugins may have multiple ActionKeywords that are global, eg. WebSearch
plugin.Metadata.ActionKeywords
- .Where(x => x == Query.GlobalPluginWildcardSign)
- .ToList()
- .Count == 1)
+ .Where(x => x == Query.GlobalPluginWildcardSign)
+ .ToList()
+ .Count == 1)
{
GlobalPlugins.Remove(plugin);
}
@@ -285,4 +343,4 @@ namespace Flow.Launcher.Core.Plugin
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Flow.Launcher.Infrastructure/Stopwatch.cs b/Flow.Launcher.Infrastructure/Stopwatch.cs
index d39d90e81..dd6edaff9 100644
--- a/Flow.Launcher.Infrastructure/Stopwatch.cs
+++ b/Flow.Launcher.Infrastructure/Stopwatch.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.Infrastructure
@@ -22,7 +23,22 @@ namespace Flow.Launcher.Infrastructure
Log.Debug(info);
return milliseconds;
}
-
+
+ ///
+ /// This stopwatch will appear only in Debug mode
+ ///
+ public static async Task DebugAsync(string message, Func action)
+ {
+ var stopWatch = new System.Diagnostics.Stopwatch();
+ stopWatch.Start();
+ await action();
+ stopWatch.Stop();
+ var milliseconds = stopWatch.ElapsedMilliseconds;
+ string info = $"{message} <{milliseconds}ms>";
+ Log.Debug(info);
+ return milliseconds;
+ }
+
public static long Normal(string message, Action action)
{
var stopWatch = new System.Diagnostics.Stopwatch();
@@ -34,6 +50,20 @@ namespace Flow.Launcher.Infrastructure
Log.Info(info);
return milliseconds;
}
+
+ public static async Task NormalAsync(string message, Func action)
+ {
+ var stopWatch = new System.Diagnostics.Stopwatch();
+ stopWatch.Start();
+ await action();
+ stopWatch.Stop();
+ var milliseconds = stopWatch.ElapsedMilliseconds;
+ string info = $"{message} <{milliseconds}ms>";
+ Log.Info(info);
+ return milliseconds;
+ }
+
+
public static void StartCount(string name, Action action)
{
diff --git a/Flow.Launcher.Plugin/IAsyncPlugin.cs b/Flow.Launcher.Plugin/IAsyncPlugin.cs
new file mode 100644
index 000000000..36f098e7d
--- /dev/null
+++ b/Flow.Launcher.Plugin/IAsyncPlugin.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Flow.Launcher.Plugin
+{
+ public interface IAsyncPlugin
+ {
+ Task> QueryAsync(Query query, CancellationToken token);
+ Task InitAsync(PluginInitContext context);
+ }
+}
\ No newline at end of file
diff --git a/Flow.Launcher.Plugin/IPlugin.cs b/Flow.Launcher.Plugin/IPlugin.cs
index 8f7d279fa..4cc6d8d40 100644
--- a/Flow.Launcher.Plugin/IPlugin.cs
+++ b/Flow.Launcher.Plugin/IPlugin.cs
@@ -5,6 +5,7 @@ namespace Flow.Launcher.Plugin
public interface IPlugin
{
List Query(Query query);
+
void Init(PluginInitContext context);
}
}
\ No newline at end of file
diff --git a/Flow.Launcher.Plugin/IPublicAPI.cs b/Flow.Launcher.Plugin/IPublicAPI.cs
index ccc00d5e9..12e430e07 100644
--- a/Flow.Launcher.Plugin/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/IPublicAPI.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace Flow.Launcher.Plugin
{
@@ -34,7 +35,7 @@ namespace Flow.Launcher.Plugin
/// Plugin's in memory data with new content
/// added by user.
///
- void ReloadAllPluginData();
+ Task ReloadAllPluginData();
///
/// Check for new Flow Launcher update
diff --git a/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs b/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs
new file mode 100644
index 000000000..9c922f667
--- /dev/null
+++ b/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Flow.Launcher.Plugin
+{
+ public interface IAsyncReloadable
+ {
+ Task ReloadDataAsync();
+ }
+}
\ No newline at end of file
diff --git a/Flow.Launcher.Plugin/PluginPair.cs b/Flow.Launcher.Plugin/PluginPair.cs
index 910367ec6..e8954b7a0 100644
--- a/Flow.Launcher.Plugin/PluginPair.cs
+++ b/Flow.Launcher.Plugin/PluginPair.cs
@@ -2,7 +2,7 @@
{
public class PluginPair
{
- public IPlugin Plugin { get; internal set; }
+ public object Plugin { get; internal set; }
public PluginMetadata Metadata { get; internal set; }
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 90d4fff63..bcf147be7 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -78,9 +78,9 @@ namespace Flow.Launcher
ImageLoader.Save();
}
- public void ReloadAllPluginData()
+ public async Task ReloadAllPluginData()
{
- PluginManager.ReloadData();
+ await PluginManager.ReloadData();
}
public void ShowMsg(string title, string subTitle = "", string iconPath = "")
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index eed30f377..bc68eb6d6 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -405,45 +405,47 @@ namespace Flow.Launcher.ViewModel
}, currentCancellationToken);
var plugins = PluginManager.ValidPluginsForQuery(query);
- Task.Run(() =>
+ Task.Run(async () =>
{
// so looping will stop once it was cancelled
+
+ Task[] tasks = new Task[plugins.Count];
var parallelOptions = new ParallelOptions { CancellationToken = currentCancellationToken };
try
{
- Parallel.ForEach(plugins, parallelOptions, plugin =>
+ Parallel.For(0, plugins.Count, parallelOptions, i =>
{
- if (!plugin.Metadata.Disabled)
+ if (!plugins[i].Metadata.Disabled)
{
- try
- {
- var results = PluginManager.QueryForPlugin(plugin, query);
- UpdateResultView(results, plugin.Metadata, query);
- }
- catch(Exception e)
- {
- Log.Exception("MainViewModel", $"Exception when querying the plugin {plugin.Metadata.Name}", e, "QueryResults");
- }
+ tasks[i] = QueryTask(i, query, currentCancellationToken);
}
+ else tasks[i] = Task.CompletedTask; // Avoid Null
});
+
+ // Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first
+ await Task.WhenAll(tasks);
}
catch (OperationCanceledException)
{
// nothing to do here
}
-
// this should happen once after all queries are done so progress bar should continue
// until the end of all querying
_isQueryRunning = false;
- if (currentUpdateSource == _updateSource)
+ if (!currentCancellationToken.IsCancellationRequested)
{ // update to hidden if this is still the current query
ProgressBarVisibility = Visibility.Hidden;
}
- }, currentCancellationToken).ContinueWith(t =>
- {
- Log.Exception("MainViewModel", "Error when querying plugins", t.Exception?.InnerException, "QueryResults");
- }, TaskContinuationOptions.OnlyOnFaulted);
+
+ async Task QueryTask(int pairIndex, Query query, CancellationToken token)
+ {
+ var result = await PluginManager.QueryForPlugin(plugins[pairIndex], query, token);
+ UpdateResultView(result, plugins[pairIndex].Metadata, query);
+ }
+
+ }, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
+ TaskContinuationOptions.OnlyOnFaulted);
}
}
else
diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/ControlPanelList.cs b/Plugins/Flow.Launcher.Plugin.ControlPanel/ControlPanelList.cs
index fdcffb0b3..70afda536 100644
--- a/Plugins/Flow.Launcher.Plugin.ControlPanel/ControlPanelList.cs
+++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/ControlPanelList.cs
@@ -38,7 +38,7 @@ namespace Flow.Launcher.Plugin.ControlPanel
int cxDesired, int cyDesired, uint fuLoad);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
- extern static bool DestroyIcon(IntPtr handle);
+ static extern bool DestroyIcon(IntPtr handle);
[DllImport("kernel32.dll")]
static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
index 5642b62ed..7ebab91a1 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
@@ -67,13 +68,15 @@ namespace Flow.Launcher.Plugin.Sys
{
c.TitleHighlightData = titleMatch.MatchData;
}
- else
+ else
{
c.SubTitleHighlightData = subTitleMatch.MatchData;
}
+
results.Add(c);
}
}
+
return results;
}
@@ -94,13 +97,15 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\shutdown.png",
Action = c =>
{
- var reuslt = MessageBox.Show(context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"),
- context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"),
- MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ var reuslt = MessageBox.Show(
+ context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"),
+ context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"),
+ MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (reuslt == MessageBoxResult.Yes)
{
Process.Start("shutdown", "/s /t 0");
}
+
return true;
}
},
@@ -111,13 +116,15 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\restart.png",
Action = c =>
{
- var result = MessageBox.Show(context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"),
- context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
- MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ var result = MessageBox.Show(
+ context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"),
+ context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
+ MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result == MessageBoxResult.Yes)
{
Process.Start("shutdown", "/r /t 0");
}
+
return true;
}
},
@@ -163,14 +170,16 @@ namespace Flow.Launcher.Plugin.Sys
// http://www.pinvoke.net/default.aspx/shell32/SHEmptyRecycleBin.html
// FYI, couldn't find documentation for this but if the recycle bin is already empty, it will return -2147418113 (0x8000FFFF (E_UNEXPECTED))
// 0 for nothing
- var result = SHEmptyRecycleBin(new WindowInteropHelper(Application.Current.MainWindow).Handle, 0);
- if (result != (uint) HRESULT.S_OK && result != (uint)0x8000FFFF)
+ var result = SHEmptyRecycleBin(new WindowInteropHelper(Application.Current.MainWindow).Handle,
+ 0);
+ if (result != (uint) HRESULT.S_OK && result != (uint) 0x8000FFFF)
{
MessageBox.Show($"Error emptying recycle bin, error code: {result}\n" +
"please refer to https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137",
- "Error",
- MessageBoxButton.OK, MessageBoxImage.Error);
+ "Error",
+ MessageBoxButton.OK, MessageBoxImage.Error);
}
+
return true;
}
},
@@ -229,9 +238,13 @@ namespace Flow.Launcher.Plugin.Sys
{
// Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen.
Application.Current.MainWindow.Hide();
- context.API.ReloadAllPluginData();
- context.API.ShowMsg(context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"),
- context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded"));
+
+ context.API.ReloadAllPluginData().ContinueWith(_ =>
+ context.API.ShowMsg(
+ context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"),
+ context.API.GetTranslation(
+ "flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded")));
+
return true;
}
},
From b8f7d899709ee4204d2a0f1cfae8722a2b80cdbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Sat, 2 Jan 2021 17:25:13 +0800
Subject: [PATCH 090/308] Allows Loading both IPlugin and IAsyncPlugin
---
.../Plugin/PluginAssemblyLoader.cs | 10 +-
Flow.Launcher.Core/Plugin/PluginsLoader.cs | 100 +++++++++---------
Flow.Launcher/ViewModel/MainViewModel.cs | 9 +-
3 files changed, 61 insertions(+), 58 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs
index b9b878a7b..1a1b17539 100644
--- a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs
@@ -20,7 +20,7 @@ namespace Flow.Launcher.Core.Plugin
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyFilePath));
- referencedPluginPackageDependencyResolver =
+ referencedPluginPackageDependencyResolver =
new AssemblyDependencyResolver(Path.Combine(Constant.ProgramDirectory, "Flow.Launcher.Plugin.dll"));
}
@@ -38,15 +38,15 @@ namespace Flow.Launcher.Core.Plugin
// that use Newtonsoft.Json
if (assemblyPath == null || ExistsInReferencedPluginPackage(assemblyName))
return null;
-
+
return LoadFromAssemblyPath(assemblyPath);
}
- internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type)
+ internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types)
{
var allTypes = assembly.ExportedTypes;
- return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(type));
+ return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Intersect(types).Any());
}
internal bool ExistsInReferencedPluginPackage(AssemblyName assemblyName)
@@ -54,4 +54,4 @@ namespace Flow.Launcher.Core.Plugin
return referencedPluginPackageDependencyResolver.ResolveAssemblyToPath(assemblyName) != null;
}
}
-}
+}
\ No newline at end of file
diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
index 224dbd85e..8295761b5 100644
--- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
@@ -37,56 +37,59 @@ namespace Flow.Launcher.Core.Plugin
foreach (var metadata in metadatas)
{
- var milliseconds = Stopwatch.Debug($"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () =>
- {
-
+ var milliseconds = Stopwatch.Debug(
+ $"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () =>
+ {
#if DEBUG
- var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
- var assembly = assemblyLoader.LoadAssemblyAndDependencies();
- var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin));
- var plugin = (IPlugin)Activator.CreateInstance(type);
-#else
- Assembly assembly = null;
- IPlugin plugin = null;
-
- try
- {
var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
- assembly = assemblyLoader.LoadAssemblyAndDependencies();
+ var assembly = assemblyLoader.LoadAssemblyAndDependencies();
+ var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin),
+ typeof(IAsyncPlugin));
- var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin));
+ var plugin = Activator.CreateInstance(type);
+#else
+ Assembly assembly = null;
+ IPlugin plugin = null;
- plugin = (IPlugin)Activator.CreateInstance(type);
- }
- catch (Exception e) when (assembly == null)
- {
- Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
- }
- catch (InvalidOperationException e)
- {
- Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
- }
- catch (ReflectionTypeLoadException e)
- {
- Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
- }
- catch (Exception e)
- {
- Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
- }
+ try
+ {
+ var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath);
+ assembly = assemblyLoader.LoadAssemblyAndDependencies();
- if (plugin == null)
- {
- erroredPlugins.Add(metadata.Name);
- return;
- }
+ var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin),
+ typeof(IAsyncPlugin));
+
+ plugin = Activator.CreateInstance(type);
+ }
+ catch (Exception e) when (assembly == null)
+ {
+ Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
+ }
+ catch (InvalidOperationException e)
+ {
+ Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
+ }
+ catch (ReflectionTypeLoadException e)
+ {
+ Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
+ }
+ catch (Exception e)
+ {
+ Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
+ }
+
+ if (plugin == null)
+ {
+ erroredPlugins.Add(metadata.Name);
+ return;
+ }
#endif
- plugins.Add(new PluginPair
- {
- Plugin = plugin,
- Metadata = metadata
+ plugins.Add(new PluginPair
+ {
+ Plugin = plugin,
+ Metadata = metadata
+ });
});
- });
metadata.InitTime += milliseconds;
}
@@ -95,15 +98,15 @@ namespace Flow.Launcher.Core.Plugin
var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
var errorMessage = "The following "
- + (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
- + "errored and cannot be loaded:";
+ + (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ + "errored and cannot be loaded:";
Task.Run(() =>
{
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
- $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
- $"Please refer to the logs for more information","",
- MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
+ $"Please refer to the logs for more information", "",
+ MessageBoxButtons.OK, MessageBoxIcon.Warning);
});
}
@@ -179,6 +182,5 @@ namespace Flow.Launcher.Core.Plugin
Metadata = metadata
});
}
-
}
}
\ No newline at end of file
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index bc68eb6d6..3e1a4b516 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -417,7 +417,7 @@ namespace Flow.Launcher.ViewModel
{
if (!plugins[i].Metadata.Disabled)
{
- tasks[i] = QueryTask(i, query, currentCancellationToken);
+ tasks[i] = QueryTask(plugins[i], query, currentCancellationToken);
}
else tasks[i] = Task.CompletedTask; // Avoid Null
});
@@ -438,10 +438,11 @@ namespace Flow.Launcher.ViewModel
ProgressBarVisibility = Visibility.Hidden;
}
- async Task QueryTask(int pairIndex, Query query, CancellationToken token)
+ // Local Function
+ async Task QueryTask(PluginPair plugin, Query query, CancellationToken token)
{
- var result = await PluginManager.QueryForPlugin(plugins[pairIndex], query, token);
- UpdateResultView(result, plugins[pairIndex].Metadata, query);
+ var results = await PluginManager.QueryForPlugin(plugin, query, token);
+ UpdateResultView(results, plugin.Metadata, query);
}
}, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
From f768b0890b8f784983da9cc2ae5a5f2b464a41ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?=
Date: Sat, 2 Jan 2021 17:58:30 +0800
Subject: [PATCH 091/308] Move Program Plugin to Async model
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 164 ++++++++++---------
1 file changed, 88 insertions(+), 76 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 8f124f3a4..0d693d363 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using Flow.Launcher.Infrastructure.Logger;
@@ -12,9 +13,8 @@ using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
namespace Flow.Launcher.Plugin.Program
{
- public class Main : ISettingProvider, IPlugin, IPluginI18n, IContextMenu, ISavable, IReloadable
+ public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, ISavable, IAsyncReloadable
{
- private static readonly object IndexLock = new object();
internal static Win32[] _win32s { get; set; }
internal static UWP.Application[] _uwps { get; set; }
internal static Settings _settings { get; set; }
@@ -30,17 +30,58 @@ namespace Flow.Launcher.Plugin.Program
public Main()
{
_settingsStorage = new PluginJsonStorage();
- _settings = _settingsStorage.Load();
+ }
- Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", () =>
+ public void Save()
+ {
+ _settingsStorage.Save();
+ _win32Storage.Save(_win32s);
+ _uwpStorage.Save(_uwps);
+ }
+
+ public async Task> QueryAsync(Query query, CancellationToken token)
+ {
+ Win32[] win32;
+ UWP.Application[] uwps;
+
+ win32 = _win32s;
+ uwps = _uwps;
+
+
+ var result = await Task.Run(delegate
{
- _win32Storage = new BinaryStorage("Win32");
- _win32s = _win32Storage.TryLoad(new Win32[] { });
- _uwpStorage = new BinaryStorage("UWP");
- _uwps = _uwpStorage.TryLoad(new UWP.Application[] { });
+ return win32.Cast()
+ .Concat(uwps)
+ .AsParallel()
+ .WithCancellation(token)
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, _context.API))
+ .Where(r => r?.Score > 0)
+ .ToList();
+ }, token).ConfigureAwait(false);
+
+ return result;
+ }
+
+ public async Task InitAsync(PluginInitContext context)
+ {
+ _context = context;
+
+ await Task.Run(() =>
+ {
+ _settings = _settingsStorage.Load();
+
+ Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", () =>
+ {
+ _win32Storage = new BinaryStorage("Win32");
+ _win32s = _win32Storage.TryLoad(new Win32[] { });
+ _uwpStorage = new BinaryStorage("UWP");
+ _uwps = _uwpStorage.TryLoad(new UWP.Application[] { });
+ });
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>");
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>");
});
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>");
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>");
+
var a = Task.Run(() =>
{
@@ -51,54 +92,22 @@ namespace Flow.Launcher.Plugin.Program
var b = Task.Run(() =>
{
if (IsStartupIndexProgramsRequired || !_uwps.Any())
- Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexUWPPrograms);
+ Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexUwpPrograms);
});
- Task.WaitAll(a, b);
+ await Task.WhenAll(a, b);
_settings.LastIndexTime = DateTime.Today;
}
- public void Save()
- {
- _settingsStorage.Save();
- _win32Storage.Save(_win32s);
- _uwpStorage.Save(_uwps);
- }
-
- public List Query(Query query)
- {
- Win32[] win32;
- UWP.Application[] uwps;
-
- win32 = _win32s;
- uwps = _uwps;
-
- var result = win32.Cast()
- .Concat(uwps)
- .AsParallel()
- .Where(p => p.Enabled)
- .Select(p => p.Result(query.Search, _context.API))
- .Where(r => r?.Score > 0)
- .ToList();
-
- return result;
- }
-
- public void Init(PluginInitContext context)
- {
- _context = context;
- }
-
public static void IndexWin32Programs()
{
var win32S = Win32.All(_settings);
_win32s = win32S;
-
}
- public static void IndexUWPPrograms()
+ public static void IndexUwpPrograms()
{
var windows10 = new Version(10, 0);
var support = Environment.OSVersion.Version.Major >= windows10.Major;
@@ -106,16 +115,15 @@ namespace Flow.Launcher.Plugin.Program
var applications = support ? UWP.All() : new UWP.Application[] { };
_uwps = applications;
-
}
- public static void IndexPrograms()
+ public static async Task IndexPrograms()
{
- var t1 = Task.Run(() => IndexWin32Programs());
+ var t1 = Task.Run(IndexWin32Programs);
- var t2 = Task.Run(() => IndexUWPPrograms());
+ var t2 = Task.Run(IndexUwpPrograms);
- Task.WaitAll(t1, t2);
+ await Task.WhenAll(t1, t2);
_settings.LastIndexTime = DateTime.Today;
}
@@ -145,19 +153,21 @@ namespace Flow.Launcher.Plugin.Program
}
menuOptions.Add(
- new Result
- {
- Title = _context.API.GetTranslation("flowlauncher_plugin_program_disable_program"),
- Action = c =>
- {
- DisableProgram(program);
- _context.API.ShowMsg(_context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
- _context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success_message"));
- return false;
- },
- IcoPath = "Images/disable.png"
- }
- );
+ new Result
+ {
+ Title = _context.API.GetTranslation("flowlauncher_plugin_program_disable_program"),
+ Action = c =>
+ {
+ DisableProgram(program);
+ _context.API.ShowMsg(
+ _context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
+ _context.API.GetTranslation(
+ "flowlauncher_plugin_program_disable_dlgtitle_success_message"));
+ return false;
+ },
+ IcoPath = "Images/disable.png"
+ }
+ );
return menuOptions;
}
@@ -168,21 +178,23 @@ namespace Flow.Launcher.Plugin.Program
return;
if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
- _uwps.Where(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier).FirstOrDefault().Enabled = false;
+ _uwps.Where(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier).FirstOrDefault().Enabled =
+ false;
if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
- _win32s.Where(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier).FirstOrDefault().Enabled = false;
+ _win32s.Where(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier).FirstOrDefault().Enabled =
+ false;
_settings.DisabledProgramSources
- .Add(
- new Settings.DisabledProgramSource
- {
- Name = programToDelete.Name,
- Location = programToDelete.Location,
- UniqueIdentifier = programToDelete.UniqueIdentifier,
- Enabled = false
- }
- );
+ .Add(
+ new Settings.DisabledProgramSource
+ {
+ Name = programToDelete.Name,
+ Location = programToDelete.Location,
+ UniqueIdentifier = programToDelete.UniqueIdentifier,
+ Enabled = false
+ }
+ );
}
public static void StartProcess(Func runProcess, ProcessStartInfo info)
@@ -200,9 +212,9 @@ namespace Flow.Launcher.Plugin.Program
}
}
- public void ReloadData()
+ public async Task ReloadDataAsync()
{
- IndexPrograms();
+ await IndexPrograms();
}
}
}
\ No newline at end of file
From 6326d6f3d57e8a5ef6065c210f8d6db7d932ca18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 20:22:07 +0800
Subject: [PATCH 092/308] Startup async
---
Flow.Launcher/App.xaml.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 59bdbc896..7417a6f2a 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -45,9 +45,9 @@ namespace Flow.Launcher
}
}
- private void OnStartup(object sender, StartupEventArgs e)
+ private async void OnStartup(object sender, StartupEventArgs e)
{
- Stopwatch.Normal("|App.OnStartup|Startup cost", () =>
+ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
{
_portable.PreStartCleanUpAfterPortabilityUpdate();
@@ -70,7 +70,7 @@ namespace Flow.Launcher
_mainVM = new MainViewModel(_settings);
var window = new MainWindow(_settings, _mainVM);
API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
- PluginManager.InitializePlugins(API);
+ await PluginManager.InitializePlugins(API);
Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
Current.MainWindow = window;
From 7be2a956dd31aa6d48a263926ea2e70f0a4e437b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 21:20:21 +0800
Subject: [PATCH 093/308] Use cancallationToken.IsCancellationRequested instead
of comparing current token with global token
---
Flow.Launcher/ViewModel/MainViewModel.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 3e1a4b516..f9c152046 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -442,7 +442,8 @@ namespace Flow.Launcher.ViewModel
async Task QueryTask(PluginPair plugin, Query query, CancellationToken token)
{
var results = await PluginManager.QueryForPlugin(plugin, query, token);
- UpdateResultView(results, plugin.Metadata, query);
+ if (!currentCancellationToken.IsCancellationRequested)
+ UpdateResultView(results, plugin.Metadata, query);
}
}, currentCancellationToken).ContinueWith(t => Log.Exception("|MainViewModel|Plugins Query Exceptions", t.Exception),
From 280b98b47a1fbdb5cb8a493339123d9586b54ccf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 21:23:34 +0800
Subject: [PATCH 094/308] Move the creation of Window later due to async
operation
---
Flow.Launcher/App.xaml.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 7417a6f2a..0145dfa34 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -68,9 +68,10 @@ namespace Flow.Launcher
PluginManager.LoadPlugins(_settings.PluginSettings);
_mainVM = new MainViewModel(_settings);
- var window = new MainWindow(_settings, _mainVM);
API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
await PluginManager.InitializePlugins(API);
+ var window = new MainWindow(_settings, _mainVM);
+
Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
Current.MainWindow = window;
From 4cb4aa88ef52dcab60c662a312f8b2e953b40ffc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 22:00:43 +0800
Subject: [PATCH 095/308] change onstartup name to async
---
Flow.Launcher/App.xaml | 2 +-
Flow.Launcher/App.xaml.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/App.xaml b/Flow.Launcher/App.xaml
index f3347d7fb..18addac73 100644
--- a/Flow.Launcher/App.xaml
+++ b/Flow.Launcher/App.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.modernwpf.com/2019"
ShutdownMode="OnMainWindowClose"
- Startup="OnStartup">
+ Startup="OnStartupAsync">
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 0145dfa34..06bb16e3b 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -45,7 +45,7 @@ namespace Flow.Launcher
}
}
- private async void OnStartup(object sender, StartupEventArgs e)
+ private async void OnStartupAsync(object sender, StartupEventArgs e)
{
await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
{
From d7805d7a8cbc7eedcee7cc7a62156397f1af5172 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 22:01:15 +0800
Subject: [PATCH 096/308] Make Explorer plugin completely async
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 4 +-
Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 14 ++-
.../DirectoryInfo/DirectoryInfoSearch.cs | 6 +-
.../Search/SearchManager.cs | 54 ++++++-----
.../Search/WindowsIndex/IndexSearch.cs | 90 +++++++++----------
.../ViewModels/SettingsViewModel.cs | 6 ++
6 files changed, 96 insertions(+), 78 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index c91144825..756ceb2d6 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -151,7 +151,7 @@ namespace Flow.Launcher.Test.Plugins
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
// When
- var results = searchManager.TopLevelDirectorySearchBehaviour(
+ var results = searchManager.TopLevelDirectorySearchBehaviourAsync(
MethodWindowsIndexSearchReturnsZeroResults,
MethodDirectoryInfoClassSearchReturnsTwoResults,
false,
@@ -171,7 +171,7 @@ namespace Flow.Launcher.Test.Plugins
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
// When
- var results = searchManager.TopLevelDirectorySearchBehaviour(
+ var results = searchManager.TopLevelDirectorySearchBehaviourAsync(
MethodWindowsIndexSearchReturnsZeroResults,
MethodDirectoryInfoClassSearchReturnsTwoResults,
true,
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
index 30a06e882..7b56df691 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
@@ -3,11 +3,13 @@ using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.ViewModels;
using Flow.Launcher.Plugin.Explorer.Views;
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using System.Windows.Controls;
namespace Flow.Launcher.Plugin.Explorer
{
- public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n
+ public class Main : ISettingProvider, IAsyncPlugin, ISavable, IContextMenu, IPluginI18n
{
internal PluginInitContext Context { get; set; }
@@ -17,17 +19,21 @@ namespace Flow.Launcher.Plugin.Explorer
private IContextMenu contextMenu;
+ private SearchManager searchManager;
+
public Control CreateSettingPanel()
{
return new ExplorerSettings(viewModel);
}
- public void Init(PluginInitContext context)
+ public async Task InitAsync(PluginInitContext context)
{
Context = context;
viewModel = new SettingsViewModel(context);
+ await viewModel.LoadStorage();
Settings = viewModel.Settings;
contextMenu = new ContextMenu(Context, Settings);
+ searchManager = new SearchManager(Settings, Context);
}
public List LoadContextMenus(Result selectedResult)
@@ -35,9 +41,9 @@ namespace Flow.Launcher.Plugin.Explorer
return contextMenu.LoadContextMenus(selectedResult);
}
- public List Query(Query query)
+ public async Task> QueryAsync(Query query, CancellationToken token)
{
- return new SearchManager(Settings, Context).Search(query);
+ return await searchManager.SearchAsync(query, token);
}
public void Save()
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
index 02de0eeae..3253b7a7b 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Windows;
namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
{
@@ -22,7 +23,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
if (search.LastIndexOf(Constants.AllFilesFolderSearchWildcard) > search.LastIndexOf(Constants.DirectorySeperator))
return DirectorySearch(SearchOption.AllDirectories, query, search, criteria);
-
+
return DirectorySearch(SearchOption.TopDirectoryOnly, query, search, criteria);
}
@@ -57,9 +58,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
try
{
var directoryInfo = new System.IO.DirectoryInfo(path);
- var fileSystemInfos = directoryInfo.GetFileSystemInfos(searchCriteria, searchOption);
- foreach (var fileSystemInfo in fileSystemInfos)
+ foreach (var fileSystemInfo in directoryInfo.EnumerateFileSystemInfos(searchCriteria, searchOption))
{
if ((fileSystemInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 5b50b7fad..6b3a96912 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -5,6 +5,8 @@ using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search
{
@@ -28,20 +30,20 @@ namespace Flow.Launcher.Plugin.Explorer.Search
this.settings = settings;
}
- internal List Search(Query query)
+ internal async Task> SearchAsync(Query query, CancellationToken token)
{
var results = new List();
var querySearch = query.Search;
if (IsFileContentSearch(query.ActionKeyword))
- return WindowsIndexFileContentSearch(query, querySearch);
+ 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
if (settings.QuickFolderAccessLinks.Count > 0
&& query.ActionKeyword == settings.SearchActionKeyword
&& string.IsNullOrEmpty(query.Search))
- return quickFolderAccess.FolderListAll(query, settings.QuickFolderAccessLinks, context);
+ return quickFolderAccess.FolderListAll(query, settings.QuickFolderAccessLinks, context);
var quickFolderLinks = quickFolderAccess.FolderListMatched(query, settings.QuickFolderAccessLinks, context);
@@ -54,11 +56,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, context);
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
- var isEnvironmentVariablePath = querySearch.Substring(1).Contains("%\\");
+ var isEnvironmentVariablePath = querySearch[1..].Contains("%\\");
if (!FilesFolders.IsLocationPathString(querySearch) && !isEnvironmentVariablePath)
{
- results.AddRange(WindowsIndexFilesAndFoldersSearch(query, querySearch));
+ results.AddRange(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token).ConfigureAwait(false));
return results;
}
@@ -72,29 +74,34 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return results;
var useIndexSearch = UseWindowsIndexForDirectorySearch(locationPath);
-
+
results.Add(resultManager.CreateOpenCurrentFolderResult(locationPath, useIndexSearch));
- results.AddRange(TopLevelDirectorySearchBehaviour(WindowsIndexTopLevelFolderSearch,
+ if (token.IsCancellationRequested)
+ return null;
+
+ results.AddRange(await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync,
DirectoryInfoClassSearch,
useIndexSearch,
query,
- locationPath));
+ locationPath,
+ token).ConfigureAwait(false));
return results;
}
- private List WindowsIndexFileContentSearch(Query query, string querySearchString)
+ private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString, CancellationToken token)
{
var queryConstructor = new QueryConstructor(settings);
if (string.IsNullOrEmpty(querySearchString))
return new List();
- return indexSearch.WindowsIndexSearch(querySearchString,
+ return await indexSearch.WindowsIndexSearchAsync(querySearchString,
queryConstructor.CreateQueryHelper().ConnectionString,
queryConstructor.QueryForFileContentSearch,
- query);
+ query,
+ token).ConfigureAwait(false);
}
public bool IsFileContentSearch(string actionKeyword)
@@ -109,37 +116,40 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return directoryInfoSearch.TopLevelDirectorySearch(query, querySearch);
}
- public List TopLevelDirectorySearchBehaviour(
- Func> windowsIndexSearch,
+ public async Task> TopLevelDirectorySearchBehaviourAsync(
+ Func>> windowsIndexSearch,
Func> directoryInfoClassSearch,
bool useIndexSearch,
Query query,
- string querySearchString)
+ string querySearchString,
+ CancellationToken token)
{
if (!useIndexSearch)
return directoryInfoClassSearch(query, querySearchString);
- return windowsIndexSearch(query, querySearchString);
+ return await windowsIndexSearch(query, querySearchString, token);
}
- private List WindowsIndexFilesAndFoldersSearch(Query query, string querySearchString)
+ private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString, CancellationToken token)
{
var queryConstructor = new QueryConstructor(settings);
- return indexSearch.WindowsIndexSearch(querySearchString,
+ return await indexSearch.WindowsIndexSearchAsync(querySearchString,
queryConstructor.CreateQueryHelper().ConnectionString,
queryConstructor.QueryForAllFilesAndFolders,
- query);
+ query,
+ token).ConfigureAwait(false);
}
-
- private List WindowsIndexTopLevelFolderSearch(Query query, string path)
+
+ private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path, CancellationToken token)
{
var queryConstructor = new QueryConstructor(settings);
- return indexSearch.WindowsIndexSearch(path,
+ return await indexSearch.WindowsIndexSearchAsync(path,
queryConstructor.CreateQueryHelper().ConnectionString,
queryConstructor.QueryForTopLevelDirectorySearch,
- query);
+ query,
+ token).ConfigureAwait(false);
}
private bool UseWindowsIndexForDirectorySearch(string locationPath)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
index 4f9325c77..5b1d47ef8 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
@@ -5,19 +5,13 @@ using System.Collections.Generic;
using System.Data.OleDb;
using System.Linq;
using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
internal class IndexSearch
{
- private readonly object _lock = new object();
-
- private OleDbConnection conn;
-
- private OleDbCommand command;
-
- private OleDbDataReader dataReaderResults;
-
private readonly ResultManager resultManager;
// Reserved keywords in oleDB
@@ -28,7 +22,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
resultManager = new ResultManager(context);
}
- internal List ExecuteWindowsIndexSearch(string indexQueryString, string connectionString, Query query)
+ internal async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token)
{
var folderResults = new List();
var fileResults = new List();
@@ -36,47 +30,49 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
try
{
- using (conn = new OleDbConnection(connectionString))
+ using var conn = new OleDbConnection(connectionString);
+ await conn.OpenAsync(token);
+ token.ThrowIfCancellationRequested();
+
+ using var command = new OleDbCommand(indexQueryString, conn);
+ // Results return as an OleDbDataReader.
+ using var dataReaderResults = await command.ExecuteReaderAsync(token) as OleDbDataReader;
+ token.ThrowIfCancellationRequested();
+
+ if (dataReaderResults.HasRows)
{
- conn.Open();
-
- using (command = new OleDbCommand(indexQueryString, conn))
+ while (await dataReaderResults.ReadAsync(token))
{
- // Results return as an OleDbDataReader.
- using (dataReaderResults = command.ExecuteReader())
+ token.ThrowIfCancellationRequested();
+ if (dataReaderResults.GetValue(0) != DBNull.Value && dataReaderResults.GetValue(1) != DBNull.Value)
{
- if (dataReaderResults.HasRows)
- {
- while (dataReaderResults.Read())
- {
- if (dataReaderResults.GetValue(0) != DBNull.Value && dataReaderResults.GetValue(1) != DBNull.Value)
- {
- // # is URI syntax for the fragment component, need to be encoded so LocalPath returns complete path
- var encodedFragmentPath = dataReaderResults
- .GetString(1)
- .Replace("#", "%23", StringComparison.OrdinalIgnoreCase);
-
- var path = new Uri(encodedFragmentPath).LocalPath;
+ // # is URI syntax for the fragment component, need to be encoded so LocalPath returns complete path
+ var encodedFragmentPath = dataReaderResults
+ .GetString(1)
+ .Replace("#", "%23", StringComparison.OrdinalIgnoreCase);
- if (dataReaderResults.GetString(2) == "Directory")
- {
- folderResults.Add(resultManager.CreateFolderResult(
- dataReaderResults.GetString(0),
- path,
- path,
- query, true, true));
- }
- else
- {
- fileResults.Add(resultManager.CreateFileResult(path, query, true, true));
- }
- }
- }
+ var path = new Uri(encodedFragmentPath).LocalPath;
+
+ if (dataReaderResults.GetString(2) == "Directory")
+ {
+ folderResults.Add(resultManager.CreateFolderResult(
+ dataReaderResults.GetString(0),
+ path,
+ path,
+ query, true, true));
+ }
+ else
+ {
+ fileResults.Add(resultManager.CreateFileResult(path, query, true, true));
}
}
}
}
}
+ catch (OperationCanceledException)
+ {
+ return new List(); // The source code indicates that without adding members, it won't allocate an array
+ }
catch (InvalidOperationException e)
{
// Internal error from ExecuteReader(): Connection closed.
@@ -91,18 +87,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
return results.Concat(folderResults.OrderBy(x => x.Title)).Concat(fileResults.OrderBy(x => x.Title)).ToList(); ;
}
- internal List WindowsIndexSearch(string searchString, string connectionString, Func constructQuery, Query query)
+ internal async Task> WindowsIndexSearchAsync(string searchString, string connectionString,
+ Func constructQuery, Query query,
+ CancellationToken token)
{
var regexMatch = Regex.Match(searchString, reservedStringPattern);
if (regexMatch.Success)
return new List();
- lock (_lock)
- {
- var constructedQuery = constructQuery(searchString);
- return ExecuteWindowsIndexSearch(constructedQuery, connectionString, query);
- }
+ var constructedQuery = constructQuery(searchString);
+ return await ExecuteWindowsIndexSearchAsync(constructedQuery, connectionString, query, token);
+
}
internal bool PathIsIndexed(string path)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs
index 7fcd77f07..21bc49741 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs
@@ -3,6 +3,7 @@ using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.FolderLinks;
using System.Diagnostics;
+using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.ViewModels
{
@@ -21,6 +22,11 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
Settings = storage.Load();
}
+ public Task LoadStorage()
+ {
+ return Task.Run(() => Settings = storage.Load());
+ }
+
public void Save()
{
storage.Save();
From 43cee65c4518b01ca49ba9a267446a390d41501e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 22:21:45 +0800
Subject: [PATCH 097/308] Move PluginManagers to Async Model
---
.../Main.cs | 19 +++++++++----------
.../Models/PluginsManifest.cs | 7 +------
2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
index f10f022d7..40579e6e5 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
@@ -7,10 +7,11 @@ using System.Windows.Controls;
using Flow.Launcher.Infrastructure;
using System;
using System.Threading.Tasks;
+using System.Threading;
namespace Flow.Launcher.Plugin.PluginsManager
{
- public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n, IReloadable
+ public class Main : ISettingProvider, IAsyncPlugin, ISavable, IContextMenu, IPluginI18n, IAsyncReloadable
{
internal PluginInitContext Context { get; set; }
@@ -29,13 +30,14 @@ namespace Flow.Launcher.Plugin.PluginsManager
return new PluginsManagerSettings(viewModel);
}
- public void Init(PluginInitContext context)
+ public async Task InitAsync(PluginInitContext context)
{
Context = context;
viewModel = new SettingsViewModel(context);
Settings = viewModel.Settings;
contextMenu = new ContextMenu(Context);
pluginManager = new PluginsManager(Context, Settings);
+ await pluginManager.UpdateManifest();
lastUpdateTime = DateTime.Now;
}
@@ -44,7 +46,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
return contextMenu.LoadContextMenus(selectedResult);
}
- public List Query(Query query)
+ public async Task> QueryAsync(Query query, CancellationToken token)
{
var search = query.Search.ToLower();
@@ -53,11 +55,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
if ((DateTime.Now - lastUpdateTime).TotalHours > 12) // 12 hours
{
- Task.Run(async () =>
- {
- await pluginManager.UpdateManifest();
- lastUpdateTime = DateTime.Now;
- });
+ await pluginManager.UpdateManifest();
+ lastUpdateTime = DateTime.Now;
}
return search switch
@@ -88,9 +87,9 @@ namespace Flow.Launcher.Plugin.PluginsManager
return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description");
}
- public void ReloadData()
+ public async Task ReloadDataAsync()
{
- Task.Run(() => pluginManager.UpdateManifest()).Wait();
+ await pluginManager.UpdateManifest();
lastUpdateTime = DateTime.Now;
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs
index 814e0764d..145aadc98 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs
@@ -9,12 +9,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models
{
internal class PluginsManifest
{
- internal List UserPlugins { get; private set; }
-
- internal PluginsManifest()
- {
- Task.Run(async () => await DownloadManifest()).Wait();
- }
+ internal List UserPlugins { get; private set; } = new List();
internal async Task DownloadManifest()
{
From 69cb8e61479d477a9f0c05a5d7f40b386af6438d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sat, 2 Jan 2021 22:30:56 +0800
Subject: [PATCH 098/308] Reload IAsyncReloadable concurrently
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 33 ++++++++++++----------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 239f0499d..2e938127c 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -33,7 +33,7 @@ namespace Flow.Launcher.Core.Plugin
///
/// Directories that will hold Flow Launcher plugin directory
///
- private static readonly string[] Directories = {Constant.PreinstalledDirectory, DataLocation.PluginsDirectory};
+ private static readonly string[] Directories = { Constant.PreinstalledDirectory, DataLocation.PluginsDirectory };
private static void DeletePythonBinding()
{
@@ -55,18 +55,21 @@ namespace Flow.Launcher.Core.Plugin
public static async Task ReloadData()
{
- foreach(var plugin in AllPlugins)
+ await Task.WhenAll(AllPlugins.Select(plugin =>
{
- switch (plugin.Plugin)
{
- case IReloadable p:
- p.ReloadData();
- break;
- case IAsyncReloadable p:
- await p.ReloadDataAsync();
- break;
+ switch (plugin)
+ {
+ case IReloadable p:
+ p.ReloadData(); // Sync reload means low time consuming
+ return Task.CompletedTask;
+ case IAsyncReloadable p:
+ return p.ReloadDataAsync();
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
}
- }
+ }));
}
static PluginManager()
@@ -142,7 +145,7 @@ namespace Flow.Launcher.Core.Plugin
catch (Exception e)
{
Log.Exception(nameof(PluginManager), $"Fail to Init plugin: {pair.Metadata.Name}", e);
- pair.Metadata.Disabled = true;
+ pair.Metadata.Disabled = true;
failedPlugins.Enqueue(pair);
}
}));
@@ -180,7 +183,7 @@ namespace Flow.Launcher.Core.Plugin
if (NonGlobalPlugins.ContainsKey(query.ActionKeyword))
{
var plugin = NonGlobalPlugins[query.ActionKeyword];
- return new List {plugin};
+ return new List { plugin };
}
else
{
@@ -262,7 +265,7 @@ namespace Flow.Launcher.Core.Plugin
var pluginPair = _contextMenuPlugins.FirstOrDefault(o => o.Metadata.ID == result.PluginID);
if (pluginPair != null)
{
- var plugin = (IContextMenu) pluginPair.Plugin;
+ var plugin = (IContextMenu)pluginPair.Plugin;
try
{
@@ -326,10 +329,10 @@ namespace Flow.Launcher.Core.Plugin
{
GlobalPlugins.Remove(plugin);
}
-
+
if (oldActionkeyword != Query.GlobalPluginWildcardSign)
NonGlobalPlugins.Remove(oldActionkeyword);
-
+
plugin.Metadata.ActionKeywords.Remove(oldActionkeyword);
}
From 6e9e51ec4d674867deb283dd721dd485978cd4e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 10:19:05 +0800
Subject: [PATCH 099/308] Error handling for OperationCancelledException in
Program plugin
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 39 ++++++++++++++------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 0d693d363..954c238a9 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -47,20 +47,35 @@ namespace Flow.Launcher.Plugin.Program
win32 = _win32s;
uwps = _uwps;
-
- var result = await Task.Run(delegate
+ try
{
- return win32.Cast()
- .Concat(uwps)
- .AsParallel()
- .WithCancellation(token)
- .Where(p => p.Enabled)
- .Select(p => p.Result(query.Search, _context.API))
- .Where(r => r?.Score > 0)
- .ToList();
- }, token).ConfigureAwait(false);
+ var result = await Task.Run(delegate
+ {
+ try
+ {
+ return win32.Cast()
+ .Concat(uwps)
+ .AsParallel()
+ .WithCancellation(token)
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, _context.API))
+ .Where(r => r?.Score > 0)
+ .ToList();
+ }
+ catch (OperationCanceledException)
+ {
+ return null;
+ }
+ }, token).ConfigureAwait(false);
- return result;
+ token.ThrowIfCancellationRequested();
+
+ return result;
+ }
+ catch (OperationCanceledException)
+ {
+ return null;
+ }
}
public async Task InitAsync(PluginInitContext context)
From 1c200695982e1e0ad170febf0d04498690baea59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 10:19:33 +0800
Subject: [PATCH 100/308] Rebase to Dev
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 47 ++++++++++++----------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 2e938127c..b34995ba6 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -197,36 +197,41 @@ namespace Flow.Launcher.Core.Plugin
try
{
var metadata = pair.Metadata;
- var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}",
- async () =>
- {
- switch (pair.Plugin)
- {
- case IAsyncPlugin plugin:
- results = await plugin.QueryAsync(query, token).ConfigureAwait(false) ??
- new List();
- UpdatePluginMetadata(results, metadata, query);
- break;
- case IPlugin plugin:
- results = await Task.Run(() => plugin.Query(query), token).ConfigureAwait(false) ??
- new List();
- UpdatePluginMetadata(results, metadata, query);
- break;
- }
- });
+
+ long milliseconds = -1L;
+
+ switch (pair.Plugin)
+ {
+ case IAsyncPlugin plugin:
+ milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}",
+ async () => results = await plugin.QueryAsync(query, token).ConfigureAwait(false));
+ break;
+ case IPlugin plugin:
+ await Task.Run(() => milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", () =>
+ results = plugin.Query(query)), token).ConfigureAwait(false);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ token.ThrowIfCancellationRequested();
+ UpdatePluginMetadata(results, metadata, query);
+
metadata.QueryCount += 1;
metadata.AvgQueryTime =
metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
+ token.ThrowIfCancellationRequested();
+ }
+ catch (Exception e) when (e is OperationCanceledException || e is TaskCanceledException)
+ {
+ return results = null;
}
catch (Exception e)
{
- Log.Exception(
- $"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>",
- e);
+ Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e);
}
// null will be fine since the results will only be added into queue if the token hasn't been cancelled
- return token.IsCancellationRequested ? results = null : results;
+ return results;
}
public static void UpdatePluginMetadata(List results, PluginMetadata metadata, Query query)
From 731c3cdcbc23e85b38b3b652d970328adc566675 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 10:37:36 +0800
Subject: [PATCH 101/308] Use OperationCancelledException instead of catch
Exception and check
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index b34995ba6..0712908bf 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -221,7 +221,7 @@ namespace Flow.Launcher.Core.Plugin
metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
token.ThrowIfCancellationRequested();
}
- catch (Exception e) when (e is OperationCanceledException || e is TaskCanceledException)
+ catch (OperationCanceledException)
{
return results = null;
}
From ecf2a7a1f7cd73b787a0aa66bb588e9994e98397 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 10:43:05 +0800
Subject: [PATCH 102/308] change plugin type in pluginLoader for Release
---
Flow.Launcher.Core/Plugin/PluginsLoader.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
index 8295761b5..b18c07e3c 100644
--- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
@@ -49,7 +49,7 @@ namespace Flow.Launcher.Core.Plugin
var plugin = Activator.CreateInstance(type);
#else
Assembly assembly = null;
- IPlugin plugin = null;
+ object plugin = null;
try
{
From 63e32f1097e6ce061bf431aa6e452f3e47ac19f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 10:52:59 +0800
Subject: [PATCH 103/308] fix testing
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 48 ++++++++++++----------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 756ceb2d6..09c7d9a30 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -7,6 +7,8 @@ using Flow.Launcher.Plugin.SharedCommands;
using NUnit.Framework;
using System;
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
namespace Flow.Launcher.Test.Plugins
{
@@ -17,15 +19,15 @@ namespace Flow.Launcher.Test.Plugins
[TestFixture]
public class ExplorerTest
{
- private List MethodWindowsIndexSearchReturnsZeroResults(Query dummyQuery, string dummyString)
+ private async Task> MethodWindowsIndexSearchReturnsZeroResultsAsync(Query dummyQuery, string dummyString, CancellationToken dummyToken)
{
return new List();
}
private List MethodDirectoryInfoClassSearchReturnsTwoResults(Query dummyQuery, string dummyString)
{
- return new List
- {
+ return new List
+ {
new Result
{
Title="Result 1"
@@ -64,10 +66,10 @@ namespace Flow.Launcher.Test.Plugins
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
-
+
//When
var queryString = queryConstructor.QueryForTopLevelDirectorySearch(folderPath);
-
+
// Then
Assert.IsTrue(queryString == expectedString,
$"Expected string: {expectedString}{Environment.NewLine} " +
@@ -112,7 +114,7 @@ namespace Flow.Launcher.Test.Plugins
}
[TestCase("scope='file:'")]
- public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereRestrictionsShouldUseScopeString(string expectedString)
+ public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereRestrictionsShouldUseScopeString(string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
@@ -130,7 +132,7 @@ namespace Flow.Launcher.Test.Plugins
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:'")]
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShouldUseExpectedString(
- string userSearchString, string expectedString)
+ string userSearchString, string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
@@ -145,18 +147,19 @@ namespace Flow.Launcher.Test.Plugins
}
[TestCase]
- public void GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldContinueDirectoryInfoClassSearch()
+ public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldContinueDirectoryInfoClassSearch()
{
// Given
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
-
+
// When
- var results = searchManager.TopLevelDirectorySearchBehaviourAsync(
- MethodWindowsIndexSearchReturnsZeroResults,
- MethodDirectoryInfoClassSearchReturnsTwoResults,
- false,
+ var results = await searchManager.TopLevelDirectorySearchBehaviourAsync(
+ MethodWindowsIndexSearchReturnsZeroResultsAsync,
+ MethodDirectoryInfoClassSearchReturnsTwoResults,
+ false,
new Query(),
- "string not used");
+ "string not used",
+ default);
// Then
Assert.IsTrue(results.Count == 2,
@@ -165,18 +168,19 @@ namespace Flow.Launcher.Test.Plugins
}
[TestCase]
- public void GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldNotContinueDirectoryInfoClassSearch()
+ public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldNotContinueDirectoryInfoClassSearch()
{
// Given
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
// When
- var results = searchManager.TopLevelDirectorySearchBehaviourAsync(
- MethodWindowsIndexSearchReturnsZeroResults,
+ var results = await searchManager.TopLevelDirectorySearchBehaviourAsync(
+ MethodWindowsIndexSearchReturnsZeroResultsAsync,
MethodDirectoryInfoClassSearchReturnsTwoResults,
true,
new Query(),
- "string not used");
+ "string not used",
+ default);
// Then
Assert.IsTrue(results.Count == 0,
@@ -223,7 +227,7 @@ namespace Flow.Launcher.Test.Plugins
var query = new Query { ActionKeyword = "doc:", Search = "search term" };
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
-
+
// When
var result = searchManager.IsFileContentSearch(query.ActionKeyword);
@@ -250,7 +254,7 @@ namespace Flow.Launcher.Test.Plugins
$"Actual check result is {result} {Environment.NewLine}");
}
-
+
[TestCase(@"C:\SomeFolder\SomeApp", true, @"C:\SomeFolder\")]
[TestCase(@"C:\SomeFolder\SomeApp\SomeFile", true, @"C:\SomeFolder\SomeApp\")]
[TestCase(@"C:\NonExistentFolder\SomeApp", false, "")]
@@ -294,7 +298,7 @@ namespace Flow.Launcher.Test.Plugins
[TestCase("c:\\SomeFolder\\>SomeName", "(System.FileName LIKE 'SomeName%' " +
"OR CONTAINS(System.FileName,'\"SomeName*\"',1033)) AND " +
"scope='file:c:\\SomeFolder'")]
- public void GivenWindowsIndexSearch_WhenSearchPatternHotKeyIsSearchAll_ThenQueryWhereRestrictionsShouldUseScopeString(string path, string expectedString)
+ public void GivenWindowsIndexSearch_WhenSearchPatternHotKeyIsSearchAll_ThenQueryWhereRestrictionsShouldUseScopeString(string path, string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
@@ -308,7 +312,7 @@ namespace Flow.Launcher.Test.Plugins
$"Actual string was: {resultString}{Environment.NewLine}");
}
- [TestCase("c:\\somefolder\\>somefile","*somefile*")]
+ [TestCase("c:\\somefolder\\>somefile", "*somefile*")]
[TestCase("c:\\somefolder\\somefile", "somefile*")]
[TestCase("c:\\somefolder\\", "*")]
public void GivenDirectoryInfoSearch_WhenSearchPatternHotKeyIsSearchAll_ThenSearchCriteriaShouldUseCriteriaString(string path, string expectedString)
From d369108b0b17d05c300919d7f20e296c5322b731 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 20:40:18 +0800
Subject: [PATCH 104/308] Error handling for plugin update
---
.../PluginsManager.cs | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 880157a77..4debf5598 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -214,11 +214,19 @@ namespace Flow.Launcher.Plugin.PluginsManager
Task.Run(async delegate
{
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
+ Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
+
await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false);
+
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
+ Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
+
Install(x.PluginNewUserPlugin, downloadToFilePath);
Context.API.RestartApp();
- });
+ }).ContinueWith(t => Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException),
+ TaskContinuationOptions.OnlyOnFaulted);
return true;
}
From 8fa1e2e33f4355766282ca6934e3a279b8a3b8be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Sun, 3 Jan 2021 20:49:14 +0800
Subject: [PATCH 105/308] add one more message
---
.../Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 4debf5598..9cef704a6 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -225,8 +225,12 @@ namespace Flow.Launcher.Plugin.PluginsManager
Install(x.PluginNewUserPlugin, downloadToFilePath);
Context.API.RestartApp();
- }).ContinueWith(t => Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException),
- TaskContinuationOptions.OnlyOnFaulted);
+ }).ContinueWith(t =>
+ {
+ Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException);
+ Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
+ string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), x.Name));
+ }, TaskContinuationOptions.OnlyOnFaulted);
return true;
}
From d35a3bb43d05cf19b1fd46ef3577376941b7ed44 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 4 Jan 2021 06:40:45 +1100
Subject: [PATCH 106/308] version bump for PluginsManager
---
Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
index f5bbf3f6b..ef2c1255a 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
@@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
- "Version": "1.4.0",
+ "Version": "1.4.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
From 6287358275e01457fabf0e2482343836a80bb9dd Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 4 Jan 2021 06:41:05 +1100
Subject: [PATCH 107/308] update error message
---
Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 9cef704a6..724ddf20d 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -227,7 +227,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.RestartApp();
}).ContinueWith(t =>
{
- Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException);
+ Log.Exception("PluginsManager", $"Update failed for {x.Name}", t.Exception.InnerException, "RequestUpdate");
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), x.Name));
}, TaskContinuationOptions.OnlyOnFaulted);
From a8dc1599d746d88c8ce28ac551abb0e02bf6a90d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 10:28:33 +0800
Subject: [PATCH 108/308] Add Http Error Handling
---
Flow.Launcher.Infrastructure/Http/Http.cs | 44 +++++++++++++++++------
1 file changed, 33 insertions(+), 11 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs
index 8e2832690..b796d807c 100644
--- a/Flow.Launcher.Infrastructure/Http/Http.cs
+++ b/Flow.Launcher.Infrastructure/Http/Http.cs
@@ -91,7 +91,7 @@ namespace Flow.Launcher.Infrastructure.Http
///
/// Asynchrously get the result as string from url.
- /// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string
+ /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string
///
///
///
@@ -101,19 +101,33 @@ namespace Flow.Launcher.Infrastructure.Http
return GetAsync(new Uri(url.Replace("#", "%23")));
}
+ ///
+ /// Asynchrously get the result as string from url.
+ /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string
+ ///
+ ///
+ ///
public static async Task GetAsync([NotNull] Uri url)
{
Log.Debug($"|Http.Get|Url <{url}>");
- using var response = await client.GetAsync(url);
- var content = await response.Content.ReadAsStringAsync();
- if (response.StatusCode == HttpStatusCode.OK)
+ try
{
- return content;
+ using var response = await client.GetAsync(url);
+ var content = await response.Content.ReadAsStringAsync();
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ return content;
+ }
+ else
+ {
+ throw new HttpRequestException(
+ $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
+ }
}
- else
+ catch (HttpRequestException e)
{
- throw new HttpRequestException(
- $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetAsync");
+ throw;
}
}
@@ -124,9 +138,17 @@ namespace Flow.Launcher.Infrastructure.Http
///
public static async Task GetStreamAsync([NotNull] string url)
{
- Log.Debug($"|Http.Get|Url <{url}>");
- var response = await client.GetAsync(url);
- return await response.Content.ReadAsStreamAsync();
+ try
+ {
+ Log.Debug($"|Http.Get|Url <{url}>");
+ var response = await client.GetAsync(url);
+ return await response.Content.ReadAsStreamAsync();
+ }
+ catch (HttpRequestException e)
+ {
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetStreamAsync");
+ throw;
+ }
}
}
}
From bc63b9ebfa100426176603ba6c7009b72dd3502e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 10:31:05 +0800
Subject: [PATCH 109/308] Change Download to DownloadAsync Add error handling
for download as well
---
Flow.Launcher.Infrastructure/Http/Http.cs | 22 +++++++++++++------
.../PluginsManager.cs | 4 ++--
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs
index b796d807c..78fa099c9 100644
--- a/Flow.Launcher.Infrastructure/Http/Http.cs
+++ b/Flow.Launcher.Infrastructure/Http/Http.cs
@@ -75,17 +75,25 @@ namespace Flow.Launcher.Infrastructure.Http
};
}
- public static async Task Download([NotNull] string url, [NotNull] string filePath)
+ public static async Task DownloadAsync([NotNull] string url, [NotNull] string filePath)
{
- using var response = await client.GetAsync(url);
- if (response.StatusCode == HttpStatusCode.OK)
+ try
{
- await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
- await response.Content.CopyToAsync(fileStream);
+ using var response = await client.GetAsync(url);
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
+ await response.Content.CopyToAsync(fileStream);
+ }
+ else
+ {
+ throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
+ }
}
- else
+ catch (HttpRequestException e)
{
- throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "DownloadAsync");
+ throw;
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 724ddf20d..68df5bc1f 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -127,7 +127,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
- await Http.Download(plugin.UrlDownload, filePath).ConfigureAwait(false);
+ await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
@@ -217,7 +217,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
- await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false);
+ await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
From fb640b68c8e5a49e105e0666ce77e057c1a43735 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 11:05:59 +0800
Subject: [PATCH 110/308] Use ValueTask instead of Task
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 25 ++++++++++++++--------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 00a0e1ae5..20d32890b 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
@@ -12,7 +13,7 @@ namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
- public class LazyAsync : Lazy>
+ public class LazyAsync : Lazy>
{
private T defaultValue;
@@ -23,21 +24,27 @@ namespace Flow.Launcher.ViewModel
{
if (!IsValueCreated)
{
- base.Value.ContinueWith(_ =>
- {
- _updateCallback();
- });
+ _ = Exercute();
return defaultValue;
}
-
+
if (!base.Value.IsCompleted || base.Value.IsFaulted)
return defaultValue;
return base.Value.Result;
+
+ // If none of the variables captured by the local function are captured by other lambdas
+ // , the compiler can avoid heap allocations.
+ async ValueTask Exercute()
+ {
+ await base.Value.ConfigureAwait(false);
+ _updateCallback();
+ }
+
}
}
- public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory)
+ public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory)
{
if (defaultValue != null)
{
@@ -55,7 +62,7 @@ namespace Flow.Launcher.ViewModel
Result = result;
Image = new LazyAsync(
- SetImage,
+ SetImage,
ImageLoader.DefaultImage,
() =>
{
@@ -82,7 +89,7 @@ namespace Flow.Launcher.ViewModel
public LazyAsync Image { get; set; }
- private async Task SetImage()
+ private async ValueTask SetImage()
{
var imagePath = Result.IcoPath;
if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
From 7967844cf381563c362f2d91bcac73342b3f5237 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 11:10:02 +0800
Subject: [PATCH 111/308] make defaultValue readonly and edit comment
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 20d32890b..d1b03f911 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -15,7 +15,7 @@ namespace Flow.Launcher.ViewModel
{
public class LazyAsync : Lazy>
{
- private T defaultValue;
+ private readonly T defaultValue;
private readonly Action _updateCallback;
public new T Value
@@ -24,7 +24,7 @@ namespace Flow.Launcher.ViewModel
{
if (!IsValueCreated)
{
- _ = Exercute();
+ _ = Exercute(); // manually use callback strategy
return defaultValue;
}
@@ -34,8 +34,8 @@ namespace Flow.Launcher.ViewModel
return base.Value.Result;
- // If none of the variables captured by the local function are captured by other lambdas
- // , the compiler can avoid heap allocations.
+ // If none of the variables captured by the local function are captured by other lambdas,
+ // the compiler can avoid heap allocations.
async ValueTask Exercute()
{
await base.Value.ConfigureAwait(false);
From fc015245b3392664f4b630a6a10a68b85d05bc2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 16:22:48 +0800
Subject: [PATCH 112/308] Change the way checking successfuly
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index d1b03f911..9eece1a97 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -29,7 +29,7 @@ namespace Flow.Launcher.ViewModel
return defaultValue;
}
- if (!base.Value.IsCompleted || base.Value.IsFaulted)
+ if (!base.Value.IsCompletedSuccessfully)
return defaultValue;
return base.Value.Result;
From 6703e0d137b3fcd03c8fdb16644df7fa5645b24b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Mon, 4 Jan 2021 16:31:48 +0800
Subject: [PATCH 113/308] Return default image when loading UWP icon fail
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 9eece1a97..4c65f2b9f 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -68,7 +68,7 @@ namespace Flow.Launcher.ViewModel
{
OnPropertyChanged(nameof(Image));
});
- }
+ }
Settings = settings;
}
@@ -101,7 +101,7 @@ namespace Flow.Launcher.ViewModel
catch (Exception e)
{
Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e);
- imagePath = Constant.MissingImgIcon;
+ return ImageLoader.DefaultImage;
}
}
From e790e9474e8fab545325eaa685314ea99821d470 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Tue, 5 Jan 2021 16:11:38 +0800
Subject: [PATCH 114/308] Add Plugin Priority Settings
---
.../UserSettings/PluginSettings.cs | 5 +-
Flow.Launcher.Plugin/PluginMetadata.cs | 5 +-
Flow.Launcher/PriorityChangeWindow.xaml | 43 ++++++++++++
Flow.Launcher/PriorityChangeWindow.xaml.cs | 69 +++++++++++++++++++
Flow.Launcher/SettingWindow.xaml | 8 ++-
Flow.Launcher/SettingWindow.xaml.cs | 12 +++-
Flow.Launcher/ViewModel/MainViewModel.cs | 6 +-
Flow.Launcher/ViewModel/PluginViewModel.cs | 7 ++
.../ViewModel/SettingWindowViewModel.cs | 1 +
.../Flow.Launcher.Plugin.Calculator/Main.cs | 2 +-
10 files changed, 149 insertions(+), 9 deletions(-)
create mode 100644 Flow.Launcher/PriorityChangeWindow.xaml
create mode 100644 Flow.Launcher/PriorityChangeWindow.xaml.cs
diff --git a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs
index ccd9beb86..29bc11480 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs
@@ -31,6 +31,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
metadata.ActionKeyword = settings.ActionKeywords[0];
}
metadata.Disabled = settings.Disabled;
+ metadata.Priority = settings.Priority;
}
else
{
@@ -40,7 +41,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Name = metadata.Name,
Version = metadata.Version,
ActionKeywords = metadata.ActionKeywords,
- Disabled = metadata.Disabled
+ Disabled = metadata.Disabled,
+ Priority = metadata.Priority
};
}
}
@@ -52,6 +54,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public string Name { get; set; }
public string Version { get; set; }
public List ActionKeywords { get; set; } // a reference of the action keywords from plugin manager
+ public int Priority { get; set; }
///
/// Used only to save the state of the plugin in settings
diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs
index d81b442e2..8bcbcd231 100644
--- a/Flow.Launcher.Plugin/PluginMetadata.cs
+++ b/Flow.Launcher.Plugin/PluginMetadata.cs
@@ -37,11 +37,14 @@ namespace Flow.Launcher.Plugin
public List ActionKeywords { get; set; }
public string IcoPath { get; set;}
-
+
public override string ToString()
{
return Name;
}
+ [JsonIgnore]
+ public int Priority { get; set; }
+
///
/// Init time include both plugin load time and init time
diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml
new file mode 100644
index 000000000..51509f1ab
--- /dev/null
+++ b/Flow.Launcher/PriorityChangeWindow.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Flow.Launcher/PriorityChangeWindow.xaml.cs b/Flow.Launcher/PriorityChangeWindow.xaml.cs
new file mode 100644
index 000000000..01c6454c9
--- /dev/null
+++ b/Flow.Launcher/PriorityChangeWindow.xaml.cs
@@ -0,0 +1,69 @@
+using Flow.Launcher.Core.Plugin;
+using Flow.Launcher.Core.Resource;
+using Flow.Launcher.Infrastructure.UserSettings;
+using Flow.Launcher.Plugin;
+using Flow.Launcher.ViewModel;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Flow.Launcher
+{
+ ///
+ /// PriorityChangeWindow.xaml 的交互逻辑
+ ///
+ public partial class PriorityChangeWindow : Window
+ {
+ private readonly PluginPair plugin;
+ private Settings settings;
+ private readonly Internationalization translater = InternationalizationManager.Instance;
+ private readonly PluginViewModel pluginViewModel;
+
+ public PriorityChangeWindow(string pluginId, Settings settings, PluginViewModel pluginViewModel)
+ {
+ InitializeComponent();
+ plugin = PluginManager.GetPluginForId(pluginId);
+ this.settings = settings;
+ this.pluginViewModel = pluginViewModel;
+ if (plugin == null)
+ {
+ MessageBox.Show(translater.GetTranslation("cannotFindSpecifiedPlugin"));
+ Close();
+ }
+ }
+
+ private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
+ {
+ Close();
+ }
+
+ private void btnDone_OnClick(object sender, RoutedEventArgs e)
+ {
+ if (int.TryParse(tbAction.Text.Trim(), out var newPriority))
+ {
+ pluginViewModel.ChangePriority(newPriority);
+ Close();
+ }
+ else
+ {
+ string msg = "Please provide an valid integer";// translater.GetTranslation("newActionKeywordsHasBeenAssigned");
+ MessageBox.Show(msg);
+ }
+
+ }
+
+ private void PriorityChangeWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ OldPriority.Text = pluginViewModel.Priority.ToString();
+ tbAction.Focus();
+ }
+ }
+}
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index e47f0e779..b000db20e 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -172,10 +172,14 @@
-
+
+
+ Margin="5 0 0 0"/>
PluginPair.Metadata.InitTime.ToString() + "ms";
public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms";
public string ActionKeywordsText => string.Join(Query.ActionKeywordSeperater, PluginPair.Metadata.ActionKeywords);
+ public int Priority => PluginPair.Metadata.Priority;
public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword)
{
@@ -34,6 +35,12 @@ namespace Flow.Launcher.ViewModel
OnPropertyChanged(nameof(ActionKeywordsText));
}
+ public void ChangePriority(int newPriority)
+ {
+ PluginPair.Metadata.Priority = newPriority;
+ OnPropertyChanged(nameof(Priority));
+ }
+
public bool IsActionKeywordRegistered(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword);
}
}
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index c122f8037..4ebf898ea 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -88,6 +88,7 @@ namespace Flow.Launcher.ViewModel
var id = vm.PluginPair.Metadata.ID;
Settings.PluginSettings.Plugins[id].Disabled = vm.PluginPair.Metadata.Disabled;
+ Settings.PluginSettings.Plugins[id].Priority = vm.Priority;
}
PluginManager.Save();
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs
index 949911229..5b23ceacc 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs
@@ -91,7 +91,7 @@ namespace Flow.Launcher.Plugin.Caculator
};
}
}
- catch
+ catch (Exception)
{
// ignored
}
From a2f741b376d5c00da6ad51e0d800e5f3ccf24d5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 6 Jan 2021 09:59:20 +0800
Subject: [PATCH 115/308] change bitmap scaling mode to Fant (High Quality) to
make the search icon looks better.
---
Flow.Launcher/MainWindow.xaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 07bb96339..b6782cb60 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -92,7 +92,7 @@
-
+
Date: Wed, 6 Jan 2021 10:34:08 +0800
Subject: [PATCH 116/308] Use SVG for search icon
---
Flow.Launcher.Infrastructure/Constant.cs | 2 +-
Flow.Launcher/Flow.Launcher.csproj | 1 +
Flow.Launcher/Images/mainsearch.svg | 10 ++++++++++
Flow.Launcher/MainWindow.xaml | 9 +++++----
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
5 files changed, 18 insertions(+), 6 deletions(-)
create mode 100644 Flow.Launcher/Images/mainsearch.svg
diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs
index 3dba35f8d..de6ed1b29 100644
--- a/Flow.Launcher.Infrastructure/Constant.cs
+++ b/Flow.Launcher.Infrastructure/Constant.cs
@@ -30,7 +30,7 @@ namespace Flow.Launcher.Infrastructure
public static string PythonPath;
- public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.png";
+ public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.svg";
public const string DefaultTheme = "Darker";
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 39b2087aa..0f8e6a767 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -82,6 +82,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/Flow.Launcher/Images/mainsearch.svg b/Flow.Launcher/Images/mainsearch.svg
new file mode 100644
index 000000000..5d28abdb3
--- /dev/null
+++ b/Flow.Launcher/Images/mainsearch.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index b6782cb60..c9db58385 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -6,6 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
+ xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
mc:Ignorable="d"
Title="Flow Launcher"
Topmost="True"
@@ -68,8 +69,8 @@
Margin="18,0,56,0">
-
-
+
+
@@ -81,7 +82,7 @@
AllowDrop="True"
Visibility="Visible"
Background="Transparent"
- Margin="18,0,56,0">
+ Margin="18,1,0,1" HorizontalAlignment="Left" Width="660">
@@ -92,7 +93,7 @@
-
+
ImageLoader.Load(Constant.QueryTextBoxIconImagePath);
+ public string Image => Constant.QueryTextBoxIconImagePath;
#endregion
From 0dd6a982ad93affc9cc2d3aae8dd7a4ba31bc176 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 6 Jan 2021 15:51:52 +0800
Subject: [PATCH 117/308] change setting window to svg as well
---
Flow.Launcher/SettingWindow.xaml | 3 ++-
Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index e47f0e779..121b062ee 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -8,6 +8,7 @@
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ui="http://schemas.modernwpf.com/2019"
+ xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
x:Class="Flow.Launcher.SettingWindow"
mc:Ignorable="d"
Icon="Images\app.png"
@@ -252,7 +253,7 @@
Text="{DynamicResource hiThere}" IsReadOnly="True"
Style="{DynamicResource QueryBoxStyle}"
Margin="18 0 56 0" />
-
+
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index c122f8037..c43167e09 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -438,7 +438,7 @@ namespace Flow.Launcher.ViewModel
}
}
- public ImageSource ThemeImage => ImageLoader.Load(Constant.QueryTextBoxIconImagePath);
+ public string ThemeImage => Constant.QueryTextBoxIconImagePath;
#endregion
From 3bfd900f054687dee90a9c9670ff55e096000116 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 6 Jan 2021 16:10:52 +0800
Subject: [PATCH 118/308] revert change for oneway for mutli binding
---
Flow.Launcher/MainWindow.xaml | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index c9db58385..4373c0f0c 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -69,8 +69,8 @@
Margin="18,0,56,0">
-
-
+
+
@@ -93,7 +93,8 @@
-
+
Date: Wed, 6 Jan 2021 16:46:38 +0800
Subject: [PATCH 119/308] remove unintended change and change the binding mode
to default
---
Flow.Launcher/MainWindow.xaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 4373c0f0c..998bc3e9a 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -82,7 +82,7 @@
AllowDrop="True"
Visibility="Visible"
Background="Transparent"
- Margin="18,1,0,1" HorizontalAlignment="Left" Width="660">
+ Margin="18,0,56,0" HorizontalAlignment="Left" Width="660">
@@ -93,7 +93,7 @@
-
Date: Wed, 6 Jan 2021 17:00:16 +0800
Subject: [PATCH 120/308] change autogenerated summary to english
---
Flow.Launcher/PriorityChangeWindow.xaml.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/PriorityChangeWindow.xaml.cs b/Flow.Launcher/PriorityChangeWindow.xaml.cs
index 01c6454c9..f04ad110c 100644
--- a/Flow.Launcher/PriorityChangeWindow.xaml.cs
+++ b/Flow.Launcher/PriorityChangeWindow.xaml.cs
@@ -18,7 +18,7 @@ using System.Windows.Shapes;
namespace Flow.Launcher
{
///
- /// PriorityChangeWindow.xaml 的交互逻辑
+ /// Interaction Logic of PriorityChangeWindow.xaml
///
public partial class PriorityChangeWindow : Window
{
From 4973f2d979b2da3e6a66245b828105e6154676c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?=
Date: Wed, 6 Jan 2021 17:05:10 +0800
Subject: [PATCH 121/308] remove png file
---
Flow.Launcher/Images/mainsearch.png | Bin 63073 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 Flow.Launcher/Images/mainsearch.png
diff --git a/Flow.Launcher/Images/mainsearch.png b/Flow.Launcher/Images/mainsearch.png
deleted file mode 100644
index ac5492fa62dfa1d7bf207c60823b2f9fa6f4b622..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 63073
zcmeFZiCc~N|37}G)I{{2EQM%>Q#nMDRMKM1$T_Kq7A-mr329N3XgO(U42ru=dzK2V
zGL^KQ#*kB}nN&D!IH{z4-@lJnGxPf&e%JMJUGHn&SLeQ8%k%YI9?!?~`MNLfH8ET;
zZ}~imq86}r|7b>05?u1XZ^ZEz)!Xdn_>ZLf?t`8bwQ&vkpUBx{eJ_d{Uc~xw$APo&
zzc%{ZjCa~GGgIYvl)jW_U{g^t?^pWABm2CP4Mgtzo)_(N^zTT6pRPUrc;TbvVu{6b
z>$AR_WaKQK$55}@V`iQ7)k5Upkwq~gH~dmJxZJXdjP{(FKGu81;QLAyC!gX>=gdoo
z+)wo#-R7Avpgl6cz-s>Q-~UPA|0M8#68Qh01pLx=QYqa6P^{G_pa!?yU>$1;X~=@|{p*pMtg(iL#0?%c_Yp_@G;&9xn;pRh{$x&pEU
zUES-GZD&@_)Hyq6NU)ifQD#d|WHf(0y=`LY(xsX9gye0}$*?HAYl^FO54Xm8?gaL!OZy)AxG$xvI+ovsZ=Ol5}l_xufE
z4XgQ^SRuw9wsfvv!bh8+{%JB7dDG0%*l2WAzu*v%J4^V`yZ
znc6#d?pWr#6gGP=A+uf*aw$w&Z
zHHvDstl6@L&-&b=X3HLH
z$e)fA4q&4LSFT*KKPK?nr-awJO+QoOl$^V9O@j)5+`6+-C;oM#bB4ERe@2#$^1(YY
zhV2g+1FYe2Grh(xFMT`q*lBvkBkeeOwbp^W`ahezlLb%z_~Vb_um*L$t`T!&v@S8M
zVbAv#)q#veqkg{I%$L*K6iP>md#0lA-@l*vBi^MdpW-yD4P#Q4b$Au(TeA-~cbwiT
zd>&T3!sFA6LW}Rmc|Xuq%F$W5-K@>_>~~>DN?ZghghXmu+r&8(ch!-0$8VNhB7cbF
z;*2;E8pi6h(C|dYNayKoBWbx!s{AQB?%qP-C5FQNT>pFF{kKd~2X4hSem$z7+fy_!
z%ofGFy^TbA>+ci{L;swsz
zWn2*|lAmH68&dFWgX^hM>rT`L6=k^y+;)?R
zq!!_OIl4FE+{-n-4ns)t@R~IpUumO3;gVGDhu=g-40=8#$Dky*Y!7V~){
zYt;?m_Y$RBpL?En*z229H=cm)Czw@~nwXmQ@UP{ElS$fjh%9^hmft@fGZAHGl98*o
zoo}jCkfEZsCDW+C+pMCHE*gk&&h#mNCTm}0N+gh^AjcKq-Wthh8}S#kOe8V#EyT6j
z#~BI_a!Vf7bQBG}Jsj$n+V&0Eb#VnwSt^;&=b!g3Y~0Ug>f1T{{YVSa=E&c6ri<=`
z_q!#B2XuKA&is|vbz22*7^tdIqSQ`@%E%4ghiq*dPWOiQtO<)tpO^ik>+b$cvkDvM
z3^y0Sa8RF=10Lr@ki`U^9`8tP_U(F~tG}PEt--&~>du^({X>Zbdo16&(?(WSR`q?Z
zbG;>lsEfsK5UkwIdJU-jOp9c5jmIZXUqeR`i-Ve)ditXou#k*;ThCWI8%st%`sLsa
zs`44OF_=+fqSN*EaESKjP08Vj#{F*@-uvgapR$ZJYqD_mBNnj2tEb5?n!r4s*=B6R
zFZpLS@^#K{L}To
zqm(AuVtUNOhYuB2E?f4_%-Mxbw-jr+?psoKZU-~DG27v3sj0E?8AT$(lG%svr5sza(KO+*E>g9dk?W7O+|?n3%IR}=j>iPoTF07I9B29Omf~
z4K-+q=PSp#|FI(9t=Zo|1`o^WVQZX&TZ{+RB!@pbk@1POb?uz&+a+;FEa{Fsm*$AO
zY_g}PWmu<5G|{M9>#EFL6GlP)YD)J*C+jmE=OzWE=9W1@oFNsTU&XrVZ`(Hhr*-F|
zPthe*aW}+2|3pUHt5>i5b}uATZpV}@+3~X`rlJxTc9+$Eow3rK8h`D}Ox}}O}k`rNv_y79kpKA|s&$fwA@8Dohy+Y|S(-$e>CS%lZnyMJ~s3^Njy5Z6zU;$%d<+?
zyK$)AUjLA@p9j6aNC{r&>;2r4qVWETJQvj{V#nu#G|!80e!Y6_T4QQW$K*Ns5#3<>
zEfr~?$rl(gtH_{sar21q%^fLmu88-4@iO7&5gS@!?Hu0b@gB1ZBWZc9Ub?Z+JHU>}
z-^vH_m)lF?hXB?C_s|B{vzkgz@=Fe%A2#{)<;$0aLOjTgI7~+Ud&{fc8D~71jyANR
zV#mEXymb=>bXR9x#`&SKw#0yVc|4k31mUYuueICaY~;1vInEhFmSHFNig8yB=2~|e
z88KB|1;YbGQoMe68UqDLs^M*y*UWePAL+x3MUtdXhZPlv_fJMgN7pOfC#S^w8>eKT
zFg=}c^X6IKjG+$JDkTZZ@9QGgq3|Q;1$mmY2V_`<1M>SBt10hlEF6iVAteP1F|LS*
zPsWgAa=7g8E)$AGms(yRf+Ur@yvu2Q4IpK@K6yKnzhQ|8hufu^T;z4?RG(Yh=g&>+
zCGf1g9*$`6USD5dFd$ZQW^TfbBiB|_QqkVE)-$)lbJAP{Kh2I=4gE|i-?L{=+_~Pd
zlF;G8yG3PvDV?^Mi(?$2CC|yoXigCGoz+|5(tA7Qn`~EkSZ&W2D^B`BR
z)J3qq6;E<|UST_Fh>JFnX8x&leb}_kx;a#^O90)0pc7S7Q=@9(6r}V_foP%PYGR8Ksu&v1g2O<{Zi}
zBUZQoURN8>_1wU7TnAV%cS-e@SGr-7{5v6-tRO|sG7aMa
zE@MB-|8QZGGUTOh0r4k5tC~*dFhT_e0?+l$Y0v?_E^xV=I
zj&ODn|HC3$*6uMe(R(cDnm#C1N>!U~%*dTS!)&c}5p1l$B6#0HdwAc0H<$jlsFYIMJ^aQxQA0;Zz{VH`rEsLP
zVLc%^y!2jfh+@auIh1HeBWv1JkT=86LTz*Ttk>JTd2@tNmQLR%MqT>Drm(SF
z;U)2T^YGaCHAKIXVD;BppMLr4ufOzFk|%f3pB5va*KA0B39Y*4A}}TEHYkO8@bZtx
zd_I~S-uxhUdIudw9`pW=Ux|R4>ecmrXbI81_A}xfYPUxPGxciIcwN4~2koR(aA!5e
z^M0IJHy#QVuPSc2Fh4Vroa`aE2Tr>&^wipUDwd(2DNgl@`sRlBzqIbGe4l4WG>Ur&
z*3LP04bCPD&c>KFye~q@r_5yL>K*p-%8Ni4;2r{M<+N`x_KY&CXntc|PM=;ZLWTTM
zikQ|M8yh=ueKA%xI0uKg^V49BY3Uf^KOE=SD@HjqQ{{#=JKE05YIMr3(96$+n1)4|
zh#WVt9v+6a-_xJU>Q4HG%HETim0QA@nVzaD=>21U)~s&Uaxin!wb0N+GxnH(F=8o7
zS$%JB(x1*ybpfWH9g8Moo$l2xtxC%^8TXT*(&-T>U~_arf`2GkS^8qPUq#jSF4Suq
zsWM`g#t@@6kUrap7~pnR4@m*F9{!%kn>1OWpwMj19;-b2T9v9kpQ)NWIiyiBN0cPtU|iBF|)4W>U`{==Jc|cLPSOgb1M*dF(_$#!w=gS#?Y>Y&|>MJThAa
zEGh^1C;n9Bx3r?iB
zo8iG1liqYH{HYfcPiV{pERid7>5D=MXJ`g7*3~?q!dqS$Eq1?owz^)S!f@l=&l{
zfzN`_t5=J@M*FqyR~MV#W%qkA%jqMV$Znw7{n8LM0sFBi?gwIk?=*}b>1ig6`(XI?^
z4wi46v+G-myX47R)nov}vD}q9Ubav&ig(>^5u4(9xPOtQIJJJa!u!J!GBtNYernqh
zgH`VDH_>(+tjjMMstKE9k=ROEooQ1Z>&kP<3Wv^ddf_~+HUoug^3&*(dqt_FRNF)B
zcU#rfJp;)~f)Iju`$)e3uV@aQ!dyvF@ufgK_NB8HNybsbI9lrtA3p5eb9!5wvd=wi
z%J0LY*Ib+BTntf8>RZ1irgoKpmpfm7N
z-Ax0i(UkSP7QW3{0m+H!O?Z@FXU8E{>97o1>&t9aWVxo{APnBxu%oR@{io~+K5oTO
z?QS@Yh5WhiF+cH
zTJ=Vweqo-Ay(&)CAOK*_JuD?9W!u2OKvjC~^gdbxW+`=TpgzN9Bn_Zv`ivQ79F&EX
zH1Dt3l5f;s!3fo#LtKX!8qJY(4qd
z%in+6kKmy}31zOxsDg1#`ac0ob1DR;ASm*3aQGnW-P1I6hFIIVSj`cU-84LJ6(ft)
zA9eycw65h_=F*>$
z8*IAs9zWKK6^h{1Y^jn1?C3azroP9>=2I9WP*AR;#}$TY!{bw*
zrghH`PZkorNqZ{E;fibpPgOAZx6#b)@O}yZ&!SZJg^jyCTuI(W=5t&oN{Jt+*`lnd
ztS!_Z=$pLae5j8hp5Wv^EYx%*4C+AX}p@uX;SIK!_U*9W4^VXM>
zX==8-ddHg9=0C)Gt3^*_3}wyw=Gm~rZG~ye{SW77+<$=~cmpX&6sxmp^13XOF@P2F
zE3QcPzuxHgStmm2el=ok&3Bp5BPSPG{;L=@h1_$~=nuG_tom4N*|SM34k
zwv!y4iZ1kI{4EiCgxT~a{wA^(r@X|oA1{|aB3`KG$q3jcIwG^5jqN6yLfBEud
zWg|Ei_rYBZs$Kfir%yKYOT~f+oV3)aPmTBb`s7UKYtx*AP{T_vl0lD!HiIr`
zyNiuzAxGq{%7xf;u3f!q8!jxtcGZ3(2V$c&E7gsd%;>C;eKaCA55>*GPN;&lnhRkc$j7qoBWHy}cEC%n^FsqEx(|AMGMIw2?eBa+DIc
za)fL*vtothV0hAl_o2R{B#$H#oaMU+tQRQy_|X$-_*3xL9Dwvuum&?kS6c!)cT?Hh
zVp0m+XzAyp^YK9ER)nmT#x;8g7VRy)hTr=U`%Ib1wsFEbGRwEij5p^&OF9X9=pkCt
z@M1%fh{anR%Cg+LdPYI?a>@|-K$^6_UDy#fdIfE3!`80u^2*wntn$XXH2O#Y*wjox
z*CCL7Bc+EHN9B+owf~%X9UEa*=U3jmf|=ZKyY3u<-dk`Pgj5a+aNEL{WYsaWr(3FK
z7A^E&**WtA_YU}yIwX$aPy-5Qw?sovZ`wIIysdmCfNxC`!;(?(wWYo_w{ATU%n}L1
zhBPClWk6>Yau-W`@5VEh_NV{)seWW&rak3&-A2#?*?_u>;F~0K>lWb^@*g%+SxNhT
z-MLtXvclw(S7lkB{3?+|MIG`VYc&P0W3-g$&LvQIoQwWVCVTd5M+y~im%8+F0ZT7R
zI6paDRcXwZt^z4mxog+1Oe-s^$FuY>sA02}Pi9kc&C;<~VMfgS?$g`y!9@^m*p^-3
zN$V&Vbe5GSBrR1t(vaq@m-qzt_2Q
z|K0!s?(*qs>iuT`OkScoA#7Z2V8w
zSE9#fouJZA2GF6Op9hYJN|fro&+F2>>u`T%QT(8El-a85LJ^6XbES;(2cqdY&&(?F
zfRmzFFeNEb1VNeQKoiH9t!G#!2SlwLH2BJFW)B3W!0!KW@#014^Se~jIvPBy?7UxT
z)Sr}x6z%DWI%|cS!g3&M2`h&yKyQgaZx7*Wcu8;)DmUOSA6j>&g~{I$&z_?fD_p64
zHpjd1$r*)hGm`^ZVHXd1&t_|1Eb_;1m{o|fnbJo6y$z!$9qN^MIUpe2yu5~`BZ&P(
zYaRs4Q?n(Ebtw8s#&X_ft34jaGlm+GuIs{2_QV4jWi_1rA}ju3q(wmgz;bse1v3I9+WLl8i}dpKN2Ko+low55oJmFu7~8_4%b3Cg<_v(Y&mHsZNE*#GsD^?$p%Q_UW&noI)0vhuTweYVWXd^b$EhD#NsJ~Km#xzJ(
zB?GiVAy7>Xy?uz&7sxS%|{7#JZ(=6l?JNGo&DZwZ9#*G_^9jCX2X63rFJ&M-xMta{dLQe>W
z)rqjCUP4&kAT%7L=hNFQ7PJU_*YGbQs4bP1Z7#t9W*N;Xp3wn)mW}G1HPcarztUW!
zt=?O4HaqI0X8=oAKX*V^lx%$Rh;au;L-VT=k
zfhFJZQ$0ShTB=Cw8e9YUj+}abJauIu{2o@YYk}N}#0RC&=mK
z$*-_pr%1Ecd-@k;Mse=>ZFQAEY#(I09itk4fymmHPK@-FYVmj0g7+})?`F8r^NYvk
zKW%%dUR6|!C|(s|7Sk}gBm3}yz*_^k2smE`2M3d9WdMcg)s6EX@6go$eDm<3L}BV1
z?ybL!`!gFxi+UP&*|*rd-ahcs=2}QdLZt8|Bh)y@WQp8zdl*J&0<7gR&Ucnu@eO|T
zdRwOuHm<2$khol}_XHha3iSR6!JH}CI~8}nyPz|(bb7p;@eX9k7{l2-Fwol^nL-2B
z5B8`aMU&(YxDv9m8TD0~8*
z>SaSi!+GM!&c$o4r50|R`1;6nJ6yI+ScClnx!soGW=H9wqeqW^Zub1tVb4|kYs;%p
zhW12Dz3!60z`-G)g?54#ND|lXi1TE$K@B$y_cYH$GNccPidRfCveI%(ChvxsoU0k`
z5=if!qmoZR9jRm856@BLOa8_)C@4Zj%fr>xl`tX(S;%yD_O$Su^Pi~)IP87Ha7)Wg
z2za@v+_v|NW$Abgp
z$CH*w6Y=Xw%dN9~V_ii^p~vzDst}eJODSyf2U@{WY`n>lwd!47SJCVWz|-yQob|Mg
zXX@>40zVlve^J6X1DVCc@8{2!gJ`PQf5FyGn@+JahGglhirN-3?KUWK)*#b51azAe
z1?J}#7|vI;?M>kUjU-jSyzqWgtO0a|xi;7TA2S?&?@V}K4gS-`fhB_%8KK};W-YAv
z4@ycZK1eyhK34efgn|9RwaH&ia{Q*ohujipwOi^pR9&uvRQIIiQ@29DFp1@9jtG|jR
zbzSv1_^hT){R%v|i;YeA?^_v6F?IXEYd1`aQw!N
z(+A;~Vcl6k2%2+-OvkqIq0TDebCAzb>Fq<1y<&cSgjcj!I8SAoR)FTq%GaZs=FtW
z_T>s|T8WRGx7cDKH$oj5YII`aOo4T0B4dp86X#5=bt*W!#AGqdECaI904a>Gd%nQW
zi2hW|H6M7#2mpK06lF*7aHUB0Il@DnAO4EEm#Jz0cRz7z-&l8My?*_=gm4U;0-Smv
zT!koIq|4v%hHKteW>)bAGP3W{_NI!R5T$P=htGrw+id6m@!%fIzraNhMdGH4vg{Pk
z;3o1X?|i{jK0`T8WPP_jn;8HmXy8f1=yN4XHy!oqNVDmCb=$gQ{%6qu?k4@+yLT3|
z^FDqnG2Zkq@7