Commit Graph
641 Commits
Author SHA1 Message Date
JonKazama-Hellion a2d8a9c223 feat(themes): add an export button for the active theme 2026-06-15 16:55:50 +02:00
JonKazama-Hellion dcf089b886 chore(release): bump manifest to 1.8.8 for theme export, default-fill, font-apply 2026-06-15 16:18:05 +02:00
JonKazama-Hellion c4562dd6a0 style(selftests): wrap HonorificTitleData ctor to satisfy csharpier
Inherited csharpier drift from the 1.8.7 merge (72099c8); format-only, no behaviour change.
2026-06-15 16:18:05 +02:00
JonKazama-Hellion 8afcb87624 test(about): assert integrations status through the real render 2026-06-15 14:44:26 +02:00
JonKazama-Hellion f9ed487ae2 feat(about): restore the integrations section with honorific status 2026-06-15 14:40:21 +02:00
JonKazama-Hellion 72099c8871 test(honorific): assert the title gate through the real draw path 2026-06-15 14:35:20 +02:00
JonKazama-Hellion fe766285ad feat(honorific): wire title gate + colour + truncation, restore preview glyphs 2026-06-15 14:26:22 +02:00
JonKazama-Hellion 8db2dee38c chore(release): bump manifest to 1.8.7 for honorific + integrations restoration 2026-06-15 13:53:06 +02:00
JonKazama-Hellion 5dfe8e3b49 fix(unread): restore the tab unread badge and fix the post-F2 unread decision
The v1.8.x sidebar/top-bar rebuild never re-rendered the unread dot, so inactive tabs showed no badge even though the counter was tracked. Draw it again top-right of the tab icon in both Sidebar and TopTabBar, gated on !active && UnreadMode != None && Unread > 0, and zero the active tab's counter every frame (1.5.6 convention) so the dot only ever shows on tabs you are not looking at.

The unread decision moves to MessageManager.ShouldCountUnread and snapshots the active tab + whether it shows the message once before the loop: Unseen suppresses unread on an inactive tab only when the active (real, post-F2) tab also shows that message. Adds SidebarUnreadDotStep (render) and UnreadDecisionStep (decision) self-tests (step count 32 -> 34).
2026-06-13 18:49:27 +02:00
JonKazama-Hellion 0ca8513065 fix(tell): couple CurrentTab to the active tab, retire LastTab
Plugin.CurrentTab now delegates to MainWindow.ActiveTab (fallback Tabs[0]) instead of the never-assigned LastTab index, so the game hooks, unread tracking, notification sounds, InputDisabled and Foray/Eureka paths all operate on the tab the user actually has selected. The dead LastTab/WantedTab fields and both WantedTab writes are removed.

A reference-based MainWindow.ResetActiveTabIfRemoved repairs the active-tab reference on eviction/logout (immune to the SaveConfig temp-tab strip window). The worker-thread eviction path marshals it onto the framework thread so the strip mutation serializes with Draw; logout is already framework-thread. The Draw-seed gains a lazy re-seed for a wholesale config swap. Adds CurrentTabCouplingStep (headless) and the interactive CurrentTabGuidedStep self-test (step count 30 -> 32).
2026-06-13 16:09:59 +02:00
JonKazama-Hellion ad635c77c1 fix(tell): strip stale tell state on tab activation
OnTabActivated clears the runtime tell state the game-side detour leaves on a tab (CurrentChannel tell target + partner label) when a DIFFERENT tab becomes the input surface, so a normal typed line can no longer route as a silent /tell to the old partner. Re-clicking the active tab and tabs carrying their own Tab.TellTarget binding (leg1) are preserved.

All four activation paths route through it: Sidebar, TopTabBar, ChannelPopoutPool.TryOpen, and the MainWindow draw-seed. EnsureCurrentChannel becomes a pure derive-helper reached only via OnTabActivated. Adds the TellResetOnActivateStep self-test (step count 29 -> 30).
2026-06-13 15:09:38 +02:00
JonKazama-Hellion 593eb30c9f chore(release): bump manifest to 1.8.6
Branch start for the LastTab-Decoupling fix cycle. csproj <Version> and repo.json AssemblyVersion + TestingAssemblyVersion go 1.8.5 -> 1.8.6. DownloadLinks and Changelog stay release-deferred on v1.5.6.
2026-06-13 14:23:10 +02:00
JonKazama-Hellion c28e3f72a1 feat(messages): restore scroll-to-bottom bar with snap decision 2026-06-10 16:55:26 +02:00
JonKazama-Hellion dc51e295ea feat(sidebar): restore section headers and compact separators 2026-06-10 16:22:49 +02:00
JonKazama-Hellion 540cb7ac52 feat(sidebar): restore per-tab greeted toggle glyph 2026-06-10 14:59:51 +02:00
JonKazama-Hellion 1f2c354471 feat(sidebar): restore per-tab notification sound picker with preview 2026-06-10 13:26:55 +02:00
JonKazama-Hellion ac7f74b227 feat(sidebar): restore tab rename via shared context menu 2026-06-10 11:42:44 +02:00
JonKazama-Hellion c7047407f5 feat(core): add static Plugin.Instance handle for UI helper access 2026-06-10 10:09:32 +02:00
JonKazama-Hellion e5a17ee798 chore(release): bump manifest to 1.8.5 for sidebar-ui restoration 2026-06-10 10:01:55 +02:00
JonKazama-Hellion 51c8f79846 chore(release): bump manifest to 1.8.4 for tell-routing restoration
Download links stay on v1.5.6 (local-only block, no public release yet).
2026-06-04 17:11:32 +02:00
JonKazama-Hellion d40b120b91 fix(tell): restore outgoing tell routing from the input bar
Input-bar tells went out as a bare "/t" without the target, so the game
rejected them with "you must add the World name". Rebuild the full
"/tell name@world" from the 1.5.6 target chain in a pure BuildOutgoing:

- leg2/leg3 gated on current == Tell so a stale tell target on a Say tab
  can't send a say line silently as /tell (CORR-1)
- world-resolve gate: an unresolvable world falls back to the channel
  prefix, never "/tell name@ text" (COMP-1)
- ResetTempChannel after the send, tell-only

Also clear the runtime tell state on PromoteToPermanent so a promoted tab
can't route a typed line to the old partner, and surface the tell partner
("-> name@world") in the channel pill so a misfire stays visible. Adds
tell-routing and pill-transparency self tests.
2026-06-04 17:11:32 +02:00
renovate-bot 7ef1337ea0 chore(deps): update minor and patch updates (nuget)
Build / Build (Release) (pull_request) Successful in 26s
Security / scan (pull_request) Successful in 20s
2026-06-03 06:06:55 +00:00
JonKazama-Hellion b0bee25770 feat(input): warn and hold before sending plugin-only symbols 2026-05-31 00:45:31 +02:00
JonKazama-Hellion 92f1736ea9 feat(settings): add world suffix and name format combos to the chat tab 2026-05-31 00:36:09 +02:00
JonKazama-Hellion 83b1708d5d feat(messages): render sender names through the name-aware path 2026-05-31 00:31:48 +02:00
JonKazama-Hellion 8fcb10cf51 chore(release): bump manifest to 1.8.3 for restoration block 2 2026-05-31 00:11:29 +02:00
JonKazama-Hellion 78d56f0e3e fix(channels): restore auto-tell limit range to 50 and relocate enable toggle 2026-05-30 19:04:32 +02:00
JonKazama-Hellion ca00f528d6 feat(config): drop dead SidebarTabView and migrate false to top tabs (schema v23) 2026-05-30 18:55:26 +02:00
JonKazama-Hellion a7a5aee982 feat(sidebar): wire configurable expanded width through a single source 2026-05-30 18:22:38 +02:00
JonKazama-Hellion caacb87a6a feat(window): wire move/resize flags and consolidate the duplicate toggle 2026-05-30 17:54:15 +02:00
JonKazama-Hellion 336f722eef feat(window): wire inactive opacity to main window focus state 2026-05-30 16:57:59 +02:00
JonKazama-Hellion 7792b327dc chore(release): bump manifest to 1.8.2 for restoration block 1 2026-05-30 16:17:06 +02:00
JonKazama-Hellion c84891e75d docs(selftest): add binding render-path selftest standard 2026-05-30 08:43:06 +02:00
JonKazama-Hellion 6af9e05664 test(selftest): add PayloadHandler and ChunkRenderer ctor smoke steps 2026-05-30 08:40:51 +02:00
JonKazama-Hellion ea549ebcd0 test(selftest): remove dead ConfigMigrationV21 step superseded by V22 2026-05-30 08:23:29 +02:00
JonKazama-Hellion d33c25e77a chore(release): bump manifest to 1.8.1 for restoration block 0 2026-05-30 08:18:16 +02:00
JonKazama-Hellion ad892cbcb6 feat(layout): add top-tabs layout mode and shared channel resolver 2026-05-29 14:06:41 +02:00
JonKazama-Hellion a9e70ce2af fix(popout): guard against mid-frame unbind when closing from the header 2026-05-29 13:29:29 +02:00
JonKazama-Hellion db47708264 feat(popout): wire pool + window render + sidebar pop-out routing 2026-05-29 12:49:21 +02:00
JonKazama-Hellion e786257cb3 feat(config): add MainWindowLayoutMode + v22 migration; scaffold popout pool 2026-05-29 11:56:18 +02:00
JonKazama-Hellion b221a6e418 feat(input-bar): wire auto-translate tab picker + payload-replace on send
v1.7.0 component-layer refactor removed ChatLogWindow.cs (which housed
the auto-translate popup) and dropped Ui/AutoCompleteInfo.cs without
migrating the logic into the new InputBar component — v2.x spec §3
said "LÖSCHEN + Logik migrieren", but only the deletion happened.
Result: Tab key did nothing in v1.7.1, and even manually typed
<at:group,key> tokens were never resolved into real auto-translate
payloads on send.

Root cause confirmed empirically via VN-1 diagnostic build
(_logger.LogDebug in SlashCommandCallback proved CallbackCompletion
fires on Tab once the flag is set). Following the diagnose-zuerst
pattern established by Issue #3 to avoid the source-code-only
hypothesis trap from Issue #2.

Migration follows v1.5.6 ChatLogWindow.DrawAutoComplete + ChatTwo
upstream AutoCompleteHandler patterns, but ported to v1.7.0 stil:

- ImGuiInputTextFlags extended with CallbackCompletion (Tab trigger)
  and CallbackAlways (cursor restore via _activatePos analog v1.5.6
  ActivatePos)
- SlashCommandCallback now dispatches three branches: CallbackAlways
  (cursor restore), CallbackCompletion (Tab → word-boundary search
  via Encoding.UTF8.GetString on the byte span, char-offset DTO
  construction to avoid the byte-vs-char drift in v1.5.6's raw
  pointer arithmetic), CallbackEdit (existing slash-command help
  detection, now properly scoped)
- 7 new private state fields (_autoCompleteInfo, _autoCompleteOpen,
  _autoCompleteList, _fixCursor, _autoCompleteSelection,
  _autoCompleteShouldScroll, _activatePos)
- DrawAutoCompletePopup renders the picker at the end of Draw():
  IsWindowAppearing seeds _fixCursor + focus, ListClipper-wrapper
  from Util/SearchSelector.cs (IDisposable, automatic Destroy) for
  the result list, Ctrl+0-9 quick-pick, Enter/Escape handling,
  char-splice commit (_pendingMessage = before + replacement + after)
- AutoCompleteCallback handles popup-input-field fix-cursor seeding,
  Up/Down navigation with wrap-around, Tab cycle in the default case
- TrySend now runs AutoTranslate.ReplaceWithPayload(ref bytes) and
  sends via ChatBox.SendMessageUnsafe(byte[]) with a manual 500-byte
  guard, because SendMessage(string) would route through SanitiseText
  which destroys the binary SeString macro bytes that
  ReplaceWithPayload emits
- AutoCompleteInfo DTO added as sealed internal companion type at the
  end of InputBar.cs (15 LOC, exclusively consumed by InputBar);
  ToComplete is a mutable field rather than auto-property so it can
  be passed as ref to ImGui.InputTextWithHint without CS0206

Verified in-game (Flo): Tab on empty input opens picker with full
list, "fire" + Tab filters correctly, Up/Down/Tab navigate, Enter
commits <at:group,key>, send resolves to real auto-translate payload
in chat, Ctrl+0-9 quick-pick works, Escape closes without commit.
dotnet build clean, dotnet csharpier check clean.

Single minor plan-drift: scroll-to-selected uses
ImGui.SetScrollY(selection * lineHeight) instead of
SetScrollFromPosY(clipper.StartPosY) because the local
ListClipper-wrapper does not expose StartPosY — same UX effect.
2026-05-28 17:23:11 +02:00
JonKazama-Hellion 0319636fc5 fix(chat): route inventory item-link addIfNotPresent into InputBar
The AddonChatLog.OnRefresh hook is registered and fires correctly
when the user picks "Link item" from the inventory right-click menu
in-game. The detour extracts addIfNotPresent="<item>" from the
AtkValue array — verified empirically via a temporary _logger.LogDebug
diagnostic build (eventId=31 valueUInt=C addIfNotPresent=<item>).

Pre-fix the extracted value was discarded with `_ = addIfNotPresent;`
and a comment "Chat-window Activated integration is offline until the
new chat layer surfaces an Activated entry point." The Activated entry
point on the new v1.7.0 component layer has existed since that cycle
(InputBar.AppendPending + InputBar.Activate, same pattern as
PayloadHandler.DrawStatusPopup:546-549), but the rewiring was forgotten
when ChatLogWindow.Activated() was removed.

Route addIfNotPresent through InputBar.AppendPending with a
v1.5.6-equivalent !PendingMessage.Contains() guard to prevent
double-insertion on repeated OnRefresh events. Activate = true marks
the input bar for ImGui.SetKeyboardFocusHere on the next draw, so the
user can immediately keep typing after the link is inserted.

Verified in-game: right-click "Link item" on multiple inventory items
inserts <item> into the HellionChat input bar, repeated link insertion
does not produce <item><item>, MainWindow gains keyboard focus.
2026-05-28 16:03:57 +02:00
JonKazama-Hellion b954a19b67 fix(payload-handler): popup-pfad in MessageList-Child-Scope verschieben
Seit dem v1.7.0-Components-Layer-Refactor lebte der PayloadHandler-
Popup-Render in MainWindow.Draw als _messages.DrawHandlerPopups()-
Aufruf nach dem ##hellion-body-Child-Close. ImGui.OpenPopup (in
RightClickPayload, innerhalb ##hellion-main-area-Child) und
ImGui.BeginPopup (in PayloadHandler.DrawPopups, im MainWindow-Root
nach Child-Close) hashed die Popup-ID per g.CurrentWindow->GetID(...)
window-relativ — also unterschiedlich. OpenPopupStack-Eintrag wurde
nie gefunden, popup.Success blieb false, _popup wurde auf null
zurückgesetzt. Alle vier Popup-Switch-Cases waren tot: URL-Rechtsklick,
Player, Item (inkl. EventItem-Subpfad), Status.

Fix nach v1.5.6/ChatTwo-Pattern: _handler?.Draw() ans Ende von
MessageList.Draw() verschieben. MessageList läuft im
##hellion-main-area-Scope und öffnet selbst kein Child, also teilen
OpenPopup und BeginPopup denselben Window-Stack. ID-Hash matched,
Popup rendert.

DrawHandlerPopups-Wrapper aus MessageList und der Aufruf in
MainWindow.Draw entfallen — kein toter Code mehr (grep
DrawHandlerPopups: 0 Treffer).

Hypothese verifiziert gegen imgui.h:845 + imgui.cpp:12282+12528
(beide BeginPopup-Hash und OpenPopup-Hash sind window-relativ),
v1.5.6 ChatLogWindow.cs:1667 (handler.Draw im
##chat2-messages-Child), ChatTwo ChatLog.Window.cs:620 (identisches
Pattern). Reader-Lock auf tab.Messages bleibt während DrawPopups
gehalten — identisch zu v1.5.6-Semantik.

Verifiziert in-game (Flo): Linksklick auf URL öffnet Browser direkt
(v1.5.6-konform), Rechtsklick öffnet wieder das Kontext-Popup. dotnet
build clean, dotnet csharpier check clean.

Plan-Runde 1 dieses Cycles (4-LOC-Reroute LeftClick → RightClickPayload)
wurde verworfen weil empirischer Test zeigte dass auch Rechtsklick
broken war — der Reroute hätte das Symptom nur sichtbarer gemacht
ohne die Root-Cause zu adressieren.
2026-05-28 15:25:05 +02:00
JonKazama-Hellion 29fb4b92eb fix(input-preview): wire Inside-mode + Tooltip-mode render paths
InputPreview was only rendered for PreviewPosition.Top/Bottom (the
DrawConditions IsWindowMode gate). Inside-mode (the default) and
Tooltip-mode had no caller at all because v1.5.6's inline-render path
lived on the deleted ChatLogWindow and was not migrated to the v1.7.0
Components-Layer.

Wire Inside-mode by calling CalculatePreviewHeight + DrawPreview
inline from MainWindow.DrawMainArea between the message-list child
and the input bar, with the message-list height reserved for the
preview block. Wire Tooltip-mode by sampling IsItemHovered() on the
input text widget inside InputBar.DrawInputField (analog to the
existing _isFocused = ImGui.IsItemFocused() idiom on the same line)
and exposing it as WasInputTextHovered; MainWindow opens the tooltip
after _input.Draw when both the hover-flag and PreviewPosition.Tooltip
are active.

Plan-drift acknowledged: the plan stated Plugin.InputPreview is
statically reachable, but the property was declared as an instance
member on Plugin.cs:101. Hoisted to internal static to match the
plan's intention (analog to Plugin.Config); updated the single
external instance-access site in PluginLifecycle.RegisterWindows
to the type-qualified form.

Verified in-game: Inside-mode preview block appears between message
list and input bar on first keystroke; tooltip-mode shows preview on
text-field hover only; Top/Bottom-mode unchanged; empty buffer hides
the preview in all modes. dotnet build clean, dotnet csharpier check
clean.
2026-05-28 13:21:59 +02:00
JonKazama-Hellion 24d3f69041 fix(host): break InputBar/CommandHelpWindow/MainWindow DI cycle
J + J2 closed a singleton cycle:
  InputBar.ctor -> CommandHelpWindow (J2)
  CommandHelpWindow.ctor -> MainWindow (J)
  MainWindow.ctor -> InputBar (pre-existing)

MS.DI does not detect cycles through FactoryCallSite registrations,
so resolution recursed silently on the async plugin-init thread until
the worker died with an uncatchable StackOverflowException. Dalamud's
LoadAsync task never resolved; the plugin UI hung on "Enabling..."
with no exception in the log. First triggered at Plugin.cs:289
(TypingIpc.ctor needs InputBar).

Fix: break the cycle on the laziest edge.
  - CommandHelpWindow.ctor no longer takes MainWindow.
  - New AttachMainWindow setter wired in
    CommandHelpWindowInitHostedService.StartAsync, mirroring the
    existing §6.2 MessageList.AttachPayloadHandler pattern.
  - UpdateContent throws InvalidOperationException if the setter
    never ran, so a future regression fails loudly instead of a
    silent NullRef during input draw.

Also enable UseDefaultServiceProvider(ValidateOnBuild + ValidateScopes)
so future ConstructorCallSite cycles throw at Build time instead of
silently hanging. Catches reflection-based registrations; will not
catch FactoryCallSite cycles like this one (those still need code review).

Verified via 6 enable/disable cycles in-game; plugin loads cleanly,
Hosting starts, FilterAllTabs completes, command help popup renders
for /em and /say (exercises AttachMainWindow), hover counter ticks
(exercises PayloadHandlerInitHostedService AddonLifecycle wiring).
2026-05-28 08:16:27 +02:00
JonKazama-Hellion f6749d206b chore(polish): cycle-end sweep — drop dead fields, dep-cycle, comments
Accumulated polish across the v1.7.1 R-Block reviewer findings. Single
sweep before Phase-3 Smoke-Gate.

Dep-cycle cleanup (Block H + #30):
- CommandHelpWindow drops the dead _inputBar ctor-param + discard that
  was J's speculative prep; this eliminates the InputBar <-> CommandHelpWindow
  ctor cycle at its root
- InputBar replaces Lazy<CommandHelpWindow> wrapper with direct
  CommandHelpWindow ctor-param now that the cycle is broken
- PluginHostFactory InputBar + CommandHelpWindow DI-regs simplified

Dead-field removals:
- MessageList drops _themes + _resolver (no reads after H's render-path
  swap to _chunkRenderer.DrawChunks)
- InputBar drops FocusedPreview (no consumer wiring in the new architecture)
- InputPreview drops SelectedCursorPos (v1.5.6 letter-by-letter renderer
  artifact, no callers in R1)
- InputPreview drops WhitespaceRegex + partial keyword on class (dead
  GeneratedRegex with no callers)

Visibility fixes:
- InputPreview + CommandHelpWindow + DebuggerWindow ctors flip
  public -> internal for consistency with internal sealed class declarations

DI helper extraction:
- PluginHostFactory MakePayloadHandler private static helper DRYs the
  7-arg list shared between PayloadHandler-singleton and Lender<T> factory

ImGui-rendering fix:
- MessageList.DrawCompactRow uses SameLine(0f, 0f) — eliminates visible
  ItemSpacing.X gap between sender-prefix and chunk content

Bug fixes:
- PayloadHandler.LeftClickPayload drops spurious unsafe keyword (no
  pointer ops in the method body; v1.5.6 had no unsafe here)
- PayloadHandler.StringifyMessage Aggregate seeded with string.Empty to
  fix empty-sequence crash for pure-icon messages
- PayloadHandler.MoveTooltip args==null LogWarning template simplified
  (?.GetType().Name was always null after the null-check — misleading)
- InputBar.SlashCommandCallback drops redundant BufTextLen==0 guard
  (BufTextSpan handles empty correctly)

Comment improvements (WHY-not-WHAT):
- ImGuiUtil.cs payload-state cluster comment moved below Buttons array
- PayloadHandler: §6.9 trimmed to 1 line, FindCharacterForPayload
  documented, hq symbol marker restored, MoveTooltip guard documented
  as defensive v1.7.1 addition, NativeItemTooltips branch explained,
  §4.2 theme colour swap explained
- DebuggerWindow class comment mentions PayloadHandler counters section
- InitHostedServices StopAsync explains params-overload semantics
- InputBar AppendPending null policy vs SetPendingMessage documented,
  CommandManager leading-slash assumption noted
- PluginHostFactory block comment explains singleton+Lender split

Build: 0 warnings, 0 errors. csharpier: clean. Version unchanged.
2026-05-27 23:42:28 +02:00
JonKazama-Hellion d1bfddd9b8 feat(main-window): wire Lender + handler.Draw() (A2, MessageList popups)
A2 completes the deferred Lender-cycle from A1 and addresses the
handler.Draw() gap identified in I code-quality-review:

- MainWindow ctor takes Lender<PayloadHandler> as new param (DI-reg
  extended in PluginHostFactory); _handlerLender.ResetCounter() called
  at top of Draw() as primary pool-reset path (InputPreview has the
  secondary defensive fallback for MainWindow-closed edge case)

- MessageList.DrawHandlerPopups() new passthrough method
  (=> _handler?.Draw()) provides the per-frame popup-tick that
  PayloadHandler needs to render the right-click context popup;
  MainWindow.Draw() calls it after the message-list body renders

Without this fix, right-clicking a player/item/status in the chat log
would silently fail to open a popup (handler.Draw() never fired for the
MessageList's _handler). Phase 3 smoke steps 3/4/5 unblocked.

Polish-Sweep + Smoke-Gate are the last cycle-tasks.
2026-05-27 23:29:18 +02:00
JonKazama-Hellion cba6a16f8e feat(input-bar): wire slash-command callback + AllCommands (J2)
J2 closes the trigger-gap discovered in J review (2026-05-27): J
migrated CommandHelpWindow as a window but the v1.5.6 trigger-path
was never ported. J2 restores it:

- InputBar.cs adds ImGuiInputTextFlags.CallbackEdit + character-level
  callback that reads data.BufTextSpan, detects /-prefix, extracts
  command word, and calls _commandHelpWindow.Value.UpdateContent(desc)
- AllCommands.cs (new file, 1:1 port from v1.5.6) populates a static
  Dictionary<string, TextCommand> from Sheets.TextCommandSheet at
  startup; Plugin.CommandManager.Commands is the fallback for
  non-hardcoded commands
- CommandHelpWindow injected into InputBar via Lazy<T> ctor param to
  break the InputBar <-> CommandHelpWindow circular dep; PluginHostFactory
  DI-reg extended with the Lazy wrapper accordingly

Closes the smoke-step-9 gap. Phase-3 windows are now all reachable
end-to-end (R1 InputPreview, R2 CommandHelpWindow, R3 DebuggerWindow).
2026-05-27 23:19:21 +02:00
JonKazama-Hellion c652a1c450 feat(debugger): reactivate PayloadHandler counters (R3)
K reactivates the debugger's PayloadHandler counter readout
(HandleTooltips / HoveredItem / HoverCounter / LastHoverCounter —
populated in E1's PayloadHandler skeleton). PayloadHandler injected
via DI-extended ctor; class flipped to internal sealed to match
PayloadHandler's internal visibility and avoid CS0051. Plugin.cs
property updated public → internal accordingly (same pattern as I/J).

Last Phase-3 window sub-task before A2 (Lender + handler.Draw fix),
J2 (InputBar slash-callback), Polish-Sweep, and Smoke-Gate.
2026-05-27 22:54:33 +02:00
JonKazama-Hellion 830d247eda feat(command-help-window): full R2 migration (ctor-injected + DI-reg)
J resurrects CommandHelpWindow from the v1.7.0 stub state:

- Class header public → internal sealed
- Ctor takes 4 DI deps (ChunkRenderer, MainWindow, InputBar, ILogger)
  via Factory-Lambda DI-reg. NO Lender<PayloadHandler> — command-help
  chunks are read-only command-description text with no click-targets
  (per spec §5-J + F W8 consumer audit).
- Draw() calls _chunkRenderer.DrawChunks(desc chunks, wrap: true,
  handler: null, lineWidth: 0f) — null-handler is intentional.
- Plugin.cs property visibility flipped public → internal to satisfy
  CS0053 (analogous to I's InputPreview fix).

K (R3 DebuggerWindow counters) and A2 (Lender + handler.Draw fix) are
the remaining Phase-3 sub-tasks before Polish-Sweep + Smoke-Gate.
2026-05-27 21:04:42 +02:00