mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-12 15:26:28 +01:00
Merge pull request #18 from zadjii-msft/dev/crutkas/hackerNews
Dev/crutkas/hacker news
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.Diagnostics;
|
||||
using Microsoft.Windows.CommandPalette.Extensions.Helpers;
|
||||
|
||||
namespace HackerNewsExtension;
|
||||
|
||||
internal sealed class CommentAction : InvokableCommand
|
||||
{
|
||||
private readonly NewsPost _post;
|
||||
|
||||
internal CommentAction(NewsPost post)
|
||||
{
|
||||
_post = post;
|
||||
Name = "Open comments";
|
||||
Icon = new("\ue8f2"); // chat bubbles
|
||||
}
|
||||
|
||||
public override ActionResult Invoke()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(_post.CommentsLink) { UseShellExecute = true });
|
||||
return ActionResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -3,124 +3,18 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using ABI.System;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.Windows.CommandPalette.Extensions;
|
||||
using Microsoft.Windows.CommandPalette.Extensions.Helpers;
|
||||
using Windows.Foundation;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace HackerNewsExtension;
|
||||
|
||||
internal sealed class NewsPost
|
||||
{
|
||||
internal string Title { get; init; } = "";
|
||||
internal string Link { get; init; } = "";
|
||||
internal string CommentsLink { get; init; } = "";
|
||||
internal string Poster { get; init; } = "";
|
||||
}
|
||||
internal sealed class LinkAction : InvokableCommand {
|
||||
private readonly NewsPost post;
|
||||
internal LinkAction(NewsPost post)
|
||||
{
|
||||
this.post = post;
|
||||
this.Name = "Open link";
|
||||
this.Icon = new("\uE8A7");
|
||||
}
|
||||
public override ActionResult Invoke()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(post.Link) { UseShellExecute = true });
|
||||
return ActionResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
internal sealed class CommentAction : InvokableCommand
|
||||
{
|
||||
private readonly NewsPost post;
|
||||
internal CommentAction(NewsPost post)
|
||||
{
|
||||
this.post = post;
|
||||
this.Name = "Open comments";
|
||||
this.Icon = new("\ue8f2"); // chat bubbles
|
||||
}
|
||||
public override ActionResult Invoke()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(post.CommentsLink) { UseShellExecute = true });
|
||||
return ActionResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class HackerNewsPage : ListPage {
|
||||
|
||||
public HackerNewsPage()
|
||||
{
|
||||
this.Icon = new("https://news.ycombinator.com/favicon.ico");
|
||||
this.Name = "Hacker News";
|
||||
}
|
||||
|
||||
private static async Task<List<NewsPost>> GetHackerNewsTopPosts()
|
||||
{
|
||||
var posts = new List<NewsPost>();
|
||||
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
var response = await client.GetStringAsync("https://news.ycombinator.com/rss");
|
||||
var xdoc = XDocument.Parse(response);
|
||||
var x = xdoc.Descendants("item").First();
|
||||
posts = xdoc.Descendants("item")
|
||||
.Take(20)
|
||||
.Select(item => new NewsPost()
|
||||
{
|
||||
Title = item.Element("title")?.Value ?? "",
|
||||
Link = item.Element("link")?.Value ?? "",
|
||||
CommentsLink = item.Element("comments")?.Value ?? "",
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return posts;
|
||||
}
|
||||
|
||||
public override ISection[] GetItems()
|
||||
{
|
||||
var t = DoGetItems();
|
||||
t.ConfigureAwait(false);
|
||||
return t.Result;
|
||||
}
|
||||
private async Task<ISection[]> DoGetItems()
|
||||
{
|
||||
List<NewsPost> items = await GetHackerNewsTopPosts();
|
||||
this.Loading = false;
|
||||
var s = new ListSection()
|
||||
{
|
||||
Title = "Posts",
|
||||
Items = items.Select((post) => new ListItem(new LinkAction(post))
|
||||
{
|
||||
Title = post.Title,
|
||||
Subtitle = post.Link,
|
||||
MoreCommands = [
|
||||
new CommandContextItem(new CommentAction(post))
|
||||
]
|
||||
}).ToArray()
|
||||
};
|
||||
return [ s ] ;
|
||||
}
|
||||
}
|
||||
|
||||
public class HackerNewsActionsProvider : ICommandProvider
|
||||
{
|
||||
public string DisplayName => $"Hacker News Commands";
|
||||
public IconDataType Icon => new("");
|
||||
|
||||
private readonly IListItem[] _Actions = [
|
||||
public IconDataType Icon => new(string.Empty);
|
||||
|
||||
private readonly IListItem[] _actions = [
|
||||
new ListItem(new HackerNewsPage()),
|
||||
];
|
||||
|
||||
@@ -128,9 +22,8 @@ public class HackerNewsActionsProvider : ICommandProvider
|
||||
public void Dispose() => throw new NotImplementedException();
|
||||
#pragma warning restore CA1816 // Dispose methods should call SuppressFinalize
|
||||
|
||||
|
||||
public IListItem[] TopLevelCommands()
|
||||
{
|
||||
return _Actions;
|
||||
return _actions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
|
||||
<UseWinUI>false</UseWinUI>
|
||||
<EnableMsixTooling>true</EnableMsixTooling>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Windows.CommandPalette.Extensions;
|
||||
using Microsoft.Windows.CommandPalette.Extensions.Helpers;
|
||||
|
||||
namespace HackerNewsExtension;
|
||||
|
||||
internal sealed class HackerNewsPage : ListPage
|
||||
{
|
||||
public HackerNewsPage()
|
||||
{
|
||||
Icon = new("https://news.ycombinator.com/favicon.ico");
|
||||
Name = "Hacker News";
|
||||
}
|
||||
|
||||
private static async Task<List<NewsPost>> GetHackerNewsTopPosts()
|
||||
{
|
||||
var posts = new List<NewsPost>();
|
||||
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
var response = await client.GetStringAsync("https://news.ycombinator.com/rss");
|
||||
var xdoc = XDocument.Parse(response);
|
||||
var x = xdoc.Descendants("item").First();
|
||||
posts = xdoc.Descendants("item")
|
||||
.Take(20)
|
||||
.Select(item => new NewsPost()
|
||||
{
|
||||
Title = item.Element("title")?.Value ?? string.Empty,
|
||||
Link = item.Element("link")?.Value ?? string.Empty,
|
||||
CommentsLink = item.Element("comments")?.Value ?? string.Empty,
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return posts;
|
||||
}
|
||||
|
||||
public override ISection[] GetItems()
|
||||
{
|
||||
var t = DoGetItems();
|
||||
t.ConfigureAwait(false);
|
||||
return t.Result;
|
||||
}
|
||||
|
||||
private async Task<ISection[]> DoGetItems()
|
||||
{
|
||||
List<NewsPost> items = await GetHackerNewsTopPosts();
|
||||
this.Loading = false;
|
||||
var s = new ListSection()
|
||||
{
|
||||
Title = "Posts",
|
||||
Items = items.Select((post) => new ListItem(new LinkAction(post))
|
||||
{
|
||||
Title = post.Title,
|
||||
Subtitle = post.Link,
|
||||
MoreCommands = [new CommandContextItem(new CommentAction(post))],
|
||||
}).ToArray(),
|
||||
};
|
||||
return [s];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.Diagnostics;
|
||||
using Microsoft.Windows.CommandPalette.Extensions.Helpers;
|
||||
|
||||
namespace HackerNewsExtension;
|
||||
|
||||
internal sealed class LinkAction : InvokableCommand
|
||||
{
|
||||
private readonly NewsPost _post;
|
||||
|
||||
internal LinkAction(NewsPost post)
|
||||
{
|
||||
this._post = post;
|
||||
this.Name = "Open link";
|
||||
this.Icon = new("\uE8A7");
|
||||
}
|
||||
|
||||
public override ActionResult Invoke()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(_post.Link) { UseShellExecute = true });
|
||||
return ActionResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace HackerNewsExtension;
|
||||
|
||||
public sealed class NewsPost
|
||||
{
|
||||
public string Title { get; init; } = string.Empty;
|
||||
|
||||
public string Link { get; init; } = string.Empty;
|
||||
|
||||
public string CommentsLink { get; init; } = string.Empty;
|
||||
|
||||
public string Poster { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -15,16 +15,16 @@ public static class RuntimeHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO! for whatever reason, when I ported this into the PT
|
||||
// TODO: for whatever reason, when I ported this into the PT
|
||||
// codebase, this no longer compiled. We're only ever using it for
|
||||
// the hacked up settings and ignoring it anyways, so I'm leaving
|
||||
// it commented out for now.
|
||||
//
|
||||
// it commented out for now.
|
||||
//
|
||||
// See also:
|
||||
// * https://github.com/microsoft/win32metadata/commit/6fee67ba73bfe1b126ce524f7de8d367f0317715
|
||||
// * https://github.com/microsoft/win32metadata/issues/1311
|
||||
//uint length = 0;
|
||||
//return PInvoke.GetCurrentPackageFullName(ref length, null) != WIN32_ERROR.APPMODEL_ERROR_NO_PACKAGE;
|
||||
// uint length = 0;
|
||||
// return PInvoke.GetCurrentPackageFullName(ref length, null) != WIN32_ERROR.APPMODEL_ERROR_NO_PACKAGE;
|
||||
#pragma warning disable IDE0025 // Use expression body for property
|
||||
return true;
|
||||
#pragma warning restore IDE0025 // Use expression body for property
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<RootNamespace>Microsoft.CmdPal.Common</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace Microsoft.CmdPal.Common.Services;
|
||||
|
||||
public class FileService : IFileService
|
||||
{
|
||||
static readonly Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
||||
|
||||
private static readonly Encoding _encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
|
||||
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
public T Read<T>(string folderPath, string fileName)
|
||||
@@ -36,7 +35,7 @@ public class FileService : IFileService
|
||||
}
|
||||
|
||||
var fileContent = JsonSerializer.Serialize(content);
|
||||
File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, encoding);
|
||||
File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, _encoding);
|
||||
}
|
||||
|
||||
public void Delete(string folderPath, string fileName)
|
||||
|
||||
@@ -13,7 +13,6 @@ public interface IExtensionService
|
||||
Task<IEnumerable<IExtensionWrapper>> GetInstalledExtensionsAsync(bool includeDisabledExtensions = false);
|
||||
|
||||
// Task<IEnumerable<string>> GetInstalledHomeWidgetPackageFamilyNamesAsync(bool includeDisabledExtensions = false);
|
||||
|
||||
Task<IEnumerable<IExtensionWrapper>> GetInstalledExtensionsAsync(Microsoft.Windows.CommandPalette.Extensions.ProviderType providerType, bool includeDisabledExtensions = false);
|
||||
|
||||
IExtensionWrapper? GetInstalledExtension(string extensionUniqueId);
|
||||
@@ -32,5 +31,5 @@ public interface IExtensionService
|
||||
///// </summary>
|
||||
///// <param name="extension">The out of proc extension object</param>
|
||||
///// <returns>True only if the extension was disabled. False otherwise.</returns>
|
||||
//public Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension);
|
||||
// public Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension);
|
||||
}
|
||||
|
||||
@@ -28,15 +28,14 @@ public class LocalSettingsService : ILocalSettingsService
|
||||
private readonly string _applicationDataFolder;
|
||||
private readonly string _localSettingsFile;
|
||||
|
||||
private Dictionary<string, object> _settings;
|
||||
|
||||
private bool _isInitialized;
|
||||
|
||||
private readonly bool _isMsix;
|
||||
|
||||
private Dictionary<string, object> _settings;
|
||||
private bool _isInitialized;
|
||||
|
||||
public LocalSettingsService(IFileService fileService, IOptions<LocalSettingsOptions> options)
|
||||
{
|
||||
_isMsix = false; // RuntimeHelper.IsMSIX;
|
||||
_isMsix = false; // RuntimeHelper.IsMSIX;
|
||||
|
||||
_fileService = fileService;
|
||||
_options = options.Value;
|
||||
|
||||
Reference in New Issue
Block a user