From 9c13416231074f78968640b0a4e87b4a00705651 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Mon, 6 Sep 2021 12:31:07 -0500 Subject: [PATCH 01/98] Fixes Typo TermSeparator & remove the actionkeyword in Terms --- Flow.Launcher.Core/Plugin/QueryBuilder.cs | 24 +++++------- Flow.Launcher.Plugin/Query.cs | 37 +++++++------------ Flow.Launcher/ActionKeywords.xaml.cs | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 2 +- .../Main.cs | 2 +- .../Main.cs | 2 +- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 2 +- 7 files changed, 28 insertions(+), 43 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/QueryBuilder.cs b/Flow.Launcher.Core/Plugin/QueryBuilder.cs index df336e14b..444335afd 100644 --- a/Flow.Launcher.Core/Plugin/QueryBuilder.cs +++ b/Flow.Launcher.Core/Plugin/QueryBuilder.cs @@ -10,35 +10,31 @@ namespace Flow.Launcher.Core.Plugin public static Query Build(string text, Dictionary nonGlobalPlugins) { // replace multiple white spaces with one white space - var terms = text.Split(new[] { Query.TermSeperater }, StringSplitOptions.RemoveEmptyEntries); - if (terms.Length == 0) + var textSplit = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries); + if (textSplit.Length == 0) { // nothing was typed return null; } - var rawQuery = string.Join(Query.TermSeperater, terms); + var rawQuery = string.Join(Query.TermSeparator, textSplit); string actionKeyword, search; - string possibleActionKeyword = terms[0]; - List actionParameters; + string possibleActionKeyword = textSplit[0]; + string[] terms; + if (nonGlobalPlugins.TryGetValue(possibleActionKeyword, out var pluginPair) && !pluginPair.Metadata.Disabled) { // use non global plugin for query actionKeyword = possibleActionKeyword; - actionParameters = terms.Skip(1).ToList(); - search = actionParameters.Count > 0 ? rawQuery.Substring(actionKeyword.Length + 1) : string.Empty; + search = textSplit.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..] : string.Empty; + terms = textSplit[1..]; } else { // non action keyword actionKeyword = string.Empty; search = rawQuery; + terms = textSplit; } - var query = new Query - { - Terms = terms, - RawQuery = rawQuery, - ActionKeyword = actionKeyword, - Search = search - }; + var query = new Query(rawQuery, search, terms, actionKeyword); return query; } diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index 1eb5c9c14..05e34b9d9 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -1,4 +1,5 @@ -using System; +using JetBrains.Annotations; +using System; using System.Collections.Generic; using System.Linq; @@ -23,7 +24,7 @@ namespace Flow.Launcher.Plugin /// Raw query, this includes action keyword if it has /// We didn't recommend use this property directly. You should always use Search property. /// - public string RawQuery { get; internal set; } + public string RawQuery { get; internal init; } /// /// Search part of a query. @@ -31,45 +32,40 @@ namespace Flow.Launcher.Plugin /// Since we allow user to switch a exclusive plugin to generic plugin, /// so this property will always give you the "real" query part of the query /// - public string Search { get; internal set; } + public string Search { get; internal init; } /// /// The raw query splited into a string array. /// - public string[] Terms { get; set; } + public string[] Terms { get; init; } /// /// Query can be splited into multiple terms by whitespace /// - public const string TermSeperater = " "; + public const string TermSeparator = " "; /// /// User can set multiple action keywords seperated by ';' /// - public const string ActionKeywordSeperater = ";"; + public const string ActionKeywordSeparator = ";"; /// /// '*' is used for System Plugin /// public const string GlobalPluginWildcardSign = "*"; - public string ActionKeyword { get; set; } + public string ActionKeyword { get; init; } /// /// Return first search split by space if it has /// public string FirstSearch => SplitSearch(0); + private string _secondToEndSearch; + /// /// strings from second search (including) to last search /// - public string SecondToEndSearch - { - get - { - var index = string.IsNullOrEmpty(ActionKeyword) ? 1 : 2; - return string.Join(TermSeperater, Terms.Skip(index).ToArray()); - } - } + public string SecondToEndSearch => _secondToEndSearch ??= string.Join(' ', Terms.AsMemory(2)); /// /// Return second search split by space if it has @@ -83,16 +79,9 @@ namespace Flow.Launcher.Plugin private string SplitSearch(int index) { - try - { - return string.IsNullOrEmpty(ActionKeyword) ? Terms[index] : Terms[index + 1]; - } - catch (IndexOutOfRangeException) - { - return string.Empty; - } + return index < Terms.Length ? Terms[index] : string.Empty; } public override string ToString() => RawQuery; } -} +} \ No newline at end of file diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 4a2368347..281be6e52 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -30,7 +30,7 @@ namespace Flow.Launcher private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e) { - tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeperater, plugin.Metadata.ActionKeywords.ToArray()); + tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, plugin.Metadata.ActionKeywords.ToArray()); tbAction.Focus(); } diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 1ac320cf0..b0db8bca0 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.ViewModel public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed; public string InitilizaTime => PluginPair.Metadata.InitTime.ToString() + "ms"; public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms"; - public string ActionKeywordsText => string.Join(Query.ActionKeywordSeperater, PluginPair.Metadata.ActionKeywords); + public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); public int Priority => PluginPair.Metadata.Priority; public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword) diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs index 190f40a03..a27986e75 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs @@ -27,7 +27,7 @@ namespace Flow.Launcher.Plugin.PluginIndicator IcoPath = metadata.IcoPath, Action = c => { - context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeperater}"); + context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}"); return false; } }; diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index c3d9d1ab2..29d3511eb 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { var termToSearch = query.Terms.Length <= 1 ? null - : string.Join(Plugin.Query.TermSeperater, query.Terms.Skip(1)).ToLower(); + : string.Join(Plugin.Query.TermSeparator, query.Terms.Skip(1)).ToLower(); var processlist = processHelper.GetMatchingProcesses(termToSearch); diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 58f8538f0..9ccb600e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -297,7 +297,7 @@ namespace Flow.Launcher.Plugin.Shell private void OnWinRPressed() { - context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeperater}"); + context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); // show the main window and set focus to the query box Window mainWindow = Application.Current.MainWindow; From 812703766ab03693ea1366052f9acb1682f8de41 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Tue, 7 Sep 2021 17:07:21 -0500 Subject: [PATCH 02/98] Mark previous api as obsolete to preserve backward compatibility. --- Flow.Launcher.Core/Plugin/QueryBuilder.cs | 18 +++++++-------- Flow.Launcher.Plugin/Query.cs | 23 +++++++++++++++---- .../Main.cs | 4 ++-- .../Main.cs | 4 +--- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/QueryBuilder.cs b/Flow.Launcher.Core/Plugin/QueryBuilder.cs index 444335afd..ef387b693 100644 --- a/Flow.Launcher.Core/Plugin/QueryBuilder.cs +++ b/Flow.Launcher.Core/Plugin/QueryBuilder.cs @@ -10,31 +10,31 @@ namespace Flow.Launcher.Core.Plugin public static Query Build(string text, Dictionary nonGlobalPlugins) { // replace multiple white spaces with one white space - var textSplit = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries); - if (textSplit.Length == 0) + var terms = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries); + if (terms.Length == 0) { // nothing was typed return null; } - var rawQuery = string.Join(Query.TermSeparator, textSplit); + var rawQuery = string.Join(Query.TermSeparator, terms); string actionKeyword, search; - string possibleActionKeyword = textSplit[0]; - string[] terms; + string possibleActionKeyword = terms[0]; + string[] searchTerms; if (nonGlobalPlugins.TryGetValue(possibleActionKeyword, out var pluginPair) && !pluginPair.Metadata.Disabled) { // use non global plugin for query actionKeyword = possibleActionKeyword; - search = textSplit.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..] : string.Empty; - terms = textSplit[1..]; + search = terms.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..] : string.Empty; + searchTerms = terms[1..]; } else { // non action keyword actionKeyword = string.Empty; search = rawQuery; - terms = textSplit; + searchTerms = terms; } - var query = new Query(rawQuery, search, terms, actionKeyword); + var query = new Query(rawQuery, search,terms, searchTerms, actionKeyword); return query; } diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index 05e34b9d9..12681388e 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -12,11 +12,11 @@ namespace Flow.Launcher.Plugin /// /// to allow unit tests for plug ins /// - public Query(string rawQuery, string search, string[] terms, string actionKeyword = "") + public Query(string rawQuery, string search, string[] terms, string[] searchTerms, string actionKeyword = "") { Search = search; RawQuery = rawQuery; - Terms = terms; + SearchTerms = searchTerms; ActionKeyword = actionKeyword; } @@ -35,18 +35,31 @@ namespace Flow.Launcher.Plugin public string Search { get; internal init; } /// - /// The raw query splited into a string array. + /// The search string split into a string array. /// + public string[] SearchTerms { get; init; } + + /// + /// The raw query split into a string array + /// + [Obsolete("It may or may not include action keyword, which can be confusing. Use SearchTerms instead")] public string[] Terms { get; init; } /// /// Query can be splited into multiple terms by whitespace /// public const string TermSeparator = " "; + + [Obsolete("Typo")] + public const string TermSeperater = TermSeparator; /// /// User can set multiple action keywords seperated by ';' /// public const string ActionKeywordSeparator = ";"; + + [Obsolete("Typo")] + public const string ActionKeywordSeperater = ActionKeywordSeparator; + /// /// '*' is used for System Plugin @@ -65,7 +78,7 @@ namespace Flow.Launcher.Plugin /// /// strings from second search (including) to last search /// - public string SecondToEndSearch => _secondToEndSearch ??= string.Join(' ', Terms.AsMemory(2)); + public string SecondToEndSearch => _secondToEndSearch ??= string.Join(' ', SearchTerms.AsMemory(2)); /// /// Return second search split by space if it has @@ -79,7 +92,7 @@ namespace Flow.Launcher.Plugin private string SplitSearch(int index) { - return index < Terms.Length ? Terms[index] : string.Empty; + return index < SearchTerms.Length ? SearchTerms[index] : string.Empty; } public override string ToString() => RawQuery; diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs index a27986e75..b046b2beb 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs @@ -12,11 +12,11 @@ namespace Flow.Launcher.Plugin.PluginIndicator { // if query contains more than one word, eg. github tips // user has decided to type something else rather than wanting to see the available action keywords - if (query.Terms.Length > 1) + if (query.SearchTerms.Length > 1) return new List(); var results = from keyword in PluginManager.NonGlobalPlugins.Keys - where keyword.StartsWith(query.Terms[0]) + where keyword.StartsWith(query.SearchTerms[0]) let metadata = PluginManager.NonGlobalPlugins[keyword].Metadata where !metadata.Disabled select new Result diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 29d3511eb..31b4a67ed 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -23,9 +23,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller public List Query(Query query) { - var termToSearch = query.Terms.Length <= 1 - ? null - : string.Join(Plugin.Query.TermSeparator, query.Terms.Skip(1)).ToLower(); + var termToSearch = query.Search; var processlist = processHelper.GetMatchingProcesses(termToSearch); From 9b84f6c559a1ac46fed6fd41c1dc3558dd63d289 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sat, 11 Sep 2021 09:41:39 -0500 Subject: [PATCH 03/98] fix an issue of joining string --- Flow.Launcher.Plugin/Query.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index 12681388e..84dbb3b36 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -78,7 +78,7 @@ namespace Flow.Launcher.Plugin /// /// strings from second search (including) to last search /// - public string SecondToEndSearch => _secondToEndSearch ??= string.Join(' ', SearchTerms.AsMemory(2)); + public string SecondToEndSearch => _secondToEndSearch ??= string.Join(' ', SearchTerms[1..]); /// /// Return second search split by space if it has From 6a0b190120a37309573e710bdcfb07b8fde1f744 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Mon, 20 Sep 2021 21:51:07 -0500 Subject: [PATCH 04/98] Fix Unassigned Terms --- Flow.Launcher.Plugin/Query.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index 84dbb3b36..a4a806a62 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -16,6 +16,9 @@ namespace Flow.Launcher.Plugin { Search = search; RawQuery = rawQuery; +#pragma warning disable 618 Legacy Support + Terms = terms; +#pragma warning restore 618 SearchTerms = searchTerms; ActionKeyword = actionKeyword; } @@ -38,7 +41,7 @@ namespace Flow.Launcher.Plugin /// The search string split into a string array. /// public string[] SearchTerms { get; init; } - + /// /// The raw query split into a string array /// @@ -56,7 +59,7 @@ namespace Flow.Launcher.Plugin /// User can set multiple action keywords seperated by ';' /// public const string ActionKeywordSeparator = ";"; - + [Obsolete("Typo")] public const string ActionKeywordSeperater = ActionKeywordSeparator; From 7ff9b688c91af89a49b94ea1b67c09f9462241cd Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Tue, 21 Sep 2021 13:50:51 -0500 Subject: [PATCH 05/98] Refactor Bookmark plugin --- .../Bookmark.cs | 47 ++-------- .../ChromeBookmarkLoader.cs | 26 ++++++ .../ChromeBookmarks.cs | 87 ------------------- .../ChromiumBookmarkLoader.cs | 62 +++++++++++++ .../Commands/Bookmarks.cs | 6 +- .../EdgeBookmarkLoader.cs | 30 +++++++ .../EdgeBookmarks.cs | 87 ------------------- ...xBookmarks.cs => FirefoxBookmarkLoader.cs} | 33 +++---- .../IBookmarkLoader.cs | 9 ++ 9 files changed, 156 insertions(+), 231 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarks.cs create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarks.cs rename Plugins/Flow.Launcher.Plugin.BrowserBookmark/{FirefoxBookmarks.cs => FirefoxBookmarkLoader.cs} (85%) create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs index 790c03686..185cf1620 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs @@ -7,50 +7,19 @@ using System.Text; namespace Flow.Launcher.Plugin.BrowserBookmark { - public class Bookmark : IEquatable, IEqualityComparer + // Source may be important in the future + public record Bookmark(string Name, string Url, string Source = "") { - private string m_Name; - public string Name + public override int GetHashCode() { - get - { - return m_Name; - } - set - { - m_Name = value; - } - } - public string Url { get; set; } - public string Source { get; set; } - public int Score { get; set; } - - /* TODO: since Source maybe unimportant, we just need to compare Name and Url */ - public bool Equals(Bookmark other) - { - return Equals(this, other); - } - - public bool Equals(Bookmark x, Bookmark y) - { - if (Object.ReferenceEquals(x, y)) return true; - if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) - return false; - - return x.Name == y.Name && x.Url == y.Url; - } - - public int GetHashCode(Bookmark bookmark) - { - if (Object.ReferenceEquals(bookmark, null)) return 0; - int hashName = bookmark.Name == null ? 0 : bookmark.Name.GetHashCode(); - int hashUrl = bookmark.Url == null ? 0 : bookmark.Url.GetHashCode(); + var hashName = Name?.GetHashCode() ?? 0; + var hashUrl = Url?.GetHashCode() ?? 0; return hashName ^ hashUrl; } - public override int GetHashCode() + public virtual bool Equals(Bookmark other) { - return GetHashCode(this); + return other != null && Name == other.Name && Url == other.Url; } } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs new file mode 100644 index 000000000..7fdb86f31 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace Flow.Launcher.Plugin.BrowserBookmark +{ + public class ChromeBookmarkLoader : ChromiumBookmarkLoader + { + public override List GetBookmarks() + { + return LoadChromeBookmarks(); + } + + private List LoadChromeBookmarks() + { + var bookmarks = new List(); + String platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Google\Chrome\User Data"), "Google Chrome")); + bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Google\Chrome SxS\User Data"), "Google Chrome Canary")); + bookmarks.AddRange(LoadBookmarks(Path.Combine(platformPath, @"Chromium\User Data"), "Chromium")); + return bookmarks; + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarks.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarks.cs deleted file mode 100644 index def7f3abe..000000000 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarks.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; - -namespace Flow.Launcher.Plugin.BrowserBookmark -{ - public class ChromeBookmarks - { - private List bookmarks = new List(); - - public List GetBookmarks() - { - bookmarks.Clear(); - LoadChromeBookmarks(); - - return bookmarks; - } - - private void ParseChromeBookmarks(String path, string source) - { - if (!File.Exists(path)) return; - - string all = File.ReadAllText(path); - Regex nameRegex = new Regex("\"name\": \"(?.*?)\""); - MatchCollection nameCollection = nameRegex.Matches(all); - Regex typeRegex = new Regex("\"type\": \"(?.*?)\""); - MatchCollection typeCollection = typeRegex.Matches(all); - Regex urlRegex = new Regex("\"url\": \"(?.*?)\""); - MatchCollection urlCollection = urlRegex.Matches(all); - - List names = (from Match match in nameCollection select match.Groups["name"].Value).ToList(); - List types = (from Match match in typeCollection select match.Groups["type"].Value).ToList(); - List urls = (from Match match in urlCollection select match.Groups["url"].Value).ToList(); - - int urlIndex = 0; - for (int i = 0; i < names.Count; i++) - { - string name = DecodeUnicode(names[i]); - string type = types[i]; - if (type == "url") - { - string url = urls[urlIndex]; - urlIndex++; - - if (url == null) continue; - if (url.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase)) continue; - if (url.StartsWith("vbscript:", StringComparison.OrdinalIgnoreCase)) continue; - - bookmarks.Add(new Bookmark() - { - Name = name, - Url = url, - Source = source - }); - } - } - } - - private void LoadChromeBookmarks(string path, string name) - { - if (!Directory.Exists(path)) return; - var paths = Directory.GetDirectories(path); - - foreach (var profile in paths) - { - if (File.Exists(Path.Combine(profile, "Bookmarks"))) - ParseChromeBookmarks(Path.Combine(profile, "Bookmarks"), name + (Path.GetFileName(profile) == "Default" ? "" : (" (" + Path.GetFileName(profile) + ")"))); - } - } - - private void LoadChromeBookmarks() - { - String platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - LoadChromeBookmarks(Path.Combine(platformPath, @"Google\Chrome\User Data"), "Google Chrome"); - LoadChromeBookmarks(Path.Combine(platformPath, @"Google\Chrome SxS\User Data"), "Google Chrome Canary"); - LoadChromeBookmarks(Path.Combine(platformPath, @"Chromium\User Data"), "Chromium"); - } - - private String DecodeUnicode(String dataStr) - { - Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})"); - return reg.Replace(dataStr, m => ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString()); - } - } -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs new file mode 100644 index 000000000..7be66eea5 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -0,0 +1,62 @@ +using Microsoft.AspNetCore.Authentication; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; + +namespace Flow.Launcher.Plugin.BrowserBookmark +{ + public abstract class ChromiumBookmarkLoader : IBookmarkLoader + { + public abstract List GetBookmarks(); + protected List LoadBookmarks(string browserDataPath, string name) + { + var bookmarks = new List(); + if (!Directory.Exists(browserDataPath)) return bookmarks; + var paths = Directory.GetDirectories(browserDataPath); + + foreach (var profile in paths) + { + var bookmarkPath = Path.Combine(profile, "Bookmarks"); + if (!File.Exists(bookmarkPath)) + continue; + + var source = name + (Path.GetFileName(profile) == "Default" ? "" : $" ({Path.GetFileName(profile)})"); + bookmarks.AddRange(LoadBookmarksFromFile(bookmarkPath, source)); + } + return bookmarks; + } + + protected List LoadBookmarksFromFile(string path, string source) + { + var bookmarks = new List(); + using var jsonDocument = JsonDocument.Parse(File.ReadAllText(path)); + if (!jsonDocument.RootElement.TryGetProperty("roots", out var rootElement)) + return new(); + foreach (var folder in rootElement.EnumerateObject()) + { + EnumerateFolderBookmark(folder.Value, bookmarks, source); + } + return bookmarks; + } + + private void EnumerateFolderBookmark(JsonElement folderElement, List bookmarks, string source) + { + foreach (var subElement in folderElement.GetProperty("children").EnumerateArray()) + { + switch (subElement.GetProperty("type").GetString()) + { + case "folder": + EnumerateFolderBookmark(subElement, bookmarks, source); + break; + default: + bookmarks.Add(new Bookmark( + subElement.GetProperty("name").GetString(), + subElement.GetProperty("url").GetString(), + source)); + break; + } + } + + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs index 60c4a0ee6..c7cf4867d 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs @@ -20,9 +20,9 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Commands { var allbookmarks = new List(); - var chromeBookmarks = new ChromeBookmarks(); - var mozBookmarks = new FirefoxBookmarks(); - var edgeBookmarks = new EdgeBookmarks(); + var chromeBookmarks = new ChromeBookmarkLoader(); + var mozBookmarks = new FirefoxBookmarkLoader(); + var edgeBookmarks = new EdgeBookmarkLoader(); //TODO: Let the user select which browser's bookmarks are displayed // Add Firefox bookmarks diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs new file mode 100644 index 000000000..d3f109445 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; + +namespace Flow.Launcher.Plugin.BrowserBookmark +{ + public class EdgeBookmarkLoader : ChromiumBookmarkLoader + { + + private readonly List _bookmarks = new(); + + private void LoadEdgeBookmarks() + { + var platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge\User Data"), "Microsoft Edge"); + LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge Dev\User Data"), "Microsoft Edge Dev"); + LoadBookmarks(Path.Combine(platformPath, @"Microsoft\Edge SxS\User Data"), "Microsoft Edge Canary"); + } + + public override List GetBookmarks() + { + _bookmarks.Clear(); + LoadEdgeBookmarks(); + return _bookmarks; + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarks.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarks.cs deleted file mode 100644 index 376808549..000000000 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarks.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; - -namespace Flow.Launcher.Plugin.BrowserBookmark -{ - public class EdgeBookmarks - { - private List bookmarks = new List(); - - public List GetBookmarks() - { - bookmarks.Clear(); - LoadEdgeBookmarks(); - - return bookmarks; - } - - private void ParseEdgeBookmarks(string path, string source) - { - if (!File.Exists(path)) return; - - string all = File.ReadAllText(path); - Regex nameRegex = new Regex("\"name\": \"(?.*?)\""); - MatchCollection nameCollection = nameRegex.Matches(all); - Regex typeRegex = new Regex("\"type\": \"(?.*?)\""); - MatchCollection typeCollection = typeRegex.Matches(all); - Regex urlRegex = new Regex("\"url\": \"(?.*?)\""); - MatchCollection urlCollection = urlRegex.Matches(all); - - List names = (from Match match in nameCollection select match.Groups["name"].Value).ToList(); - List types = (from Match match in typeCollection select match.Groups["type"].Value).ToList(); - List urls = (from Match match in urlCollection select match.Groups["url"].Value).ToList(); - - int urlIndex = 0; - for (int i = 0; i < names.Count; i++) - { - string name = DecodeUnicode(names[i]); - string type = types[i]; - if (type == "url") - { - string url = urls[urlIndex]; - urlIndex++; - - if (url == null) continue; - if (url.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase)) continue; - if (url.StartsWith("vbscript:", StringComparison.OrdinalIgnoreCase)) continue; - - bookmarks.Add(new Bookmark() - { - Name = name, - Url = url, - Source = source - }); - } - } - } - - private void LoadEdgeBookmarks(string path, string name) - { - if (!Directory.Exists(path)) return; - var paths = Directory.GetDirectories(path); - - foreach (var profile in paths) - { - if (File.Exists(Path.Combine(profile, "Bookmarks"))) - ParseEdgeBookmarks(Path.Combine(profile, "Bookmarks"), name + (Path.GetFileName(profile) == "Default" ? "" : (" (" + Path.GetFileName(profile) + ")"))); - } - } - - private void LoadEdgeBookmarks() - { - string platformPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - LoadEdgeBookmarks(Path.Combine(platformPath, @"Microsoft\Edge\User Data"), "Microsoft Edge"); - LoadEdgeBookmarks(Path.Combine(platformPath, @"Microsoft\Edge Dev\User Data"), "Microsoft Edge Dev"); - LoadEdgeBookmarks(Path.Combine(platformPath, @"Microsoft\Edge SxS\User Data"), "Microsoft Edge Canary"); - } - - private string DecodeUnicode(string dataStr) - { - Regex reg = new Regex(@"(?i)\\[uU]([0-9a-f]{4})"); - return reg.Replace(dataStr, m => ((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString()); - } - } -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarks.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs similarity index 85% rename from Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarks.cs rename to Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index b718da3cf..5d47c80e3 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarks.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -6,7 +6,7 @@ using System.Linq; namespace Flow.Launcher.Plugin.BrowserBookmark { - public class FirefoxBookmarks + public class FirefoxBookmarkLoader : IBookmarkLoader { private const string queryAllBookmarks = @"SELECT moz_places.url, moz_bookmarks.title FROM moz_places @@ -27,10 +27,10 @@ namespace Flow.Launcher.Plugin.BrowserBookmark if (string.IsNullOrEmpty(PlacesPath) || !File.Exists(PlacesPath)) return new List(); - var bookmarList = new List(); + var bookmarkList = new List(); // create the connection string and init the connection - string dbPath = string.Format(dbPathFormat, PlacesPath); + string dbPath = string.Format(dbPathFormat, PlacesPath); using (var dbConnection = new SQLiteConnection(dbPath)) { // Open connection to the database file and execute the query @@ -38,14 +38,13 @@ namespace Flow.Launcher.Plugin.BrowserBookmark var reader = new SQLiteCommand(queryAllBookmarks, dbConnection).ExecuteReader(); // return results in List format - bookmarList = reader.Select(x => new Bookmark() - { - Name = (x["title"] is DBNull) ? string.Empty : x["title"].ToString(), - Url = x["url"].ToString() - }).ToList(); + bookmarkList = reader.Select( + x => new Bookmark(x["title"] is DBNull ? string.Empty : x["title"].ToString(), + x["url"].ToString()) + ).ToList(); } - return bookmarList; + return bookmarkList; } /// @@ -63,7 +62,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark // get firefox default profile directory from profiles.ini string ini; - using (var sReader = new StreamReader(profileIni)) { + using (var sReader = new StreamReader(profileIni)) + { ini = sReader.ReadToEnd(); } @@ -95,7 +95,10 @@ namespace Flow.Launcher.Plugin.BrowserBookmark Version=2 */ - var lines = ini.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList(); + var lines = ini.Split(new string[] + { + "\r\n" + }, StringSplitOptions.None).ToList(); var defaultProfileFolderNameRaw = lines.Where(x => x.Contains("Default=") && x != "Default=1").FirstOrDefault() ?? string.Empty; @@ -104,14 +107,14 @@ namespace Flow.Launcher.Plugin.BrowserBookmark var defaultProfileFolderName = defaultProfileFolderNameRaw.Split('=').Last(); - var indexOfDefaultProfileAtttributePath = lines.IndexOf("Path="+ defaultProfileFolderName); + var indexOfDefaultProfileAtttributePath = lines.IndexOf("Path=" + defaultProfileFolderName); // Seen in the example above, the IsRelative attribute is always above the Path attribute var relativeAttribute = lines[indexOfDefaultProfileAtttributePath - 1]; return relativeAttribute == "0" // See above, the profile is located in a custom location, path is not relative, so IsRelative=0 - ? defaultProfileFolderName + @"\places.sqlite" - : Path.Combine(profileFolderPath, defaultProfileFolderName) + @"\places.sqlite"; + ? defaultProfileFolderName + @"\places.sqlite" + : Path.Combine(profileFolderPath, defaultProfileFolderName) + @"\places.sqlite"; } } } @@ -126,4 +129,4 @@ namespace Flow.Launcher.Plugin.BrowserBookmark } } } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs new file mode 100644 index 000000000..1dbd8b6bf --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Flow.Launcher.Plugin.BrowserBookmark +{ + public interface IBookmarkLoader + { + public List GetBookmarks(); + } +} \ No newline at end of file From d51579967bad180e9bc3da557674cfe1d40fa0c1 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Wed, 22 Sep 2021 18:09:30 -0500 Subject: [PATCH 06/98] Further Refactor & add CustomBrowsers UI --- .../ChromeBookmarkLoader.cs | 3 +- .../ChromiumBookmarkLoader.cs | 5 +- .../{Bookmarks.cs => BookmarkLoader.cs} | 16 ++++--- .../CustomChromiumBookmarkLoader.cs | 14 ++++++ .../EdgeBookmarkLoader.cs | 1 + .../FirefoxBookmarkLoader.cs | 1 + ...low.Launcher.Plugin.BrowserBookmark.csproj | 4 ++ .../IBookmarkLoader.cs | 3 +- .../Main.cs | 6 +-- .../{ => Models}/Bookmark.cs | 11 ++--- .../Models/CustomBrowser.cs | 8 ++++ .../Models/Settings.cs | 20 +++++++- .../Views/CustomBrowserSetting.xaml | 36 +++++++++++++++ .../Views/CustomBrowserSetting.xaml.cs | 45 ++++++++++++++++++ .../Views/SettingsControl.xaml | 46 +++++++++++++++---- .../Views/SettingsControl.xaml.cs | 40 +++++++++++----- 16 files changed, 218 insertions(+), 41 deletions(-) rename Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/{Bookmarks.cs => BookmarkLoader.cs} (71%) create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/CustomChromiumBookmarkLoader.cs rename Plugins/Flow.Launcher.Plugin.BrowserBookmark/{ => Models}/Bookmark.cs (73%) create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/CustomBrowser.cs create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml create mode 100644 Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml.cs diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs index 7fdb86f31..d7cfcaf6a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromeBookmarkLoader.cs @@ -1,4 +1,5 @@ -using System; +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 7be66eea5..a6edf3302 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authentication; +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using Microsoft.AspNetCore.Authentication; using System.Collections.Generic; using System.IO; using System.Text.Json; @@ -28,6 +29,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark protected List LoadBookmarksFromFile(string path, string source) { + if (!File.Exists(path)) + return new(); var bookmarks = new List(); using var jsonDocument = JsonDocument.Parse(File.ReadAllText(path)); if (!jsonDocument.RootElement.TryGetProperty("roots", out var rootElement)) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs similarity index 71% rename from Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs rename to Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs index c7cf4867d..b4c6235e0 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/Bookmarks.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs @@ -1,11 +1,12 @@ using System.Collections.Generic; using System.Linq; using Flow.Launcher.Infrastructure; +using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.SharedModels; namespace Flow.Launcher.Plugin.BrowserBookmark.Commands { - internal static class Bookmarks + internal static class BookmarkLoader { internal static MatchResult MatchProgram(Bookmark bookmark, string queryString) { @@ -18,23 +19,24 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Commands internal static List LoadAllBookmarks() { - var allbookmarks = new List(); var chromeBookmarks = new ChromeBookmarkLoader(); var mozBookmarks = new FirefoxBookmarkLoader(); var edgeBookmarks = new EdgeBookmarkLoader(); + var allBookmarks = new List(); + //TODO: Let the user select which browser's bookmarks are displayed // Add Firefox bookmarks - mozBookmarks.GetBookmarks().ForEach(x => allbookmarks.Add(x)); + allBookmarks.AddRange(mozBookmarks.GetBookmarks()); // Add Chrome bookmarks - chromeBookmarks.GetBookmarks().ForEach(x => allbookmarks.Add(x)); + allBookmarks.AddRange(chromeBookmarks.GetBookmarks()); // Add Edge (Chromium) bookmarks - edgeBookmarks.GetBookmarks().ForEach(x => allbookmarks.Add(x)); + allBookmarks.AddRange(edgeBookmarks.GetBookmarks()); - return allbookmarks.Distinct().ToList(); + return allBookmarks.Distinct().ToList(); } } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/CustomChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/CustomChromiumBookmarkLoader.cs new file mode 100644 index 000000000..91189ace7 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/CustomChromiumBookmarkLoader.cs @@ -0,0 +1,14 @@ +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using System.Collections.Generic; + +namespace Flow.Launcher.Plugin.BrowserBookmark +{ + public class CustomChromiumBookmarkLoader : ChromiumBookmarkLoader + { + public string BrowserDataPath { get; init; } + public string BookmarkFilePath { get; init; } + public string BrowserName { get; init; } + + public override List GetBookmarks() => BrowserDataPath != null ? LoadBookmarks(BrowserDataPath, BrowserName) : LoadBookmarksFromFile(BookmarkFilePath, BrowserName); + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs index d3f109445..d982ee99e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/EdgeBookmarkLoader.cs @@ -1,3 +1,4 @@ +using Flow.Launcher.Plugin.BrowserBookmark.Models; using System; using System.Collections.Generic; using System.IO; diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 5d47c80e3..3df034781 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -1,3 +1,4 @@ +using Flow.Launcher.Plugin.BrowserBookmark.Models; using System; using System.Collections.Generic; using System.Data.SQLite; 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 acfc79d7a..46313d38f 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -69,4 +69,8 @@ + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs index 1dbd8b6bf..2c48cfd55 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/IBookmarkLoader.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using System.Collections.Generic; namespace Flow.Launcher.Plugin.BrowserBookmark { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index a0b443e75..eaf14d5c2 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -26,7 +26,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark _settings = context.API.LoadSettingJsonStorage(); - cachedBookmarks = Bookmarks.LoadAllBookmarks(); + cachedBookmarks = BookmarkLoader.LoadAllBookmarks(); } public List Query(Query query) @@ -45,7 +45,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark Title = c.Name, SubTitle = c.Url, IcoPath = @"Images\bookmark.png", - Score = Bookmarks.MatchProgram(c, param).Score, + Score = BookmarkLoader.MatchProgram(c, param).Score, Action = _ => { if (_settings.OpenInNewBrowserWindow) @@ -93,7 +93,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark { cachedBookmarks.Clear(); - cachedBookmarks = Bookmarks.LoadAllBookmarks(); + cachedBookmarks = BookmarkLoader.LoadAllBookmarks(); } public string GetTranslatedPluginTitle() diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs similarity index 73% rename from Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs rename to Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs index 185cf1620..c2fa9d977 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Bookmark.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs @@ -1,11 +1,6 @@ -using BinaryAnalysis.UnidecodeSharp; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; - -namespace Flow.Launcher.Plugin.BrowserBookmark +namespace Flow.Launcher.Plugin.BrowserBookmark.Models { // Source may be important in the future public record Bookmark(string Name, string Url, string Source = "") @@ -21,5 +16,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark { return other != null && Name == other.Name && Url == other.Url; } + + public List CustomBrowsers { get; set; }= new(); } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/CustomBrowser.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/CustomBrowser.cs new file mode 100644 index 000000000..1ddeab5df --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/CustomBrowser.cs @@ -0,0 +1,8 @@ +namespace Flow.Launcher.Plugin.BrowserBookmark.Models +{ + public class CustomBrowser : BaseModel + { + public string Name { get; set; } + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Settings.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Settings.cs index dc444fd73..e63b90dbc 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Settings.cs @@ -1,9 +1,27 @@ -namespace Flow.Launcher.Plugin.BrowserBookmark.Models +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text.Json.Serialization; + +namespace Flow.Launcher.Plugin.BrowserBookmark.Models { public class Settings : BaseModel { public bool OpenInNewBrowserWindow { get; set; } = true; public string BrowserPath { get; set; } + + public ObservableCollection CustomBrowsers { get; set; } = new() + { + new CustomBrowser + { + Name="awefawef", + Path="awefawef" + }, + new CustomBrowser + { + Name = "awefawefawefawef", + Path = "aweawefawfawef" + } + }; } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml new file mode 100644 index 000000000..2370789f1 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/CustomBrowserSetting.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + /// - public void ChangeQueryText(string queryText) + public void ChangeQueryText(string queryText, bool reQuery) { - QueryText = queryText; + if (QueryText!=queryText) + { + QueryText = queryText; + } + else if (reQuery) + { + Query(); + } QueryTextCursorMovedToEnd = true; } From 54b5966e410a601f244e978b673a36a871dc5ff2 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Fri, 24 Sep 2021 20:07:01 -0500 Subject: [PATCH 12/98] add default Parameter --- 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 b5eec4972..e012a2dfd 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -285,7 +285,7 @@ namespace Flow.Launcher.ViewModel /// but we don't want to move cursor to end when query is updated from TextBox /// /// - public void ChangeQueryText(string queryText, bool reQuery) + public void ChangeQueryText(string queryText, bool reQuery = false) { if (QueryText!=queryText) { From 9a488dc89628e10b2a7060dee64ede46b15fa884 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 27 Sep 2021 07:39:49 +1000 Subject: [PATCH 13/98] version bump 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 08dab6fbf..592025103 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.8.5", + "Version": "1.9.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From 0123f5e930d9a1a7b6e6c73928ba110f76a34850 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 27 Sep 2021 14:01:14 +1000 Subject: [PATCH 14/98] add comment to clarify re-query --- Flow.Launcher/ViewModel/MainViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e012a2dfd..04b5ffede 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -289,6 +289,7 @@ namespace Flow.Launcher.ViewModel { if (QueryText!=queryText) { + // re-query is done in QueryText's setter method QueryText = queryText; } else if (reQuery) From 3a0594f99b6167873b4b0e6dd3344780685153dc Mon Sep 17 00:00:00 2001 From: Dobin Park Date: Mon, 27 Sep 2021 20:00:46 +0900 Subject: [PATCH 15/98] - Changing Result item and hotkey layout - Add Hightlight Styling - Add New Themes and adjust classic themes --- Flow.Launcher.Core/Resource/Theme.cs | 12 +- .../Converters/HighlightTextConverter.cs | 8 +- Flow.Launcher/Flow.Launcher.csproj | 4 + Flow.Launcher/MainWindow.xaml | 24 +- Flow.Launcher/ResultListBox.xaml | 51 +-- Flow.Launcher/Themes/Base.xaml | 43 +- Flow.Launcher/Themes/BlackAndWhite.xaml | 10 + Flow.Launcher/Themes/BlurBlack Darker.xaml | 8 + Flow.Launcher/Themes/BlurBlack.xaml | 8 + Flow.Launcher/Themes/BlurWhite.xaml | 4 + Flow.Launcher/Themes/Darker.xaml | 8 + Flow.Launcher/Themes/Gray.xaml | 13 + Flow.Launcher/Themes/League.Designer.xaml | 36 ++ Flow.Launcher/Themes/League.xaml | 58 +++ Flow.Launcher/Themes/Light.xaml | 13 + Flow.Launcher/Themes/Metro Server.xaml | 16 +- Flow.Launcher/Themes/Nord Darker.xaml | 8 + Flow.Launcher/Themes/Nord.xaml | 8 + Flow.Launcher/Themes/Pink.xaml | 28 +- Flow.Launcher/Themes/Win11Dark.Designer.xaml | 36 ++ Flow.Launcher/Themes/Win11Dark.xaml | 251 +++++++++++ Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +- Flow.Launcher/ViewModel/ResultsViewModel.cs | 2 +- ...her.Plugin.Explorer_ovmyrfet_wpftmp.csproj | 403 ++++++++++++++++++ 24 files changed, 991 insertions(+), 63 deletions(-) create mode 100644 Flow.Launcher/Themes/League.Designer.xaml create mode 100644 Flow.Launcher/Themes/League.xaml create mode 100644 Flow.Launcher/Themes/Win11Dark.Designer.xaml create mode 100644 Flow.Launcher/Themes/Win11Dark.xaml create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer_ovmyrfet_wpftmp.csproj diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index e70de673e..ac5363a2c 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -244,7 +244,7 @@ namespace Flow.Launcher.Core.Resource effectSetter.Property = Border.EffectProperty; effectSetter.Value = new DropShadowEffect { - Opacity = 0.9, + Opacity = 0.4, ShadowDepth = 2, BlurRadius = 15 }; @@ -261,7 +261,7 @@ namespace Flow.Launcher.Core.Resource } else { - var baseMargin = (Thickness) marginSetter.Value; + var baseMargin = (Thickness)marginSetter.Value; var newMargin = new Thickness( baseMargin.Left + ShadowExtraMargin, baseMargin.Top + ShadowExtraMargin, @@ -282,8 +282,8 @@ namespace Flow.Launcher.Core.Resource var effectSetter = windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == Border.EffectProperty) as Setter; var marginSetter = windowBorderStyle.Setters.FirstOrDefault(setterBase => setterBase is Setter setter && setter.Property == Border.MarginProperty) as Setter; - - if(effectSetter != null) + + if (effectSetter != null) { windowBorderStyle.Setters.Remove(effectSetter); } @@ -371,11 +371,11 @@ namespace Flow.Launcher.Core.Resource private void SetWindowAccent(Window w, AccentState state) { var windowHelper = new WindowInteropHelper(w); - + // this determines the width of the main query window w.Width = mainWindowWidth; windowHelper.EnsureHandle(); - + var accent = new AccentPolicy { AccentState = state }; var accentStructSize = Marshal.SizeOf(accent); diff --git a/Flow.Launcher/Converters/HighlightTextConverter.cs b/Flow.Launcher/Converters/HighlightTextConverter.cs index 006e52320..6bea2092c 100644 --- a/Flow.Launcher/Converters/HighlightTextConverter.cs +++ b/Flow.Launcher/Converters/HighlightTextConverter.cs @@ -1,4 +1,4 @@ -using System; +using System.Windows;using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -6,6 +6,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; +using System.Windows.Media; using System.Windows.Documents; namespace Flow.Launcher.Converters @@ -30,7 +31,10 @@ namespace Flow.Launcher.Converters var currentCharacter = text.Substring(i, 1); if (this.ShouldHighlight(highlightData, i)) { - textBlock.Inlines.Add(new Bold(new Run(currentCharacter))); + //textBlock.Inlines.Add(new Bold(new Run(currentCharacter))); + //textBlock.Inlines.Add(new Run(currentCharacter) { Foreground = Brushes.RoyalBlue }); + textBlock.Inlines.Add(new Run(currentCharacter) { Style = (Style)Application.Current.FindResource("HighlightStyle") }); + } else { diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 529fc52a2..bb3c84eec 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -47,7 +47,11 @@ + + + + diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 83cc016bb..80373e1f8 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -31,6 +31,7 @@ + @@ -62,13 +63,13 @@ - + + Margin="16,0,56,0"> @@ -83,24 +84,29 @@ AllowDrop="True" Visibility="Visible" Background="Transparent" - Margin="18,0,56,0"> + Margin="16,0,56,0"> - + - + - + + - + Y1="0" Y2="0" X2="100" Height="2" Width="Auto" StrokeThickness="1"> + + + diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml index dfee89810..605d0ffa5 100644 --- a/Flow.Launcher/ResultListBox.xaml +++ b/Flow.Launcher/ResultListBox.xaml @@ -20,6 +20,7 @@ IsSynchronizedWithCurrentItem="True" PreviewMouseDown="ListBox_PreviewMouseDown"> + - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + - - - - - + + + + + + + + - + - - - - - - - - + Width="130" Margin="10 0 0 0"> + + + + + + + + + + + + + + +  + - - - - - - - + + + + + + - + - - - - - - - - + Width="130" Margin="10 -2 0 0"> + + + + + + + + + + + + + + +  + - - - + + + + + + + + + + + + +  + + + + - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - -