feat(settings): add About tab with brand, links, credits
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using HellionChat.Branding;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HellionChat.Ui.Components.Settings.Tabs;
|
||||
|
||||
internal sealed class AboutTab
|
||||
{
|
||||
private readonly FontManager _fonts;
|
||||
private readonly ILogger<AboutTab> _logger;
|
||||
|
||||
public AboutTab(FontManager fonts, ILogger<AboutTab> logger)
|
||||
{
|
||||
_fonts = fonts;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
DrawPluginInfo();
|
||||
DrawSectionHeader("Brand");
|
||||
DrawBrand();
|
||||
DrawSectionHeader("Links");
|
||||
DrawLinks();
|
||||
DrawSectionHeader("Credits");
|
||||
DrawCredits();
|
||||
DrawSectionHeader("License");
|
||||
DrawLicense();
|
||||
}
|
||||
|
||||
// Dalamud.Bindings.ImGui does not expose ImGui.SeparatorText, so we use
|
||||
// the Separator + TextUnformatted idiom the rest of the codebase uses.
|
||||
private static void DrawSectionHeader(string title)
|
||||
{
|
||||
ImGui.Spacing();
|
||||
ImGui.Separator();
|
||||
ImGui.Spacing();
|
||||
ImGui.TextUnformatted(title);
|
||||
}
|
||||
|
||||
private static void DrawPluginInfo()
|
||||
{
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
|
||||
ImGui.TextUnformatted("HellionChat");
|
||||
// Schema version pulled from Configuration.LatestVersion (single source of
|
||||
// truth) so future schema bumps don't have to touch this string.
|
||||
ImGui.TextDisabled($"Version {version} · Schema v{Configuration.LatestVersion}");
|
||||
}
|
||||
|
||||
private void DrawBrand()
|
||||
{
|
||||
using (_fonts.FontAwesome.Push())
|
||||
{
|
||||
// ImGui's PushStyleColor uint API is ABGR-native. 0xFF0C41C2u packs
|
||||
// as A=FF B=0C G=41 R=C2 → RGB #C2410C (Forge-Bronze). No swap needed
|
||||
// because the literal is already ABGR; theme-sourced uints from
|
||||
// ThemeColors.* (RGBA) would need ColourUtil.RgbaToAbgr first.
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, 0xFF0C41C2u);
|
||||
ImGui.TextUnformatted(FontAwesomeIcon.Hammer.ToIconString());
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted("by Hellion Online Media");
|
||||
ImGui.TextDisabled("Hellion Forge — Modding Division");
|
||||
}
|
||||
|
||||
private void DrawLinks()
|
||||
{
|
||||
DrawLinkButton("Discord (Hellion Forge)", BrandingLinks.HellionForgeDiscordInvite);
|
||||
DrawLinkButton("Gitea repository", BrandingLinks.HellionChatRepo);
|
||||
DrawLinkButton("Custom repo manifest", BrandingLinks.HellionChatCustomRepoManifest);
|
||||
}
|
||||
|
||||
// URLs in v1.7.0 are exclusively hardcoded BrandingLinks.* constants —
|
||||
// Process.Start with UseShellExecute=true is safe under that constraint.
|
||||
// If a future cycle ever feeds user-supplied URLs here, add an https/http
|
||||
// allow-list filter via Uri.TryCreate before Process.Start; without it
|
||||
// UseShellExecute would happily launch file:// or shell-protocol handlers.
|
||||
private void DrawLinkButton(string label, string url)
|
||||
{
|
||||
if (ImGui.Button(label))
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Could not open {Url}, copying to clipboard instead", url);
|
||||
ImGui.SetClipboardText(url);
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton($"Copy##{url}"))
|
||||
{
|
||||
ImGui.SetClipboardText(url);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawCredits()
|
||||
{
|
||||
ImGui.BulletText("ChatTwo — original maintainer Anna Clemens, GPL-3.0");
|
||||
ImGui.BulletText("Dalamud — goatcorp, AGPL-3.0");
|
||||
ImGui.BulletText("ImGui — Omar Cornut, MIT");
|
||||
ImGui.BulletText("FontAwesome — Fonticons, OFL-1.1");
|
||||
ImGui.BulletText("Inter — rsms, OFL-1.1");
|
||||
ImGui.BulletText("NotoSansCJK — Google, OFL-1.1");
|
||||
}
|
||||
|
||||
private static void DrawLicense()
|
||||
{
|
||||
ImGui.TextUnformatted("GPL-3.0-or-later");
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ internal sealed class SettingsWindow : Window
|
||||
private readonly WindowTab _window;
|
||||
private readonly ChannelsTab _channels;
|
||||
private readonly DataPrivacyTab _dataPrivacy;
|
||||
private readonly AboutTab _about;
|
||||
|
||||
public SettingsWindow(
|
||||
Plugin plugin,
|
||||
@@ -39,6 +40,7 @@ internal sealed class SettingsWindow : Window
|
||||
WindowTab window,
|
||||
ChannelsTab channels,
|
||||
DataPrivacyTab dataPrivacy,
|
||||
AboutTab about,
|
||||
ILoggerFactory loggerFactory
|
||||
)
|
||||
: base($"{Language.Settings_Title.Format(Plugin.PluginName)}###chat2-settings")
|
||||
@@ -55,6 +57,7 @@ internal sealed class SettingsWindow : Window
|
||||
_window = window;
|
||||
_channels = channels;
|
||||
_dataPrivacy = dataPrivacy;
|
||||
_about = about;
|
||||
_ = loggerFactory;
|
||||
|
||||
Size = new Vector2(720, 540);
|
||||
@@ -98,6 +101,9 @@ internal sealed class SettingsWindow : Window
|
||||
case "data-privacy":
|
||||
_dataPrivacy.Draw();
|
||||
break;
|
||||
case "about":
|
||||
_about.Draw();
|
||||
break;
|
||||
case "appearance":
|
||||
_appearance.Draw();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user