From fa8c3db5e1a22322543becefddea3a007d9988b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 19 May 2021 12:50:29 +0800 Subject: [PATCH 001/221] stop auto hiding scroller --- Flow.Launcher/SettingWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 651d7db09..4cb585597 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -36,7 +36,7 @@ - + From acba2dd1a39d0f73421dad0c202a463820fb787f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sat, 22 May 2021 17:23:25 +0800 Subject: [PATCH 002/221] Add specific keyword for path explore in explorer plugin --- .editorconfig | 4 ++ Flow.Launcher.Test/Flow.Launcher.Test.csproj | 4 ++ Flow.Launcher.sln | 1 + .../Languages/en.xaml | 3 +- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 4 +- .../Search/EnvironmentVariables.cs | 6 +-- .../Search/SearchManager.cs | 41 ++++++++++++++----- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 2 + .../ViewModels/SettingsViewModel.cs | 31 ++++++++++---- .../Views/ActionKeywordSetting.xaml.cs | 14 +++---- .../Views/ExplorerSettings.xaml | 2 +- .../Views/ExplorerSettings.xaml.cs | 41 +++++++++++-------- 12 files changed, 106 insertions(+), 47 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..d69b8462e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# IDE0011: 添加大括号 +csharp_prefer_braces = when_multiline diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 1d0dce5e7..5906e6093 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -38,6 +38,10 @@ + + + + diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index 21c3b47dc..46c4488a1 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -45,6 +45,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Url", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FFD651C7-0546-441F-BC8C-D4EE8FD01EA7}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore appveyor.yml = appveyor.yml diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 9ba0da3f6..3a1a1fb05 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -19,7 +19,8 @@ Quick Access Links Index Search Excluded Paths Indexing Options - Search Activation: + Index Search Activation: + Path Explore Activation: File Content Search: diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index 8204e755c..92b7c95a0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -28,7 +28,7 @@ namespace Flow.Launcher.Plugin.Explorer return new ExplorerSettings(viewModel); } - public async Task InitAsync(PluginInitContext context) + public Task InitAsync(PluginInitContext context) { Context = context; @@ -47,6 +47,8 @@ namespace Flow.Launcher.Plugin.Explorer contextMenu = new ContextMenu(Context, Settings, viewModel); searchManager = new SearchManager(Settings, Context); ResultManager.Init(Context); + + return Task.CompletedTask; } public List LoadContextMenus(Result selectedResult) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs index 1e9815cb9..595ac3610 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs @@ -10,10 +10,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search { internal static bool IsEnvironmentVariableSearch(string search) { - return LoadEnvironmentStringPaths().Count > 0 - && search.StartsWith("%") + return search.StartsWith("%") && search != "%%" - && !search.Contains("\\"); + && !search.Contains("\\") && + LoadEnvironmentStringPaths().Count > 0; } internal static Dictionary LoadEnvironmentStringPaths() diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index e9b4b0fc1..1cb82b75f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -39,21 +39,47 @@ namespace Flow.Launcher.Plugin.Explorer.Search internal async Task> SearchAsync(Query query, CancellationToken token) { - var results = new HashSet(PathEqualityComparator.Instance); - var querySearch = query.Search; if (IsFileContentSearch(query.ActionKeyword)) return await WindowsIndexFileContentSearchAsync(query, querySearch, token).ConfigureAwait(false); + var result = new HashSet(PathEqualityComparator.Instance); + + if (ActionKeywordMatch(query, settings.PathSearchActionKeyword)) + { + result.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); + } + + if (ActionKeywordMatch(query, settings.SearchActionKeyword) && + querySearch.Length > 0 && + !querySearch.IsLocationPathString()) + { + result.UnionWith(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token).ConfigureAwait(false)); + } + + return result.ToList(); + } + + private bool ActionKeywordMatch(Query query, string actionKeyword) + { + return query.ActionKeyword == actionKeyword || + query.ActionKeyword.Length == 0 && actionKeyword == Query.GlobalPluginWildcardSign; + } + + public async Task> PathSearchAsync(Query query, CancellationToken token = default) + { + var querySearch = query.Search; + // This allows the user to type the assigned action keyword and only see the list of quick folder links if (string.IsNullOrEmpty(query.Search)) return QuickAccess.AccessLinkListAll(query, settings.QuickAccessLinks); + var results = new HashSet(PathEqualityComparator.Instance); + var quickaccessLinks = QuickAccess.AccessLinkListMatched(query, settings.QuickAccessLinks); - if (quickaccessLinks.Count > 0) - results.UnionWith(quickaccessLinks); + results.UnionWith(quickaccessLinks); var isEnvironmentVariable = EnvironmentVariables.IsEnvironmentVariableSearch(querySearch); @@ -63,13 +89,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search // Query is a location path with a full environment variable, eg. %appdata%\somefolder\ var isEnvironmentVariablePath = querySearch[1..].Contains("%\\"); - if (!querySearch.IsLocationPathString() && !isEnvironmentVariablePath) - { - results.UnionWith(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token).ConfigureAwait(false)); - - return results.ToList(); - } - var locationPath = querySearch; if (isEnvironmentVariablePath) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index a8eac986d..e078bca67 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -20,5 +20,7 @@ namespace Flow.Launcher.Plugin.Explorer public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; public string FileContentSearchActionKeyword { get; set; } = Constants.DefaultContentSearchActionKeyword; + + public string PathSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 92932bf4c..9d4019b9a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -41,19 +41,36 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels Process.Start(psi); } - internal void UpdateActionKeyword(string newActionKeyword, string oldActionKeyword) + internal void UpdateActionKeyword(ActionKeywordProperty modifiedActionKeyword, string newActionKeyword, string oldActionKeyword) { - PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword); + if (Settings.SearchActionKeyword == Settings.PathSearchActionKeyword) + PluginManager.AddActionKeyword(Context.CurrentPluginMetadata.ID, newActionKeyword); + else + PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword); - if (Settings.FileContentSearchActionKeyword == oldActionKeyword) - Settings.FileContentSearchActionKeyword = newActionKeyword; - - if (Settings.SearchActionKeyword == oldActionKeyword) - Settings.SearchActionKeyword = newActionKeyword; + switch (modifiedActionKeyword) + { + case ActionKeywordProperty.SearchActionKeyword: + Settings.SearchActionKeyword = newActionKeyword; + break; + case ActionKeywordProperty.PathSearchActionKeyword: + Settings.PathSearchActionKeyword = newActionKeyword; + break; + case ActionKeywordProperty.FileContentSearchActionKeyword: + Settings.FileContentSearchActionKeyword = newActionKeyword; + break; + } } internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); internal bool IsNewActionKeywordGlobal(string newActionKeyword) => newActionKeyword == Query.GlobalPluginWildcardSign; } + + public enum ActionKeywordProperty + { + SearchActionKeyword, + PathSearchActionKeyword, + FileContentSearchActionKeyword + } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs index 2957283ad..d1040f746 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs @@ -23,6 +23,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views private ActionKeywordView currentActionKeyword; + private List actionKeywordListView; public ActionKeywordSetting(SettingsViewModel settingsViewModel, List actionKeywordListView, ActionKeywordView selectedActionKeyword) @@ -35,7 +36,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views txtCurrentActionKeyword.Text = selectedActionKeyword.Keyword; - this.actionKeywordListView = actionKeywordListView; + this.actionKeywordListView = actionKeywordListView; } private void OnConfirmButtonClick(object sender, RoutedEventArgs e) @@ -52,20 +53,19 @@ namespace Flow.Launcher.Plugin.Explorer.Views return; } - if (settingsViewModel.IsNewActionKeywordGlobal(newActionKeyword) - && currentActionKeyword.Description - == settingsViewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_filecontentsearch")) + if (settingsViewModel.IsNewActionKeywordGlobal(newActionKeyword) + && currentActionKeyword.KeywordProperty == ActionKeywordProperty.FileContentSearchActionKeyword) { MessageBox.Show(settingsViewModel.Context.API.GetTranslation("plugin_explorer_globalActionKeywordInvalid")); return; } - + if (!settingsViewModel.IsActionKeywordAlreadyAssigned(newActionKeyword)) { - settingsViewModel.UpdateActionKeyword(newActionKeyword, currentActionKeyword.Keyword); + settingsViewModel.UpdateActionKeyword(currentActionKeyword.KeywordProperty, newActionKeyword, currentActionKeyword.Keyword); - actionKeywordListView.Where(x => x.Description == currentActionKeyword.Description).FirstOrDefault().Keyword = newActionKeyword; + actionKeywordListView.FirstOrDefault(x => x.Description == currentActionKeyword.Description).Keyword = newActionKeyword; Close(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index b4795ec8b..ce6dbba36 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -24,7 +24,7 @@ Margin="0,5,0,0" /> + Margin="250,5,0,0" /> diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs index 26f169c92..b8c9a605a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml.cs @@ -35,16 +35,24 @@ namespace Flow.Launcher.Plugin.Explorer.Views actionKeywordsListView = new List { - new ActionKeywordView() - { - Description = viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_search"), - Keyword = this.viewModel.Settings.SearchActionKeyword - }, - new ActionKeywordView() - { - Description = viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_filecontentsearch"), - Keyword = this.viewModel.Settings.FileContentSearchActionKeyword - } + new () + { + Description = viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_search"), + Keyword = this.viewModel.Settings.SearchActionKeyword, + KeywordProperty = ActionKeywordProperty.SearchActionKeyword + }, + new () + { + Description = viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_filecontentsearch"), + Keyword = this.viewModel.Settings.FileContentSearchActionKeyword, + KeywordProperty = ActionKeywordProperty.FileContentSearchActionKeyword + }, + new () + { + Description = viewModel.Context.API.GetTranslation("plugin_explorer_actionkeywordview_path"), + Keyword = this.viewModel.Settings.PathSearchActionKeyword, + KeywordProperty = ActionKeywordProperty.PathSearchActionKeyword + } }; lbxActionKeywords.ItemsSource = actionKeywordsListView; @@ -71,7 +79,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views && btnEdit.Visibility == Visibility.Hidden) btnEdit.Visibility = Visibility.Visible; - if ((lbxAccessLinks.Items.Count == 0 && lbxExcludedPaths.Items.Count == 0) + if (lbxAccessLinks.Items.Count == 0 && lbxExcludedPaths.Items.Count == 0 && btnDelete.Visibility == Visibility.Visible && btnEdit.Visibility == Visibility.Visible) { @@ -122,7 +130,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views private void expActionKeywords_Collapsed(object sender, RoutedEventArgs e) { if (!expActionKeywords.IsExpanded) - expActionKeywords.Height = Double.NaN; + expActionKeywords.Height = double.NaN; } private void expAccessLinks_Click(object sender, RoutedEventArgs e) @@ -135,20 +143,20 @@ namespace Flow.Launcher.Plugin.Explorer.Views if (expActionKeywords.IsExpanded) expActionKeywords.IsExpanded = false; - + RefreshView(); } private void expAccessLinks_Collapsed(object sender, RoutedEventArgs e) { if (!expAccessLinks.IsExpanded) - expAccessLinks.Height = Double.NaN; + expAccessLinks.Height = double.NaN; } private void expExcludedPaths_Click(object sender, RoutedEventArgs e) { if (expExcludedPaths.IsExpanded) - expAccessLinks.Height = Double.NaN; + expAccessLinks.Height = double.NaN; if (expAccessLinks.IsExpanded) expAccessLinks.IsExpanded = false; @@ -161,7 +169,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views private void btnDelete_Click(object sender, RoutedEventArgs e) { - var selectedRow = lbxAccessLinks.SelectedItem as AccessLink?? lbxExcludedPaths.SelectedItem as AccessLink; + var selectedRow = lbxAccessLinks.SelectedItem as AccessLink ?? lbxExcludedPaths.SelectedItem as AccessLink; if (selectedRow != null) { @@ -315,6 +323,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views { public string Description { get; set; } + public ActionKeywordProperty KeywordProperty { get; init; } public string Keyword { get; set; } } } From 972a291be3d01e96e2f4d1f2cb920bd71afab236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sat, 22 May 2021 17:26:49 +0800 Subject: [PATCH 003/221] add Chinese translation --- Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml index c4a2322b2..1aed9bf29 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml @@ -20,6 +20,7 @@ 索引搜索排除的路径 索引选项 搜索激活: + 路径搜索激活: 文件内容搜索: From e8691c210dbd2ee79d9f06503402a8bd4a2e2720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 23 May 2021 12:28:45 +0800 Subject: [PATCH 004/221] No need for the wrapped Lazy instance in image loading. --- Flow.Launcher/ResultListBox.xaml | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 92 ++++++---------------- 2 files changed, 27 insertions(+), 67 deletions(-) diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml index 2f9d06d81..0f70dce41 100644 --- a/Flow.Launcher/ResultListBox.xaml +++ b/Flow.Launcher/ResultListBox.xaml @@ -42,7 +42,7 @@ + Source="{Binding Image}" /> diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index c91bbb107..dd4b351c3 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -11,62 +11,12 @@ namespace Flow.Launcher.ViewModel { public class ResultViewModel : BaseModel { - public class LazyAsync : Lazy> - { - private readonly T defaultValue; - - private readonly Action _updateCallback; - public new T Value - { - get - { - if (!IsValueCreated) - { - _ = Exercute(); // manually use callback strategy - - return defaultValue; - } - - if (!base.Value.IsCompletedSuccessfully) - 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) - { - if (defaultValue != null) - { - this.defaultValue = defaultValue; - } - - _updateCallback = updateCallback; - } - } - public ResultViewModel(Result result, Settings settings) { if (result != null) { Result = result; - - Image = new LazyAsync( - SetImage, - ImageLoader.DefaultImage, - () => - { - OnPropertyChanged(nameof(Image)); - }); - } + } Settings = settings; } @@ -85,44 +35,54 @@ namespace Flow.Launcher.ViewModel ? Result.SubTitle : Result.SubTitleToolTip; - public LazyAsync Image { get; set; } + private bool ImageLoaded; - private async ValueTask SetImage() + private ImageSource image = ImageLoader.DefaultImage; + + public ImageSource Image + { + get + { + if (!ImageLoaded) + { + ImageLoaded = true; + LoadImage(); + } + return image; + } + private set => image = value; + } + private async void LoadImage() { var imagePath = Result.IcoPath; if (string.IsNullOrEmpty(imagePath) && Result.Icon != null) { try { - return Result.Icon(); + Image = Result.Icon(); + return; } catch (Exception e) { Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); - return ImageLoader.DefaultImage; } } 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); + Image = ImageLoader.Load(imagePath); + return; + } - return await Task.Run(() => ImageLoader.Load(imagePath)); + Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false); } public Result Result { get; } public override bool Equals(object obj) { - var r = obj as ResultViewModel; - if (r != null) - { - return Result.Equals(r.Result); - } - else - { - return false; - } + return obj is ResultViewModel r && Result.Equals(r.Result); } public override int GetHashCode() From 37f1a64495b848e5951cce83d57e375bb5fce5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 23 May 2021 22:54:52 +0800 Subject: [PATCH 005/221] avoid duplicate removing --- Flow.Launcher.Infrastructure/Image/ImageCache.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index bb7ec6817..4e95278c1 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) @@ -35,6 +35,8 @@ namespace Flow.Launcher.Infrastructure.Image } } + private volatile bool removing; + public ImageSource this[string path] { get @@ -62,11 +64,13 @@ namespace Flow.Launcher.Infrastructure.Image // To prevent the dictionary from drastically increasing in size by caching images, the dictionary size is not allowed to grow more than the permissibleFactor * maxCached size // This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time - if (Data.Count > permissibleFactor * MaxCached) + if (Data.Count > permissibleFactor * MaxCached && !removing) { + removing = true; // 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)) Data.TryRemove(key, out _); + removing = false; } } } From 1c6d207595c941c8bfa3d99a12d7e5c208ffe007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 24 May 2021 10:34:16 +0800 Subject: [PATCH 006/221] only modify property when async (avoid duplicate read) --- 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 dd4b351c3..791aa6da9 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -59,7 +59,7 @@ namespace Flow.Launcher.ViewModel { try { - Image = Result.Icon(); + image = Result.Icon(); return; } catch (Exception e) @@ -71,7 +71,7 @@ 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 - Image = ImageLoader.Load(imagePath); + image = ImageLoader.Load(imagePath); return; } From 734a0cbfa1ac5fbfa47b4b6cdae13c8c20b2b051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 24 May 2021 10:35:18 +0800 Subject: [PATCH 007/221] Update comment --- Flow.Launcher/ViewModel/ResultViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 791aa6da9..4d57f8252 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -75,6 +75,7 @@ namespace Flow.Launcher.ViewModel return; } + // We need to modify the property not field here to trigger the OnPropertyChanged event Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false); } From 39b750e821488cad8e1f9fd27716e586fba3ae40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 24 May 2021 12:34:59 +0800 Subject: [PATCH 008/221] Avoid AppxManifest.xml leak release Com stream Object immediately Co-Authored-By: Andrey Nekrasov <1828123+yuyoyuppe@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs index 89d6dcc7d..e53fb7a52 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs @@ -17,6 +17,7 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.Program.Logger; using Rect = System.Windows.Rect; using Flow.Launcher.Plugin.SharedModels; +using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher.Plugin.Program.Programs { @@ -81,6 +82,11 @@ namespace Flow.Launcher.Plugin.Program.Programs Apps = new List().ToArray(); } + + if (Marshal.ReleaseComObject(stream) > 0) + { + Log.Error("Flow.Launcher.Plugin.Program.Programs.UWP", "AppxManifest.xml was leaked"); + } } From 89757de04eab1bca5f5d6c2097d0377e73c2370f Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 24 May 2021 21:04:50 +1000 Subject: [PATCH 009/221] version bump Program plugin --- Plugins/Flow.Launcher.Plugin.Program/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/plugin.json b/Plugins/Flow.Launcher.Plugin.Program/plugin.json index 2d335b77d..79044f08a 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.5.0", + "Version": "1.5.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Program.dll", From d024f8eff4c6ffdd3a001bf3c202e8f29e01bdb9 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 25 May 2021 22:20:22 +1000 Subject: [PATCH 010/221] fix loading when no action keywords present for a plugin in userdata --- Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs index 29bc11480..dd768afb4 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs @@ -30,6 +30,11 @@ namespace Flow.Launcher.Infrastructure.UserSettings metadata.ActionKeywords = settings.ActionKeywords; metadata.ActionKeyword = settings.ActionKeywords[0]; } + else + { + metadata.ActionKeywords = new List(); + metadata.ActionKeyword = string.Empty; + } metadata.Disabled = settings.Disabled; metadata.Priority = settings.Priority; } From e06cf9cf6fada1a7bc6645d4d2d9652eccc08ae3 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 26 May 2021 08:38:55 +1000 Subject: [PATCH 011/221] add tool tip to explain functionality --- Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml | 3 +++ .../Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml | 6 +++--- Plugins/Flow.Launcher.Plugin.Program/plugin.json | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml index ce84aa65b..e00534367 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml @@ -13,8 +13,11 @@ Reindex Indexing Index Start Menu + When enabled, Flow will load programs from the start menu Index Registry + When enabled, Flow will load programs from the registry Enable Program Description + Disabling this will also stop Flow from searching via the program desciption Suffixes Max Depth diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml index 45f2a609d..8712cdb83 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml @@ -16,9 +16,9 @@ - - - + + +