268 lines
9.6 KiB
C#
268 lines
9.6 KiB
C#
using System.Reflection;
|
|
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface;
|
|
using HellionChat.Branding;
|
|
using HellionChat.Integrations;
|
|
using HellionChat.Resources;
|
|
using HellionChat.Themes;
|
|
using HellionChat.Util;
|
|
|
|
namespace HellionChat.Ui.Components.Settings.Tabs;
|
|
|
|
internal sealed class AboutTab
|
|
{
|
|
private readonly FontManager _fonts;
|
|
private readonly Plugin _plugin;
|
|
private readonly HonorificService _honorific;
|
|
private readonly ThemeRegistry _themes;
|
|
private readonly IPlatformUtil _platformUtil;
|
|
|
|
// SelfTest observable — the status key the real render path resolved.
|
|
internal string? LastHonorificStatusKey { get; private set; }
|
|
|
|
public AboutTab(
|
|
FontManager fonts,
|
|
Plugin plugin,
|
|
HonorificService honorific,
|
|
ThemeRegistry themes,
|
|
IPlatformUtil platformUtil
|
|
)
|
|
{
|
|
_fonts = fonts;
|
|
_plugin = plugin;
|
|
_honorific = honorific;
|
|
_themes = themes;
|
|
_platformUtil = platformUtil;
|
|
}
|
|
|
|
public void Draw()
|
|
{
|
|
// Reset the SelfTest observable each frame so a stale value from a prior
|
|
// real render can never let the integrations-status SelfTest pass falsely.
|
|
LastHonorificStatusKey = null;
|
|
DrawPluginInfo();
|
|
DrawSectionHeader("Brand");
|
|
DrawBrand();
|
|
DrawSectionHeader("Links");
|
|
DrawLinks();
|
|
DrawSectionHeader("Integrations");
|
|
DrawIntegrations();
|
|
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);
|
|
}
|
|
|
|
private void DrawIntegrations()
|
|
{
|
|
ImGui.TextWrapped(HellionStrings.Settings_Integrations_Intro);
|
|
ImGui.Spacing();
|
|
|
|
ImGui.TextUnformatted(HellionStrings.Settings_Integrations_Honorific_SectionHeader);
|
|
DrawHonorificStatus();
|
|
DrawToggle(
|
|
HellionStrings.Settings_Integrations_Honorific_Toggle,
|
|
() => Plugin.Config.ShowHonorificTitleInHeader,
|
|
v => Plugin.Config.ShowHonorificTitleInHeader = v
|
|
);
|
|
ImGui.TextDisabled(HellionStrings.Settings_Integrations_Honorific_ToggleHint);
|
|
DrawLinkButton(
|
|
HellionStrings.Settings_Integrations_Honorific_LinkRepo,
|
|
IntegrationLinks.HonorificRepo
|
|
);
|
|
DrawLinkButton(
|
|
HellionStrings.Settings_Integrations_Honorific_LinkAuthor,
|
|
IntegrationLinks.HonorificAuthor
|
|
);
|
|
|
|
DrawComingSoon();
|
|
DrawGotAnIdea();
|
|
}
|
|
|
|
private void DrawHonorificStatus()
|
|
{
|
|
var kind = HonorificStatus.Resolve(_honorific.IsAvailable, _honorific.DetectedApiVersion);
|
|
LastHonorificStatusKey = kind.ToString();
|
|
var colors = _themes.Active.Colors;
|
|
|
|
// Null-safety via the `is { } v` pattern, never `.Value` raw (spec SEC-2):
|
|
// the version is bound only on the arms that have it; the impossible
|
|
// Detected/Incompatible-without-version state falls through to default.
|
|
switch (kind)
|
|
{
|
|
case HonorificStatusKind.Detected when _honorific.DetectedApiVersion is { } v:
|
|
DrawStatusGlyph('●', colors.StatusSuccess);
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(
|
|
string.Format(
|
|
HellionStrings.Settings_Integrations_Honorific_Status_Detected,
|
|
v.Major,
|
|
v.Minor
|
|
)
|
|
);
|
|
break;
|
|
case HonorificStatusKind.Incompatible when _honorific.DetectedApiVersion is { } iv:
|
|
DrawStatusGlyph('⚠', colors.StatusWarning);
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(
|
|
string.Format(
|
|
HellionStrings.Settings_Integrations_Honorific_Status_Incompatible,
|
|
HonorificService.ExpectedApiMajor,
|
|
iv.Major,
|
|
iv.Minor
|
|
)
|
|
);
|
|
break;
|
|
default:
|
|
DrawStatusGlyph('○', colors.TextMuted);
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(
|
|
HellionStrings.Settings_Integrations_Honorific_Status_NotInstalled
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static void DrawStatusGlyph(char glyph, uint rgba)
|
|
{
|
|
ImGui.PushStyleColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(rgba));
|
|
ImGui.TextUnformatted(glyph.ToString());
|
|
ImGui.PopStyleColor();
|
|
}
|
|
|
|
private void DrawComingSoon()
|
|
{
|
|
ImGui.Spacing();
|
|
ImGui.TextUnformatted(HellionStrings.Settings_Integrations_ComingSoon_SectionHeader);
|
|
ImGui.TextDisabled(HellionStrings.Settings_Integrations_ComingSoon_Intro);
|
|
DrawComingSoonItem(
|
|
HellionStrings.Settings_Integrations_ComingSoon_ContextMenu_Title,
|
|
HellionStrings.Settings_Integrations_ComingSoon_ContextMenu_Description
|
|
);
|
|
DrawComingSoonItem(
|
|
HellionStrings.Settings_Integrations_ComingSoon_Notifications_Title,
|
|
HellionStrings.Settings_Integrations_ComingSoon_Notifications_Description
|
|
);
|
|
DrawComingSoonItem(
|
|
HellionStrings.Settings_Integrations_ComingSoon_RPStatus_Title,
|
|
HellionStrings.Settings_Integrations_ComingSoon_RPStatus_Description
|
|
);
|
|
DrawComingSoonItem(
|
|
HellionStrings.Settings_Integrations_ComingSoon_ExtraChat_Title,
|
|
HellionStrings.Settings_Integrations_ComingSoon_ExtraChat_Description
|
|
);
|
|
DrawComingSoonItem(
|
|
HellionStrings.Settings_Integrations_ComingSoon_QuickDM_Title,
|
|
HellionStrings.Settings_Integrations_ComingSoon_QuickDM_Description
|
|
);
|
|
}
|
|
|
|
private void DrawComingSoonItem(string title, string description)
|
|
{
|
|
using (_fonts.FontAwesome.Push())
|
|
{
|
|
ImGui.TextDisabled(FontAwesomeIcon.Hourglass.ToIconString());
|
|
}
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(title);
|
|
ImGui.TextDisabled(description);
|
|
}
|
|
|
|
private void DrawGotAnIdea()
|
|
{
|
|
ImGui.Spacing();
|
|
ImGui.TextUnformatted(HellionStrings.Settings_Integrations_GotAnIdea_SectionHeader);
|
|
ImGui.TextWrapped(HellionStrings.Settings_Integrations_GotAnIdea_Body);
|
|
if (ImGui.Button(HellionStrings.Settings_Integrations_GotAnIdea_LinkLabel))
|
|
{
|
|
_platformUtil.OpenLink(BrandingLinks.HellionForgeDiscordInvite);
|
|
}
|
|
}
|
|
|
|
private void DrawToggle(string label, Func<bool> get, Action<bool> set)
|
|
{
|
|
var current = get();
|
|
if (ImGui.Checkbox(label, ref current))
|
|
{
|
|
set(current);
|
|
_plugin.SaveConfig();
|
|
}
|
|
}
|
|
|
|
// URLs are exclusively hardcoded BrandingLinks/IntegrationLinks constants,
|
|
// validated to http/https at module-init. OpenLink centralises the browser
|
|
// open on an off-draw thread (it internally uses the same ShellExecute, so
|
|
// this is a consistency cleanup, not a security change). The standalone Copy
|
|
// button stays as the clipboard path.
|
|
private void DrawLinkButton(string label, string url)
|
|
{
|
|
if (ImGui.Button(label))
|
|
{
|
|
_platformUtil.OpenLink(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");
|
|
}
|
|
}
|