refactor(settings): merge integrations into the About tab, finalize seven tabs

This commit is contained in:
2026-05-23 04:11:18 +02:00
parent 0da4751b0f
commit 4cf7aa5501
7 changed files with 333 additions and 320 deletions
+2 -3
View File
@@ -51,12 +51,11 @@ public sealed class SettingsWindow : Dalamud.Interface.Windowing.Window
[
new General(Plugin, Mutable),
new Appearance(Plugin, Mutable, loggerFactory.CreateLogger<Appearance>()),
new SettingsTabs.Window(Plugin, Mutable),
new Chat(Plugin, Mutable),
new SettingsTabs.Window(Plugin, Mutable),
new SettingsTabs.Tabs(Plugin, Mutable),
new DataAndPrivacy(Plugin, Mutable, loggerFactory.CreateLogger<DataAndPrivacy>()),
new SettingsTabs.Integrations(Plugin, Mutable),
new About(Mutable),
new About(Plugin, Mutable),
];
RespectCloseHotkey = false;
+5 -10
View File
@@ -24,16 +24,16 @@ internal sealed class SettingsOverview
HellionStrings.Settings_Card_Appearance_Title,
HellionStrings.Settings_Card_Appearance_Subtext
),
(
FontAwesomeIcon.WindowMaximize,
HellionStrings.Settings_Card_Window_Title,
HellionStrings.Settings_Card_Window_Subtext
),
(
FontAwesomeIcon.Comments,
HellionStrings.Settings_Card_Chat_Title,
HellionStrings.Settings_Card_Chat_Subtext
),
(
FontAwesomeIcon.WindowMaximize,
HellionStrings.Settings_Card_Window_Title,
HellionStrings.Settings_Card_Window_Subtext
),
(
FontAwesomeIcon.FolderTree,
HellionStrings.Settings_Card_Tabs_Title,
@@ -44,11 +44,6 @@ internal sealed class SettingsOverview
HellionStrings.Settings_Card_DataManagement_Title,
HellionStrings.Settings_Card_DataManagement_Subtext
),
(
FontAwesomeIcon.Plug,
HellionStrings.Settings_Card_Integrations_Title,
HellionStrings.Settings_Card_Integrations_Subtext
),
(
FontAwesomeIcon.InfoCircle,
HellionStrings.Settings_Card_Information_Title,
+298 -56
View File
@@ -5,14 +5,17 @@ using Dalamud.Interface.Colors;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using HellionChat.Branding;
using HellionChat.Integrations;
using HellionChat.Resources;
using HellionChat.Util;
namespace HellionChat.Ui.SettingsTabs;
// Combines the former About and Changelog tabs into three collapsible sections.
// The About tab absorbs the former Integrations tab (now the first section)
// and organises its remaining content into four thematic sections.
internal sealed class About : ISettingsTab
{
private Plugin Plugin { get; }
private Configuration Mutable { get; }
public string Name => HellionStrings.Settings_Tab_Information + "###tabs-information";
@@ -47,8 +50,9 @@ internal sealed class About : ISettingsTab
"Sirayuki",
];
internal About(Configuration mutable)
internal About(Plugin plugin, Configuration mutable)
{
Plugin = plugin;
Mutable = mutable;
Translators.Sort(
(a, b) =>
@@ -60,16 +64,270 @@ internal sealed class About : ISettingsTab
{
using var wrap = ImRaii.TextWrapPos(0.0f);
DrawHellionForgeSection();
DrawExtensionsSection(sectionJustEntered);
ImGui.Spacing();
DrawVersionInfoSection();
DrawPluginInfoSection(sectionJustEntered);
ImGui.Spacing();
DrawAboutSection();
DrawProjectSection(sectionJustEntered);
ImGui.Spacing();
DrawChangelogSection();
DrawTranslatorsSection(sectionJustEntered);
ImGui.Spacing();
DrawChangelogSection(sectionJustEntered);
}
private void DrawHellionForgeSection()
// ── Extensions ──────────────────────────────────────────────────────────
private void DrawExtensionsSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Extensions);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
ImGui.TextWrapped(HellionStrings.Settings_Integrations_Intro);
ImGui.Spacing();
ImGui.Spacing();
DrawHonorificSection();
ImGui.Spacing();
ImGui.Spacing();
DrawComingSoonSection();
ImGui.Spacing();
ImGui.Spacing();
DrawGotAnIdeaSection();
}
}
private void DrawHonorificSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_Honorific_SectionHeader);
DrawHonorificStatus();
ImGui.Spacing();
// Toggle works regardless of detection state: "show when available,
// hide otherwise". Disabling it when Honorific is missing would force
// the user to retoggle on every reload.
if (
ImGui.Checkbox(
HellionStrings.Settings_Integrations_Honorific_Toggle,
ref Mutable.ShowHonorificTitleInHeader
)
)
{
Plugin.SaveConfig();
}
using (ImRaii.PushIndent())
{
using (
ImRaii.PushColor(
ImGuiCol.Text,
ColourUtil.RgbaToAbgr(Plugin.ThemeRegistry.Active.Colors.TextMuted)
)
)
{
ImGui.TextWrapped(HellionStrings.Settings_Integrations_Honorific_ToggleHint);
}
if (
ImGui.Checkbox(
HellionStrings.Settings_Integrations_Honorific_Glow_Toggle,
ref Mutable.ShowHonorificGlow
)
)
{
Plugin.SaveConfig();
}
ImGuiUtil.HelpMarker(HellionStrings.Settings_Integrations_Honorific_Glow_Hint);
}
// Honorific has no LICENSE in its repo so we link upstream and author
// instead of bundling assets. Text labels because FA Brands isn't
// guaranteed in Dalamud's font set.
ImGui.Spacing();
if (ImGui.Button(HellionStrings.Settings_Integrations_Honorific_LinkRepo))
{
Plugin.PlatformUtil.OpenLink(IntegrationLinks.HonorificRepo);
}
ImGui.SameLine();
if (ImGui.Button(HellionStrings.Settings_Integrations_Honorific_LinkAuthor))
{
Plugin.PlatformUtil.OpenLink(IntegrationLinks.HonorificAuthor);
}
}
private void DrawHonorificStatus()
{
var theme = Plugin.ThemeRegistry.Active;
var service = Plugin.HonorificService;
if (service.IsAvailable && service.DetectedApiVersion is { } version)
{
DrawStatusGlyph('●', theme.Colors.StatusSuccess);
ImGui.SameLine();
ImGui.TextUnformatted(
string.Format(
HellionStrings.Settings_Integrations_Honorific_Status_Detected,
version.Major,
version.Minor
)
);
}
else if (service.DetectedApiVersion is { } incompatibleVersion)
{
DrawStatusGlyph('⚠', theme.Colors.StatusWarning);
ImGui.SameLine();
ImGui.TextUnformatted(
string.Format(
HellionStrings.Settings_Integrations_Honorific_Status_Incompatible,
HonorificService.ExpectedApiMajor,
incompatibleVersion.Major,
incompatibleVersion.Minor
)
);
}
else
{
DrawStatusGlyph('○', theme.Colors.TextMuted);
ImGui.SameLine();
ImGui.TextUnformatted(
HellionStrings.Settings_Integrations_Honorific_Status_NotInstalled
);
}
}
private static void DrawStatusGlyph(char glyph, uint rgba)
{
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(rgba)))
{
ImGui.TextUnformatted(glyph.ToString());
}
}
private void DrawComingSoonSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_ComingSoon_SectionHeader);
ImGui.TextWrapped(HellionStrings.Settings_Integrations_ComingSoon_Intro);
ImGui.Spacing();
// Each integration cycle removes its stub here and adds a full section above.
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)
{
var theme = Plugin.ThemeRegistry.Active;
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.TextMuted)))
using (Plugin.FontManager.FontAwesome.Push())
{
ImGui.TextUnformatted(FontAwesomeIcon.Hourglass.ToIconString());
}
ImGui.SameLine();
ImGui.TextUnformatted(title);
using (ImRaii.PushIndent())
{
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.TextMuted)))
{
ImGui.TextWrapped(description);
}
}
ImGui.Spacing();
}
private void DrawGotAnIdeaSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_GotAnIdea_SectionHeader);
ImGui.TextWrapped(HellionStrings.Settings_Integrations_GotAnIdea_Body);
ImGui.Spacing();
if (ImGui.Button(HellionStrings.Settings_Integrations_GotAnIdea_LinkLabel))
{
Plugin.PlatformUtil.OpenLink(BrandingLinks.HellionForgeDiscordInvite);
}
}
private void DrawSectionHeader(string label)
{
var theme = Plugin.ThemeRegistry.Active;
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.Primary)))
{
ImGui.TextUnformatted("── " + label + " ──");
}
}
// ── Plugin info ──────────────────────────────────────────────────────────
private void DrawPluginInfoSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_PluginInfo);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
DrawFoxBanner();
ImGuiHelpers.ScaledDummy(6.0f);
ImGui.TextUnformatted(string.Format(Language.Options_About_Opening, Plugin.PluginName));
ImGuiHelpers.ScaledDummy(10.0f);
ImGui.TextUnformatted(Language.Options_About_Authors);
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGold, Plugin.Interface.Manifest.Author);
ImGui.TextUnformatted(Language.Options_About_Discord);
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGold, "@j.j_kazama");
ImGui.TextUnformatted(Language.Options_About_Version);
ImGui.SameLine();
ImGui.TextColored(
ImGuiColors.ParsedOrange,
Plugin.Interface.Manifest.AssemblyVersion.ToString(3)
);
ImGuiHelpers.ScaledDummy(10.0f);
ImGui.TextUnformatted(Language.Options_About_Github_Issues);
ImGui.SameLine();
if (ImGuiUtil.IconButton(FontAwesomeIcon.ExternalLinkAlt, "githubIssues"))
Plugin.PlatformUtil.OpenLink(
"https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues"
);
}
}
private void DrawFoxBanner()
{
var banner = FoxBannerTexture.Shared.GetWrapOrDefault();
if (banner is null)
@@ -103,47 +361,14 @@ internal sealed class About : ISettingsTab
ImGui.Dummy(new Vector2(cardWidth, cardHeight));
}
private void DrawVersionInfoSection()
// ── The Project ──────────────────────────────────────────────────────────
private void DrawProjectSection(bool sectionJustEntered)
{
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Information_VersionInfo_Heading);
if (!tree.Success)
return;
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
ImGui.TextUnformatted(string.Format(Language.Options_About_Opening, Plugin.PluginName));
ImGuiHelpers.ScaledDummy(10.0f);
ImGui.TextUnformatted(Language.Options_About_Authors);
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGold, Plugin.Interface.Manifest.Author);
ImGui.TextUnformatted(Language.Options_About_Discord);
ImGui.SameLine();
ImGui.TextColored(ImGuiColors.ParsedGold, "@j.j_kazama");
ImGui.TextUnformatted(Language.Options_About_Version);
ImGui.SameLine();
ImGui.TextColored(
ImGuiColors.ParsedOrange,
Plugin.Interface.Manifest.AssemblyVersion.ToString(3)
);
ImGuiHelpers.ScaledDummy(10.0f);
ImGui.TextUnformatted(Language.Options_About_Github_Issues);
ImGui.SameLine();
if (ImGuiUtil.IconButton(FontAwesomeIcon.ExternalLinkAlt, "githubIssues"))
Plugin.PlatformUtil.OpenLink(
"https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/issues"
);
}
}
private void DrawAboutSection()
{
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Information_About_Heading);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Project);
if (!tree.Success)
return;
@@ -195,24 +420,41 @@ internal sealed class About : ISettingsTab
ImGui.TextColored(ImGuiColors.ParsedGold, HellionStrings.About_Localization_Heading);
ImGui.TextUnformatted(HellionStrings.About_Localization_P1);
ImGui.TextUnformatted(HellionStrings.About_Localization_P2);
}
}
ImGui.Spacing();
// ── Translators ──────────────────────────────────────────────────────────
using (var translatorTree = ImRaii.TreeNode(HellionStrings.About_Translators_TreeNode))
private void DrawTranslatorsSection(bool sectionJustEntered)
{
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Translators);
if (!tree.Success)
return;
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
{
// The translator list belongs to the Chat 2 upstream Crowdin project.
using var translatorTree = ImRaii.TreeNode(HellionStrings.About_Translators_TreeNode);
if (translatorTree)
{
if (translatorTree)
{
using var indent = ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false);
foreach (var translator in Translators)
ImGui.TextUnformatted(translator);
}
using var indent = ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false);
foreach (var translator in Translators)
ImGui.TextUnformatted(translator);
}
}
}
private void DrawChangelogSection()
// ── Changelog ────────────────────────────────────────────────────────────
private void DrawChangelogSection(bool sectionJustEntered)
{
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Information_Changelog_Heading);
if (sectionJustEntered)
ImGui.SetNextItemOpen(false);
using var tree = ImRaii.TreeNode(HellionStrings.Settings_Section_Changelog);
if (!tree.Success)
return;
-219
View File
@@ -1,219 +0,0 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii;
using HellionChat.Branding;
using HellionChat.Integrations;
using HellionChat.Resources;
using HellionChat.Util;
namespace HellionChat.Ui.SettingsTabs;
// Added in v1.3.0. Each future integration cycle adds a section above
// the "Coming soon" block and removes its stub item.
internal sealed class Integrations : ISettingsTab
{
private Plugin Plugin { get; }
private Configuration Mutable { get; }
public string Name => HellionStrings.Settings_Tab_Integrations + "###tabs-integrations";
internal Integrations(Plugin plugin, Configuration mutable)
{
Plugin = plugin;
Mutable = mutable;
}
public void Draw(bool sectionJustEntered)
{
ImGui.TextWrapped(HellionStrings.Settings_Integrations_Intro);
ImGui.Spacing();
ImGui.Spacing();
DrawHonorificSection();
ImGui.Spacing();
ImGui.Spacing();
DrawComingSoonSection();
ImGui.Spacing();
ImGui.Spacing();
DrawGotAnIdeaSection();
}
private void DrawHonorificSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_Honorific_SectionHeader);
DrawHonorificStatus();
ImGui.Spacing();
// Toggle works regardless of detection state: "show when available,
// hide otherwise". Disabling it when Honorific is missing would force
// the user to retoggle on every reload.
if (
ImGui.Checkbox(
HellionStrings.Settings_Integrations_Honorific_Toggle,
ref Mutable.ShowHonorificTitleInHeader
)
)
{
Plugin.SaveConfig();
}
using (ImRaii.PushIndent())
{
using (
ImRaii.PushColor(
ImGuiCol.Text,
ColourUtil.RgbaToAbgr(Plugin.ThemeRegistry.Active.Colors.TextMuted)
)
)
{
ImGui.TextWrapped(HellionStrings.Settings_Integrations_Honorific_ToggleHint);
}
if (
ImGui.Checkbox(
HellionStrings.Settings_Integrations_Honorific_Glow_Toggle,
ref Mutable.ShowHonorificGlow
)
)
{
Plugin.SaveConfig();
}
ImGuiUtil.HelpMarker(HellionStrings.Settings_Integrations_Honorific_Glow_Hint);
}
// Honorific has no LICENSE in its repo so we link upstream and author
// instead of bundling assets. Text labels because FA Brands isn't
// guaranteed in Dalamud's font set.
ImGui.Spacing();
if (ImGui.Button(HellionStrings.Settings_Integrations_Honorific_LinkRepo))
{
Plugin.PlatformUtil.OpenLink(IntegrationLinks.HonorificRepo);
}
ImGui.SameLine();
if (ImGui.Button(HellionStrings.Settings_Integrations_Honorific_LinkAuthor))
{
Plugin.PlatformUtil.OpenLink(IntegrationLinks.HonorificAuthor);
}
}
private void DrawHonorificStatus()
{
var theme = Plugin.ThemeRegistry.Active;
var service = Plugin.HonorificService;
if (service.IsAvailable && service.DetectedApiVersion is { } version)
{
DrawStatusGlyph('●', theme.Colors.StatusSuccess);
ImGui.SameLine();
ImGui.TextUnformatted(
string.Format(
HellionStrings.Settings_Integrations_Honorific_Status_Detected,
version.Major,
version.Minor
)
);
}
else if (service.DetectedApiVersion is { } incompatibleVersion)
{
DrawStatusGlyph('⚠', theme.Colors.StatusWarning);
ImGui.SameLine();
ImGui.TextUnformatted(
string.Format(
HellionStrings.Settings_Integrations_Honorific_Status_Incompatible,
HonorificService.ExpectedApiMajor,
incompatibleVersion.Major,
incompatibleVersion.Minor
)
);
}
else
{
DrawStatusGlyph('○', theme.Colors.TextMuted);
ImGui.SameLine();
ImGui.TextUnformatted(
HellionStrings.Settings_Integrations_Honorific_Status_NotInstalled
);
}
}
private static void DrawStatusGlyph(char glyph, uint rgba)
{
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(rgba)))
{
ImGui.TextUnformatted(glyph.ToString());
}
}
private void DrawComingSoonSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_ComingSoon_SectionHeader);
ImGui.TextWrapped(HellionStrings.Settings_Integrations_ComingSoon_Intro);
ImGui.Spacing();
// Each integration cycle removes its stub here and adds a full section above.
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)
{
var theme = Plugin.ThemeRegistry.Active;
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.TextMuted)))
using (Plugin.FontManager.FontAwesome.Push())
{
ImGui.TextUnformatted(FontAwesomeIcon.Hourglass.ToIconString());
}
ImGui.SameLine();
ImGui.TextUnformatted(title);
using (ImRaii.PushIndent())
{
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.TextMuted)))
{
ImGui.TextWrapped(description);
}
}
ImGui.Spacing();
}
private void DrawGotAnIdeaSection()
{
DrawSectionHeader(HellionStrings.Settings_Integrations_GotAnIdea_SectionHeader);
ImGui.TextWrapped(HellionStrings.Settings_Integrations_GotAnIdea_Body);
ImGui.Spacing();
if (ImGui.Button(HellionStrings.Settings_Integrations_GotAnIdea_LinkLabel))
{
Plugin.PlatformUtil.OpenLink(BrandingLinks.HellionForgeDiscordInvite);
}
}
private void DrawSectionHeader(string label)
{
var theme = Plugin.ThemeRegistry.Active;
using (ImRaii.PushColor(ImGuiCol.Text, ColourUtil.RgbaToAbgr(theme.Colors.Primary)))
{
ImGui.TextUnformatted("── " + label + " ──");
}
}
}