From 16557213cd6f7b02ba38df3bcc9706e7e5ca26d9 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 19 Aug 2026 22:03:12 +0200 Subject: [PATCH] chore: comments, second pass -- the task codes the first pass missed The first sweep matched a character class that swallowed the digit, so a bare B1 slipped through while B1-2 was caught. Searching the whole A-Z space instead of guessing prefixes turned up 130-odd more: B0 through B6, C2, C3, D1, H2, M6, P7, P8, T2, W2, plus GP-04, KB-01, OD-1, PM-1, PM-3, SEC-01, TR-4, TR-7, UI-11, UI-12, XC-8 and API-3. Kept deliberately: 41 B4 01 is a byte signature, "N0" a format string, #L119-L128 a source anchor, LS4/LS6 are linkshells, and A=FF B=0C G=41 R=C2 explains a colour-channel order. Those look like codes and are not. Also translated the eight German comments left in the theme files and ImGuiUtil. Seven of them described what a palette does to which channel, which is worth reading -- just not in a second language in an otherwise English codebase. --- HellionChat/AutoTellTabsService.cs | 8 +- HellionChat/CjkFallbackRange.cs | 6 +- HellionChat/Configuration.cs | 10 +- HellionChat/FontManager.cs | 12 +- HellionChat/GameFunctions/KeybindManager.cs | 14 +- HellionChat/Ipc/ExtraChat.cs | 2 +- HellionChat/MessageManager.cs | 6 +- HellionChat/NameDisplayModes.cs | 2 +- HellionChat/PayloadHandler.cs | 2 +- HellionChat/Plugin.cs | 201 ++++++++++++------ HellionChat/SelfTests/CardClipPlanStep.cs | 2 +- HellionChat/SelfTests/CurrentTabGuidedStep.cs | 2 +- HellionChat/SelfTests/DisclosureArmStep.cs | 2 +- .../SelfTests/FontManagerCtorSmokeStep.cs | 4 +- .../SelfTests/HideRestoreSelfTestStep.cs | 2 +- HellionChat/SelfTests/MainWindowFlagsStep.cs | 4 +- .../SelfTests/MainWindowFocusOpacityStep.cs | 2 +- .../SelfTests/NotificationSoundSelectStep.cs | 2 +- .../SelfTests/PerformanceBaselineLog.cs | 2 +- .../SelfTests/PerformanceBaselineStep.cs | 2 +- .../SelfTests/ScrollSnapDecisionStep.cs | 2 +- .../SelfTests/SenderNameReformatStep.cs | 2 +- .../SelfTests/SidebarActiveSurfaceStep.cs | 2 +- .../SelfTests/SidebarGreetedGlyphStep.cs | 2 +- .../SelfTests/SidebarModeAutoSwitchStep.cs | 2 +- .../SelfTests/SidebarSectionHeaderStep.cs | 2 +- HellionChat/SelfTests/TabRenamePersistStep.cs | 2 +- .../SelfTests/TellResetOnActivateStep.cs | 4 +- .../SelfTests/ThemeCrossfadeSelfTestStep.cs | 6 +- HellionChat/SelfTests/TopTabUnderlineStep.cs | 2 +- HellionChat/Themes/Builtin/EventHorizon.cs | 6 +- .../Themes/Builtin/ForgeMerchantman.cs | 4 +- HellionChat/Themes/Builtin/HellionArctic.cs | 4 +- HellionChat/Themes/Builtin/IndigoViolet.cs | 7 +- HellionChat/Themes/Builtin/MintGrove.cs | 6 +- HellionChat/Themes/Builtin/NightBlue.cs | 5 +- HellionChat/Themes/Builtin/SynthwaveSunset.cs | 5 +- HellionChat/Themes/ThemeRegistry.cs | 10 +- HellionChat/Themes/ThemeStampDiff.cs | 2 +- HellionChat/Ui/Components/CardClipPlanner.cs | 2 +- HellionChat/Ui/Components/ChunkRenderer.cs | 6 +- HellionChat/Ui/Components/InputBar.cs | 6 +- HellionChat/Ui/Components/MessageList.cs | 20 +- .../Ui/Components/Settings/Tabs/AboutTab.cs | 2 +- .../Ui/Components/Settings/ThemePicker.cs | 2 +- HellionChat/Ui/Components/Sidebar.cs | 12 +- HellionChat/Ui/Components/TabContextMenu.cs | 2 +- HellionChat/Ui/DbViewer.cs | 4 +- HellionChat/Ui/InputPreview.cs | 2 +- HellionChat/Ui/Windows/ChannelPopoutPool.cs | 2 +- HellionChat/Ui/Windows/ChannelPopoutWindow.cs | 2 +- HellionChat/Ui/Windows/MainWindow.cs | 6 +- HellionChat/Ui/Windows/SettingsWindow.cs | 2 +- HellionChat/Util/ColourUtil.cs | 4 +- HellionChat/Util/ImGuiUtil.cs | 7 +- HellionChat/Util/SenderNameDisplay.cs | 4 +- HellionChat/Util/TabLifecycleHelpers.cs | 4 +- .../_Helpers/PluginDisclosureScanner.cs | 2 +- HellionChat/_Helpers/SenderNameFormatter.cs | 2 +- 59 files changed, 262 insertions(+), 193 deletions(-) diff --git a/HellionChat/AutoTellTabsService.cs b/HellionChat/AutoTellTabsService.cs index efd88d1..ac01d39 100644 --- a/HellionChat/AutoTellTabsService.cs +++ b/HellionChat/AutoTellTabsService.cs @@ -23,7 +23,7 @@ internal sealed class AutoTellTabsService : IDisposable private readonly ILogger _logger; // Tabs-list structure lock now lives on Plugin (neutral owner) so the - // MessageManager refilter can share it. See Plugin.TabsListLock / B3. + // MessageManager refilter can share it. See Plugin.TabsListLock. private object TabsListLock => _plugin.TabsListLock; // Bumped whenever something wipes unpinned temp tabs wholesale (logout). @@ -179,7 +179,7 @@ internal sealed class AutoTellTabsService : IDisposable } // Three steps, because building the tab pulls history out of the store and - // that must not happen under TabsListLock (B3 rule; the query sorts the whole + // that must not happen under TabsListLock (the query sorts the whole // receiver history). Step 1 and 3 are locked, step 2 is not. int generation; lock (TabsListLock) @@ -303,7 +303,7 @@ internal sealed class AutoTellTabsService : IDisposable internal void DropOldestTempTab() { - // B3: lock the list-structure ops so the (currently caller-less) Unpin path + // Lock the list-structure ops so the (currently caller-less) Unpin path // can't race the worker; re-entrant when HandleTell already holds the lock. lock (TabsListLock) { @@ -577,7 +577,7 @@ internal sealed class AutoTellTabsService : IDisposable // Count and flag under one lock so the cap can't be raced. SaveConfig stays // OUTSIDE -- holding TabsListLock across a save would put an fsync on the - // click path, which is what B6 just removed elsewhere. + // click path, which is what a later cycle just removed elsewhere. lock (TabsListLock) { if (PinnedTempTabCount >= MaxPinnedTempTabs) diff --git a/HellionChat/CjkFallbackRange.cs b/HellionChat/CjkFallbackRange.cs index d7d16db..d18210c 100644 --- a/HellionChat/CjkFallbackRange.cs +++ b/HellionChat/CjkFallbackRange.cs @@ -1,7 +1,7 @@ namespace HellionChat; -// Reduced CJK fallback coverage for the v1.5.3 NotoSansCjk fallback merge (B1). -// Before B1 the fallback merged over the full `Ranges` array (Default + endonyms), +// Reduced CJK fallback coverage for the v1.5.3 NotoSansCjk fallback merge. +// Before that the fallback merged over the full `Ranges` array (Default + endonyms), // duplicating the Latin/Default work already done by the global/Japanese fonts. // This is the trimmed remainder the fallback is actually the sole source for: // - Hangul Syllables (AC00-D7A3): no other merged font ships Korean glyphs. @@ -9,7 +9,7 @@ namespace HellionChat; // font is Inter-Light (no CJK), so the fallback is the SOLE Han source. The JpRange // overlap is harmless (MergeMode: the Japanese font wins for shared kanji). // Deliberately excluded: ONLY the ASCII/Latin Default block (0x20-0xFF), which the -// global font already owns -- that doubled Latin merge is the B1 waste being removed. +// global font already owns -- that doubled Latin merge is the waste being removed. // Kept as plain start/end pairs so it is unit-testable without the unsafe ImGui // glyph-range builder (mirrors FontSizeResolver's split-for-test rationale). internal static class CjkFallbackRange diff --git a/HellionChat/Configuration.cs b/HellionChat/Configuration.cs index 6cdc1b6..dcbacaa 100755 --- a/HellionChat/Configuration.cs +++ b/HellionChat/Configuration.cs @@ -35,7 +35,7 @@ public class ConfigKeyBind [Serializable] public class Configuration : IPluginConfiguration { - internal const int LatestVersion = 26; + internal const int LatestVersion = 27; public int Version { get; set; } = LatestVersion; @@ -45,7 +45,7 @@ public class Configuration : IPluginConfiguration // Global window opacity, applied across all themes. public float WindowOpacity = 0.85f; - // UI-12: background opacity of the main chat window while unfocused. + // Background opacity of the main chat window while unfocused. // WindowOpacity above stays the focused value. public float WindowOpacityInactive = 0.65f; @@ -161,7 +161,7 @@ public class Configuration : IPluginConfiguration public bool SeenPopOutHeaderHint; public bool AutoTellTabsOpenAsPopout; - // UI-7: how sender names are rendered in the chat log. + // How sender names are rendered in the chat log. public WorldSuffixMode WorldSuffixMode = WorldSuffixMode.OtherWorldOnly; public NameFormMode NameFormMode = NameFormMode.Full; @@ -232,7 +232,7 @@ public class Configuration : IPluginConfiguration // Toast when a tell the user sent could not be delivered. public bool NotifyFailedTell = true; - // UI-11: warn before sending a message that carries plugin-only glyphs. + // Warn before sending a message that carries plugin-only glyphs. public bool NotifyPluginDisclosure = true; public bool KeepInputFocus = true; public bool Use24HourClock = true; @@ -462,7 +462,7 @@ public class Tab [NonSerialized] internal string? _cachedTellIcon; - // PM-3 hover-lerp state. Default 0f means "not hovered". Sidebar + // hover-lerp state. Default 0f means "not hovered". Sidebar // path animates per tab; card-mode-border path is tab-aggregate // (any card-row hover ramps the alpha for all cards in this tab). // Lerp speed lives in the render loop, not here, so the same field diff --git a/HellionChat/FontManager.cs b/HellionChat/FontManager.cs index b9e6013..6a60292 100644 --- a/HellionChat/FontManager.cs +++ b/HellionChat/FontManager.cs @@ -94,13 +94,13 @@ public sealed class FontManager : IDisposable private ushort[] Ranges = []; private ushort[] JpRange = []; - // B1: trimmed remainder the NotoSansCjk fallback is the sole source for + // Trimmed remainder the NotoSansCjk fallback is the sole source for // (Hangul + full Han); excludes the Default/Latin block already merged // by the global font, so the fallback no longer re-merges the full Ranges array. private ushort[] CjkFallbackGlyphRange = []; // Report accessor for the ctor self-test: built glyph-range array lengths so - // the step can show the B1 dedup effect (a small trimmed fallback vs the large + // the step can show the dedup effect (a small trimmed fallback vs the large // primary range) in its on-disk report instead of a bare Pass. internal (int Ranges, int JpRange, int CjkFallback) GlyphRangeLengths => (Ranges.Length, JpRange.Length, CjkFallbackGlyphRange.Length); @@ -247,7 +247,7 @@ public sealed class FontManager : IDisposable // Instance method so Ranges / JpRange are reachable without parameter // plumbing; PascalCase field names follow the existing class style. - // B1: shared CJK + symbols tail for both the regular and italic delegate + // Shared CJK + symbols tail for both the regular and italic delegate // fonts. Earlier-merged fonts win for shared codepoints (imgui MergeMode), // so this runs AFTER the primary font is set as config.MergeFont. The CJK // fallback is the sole Hangul/Simplified-Han source when UseHellionFont=true @@ -265,7 +265,7 @@ public sealed class FontManager : IDisposable config.GlyphRanges = JpRange; AddFontWithFallback(tk, Plugin.Config.JapaneseFontV2.FontId, config, "japanese"); - // NotoSansCjk fallback, trimmed to CjkFallbackGlyphRange (B1). Merged last so earlier fonts win. + // NotoSansCjk fallback, trimmed to CjkFallbackGlyphRange. Merged last so earlier fonts win. config.SizePt = basePt; config.GlyphRanges = CjkFallbackGlyphRange; AddFontWithFallback( @@ -427,7 +427,7 @@ public sealed class FontManager : IDisposable // Common extras (Axis ingame glyphs, endonyms, enclosed alphanumerics) // belong to the primary/Japanese ranges only. The trimmed CJK fallback - // (B1) skips them so it stays a pure Hangul/Simplified-Han remainder and + // skips them so it stays a pure Hangul/Simplified-Han remainder and // does not re-merge the Default-block work the global font already did. if (includeCommonExtras) { @@ -498,7 +498,7 @@ public sealed class FontManager : IDisposable ); JpRange = BuildRange(GlyphRangesJapanese.GlyphRanges, includeCommonExtras: true); - // B1: the fallback gets only the trimmed Hangul/Simplified-Han remainder. + // The fallback gets only the trimmed Hangul/Simplified-Han remainder. // No Default block, no endonyms — those are already merged by the global and // Japanese fonts, so re-merging them on the fallback was wasted atlas work. CjkFallbackGlyphRange = BuildRange(CjkFallbackRange.Pairs, includeCommonExtras: false); diff --git a/HellionChat/GameFunctions/KeybindManager.cs b/HellionChat/GameFunctions/KeybindManager.cs index 8de21bc..1feb9ed 100644 --- a/HellionChat/GameFunctions/KeybindManager.cs +++ b/HellionChat/GameFunctions/KeybindManager.cs @@ -507,14 +507,14 @@ internal unsafe class KeybindManager : IDisposable // Resolve the surface this keybind acts on FIRST: a focused pop-out otherwise // the main window. Channel-set/REPLY/prefill all write here so the action - // follows the input the user is typing in (C3 full tail rebuild, OD-1). + // follows the input the user is typing in. var (targetWindow, targetTab) = ResolveKeybindTarget(); // Surface + focus the resolved target ONCE, before routing. Main: ActivateChat // re-surfaces it from a hide/closed state (the chat-activation entry point // retired in v1.6.0). Pop-out: arm only its focus — NOT ActivateChat, which // would yank the main window to front and un-hide it on every pop-out-targeted - // keybind (OD-1: stay where the user types). Exactly one window arms focus per + // keybind: stay where the user types. Exactly one window arms focus per // keybind, so the next frame has no SetKeyboardFocusHere race. if (targetWindow is ChannelPopoutWindow) targetWindow.RequestInputFocus(); @@ -547,7 +547,7 @@ internal unsafe class KeybindManager : IDisposable // Rotation binds (REPLY / linkshell-cycle). Ported from v1.5.6's // ChatLogWindow.Activated (1d3b429:240-334) without the ChatActivatedArgs // indirection (gone in the rewrite). Writes onto the resolved surface's - // tab (C2/C3 shared target), not Plugin.CurrentTab. + // tab, not Plugin.CurrentTab. if (targetTab is { } rotTab) { var targetChannel = (InputChannel?)rotateChannel; @@ -629,7 +629,7 @@ internal unsafe class KeybindManager : IDisposable if (info.Permanent) { - // KB-01 (1.5.6 parity, ChatLogWindow.SetChannel 1d3b429:1476-1479): + // 1.5.6 parity (ChatLogWindow.SetChannel, 1d3b429:1476-1479): // committing the game channel also pre-targets the game's native input. // Forward the tab's reply target for Tell so the partner is armed // game-side (ChangeChatChannel code 17); null for a linkshell — @@ -654,7 +654,7 @@ internal unsafe class KeybindManager : IDisposable // Prefill text binds (CMD_COMMAND seeds "/"): the token always goes to the // main InputBar (the focus contract does not expose pop-out buffers); a // focused pop-out already received focus above, so only token routing matters - // here (documented scope limit, OD-1). + // here -- a documented scope limit. if (info.Text is { } text) Plugin.Instance.InputBar.SetPendingMessage(text); } @@ -665,7 +665,7 @@ internal unsafe class KeybindManager : IDisposable } // Resolve which chat surface a keybind action targets: the open pop-out whose - // input currently has focus, otherwise the main window. C2/C3 share this so a + // input currently has focus, otherwise the main window. Both paths share it so a // channel-switch/REPLY/prefill follows the surface the user is typing in. The // returned tab is that surface's bound tab (pop-out: Bound; main: ActiveTab). // Null tab => skip the tab-write (early-load window where no tab exists yet). @@ -682,7 +682,7 @@ internal unsafe class KeybindManager : IDisposable } // Tab-delta keybinds (ChatTabForward/Backward) stay main-window-only by design: - // a channel-bound pop-out has no tab list to cycle (OD-1). The focus contract is + // a channel-bound pop-out has no tab list to cycle. The focus contract is // consumed by the channel-set/REPLY/prefill tail, not here. private void DispatchTabDelta(int delta) { diff --git a/HellionChat/Ipc/ExtraChat.cs b/HellionChat/Ipc/ExtraChat.cs index f69547c..1751f49 100644 --- a/HellionChat/Ipc/ExtraChat.cs +++ b/HellionChat/Ipc/ExtraChat.cs @@ -31,7 +31,7 @@ public sealed class ExtraChat : IDisposable // volatile: IPC callbacks fire on a Dalamud thread while ImGui reads these. // Reference assignment is atomic on x64, but the barrier ensures visibility - // across threads (especially Mono/Wine). See AUDIT-2026-05-05 [SEC-01]. + // across threads (especially Mono/Wine). Raised in the 2026-05-05 audit. private volatile Dictionary ChannelCommandColoursInternal = new(); internal IReadOnlyDictionary ChannelCommandColours => ChannelCommandColoursInternal; diff --git a/HellionChat/MessageManager.cs b/HellionChat/MessageManager.cs index 24c533e..c44bf9f 100644 --- a/HellionChat/MessageManager.cs +++ b/HellionChat/MessageManager.cs @@ -163,7 +163,7 @@ internal class MessageManager : IAsyncDisposable internal void ClearAllTabs() { - // B3: snapshot the tab LIST under the shared lock so the worker-thread + // Snapshot the tab LIST under the shared lock so the worker-thread // add/remove can't tear the enumeration; tab.Clear() then runs lock-free // (each tab's Messages has its own SemaphoreSlim — lock order: list outer). List tabsSnapshot; @@ -184,8 +184,8 @@ internal class MessageManager : IAsyncDisposable using var messages = Store.GetMostRecentMessages(CurrentContentId, since); // TempTabs excluded (live state from AutoTellTabsService). Bucket via the - // pure MapMessagesToTabs so the assignment stays testable outside Dalamud (B3-1). - // B3: snapshot under the shared lock (list copy only — short critical + // pure MapMessagesToTabs so the assignment stays testable outside Dalamud. + // Snapshot under the shared lock (list copy only — short critical // section). The Store query above and the AddSortPrune writes below stay // OUTSIDE the lock (lock order: list outer, MessageList inner). List nonTempTabs; diff --git a/HellionChat/NameDisplayModes.cs b/HellionChat/NameDisplayModes.cs index 4f71448..542471c 100644 --- a/HellionChat/NameDisplayModes.cs +++ b/HellionChat/NameDisplayModes.cs @@ -2,7 +2,7 @@ using HellionChat.Resources; namespace HellionChat; -// UI-7: how a sender's name is rendered in the chat log. Kept in its own file +// How a sender's name is rendered in the chat log. Kept in its own file // (no Dalamud usings) so the SenderNameFormatter pure-helper test stays // AppDomain-isolated (feedback_dalamud_test_isolation). diff --git a/HellionChat/PayloadHandler.cs b/HellionChat/PayloadHandler.cs index 71e44d5..2d3d95b 100644 --- a/HellionChat/PayloadHandler.cs +++ b/HellionChat/PayloadHandler.cs @@ -264,7 +264,7 @@ internal sealed class PayloadHandler if (!Sheets.IsInForay()) { // Single SetPendingMessage call; v1.5.6 used incremental Chat += writes. - // XC-8: shares the /tell builder with the native detours. IsPublic (not + // Shares the /tell builder with the native detours. IsPublic (not // IsNullOrEmpty) is resolved HERE — a private/null world must NOT leak @World. _inputBar.SetPendingMessage( GameFunctions.Chat.BuildTellCommand( diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index a0d2a52..9eba48a 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -134,7 +134,7 @@ public sealed class Plugin : IAsyncDalamudPlugin internal Integrations.HonorificService HonorificService { get; private set; } = null!; internal Integrations.CustomAudioPlayer CustomAudioPlayer { get; private set; } = null!; - // Ctor-smoke anchors (B0-2). Exposed so the Payload/Chunk ctor-smoke steps + // Ctor-smoke anchors. Exposed so the Payload/Chunk ctor-smoke steps // can drive the real per-frame Lender path (Borrow()) and the eager // singletons through the container, never via new(). Mirror of the // FontManager property pattern — every SelfTest reaches services this way. @@ -178,7 +178,7 @@ public sealed class Plugin : IAsyncDalamudPlugin internal bool ChatActivationRequested; // Set in the first DisposeAsync statement so async callbacks scheduled - // via Framework.RunOnTick (v1.4.8 B3 retention sweep) can early-bail + // via Framework.RunOnTick (v1.4.8 retention sweep) can early-bail // before they touch state that has already been torn down. Volatile // because the tick reads it from a different thread than the writer. private volatile bool _isDisposing; @@ -188,7 +188,7 @@ public sealed class Plugin : IAsyncDalamudPlugin // just unloaded belongs to nobody. internal bool IsDisposing => _isDisposing; - // v1.9.0 B5: last full Draw() wall-time in ms, written once per frame at + // v1.9.0: last full Draw() wall-time in ms, written once per frame at // the end of the UiBuilder.Draw handler. Covers the GlobalStyleScope push // and the font push (the first-frame hitch measurement must include atlas/style // prologue cost), not just WindowSystem.Draw — measuring the inner call @@ -214,7 +214,7 @@ public sealed class Plugin : IAsyncDalamudPlugin // must never block doing so. internal readonly Util.DbOperationGate DbOperations = new(); - // B3: neutral owner of the Config.Tabs LIST-structure lock so both the + // Neutral owner of the Config.Tabs LIST-structure lock so both the // worker-thread mutator (AutoTellTabsService) and the framework-thread // refilter (MessageManager) share ONE monitor. Lock order: this outer, // MessageList's SemaphoreSlim inner — never the reverse. @@ -287,83 +287,118 @@ public sealed class Plugin : IAsyncDalamudPlugin + "Please install v1.4.2 first to migrate the configuration, then upgrade to v1.4.10." ); } - // v23 migration: SidebarTabView was the 1.5.6 sidebar↔top-tabs switch, - // superseded by MainWindowLayoutMode in the v1.6.0 rewrite. A user who - // set it false (only effective in 1.5.6) wanted top tabs — carry that - // intent forward. Runs only for pre-v23 configs; fresh configs load at - // LatestVersion and skip it. Additive v20/v22 fields keep their - // initializer defaults as before. - if (Config.Version < 23 && !Config.SidebarTabView) + // 2.0.0 does not migrate, it starts over. Five cycles rebuilt the whole + // window layer, and a config carried through them keeps values chosen + // against surfaces that no longer exist -- an opacity picked for a + // window that has been redrawn twice since, tabs laid out for a sidebar + // that works differently now. Every user of this build is a tester who + // was told this happens, and it is the only way to be sure everyone + // sees the same defaults. + // + // The file is copied aside first. Rolling back to 1.5.6 is a supported + // move here and it stays cheap: the old settings are a file copy away, + // rather than an evening of clicking them back in. + if (Config.Version < 27) { - Config.MainWindowLayoutMode = MainWindowLayoutMode.TopTabs; - } + BackUpConfigBeforeReset(); + + Config = Configuration.CreateFresh(); + Config.Version = 27; + + // Saved immediately: a crash between here and the first user-driven + // save would otherwise run the whole reset again on the next start, + // and the second run would back up the already-reset file over the + // real backup. + SaveConfig(); - // v24 migration: the privacy filter used to route a known but unticked - // channel through the unknown-type failsafe, so the channel grid was - // inert whenever that failsafe was on. Corrected in v1.12.0. A config - // that never picked a channel was storing everything through that hole, - // and the corrected rule would store nothing at all -- so the intent is - // carried forward as a filter that is honestly switched off. - if ( - Config.Version < 24 - && Privacy.StorageRule.ShouldDisableFilterOnV24( - Config.PrivacyFilterEnabled, - Config.PrivacyPersistUnknownChannels, - Config.PrivacyPersistChannels.Count - ) - ) - { - Config.PrivacyFilterEnabled = false; - // Log, not LogProxy: this runs in Phase-0 and the proxy is only - // resolved from the container further down. Log.Information( - "Privacy filter switched off during the v24 migration: it was on with no channels " - + "picked, which stored everything through the unknown-channel failsafe. Pick " - + "channels in Settings to switch it back on." + "Config reset to defaults for 2.0.0. Previous settings kept as " + + "HellionChat.json.pre-2.0.0.bak next to the config file." ); } - - // v25 carried no migration step; the bump was documentation. - // - // v26 does. NameCameFromPartner is what screenshot mode reads to decide - // whether a tab name is a person, and a config written before it existed - // has it false on every tab -- including pinned tell tabs, which survive - // reloads and are named "Player@World". Anything still carrying a tell - // binding or the temp flag got its name from a partner, so the flag is - // set from those two. - // - // Tabs promoted before this version are past saving: promotion clears - // both markers and keeps the name, so nothing in the stored data says - // where that name came from. Renaming one clears the flag anyway, which - // is the same outcome the user gets by editing it. - if (Config.Version < 26) + else { - var carried = 0; - foreach (var tab in Config.Tabs) + // v23 migration: SidebarTabView was the 1.5.6 sidebar↔top-tabs switch, + // superseded by MainWindowLayoutMode in the v1.6.0 rewrite. A user who + // set it false (only effective in 1.5.6) wanted top tabs — carry that + // intent forward. Runs only for pre-v23 configs; fresh configs load at + // LatestVersion and skip it. Additive v20/v22 fields keep their + // initializer defaults as before. + if (Config.Version < 23 && !Config.SidebarTabView) { - if (tab.NameCameFromPartner || (!tab.IsTempTab && tab.TellTarget?.IsSet() != true)) - continue; - - tab.NameCameFromPartner = true; - carried++; + Config.MainWindowLayoutMode = MainWindowLayoutMode.TopTabs; } - if (carried > 0) + // v24 migration: the privacy filter used to route a known but unticked + // channel through the unknown-type failsafe, so the channel grid was + // inert whenever that failsafe was on. Corrected in v1.12.0. A config + // that never picked a channel was storing everything through that hole, + // and the corrected rule would store nothing at all -- so the intent is + // carried forward as a filter that is honestly switched off. + if ( + Config.Version < 24 + && Privacy.StorageRule.ShouldDisableFilterOnV24( + Config.PrivacyFilterEnabled, + Config.PrivacyPersistUnknownChannels, + Config.PrivacyPersistChannels.Count + ) + ) { + Config.PrivacyFilterEnabled = false; + // Log, not LogProxy: this runs in Phase-0 and the proxy is only + // resolved from the container further down. Log.Information( - $"Marked {carried} tab(s) as partner-named during the v26 migration, so " - + "screenshot mode hides them in the channel header." + "Privacy filter switched off during the v24 migration: it was on with no channels " + + "picked, which stored everything through the unknown-channel failsafe. Pick " + + "channels in Settings to switch it back on." ); } + + // v25 carried no migration step; the bump was documentation. + // + // v26 does. NameCameFromPartner is what screenshot mode reads to decide + // whether a tab name is a person, and a config written before it existed + // has it false on every tab -- including pinned tell tabs, which survive + // reloads and are named "Player@World". Anything still carrying a tell + // binding or the temp flag got its name from a partner, so the flag is + // set from those two. + // + // Tabs promoted before this version are past saving: promotion clears + // both markers and keeps the name, so nothing in the stored data says + // where that name came from. Renaming one clears the flag anyway, which + // is the same outcome the user gets by editing it. + if (Config.Version < 26) + { + var carried = 0; + foreach (var tab in Config.Tabs) + { + if ( + tab.NameCameFromPartner + || (!tab.IsTempTab && tab.TellTarget?.IsSet() != true) + ) + continue; + + tab.NameCameFromPartner = true; + carried++; + } + + if (carried > 0) + { + Log.Information( + $"Marked {carried} tab(s) as partner-named during the v26 migration, so " + + "screenshot mode hides them in the channel header." + ); + } + } } - Config.Version = 26; + Config.Version = 27; // Unpinned TempTabs are session-only and dropped on every load. Pinned // TempTabs survive reload -- tester feedback in v1.4.7. Config.Tabs.RemoveAll(TabLifecycleHelpers.ShouldStripOnLoad); - // GP-04: clear stale Tab.PopOut flags now — the pool binds further down + // Clear stale Tab.PopOut flags now — the pool binds further down // (ChannelPopoutPool resolve below), so at this point no tab can own a // slot. A persisted PopOut=true (notably on surviving pinned TempTabs) // would otherwise be a flag with no window. Runs after the strip, before @@ -462,7 +497,7 @@ public sealed class Plugin : IAsyncDalamudPlugin FirstRunWizard = _host.Services.GetRequiredService(); ChannelPopoutPool = _host.Services.GetRequiredService(); - // Ctor-smoke anchors (B0-2). Resolved last, against the fully built + // Ctor-smoke anchors. Resolved last, against the fully built // container: every MakePayloadHandler dep (MainWindow, InputBar, // ChunkRenderer, ...) is resolvable here, and the ChunkRenderer resolve // below just reuses the same cached singleton. These are plain @@ -732,7 +767,7 @@ public sealed class Plugin : IAsyncDalamudPlugin return; // Set before any cleanup so deferred Framework.RunOnTick callbacks - // (B3 retention sweep) see the flag and bail out before they touch + // (the retention sweep) see the flag and bail out before they touch // MessageManager / Log / static fields that the rest of this method // is about to tear down. _isDisposing = true; @@ -840,6 +875,38 @@ public sealed class Plugin : IAsyncDalamudPlugin return failure; } + // Copies the config aside before the 2.0.0 reset overwrites it. Best effort + // by design: a backup that cannot be written must not stop the plugin from + // starting, and the reset itself is what the user was told would happen. + // + // Overwrite=false, so a second run cannot bury the real backup under a copy + // of the already-reset file. The reset saves immediately for the same + // reason, but a crash in between is exactly when this matters. + private static void BackUpConfigBeforeReset() + { + try + { + var dir = Interface.ConfigDirectory.Parent?.FullName; + if (dir is null) + return; + + var configFile = Path.Combine(dir, "HellionChat.json"); + if (!File.Exists(configFile)) + return; + + var backup = Path.Combine(dir, "HellionChat.json.pre-2.0.0.bak"); + if (File.Exists(backup)) + return; + + File.Copy(configFile, backup); + Log.Information($"HellionChat: config backed up to {backup} before the 2.0.0 reset"); + } + catch (Exception e) + { + Log.Warning(e, "HellionChat: could not back up the config before the 2.0.0 reset"); + } + } + private static void MigrateFromChatTwoLayout() { var pluginConfigsDir = Interface.ConfigDirectory.Parent?.FullName; @@ -1181,7 +1248,7 @@ public sealed class Plugin : IAsyncDalamudPlugin // Schedule on the next framework tick to avoid the ~194ms // hitch from blocking with .Wait() while the frame finishes. // The Config.Tabs enumeration in ClearAllTabs/FilterAllTabs is - // now guarded by the shared Plugin.TabsListLock (B3), so this + // now guarded by the shared Plugin.TabsListLock, so this // tick scheduling is purely hitch-avoidance, not safety. // Pattern reference: SimpleTweaks // Tweaks/Chat/CaseInsensitiveCommands.cs:45. @@ -1268,7 +1335,7 @@ public sealed class Plugin : IAsyncDalamudPlugin private void Draw() { - // v1.9.0 B5: time the whole handler (style + font prologue included). + // v1.9.0: time the whole handler (style + font prologue included). // Bail before measuring once teardown has begun — a late Draw tick // must not touch ThemeRegistry / FontManager after DisposeAsync. if (_isDisposing) @@ -1277,7 +1344,7 @@ public sealed class Plugin : IAsyncDalamudPlugin var drawWatch = Stopwatch.StartNew(); try { - // v1.4.8 B2: pick up external edits of the active custom theme JSON + // v1.4.8: pick up external edits of the active custom theme JSON // without forcing the user to re-click the picker. The disk-stat is // 1Hz-throttled inside RefreshActiveIfStale, so this is essentially // free on built-in themes and ~1 stat/second on custom themes. @@ -1367,7 +1434,7 @@ public sealed class Plugin : IAsyncDalamudPlugin // Config.Tabs across the save so JSON includes them. Cloning only the // unpinned subset keeps the allocation proportional to // AutoTellTabsLimit (<=15) instead of the full tab list. - // B3: the strip/restore mutates the tab LIST, so it shares TabsListLock + // The strip/restore mutates the tab LIST, so it shares TabsListLock // with the worker add/remove and the refilter snapshot. Re-entrant: the // one worker caller (HandleTell) already holds it; framework callers take // it here. SavePluginConfig runs inside (short, in-memory) — the documented fallback diff --git a/HellionChat/SelfTests/CardClipPlanStep.cs b/HellionChat/SelfTests/CardClipPlanStep.cs index 1338a4f..7a51849 100644 --- a/HellionChat/SelfTests/CardClipPlanStep.cs +++ b/HellionChat/SelfTests/CardClipPlanStep.cs @@ -5,7 +5,7 @@ using HellionChat.Util; namespace HellionChat.SelfTests; -// B2: behavioural check that the card path feeds CardClipPlanner AND that a +// Behavioural check that the card path feeds CardClipPlanner AND that a // layout change clears the height cache — not a non-null check. Pure plan math // is pinned headless by CardClipPlanTests; this drives the live accessors. internal sealed class CardClipPlanStep : ISelfTestStep diff --git a/HellionChat/SelfTests/CurrentTabGuidedStep.cs b/HellionChat/SelfTests/CurrentTabGuidedStep.cs index 687fdab..f3fbe5e 100644 --- a/HellionChat/SelfTests/CurrentTabGuidedStep.cs +++ b/HellionChat/SelfTests/CurrentTabGuidedStep.cs @@ -15,7 +15,7 @@ namespace HellionChat.SelfTests; // - a BOUND auto-tell tab keeps its partner by design (leg1) — its binding is // Tab.TellTarget and is deliberately untouched by the strip. // The channel label is intentionally NOT asserted: a tell tab re-derives back to -// Tell after the strip (spec TR-7); only the target matters for privacy. +// Tell after the strip ; only the target matters for privacy. internal sealed class CurrentTabGuidedStep : ISelfTestStep { private readonly Plugin _plugin; diff --git a/HellionChat/SelfTests/DisclosureArmStep.cs b/HellionChat/SelfTests/DisclosureArmStep.cs index 6e2fb9c..2d4a184 100644 --- a/HellionChat/SelfTests/DisclosureArmStep.cs +++ b/HellionChat/SelfTests/DisclosureArmStep.cs @@ -5,7 +5,7 @@ using HellionChat._Helpers; namespace HellionChat.SelfTests; -// B2-3: proves the plugin-disclosure arm-and-hold wires the (otherwise verwaist) +// Proves the plugin-disclosure arm-and-hold wires the (otherwise verwaist) // scanner into the REAL send entry InputBar.TrySend. Drives TrySend via the // arm-test-hook with a PUA glyph in the buffer and NotifyPluginDisclosure on: // the first send must ARM and HOLD (no send), so PendingMessage stays the probe diff --git a/HellionChat/SelfTests/FontManagerCtorSmokeStep.cs b/HellionChat/SelfTests/FontManagerCtorSmokeStep.cs index acd3ae0..e05b9bf 100644 --- a/HellionChat/SelfTests/FontManagerCtorSmokeStep.cs +++ b/HellionChat/SelfTests/FontManagerCtorSmokeStep.cs @@ -112,7 +112,7 @@ internal sealed class FontManagerCtorSmokeStep : ISelfTestStep return SelfTestStepResult.Fail; } - // B1: assert the atlas actually finished building all required handles, + // Assert the atlas actually finished building all required handles, // not just that the references are non-null. FontsReady is the observable // state the trimmed-fallback rebuild must still reach; a half-built atlas // would pass the null/exception checks above but fail here. @@ -128,7 +128,7 @@ internal sealed class FontManagerCtorSmokeStep : ISelfTestStep } // Report what was actually verified rather than a bare Pass. - // The glyph-range entry counts make the B1 dedup visible — the cjk-fallback + // The glyph-range entry counts make the dedup visible — the cjk-fallback // range is now a small trimmed remainder next to the large primary range. var counts = fm.GlyphRangeLengths; var italicState = diff --git a/HellionChat/SelfTests/HideRestoreSelfTestStep.cs b/HellionChat/SelfTests/HideRestoreSelfTestStep.cs index cb5ebf9..0496819 100644 --- a/HellionChat/SelfTests/HideRestoreSelfTestStep.cs +++ b/HellionChat/SelfTests/HideRestoreSelfTestStep.cs @@ -4,7 +4,7 @@ using HellionChat.Ui.Windows; namespace HellionChat.SelfTests; -// P8 wiring: UserHide() suppresses DrawConditions; both ActivateChat() (Enter) and +// wiring: UserHide() suppresses DrawConditions; both ActivateChat() (Enter) and // Toggle() (/hellion) restore it. Pure window-state — the focus side is left to smoke. internal sealed class HideRestoreSelfTestStep : ISelfTestStep { diff --git a/HellionChat/SelfTests/MainWindowFlagsStep.cs b/HellionChat/SelfTests/MainWindowFlagsStep.cs index da3c261..0335fd1 100644 --- a/HellionChat/SelfTests/MainWindowFlagsStep.cs +++ b/HellionChat/SelfTests/MainWindowFlagsStep.cs @@ -4,7 +4,7 @@ using HellionChat.Ui.Windows; namespace HellionChat.SelfTests; -// B1-2 window flags. Drives the REAL MainWindow.PreDraw and asserts it wired +// window flags. Drives the REAL MainWindow.PreDraw and asserts it wired // Window.Flags to ResolveFlags(CanMove, CanResize), then pins the pure // fresh-base contract: false/false adds NoMove|NoResize, true/true clears them // -- flags must rebuild from a fresh base, or NoMove sticks after toggling @@ -72,7 +72,7 @@ internal sealed class MainWindowFlagsStep : ISelfTestStep return SelfTestStepResult.Fail; } - // P7 title-bar contract: ShowTitleBar=false adds NoTitleBar from the + // title-bar contract: ShowTitleBar=false adds NoTitleBar from the // fresh base, true clears it (same no-accumulation guarantee). var barHidden = MainWindow.ResolveFlags(true, true, false); var barShown = MainWindow.ResolveFlags(true, true, true); diff --git a/HellionChat/SelfTests/MainWindowFocusOpacityStep.cs b/HellionChat/SelfTests/MainWindowFocusOpacityStep.cs index 0076e0a..14fe67d 100644 --- a/HellionChat/SelfTests/MainWindowFocusOpacityStep.cs +++ b/HellionChat/SelfTests/MainWindowFocusOpacityStep.cs @@ -3,7 +3,7 @@ using Dalamud.Plugin.SelfTest; namespace HellionChat.SelfTests; -// UI-12 focus opacity. Pins the pure ResolveBgAlpha contract (focused → +// focus opacity. Pins the pure ResolveBgAlpha contract (focused → // WindowOpacity, unfocused → WindowOpacityInactive). The PreDraw wiring // (BgAlpha = ResolveBgAlpha(IsFocused) behind the main-viewport/!docked guard) // is NOT headless-deterministic — the guard may leave BgAlpha null when diff --git a/HellionChat/SelfTests/NotificationSoundSelectStep.cs b/HellionChat/SelfTests/NotificationSoundSelectStep.cs index 7009fdf..786dfa3 100644 --- a/HellionChat/SelfTests/NotificationSoundSelectStep.cs +++ b/HellionChat/SelfTests/NotificationSoundSelectStep.cs @@ -7,7 +7,7 @@ using HellionChat.Util; namespace HellionChat.SelfTests; -// B3-3: notification-sound selection. Drives the pure SelectNotificationSound +// Notification-sound selection. Drives the pure SelectNotificationSound // (the exact pick logic ProcessMessage runs per message) through its SelfTest // wrapper with local synthetic tabs — Plugin.Config.Tabs is never touched, so // no real tab gains messages or unread state. The audible preview button is diff --git a/HellionChat/SelfTests/PerformanceBaselineLog.cs b/HellionChat/SelfTests/PerformanceBaselineLog.cs index 00252c7..38a8925 100644 --- a/HellionChat/SelfTests/PerformanceBaselineLog.cs +++ b/HellionChat/SelfTests/PerformanceBaselineLog.cs @@ -3,7 +3,7 @@ using System.IO; namespace HellionChat.SelfTests; -// Disk sink for the B5 performance baseline. Kept separate from the SelfTest +// Disk sink for the performance baseline. Kept separate from the SelfTest // step so the per-frame hot path never references file IO. Writes one // perf-baseline.json into the plugin ConfigDirectory, atomically (tmp + move) // like ThemeRegistry's theme writer, so a mid-write crash leaves either the diff --git a/HellionChat/SelfTests/PerformanceBaselineStep.cs b/HellionChat/SelfTests/PerformanceBaselineStep.cs index 2595e50..f075905 100644 --- a/HellionChat/SelfTests/PerformanceBaselineStep.cs +++ b/HellionChat/SelfTests/PerformanceBaselineStep.cs @@ -18,7 +18,7 @@ internal sealed class PerformanceBaselineStep : ISelfTestStep private const int TargetFrames = 1000; // Rough draw-call proxy: ImGui emits 6 indices per quad, so vertices/6 is an - // intentional under-count of draw work, not the exact quad count (API-3). + // intentional under-count of draw work, not the exact quad count. private const int VerticesPerQuadProxy = 6; private readonly Plugin _plugin; diff --git a/HellionChat/SelfTests/ScrollSnapDecisionStep.cs b/HellionChat/SelfTests/ScrollSnapDecisionStep.cs index 54c3ce5..d0efc1f 100644 --- a/HellionChat/SelfTests/ScrollSnapDecisionStep.cs +++ b/HellionChat/SelfTests/ScrollSnapDecisionStep.cs @@ -3,7 +3,7 @@ using Dalamud.Plugin.SelfTest; namespace HellionChat.SelfTests; -// B3-5: only the snap decision is headless-testable. Scroll detection + bar + +// Only the snap decision is headless-testable. Scroll detection + bar + // hit-test are smoke-only (the scroll child exists only in-game; GetScrollY is // garbage headless). Drives ResolveSnapToBottom via the SelfTest accessor and // asserts the OR + the request reset invariant. diff --git a/HellionChat/SelfTests/SenderNameReformatStep.cs b/HellionChat/SelfTests/SenderNameReformatStep.cs index 2e7c063..999b42c 100644 --- a/HellionChat/SelfTests/SenderNameReformatStep.cs +++ b/HellionChat/SelfTests/SenderNameReformatStep.cs @@ -5,7 +5,7 @@ using Dalamud.Plugin.SelfTest; namespace HellionChat.SelfTests; -// B2-1/B2-2: proves the WorldSuffixMode/NameFormMode reformat reaches the REAL +// Proves the WorldSuffixMode/NameFormMode reformat reaches the REAL // render entry. Drives ChunkRenderer.DrawChunks (a SelfTests/README-sanctioned // real entry that wires SenderNameDisplay.ForDisplay at ChunkRenderer.cs:54) // with a synthetic ChunkSource.Sender chunk carrying a PlayerPayload, at a diff --git a/HellionChat/SelfTests/SidebarActiveSurfaceStep.cs b/HellionChat/SelfTests/SidebarActiveSurfaceStep.cs index 52fd174..73c809c 100644 --- a/HellionChat/SelfTests/SidebarActiveSurfaceStep.cs +++ b/HellionChat/SelfTests/SidebarActiveSurfaceStep.cs @@ -4,7 +4,7 @@ using HellionChat.Code; namespace HellionChat.SelfTests; -// v1.10.0/C3: the active row gets a surface and an accent bar, so exactly the +// v1.10.0: the active row gets a surface and an accent bar, so exactly the // row the user is on must be marked -- and only that one. Drives the real // Sidebar.Draw and reads the render-observability counter, so a regression in // the draw path fails rather than a parallel calculation passing. diff --git a/HellionChat/SelfTests/SidebarGreetedGlyphStep.cs b/HellionChat/SelfTests/SidebarGreetedGlyphStep.cs index c87b875..c7506e8 100644 --- a/HellionChat/SelfTests/SidebarGreetedGlyphStep.cs +++ b/HellionChat/SelfTests/SidebarGreetedGlyphStep.cs @@ -5,7 +5,7 @@ using HellionChat.GameFunctions.Types; namespace HellionChat.SelfTests; -// B3-2: greeted glyph renders only for temp tabs when the toggle is on. Drives +// Greeted glyph renders only for temp tabs when the toggle is on. Drives // the REAL Sidebar.Draw (render precedent: HonorificHeaderRenderStep, the only // real .Draw in this pool — NOT SidebarModeAutoSwitchStep which only calls // IsExpanded/GetWidth) inside the /xlperf window frame and reads the render diff --git a/HellionChat/SelfTests/SidebarModeAutoSwitchStep.cs b/HellionChat/SelfTests/SidebarModeAutoSwitchStep.cs index cb9e41a..88436e9 100644 --- a/HellionChat/SelfTests/SidebarModeAutoSwitchStep.cs +++ b/HellionChat/SelfTests/SidebarModeAutoSwitchStep.cs @@ -58,7 +58,7 @@ internal sealed class SidebarModeAutoSwitchStep : ISelfTestStep return SelfTestStepResult.Fail; } - // B1-3a: the expanded width must come from Config.SidebarWidth, not the + // The expanded width must come from Config.SidebarWidth, not the // old fixed 150 constant. Drive the REAL GetWidth (the single source // Sidebar.Draw consumes) with concrete values and assert the OBSERVED // effect — in-range passthrough plus clamping — instead of mirroring the diff --git a/HellionChat/SelfTests/SidebarSectionHeaderStep.cs b/HellionChat/SelfTests/SidebarSectionHeaderStep.cs index 1915ebd..1ff2c46 100644 --- a/HellionChat/SelfTests/SidebarSectionHeaderStep.cs +++ b/HellionChat/SelfTests/SidebarSectionHeaderStep.cs @@ -5,7 +5,7 @@ using HellionChat.GameFunctions.Types; namespace HellionChat.SelfTests; -// B3-4: section headers render once per non-empty temp-tab pool, and compact +// Section headers render once per non-empty temp-tab pool, and compact // mode suppresses the header text (separators stay). Drives the REAL // Sidebar.Draw inside the /xlperf window frame (same render precedent as // SidebarGreetedGlyphStep) and reads the render observability counter. diff --git a/HellionChat/SelfTests/TabRenamePersistStep.cs b/HellionChat/SelfTests/TabRenamePersistStep.cs index 376bf82..c397d46 100644 --- a/HellionChat/SelfTests/TabRenamePersistStep.cs +++ b/HellionChat/SelfTests/TabRenamePersistStep.cs @@ -4,7 +4,7 @@ using HellionChat.Ui.Components; namespace HellionChat.SelfTests; -// B3-1: rename must persist. Drives the real ApplyTabRename (the InputText +// Rename must persist. Drives the real ApplyTabRename (the InputText // callback path), then SaveConfig + reload from disk and asserts the new name // survived — a fresh-from-config tab, not the same reference (a reference check // would pass on a dead roundtrip). Uses a persistent (non-temp) tab: unpinned diff --git a/HellionChat/SelfTests/TellResetOnActivateStep.cs b/HellionChat/SelfTests/TellResetOnActivateStep.cs index 18da3a4..93cb69e 100644 --- a/HellionChat/SelfTests/TellResetOnActivateStep.cs +++ b/HellionChat/SelfTests/TellResetOnActivateStep.cs @@ -10,7 +10,7 @@ namespace HellionChat.SelfTests; // The activation strip. Drives the REAL OnTabActivated -- the entry the // Sidebar/TopTabBar click handlers, the pop-out path and the Draw-seed all call // — with local probe tabs (Plugin.Config.Tabs is never touched). Asserts the -// five contracts: strip-on-switch, no-strip-on-reclick (TR-4), leg1 preserve, +// five contracts: strip-on-switch, no-strip-on-reclick, leg1 preserve, // derive, and non-tell untouched. internal sealed class TellResetOnActivateStep : ISelfTestStep { @@ -41,7 +41,7 @@ internal sealed class TellResetOnActivateStep : ISelfTestStep } // (b) re-clicking the already-active tab (previous == tab) must NOT strip - // a live game-tell conversation (TR-4 regression guard). + // a live game-tell conversation (regression guard). var reclick = MakeStaleTellTab(boundTellTarget: false, withLabel: false); TabLifecycleHelpers.OnTabActivated(reclick, reclick); if (reclick.CurrentChannel.TellTarget is null) diff --git a/HellionChat/SelfTests/ThemeCrossfadeSelfTestStep.cs b/HellionChat/SelfTests/ThemeCrossfadeSelfTestStep.cs index d1034a3..598f298 100644 --- a/HellionChat/SelfTests/ThemeCrossfadeSelfTestStep.cs +++ b/HellionChat/SelfTests/ThemeCrossfadeSelfTestStep.cs @@ -4,7 +4,7 @@ using HellionChat.Themes; namespace HellionChat.SelfTests; -// Verifies the v1.5.4 PM-1 crossfade contract: switching the active +// Verifies the v1.5.4 crossfade contract: switching the active // theme arms TryGetActiveCrossfade for ~300ms, then the registry // returns to direct AbgrCache reads. A second switch within 100ms // keeps the lerped path active (no identity-snap). CleanUp restores @@ -67,7 +67,7 @@ internal sealed class ThemeCrossfadeSelfTestStep : ISelfTestStep // it as "saw the start" if more than 300ms have elapsed. // Skip the mid-crossfade-switch phase in that case -- the // lerped path is no longer active, so a second switch would - // re-arm a fresh crossfade and not exercise PM-1b's + // re-arm a fresh crossfade and not exercise its // mid-flight-origin override. if (Environment.TickCount64 - this.armedAtTickMs > 300) { @@ -83,7 +83,7 @@ internal sealed class ThemeCrossfadeSelfTestStep : ISelfTestStep if (!this.sawMidCrossfadeSwitch) { - // PM-Test-3 mid-crossfade-switch phase: within ~100ms of the + // mid-crossfade-switch phase: within ~100ms of the // first observed crossfade, fire a second Switch to a THIRD // theme. ArmCrossfade must compose the current lerped state // as the new origin -- TryGetActiveCrossfade still returns diff --git a/HellionChat/SelfTests/TopTabUnderlineStep.cs b/HellionChat/SelfTests/TopTabUnderlineStep.cs index 1245d8e..345b769 100644 --- a/HellionChat/SelfTests/TopTabUnderlineStep.cs +++ b/HellionChat/SelfTests/TopTabUnderlineStep.cs @@ -4,7 +4,7 @@ using HellionChat.Code; namespace HellionChat.SelfTests; -// v1.10.0/D1: the top-tab strip marks the active tab with a fill plus an accent +// v1.10.0: the top-tab strip marks the active tab with a fill plus an accent // underline. Drives the real TopTabBar.Draw and reads the render counter. // // "At most one", not "exactly one": the strip skips popped-out tabs, so zero diff --git a/HellionChat/Themes/Builtin/EventHorizon.cs b/HellionChat/Themes/Builtin/EventHorizon.cs index 40f722b..f226ebc 100644 --- a/HellionChat/Themes/Builtin/EventHorizon.cs +++ b/HellionChat/Themes/Builtin/EventHorizon.cs @@ -51,9 +51,9 @@ internal static class EventHorizon ChatColors: new ThemeChatColors( new Dictionary { - // Event Horizon — Cosmic-Purple-Drift: helle Pastelle bekommen - // Lavender-Tinte, Akzent-Channels (Tell) ziehen Richtung Magenta- - // Lila. Channel-Identität bleibt klar erkennbar. + // Cosmic purple drift: the pale pastels take a lavender tint and + // the accent channels (tell) pull towards magenta-violet. Channel + // identity stays readable throughout. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#E6E0F5"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#F2C25C"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#FF9050"), diff --git a/HellionChat/Themes/Builtin/ForgeMerchantman.cs b/HellionChat/Themes/Builtin/ForgeMerchantman.cs index 030c7ff..56311e2 100644 --- a/HellionChat/Themes/Builtin/ForgeMerchantman.cs +++ b/HellionChat/Themes/Builtin/ForgeMerchantman.cs @@ -51,8 +51,8 @@ internal static class ForgeMerchantman ChatColors: new ThemeChatColors( new Dictionary { - // Forge Merchantman — Patina-Tinte in Party/FC, Bernstein-Tinte in - // Yell/Alliance/CustomEmote. Channel-identity bleibt voll erhalten. + // Patina tint on party and free company, amber on yell, alliance + // and custom emotes. Channel identity is left fully intact. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#FFFFFF"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#F0C060"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#E8902C"), diff --git a/HellionChat/Themes/Builtin/HellionArctic.cs b/HellionChat/Themes/Builtin/HellionArctic.cs index 0b8ae08..cd284c8 100644 --- a/HellionChat/Themes/Builtin/HellionArctic.cs +++ b/HellionChat/Themes/Builtin/HellionArctic.cs @@ -51,8 +51,8 @@ internal static class HellionArctic ChatColors: new ThemeChatColors( new Dictionary { - // Hellion Arctic — FFXIV-Standard mit dezenter Cyan-Tinte in den - // blauen Channels (Party/FC). Channel-Identität bleibt klar. + // The FFXIV defaults with a restrained cyan tint on the blue + // channels (party, free company). Channel identity stays clear. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#FFFFFF"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#FFE066"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#FFA040"), diff --git a/HellionChat/Themes/Builtin/IndigoViolet.cs b/HellionChat/Themes/Builtin/IndigoViolet.cs index 7217d27..8897246 100644 --- a/HellionChat/Themes/Builtin/IndigoViolet.cs +++ b/HellionChat/Themes/Builtin/IndigoViolet.cs @@ -51,9 +51,10 @@ internal static class IndigoViolet ChatColors: new ThemeChatColors( new Dictionary { - // Indigo Violet — Lavender-Pink-Drift in Tell und LS6/7. Türkis- - // Mint-Aurora-Counter in Party/FC und LS4. Glitter-Gold in Yell. - // Differenzierung zu Event Horizon: dunkler, dichter, Türkis statt Gold. + // Lavender-pink drift on tell and linkshells 6 and 7, countered by + // a turquoise-mint aurora on party, free company and linkshell 4. + // Glitter gold on yell. What sets it apart from Event Horizon: + // darker, denser, and turquoise where that one goes gold. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#F0E6FF"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#F0D880"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#F09A60"), diff --git a/HellionChat/Themes/Builtin/MintGrove.cs b/HellionChat/Themes/Builtin/MintGrove.cs index 5caf0c6..fe075dc 100644 --- a/HellionChat/Themes/Builtin/MintGrove.cs +++ b/HellionChat/Themes/Builtin/MintGrove.cs @@ -51,9 +51,9 @@ internal static class MintGrove ChatColors: new ThemeChatColors( new Dictionary { - // Mint Grove — Naturthemen-Tönung: Honey-Amber in Yell-Familie, - // Mint-Drift in NoviceNetwork und Linkshell. Tell-Pink-Identität - // bleibt erhalten für Erkennbarkeit. + // Nature-themed tint: honey amber across the yell family, a mint + // drift in novice network and linkshell. Tell keeps its pink so + // the channel stays recognisable. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#E8F5EA"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#F9D580"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#F0A050"), diff --git a/HellionChat/Themes/Builtin/NightBlue.cs b/HellionChat/Themes/Builtin/NightBlue.cs index 42b3904..1345c58 100644 --- a/HellionChat/Themes/Builtin/NightBlue.cs +++ b/HellionChat/Themes/Builtin/NightBlue.cs @@ -51,8 +51,9 @@ internal static class NightBlue ChatColors: new ThemeChatColors( new Dictionary { - // Night Blue — Royal-Blue-Tinte in Party/FC, Bronze-Gold in Yell/ - // Alliance. Channel-identity (Tell-Pink, NN-Lime) bleibt erhalten. + // Royal blue on party and free company, bronze gold on yell and + // alliance. Channel identity is preserved -- tell stays pink, + // novice network stays lime. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#FFFFFF"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#FFD060"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#FFA040"), diff --git a/HellionChat/Themes/Builtin/SynthwaveSunset.cs b/HellionChat/Themes/Builtin/SynthwaveSunset.cs index 6fa0492..0dffa5a 100644 --- a/HellionChat/Themes/Builtin/SynthwaveSunset.cs +++ b/HellionChat/Themes/Builtin/SynthwaveSunset.cs @@ -51,8 +51,9 @@ internal static class SynthwaveSunset ChatColors: new ThemeChatColors( new Dictionary { - // Synthwave Sunset — Magenta dominiert die warmen Channels (Yell/Shout/FC), - // Cyan dominiert die kühlen (Tell/Party). Neon-Akzente für Status-nahe Channels. + // Magenta carries the warm channels (yell, shout, free company), + // cyan the cool ones (tell, party). Neon accents on the status- + // adjacent channels. [HellionChat.Code.ChatType.Say] = ColourUtil.HexToRgba("#F0DFFF"), [HellionChat.Code.ChatType.Yell] = ColourUtil.HexToRgba("#FF2D95"), [HellionChat.Code.ChatType.Shout] = ColourUtil.HexToRgba("#FF6BB6"), diff --git a/HellionChat/Themes/ThemeRegistry.cs b/HellionChat/Themes/ThemeRegistry.cs index 7f60e21..22bbd25 100644 --- a/HellionChat/Themes/ThemeRegistry.cs +++ b/HellionChat/Themes/ThemeRegistry.cs @@ -10,7 +10,7 @@ public sealed class ThemeRegistry public const string DefaultSlug = HellionArctic.Slug; - // 1Hz throttle for the v1.4.8 B2 auto-refresh-on-active path. The + // 1Hz throttle for the v1.4.8 auto-refresh-on-active path. The // Plugin.Draw hook calls RefreshActiveIfStale every frame, but the // actual File.GetLastWriteTimeUtc disk-stat only runs once per second // -- 60fps would otherwise mean 3600 stats/min on the same path (more @@ -24,7 +24,7 @@ public sealed class ThemeRegistry private readonly string? _customThemesDir; private Theme _active; - // v1.4.8 B2: source path of the currently active custom theme. Captured + // v1.4.8: source path of the currently active custom theme. Captured // at Switch() time so RefreshActiveIfStale does not have to reconstruct // a filename from the slug -- custom theme filenames are not required // to match the slug they declare in the JSON body. Null when the active @@ -33,7 +33,7 @@ public sealed class ThemeRegistry private long _lastActiveStampCheckMs = -ActiveStampPollIntervalMs; private DateTime _lastActiveStamp = DateTime.MinValue; - // PM-1 crossfade state. Switch() captures the previous AbgrCache as a + // crossfade state. Switch() captures the previous AbgrCache as a // VALUE-COPY (not a Theme reference) -- the built-in singletons share // their RecomputeAbgrCache identity, so a reference would mutate // alongside the new active. _crossfadeStartTickMs == long.MinValue @@ -115,7 +115,7 @@ public sealed class ThemeRegistry // ThemeImportExportRow opens this path via Process.Start. public string? CustomThemesDir => _customThemesDir; - // Read-only enumeration of all built-in theme slugs. T2 ThemePickerCategoryStep + // Read-only enumeration of all built-in theme slugs. ThemePickerCategoryStep // diffs this set against ThemePicker.CategoryMapSlugs to enforce coverage. public IEnumerable BuiltinSlugs => _builtIns.Keys; @@ -293,7 +293,7 @@ public sealed class ThemeRegistry // (see `Switch` built-in-first lookup), so saving a custom file under // a built-in slug persists the file but leaves the built-in active — // looks green, behaves broken. ColorPicker DrawIdleState forks - // built-in themes into a custom slug before BeginEditing, M6 + // built-in themes into a custom slug before BeginEditing, // ImportFromPath renames built-in-colliding imports to _imported. // New call-sites must either fork first or rename to a non-built-in slug. public bool SaveEditingBuffer(out string targetPath) diff --git a/HellionChat/Themes/ThemeStampDiff.cs b/HellionChat/Themes/ThemeStampDiff.cs index aa59a2d..3e1a575 100644 --- a/HellionChat/Themes/ThemeStampDiff.cs +++ b/HellionChat/Themes/ThemeStampDiff.cs @@ -1,6 +1,6 @@ namespace HellionChat.Themes; -// Pure stale-check for the v1.4.8 B2 theme-auto-refresh-on-active path. +// Pure stale-check for the v1.4.8 theme-auto-refresh-on-active path. // Lives in a free helper class so the Build-Suite can exercise the diff // rules without instantiating ThemeRegistry (which touches the Dalamud // log proxy and the filesystem). The rules: diff --git a/HellionChat/Ui/Components/CardClipPlanner.cs b/HellionChat/Ui/Components/CardClipPlanner.cs index debfc00..c6b0920 100644 --- a/HellionChat/Ui/Components/CardClipPlanner.cs +++ b/HellionChat/Ui/Components/CardClipPlanner.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; namespace HellionChat.Ui.Components; -// B2 (PERF-B2): variable-height clip plan. ImGuiListClipper needs a constant +// Variable-height clip plan. ImGuiListClipper needs a constant // row height, and since v1.10.0 neither density has one (compact rows wrap // too), so both compute a plan from the cached per-row heights: a lead dummy // for the rows above diff --git a/HellionChat/Ui/Components/ChunkRenderer.cs b/HellionChat/Ui/Components/ChunkRenderer.cs index 5439523..2c94df1 100644 --- a/HellionChat/Ui/Components/ChunkRenderer.cs +++ b/HellionChat/Ui/Components/ChunkRenderer.cs @@ -34,11 +34,11 @@ internal sealed class ChunkRenderer // names change every plugin reload to avoid stable cross-session linkage. _salt = new Random().Next().ToString(); - // Not yet consumed in C2/C3; E-task wiring will likely add log call-sites later. + // No call sites yet; logging here will likely come later. _ = _logger; } - // B2-1/B2-2 render-observability: the formatted sender text the real draw + // render-observability: the formatted sender text the real draw // path actually produced (post-ForDisplay). A SelfTest reads this after // driving DrawChunks to prove the WorldSuffixMode/NameFormMode reformat // reached the real render entry — never the helper in isolation. null until @@ -52,7 +52,7 @@ internal sealed class ChunkRenderer float lineWidth = 0f ) { - // UI-7: render a copy with the sender name reformatted per the user's + // Render a copy with the sender name reformatted per the user's // display options. Skipped in screenshot mode so the name-anonymising // path in DrawChunk stays reliable (privacy wins). ForDisplay returns // the list unchanged when nothing applies, so non-sender lists and the diff --git a/HellionChat/Ui/Components/InputBar.cs b/HellionChat/Ui/Components/InputBar.cs index 4e6dddd..ebf00a1 100644 --- a/HellionChat/Ui/Components/InputBar.cs +++ b/HellionChat/Ui/Components/InputBar.cs @@ -64,7 +64,7 @@ internal sealed class InputBar private bool _wasInputTextHovered; private bool? _isFocusedOverride; // Test-only; null = honour per-frame Draw() value. - // UI-11 plugin-disclosure arm-and-hold: holds the buffer that armed the + // plugin-disclosure arm-and-hold: holds the buffer that armed the // disclosure warning. null = not armed. Compared by value so an edit // re-arms and a resend on the identical buffer goes through. 1.5.6 parity // (ChatInputBar 1d3b429:27). @@ -196,7 +196,7 @@ internal sealed class InputBar ImGui.SameLine(); DrawQuickButtons(); - // UI-11: yellow inline warning while a plugin-only-glyph message is + // Yellow inline warning while a plugin-only-glyph message is // armed-and-held (buffer unchanged since it armed). Renders on its own // line below the input row. 1.5.6 parity (ChatInputBar 1d3b429:93-103). if ( @@ -589,7 +589,7 @@ internal sealed class InputBar if (string.IsNullOrEmpty(text)) return; - // UI-11: plugin-disclosure arm-and-hold. Arm + scan on the RAW + // Plugin-disclosure arm-and-hold. Arm + scan on the RAW // _pendingMessage (NOT the trimmed `text`) so the Draw warning gate // (_pendingMessage == _disclosureArmedBuffer) matches byte-for-byte even // when the buffer has leading/trailing whitespace. 1.5.6 armed/held/ diff --git a/HellionChat/Ui/Components/MessageList.cs b/HellionChat/Ui/Components/MessageList.cs index d218c59..4704632 100644 --- a/HellionChat/Ui/Components/MessageList.cs +++ b/HellionChat/Ui/Components/MessageList.cs @@ -18,13 +18,13 @@ internal sealed class MessageList private PayloadHandler? _handler; - // B3-5: scroll-to-bottom state. Per-instance, so pop-out windows (own + // Scroll-to-bottom state. Per-instance, so pop-out windows (own // MessageList instance, PluginHostFactory.cs:263-266) isolate automatically — // the old 1.5.6 updateScrollState flag is NOT needed here. private bool _scrolledUp; private bool _scrollToBottomRequested; - // B2: the height cache is only valid while these inputs are unchanged. + // The height cache is only valid while these inputs are unchanged. // FontManager's own fingerprint covers font sizes only, not density / the two // name-display modes / width — a stale height would misplace the clipper dummies. // Per tab, not per list: the old single field let a width change in tab A mark @@ -73,12 +73,12 @@ internal sealed class MessageList return snap; } - // SelfTest hook (B3-5 reset-invariant, REQUIRED — not optional). Lets + // SelfTest hook (reset-invariant, REQUIRED — not optional). Lets // ScrollSnapDecisionStep flip the request flag without a real click, so the // post-snap reset can be asserted; without it only the OR branch is testable. internal void RequestScrollToBottomForSelfTest() => _scrollToBottomRequested = true; - // SelfTest hook (B2): runs the real planner against a caller fixture so the + // SelfTest hook: runs the real planner against a caller fixture so the // step asserts the plan without a live scroll child (GetScrollY is garbage headless). internal CardClipPlan PlanCardClipForSelfTest( IReadOnlyList heights, @@ -86,7 +86,7 @@ internal sealed class MessageList float viewportHeight ) => CardClipPlanner.Plan(heights, scrollY, viewportHeight); - // SelfTest hook (B2): drives the live invalidation, returns the tab's remaining + // SelfTest hook: drives the live invalidation, returns the tab's remaining // cached-height count so the step can assert the drop. nowMs is a parameter so // the step can step past the settle window without sleeping (v1.10.0). internal int RunHeightCacheInvalidationForSelfTest(Tab tab, float contentWidth, long nowMs) @@ -165,7 +165,7 @@ internal sealed class MessageList MeasureTimestampColumn(tab); - // B2: drop stale cached heights before the snapshot draw. Both densities + // Drop stale cached heights before the snapshot draw. Both densities // need this now -- compact rows are not constant height either, they wrap. // Width read here while it is valid. InvalidateHeightCacheIfLayoutChanged( @@ -187,7 +187,7 @@ internal sealed class MessageList var frozen = _fingerprintGates[tab.Identifier].IsPending; DrawRows(tab, messages, compact ? _drawCompactRow : _drawCardRow, frozen); - // B3-5: scroll values are frame-constant inside the child, so this + // Scroll values are frame-constant inside the child, so this // reflects the current frame's state wherever it runs; kept after the // render to mirror the 1.5.6 end-of-DrawMessageLog placement. _scrolledUp = ImGui.GetScrollMaxY() - ImGui.GetScrollY() > 1f; @@ -282,7 +282,7 @@ internal sealed class MessageList ImGui.SetCursorPos(origin with { X = origin.X + _stampColumnWidth }); } - // B3-5: Discord-style full-width bar pinned to the bottom edge of the + // Discord-style full-width bar pinned to the bottom edge of the // visible region while the user is scrolled up. Geometry comes from window // pos + size (visible region), never from the content flow: when scrolled // up the visible bottom sits above the content bottom, so the @@ -335,7 +335,7 @@ internal sealed class MessageList private void DrawCompactRow(Message message, string? previousStamp) { - // B2-1/B2-2: render the sender through DrawChunks (the name-aware path + // Render the sender through DrawChunks (the name-aware path // that applies WorldSuffixMode/NameFormMode via ForDisplay), not as a // flat SenderSource.TextValue string. message.Sender already carries the // channel brackets/colon as ChunkSource.None wrappers (MessageManager @@ -566,7 +566,7 @@ internal sealed class MessageList private void DrawCardRow(Message message, string? previousStamp) { - // B2-1/B2-2: sender via DrawChunks (name-aware path), on its own line + // Sender via DrawChunks (name-aware path), on its own line // with content below — 1.5.6 card parity (ChatLogWindow.cs:1913, no // SameLine after the sender). The 1.5.6 channel-colour push on the // sender is deferred styling polish (deferred to v1.9.0); plain diff --git a/HellionChat/Ui/Components/Settings/Tabs/AboutTab.cs b/HellionChat/Ui/Components/Settings/Tabs/AboutTab.cs index 8d4e1b8..f359650 100644 --- a/HellionChat/Ui/Components/Settings/Tabs/AboutTab.cs +++ b/HellionChat/Ui/Components/Settings/Tabs/AboutTab.cs @@ -133,7 +133,7 @@ internal sealed class AboutTab LastHonorificStatusKey = kind.ToString(); var colors = _themes.Active.Colors; - // Null-safety via the `is { } v` pattern, never `.Value` raw (spec SEC-2): + // Null-safety via the `is { } v` pattern, never `.Value` raw : // the version is bound only on the arms that have it; the impossible // Detected/Incompatible-without-version state falls through to default. switch (kind) diff --git a/HellionChat/Ui/Components/Settings/ThemePicker.cs b/HellionChat/Ui/Components/Settings/ThemePicker.cs index 6069633..8ae6da0 100644 --- a/HellionChat/Ui/Components/Settings/ThemePicker.cs +++ b/HellionChat/Ui/Components/Settings/ThemePicker.cs @@ -29,7 +29,7 @@ internal sealed class ThemePicker (HellionStrings.Settings_Theme_Category_Retro, new[] { "synthwave-sunset" }, false), ]; - // T2 ThemePickerCategoryStep diffs this against ThemeRegistry.BuiltinSlugs + // ThemePickerCategoryStep diffs this against ThemeRegistry.BuiltinSlugs // to enforce coverage. Kept on the static map so the test does not pierce instance state. internal static IEnumerable CategoryMapSlugs => CategoryMap.SelectMany(c => c.Slugs); diff --git a/HellionChat/Ui/Components/Sidebar.cs b/HellionChat/Ui/Components/Sidebar.cs index 4adad40..d57afc0 100644 --- a/HellionChat/Ui/Components/Sidebar.cs +++ b/HellionChat/Ui/Components/Sidebar.cs @@ -22,7 +22,7 @@ internal sealed class Sidebar { public const float IconOnlyWidth = 38f; - // B1-3a: expanded sidebar width is user-configurable (Config.SidebarWidth), + // Expanded sidebar width is user-configurable (Config.SidebarWidth), // clamped to these bounds (matches the ChannelsTab slider range). Replaces // the old fixed 150px ExpandedWidth constant. public const float MinSidebarWidth = 40f; @@ -38,7 +38,7 @@ internal sealed class Sidebar // previously active one -- that row was still active when it was painted. internal int LastRenderedActiveSurfaceCount { get; private set; } - // B3-2 render observability: counts greeted glyphs actually drawn this frame. + // render observability: counts greeted glyphs actually drawn this frame. // Incremented ONLY in the real glyph branch in DrawRow; reset at Draw start. // The SelfTest reads it after driving the real Draw — no dead service roundtrip. internal int LastRenderedGreetedGlyphCount; @@ -48,7 +48,7 @@ internal sealed class Sidebar // beside it. private const float PinGlyphScale = 0.6f; - // B3-4 render observability: section headers actually drawn this frame. + // render observability: section headers actually drawn this frame. // Incremented only in the real header branch; reset at Draw start. internal int LastDrawnSectionHeaderCount; @@ -149,7 +149,7 @@ internal sealed class Sidebar var dimAbgr = ColourUtil.RgbaToAbgr(theme.Colors.TextDim); var dl = ImGui.GetWindowDrawList(); - // B3-4 sectioned render order (1.5.6 parity): persistent → pinned + // sectioned render order (1.5.6 parity): persistent → pinned // TempTabs → unpinned TempTabs. Only the display sequence regroups; // the tab list itself stays untouched and every row keeps its // ORIGINAL list index for PushID, so an open context-menu popup @@ -250,7 +250,7 @@ internal sealed class Sidebar // Only split off a separate pop-out hit area when there's room for // both buttons. Below that, the whole row stays as a single // selectable strip without the pop-out affordance. - // A3: gate the pop-out affordance on the expanded sidebar too. In + // Gate the pop-out affordance on the expanded sidebar too. In // icon-only mode avail still clears the width threshold, which used to // paint the pop-out glyph over the tab icon. The row stays a single // selectable strip when collapsed; right-click pop-out is unaffected. @@ -476,7 +476,7 @@ internal sealed class Sidebar // The hit area sits at the LEFT edge of the row, but the item must // be submitted AFTER TabContextMenu.Draw — any interactive item // between the row button and the popup call would steal the - // right-click trigger (B3-1 ordering constraint). + // right-click trigger (ordering constraint). ImGui.SetCursorScreenPos(origin); // CheckCircle = greeted, plain Check = still pending (1.5.6 mapping). diff --git a/HellionChat/Ui/Components/TabContextMenu.cs b/HellionChat/Ui/Components/TabContextMenu.cs index 10ffa80..5cece2c 100644 --- a/HellionChat/Ui/Components/TabContextMenu.cs +++ b/HellionChat/Ui/Components/TabContextMenu.cs @@ -82,7 +82,7 @@ internal static class TabContextMenu ClearPendingRename(); } - // Per-tab notification sound (B3-3). The checkbox gates the picker so + // Per-tab notification sound. The checkbox gates the picker so // tabs that never want a sound keep the popup short. if ( ImGui.Checkbox( diff --git a/HellionChat/Ui/DbViewer.cs b/HellionChat/Ui/DbViewer.cs index b539f72..35cce15 100644 --- a/HellionChat/Ui/DbViewer.cs +++ b/HellionChat/Ui/DbViewer.cs @@ -36,7 +36,7 @@ public class DbViewer : Window private int CurrentPage = 1; private string SimpleSearchTerm = ""; - // v1.4.8 H2: opt-in full-text search across the whole DB via FTS5. + // v1.4.8: opt-in full-text search across the whole DB via FTS5. // Transient UI state (per-session), not persisted -- users opt in fresh // every time so they always see the page-filter as the default mode. private bool UseFullTextSearch; @@ -232,7 +232,7 @@ public class DbViewer : Window tooltipRight: Language.Page_ArrowRight_Tooltip ); - // Full-text search toggle (v1.4.8 H2). IsFtsIndexBuilt is a cached + // Full-text search toggle (v1.4.8). IsFtsIndexBuilt is a cached // volatile bool in MessageStore -- single field read per frame, no // SELECT count(*). ImRaii.Disabled blocks any click while the index // is still being built, so no defensive force-off branch needed diff --git a/HellionChat/Ui/InputPreview.cs b/HellionChat/Ui/InputPreview.cs index 3a7796c..8de71c9 100644 --- a/HellionChat/Ui/InputPreview.cs +++ b/HellionChat/Ui/InputPreview.cs @@ -168,7 +168,7 @@ internal sealed class InputPreview : Window { ImGui.TextUnformatted(Language.Options_Preview_Header); - // Primary path (A2) resets the Lender counter in MainWindow.Draw(); + // Primary path resets the Lender counter in MainWindow.Draw(); // this fallback covers the edge-case where MainWindow is closed but // InputPreview is still open, preventing handler pool growth. if (!_mainWindow.IsOpen) diff --git a/HellionChat/Ui/Windows/ChannelPopoutPool.cs b/HellionChat/Ui/Windows/ChannelPopoutPool.cs index f42e0e0..052a474 100644 --- a/HellionChat/Ui/Windows/ChannelPopoutPool.cs +++ b/HellionChat/Ui/Windows/ChannelPopoutPool.cs @@ -44,7 +44,7 @@ internal sealed class ChannelPopoutPool // A popped tab gets its own input bar, so strip stale tell state first — // otherwise a popped-out stale-tell tab would be a send surface that // bypasses the click-path activation strip. Previous = the main window's - // active tab; popping the active tab itself must not strip (TR-4 guard). + // active tab; popping the active tab itself must not strip (guard). TabLifecycleHelpers.OnTabActivated(tab, Plugin.Instance.MainWindow?.ActiveTab); var slot = _slots.TryReserve(tab.Identifier); diff --git a/HellionChat/Ui/Windows/ChannelPopoutWindow.cs b/HellionChat/Ui/Windows/ChannelPopoutWindow.cs index 7138f60..9075f4a 100644 --- a/HellionChat/Ui/Windows/ChannelPopoutWindow.cs +++ b/HellionChat/Ui/Windows/ChannelPopoutWindow.cs @@ -103,7 +103,7 @@ internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow } // IFocusableChatWindow — this pop-out's own InputBar carries the focus state - // the keybind tail checks when deciding whether to route at this surface (C3). + // the keybind tail checks when deciding whether to route at this surface. public bool HasFocusedInput => _input.IsFocused; // Arm-and-hold the one-frame Activate flag; the pop-out's Draw applies the diff --git a/HellionChat/Ui/Windows/MainWindow.cs b/HellionChat/Ui/Windows/MainWindow.cs index bd07ea3..fa6996e 100644 --- a/HellionChat/Ui/Windows/MainWindow.cs +++ b/HellionChat/Ui/Windows/MainWindow.cs @@ -82,14 +82,14 @@ internal sealed class MainWindow : Window, IFocusableChatWindow RespectCloseHotkey = false; } - // UI-12: per-window focus-dependent opacity. ResolveBgAlpha stays guard-free + // Per-window focus-dependent opacity. ResolveBgAlpha stays guard-free // and pure so the self-test can drive it directly; PreDraw owns the guard + // wiring. 1.5.6 parity (focused → WindowOpacity, unfocused → // WindowOpacityInactive, ChatLogWindow.PreOpenCheck 1d3b429:724). internal float ResolveBgAlpha(bool isFocused) => isFocused ? Plugin.Config.WindowOpacity : Plugin.Config.WindowOpacityInactive; - // B1-2 / P7: rebuild flags from a fresh base every frame so toggling + // Rebuild flags from a fresh base every frame so toggling // CanMove/CanResize/ShowTitleBar back on actually CLEARS NoMove/NoResize/ // NoTitleBar (not accumulating). Move/resize/title-bar logic as 1.5.6 // (ChatLogWindow.PreOpenCheck 1d3b429:703-710); base flags = today's @@ -240,7 +240,7 @@ internal sealed class MainWindow : Window, IFocusableChatWindow } // IFocusableChatWindow — the keybind tail resolves which surface owns the - // input focus before routing a channel-set/REPLY/prefill at it (C3). + // input focus before routing a channel-set/REPLY/prefill at it. public bool HasFocusedInput => _input.IsFocused; // Arm-and-hold: field writes only, safe from the framework thread; the draw diff --git a/HellionChat/Ui/Windows/SettingsWindow.cs b/HellionChat/Ui/Windows/SettingsWindow.cs index 23b6455..aba18ee 100644 --- a/HellionChat/Ui/Windows/SettingsWindow.cs +++ b/HellionChat/Ui/Windows/SettingsWindow.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace HellionChat.Ui.Windows; -// `internal` to match the Plugin.SettingsWindow property in W2; `public` here +// `internal` to match the Plugin.SettingsWindow property; `public` here // would raise CS0053 against the internal members. Matches MainWindow shape. internal sealed class SettingsWindow : Window { diff --git a/HellionChat/Util/ColourUtil.cs b/HellionChat/Util/ColourUtil.cs index a8bd6ac..d888e09 100755 --- a/HellionChat/Util/ColourUtil.cs +++ b/HellionChat/Util/ColourUtil.cs @@ -91,7 +91,7 @@ internal static class ColourUtil } // Modulates the alpha byte of an ABGR color by a factor in [0, 1]. - // RGB stays intact. Used by the PM-3 hover-lerp path where each + // RGB stays intact. Used by the hover-lerp path where each // frame produces a fractional alpha value but the colour itself // must not shift. internal static uint ApplyAlpha(uint abgr, float alphaFactor) @@ -103,7 +103,7 @@ internal static class ColourUtil } // Mixes an ABGR colour's RGB channels toward white (0xFF) by factor t in - // [0, 1]; the alpha byte is left untouched. A1 hover-sheen accent-tint: + // [0, 1]; the alpha byte is left untouched. Hover-sheen accent tint: // a low factor nudges the sweep toward the element's accent hue without // going fully saturated (effect level stays "subtle"). RGB-only on // purpose -- DrawHoverSheen owns the alpha falloff. diff --git a/HellionChat/Util/ImGuiUtil.cs b/HellionChat/Util/ImGuiUtil.cs index db36fe0..4ed1fb3 100755 --- a/HellionChat/Util/ImGuiUtil.cs +++ b/HellionChat/Util/ImGuiUtil.cs @@ -90,10 +90,9 @@ internal static class ImGuiUtil using (ImRaii.PushColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int)ImGuiCol.TextDisabled])) ImGui.TextUnformatted("(?)"); - // AllowWhenDisabled — ohne das Flag liefert IsItemHovered bei - // ausgegrauten Settings false, der User könnte nicht mehr lesen - // warum eine Option nicht aktiv ist. Genau dann braucht er den - // Hover-Tooltip aber am dringendsten. + // AllowWhenDisabled, because without it IsItemHovered returns false on a + // greyed-out setting -- and a reader who cannot find out why an option is + // inactive is exactly the reader who needs the tooltip most. if (!ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) return; diff --git a/HellionChat/Util/SenderNameDisplay.cs b/HellionChat/Util/SenderNameDisplay.cs index a9358da..3d4f959 100644 --- a/HellionChat/Util/SenderNameDisplay.cs +++ b/HellionChat/Util/SenderNameDisplay.cs @@ -4,7 +4,7 @@ using HellionChat._Helpers; namespace HellionChat.Util; -// UI-7: produces a render-only view of a chunk list with the sender's name +// Produces a render-only view of a chunk list with the sender's name // reformatted per the user's WorldSuffixMode / NameFormMode. Called from // ChatLogWindow.DrawChunks on every draw — it never mutates the input, so the // stored message (the Sender BLOB in the DB) stays byte-for-byte unchanged and @@ -76,7 +76,7 @@ internal static class SenderNameDisplay // text, and any cross-world icon) with one formatted chunk that keeps // the PlayerPayload link so the name stays clickable. Dropping the // original sender icon is an accepted trade-off and only happens once - // the user moves UI-7 off its defaults. + // the user moves off its defaults. // Channel brackets and colons are ChunkSource.None wrappers outside the // Sender span — they are preserved untouched by the copy loops below. var copy = new List(chunks.Count); diff --git a/HellionChat/Util/TabLifecycleHelpers.cs b/HellionChat/Util/TabLifecycleHelpers.cs index 5c9887f..998b5c3 100644 --- a/HellionChat/Util/TabLifecycleHelpers.cs +++ b/HellionChat/Util/TabLifecycleHelpers.cs @@ -72,7 +72,7 @@ internal static class TabLifecycleHelpers public static bool ShouldStripOnSave(Tab t) => IsInUnpinnedPool(t); - // GP-04: clear every Tab.PopOut at load time. The pool binds later, so at + // Clear every Tab.PopOut at load time. The pool binds later, so at // load NO tab can own a slot — a persisted PopOut=true is always a stale flag // with no window. Unconditional (pinned included) because pinned TempTabs // survive the load and are the main stale-flag source; a !IsPinned filter @@ -91,7 +91,7 @@ internal static class TabLifecycleHelpers // partner-name label) so a normal typed line cannot route as a silent /tell // to the old partner — the same privacy guard StripTellBindingOnPromote // applies on promote. Re-activating the already-active tab must NOT strip - // (a live game-tell would lose its context, TR-4); a tab carrying its own + // (a live game-tell would lose its context); a tab carrying its own // Tab.TellTarget is a real tell binding (leg1) and is left intact. internal static void OnTabActivated(Tab tab, Tab? previous) { diff --git a/HellionChat/_Helpers/PluginDisclosureScanner.cs b/HellionChat/_Helpers/PluginDisclosureScanner.cs index 5f4029e..768330f 100644 --- a/HellionChat/_Helpers/PluginDisclosureScanner.cs +++ b/HellionChat/_Helpers/PluginDisclosureScanner.cs @@ -1,6 +1,6 @@ namespace HellionChat._Helpers; -// UI-11 pure decision helper: does a message about to be sent carry a glyph +// pure decision helper: does a message about to be sent carry a glyph // that only renders correctly for players running HellionChat or a similar // plugin? Those are FFXIV Private-Use-Area icon codepoints (the same range // SeIconChar covers); a recipient without a plugin sees an empty box. diff --git a/HellionChat/_Helpers/SenderNameFormatter.cs b/HellionChat/_Helpers/SenderNameFormatter.cs index a47b11b..5637ad5 100644 --- a/HellionChat/_Helpers/SenderNameFormatter.cs +++ b/HellionChat/_Helpers/SenderNameFormatter.cs @@ -2,7 +2,7 @@ using System; namespace HellionChat._Helpers; -// UI-7 pure decision helper: builds the display string for a sender's name + +// pure decision helper: builds the display string for a sender's name + // world per the user's NameFormMode / WorldSuffixMode. Dalamud-free so the // Build Suite can cover every combination; SenderNameDisplay feeds it the name // and world it pulled from the PlayerPayload.