Skip to content

Commit 3bb92e2

Browse files
committed
refactor(ui): centralize visible text/icons at Item layer
1 parent fe859dc commit 3bb92e2

12 files changed

Lines changed: 451 additions & 293 deletions

CmdPalWebSearchShortcut/WebSearchShortcut/Commands/OpenHomePageCommand.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using Microsoft.CommandPalette.Extensions.Toolkit;
22
using WebSearchShortcut.Browsers;
3-
using WebSearchShortcut.Helpers;
4-
using WebSearchShortcut.Properties;
53

64
namespace WebSearchShortcut.Commands;
75

@@ -12,8 +10,8 @@ internal sealed partial class OpenHomePageCommand : InvokableCommand
1210

1311
internal OpenHomePageCommand(WebSearchShortcutDataEntry shortcut)
1412
{
15-
Name = StringFormatter.Format(Resources.OpenHomePage_NameTemplate, new() { ["engine"] = shortcut.Name });
16-
Icon = Icons.Search;
13+
Name = $"[UNBOUND] {nameof(OpenHomePageCommand)}.{nameof(Name)} required - shortcut='{shortcut.Name}'";
14+
1715
_shortcut = shortcut;
1816
_browserInfo = new BrowserExecutionInfo(shortcut);
1917
}

CmdPalWebSearchShortcut/WebSearchShortcut/Commands/SearchWebCommand.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using Microsoft.CommandPalette.Extensions.Toolkit;
22
using WebSearchShortcut.Browsers;
3-
using WebSearchShortcut.Helpers;
4-
using WebSearchShortcut.Properties;
53

64
namespace WebSearchShortcut.Commands;
75

@@ -14,8 +12,8 @@ internal sealed partial class SearchWebCommand : InvokableCommand
1412

1513
public SearchWebCommand(WebSearchShortcutDataEntry shortcut, string query)
1614
{
17-
Name = StringFormatter.Format(Resources.SearchQuery_NameTemplate, new() { ["engine"] = shortcut.Name, ["query"] = query });
18-
Icon = Icons.Search;
15+
Name = $"[UNBOUND] {nameof(SearchWebCommand)}.{nameof(Name)} required - shortcut='{shortcut.Name}', query='{query}'";
16+
1917
_query = query;
2018
_shortcut = shortcut;
2119
_browserInfo = new BrowserExecutionInfo(shortcut);

CmdPalWebSearchShortcut/WebSearchShortcut/Forms/AddShortcutForm.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,29 @@ public AddShortcutForm(WebSearchShortcutDataEntry? shortcut)
3232
{
3333
"id": "name",
3434
"type": "Input.Text",
35-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_NameLabel, AppJsonSerializerContext.Default.String)}},
35+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Name_Label, AppJsonSerializerContext.Default.String)}},
3636
"value": {{JsonSerializer.Serialize(name, AppJsonSerializerContext.Default.String)}},
3737
"isRequired": true,
38-
"errorMessage": {{JsonSerializer.Serialize(Resources.AddShortcutForm_NameErrorMessage, AppJsonSerializerContext.Default.String)}}
38+
"errorMessage": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Name_ErrorMessage, AppJsonSerializerContext.Default.String)}}
3939
},
4040
{
4141
"id": "url",
4242
"type": "Input.Text",
4343
"style": "Url",
44-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_UrlLabel, AppJsonSerializerContext.Default.String)}},
45-
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_UrlPlaceholder, AppJsonSerializerContext.Default.String)}},
44+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Url_Label, AppJsonSerializerContext.Default.String)}},
45+
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Url_Placeholder, AppJsonSerializerContext.Default.String)}},
4646
"value": {{JsonSerializer.Serialize(url, AppJsonSerializerContext.Default.String)}},
4747
"isRequired": true,
48-
"errorMessage": {{JsonSerializer.Serialize(Resources.AddShortcutForm_UrlErrorMessage, AppJsonSerializerContext.Default.String)}}
48+
"errorMessage": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Url_ErrorMessage, AppJsonSerializerContext.Default.String)}}
4949
},
5050
{
5151
"id": "suggestionProvider",
5252
"type": "Input.ChoiceSet",
53-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProviderLabel, AppJsonSerializerContext.Default.String)}},
54-
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProviderPlaceholder, AppJsonSerializerContext.Default.String)}},
53+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProvider_Label, AppJsonSerializerContext.Default.String)}},
54+
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProvider_Placeholder, AppJsonSerializerContext.Default.String)}},
5555
"choices": [
5656
{
57-
"title": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProviderNone, AppJsonSerializerContext.Default.String)}},
57+
"title": {{JsonSerializer.Serialize(Resources.AddShortcutForm_SuggestionProvider_None, AppJsonSerializerContext.Default.String)}},
5858
"value": ""
5959
},
6060
{{SuggestionsRegistry.ProviderNames.Select(key => $$"""
@@ -71,28 +71,28 @@ public AddShortcutForm(WebSearchShortcutDataEntry? shortcut)
7171
"type": "Input.Text",
7272
"style": "text",
7373
"id": "replaceWhitespace",
74-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_ReplaceWhitespaceLabel, AppJsonSerializerContext.Default.String)}},
75-
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_ReplaceWhitespacePlaceholder, AppJsonSerializerContext.Default.String)}},
74+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_ReplaceWhitespace_Label, AppJsonSerializerContext.Default.String)}},
75+
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_ReplaceWhitespace_Placeholder, AppJsonSerializerContext.Default.String)}},
7676
"value": {{JsonSerializer.Serialize(replaceWhitespace, AppJsonSerializerContext.Default.String)}},
7777
"errorMessage": "// Just for space between items"
7878
},
7979
{
8080
"type": "Input.Text",
8181
"style": "text",
8282
"id": "homePage",
83-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_HomepageLabel, AppJsonSerializerContext.Default.String)}},
84-
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_HomepagePlaceholder, AppJsonSerializerContext.Default.String)}},
83+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Homepage_Label, AppJsonSerializerContext.Default.String)}},
84+
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_Homepage_Placeholder, AppJsonSerializerContext.Default.String)}},
8585
"value": {{JsonSerializer.Serialize(homePage, AppJsonSerializerContext.Default.String)}},
8686
"errorMessage": "// Just for space between items"
8787
},
8888
{
8989
"id": "browserPath",
9090
"type": "Input.ChoiceSet",
91-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserPathLabel, AppJsonSerializerContext.Default.String)}},
91+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserPath_Label, AppJsonSerializerContext.Default.String)}},
9292
"placeholder": {{JsonSerializer.Serialize(browserPath, AppJsonSerializerContext.Default.String)}},
9393
"choices": [
9494
{
95-
"title": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserPathDefault, AppJsonSerializerContext.Default.String)}},
95+
"title": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserPath_Default, AppJsonSerializerContext.Default.String)}},
9696
"value": ""
9797
},
9898
{{BrowserDiscovery.GetAllInstalledBrowsers()
@@ -112,8 +112,8 @@ public AddShortcutForm(WebSearchShortcutDataEntry? shortcut)
112112
"id": "browserArgs",
113113
"type": "Input.Text",
114114
"style": "text",
115-
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserArgsLabel, AppJsonSerializerContext.Default.String)}},
116-
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserArgsPlaceholder, AppJsonSerializerContext.Default.String)}},
115+
"label": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserArgs_Label, AppJsonSerializerContext.Default.String)}},
116+
"placeholder": {{JsonSerializer.Serialize(Resources.AddShortcutForm_BrowserArgs_Placeholder, AppJsonSerializerContext.Default.String)}},
117117
"value": {{JsonSerializer.Serialize(browserArgs, AppJsonSerializerContext.Default.String)}},
118118
"errorMessage": "// Just for space between items"
119119
}

CmdPalWebSearchShortcut/WebSearchShortcut/Pages/AddShortcutPage.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@ internal sealed partial class AddShortcutPage : ContentPage
1111

1212
public AddShortcutPage(WebSearchShortcutDataEntry? shortcut)
1313
{
14-
var name = shortcut?.Name ?? string.Empty;
15-
var url = shortcut?.Url ?? string.Empty;
16-
var isAdd = string.IsNullOrEmpty(name) && string.IsNullOrEmpty(url);
17-
18-
_addShortcutForm = new AddShortcutForm(shortcut);
14+
bool isAdd = shortcut is null;
1915

2016
Id = "WebSearchShortcut.AddShortcut";
21-
Icon = IconHelpers.FromRelativePath("Assets\\SearchAdd.png");
22-
Title = isAdd ? Resources.AddShortcut_AddTitle : Resources.SearchShortcut_EditTitle;
23-
Name = isAdd ? Resources.AddShortcut_AddName : Resources.SearchShortcut_EditName;
17+
Title = isAdd ? Resources.AddShortcutPage_Title_Add : Resources.AddShortcutPage_Title_Edit;
18+
Name = $"[UNBOUND] {nameof(AddShortcutPage)}.{nameof(Name)} required - shortcut={(shortcut is null ? "null" : $"'{shortcut.Name}'")}";
19+
Icon = isAdd ? IconHelpers.FromRelativePath("Assets\\SearchAdd.png") : Icons.Edit;
20+
21+
_addShortcutForm = new AddShortcutForm(shortcut);
2422
}
2523

2624
internal event TypedEventHandler<object, WebSearchShortcutDataEntry>? AddedCommand

CmdPalWebSearchShortcut/WebSearchShortcut/Pages/SearchWebPage.cs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ namespace WebSearchShortcut;
1414
internal sealed partial class SearchWebPage : DynamicListPage
1515
{
1616
private readonly WebSearchShortcutDataEntry _shortcut;
17-
private readonly IListItem _openHomePageItem;
17+
18+
private readonly IListItem _openHomepageListItem;
19+
private readonly IContextItem _openHomepageContextItem;
20+
1821
private IListItem[] _items = [];
1922
private IListItem[] _suggestionItems = [];
23+
2024
private int _lastUpdateSearchTextEpoch;
2125
private readonly Lock _swapSuggestionsCancellationSourceLock = new();
2226
private readonly Lock _renderLock = new();
@@ -25,17 +29,29 @@ internal sealed partial class SearchWebPage : DynamicListPage
2529

2630
public SearchWebPage(WebSearchShortcutDataEntry shortcut)
2731
{
28-
_shortcut = shortcut;
29-
3032
Id = shortcut.Id;
31-
Name = shortcut.Name;
33+
Title = StringFormatter.Format(Resources.SearchWebPage_TitleTemplate, new() { ["shortcut"] = shortcut.Name });
34+
Name = $"[UNBOUND] {nameof(SearchWebPage)}.{nameof(Name)} required - shortcut='{shortcut.Name}'";
3235
Icon = IconService.GetIconInfo(shortcut);
33-
_openHomePageItem = new ListItem(new OpenHomePageCommand(shortcut))
36+
37+
_shortcut = shortcut;
38+
39+
var openHomepagecommand = new OpenHomePageCommand(shortcut)
40+
{
41+
Name = StringFormatter.Format(Resources.OpenHomepageItem_NameTemplate, new() { ["shortcut"] = shortcut.Name })
42+
};
43+
_openHomepageListItem = new ListItem(openHomepagecommand)
3444
{
35-
Title = StringFormatter.Format(Resources.OpenHomePage_TitleTemplate, new() { ["engine"] = Name })
45+
Title = StringFormatter.Format(Resources.OpenHomepageItem_TitleTemplate, new() { ["shortcut"] = shortcut.Name }),
46+
Icon = Icons.Home
47+
};
48+
_openHomepageContextItem = new CommandContextItem(openHomepagecommand)
49+
{
50+
Title = StringFormatter.Format(Resources.OpenHomepageItem_TitleTemplate, new() { ["shortcut"] = shortcut.Name }),
51+
Icon = Icons.Home
3652
};
3753

38-
_items = [_openHomePageItem];
54+
_items = [_openHomepageListItem];
3955
}
4056

4157
public override IListItem[] GetItems() => Volatile.Read(ref _items);
@@ -55,6 +71,7 @@ public override async void UpdateSearchText(string oldSearch, string newSearch)
5571
if (currentEpoch != Volatile.Read(ref _lastUpdateSearchTextEpoch))
5672
{
5773
currentCancellationSource?.Dispose();
74+
5875
return;
5976
}
6077

@@ -73,7 +90,7 @@ public override async void UpdateSearchText(string oldSearch, string newSearch)
7390
{
7491
UpdateSuggestionItems([], currentEpoch);
7592

76-
RenderItems([_openHomePageItem], currentEpoch);
93+
RenderItems([_openHomepageListItem], currentEpoch);
7794

7895
return;
7996
}
@@ -108,7 +125,8 @@ public override async void UpdateSearchText(string oldSearch, string newSearch)
108125
currentCancellationSource!.Dispose();
109126
}
110127

111-
if (currentEpoch != Volatile.Read(ref _lastUpdateSearchTextEpoch)) return;
128+
if (currentEpoch != Volatile.Read(ref _lastUpdateSearchTextEpoch))
129+
return;
112130

113131
UpdateSuggestionItems(suggestionItems, currentEpoch);
114132

@@ -149,11 +167,17 @@ private ListItem[] BuildPrimaryItems(string searchText)
149167
{
150168
return
151169
[
152-
new ListItem(new SearchWebCommand(_shortcut, searchText))
170+
new ListItem(
171+
new SearchWebCommand(_shortcut, searchText)
172+
{
173+
Name = StringFormatter.Format(Resources.SearchQueryItem_NameTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = searchText }),
174+
}
175+
)
153176
{
154-
Title = searchText,
155-
Subtitle = StringFormatter.Format(Resources.SearchQuery_SubtitleTemplate, new() { ["engine"] = Name, ["query"] = searchText }),
156-
MoreCommands = [new CommandContextItem(new OpenHomePageCommand(_shortcut))]
177+
Title = StringFormatter.Format(Resources.SearchQueryItem_TitleTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = searchText }),
178+
Subtitle = StringFormatter.Format(Resources.SearchQueryItem_SubtitleTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = searchText }),
179+
Icon = Icons.Search,
180+
MoreCommands = [_openHomepageContextItem]
157181
}
158182
];
159183
}
@@ -167,12 +191,18 @@ private async Task<ListItem[]> FetchSuggestionItemsAsync(string searchText, Canc
167191

168192
return
169193
[
170-
.. suggestions.Select(suggestion => new ListItem(new SearchWebCommand(_shortcut, suggestion.Title))
194+
.. suggestions.Select(suggestion => new ListItem(
195+
new SearchWebCommand(_shortcut, suggestion.Title)
196+
{
197+
Name = StringFormatter.Format(Resources.SearchQueryItem_NameTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = suggestion.Title })
198+
}
199+
)
171200
{
172-
Title = suggestion.Title,
173-
Subtitle = suggestion.Description ?? StringFormatter.Format(Resources.SearchQuery_SubtitleTemplate, new() { ["engine"] = Name, ["query"] = suggestion.Title }),
201+
Title = StringFormatter.Format(Resources.SearchQueryItem_TitleTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = suggestion.Title }),
202+
Subtitle = suggestion.Description ?? StringFormatter.Format(Resources.SearchQueryItem_SubtitleTemplate, new() { ["shortcut"] = _shortcut.Name, ["query"] = suggestion.Title }),
203+
Icon = Icons.Search,
174204
TextToSuggest = suggestion.Title,
175-
MoreCommands = [new CommandContextItem(new OpenHomePageCommand(_shortcut))]
205+
MoreCommands = [_openHomepageContextItem]
176206
})
177207
];
178208
}

CmdPalWebSearchShortcut/WebSearchShortcut/Properties/Icons.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ namespace WebSearchShortcut.Properties;
99
/// <summary>
1010
/// Provides commonly used icons for the WebSearchShortcut application
1111
/// </summary>
12-
public static class Icons
12+
internal static class Icons
1313
{
14+
/// <summary>
15+
/// Default fallback icon for links
16+
/// </summary>
17+
public static IconInfo Link { get; } = new("🔗");
18+
1419
/// <summary>
1520
/// Edit icon (pencil)
1621
/// </summary>
@@ -22,9 +27,9 @@ public static class Icons
2227
public static IconInfo Delete { get; } = new("\uE74D");
2328

2429
/// <summary>
25-
/// Default fallback icon for links
30+
/// Homepage icon
2631
/// </summary>
27-
public static IconInfo Link { get; } = new("🔗");
32+
public static IconInfo Home { get; } = new("\uE80F");
2833

2934
/// <summary>
3035
/// Search icon

0 commit comments

Comments
 (0)