feat(PluginInstaller): add Dalamud core changelogs

This commit is contained in:
goaaats 2022-02-03 21:52:28 +01:00
parent cf9e6d3969
commit 2dd7e73bae
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
9 changed files with 275 additions and 27 deletions

View file

@ -14,6 +14,7 @@ using Dalamud.Game.Gui;
using Dalamud.Game.Internal;
using Dalamud.Interface.Internal.ManagedAsserts;
using Dalamud.Interface.Internal.Windows;
using Dalamud.Interface.Internal.Windows.PluginInstaller;
using Dalamud.Interface.Internal.Windows.SelfTest;
using Dalamud.Interface.Internal.Windows.StyleEditor;
using Dalamud.Interface.Style;

View file

@ -64,9 +64,10 @@ namespace Dalamud.Interface.Internal.Windows
this.InstalledIcon = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "installedIcon.png"))!;
this.ThirdIcon = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "thirdIcon.png"))!;
this.ThirdInstalledIcon = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "thirdInstalledIcon.png"))!;
this.CorePluginIcon = interfaceManager.LoadImage(Path.Combine(dalamud.AssetDirectory.FullName, "UIRes", "tsmLogo.png"))!;
if (this.DefaultIcon == null || this.TroubleIcon == null || this.UpdateIcon == null || this.InstalledIcon == null ||
this.ThirdIcon == null || this.ThirdInstalledIcon == null)
this.ThirdIcon == null || this.ThirdInstalledIcon == null || this.CorePluginIcon == null)
{
throw new Exception("Plugin overlay images could not be loaded.");
}
@ -105,6 +106,11 @@ namespace Dalamud.Interface.Internal.Windows
/// </summary>
public TextureWrap ThirdInstalledIcon { get; }
/// <summary>
/// Gets the core plugin icon.
/// </summary>
public TextureWrap CorePluginIcon { get; }
/// <inheritdoc/>
public void Dispose()
{
@ -114,6 +120,7 @@ namespace Dalamud.Interface.Internal.Windows
this.InstalledIcon?.Dispose();
this.ThirdIcon?.Dispose();
this.ThirdInstalledIcon?.Dispose();
this.CorePluginIcon?.Dispose();
this.downloadToken?.Cancel();

View file

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class representing a Dalamud changelog.
/// </summary>
internal class DalamudChangelog
{
/// <summary>
/// Gets the date of the version.
/// </summary>
public DateTime Date { get; init; }
/// <summary>
/// Gets the relevant version number.
/// </summary>
public string Version { get; init; }
/// <summary>
/// Gets the list of changes.
/// </summary>
public List<DalamudChangelogChange> Changes { get; init; }
/// <summary>
/// Class representing the relevant changes.
/// </summary>
public class DalamudChangelogChange
{
/// <summary>
/// Gets the commit message.
/// </summary>
public string Message { get; init; }
/// <summary>
/// Gets the commit author.
/// </summary>
public string Author { get; init; }
/// <summary>
/// Gets the commit reference SHA.
/// </summary>
public string Sha { get; init; }
/// <summary>
/// Gets the commit datetime.
/// </summary>
public DateTime Date { get; init; }
}
}
}

View file

@ -0,0 +1,54 @@
using System;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class representing a Dalamud changelog.
/// </summary>
internal class DalamudChangelogEntry : IChangelogEntry
{
private readonly DalamudChangelog changelog;
/// <summary>
/// Initializes a new instance of the <see cref="DalamudChangelogEntry"/> class.
/// </summary>
/// <param name="changelog">The changelog.</param>
/// <param name="icon">The icon.</param>
public DalamudChangelogEntry(DalamudChangelog changelog, TextureWrap icon)
{
this.changelog = changelog;
this.Icon = icon;
var changelogText = string.Empty;
for (var i = 0; i < changelog.Changes.Count; i++)
{
var change = changelog.Changes[i];
changelogText += $"{change.Message} (by {change.Author})";
if (i < changelog.Changes.Count - 1)
{
changelogText += Environment.NewLine;
}
}
this.Text = changelogText;
}
/// <inheritdoc/>
public string Title => "Dalamud Core";
/// <inheritdoc/>
public string Version => this.changelog.Version;
/// <inheritdoc/>
public string Text { get; init; }
/// <inheritdoc/>
public TextureWrap Icon { get; init; }
/// <inheritdoc/>
public DateTime Date => this.changelog.Date;
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class responsible for managing Dalamud changelogs.
/// </summary>
internal class DalamudChangelogManager : IDisposable
{
private const string ChangelogUrl = "https://kamori.goats.dev/Plugin/CoreChangelog";
private readonly HttpClient client = new();
/// <summary>
/// Gets a list of all available changelogs.
/// </summary>
public IReadOnlyList<DalamudChangelog>? Changelogs { get; private set; }
/// <summary>
/// Reload the changelog list.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task ReloadChangelogAsync()
{
this.Changelogs = await this.client.GetFromJsonAsync<List<DalamudChangelog>>(ChangelogUrl);
}
/// <inheritdoc/>
public void Dispose()
{
this.client.Dispose();
}
}
}

View file

@ -0,0 +1,37 @@
using System;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class representing a changelog entry.
/// </summary>
internal interface IChangelogEntry
{
/// <summary>
/// Gets the title of the entry.
/// </summary>
string Title { get; }
/// <summary>
/// Gets the version this entry applies to.
/// </summary>
string Version { get; }
/// <summary>
/// Gets the text of the entry.
/// </summary>
string Text { get; }
/// <summary>
/// Gets the icon of the entry.
/// </summary>
TextureWrap Icon { get; }
/// <summary>
/// Gets the date of the entry.
/// </summary>
DateTime Date { get; }
}
}

View file

@ -0,0 +1,52 @@
using System;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class representing a plugin changelog.
/// </summary>
internal class PluginChangelogEntry : IChangelogEntry
{
private readonly LocalPlugin plugin;
/// <summary>
/// Initializes a new instance of the <see cref="PluginChangelogEntry"/> class.
/// </summary>
/// <param name="plugin">The plugin manifest.</param>
/// <param name="icon">The icon.</param>
public PluginChangelogEntry(LocalPlugin plugin, TextureWrap icon)
{
this.plugin = plugin;
this.Icon = icon;
if (plugin.Manifest.Changelog.IsNullOrEmpty())
throw new ArgumentException("Manifest has no changelog.");
var version = plugin.AssemblyName?.Version;
version ??= plugin.Manifest.Testing
? plugin.Manifest.TestingAssemblyVersion
: plugin.Manifest.AssemblyVersion;
this.Version = version!.ToString();
}
/// <inheritdoc/>
public string Title => this.plugin.Manifest.Name;
/// <inheritdoc/>
public string Version { get; init; }
/// <inheritdoc/>
public string Text => this.plugin.Manifest.Changelog!;
/// <inheritdoc/>
public TextureWrap Icon { get; init; }
/// <inheritdoc/>
public DateTime Date => DateTimeOffset.FromUnixTimeSeconds(this.plugin.Manifest.LastUpdate).DateTime;
}
}

View file

@ -5,6 +5,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Numerics;
using System.Threading.Tasks;
@ -25,7 +26,7 @@ using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;
namespace Dalamud.Interface.Internal.Windows
namespace Dalamud.Interface.Internal.Windows.PluginInstaller
{
/// <summary>
/// Class responsible for drawing the plugin installer.
@ -39,6 +40,9 @@ namespace Dalamud.Interface.Internal.Windows
private readonly PluginCategoryManager categoryManager = new();
private readonly PluginImageCache imageCache = new();
private readonly DalamudChangelogManager dalamudChangelogManager = new();
private readonly List<int> openPluginCollapsibles = new();
#region Image Tester State
@ -81,8 +85,6 @@ namespace Dalamud.Interface.Internal.Windows
private OperationStatus installStatus = OperationStatus.Idle;
private OperationStatus updateStatus = OperationStatus.Idle;
private List<int> openPluginCollapsibles = new();
/// <summary>
/// Initializes a new instance of the <see cref="PluginInstallerWindow"/> class.
/// </summary>
@ -150,6 +152,7 @@ namespace Dalamud.Interface.Internal.Windows
var pluginManager = Service<PluginManager>.Get();
_ = pluginManager.ReloadPluginMastersAsync();
_ = this.dalamudChangelogManager.ReloadChangelogAsync();
this.searchText = string.Empty;
this.sortKind = PluginSortKind.Alphabetical;
@ -518,13 +521,28 @@ namespace Dalamud.Interface.Internal.Windows
return;
}
var filteredList = this.pluginListInstalled
var pluginChangelogs = this.pluginListInstalled
.Where(plugin => !this.IsManifestFiltered(plugin.Manifest)
&& !plugin.Manifest.Changelog.IsNullOrEmpty())
.OrderByDescending(plugin => plugin.Manifest.LastUpdate)
.ToList();
.Select(x =>
{
var iconTex = this.imageCache.DefaultIcon;
var hasIcon = this.imageCache.TryGetIcon(x, x.Manifest, x.Manifest.IsThirdParty, out var cachedIconTex);
if (hasIcon && cachedIconTex != null)
{
iconTex = cachedIconTex;
}
if (!filteredList.Any())
var changelog = new PluginChangelogEntry(x, iconTex);
return (IChangelogEntry)changelog;
});
var changelogs = (this.dalamudChangelogManager.Changelogs != null
? pluginChangelogs
.Concat(this.dalamudChangelogManager.Changelogs.Select(x => new DalamudChangelogEntry(x, this.imageCache.CorePluginIcon)))
: pluginChangelogs).OrderByDescending(x => x.Date).ToList();
if (!changelogs.Any())
{
ImGui.TextColored(
ImGuiColors.DalamudGrey2,
@ -535,9 +553,9 @@ namespace Dalamud.Interface.Internal.Windows
return;
}
foreach (var plugin in filteredList)
foreach (var logEntry in changelogs)
{
this.DrawChangelog(plugin);
this.DrawChangelog(logEntry);
}
}
@ -1202,41 +1220,30 @@ namespace Dalamud.Interface.Internal.Windows
return isOpen;
}
private void DrawChangelog(LocalPlugin plugin)
private void DrawChangelog(IChangelogEntry log)
{
ImGui.Separator();
var startCursor = ImGui.GetCursorPos();
var iconTex = this.imageCache.DefaultIcon;
var hasIcon = this.imageCache.TryGetIcon(plugin, plugin.Manifest, plugin.Manifest.IsThirdParty, out var cachedIconTex);
if (hasIcon && cachedIconTex != null)
{
iconTex = cachedIconTex;
}
var iconSize = ImGuiHelpers.ScaledVector2(64, 64);
ImGui.Image(iconTex.ImGuiHandle, iconSize);
ImGui.Image(log.Icon.ImGuiHandle, iconSize);
ImGui.SameLine();
ImGuiHelpers.ScaledDummy(5);
ImGui.SameLine();
var cursor = ImGui.GetCursorPos();
ImGui.Text(plugin.Name);
ImGui.Text(log.Title);
ImGui.SameLine();
var version = plugin.AssemblyName?.Version;
version ??= plugin.Manifest.Testing
? plugin.Manifest.TestingAssemblyVersion
: plugin.Manifest.AssemblyVersion;
ImGui.TextColored(ImGuiColors.DalamudGrey3, $" v{version}");
ImGui.TextColored(ImGuiColors.DalamudGrey3, $" v{log.Version}");
cursor.Y += ImGui.GetTextLineHeightWithSpacing();
ImGui.SetCursorPos(cursor);
ImGui.TextWrapped(plugin.Manifest.Changelog);
ImGui.TextWrapped(log.Text);
var endCursor = ImGui.GetCursorPos();

View file

@ -15,7 +15,7 @@ namespace Dalamud.Plugin.Internal
/// </summary>
internal class PluginRepository
{
private const string DalamudPluginsMasterUrl = "https://kamori.goats.dev/Plugin/GetPluginMaster";
private const string DalamudPluginsMasterUrl = "https://kamori.goats.dev/Plugin/PluginMaster";
private static readonly ModuleLog Log = new("PLUGINR");