From 2f29559faf51e5f5983b2006e2d217e7a146c949 Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 13:36:50 +0700
Subject: [PATCH 1/9] Add HtmlAgilityPack package
---
Directory.Packages.props | 3 ++-
src/Ryujinx/Ryujinx.csproj | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c3af18ceec..0d447c3108 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -17,6 +17,7 @@
+
@@ -49,4 +50,4 @@
-
+
\ No newline at end of file
diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj
index 38453f2c66..baf9aaf863 100644
--- a/src/Ryujinx/Ryujinx.csproj
+++ b/src/Ryujinx/Ryujinx.csproj
@@ -44,6 +44,7 @@
+
From 4b7b3dc4c7a71154ea96f366c99de90bf63f28dc Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 13:41:05 +0700
Subject: [PATCH 2/9] Add OpenChangelogWindow function
---
src/Ryujinx/UI/Windows/AboutWindow.axaml | 3 +--
src/Ryujinx/UI/Windows/AboutWindow.axaml.cs | 6 ++++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/Ryujinx/UI/Windows/AboutWindow.axaml b/src/Ryujinx/UI/Windows/AboutWindow.axaml
index 69fa82517a..6af99238d5 100644
--- a/src/Ryujinx/UI/Windows/AboutWindow.axaml
+++ b/src/Ryujinx/UI/Windows/AboutWindow.axaml
@@ -87,8 +87,7 @@
Padding="5"
HorizontalAlignment="Center"
Background="Transparent"
- Click="Button_OnClick"
- Tag="https://github.com/Ryujinx/Ryujinx/wiki/Changelog#ryujinx-changelog">
+ Click="OpenChangelogWindow">
Date: Thu, 18 Apr 2024 18:07:37 +0700
Subject: [PATCH 3/9] Add view changelog strings and window
---
src/Ryujinx/Assets/Locales/en_US.json | 6 ++-
src/Ryujinx/UI/Windows/AboutWindow.axaml | 1 -
src/Ryujinx/UI/Windows/ChangelogWindow.axaml | 42 ++++++++++++++++++++
3 files changed, 46 insertions(+), 3 deletions(-)
create mode 100644 src/Ryujinx/UI/Windows/ChangelogWindow.axaml
diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json
index 77ad7d1f8c..9fd9903de0 100644
--- a/src/Ryujinx/Assets/Locales/en_US.json
+++ b/src/Ryujinx/Assets/Locales/en_US.json
@@ -765,8 +765,10 @@
"NetworkInterfaceTooltip": "The network interface used for LAN/LDN features.\n\nIn conjunction with a VPN or XLink Kai and a game with LAN support, can be used to spoof a same-network connection over the Internet.\n\nLeave on DEFAULT if unsure.",
"NetworkInterfaceDefault": "Default",
"PackagingShaders": "Packaging Shaders",
- "AboutChangelogButton": "View Changelog on GitHub",
- "AboutChangelogButtonTooltipMessage": "Click to open the changelog for this version in your default browser.",
+ "AboutChangelogButton": "View Changelog",
+ "AboutChangelogButtonTooltipMessage": "Click to view the changelog.",
+ "ChangelogWindowTitle": "Changelog",
+ "ChangelogDescription": "Showing the 10 most recent versions. For more changelog version history please visit Ryujinx GitHub page.",
"SettingsTabNetworkMultiplayer": "Multiplayer",
"MultiplayerMode": "Mode:",
"MultiplayerModeTooltip": "Change LDN multiplayer mode.\n\nLdnMitm will modify local wireless/local play functionality in games to function as if it were LAN, allowing for local, same-network connections with other Ryujinx instances and hacked Nintendo Switch consoles that have the ldn_mitm module installed.\n\nMultiplayer requires all players to be on the same game version (i.e. Super Smash Bros. Ultimate v13.0.1 can't connect to v13.0.0).\n\nLeave DISABLED if unsure.",
diff --git a/src/Ryujinx/UI/Windows/AboutWindow.axaml b/src/Ryujinx/UI/Windows/AboutWindow.axaml
index 6af99238d5..cadd875bcf 100644
--- a/src/Ryujinx/UI/Windows/AboutWindow.axaml
+++ b/src/Ryujinx/UI/Windows/AboutWindow.axaml
@@ -144,7 +144,6 @@
Background="Transparent"
Click="Button_OnClick"
CornerRadius="15"
- Tag="https://github.com/Ryujinx/Ryujinx"
ToolTip.Tip="{locale:Locale AboutGithubUrlTooltipMessage}">
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml
new file mode 100644
index 0000000000..413a0869b8
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
From 05de6aeadfed8f30ed27dd27a7f48d1de6977c7a Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 18:08:03 +0700
Subject: [PATCH 4/9] Implement ChangelogWindow function
---
.../UI/Windows/ChangelogWindow.axaml.cs | 150 ++++++++++++++++++
1 file changed, 150 insertions(+)
create mode 100644 src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
new file mode 100644
index 0000000000..e4eb3bd50a
--- /dev/null
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
@@ -0,0 +1,150 @@
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.Layout;
+using Avalonia.Styling;
+using FluentAvalonia.UI.Controls;
+using HtmlAgilityPack;
+using Ryujinx.Ava.Common.Locale;
+using Ryujinx.Ava.UI.Helpers;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.UI.Common.Helper;
+using System;
+using System.Diagnostics;
+using System.Text;
+using System.Threading.Tasks;
+using Button = Avalonia.Controls.Button;
+using System.Net.Http;
+
+
+namespace Ryujinx.Ava.UI.Windows
+{
+ public partial class ChangelogWindow : Window
+ {
+ public ChangelogWindow()
+ {
+ InitializeComponent();
+ InitializeAsync();
+ }
+
+ private async void InitializeAsync()
+ {
+ try
+ {
+ LoadingTextBlock.IsVisible = true; // Show the loading text
+ ChangelogTextBlock.IsVisible = false; // Hide the changelog text initially
+
+ string changelogHtml = await FetchChangelogHtml();
+ string changelog = ParseChangelogForRecentVersions(changelogHtml, 10);
+ LoadChangelog(changelog);
+
+ LoadingTextBlock.IsVisible = false; // Hide the loading text
+ ChangelogTextBlock.IsVisible = true; // Show the changelog text
+ }
+ catch (Exception ex)
+ {
+ LoadingTextBlock.Text = "Failed to load changelog: " + ex.Message;
+ }
+ }
+
+ private void LoadChangelog(string changelog)
+ {
+ ChangelogTextBlock.Text = changelog;
+ }
+
+ private static async Task FetchChangelogHtml()
+ {
+ using (var client = new HttpClient())
+ {
+ client.DefaultRequestHeaders.UserAgent.ParseAdd("Ryujinx-Updater/1.0.0");
+ return await client.GetStringAsync("https://github.com/Ryujinx/Ryujinx/wiki/Changelog");
+ }
+ }
+
+ private static string ParseChangelogForRecentVersions(string html, int count)
+ {
+ var doc = new HtmlDocument();
+ doc.LoadHtml(html);
+
+ var headers = doc.DocumentNode.SelectNodes("//div[contains(@class, 'markdown-heading')]//h2");
+ if (headers != null)
+ {
+ var content = new StringBuilder();
+ int versionsFound = 0;
+
+ foreach (var header in headers)
+ {
+ if (versionsFound >= count) break; // Stop after finding the desired number of versions
+ content.Append(header.OuterHtml);
+ var currentNode = header.ParentNode.NextSibling;
+
+ while (currentNode != null && versionsFound < count)
+ {
+ if (currentNode.Name == "div" && currentNode.SelectSingleNode("h2") != null)
+ {
+ versionsFound++; // Increment for each version header found
+ if (versionsFound >= count) break;
+ }
+ content.Append(currentNode.OuterHtml);
+ currentNode = currentNode.NextSibling;
+ }
+ }
+
+ return ConvertHtmlToPlainText(content.ToString());
+ }
+ return "No changelog found.";
+ }
+
+ private static string ConvertHtmlToPlainText(string html)
+ {
+ var doc = new HtmlDocument();
+ doc.LoadHtml(html);
+
+ // Recursively format nodes
+ string formattedText = FormatNode(doc.DocumentNode);
+
+ return HtmlEntity.DeEntitize(formattedText);
+ }
+
+ private static string FormatNode(HtmlNode node, int depth = 0)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (var child in node.ChildNodes)
+ {
+ switch (child.Name)
+ {
+ case "ul":
+ // Recursively format the list items
+ sb.Append(FormatNode(child, depth));
+ sb.AppendLine();
+ break;
+
+ case "li":
+ // Format list item based on depth: "-" for top-level, "+" for nested items
+ string prefix = (depth == 0 ? "- " : new string(' ', depth * 4) + "+ ");
+ sb.AppendLine($"{prefix}{FormatNode(child, depth + 1).Trim()}");
+ break;
+
+ case "p":
+ case "#text": // Handling direct text nodes
+ if (!string.IsNullOrWhiteSpace(child.InnerText))
+ {
+ // Trim the text
+ string text = HtmlEntity.DeEntitize(child.InnerText).Trim();
+ sb.Append($"{text}\n");
+ }
+ break;
+
+ default:
+ // Recursively process other types of nodes
+ if (child.HasChildNodes)
+ {
+ sb.Append(FormatNode(child, depth)); // Keep current depth for other types
+ }
+ break;
+ }
+ }
+ return sb.ToString();
+ }
+ }
+}
From 3630f1a307a9496705311f6ed4d9604f3f2442d5 Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 20:11:40 +0700
Subject: [PATCH 5/9] Make the window center as default
---
src/Ryujinx/UI/Windows/ChangelogWindow.axaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml
index 413a0869b8..f8f6821e8c 100644
--- a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml
@@ -12,9 +12,9 @@
d:DesignHeight="600"
d:DesignWidth="800"
CanResize="False"
+ WindowStartupLocation="CenterOwner"
Focusable="True"
mc:Ignorable="d"
- Title="{locale:Locale ChangelogWindowTitle}"
Icon="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common">
From d8d05d0f62dd9a33928236ca7b3d421b87904100 Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 20:12:07 +0700
Subject: [PATCH 6/9] Re-implement OpenChangelogWindow
---
src/Ryujinx/UI/Windows/AboutWindow.axaml.cs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/Ryujinx/UI/Windows/AboutWindow.axaml.cs b/src/Ryujinx/UI/Windows/AboutWindow.axaml.cs
index d6e24b4397..9663eec919 100644
--- a/src/Ryujinx/UI/Windows/AboutWindow.axaml.cs
+++ b/src/Ryujinx/UI/Windows/AboutWindow.axaml.cs
@@ -3,6 +3,7 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Styling;
+using Avalonia.VisualTree;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
@@ -55,7 +56,13 @@ namespace Ryujinx.Ava.UI.Windows
private void OpenChangelogWindow(object sender, RoutedEventArgs e)
{
ChangelogWindow changelogWindow = new ChangelogWindow();
- changelogWindow.Show();
+
+ // Find the parent window to use as the owner for the modal dialog
+ var parentWindow = this.FindAncestorOfType();
+ if (parentWindow != null)
+ {
+ changelogWindow.ShowDialog(parentWindow); // Pass the parent window as the owner
+ }
}
private void AmiiboLabel_OnPointerPressed(object sender, PointerPressedEventArgs e)
From 9e473dde995b7b0337b189e643c44cea76f36e85 Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 20:12:21 +0700
Subject: [PATCH 7/9] Changing some stuff in ChangelogWindow
---
src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
index e4eb3bd50a..a42ec40ede 100644
--- a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
@@ -19,12 +19,14 @@ using System.Net.Http;
namespace Ryujinx.Ava.UI.Windows
{
- public partial class ChangelogWindow : Window
+ public partial class ChangelogWindow : StyleableWindow
{
public ChangelogWindow()
{
+ DataContext = this;
InitializeComponent();
InitializeAsync();
+ Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance[LocaleKeys.ChangelogWindowTitle];
}
private async void InitializeAsync()
From 2b3d26910bb6431576f8a22653f83c68389e7efb Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 20:54:50 +0700
Subject: [PATCH 8/9] Fix whitespace
---
src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
index a42ec40ede..4b6dbbc5d9 100644
--- a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
@@ -11,10 +11,10 @@ using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.UI.Common.Helper;
using System;
using System.Diagnostics;
+using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Button = Avalonia.Controls.Button;
-using System.Net.Http;
namespace Ryujinx.Ava.UI.Windows
@@ -76,7 +76,9 @@ namespace Ryujinx.Ava.UI.Windows
foreach (var header in headers)
{
- if (versionsFound >= count) break; // Stop after finding the desired number of versions
+ if (versionsFound >= count)
+ break; // Stop after finding the desired number of versions
+
content.Append(header.OuterHtml);
var currentNode = header.ParentNode.NextSibling;
@@ -85,7 +87,8 @@ namespace Ryujinx.Ava.UI.Windows
if (currentNode.Name == "div" && currentNode.SelectSingleNode("h2") != null)
{
versionsFound++; // Increment for each version header found
- if (versionsFound >= count) break;
+ if (versionsFound >= count)
+ break;
}
content.Append(currentNode.OuterHtml);
currentNode = currentNode.NextSibling;
From 2953b87e5828b534093f23ae7ef827566ab9a063 Mon Sep 17 00:00:00 2001
From: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com>
Date: Thu, 18 Apr 2024 21:01:27 +0700
Subject: [PATCH 9/9] Fix IDE0063
---
src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
index 4b6dbbc5d9..1992e59492 100644
--- a/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
+++ b/src/Ryujinx/UI/Windows/ChangelogWindow.axaml.cs
@@ -56,11 +56,9 @@ namespace Ryujinx.Ava.UI.Windows
private static async Task FetchChangelogHtml()
{
- using (var client = new HttpClient())
- {
- client.DefaultRequestHeaders.UserAgent.ParseAdd("Ryujinx-Updater/1.0.0");
- return await client.GetStringAsync("https://github.com/Ryujinx/Ryujinx/wiki/Changelog");
- }
+ using var client = new HttpClient();
+ client.DefaultRequestHeaders.UserAgent.ParseAdd("Ryujinx-Updater/1.0.0");
+ return await client.GetStringAsync("https://github.com/Ryujinx/Ryujinx/wiki/Changelog");
}
private static string ParseChangelogForRecentVersions(string html, int count)