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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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<float> 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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<string> CategoryMapSlugs => CategoryMap.SelectMany(c => c.Slugs);
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user