Skip to content

Commit 9f875e0

Browse files
authored
refactor: all repo (#59)
* refactor (Resources): rename Resources keys for improved clarity * refactor (OpenHomePage): unify OpenHomePage logic with SearchWebCommand * refactor (SearchWeb): rename SearchCommand → SearchWebCommand and SearchPage → SearchWebPage for clarity * fix (Storage): respect provided path in WriteToFile instead of always using StateJsonPath * chore: remove unnecessary and outdated comments, reorder variables, format * refactor(Icons): move Icons.cs to Properties folder * refactor (SearchWebCommand): rename Arguments to Query for clarity * fix (Commands): use Icons.Search instead of hardcoded search icon in OpenHomePageCommand and SearchWebCommand * refactor (WebSearchShortcutDataEntry): rename WebSearchShortcutItem → WebSearchShortcutDataEntry for clarity * refactor: SearchWebPage * refactor: WebSearchShortcutCommandsProvider * refactor: Suggestions * refactor (BrowserDiscovery): replace DCL with Lazy<T> cache and ensure memory visibility; add warm reload * refactor: others
1 parent f56bf62 commit 9f875e0

40 files changed

Lines changed: 1018 additions & 1121 deletions

CmdPalWebSearchShortcut/WebSearchShortcut/Browsers/BrowserDiscovery.cs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,31 @@
11
using System;
22
using System.Linq;
33
using System.Collections.Generic;
4+
using System.Threading;
45
using Microsoft.Win32;
56

67
namespace WebSearchShortcut.Browsers;
78

89
public static class BrowserDiscovery
910
{
10-
private static readonly object _loadLock = new();
11-
private static bool _isLoaded;
12-
private static List<BrowserInfo> _cachedBrowsers = [];
11+
private static Lazy<BrowserInfo[]> _installedBrowsersCache = CreateInstalledBrowsersCache();
12+
private static Lazy<BrowserInfo[]> CreateInstalledBrowsersCache() =>
13+
new(LoadInstalledBrowsers, LazyThreadSafetyMode.ExecutionAndPublication);
14+
public static IReadOnlyCollection<BrowserInfo> GetAllInstalledBrowsers() => _installedBrowsersCache.Value;
1315

14-
public static List<BrowserInfo> GetAllInstalledBrowsers()
16+
public static void Reload(bool warm = false)
1517
{
16-
if (_isLoaded) return _cachedBrowsers;
18+
var newCache = CreateInstalledBrowsersCache();
1719

18-
lock (_loadLock)
19-
{
20-
if (!_isLoaded)
21-
{
22-
_cachedBrowsers = LoadInstalledBrowsers();
23-
_isLoaded = true;
24-
}
25-
}
20+
Interlocked.Exchange(ref _installedBrowsersCache, newCache);
2621

27-
return _cachedBrowsers;
28-
}
29-
30-
public static void Reload()
31-
{
32-
lock (_loadLock)
33-
{
34-
_cachedBrowsers = LoadInstalledBrowsers();
35-
_isLoaded = true;
36-
}
22+
if (warm)
23+
_ = newCache.Value;
3724
}
3825

39-
private static List<BrowserInfo> LoadInstalledBrowsers()
26+
private static BrowserInfo[] LoadInstalledBrowsers()
4027
{
41-
List<string> progIds = GetAssociatedProgIds();
28+
string[] progIds = GetAssociatedProgIds();
4229
List<BrowserInfo> result = [];
4330

4431
foreach (var progId in progIds)
@@ -56,9 +43,9 @@ private static List<BrowserInfo> LoadInstalledBrowsers()
5643
return [.. result.OrderBy(b => b.Name, StringComparer.OrdinalIgnoreCase)];
5744
}
5845

59-
private static List<string> GetAssociatedProgIds()
46+
private static string[] GetAssociatedProgIds()
6047
{
61-
HashSet<string> progIdSet = new HashSet<string>();
48+
HashSet<string> progIdSet = [];
6249

6350
progIdSet.UnionWith(ScanProgIdsFromRegistry(
6451
Registry.LocalMachine,

CmdPalWebSearchShortcut/WebSearchShortcut/Browsers/BrowserExecutionInfo.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,34 @@
33

44
namespace WebSearchShortcut.Browsers;
55

6-
public class BrowserExecutionInfo
6+
internal sealed class BrowserExecutionInfo
77
{
88
public string? Path { get; }
99
public string? ArgumentsPattern { get; }
1010

11-
public BrowserExecutionInfo(WebSearchShortcutItem item)
11+
public BrowserExecutionInfo(WebSearchShortcutDataEntry shortcut)
1212
{
1313
DefaultBrowserProvider.UpdateIfTimePassed();
1414

15-
Path = !string.IsNullOrWhiteSpace(item.BrowserPath)
16-
? item.BrowserPath
15+
Path = !string.IsNullOrWhiteSpace(shortcut.BrowserPath)
16+
? shortcut.BrowserPath
1717
: DefaultBrowserProvider.Path;
1818

1919
string? trimmedArgs;
2020

21-
if (!string.IsNullOrWhiteSpace(item.BrowserArgs))
21+
if (!string.IsNullOrWhiteSpace(shortcut.BrowserArgs))
2222
{
23-
trimmedArgs = item.BrowserArgs.Trim();
23+
trimmedArgs = shortcut.BrowserArgs.Trim();
2424
}
25-
else if (string.IsNullOrWhiteSpace(item.BrowserPath))
25+
else if (string.IsNullOrWhiteSpace(shortcut.BrowserPath))
2626
{
2727
trimmedArgs = DefaultBrowserProvider.ArgumentsPattern;
2828
}
2929
else
3030
{
3131
trimmedArgs = BrowserDiscovery
3232
.GetAllInstalledBrowsers()
33-
.FirstOrDefault(b => string.Equals(b.Path, item.BrowserPath, StringComparison.OrdinalIgnoreCase))
33+
.FirstOrDefault(b => string.Equals(b.Path, shortcut.BrowserPath, StringComparison.OrdinalIgnoreCase))
3434
?.ArgumentsPattern.Trim();
3535
}
3636

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
namespace WebSearchShortcut.Browsers;
22

3-
public record BrowserInfo(string Id, string Name, string Path, string ArgumentsPattern);
3+
public sealed record BrowserInfo(string Id, string Name, string Path, string ArgumentsPattern);

CmdPalWebSearchShortcut/WebSearchShortcut/Browsers/DefaultBrowserProvider.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6-
using System.Text;
76
using System.Threading;
87
using Microsoft.Win32;
98

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
11
using Microsoft.CommandPalette.Extensions.Toolkit;
2-
using WebSearchShortcut.Properties;
2+
using WebSearchShortcut.Browsers;
33
using WebSearchShortcut.Helpers;
4+
using WebSearchShortcut.Properties;
45

56
namespace WebSearchShortcut.Commands;
67

78
internal sealed partial class OpenHomePageCommand : InvokableCommand
89
{
9-
// private readonly SettingsManager _settingsManager;
10-
public WebSearchShortcutItem Item;
10+
private readonly WebSearchShortcutDataEntry _shortcut;
11+
private readonly BrowserExecutionInfo _browserInfo;
1112

12-
internal OpenHomePageCommand(WebSearchShortcutItem item)
13+
internal OpenHomePageCommand(WebSearchShortcutDataEntry shortcut)
1314
{
14-
Icon = new IconInfo("\uE721");
15-
Name = StringFormatter.Format(Resources.OpenHomePageCommand_Name, new() { ["engine"] = item.Name });
16-
Item = item;
17-
// Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png");
18-
// Name = Properties.Resources.open_in_default_browser;
19-
// _settingsManager = settingsManager;
15+
Name = StringFormatter.Format(Resources.OpenHomePage_NameTemplate, new() { ["engine"] = shortcut.Name });
16+
Icon = Icons.Search;
17+
_shortcut = shortcut;
18+
_browserInfo = new BrowserExecutionInfo(shortcut);
2019
}
2120

2221
public override CommandResult Invoke()
2322
{
24-
if (!HomePageLauncher.OpenHomePageWithBrowser(Item))
23+
if (!ShellHelpers.OpenCommandInShell(_browserInfo.Path, _browserInfo.ArgumentsPattern, WebSearchShortcutDataEntry.GetHomePageUrl(_shortcut)))
2524
{
2625
// TODO GH# 138 --> actually display feedback from the extension somewhere.
2726
return CommandResult.KeepOpen();
2827
}
2928

30-
// if (_settingsManager.ShowHistory != Resources.history_none)
31-
// {
32-
// _settingsManager.SaveHistory(new HistoryItem(Arguments, DateTime.Now));
33-
// }
34-
3529
return CommandResult.Dismiss();
3630
}
3731
}

CmdPalWebSearchShortcut/WebSearchShortcut/Commands/SearchCommand.cs renamed to CmdPalWebSearchShortcut/WebSearchShortcut/Commands/SearchWebCommand.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,24 @@ namespace WebSearchShortcut.Commands;
77

88
internal sealed partial class SearchWebCommand : InvokableCommand
99
{
10+
private readonly string _query;
11+
private readonly WebSearchShortcutDataEntry _shortcut;
12+
private readonly BrowserExecutionInfo _browserInfo;
1013
// private readonly SettingsManager _settingsManager;
11-
public string Arguments { get; internal set; } = string.Empty;
12-
public WebSearchShortcutItem Item;
13-
private readonly BrowserExecutionInfo BrowserInfo;
1414

15-
internal SearchWebCommand(string arguments, WebSearchShortcutItem item)
15+
public SearchWebCommand(WebSearchShortcutDataEntry shortcut, string query)
1616
{
17-
Arguments = arguments;
18-
BrowserInfo = new BrowserExecutionInfo(item);
19-
Icon = new IconInfo("\uE721");
20-
Name = StringFormatter.Format(Resources.SearchWebCommand_Name, new() { ["engine"] = item.Name, ["query"] = arguments });
21-
Item = item;
22-
// Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png");
23-
// Name = Properties.Resources.open_in_default_browser;
17+
Name = StringFormatter.Format(Resources.SearchQuery_NameTemplate, new() { ["engine"] = shortcut.Name, ["query"] = query });
18+
Icon = Icons.Search;
19+
_query = query;
20+
_shortcut = shortcut;
21+
_browserInfo = new BrowserExecutionInfo(shortcut);
2422
// _settingsManager = settingsManager;
2523
}
2624

2725
public override CommandResult Invoke()
2826
{
29-
if (!ShellHelpers.OpenCommandInShell(BrowserInfo.Path, BrowserInfo.ArgumentsPattern, $"{WebSearchShortcutItem.GetSearchUrl(Item, Arguments)}"))
27+
if (!ShellHelpers.OpenCommandInShell(_browserInfo.Path, _browserInfo.ArgumentsPattern, WebSearchShortcutDataEntry.GetSearchUrl(_shortcut, _query)))
3028
{
3129
// TODO GH# 138 --> actually display feedback from the extension somewhere.
3230
return CommandResult.KeepOpen();

CmdPalWebSearchShortcut/WebSearchShortcut/Forms/AddShortcutForm.cs

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,18 @@ namespace WebSearchShortcut;
1010

1111
internal sealed partial class AddShortcutForm : FormContent
1212
{
13-
internal event TypedEventHandler<object, WebSearchShortcutItem>? AddedCommand;
13+
private readonly WebSearchShortcutDataEntry? _shortcut;
1414

15-
private readonly WebSearchShortcutItem? _item;
16-
17-
public AddShortcutForm(WebSearchShortcutItem? item)
15+
public AddShortcutForm(WebSearchShortcutDataEntry? shortcut)
1816
{
19-
_item = item;
20-
var name = _item?.Name ?? string.Empty;
21-
var url = _item?.Url ?? string.Empty;
22-
var suggestionProvider = _item?.SuggestionProvider ?? string.Empty;
23-
var replaceWhitespace = _item?.ReplaceWhitespace ?? string.Empty;
24-
var homePage = _item?.HomePage ?? string.Empty;
25-
var browserPath = _item?.BrowserPath ?? string.Empty;
26-
var browserArgs = _item?.BrowserArgs ?? string.Empty;
17+
_shortcut = shortcut;
18+
var name = shortcut?.Name ?? string.Empty;
19+
var url = shortcut?.Url ?? string.Empty;
20+
var suggestionProvider = shortcut?.SuggestionProvider ?? string.Empty;
21+
var replaceWhitespace = shortcut?.ReplaceWhitespace ?? string.Empty;
22+
var homePage = shortcut?.HomePage ?? string.Empty;
23+
var browserPath = shortcut?.BrowserPath ?? string.Empty;
24+
var browserArgs = shortcut?.BrowserArgs ?? string.Empty;
2725

2826
TemplateJson = $$"""
2927
{
@@ -59,10 +57,10 @@ public AddShortcutForm(WebSearchShortcutItem? item)
5957
"title": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProviderNone, AppJsonSerializerContext.Default.String)}},
6058
"value": ""
6159
},
62-
{{Suggestions.SuggestionProviders.Keys.Select(k => $$"""
60+
{{SuggestionsRegistry.ProviderNames.Select(key => $$"""
6361
{
64-
"title": {{JsonSerializer.Serialize(k, AppJsonSerializerContext.Default.String)}},
65-
"value": {{JsonSerializer.Serialize(k, AppJsonSerializerContext.Default.String)}}
62+
"title": {{JsonSerializer.Serialize(key, AppJsonSerializerContext.Default.String)}},
63+
"value": {{JsonSerializer.Serialize(key, AppJsonSerializerContext.Default.String)}}
6664
}
6765
""").Aggregate((a, b) => a + "," + b)}}
6866
],
@@ -139,33 +137,23 @@ public AddShortcutForm(WebSearchShortcutItem? item)
139137
""";
140138
}
141139

142-
public override CommandResult SubmitForm(string payload)
143-
{
144-
var formInput = JsonNode.Parse(payload);
145-
if (formInput == null)
146-
{
147-
return CommandResult.GoHome();
148-
}
140+
internal event TypedEventHandler<object, WebSearchShortcutDataEntry>? AddedCommand;
149141

150-
// get the name and url out of the values
151-
var formName = formInput["name"] ?? string.Empty;
152-
var formUrl = formInput["url"] ?? string.Empty;
153-
var formSuggestionProvider = formInput["suggestionProvider"] ?? string.Empty;
154-
var formReplaceWhitespace = formInput["replaceWhitespace"] ?? string.Empty;
155-
var formHomePage = formInput["homePage"] ?? string.Empty;
156-
var formBrowserPath = formInput["browserPath"] ?? string.Empty;
157-
var formBrowserArgs = formInput["browserArgs"] ?? string.Empty;
142+
public override CommandResult SubmitForm(string inputs)
143+
{
144+
var root = JsonNode.Parse(inputs);
145+
if (root is null) return CommandResult.GoHome();
158146

159-
var updated = _item ?? new WebSearchShortcutItem();
160-
updated.Name = formName.ToString();
161-
updated.Url = formUrl.ToString();
162-
updated.SuggestionProvider = formSuggestionProvider.ToString();
163-
updated.ReplaceWhitespace = formReplaceWhitespace.ToString();
164-
updated.HomePage = formHomePage.ToString();
165-
updated.BrowserPath = formBrowserPath.ToString();
166-
updated.BrowserArgs = formBrowserArgs.ToString();
147+
var shortcut = _shortcut ?? new WebSearchShortcutDataEntry();
148+
shortcut.Name = root["name"]?.GetValue<string>() ?? string.Empty;
149+
shortcut.Url = root["url"]?.GetValue<string>() ?? string.Empty;
150+
shortcut.SuggestionProvider = root["suggestionProvider"]?.GetValue<string>() ?? string.Empty;
151+
shortcut.ReplaceWhitespace = root["replaceWhitespace"]?.GetValue<string>() ?? string.Empty;
152+
shortcut.HomePage = root["homePage"]?.GetValue<string>() ?? string.Empty;
153+
shortcut.BrowserPath = root["browserPath"]?.GetValue<string>() ?? string.Empty;
154+
shortcut.BrowserArgs = root["browserArgs"]?.GetValue<string>() ?? string.Empty;
167155

168-
AddedCommand?.Invoke(this, updated);
156+
AddedCommand?.Invoke(this, shortcut);
169157
return CommandResult.GoHome();
170158
}
171159
}

CmdPalWebSearchShortcut/WebSearchShortcut/Helpers/HomePageLauncher.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

CmdPalWebSearchShortcut/WebSearchShortcut/Helpers/JsonPrettyFormatter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace WebSearchShortcut.Helpers;
88

9-
internal static class JsonPrettyFormatter
9+
public static class JsonPrettyFormatter
1010
{
1111
private static readonly JsonWriterOptions PrettyWriterOptions = new()
1212
{
@@ -18,11 +18,15 @@ internal static class JsonPrettyFormatter
1818
public static string ToPrettyJson<T>(T obj, JsonTypeInfo<T> typeInfo)
1919
{
2020
byte[] utf8Json = JsonSerializer.SerializeToUtf8Bytes(obj, typeInfo);
21+
2122
using JsonDocument doc = JsonDocument.Parse(utf8Json);
23+
2224
using var output = new MemoryStream();
2325
using var writer = new Utf8JsonWriter(output, PrettyWriterOptions);
26+
2427
doc.RootElement.WriteTo(writer);
2528
writer.Flush();
29+
2630
return Encoding.UTF8.GetString(output.ToArray());
2731
}
2832
}

CmdPalWebSearchShortcut/WebSearchShortcut/JSONContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace WebSearchShortcut;
44

55
[JsonSourceGenerationOptions(IncludeFields = true)]
66
[JsonSerializable(typeof(Storage))]
7-
[JsonSerializable(typeof(WebSearchShortcutItem))]
7+
[JsonSerializable(typeof(WebSearchShortcutDataEntry))]
88
internal partial class AppJsonSerializerContext : JsonSerializerContext
99
{
1010
}

0 commit comments

Comments
 (0)