Skip to content

Commit

Permalink
MAIN: Update lists for better dynamic lists, pagination, async (#150)
Browse files Browse the repository at this point in the history
Originally in #142 and #144, but github didn't automatically change the base branch 😨 

----- 

As discussed in #77. 

Biggest change is that `IDynamicListPage` doesn't have `GetItems(String query)` anymore. Instead, the host will call the `SearchText` setter, and the list can raise `ItemsChanged` to let the host know to call `GetItems` again

See src/modules/cmdpal/Exts/EverythingExtension/Pages/EverythingExtensionPage.cs for an example of how to update dynamic extensions. 

Closes #131 
Closes #77 

----

* I put the sample pages into a single top-level command, so deploying that extension didn't add 5 top-level commands to your palette
* I tightened up some of the phrasing for the samples, and the builtins, to be less repetitive
* I added a few icons
* I made the markdown sample longer (and work more reliably)
* and also thank you Hawker for auto-format on save, you the man
  • Loading branch information
zadjii-msft authored Nov 12, 2024
1 parent b96ab5e commit a41e7e7
Show file tree
Hide file tree
Showing 31 changed files with 605 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
Expand Down Expand Up @@ -30,10 +31,14 @@ public EverythingExtensionPage()
Everything_SetMax(20);
}

public override IListItem[] GetItems(string query)
public override void UpdateSearchText(string oldSearch, string newSearch)
{
Everything_SetSearchW(query);
Everything_SetSearchW(SearchText);
RaiseItemsChanged(0);
}

public override IListItem[] GetItems()
{
if (!Everything_QueryW(true))
{
// Throwing an exception would make sense, however,
Expand Down
39 changes: 33 additions & 6 deletions src/modules/cmdpal/Exts/MastodonExtension/MastodonExtensionPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,34 @@ internal sealed partial class MastodonExtensionPage : ListPage
internal static readonly HttpClient Client = new();
internal static readonly JsonSerializerOptions Options = new() { PropertyNameCaseInsensitive = true };

private readonly List<MastodonStatus> _posts = new();

public MastodonExtensionPage()
{
Icon = new("https://mastodon.social/packs/media/icons/android-chrome-36x36-4c61fdb42936428af85afdbf8c6a45a8.png");
Name = "Mastodon";
ShowDetails = true;
HasMore = true;
}

public override IListItem[] GetItems()
{
var postsAsync = FetchExplorePage();
postsAsync.ConfigureAwait(false);
var posts = postsAsync.Result;
return posts
if (_posts.Count == 0)
{
var postsAsync = FetchExplorePage();
postsAsync.ConfigureAwait(false);
var posts = postsAsync.Result;
this._posts.AddRange(posts);
}

return _posts
.Select(p => new ListItem(new MastodonPostPage(p))
{
Title = p.Account.DisplayName, // p.ContentAsPlainText(),
Subtitle = $"@{p.Account.Username}",
Icon = new(p.Account.Avatar),

// *
Tags = [
new Tag()
{
Expand All @@ -53,7 +63,7 @@ public override IListItem[] GetItems()
Icon = new("\ue8ee"), // RepeatAll
Text = p.Boosts.ToString(CultureInfo.CurrentCulture),
},
],
], // */
Details = new Details()
{
// It was a cool idea to have a single image as the HeroImage, but the scaling is terrible
Expand All @@ -67,14 +77,31 @@ public override IListItem[] GetItems()
.ToArray();
}

public override void LoadMore()
{
var postsAsync = FetchExplorePage(20, this._posts.Count);
postsAsync.ContinueWith((res) =>
{
var posts = postsAsync.Result;
this._posts.AddRange(posts);
this.RaiseItemsChanged(this._posts.Count);
}).ConfigureAwait(false);
}

public async Task<List<MastodonStatus>> FetchExplorePage()
{
return await FetchExplorePage(20, 0);
}

public async Task<List<MastodonStatus>> FetchExplorePage(int limit, int offset)
{
var statuses = new List<MastodonStatus>();

try
{
// Make a GET request to the Mastodon trends API endpoint
HttpResponseMessage response = await Client.GetAsync("https://mastodon.social/api/v1/trends/statuses");
HttpResponseMessage response = await Client
.GetAsync($"https://mastodon.social/api/v1/trends/statuses?limit={limit}&offset={offset}");
response.EnsureSuccessStatusCode();

// Read and deserialize the response JSON into a list of MastodonStatus objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,12 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CmdPal.Ext.Registry.Classes;
using Microsoft.CmdPal.Ext.Registry.Helpers;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Microsoft.UI.Windowing;

namespace Microsoft.CmdPal.Ext.Registry;

Expand All @@ -27,7 +18,7 @@ internal sealed partial class RegistryListPage : DynamicListPage

public RegistryListPage()
{
Icon = new(string.Empty);
Icon = new("\uE74C"); // OEM
Name = "Windows Registry";
_defaultIconPath = "Images/reg.light.png";
}
Expand All @@ -54,12 +45,9 @@ public List<ListItem> Query(string query)

// when only one sub-key was found and a user search for values ("\\")
// show the filtered list of values of one sub-key
if (searchForValueName && list.Count == 1)
{
return ResultHelper.GetValuesFromKey(list.First().Key, _defaultIconPath, queryValueName);
}

return ResultHelper.GetResultList(list, _defaultIconPath);
return searchForValueName && list.Count == 1
? ResultHelper.GetValuesFromKey(list.First().Key, _defaultIconPath, queryValueName)
: ResultHelper.GetResultList(list, _defaultIconPath);
}
else if (baseKeyList.Count() > 1)
{
Expand All @@ -70,8 +58,13 @@ public List<ListItem> Query(string query)
return new List<ListItem>();
}

public override IListItem[] GetItems(string query)
public override void UpdateSearchText(string oldSearch, string newSearch)
{
RaiseItemsChanged(0);
}

public override IListItem[] GetItems()
{
return Query(query).ToArray();
return Query(SearchText).ToArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;

Expand All @@ -20,8 +19,8 @@ public override IListItem[] TopLevelCommands()
return [
new ListItem(new RegistryListPage())
{
Title = "Search the Windows Registry",
Subtitle = "Navigates inside the Windows registry",
Title = "Registry",
Subtitle = "Navigate the Windows registry",
}
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ public ServicesListPage()
Name = "Windows Services";
}

public override IListItem[] GetItems(string query)
public override void UpdateSearchText(string oldSearch, string newSearch)
{
ListItem[] items = ServiceHelper.Search(query).ToArray();
RaiseItemsChanged(0);
}

public override IListItem[] GetItems()
{
ListItem[] items = ServiceHelper.Search(SearchText).ToArray();

return items;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;

Expand All @@ -20,8 +19,8 @@ public override IListItem[] TopLevelCommands()
return [
new ListItem(new ServicesListPage())
{
Title = "Search Windows Services",
Subtitle = "Quickly manage all Windows Services",
Title = "Windows Services",
Subtitle = "Manage Windows Services",
}
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,11 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Microsoft.UI.Windowing;

namespace Microsoft.CmdPal.Ext.WindowsSettings;

Expand All @@ -28,7 +18,7 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage

public WindowsSettingsListPage(Classes.WindowsSettings windowsSettings)
{
Icon = new(string.Empty);
Icon = new("\uE713"); // Settings
Name = "Windows Settings";
_defaultIconPath = "Images/WindowsSettings.light.png";
_windowsSettings = windowsSettings;
Expand Down Expand Up @@ -92,18 +82,18 @@ bool Predicate(WindowsSetting found)
}

// Search by key char '>' for app name and settings path
if (query.Contains('>'))
{
return ResultHelper.FilterBySettingsPath(found, query);
}

return false;
return query.Contains('>') ? ResultHelper.FilterBySettingsPath(found, query) : false;
}
}

public override IListItem[] GetItems(string query)
public override void UpdateSearchText(string oldSearch, string newSearch)
{
RaiseItemsChanged(0);
}

public override IListItem[] GetItems()
{
ListItem[] items = Query(query).ToArray();
var items = Query(SearchText).ToArray();

return items;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
Expand All @@ -20,13 +18,13 @@ public partial class WindowsSettingsCommandsProvider : CommandProvider

public WindowsSettingsCommandsProvider()
{
DisplayName = $"Windows Services";
DisplayName = $"Windows Settings";

_windowsSettings = JsonSettingsListHelper.ReadAllPossibleSettings();
_searchSettingsListItem = new ListItem(new WindowsSettingsListPage(_windowsSettings))
{
Title = "Search Windows Settings",
Subtitle = "Quickly navigate to specific Windows settings",
Title = "Windows Settings",
Subtitle = "Navigate to specific Windows settings",
};

UnsupportedSettingsHelper.FilterByBuild(_windowsSettings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,27 @@ internal sealed partial class SampleDynamicListPage : DynamicListPage
public SampleDynamicListPage()
{
Icon = new(string.Empty);
Name = "SSH Keychain";
Name = "Dynamic List";
}

public override IListItem[] GetItems(string query)
public override void UpdateSearchText(string oldSearch, string newSearch)
{
return [
new ListItem(new NoOpCommand()) { Title = string.IsNullOrEmpty(query) ? "dynamic item" : query, Subtitle = "Notice how the title changes for this list item when you type in the filter box" },
new ListItem(new NoOpCommand()) { Title = "TODO: Implement your extension here" },
new ListItem(new NoOpCommand()) { Title = "This one has a subtitle too", Subtitle = "Example Subtitle" },
new ListItem(new NoOpCommand())
{
Title = "This one has a tag too",
Subtitle = "the one with a tag",
Tags = [new Tag()
{
Text = "Sample Tag",
}
],
}
];
RaiseItemsChanged(newSearch.Length);
}

public override IListItem[] GetItems()
{
var items = SearchText.ToCharArray().Select(ch => new ListItem(new NoOpCommand()) { Title = ch.ToString() }).ToArray();
if (items.Length == 0)
{
items = [new ListItem(new NoOpCommand()) { Title = "Start typing in the search box" }];
}

if (items.Length > 0)
{
items[0].Subtitle = "Notice how the number of items changes for this page when you type in the filter box";
}

return items;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,8 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Microsoft.UI.Windowing;

namespace SamplePagesExtension;

Expand Down
Loading

0 comments on commit a41e7e7

Please sign in to comment.