mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
savings changes for jordi to play around
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Extensions.Helpers;
|
||||
|
||||
namespace YouTubeExtension.Helper;
|
||||
|
||||
internal sealed partial class GetVideoInfoAction : InvokableCommand
|
||||
{
|
||||
private readonly YouTubeVideo _video;
|
||||
|
||||
internal GetVideoInfoAction(YouTubeVideo video)
|
||||
{
|
||||
this._video = video;
|
||||
this.Name = "See more information";
|
||||
this.Icon = new("\uE946");
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
return CommandResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Extensions.Helpers;
|
||||
|
||||
namespace YouTubeExtension.Helper;
|
||||
|
||||
internal sealed partial class OpenChannelLinkAction : InvokableCommand
|
||||
{
|
||||
private readonly YouTubeVideo _video;
|
||||
|
||||
internal OpenChannelLinkAction(YouTubeVideo video)
|
||||
{
|
||||
this._video = video;
|
||||
this.Name = "Open channel";
|
||||
this.Icon = new("\uF131");
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(_video.ChannelUrl) { UseShellExecute = true });
|
||||
return CommandResult.KeepOpen();
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,15 @@ using Microsoft.CmdPal.Extensions.Helpers;
|
||||
|
||||
namespace YouTubeExtension.Helper;
|
||||
|
||||
internal sealed partial class LinkAction : InvokableCommand
|
||||
internal sealed partial class OpenVideoLinkAction : InvokableCommand
|
||||
{
|
||||
private readonly YouTubeVideo _video;
|
||||
|
||||
internal LinkAction(YouTubeVideo video)
|
||||
internal OpenVideoLinkAction(YouTubeVideo video)
|
||||
{
|
||||
this._video = video;
|
||||
this.Name = "Open link";
|
||||
this.Icon = new("https://www.youtube.com/favicon.ico");
|
||||
this.Name = "Open video";
|
||||
this.Icon = new("\uE714");
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
@@ -21,6 +21,12 @@ public sealed class YouTubeVideo
|
||||
// The author or channel name of the video
|
||||
public string Author { get; init; } = string.Empty;
|
||||
|
||||
// The channel id (needed for the channel URL)
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
// The URL link to the channel
|
||||
public string ChannelUrl { get; set; }
|
||||
|
||||
// The URL to the thumbnail image of the video
|
||||
public string ThumbnailUrl { get; init; } = string.Empty;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ internal sealed partial class YouTubeAPIForm : Form
|
||||
"body": [
|
||||
{
|
||||
"type": "Input.Text",
|
||||
"style": "text",
|
||||
"style": "password",
|
||||
"id": "apiKey",
|
||||
"label": "API Key",
|
||||
"isRequired": true,
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed partial class YouTubeAPIPage : FormPage
|
||||
|
||||
public YouTubeAPIPage()
|
||||
{
|
||||
Name = "YouTube API";
|
||||
Name = "Edit YouTube API Key";
|
||||
Icon = new("https://www.youtube.com/favicon.ico");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.CmdPal.Extensions;
|
||||
using Microsoft.CmdPal.Extensions.Helpers;
|
||||
using YouTubeExtension.Helper;
|
||||
|
||||
namespace YouTubeExtension.Pages;
|
||||
|
||||
internal sealed partial class YouTubeChannelsPage : DynamicListPage
|
||||
{
|
||||
public YouTubeChannelsPage()
|
||||
{
|
||||
Icon = new("https://www.youtube.com/favicon.ico");
|
||||
Name = "YouTube";
|
||||
this.ShowDetails = true;
|
||||
}
|
||||
|
||||
public override ISection[] GetItems(string query)
|
||||
{
|
||||
return DoGetItems(query).GetAwaiter().GetResult(); // Fetch and await the task synchronously
|
||||
}
|
||||
|
||||
private async Task<ISection[]> DoGetItems(string query)
|
||||
{
|
||||
// Fetch YouTube videos based on the query
|
||||
List<YouTubeVideo> items = await GetYouTubeVideos(query);
|
||||
|
||||
// Create a section and populate it with the video results
|
||||
var section = new ListSection()
|
||||
{
|
||||
Title = "Search Results",
|
||||
Items = items.Select(video => new ListItem(new OpenVideoLinkAction(video))
|
||||
{
|
||||
Title = video.Title,
|
||||
Subtitle = $"{video.Author}",
|
||||
Details = new Details()
|
||||
{
|
||||
Title = video.Title,
|
||||
HeroImage = new(video.ThumbnailUrl),
|
||||
Body = $"{video.Author}",
|
||||
},
|
||||
Tags = [new Tag()
|
||||
{
|
||||
Text = video.PublishedAt.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture), // Show the date of the video post
|
||||
}
|
||||
],
|
||||
}).ToArray(),
|
||||
};
|
||||
|
||||
return new[] { section }; // Properly return an array of sections
|
||||
}
|
||||
|
||||
// Method to fetch videos from YouTube API
|
||||
private static async Task<List<YouTubeVideo>> GetYouTubeVideos(string query)
|
||||
{
|
||||
var state = File.ReadAllText(YouTubeHelper.StateJsonPath());
|
||||
var jsonState = JsonNode.Parse(state);
|
||||
var apiKey = jsonState["apiKey"]?.ToString() ?? string.Empty;
|
||||
|
||||
var videos = new List<YouTubeVideo>();
|
||||
|
||||
using HttpClient client = new HttpClient();
|
||||
{
|
||||
try
|
||||
{
|
||||
// Send the request to the YouTube API with the provided query
|
||||
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=2");
|
||||
var json = JsonNode.Parse(response);
|
||||
|
||||
// Parse the response
|
||||
if (json?["items"] is JsonArray itemsArray)
|
||||
{
|
||||
foreach (var item in itemsArray)
|
||||
{
|
||||
// Add each video to the list with title, link, author, thumbnail, and captions (if available)
|
||||
videos.Add(new YouTubeVideo
|
||||
{
|
||||
Title = item["snippet"]?["title"]?.ToString() ?? string.Empty,
|
||||
Link = $"https://www.youtube.com/watch?v={item["id"]?["videoId"]?.ToString()}",
|
||||
Author = item["snippet"]?["channelTitle"]?.ToString() ?? string.Empty,
|
||||
ThumbnailUrl = item["snippet"]?["thumbnails"]?["default"]?["url"]?.ToString() ?? string.Empty, // Get the default thumbnail URL
|
||||
Captions = "Captions not available", // Placeholder for captions; You can integrate with another API if needed
|
||||
PublishedAt = DateTime.Parse(item["snippet"]?["publishedAt"]?.ToString(), CultureInfo.InvariantCulture), // Use CultureInfo.InvariantCulture
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Handle any errors from the API call or parsing
|
||||
videos.Add(new YouTubeVideo
|
||||
{
|
||||
Title = "Error fetching data",
|
||||
Link = string.Empty,
|
||||
Author = $"Error: {ex.Message}",
|
||||
ThumbnailUrl = string.Empty,
|
||||
Captions = string.Empty,
|
||||
PublishedAt = DateTime.MinValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return videos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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;
|
||||
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;
|
||||
|
||||
internal sealed partial class YouTubeVideoInfoMarkdownPage : MarkdownPage
|
||||
{
|
||||
private readonly string _markdown = @"
|
||||
# Markdown Guide
|
||||
|
||||
Markdown is a lightweight markup language with plain text formatting syntax. It's often used to format readme files, for writing messages in online forums, and to create rich text using a simple, plain text editor.
|
||||
|
||||
---
|
||||
|
||||
## Headings
|
||||
|
||||
You can create headings using the `#` symbol, with the number of `#` determining the heading level.
|
||||
|
||||
```markdown
|
||||
# H1 Heading
|
||||
## H2 Heading
|
||||
### H3 Heading
|
||||
#### H4 Heading
|
||||
";
|
||||
|
||||
public YouTubeVideoInfoMarkdownPage()
|
||||
{
|
||||
Icon = new("\uE946");
|
||||
Name = "See more information";
|
||||
}
|
||||
|
||||
public override string[] Bodies()
|
||||
{
|
||||
return [_markdown];
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,13 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Extensions;
|
||||
using Microsoft.CmdPal.Extensions.Helpers;
|
||||
using SamplePagesExtension;
|
||||
using YouTubeExtension.Helper;
|
||||
using YouTubeExtension.Pages;
|
||||
|
||||
namespace YouTubeExtension;
|
||||
|
||||
@@ -39,7 +42,7 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
|
||||
var section = new ListSection()
|
||||
{
|
||||
Title = "Search Results",
|
||||
Items = items.Select(video => new ListItem(new LinkAction(video))
|
||||
Items = items.Select(video => new ListItem(new OpenVideoLinkAction(video))
|
||||
{
|
||||
Title = video.Title,
|
||||
Subtitle = $"{video.Author}",
|
||||
@@ -54,6 +57,11 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
|
||||
Text = video.PublishedAt.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture), // Show the date of the video post
|
||||
}
|
||||
],
|
||||
MoreCommands = [
|
||||
new CommandContextItem(new OpenChannelLinkAction(video)),
|
||||
new CommandContextItem(new YouTubeVideoInfoMarkdownPage()),
|
||||
new CommandContextItem(new YouTubeAPIPage()),
|
||||
],
|
||||
}).ToArray(),
|
||||
};
|
||||
|
||||
@@ -74,7 +82,7 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
|
||||
try
|
||||
{
|
||||
// Send the request to the YouTube API with the provided query
|
||||
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=20");
|
||||
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=2");
|
||||
var json = JsonNode.Parse(response);
|
||||
|
||||
// Parse the response
|
||||
@@ -88,6 +96,8 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
|
||||
Title = item["snippet"]?["title"]?.ToString() ?? string.Empty,
|
||||
Link = $"https://www.youtube.com/watch?v={item["id"]?["videoId"]?.ToString()}",
|
||||
Author = item["snippet"]?["channelTitle"]?.ToString() ?? string.Empty,
|
||||
ChannelId = item["snippet"]?["channelId"]?.ToString() ?? string.Empty,
|
||||
ChannelUrl = $"https://www.youtube.com/channel/{item["snippet"]?["channelId"]?.ToString()}" ?? string.Empty,
|
||||
ThumbnailUrl = item["snippet"]?["thumbnails"]?["default"]?["url"]?.ToString() ?? string.Empty, // Get the default thumbnail URL
|
||||
Captions = "Captions not available", // Placeholder for captions; You can integrate with another API if needed
|
||||
PublishedAt = DateTime.Parse(item["snippet"]?["publishedAt"]?.ToString(), CultureInfo.InvariantCulture), // Use CultureInfo.InvariantCulture
|
||||
|
||||
@@ -25,6 +25,7 @@ public partial class YouTubeExtensionActionsProvider : ICommandProvider
|
||||
|
||||
private readonly IListItem[] _commands = [
|
||||
new ListItem(new YouTubeVideosPage()) { Title = "Search Videos", Subtitle = "YouTube" },
|
||||
new ListItem(new YouTubeChannelsPage()) { Title = "Search Channels", Subtitle = "YouTube" },
|
||||
];
|
||||
|
||||
private readonly YouTubeAPIPage apiPage = new();
|
||||
|
||||
Reference in New Issue
Block a user