chore: comments say what the code does, not which task produced it
A comment that reads "MUST stay in lockstep with TryGetActiveCrossfade (K8)" helps nobody outside the plan that used to have a K8 in it, and the plans are not in this repo. Same for "Spec FR-4", "plan §B.2", "Sub-Task 4.4" and the F/R/M/A/S round codes scattered through the style engine and the self-tests. Personal names go too. "tester feedback from Jin (v1.4.7)" and "Flo decision 2026-06-15" carry the reason fine without naming anyone -- the version and the reason are the parts a reader can act on, and a public repo should not need a cast list to be read. The rule applied throughout: keep the why, drop the reference. Version numbers stay, since those resolve through the changelog. 77 files. ChunkUtil also carried 281 lines of commented-out code -- an older ToChunks variant and two helpers with no callers, inherited and never removed. Deleted; git remembers them.
This commit is contained in:
@@ -18,7 +18,7 @@ internal sealed class CommandHelpWindow : Window
|
||||
// Setter-injected post-ctor to break the InputBar -> CommandHelpWindow ->
|
||||
// MainWindow -> InputBar singleton cycle (MS.DI does not detect cycles
|
||||
// through FactoryCallSite registrations). Wired in
|
||||
// CommandHelpWindowInitHostedService.StartAsync, same §6.2 pattern as
|
||||
// CommandHelpWindowInitHostedService.StartAsync, same setter-injection pattern as
|
||||
// MessageList.AttachPayloadHandler.
|
||||
private Windows.MainWindow? _mainWindow;
|
||||
|
||||
@@ -41,7 +41,7 @@ internal sealed class CommandHelpWindow : Window
|
||||
RespectCloseHotkey = false;
|
||||
DisableWindowSounds = true;
|
||||
|
||||
// Logger injected for future diagnostic hooks (no call-sites yet in R2).
|
||||
// Logger injected for future diagnostic hooks; no call sites yet.
|
||||
_ = _logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
namespace HellionChat.Ui.Components;
|
||||
|
||||
// B2 (PERF-B2): variable-height clip plan. ImGuiListClipper needs a constant
|
||||
// row height, and since v1.10.0/A2 neither density has one (compact rows wrap
|
||||
// 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
|
||||
// the viewport, the [first..last] index range that overlaps the viewport, and
|
||||
|
||||
@@ -118,7 +118,7 @@ internal sealed class InputBar
|
||||
// Note: when MainWindow is closed, DrawInputField never runs, so
|
||||
// _isFocused keeps the last value written by the previous draw pass.
|
||||
// The consumer that actually pushes this state across the IPC boundary
|
||||
// (TypingIpc.BuildState, see F3 Step 2) gates on Plugin.MainWindow.IsOpen
|
||||
// (TypingIpc.BuildState) gates on Plugin.MainWindow.IsOpen
|
||||
// itself, so the stale backing-field never leaks to subscribers. Mirroring
|
||||
// the gate here would require an extra Plugin-backref in InputBar that the
|
||||
// rest of the component doesn't need.
|
||||
@@ -1183,7 +1183,7 @@ internal sealed class InputBar
|
||||
}
|
||||
|
||||
// DTO for an in-flight auto-translate completion. Lives as a companion type
|
||||
// in this file because it is only consumed by InputBar (see v1.7.1 Fix #4 plan §2.4).
|
||||
// in this file because it is only consumed by InputBar.
|
||||
internal sealed class AutoCompleteInfo
|
||||
{
|
||||
// ToComplete MUST be a mutable field (not an auto-property), because the
|
||||
|
||||
@@ -38,7 +38,7 @@ internal sealed class MessageList
|
||||
private readonly Action<Message, string?> _drawCardRow;
|
||||
|
||||
// Reused across frames: at MessageManager.MessageDisplayLimit a fresh array
|
||||
// per frame is 40 KB of garbage, and A2 put the default density on this
|
||||
// per frame is 40 KB of garbage, and A later cycle put the default density on this
|
||||
// path. The old comment named MaxLinesToRender and its 2500 default, a
|
||||
// config field that had stopped bounding anything.
|
||||
private float[] _heightScratch = [];
|
||||
@@ -49,7 +49,7 @@ internal sealed class MessageList
|
||||
private bool _stampVisible;
|
||||
private float _metaDrop;
|
||||
|
||||
// §6.2: setter-injection breaks the PayloadHandler → MainWindow → MessageList → PayloadHandler 3-cycle.
|
||||
// Setter-injection breaks the PayloadHandler → MainWindow → MessageList → PayloadHandler 3-cycle.
|
||||
// Wired by PayloadHandlerInitHostedService.StartAsync after both singletons exist.
|
||||
internal void AttachPayloadHandler(PayloadHandler handler)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ internal sealed class MessageList
|
||||
|
||||
// SelfTest hook (B2): 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/A1).
|
||||
// the step can step past the settle window without sleeping (v1.10.0).
|
||||
internal int RunHeightCacheInvalidationForSelfTest(Tab tab, float contentWidth, long nowMs)
|
||||
{
|
||||
InvalidateHeightCacheIfLayoutChanged(tab, contentWidth, nowMs);
|
||||
@@ -569,7 +569,7 @@ internal sealed class MessageList
|
||||
// B2-1/B2-2: 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 (masterplan §6 -> v1.9.0); plain
|
||||
// sender is deferred styling polish (deferred to v1.9.0); plain
|
||||
// text here.
|
||||
// A system message has no sender, so a header row would be a stamp on a
|
||||
// line of its own -- an empty gesture. Those stay single-line in both
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed class LivePreviewPanel : IDisposable
|
||||
private static uint Abgr(StyleEngine.Token token, ThemeColors colors) =>
|
||||
ColourUtil.RgbaToAbgr(Tokens.Resolve(token, colors));
|
||||
|
||||
// Static counter for S5 reload-stress verification: after 10 reloads the
|
||||
// Static counter for reload-stress verification: after 10 reloads the
|
||||
// counter must read 0 (plugin disabled) or 1 (plugin enabled). Anything
|
||||
// higher signals a Dispose skip and a subscriber leak against ThemeRegistry.
|
||||
internal static int InstanceCount;
|
||||
|
||||
@@ -254,7 +254,7 @@ internal sealed class DataPrivacyTab
|
||||
)
|
||||
{
|
||||
// Read-only statement, not a switch. Do not promote it to one
|
||||
// without an explicit Sub-Spec change: a toggle implies there is
|
||||
// without an explicit design change: a toggle implies there is
|
||||
// something to turn off.
|
||||
ImGuiUtil.HelpText(HellionStrings.Settings_Telemetry_None);
|
||||
}
|
||||
|
||||
@@ -173,8 +173,7 @@ internal sealed class ThemeImportExportRow
|
||||
// Slug sanitisation BEFORE BeginEditing — SaveEditingBuffer would
|
||||
// reject too, but rejecting here means an unsafe slug never enters
|
||||
// the editing buffer. Shared helper ThemeRegistry.IsSafeThemeSlug
|
||||
// keeps the rule set in sync with F1's save-side guard (see
|
||||
// ThemeRegistry.IsSafeThemeSlug shared helper).
|
||||
// keeps the rule set in sync with the save-side guard.
|
||||
var importSlug = theme.Slug;
|
||||
if (!ThemeRegistry.IsSafeThemeSlug(importSlug))
|
||||
{
|
||||
@@ -186,9 +185,9 @@ internal sealed class ThemeImportExportRow
|
||||
return;
|
||||
}
|
||||
|
||||
// Pragmatic deviation from §1.6 wording ("File.Copy into themes/"):
|
||||
// BeginEditing+SaveEditingBuffer produces the same end-state and
|
||||
// reuses the validated F1 save pipeline. Trade-off: destination
|
||||
// Not a plain File.Copy into themes/: BeginEditing+SaveEditingBuffer
|
||||
// produces the same end state and reuses the validated save
|
||||
// pipeline. Trade-off: destination
|
||||
// filename becomes the theme's slug, not the original filename.
|
||||
//
|
||||
// Slug-collision handling:
|
||||
|
||||
@@ -54,7 +54,7 @@ internal sealed class InputPreview : Window
|
||||
DisableWindowSounds = true;
|
||||
IsOpen = true;
|
||||
|
||||
// TODO Polish-Sweep: remove discard once logging call-sites exist
|
||||
// TODO: remove discard once logging call sites exist
|
||||
_ = _logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace HellionChat.Ui.StyleEngine;
|
||||
// ABGR before delegating to ImDrawList.
|
||||
internal static class DrawListExtensions
|
||||
{
|
||||
// A1 accent-tint (Variante A): how far the white sweep is pulled toward
|
||||
// Accent tint: how far the white sweep is pulled toward
|
||||
// the element's accent hue. Kept low so the sheen reads as a tinted
|
||||
// highlight, not a saturated accent flash (effect level "subtle").
|
||||
private const float SheenTintStrength = 0.35f;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace HellionChat.Ui.StyleEngine;
|
||||
// compare an unscaled value (Sidebar.GetWidth, the width slider bounds).
|
||||
//
|
||||
// Deliberately NOT part of ThemeLayout: that record is serialised into theme
|
||||
// JSON, and layout customisation is out of scope per the master spec.
|
||||
// JSON, and layout customisation is deliberately out of scope.
|
||||
internal static class Metrics
|
||||
{
|
||||
// --- Sidebar ---
|
||||
@@ -65,7 +65,7 @@ internal static class Metrics
|
||||
return _cachedScale;
|
||||
|
||||
// Safe variant: GlobalScale throws while the interface manager is
|
||||
// still coming up, and Block F pulls Metrics into more call sites.
|
||||
// still coming up, and Metrics reaches more call sites than it did.
|
||||
_cachedScale = ImGuiHelpers.GlobalScaleSafe;
|
||||
_cachedFrame = frame;
|
||||
return _cachedScale;
|
||||
|
||||
@@ -23,7 +23,7 @@ internal enum TypeRole
|
||||
// exactly Body and never be pushed -- a value with no call site, which is the one
|
||||
// thing this whole style track exists to stop.
|
||||
//
|
||||
// The factors are defaults, not constants. The master spec puts typography under
|
||||
// The factors are defaults, not constants. Typography is meant to sit under
|
||||
// theme control rather than user control, and ThemeTypography already exists as
|
||||
// the extension point for exactly that. A const would wall it off. What is
|
||||
// deliberately absent either way is a user-facing slider per role.
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace HellionChat.Ui.StyleEngine.Widgets;
|
||||
//
|
||||
// So: no plate, but a tint. A tenth-opacity accent wash falling from the top
|
||||
// edge -- colour as atmosphere rather than as a box, which is what the plate got
|
||||
// wrong. Flo picked it from the lab over the rule-only variant; at this strength
|
||||
// it survives the violet themes that killed the filled bar.
|
||||
// wrong. Picked from the lab over the rule-only variant; at this strength it
|
||||
// survives the violet themes that killed the filled bar.
|
||||
//
|
||||
// Which face draws what is not a style choice here, it is a constraint. The meta
|
||||
// face has a glyph range of ASCII plus a middle dot, so only the world name and
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace HellionChat.Ui.Windows;
|
||||
// windows via the injected factory, all registered once in the WindowSystem
|
||||
// (PluginLifecycle.RegisterWindows, framework thread). Open/Close is IsOpen +
|
||||
// Bind/Unbind only — NEVER runtime AddWindow/RemoveWindow (v1.4.9 Stage-2
|
||||
// freeze lesson). Pure DI-sink: no PayloadHandler in the ctor (plan §B.2).
|
||||
// freeze lesson). Pure DI-sink: no PayloadHandler in the ctor.
|
||||
internal sealed class ChannelPopoutPool
|
||||
{
|
||||
private readonly List<ChannelPopoutWindow> _instances;
|
||||
@@ -30,7 +30,7 @@ internal sealed class ChannelPopoutPool
|
||||
|
||||
// Route each window's in-body close through the pool so closing releases
|
||||
// the slot. Wired here (post-construction) rather than via ctor to avoid
|
||||
// a Window->Pool edge that would re-enter pool resolution (plan §B.2).
|
||||
// a Window->Pool edge that would re-enter pool resolution.
|
||||
foreach (var window in _instances)
|
||||
window.CloseRequested = TryClose;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace HellionChat.Ui.Windows;
|
||||
|
||||
// One pre-allocated pop-out window bound to a single Tab. Pure DI-sink: the
|
||||
// PayloadHandler arrives via AttachPayloadHandler (post-build setter), NEVER
|
||||
// via ctor — see plan §B.2. The ###id carries the slot index so all N
|
||||
// via ctor. The ###id carries the slot index so all N
|
||||
// instances are unique for WindowSystem.AddWindow and ImGui state is stable
|
||||
// per slot (not per bound tab).
|
||||
internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
|
||||
@@ -66,10 +66,10 @@ internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
|
||||
|
||||
// Wired post-build by ChannelPopoutPool so closing routes through the pool
|
||||
// (which owns the slot map). The window can't reach the pool by ctor without
|
||||
// a DI cycle, so the pool sets this after construction. See plan §B.2.
|
||||
// a DI cycle, so the pool sets this after construction.
|
||||
public Action<Guid>? CloseRequested { get; set; }
|
||||
|
||||
// Post-build setter — see plan §B.2. Wired by ChannelPopoutInitHostedService.
|
||||
// Post-build setter. Wired by ChannelPopoutInitHostedService.
|
||||
public void AttachPayloadHandler(PayloadHandler handler) =>
|
||||
_messages.AttachPayloadHandler(handler);
|
||||
|
||||
@@ -78,7 +78,7 @@ internal sealed class ChannelPopoutWindow : Window, IFocusableChatWindow
|
||||
Bound = tab;
|
||||
|
||||
var isTell = tab is { IsTempTab: true, TellTarget: { } target } && target.IsSet();
|
||||
// Master §4.3 default sizes: Tell is the more compact conversation window.
|
||||
// Default sizes: Tell is the more compact conversation window.
|
||||
Size = isTell ? new Vector2(380f, 320f) : new Vector2(420f, 320f);
|
||||
SizeCondition = ImGuiCond.FirstUseEver;
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace HellionChat.Ui.Windows;
|
||||
// Variants of UI elements, drawn side by side so decisions are made by looking
|
||||
// rather than by imagining. Reachable with /hellion lab.
|
||||
//
|
||||
// Permanent, by Flo's call: a dev playground for seeing ideas in-game against
|
||||
// the live theme. The radios default to whatever shipped, so the window also
|
||||
// Permanent: a playground for seeing ideas in-game against the live theme.
|
||||
// The radios default to whatever shipped, so the window also
|
||||
// documents which variant won and what it beat.
|
||||
//
|
||||
// It exists because the alternative was drawing mockups, and mockups are what
|
||||
|
||||
Reference in New Issue
Block a user