Merge branch 'master' of https://github.com/goatcorp/Dalamud into feat/rxnet-improvements

This commit is contained in:
karashiiro 2023-02-15 22:49:30 -08:00
commit d295fa1494
7 changed files with 155 additions and 36 deletions

View file

@ -8,7 +8,7 @@
</PropertyGroup>
<PropertyGroup Label="Feature">
<DalamudVersion>7.4.4.1</DalamudVersion>
<DalamudVersion>7.4.5.0</DalamudVersion>
<Description>XIV Launcher addon framework</Description>
<AssemblyVersion>$(DalamudVersion)</AssemblyVersion>
<Version>$(DalamudVersion)</Version>

View file

@ -41,6 +41,9 @@ internal class DalamudChangelogEntry : IChangelogEntry
/// <inheritdoc/>
public string Text { get; init; }
/// <inheritdoc/>
public string? Author { get; private set; } = null;
/// <inheritdoc/>
public DateTime Date => this.changelog.Date;
}

View file

@ -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;
/// <summary>
/// Class responsible for managing Dalamud changelogs.
/// </summary>
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;
/// <summary>
/// Initializes a new instance of the <see cref="DalamudChangelogManager"/> class.
/// </summary>
/// <param name="manager">The responsible PluginManager.</param>
public DalamudChangelogManager(PluginManager manager)
{
this.manager = manager;
}
/// <summary>
/// Gets a list of all available changelogs.
/// </summary>
public IReadOnlyList<DalamudChangelog>? Changelogs { get; private set; }
public IReadOnlyList<IChangelogEntry>? Changelogs { get; private set; }
/// <summary>
/// Reload the changelog list.
@ -26,12 +41,58 @@ internal class DalamudChangelogManager : IDisposable
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task ReloadChangelogAsync()
{
this.Changelogs = await this.client.GetFromJsonAsync<List<DalamudChangelog>>(ChangelogUrl);
using var client = new HttpClient();
this.Changelogs = null;
var dalamudChangelogs = await client.GetFromJsonAsync<List<DalamudChangelog>>(DalamudChangelogUrl);
var changelogs = dalamudChangelogs.Select(x => new DalamudChangelogEntry(x)).Cast<IChangelogEntry>();
foreach (var plugin in this.manager.InstalledPlugins)
{
if (plugin.Manifest.IsThirdParty || !plugin.Manifest.IsDip17Plugin)
continue;
var pluginChangelogs = await client.GetFromJsonAsync<PluginHistory>(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();
}
/// <inheritdoc/>
public void Dispose()
/// <summary>
/// API response for a history of plugin versions.
/// </summary>
internal class PluginHistory
{
this.client.Dispose();
/// <summary>
/// Gets or sets the version history of the plugin.
/// </summary>
public List<PluginVersion> Versions { get; set; } = null!;
/// <summary>
/// A single plugin version.
/// </summary>
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
}
}
}

View file

@ -22,6 +22,11 @@ internal interface IChangelogEntry
/// </summary>
string Text { get; }
/// <summary>
/// Gets the author of the changelog.
/// </summary>
string? Author { get; }
/// <summary>
/// Gets the date of the entry.
/// </summary>

View file

@ -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 <see cref="PluginChangelogEntry"/> class.
/// </summary>
/// <param name="plugin">The plugin manifest.</param>
public PluginChangelogEntry(LocalPlugin plugin)
/// <param name="history">The changelog history entry.</param>
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;
}
/// <summary>
@ -35,11 +34,14 @@ internal class PluginChangelogEntry : IChangelogEntry
public string Title => this.Plugin.Manifest.Name;
/// <inheritdoc/>
public string Version { get; init; }
public string Version { get; private set; }
/// <inheritdoc/>
public string Text => this.Plugin.Manifest.Changelog!;
public string Text { get; private set; }
/// <inheritdoc/>
public DateTime Date => DateTimeOffset.FromUnixTimeSeconds(this.Plugin.Manifest.LastUpdate).DateTime;
public string? Author { get; private set; }
/// <inheritdoc/>
public DateTime Date { get; private set; }
}

View file

@ -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<int> 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
/// <inheritdoc/>
public void Dispose()
{
this.dalamudChangelogRefreshTaskCts?.Cancel();
var pluginManager = Service<PluginManager>.GetNullable();
if (pluginManager != null)
{
@ -193,7 +201,6 @@ internal class PluginInstallerWindow : Window, IDisposable
var pluginManager = Service<PluginManager>.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<IChangelogEntry> 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<DalamudChangelogEntry>();
}
else if (displayPlugins)
{
changelogs = pluginChangelogs;
changelogs = this.dalamudChangelogManager.Changelogs.OfType<PluginChangelogEntry>();
}
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

View file

@ -1299,6 +1299,35 @@ Thanks and have fun!";
return this.bannedPlugins.LastOrDefault(ban => ban.Name == manifest.InternalName).Reason;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>The calling plugin, or null.</returns>
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<AvailablePluginUpdate>();