From 78581d637abb8f423342f0dfee19dbf390558053 Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 15 Feb 2023 19:21:42 +0100 Subject: [PATCH 1/3] feat: plugin changelog history --- .../PluginInstaller/DalamudChangelogEntry.cs | 3 + .../DalamudChangelogManager.cs | 77 +++++++++++++++++-- .../PluginInstaller/IChangelogEntry.cs | 5 ++ .../PluginInstaller/PluginChangelogEntry.cs | 24 +++--- .../PluginInstaller/PluginInstallerWindow.cs | 51 ++++++++---- 5 files changed, 125 insertions(+), 35 deletions(-) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogEntry.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogEntry.cs index 2ea845ed1..5108a535e 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogEntry.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogEntry.cs @@ -41,6 +41,9 @@ internal class DalamudChangelogEntry : IChangelogEntry /// public string Text { get; init; } + /// + public string? Author { get; private set; } = null; + /// public DateTime Date => this.changelog.Date; } diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogManager.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogManager.cs index 086a389d3..622ad912b 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogManager.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/DalamudChangelogManager.cs @@ -1,24 +1,39 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using System.Net.Http.Json; +using System.Threading; using System.Threading.Tasks; +using Dalamud.Plugin.Internal; +using Serilog; + namespace Dalamud.Interface.Internal.Windows.PluginInstaller; /// /// Class responsible for managing Dalamud changelogs. /// -internal class DalamudChangelogManager : IDisposable +internal class DalamudChangelogManager { - private const string ChangelogUrl = "https://kamori.goats.dev/Plugin/CoreChangelog"; + private const string DalamudChangelogUrl = "https://kamori.goats.dev/Dalamud/Release/Changelog"; + private const string PluginChangelogUrl = "https://kamori.goats.dev/Plugin/History/{0}?track={1}"; - private readonly HttpClient client = new(); + private readonly PluginManager manager; + + /// + /// Initializes a new instance of the class. + /// + /// The responsible PluginManager. + public DalamudChangelogManager(PluginManager manager) + { + this.manager = manager; + } /// /// Gets a list of all available changelogs. /// - public IReadOnlyList? Changelogs { get; private set; } + public IReadOnlyList? Changelogs { get; private set; } /// /// Reload the changelog list. @@ -26,12 +41,58 @@ internal class DalamudChangelogManager : IDisposable /// A representing the asynchronous operation. public async Task ReloadChangelogAsync() { - this.Changelogs = await this.client.GetFromJsonAsync>(ChangelogUrl); + using var client = new HttpClient(); + this.Changelogs = null; + + var dalamudChangelogs = await client.GetFromJsonAsync>(DalamudChangelogUrl); + var changelogs = dalamudChangelogs.Select(x => new DalamudChangelogEntry(x)).Cast(); + + foreach (var plugin in this.manager.InstalledPlugins) + { + if (plugin.Manifest.IsThirdParty || !plugin.Manifest.IsDip17Plugin) + continue; + + var pluginChangelogs = await client.GetFromJsonAsync(string.Format( + PluginChangelogUrl, + plugin.Manifest.InternalName, + plugin.Manifest.Dip17Channel)); + + changelogs = changelogs.Concat(pluginChangelogs.Versions + .Where(x => x.Dip17Track == plugin.Manifest.Dip17Channel) + .Select(x => new PluginChangelogEntry(plugin, x))); + } + + this.Changelogs = changelogs.OrderByDescending(x => x.Date).ToList(); } - /// - public void Dispose() + /// + /// API response for a history of plugin versions. + /// + internal class PluginHistory { - this.client.Dispose(); + /// + /// Gets or sets the version history of the plugin. + /// + public List Versions { get; set; } = null!; + + /// + /// A single plugin version. + /// + internal class PluginVersion + { +#pragma warning disable SA1600 + public string Version { get; set; } = null!; + + public string Dip17Track { get; set; } = null!; + + public string? Changelog { get; set; } + + public DateTime PublishedAt { get; set; } + + public int? PrNumber { get; set; } + + public string? PublishedBy { get; set; } +#pragma warning restore SA1600 + } } } diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/IChangelogEntry.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/IChangelogEntry.cs index 04089f23c..1f5baa1be 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/IChangelogEntry.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/IChangelogEntry.cs @@ -22,6 +22,11 @@ internal interface IChangelogEntry /// string Text { get; } + /// + /// Gets the author of the changelog. + /// + string? Author { get; } + /// /// Gets the date of the entry. /// diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginChangelogEntry.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginChangelogEntry.cs index 90e78b35a..495d59d64 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginChangelogEntry.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginChangelogEntry.cs @@ -1,7 +1,7 @@ using System; +using CheapLoc; using Dalamud.Plugin.Internal.Types; -using Dalamud.Utility; namespace Dalamud.Interface.Internal.Windows.PluginInstaller; @@ -14,16 +14,15 @@ internal class PluginChangelogEntry : IChangelogEntry /// Initializes a new instance of the class. /// /// The plugin manifest. - public PluginChangelogEntry(LocalPlugin plugin) + /// The changelog history entry. + public PluginChangelogEntry(LocalPlugin plugin, DalamudChangelogManager.PluginHistory.PluginVersion history) { this.Plugin = plugin; - if (plugin.Manifest.Changelog.IsNullOrEmpty()) - throw new ArgumentException("Manifest has no changelog."); - - var version = plugin.Manifest.EffectiveVersion; - - this.Version = version!.ToString(); + this.Version = history.Version; + this.Text = history.Changelog ?? Loc.Localize("ChangelogNoText", "No changelog for this version."); + this.Author = history.PublishedBy; + this.Date = history.PublishedAt; } /// @@ -35,11 +34,14 @@ internal class PluginChangelogEntry : IChangelogEntry public string Title => this.Plugin.Manifest.Name; /// - public string Version { get; init; } + public string Version { get; private set; } /// - public string Text => this.Plugin.Manifest.Changelog!; + public string Text { get; private set; } /// - public DateTime Date => DateTimeOffset.FromUnixTimeSeconds(this.Plugin.Manifest.LastUpdate).DateTime; + public string? Author { get; private set; } + + /// + public DateTime Date { get; private set; } } diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 4710dd68b..66f706bfe 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Numerics; +using System.Threading; using System.Threading.Tasks; using CheapLoc; @@ -40,7 +41,6 @@ internal class PluginInstallerWindow : Window, IDisposable private readonly PluginImageCache imageCache; private readonly PluginCategoryManager categoryManager = new(); - private readonly DalamudChangelogManager dalamudChangelogManager = new(); private readonly List openPluginCollapsibles = new(); @@ -48,6 +48,10 @@ internal class PluginInstallerWindow : Window, IDisposable private readonly object listLock = new(); + private DalamudChangelogManager? dalamudChangelogManager; + private Task? dalamudChangelogRefreshTask; + private CancellationTokenSource? dalamudChangelogRefreshTaskCts; + #region Image Tester State private string[] testerImagePaths = new string[5]; @@ -132,6 +136,8 @@ internal class PluginInstallerWindow : Window, IDisposable if (pluginManager.PluginsReady) this.OnInstalledPluginsChanged(); + this.dalamudChangelogManager = new(pluginManager); + pluginManager.OnAvailablePluginsChanged += this.OnAvailablePluginsChanged; pluginManager.OnInstalledPluginsChanged += this.OnInstalledPluginsChanged; @@ -179,6 +185,8 @@ internal class PluginInstallerWindow : Window, IDisposable /// public void Dispose() { + this.dalamudChangelogRefreshTaskCts?.Cancel(); + var pluginManager = Service.GetNullable(); if (pluginManager != null) { @@ -193,7 +201,6 @@ internal class PluginInstallerWindow : Window, IDisposable var pluginManager = Service.Get(); _ = pluginManager.ReloadPluginMastersAsync(); - _ = this.dalamudChangelogManager.ReloadChangelogAsync(); this.searchText = string.Empty; this.sortKind = PluginSortKind.Alphabetical; @@ -837,30 +844,40 @@ internal class PluginInstallerWindow : Window, IDisposable return; } - var pluginChangelogs = this.pluginListInstalled - .Where(plugin => !this.IsManifestFiltered(plugin.Manifest) - && !plugin.Manifest.Changelog.IsNullOrEmpty()) - .Select(x => - { - var changelog = new PluginChangelogEntry(x); - return (IChangelogEntry)changelog; - }); + if (this.dalamudChangelogRefreshTask?.IsFaulted == true || + this.dalamudChangelogRefreshTask?.IsCanceled == true) + { + ImGui.TextColored(ImGuiColors.DalamudGrey, Locs.TabBody_ChangelogError); + return; + } + + if (this.dalamudChangelogManager?.Changelogs == null) + { + ImGui.TextColored(ImGuiColors.DalamudGrey, Locs.TabBody_LoadingPlugins); + + if (this.dalamudChangelogManager != null && + this.dalamudChangelogRefreshTask == null) + { + this.dalamudChangelogRefreshTaskCts = new CancellationTokenSource(); + this.dalamudChangelogRefreshTask = + Task.Run(this.dalamudChangelogManager.ReloadChangelogAsync, this.dalamudChangelogRefreshTaskCts.Token); + } + + return; + } IEnumerable changelogs = null; if (displayDalamud && displayPlugins && this.dalamudChangelogManager.Changelogs != null) { - changelogs = pluginChangelogs - .Concat(this.dalamudChangelogManager.Changelogs.Select( - x => new DalamudChangelogEntry(x))); + changelogs = this.dalamudChangelogManager.Changelogs; } else if (displayDalamud && this.dalamudChangelogManager.Changelogs != null) { - changelogs = this.dalamudChangelogManager.Changelogs.Select( - x => new DalamudChangelogEntry(x)); + changelogs = this.dalamudChangelogManager.Changelogs.OfType(); } else if (displayPlugins) { - changelogs = pluginChangelogs; + changelogs = this.dalamudChangelogManager.Changelogs.OfType(); } var sortedChangelogs = changelogs?.OrderByDescending(x => x.Date).ToList(); @@ -2898,6 +2915,8 @@ internal class PluginInstallerWindow : Window, IDisposable public static string TabBody_ChangelogNone => Loc.Localize("InstallerNoChangelog", "None of your installed plugins have a changelog."); + public static string TabBody_ChangelogError => Loc.Localize("InstallerChangelogError", "Could not download changelogs."); + #endregion #region Plugin title text From 3072d624a60ff28922e8507ba9799c2f5d57ddff Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 15 Feb 2023 19:51:36 +0100 Subject: [PATCH 2/3] feat: add PluginManager::FindCallingPlugin() --- Dalamud/Plugin/Internal/PluginManager.cs | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index a59e83a72..e6fbade38 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -1299,6 +1299,35 @@ Thanks and have fun!"; return this.bannedPlugins.LastOrDefault(ban => ban.Name == manifest.InternalName).Reason; } + /// + /// Get the plugin that called this method by walking the stack, + /// or null, if it cannot be determined. + /// At the time, this is naive and shouldn't be used for security-critical checks. + /// + /// The calling plugin, or null. + public LocalPlugin? FindCallingPlugin() + { + var trace = new StackTrace(); + foreach (var frame in trace.GetFrames()) + { + var declaringType = frame.GetMethod()?.DeclaringType; + if (declaringType == null) + continue; + + lock (this.pluginListLock) + { + foreach (var plugin in this.InstalledPlugins) + { + if (plugin.AssemblyName != null && + plugin.AssemblyName.FullName == declaringType.Assembly.GetName().FullName) + return plugin; + } + } + } + + return null; + } + private void DetectAvailablePluginUpdates() { var updatablePlugins = new List(); From 40cd838e1c89742376301a11036f679c8492229e Mon Sep 17 00:00:00 2001 From: goat Date: Wed, 15 Feb 2023 19:52:04 +0100 Subject: [PATCH 3/3] build: 7.4.5.0 --- Dalamud/Dalamud.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 26ff61776..a133731e9 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -8,7 +8,7 @@ - 7.4.4.1 + 7.4.5.0 XIV Launcher addon framework $(DalamudVersion) $(DalamudVersion)