diff --git a/.github/forge-posts/v1.4.6.md b/.github/forge-posts/v1.4.6.md index 040e7b4..0285ae2 100644 --- a/.github/forge-posts/v1.4.6.md +++ b/.github/forge-posts/v1.4.6.md @@ -13,5 +13,6 @@ Wartungs-Patch ohne User-sichtbare Änderungen. Saubere Code-Basis als Vorbereit - **Aktive-Tab-Underline pixel-perfect bei DPI-Scaling**: Die Underline-Pill skaliert jetzt mit `ImGuiHelpers.GlobalScale` und rundet die DrawList-Koordinaten auf physische Pixel. Kein Sub-Pixel-Blur mehr auf 125/150%-Setups. - **IconButton-Width-Fix**: der manuelle `width - 2 * CellPadding.X`-Subtract verlor den HUD-Scale (Padding skaliert, der raw int nicht). Gemessene Breite läuft jetzt unverändert durch. - **Test-Isolation für MessageStore**: `Dalamud.Utility.Util`-Surface (IsWine, OpenLink) läuft jetzt durch eine `IPlatformUtil`-Indirektion. MessageStores `IsWine`-Probe ist isoliert testbar in der Build-Suite. Plus: HellionStyle-ChildBgAlpha als Pure-Helper extrahiert, Plugin.SaveConfig kopiert nur Session-Tabs statt der ganzen Tab-Liste, SettingsOverview cached den DrawList einmal pro Frame. +- **Built-in-Theme-Roster**: Crystal Nocturne (Royal Sapphire + Electric Magenta auf Obsidian, von CRYSTALLITE) ersetzt Moonlit Bloom. User mit Moonlit Bloom als aktivem Theme fallen beim ersten Plugin-Load auf Hellion Arctic zurück. Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2). diff --git a/HellionChat/HellionChat.yaml b/HellionChat/HellionChat.yaml index db7db94..549b301 100755 --- a/HellionChat/HellionChat.yaml +++ b/HellionChat/HellionChat.yaml @@ -65,6 +65,10 @@ changelog: |- Dalamud.Utility.Util surface routed through an IPlatformUtil indirection (MessageStore IsWine probe is now testable in isolation) + - Built-in themes: Crystal Nocturne (sapphire and electric + magenta over obsidian, by CRYSTALLITE) replaces Moonlit Bloom. + Users with Moonlit Bloom selected fall back to Hellion Arctic + on first load Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2). diff --git a/HellionChat/Themes/Builtin/CrystalNocturne.cs b/HellionChat/Themes/Builtin/CrystalNocturne.cs new file mode 100644 index 0000000..ad7cf5f --- /dev/null +++ b/HellionChat/Themes/Builtin/CrystalNocturne.cs @@ -0,0 +1,82 @@ +using HellionChat.Util; + +namespace HellionChat.Themes.Builtin; + +internal static class CrystalNocturne +{ + public const string Slug = "crystal-nocturne"; + + public static Theme Build() => + new( + Slug: Slug, + Name: "Crystal Nocturne", + Author: "CRYSTALLITE", + Description: "Royal sapphire and electric magenta over obsidian — a nocturne for the crystal-lit dance floor.", + Colors: new ThemeColors( + PrimaryDark: ColourUtil.HexToRgba("#1D4ED8"), + Primary: ColourUtil.HexToRgba("#3B82F6"), + PrimaryLight: ColourUtil.HexToRgba("#93C5FD"), + PrimaryGlow: ColourUtil.HexToRgba("#3B82F699"), + AccentDark: ColourUtil.HexToRgba("#A21CAF"), + Accent: ColourUtil.HexToRgba("#D946EF"), + AccentLight: ColourUtil.HexToRgba("#F0ABFC"), + Identity: ColourUtil.HexToRgba("#3B82F6"), + WindowBg: ColourUtil.HexToRgba("#08070F"), + ChildBg: ColourUtil.HexToRgba("#11101F"), + FrameBg: ColourUtil.HexToRgba("#1C1A33"), + Surface: ColourUtil.HexToRgba("#262340"), + SurfaceHover: ColourUtil.HexToRgba("#332D55"), + Border: ColourUtil.HexToRgba("#D946EF55"), + TextPrimary: ColourUtil.HexToRgba("#F5F3FF"), + TextMuted: ColourUtil.HexToRgba("#A5A0C0"), + TextDim: ColourUtil.HexToRgba("#4B4763"), + StatusSuccess: ColourUtil.HexToRgba("#10B981"), + StatusDanger: ColourUtil.HexToRgba("#F43F5E"), + StatusWarning: ColourUtil.HexToRgba("#FACC15"), + StatusInfo: ColourUtil.HexToRgba("#3B82F6") + ), + Layout: new ThemeLayout( + WindowRounding: 2f, + ChildRounding: 1f, + PopupRounding: 2f, + FrameRounding: 1f, + GrabRounding: 1f, + TabRounding: 1f, + ScrollbarRounding: 2f, + WindowBorderSize: 1f, + FrameBorderSize: 1f + ), + Typography: new ThemeTypography(), + IsBuiltIn: true, + ChatColors: new ThemeChatColors( + new Dictionary + { + // Crystal Nocturne — sapphire-blue identity for party/team channels, + // accent-magenta for tells, with mint/peach accents on linkshells + // so the eight LS slots stay individually distinguishable on the + // dark obsidian background. + [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#F5F3FF"), + [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#FACC15"), + [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#F0B090"), + [HellionChat.Code.ChatType.TellIncoming] = ColourUtil.HexToRgba("#F0ABFC"), + [HellionChat.Code.ChatType.TellOutgoing] = ColourUtil.HexToRgba("#F0ABFC"), + [HellionChat.Code.ChatType.Party] = ColourUtil.HexToRgba("#93C5FD"), + [HellionChat.Code.ChatType.Alliance] = ColourUtil.HexToRgba("#F0B090"), + [HellionChat.Code.ChatType.FreeCompany] = ColourUtil.HexToRgba("#A8C8E8"), + [HellionChat.Code.ChatType.NoviceNetwork] = ColourUtil.HexToRgba("#10B981"), + [HellionChat.Code.ChatType.CrossParty] = ColourUtil.HexToRgba("#93C5FD"), + [HellionChat.Code.ChatType.Linkshell1] = ColourUtil.HexToRgba("#10B981"), + [HellionChat.Code.ChatType.Linkshell2] = ColourUtil.HexToRgba("#FACC15"), + [HellionChat.Code.ChatType.Linkshell3] = ColourUtil.HexToRgba("#F0ABFC"), + [HellionChat.Code.ChatType.Linkshell4] = ColourUtil.HexToRgba("#93C5FD"), + [HellionChat.Code.ChatType.Linkshell5] = ColourUtil.HexToRgba("#F0B090"), + [HellionChat.Code.ChatType.Linkshell6] = ColourUtil.HexToRgba("#A5A0C0"), + [HellionChat.Code.ChatType.Linkshell7] = ColourUtil.HexToRgba("#D946EF"), + [HellionChat.Code.ChatType.Linkshell8] = ColourUtil.HexToRgba("#3B82F6"), + [HellionChat.Code.ChatType.CustomEmote] = ColourUtil.HexToRgba("#F0B090"), + [HellionChat.Code.ChatType.StandardEmote] = ColourUtil.HexToRgba("#F0B090"), + [HellionChat.Code.ChatType.Echo] = ColourUtil.HexToRgba("#A5A0C0"), + } + ) + ); +} diff --git a/HellionChat/Themes/Builtin/MoonlitBloom.cs b/HellionChat/Themes/Builtin/MoonlitBloom.cs deleted file mode 100644 index 544bb02..0000000 --- a/HellionChat/Themes/Builtin/MoonlitBloom.cs +++ /dev/null @@ -1,80 +0,0 @@ -using HellionChat.Util; - -namespace HellionChat.Themes.Builtin; - -internal static class MoonlitBloom -{ - public const string Slug = "moonlit-bloom"; - - public static Theme Build() => - new( - Slug: Slug, - Name: "Moonlit Bloom", - Author: "Hellion Forge", - Description: "Bloom Magenta + Soft Sage auf Deep Violet Night.", - Colors: new ThemeColors( - PrimaryDark: ColourUtil.HexToRgba("#C957D0"), - Primary: ColourUtil.HexToRgba("#E374E8"), - PrimaryLight: ColourUtil.HexToRgba("#EF8AF4"), - PrimaryGlow: ColourUtil.HexToRgba("#E374E899"), - AccentDark: ColourUtil.HexToRgba("#7AAC5C"), - Accent: ColourUtil.HexToRgba("#9CCB7C"), - AccentLight: ColourUtil.HexToRgba("#B6E297"), - Identity: ColourUtil.HexToRgba("#E374E8"), - WindowBg: ColourUtil.HexToRgba("#0E0C1F"), - ChildBg: ColourUtil.HexToRgba("#15122B"), - FrameBg: ColourUtil.HexToRgba("#1F1A38"), - Surface: ColourUtil.HexToRgba("#28224A"), - SurfaceHover: ColourUtil.HexToRgba("#332B5B"), - Border: ColourUtil.HexToRgba("#E374E844"), - TextPrimary: ColourUtil.HexToRgba("#ECE6F5"), - TextMuted: ColourUtil.HexToRgba("#9A8BB0"), - TextDim: ColourUtil.HexToRgba("#554B6E"), - StatusSuccess: ColourUtil.HexToRgba("#7AAC5C"), - StatusDanger: ColourUtil.HexToRgba("#E85C6A"), - StatusWarning: ColourUtil.HexToRgba("#E8B590"), - StatusInfo: ColourUtil.HexToRgba("#6278FF") - ), - Layout: new ThemeLayout( - WindowRounding: 6f, - ChildRounding: 5f, - PopupRounding: 5f, - FrameRounding: 4f, - GrabRounding: 4f, - TabRounding: 4f, - ScrollbarRounding: 4f, - WindowBorderSize: 1f, - FrameBorderSize: 1f - ), - Typography: new ThemeTypography(), - IsBuiltIn: true, - ChatColors: new ThemeChatColors( - new Dictionary - { - // Moonlit Bloom — Bloom-Magenta-Tönung. Sage-Drift in NoviceNetwork - // und Linkshell4. Tell-Pink-Identität bleibt sichtbar. - [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#ECE6F5"), - [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#F0D080"), - [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#F09A60"), - [HellionChat.Code.ChatType.TellIncoming] = ColourUtil.HexToRgba("#EF8AF4"), - [HellionChat.Code.ChatType.TellOutgoing] = ColourUtil.HexToRgba("#EF8AF4"), - [HellionChat.Code.ChatType.Party] = ColourUtil.HexToRgba("#A0B0F0"), - [HellionChat.Code.ChatType.Alliance] = ColourUtil.HexToRgba("#F0B090"), - [HellionChat.Code.ChatType.FreeCompany] = ColourUtil.HexToRgba("#A8C8E8"), - [HellionChat.Code.ChatType.NoviceNetwork] = ColourUtil.HexToRgba("#9CCB7C"), - [HellionChat.Code.ChatType.CrossParty] = ColourUtil.HexToRgba("#A0B0F0"), - [HellionChat.Code.ChatType.Linkshell1] = ColourUtil.HexToRgba("#9CCB7C"), - [HellionChat.Code.ChatType.Linkshell2] = ColourUtil.HexToRgba("#F0BC92"), - [HellionChat.Code.ChatType.Linkshell3] = ColourUtil.HexToRgba("#F0D080"), - [HellionChat.Code.ChatType.Linkshell4] = ColourUtil.HexToRgba("#B6E297"), - [HellionChat.Code.ChatType.Linkshell5] = ColourUtil.HexToRgba("#A0B0F0"), - [HellionChat.Code.ChatType.Linkshell6] = ColourUtil.HexToRgba("#C098D8"), - [HellionChat.Code.ChatType.Linkshell7] = ColourUtil.HexToRgba("#EF8AF4"), - [HellionChat.Code.ChatType.Linkshell8] = ColourUtil.HexToRgba("#E8B0E8"), - [HellionChat.Code.ChatType.CustomEmote] = ColourUtil.HexToRgba("#E8B590"), - [HellionChat.Code.ChatType.StandardEmote] = ColourUtil.HexToRgba("#E8B590"), - [HellionChat.Code.ChatType.Echo] = ColourUtil.HexToRgba("#9A8BB0"), - } - ) - ); -} diff --git a/HellionChat/Themes/ThemeRegistry.cs b/HellionChat/Themes/ThemeRegistry.cs index ac26dd7..53b4610 100644 --- a/HellionChat/Themes/ThemeRegistry.cs +++ b/HellionChat/Themes/ThemeRegistry.cs @@ -15,17 +15,21 @@ public sealed class ThemeRegistry public ThemeRegistry(string? customThemesDir = null) { + // Insertion order drives the Theme-Picker grid layout (3 columns). + // Row 1: blue family. Row 2: purple to magenta family. + // Row 3: green / warm / classic. Row 4: Synthwave Sunset as a + // retro bonus on its own line. _builtIns = new Dictionary(StringComparer.OrdinalIgnoreCase) { { HellionArctic.Slug, HellionArctic.Build() }, { HellionSpectrum.Slug, HellionSpectrum.Build() }, - { Chat2Classic.Slug, Chat2Classic.Build() }, - { EventHorizon.Slug, EventHorizon.Build() }, - { MoonlitBloom.Slug, MoonlitBloom.Build() }, { NightBlue.Slug, NightBlue.Build() }, + { EventHorizon.Slug, EventHorizon.Build() }, { IndigoViolet.Slug, IndigoViolet.Build() }, - { ForgeMerchantman.Slug, ForgeMerchantman.Build() }, + { CrystalNocturne.Slug, CrystalNocturne.Build() }, { MintGrove.Slug, MintGrove.Build() }, + { ForgeMerchantman.Slug, ForgeMerchantman.Build() }, + { Chat2Classic.Slug, Chat2Classic.Build() }, { SynthwaveSunset.Slug, SynthwaveSunset.Build() }, }; diff --git a/README.md b/README.md index 7ddf9cc..46ddd17 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Hellion Chat is developed under **Hellion Forge**, the specialized modding and p #### Custom Themes (v1.1.0) HellionChat ships a theme engine with ten built-in themes (Hellion Arctic, Hellion Spectrum, Chat 2 Classic, Event -Horizon, Moonlit Bloom, Mint Grove, Night Blue, Indigo Violet, Forge Merchantman, Synthwave Sunset) and a JSON-based +Horizon, Crystal Nocturne, Mint Grove, Night Blue, Indigo Violet, Forge Merchantman, Synthwave Sunset) and a JSON-based authoring format for custom themes. Schema and step-by-step guide in [`docs/THEME-AUTHORING.md`](docs/THEME-AUTHORING.md). Hellion Spectrum is Deuteranopia/Protanopia-safe (red-green color blindness) based on the Wong/Okabe-Ito palette. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index b4b70ea..2374956 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -47,6 +47,10 @@ upstream-inherited bugs from ChatTwo `f35b7d3`, and prepares the code for the v1 indirection. `MessageStore`'s `IsWine` probe is now reachable from the xUnit AppDomain via a `FakePlatformUtil` fixture (full isolated MessageStore construction still pending — `Plugin.Log.Information` in `Migrate0` is a separate Dalamud-static surface, slated for v1.4.7) +- Built-in themes: Crystal Nocturne (royal sapphire and electric magenta over obsidian, by CRYSTALLITE) replaces + Moonlit Bloom in the built-in roster. Users who had Moonlit Bloom selected fall back to the default Hellion Arctic + on the first plugin load; an existing custom JSON copy of Moonlit Bloom under `pluginConfigs/HellionChat/themes/` + keeps working unchanged Modding & support: join Hellion Forge — diff --git a/docs/THEME-AUTHORING.md b/docs/THEME-AUTHORING.md index 9fcee0c..5520b67 100644 --- a/docs/THEME-AUTHORING.md +++ b/docs/THEME-AUTHORING.md @@ -141,7 +141,7 @@ A theme can tint these toward its brand family (e.g., a purple theme can shift T **don't** flip them (Tell suddenly green, Yell suddenly cyan). RP groups and combat-spec setups depend on the visual hierarchy. -The eight colored built-in themes (Hellion Arctic, Hellion Spectrum, Event Horizon, Moonlit Bloom, Mint Grove, Night +The eight colored built-in themes (Hellion Arctic, Hellion Spectrum, Event Horizon, Crystal Nocturne, Mint Grove, Night Blue, Indigo Violet, Forge Merchantman) all follow this rule — read their source for reference. Chat 2 Klassik intentionally ships without `chatChannels` so the user keeps their existing picks. diff --git a/repo.json b/repo.json index 6910163..81b8df0 100644 --- a/repo.json +++ b/repo.json @@ -14,7 +14,7 @@ "CanUnloadAsync": false, "LoadPriority": 0, "Punchline": "A Hellion Forge plugin. Privacy-first chat for FFXIV, built to stay out of your way.", - "Changelog": "**v1.4.6 — Code Hygiene and Refactor (2026-05-12)**\n\nMaintenance patch. No user-visible behaviour changes; tightens the development feedback loop, fixes two upstream-inherited bugs, and prepares the code for the v1.4.7 backlog cleanup.\n\n- preflight.sh gains a csharpier reflow check and a markdownlint pass so style drift and markdown violations are caught at the pre-push gate\n- FontManager fallback catches the full set of atlas-toolkit throws (IO, InvalidOperation, ArgumentException) — a corrupt font config no longer takes down the whole atlas build\n- BrandingLinks and IntegrationLinks URLs validated on plugin load — a typo in a future URL rotation now throws at startup\n- Cherry-picked from ChatTwo upstream f35b7d3: Chat.SetChannel no longer leaks the native Utf8String when the linkshell check rejects the channel\n- Cherry-picked from ChatTwo upstream f35b7d3: Tab.Clone now deep-clones UsedChannel and TellTarget — PopOut and Temp tabs no longer mutate each other's channel state\n- Active-tab underline scales with DPI and rounds to physical pixels for crisp rendering above 100% scaling\n- IconButton width parameter no longer subtracts HUD-scaled padding from a raw int (measured width passes through verbatim)\n- Internal: HellionStyle ChildBgAlpha extracted to a testable helper; Plugin.SaveConfig clones only the temp tabs; SettingsOverview caches the draw-list per frame; Dalamud.Utility.Util surface routed through an IPlatformUtil indirection (MessageStore IsWine probe is now testable in isolation)\n\nBased on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).\n\n---\n\n**v1.4.5 — UX and Robustness (2026-05-12)**\n\nSixth sub-patch of the v1.4.x polish-sweep series. Chat-log draw failures surface as a notification, the first-run wizard has an explicit Later option, the input history clears on plugin reload, and the status bar version slot stops clipping in narrow windows.\n\n- Chat window draw errors now show a one-shot notification instead of failing silently — stack trace stays in /xllog\n- First-run wizard: explicit \"Later — keep defaults\" button. Closing the X no longer silently accepts the defaults; the wizard reopens on the next plugin load if nothing was picked\n- InputHistoryService clears on plugin dispose so the previous session's typed commands don't bleed into the next load\n- Status bar hides the version slot when the chat window is too narrow to fit all five slots without overlap\n- Internal: explicit session-only Auto-Tell-Tab invariant in Plugin.cs plus a pinning test in the Build-Suite\n- Internal: FontManager falls back to the system font if the embedded Hellion font resource is missing — logs a Warning\n\n---\n\n**v1.4.4 — Threading and IPC safety polish (2026-05-12)**\n\nFifth sub-patch of the v1.4.x polish-sweep series. Threading assumptions are documented per-method, a hot-path lock falls away, and the privacy filter speaks up when an unknown ChatType shows up.\n\n- AutoTellTabs hot-path getter uses an Interlocked counter instead of taking the lock on every read\n- Honorific integration: per-method threading banners, plus Warning-level log on unsubscribe failure\n- AutoTranslate warmup thread marked IsBackground so plugin unload doesn't wait for it\n- PrivacyFilter logs once per unknown ChatType so a future patch's added channel doesn't drop off the radar\n- New installs persist unknown channels by default; existing configs keep their explicit choice\n\n---\n\n**v1.4.3 — Faster plugin load + new repo (2026-05-08)**\n\nHeavy startup work (migrations, hooks, windows) now runs async so Dalamud's UI stays responsive during load. Load time is comparable to v1.4.2 — this is the foundation for v1.4.4 optimisations.\n\n- Two-phase async load via IAsyncDalamudPlugin\n- Schema-gate replaces the v9→v16 migration chain; old configs require a v1.4.2 install first\n- AutoTranslate cache loads on first use instead of every startup\n- Custom font (Hellion-Exo2) appears with a brief pop after load\n- Repo moved to gitea.hellion-forge.cloud — update your custom-repo URL\n\n---\n\nFull history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases", + "Changelog": "**v1.4.6 — Code Hygiene and Refactor (2026-05-12)**\n\nMaintenance patch. No user-visible behaviour changes; tightens the development feedback loop, fixes two upstream-inherited bugs, and prepares the code for the v1.4.7 backlog cleanup.\n\n- preflight.sh gains a csharpier reflow check and a markdownlint pass so style drift and markdown violations are caught at the pre-push gate\n- FontManager fallback catches the full set of atlas-toolkit throws (IO, InvalidOperation, ArgumentException) — a corrupt font config no longer takes down the whole atlas build\n- BrandingLinks and IntegrationLinks URLs validated on plugin load — a typo in a future URL rotation now throws at startup\n- Cherry-picked from ChatTwo upstream f35b7d3: Chat.SetChannel no longer leaks the native Utf8String when the linkshell check rejects the channel\n- Cherry-picked from ChatTwo upstream f35b7d3: Tab.Clone now deep-clones UsedChannel and TellTarget — PopOut and Temp tabs no longer mutate each other's channel state\n- Active-tab underline scales with DPI and rounds to physical pixels for crisp rendering above 100% scaling\n- IconButton width parameter no longer subtracts HUD-scaled padding from a raw int (measured width passes through verbatim)\n- Internal: HellionStyle ChildBgAlpha extracted to a testable helper; Plugin.SaveConfig clones only the temp tabs; SettingsOverview caches the draw-list per frame; Dalamud.Utility.Util surface routed through an IPlatformUtil indirection (MessageStore IsWine probe is now testable in isolation)\n- Built-in themes: Crystal Nocturne (sapphire and electric magenta over obsidian, by CRYSTALLITE) replaces Moonlit Bloom. Users with Moonlit Bloom selected fall back to Hellion Arctic on first load\n\nBased on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).\n\n---\n\n**v1.4.5 — UX and Robustness (2026-05-12)**\n\nSixth sub-patch of the v1.4.x polish-sweep series. Chat-log draw failures surface as a notification, the first-run wizard has an explicit Later option, the input history clears on plugin reload, and the status bar version slot stops clipping in narrow windows.\n\n- Chat window draw errors now show a one-shot notification instead of failing silently — stack trace stays in /xllog\n- First-run wizard: explicit \"Later — keep defaults\" button. Closing the X no longer silently accepts the defaults; the wizard reopens on the next plugin load if nothing was picked\n- InputHistoryService clears on plugin dispose so the previous session's typed commands don't bleed into the next load\n- Status bar hides the version slot when the chat window is too narrow to fit all five slots without overlap\n- Internal: explicit session-only Auto-Tell-Tab invariant in Plugin.cs plus a pinning test in the Build-Suite\n- Internal: FontManager falls back to the system font if the embedded Hellion font resource is missing — logs a Warning\n\n---\n\n**v1.4.4 — Threading and IPC safety polish (2026-05-12)**\n\nFifth sub-patch of the v1.4.x polish-sweep series. Threading assumptions are documented per-method, a hot-path lock falls away, and the privacy filter speaks up when an unknown ChatType shows up.\n\n- AutoTellTabs hot-path getter uses an Interlocked counter instead of taking the lock on every read\n- Honorific integration: per-method threading banners, plus Warning-level log on unsubscribe failure\n- AutoTranslate warmup thread marked IsBackground so plugin unload doesn't wait for it\n- PrivacyFilter logs once per unknown ChatType so a future patch's added channel doesn't drop off the radar\n- New installs persist unknown channels by default; existing configs keep their explicit choice\n\n---\n\n**v1.4.3 — Faster plugin load + new repo (2026-05-08)**\n\nHeavy startup work (migrations, hooks, windows) now runs async so Dalamud's UI stays responsive during load. Load time is comparable to v1.4.2 — this is the foundation for v1.4.4 optimisations.\n\n- Two-phase async load via IAsyncDalamudPlugin\n- Schema-gate replaces the v9→v16 migration chain; old configs require a v1.4.2 install first\n- AutoTranslate cache loads on first use instead of every startup\n- Custom font (Hellion-Exo2) appears with a brief pop after load\n- Repo moved to gitea.hellion-forge.cloud — update your custom-repo URL\n\n---\n\nFull history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases", "AcceptsFeedback": true, "DownloadLinkInstall": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.6/latest.zip", "DownloadLinkUpdate": "https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/download/v1.4.6/latest.zip",