Commit Graph
1514 Commits
Author SHA1 Message Date
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
JonKazama-Hellion 8431fbcf80 feat(input-preview): full R1 migration (PreOpenCheck/PreDraw split + Lender)
I resurrects InputPreview as a fully ctor-injected window:

- Class header public → internal sealed (Components-Layer style); Plugin.cs
  property visibility corrected to internal to match
- Ctor takes 5 DI deps (ChunkRenderer, Lender<PayloadHandler>, MainWindow,
  InputBar, ILogger) via Factory-Lambda DI-reg
- Window-hook split: PreOpenCheck() owns the state (Drawing/PreviewMessage/
  HasEvaluation/PreviewHeight/LastLength), PreDraw() owns position/size
  computation. Matches v1.5.6's split — avoids wasted position-math when
  Window isn't drawn (DrawConditions gates on IsDrawable getter).
- Framework.Update subscribe/unsubscribe removed (PreOpenCheck runs per
  draw-frame, same cadence as Framework.Update for our needs)
- Draw() borrows fresh PayloadHandler per-frame from Lender for popup
  isolation (preview hover doesn't bleed into log)
- Defensive ResetCounter fallback when MainWindow closed + InputPreview
  open — primary path is A2's MainWindow.Draw() ResetCounter

R2/R3 (J/K) next. A2 closes out the Lender DI-cycle for MainWindow.
2026-05-27 20:35:25 +02:00
JonKazama-Hellion 931a152d00 feat(infra): wire PayloadHandlerInitHostedService (AddonLifecycle + setter)
G connects PayloadHandler to the runtime — this is the activation point
after E1-E6 built the type and F registered it in DI:

- StartAsync calls MessageList.AttachPayloadHandler(_payloadHandler) to
  complete the §6.2 cycle-resolution (ctor-cycle was broken by setter,
  this is where the setter actually fires)
- StartAsync registers AddonLifecycle listener for MoveTooltip on
  PostUpdate of "ItemDetail" and "ActionDetail" addons
- StopAsync unregisters the listener
- Both Register/Unregister wrapped in Plugin.Framework.RunOnFrameworkThread
  as defensive insurance — IAddonLifecycle thread-affinity is not
  explicitly documented in Dalamud API; wrap keeps the v1.5.6 runtime
  contract intact (per spec §5-G note)

Mirrors existing IpcManagerInitHostedService / TypingIpcInitHostedService
pattern in Infrastructure/Hosting/. PluginHostFactory adds the
AddHostedService<PayloadHandlerInitHostedService>() registration.

After G, the chunked-message-render pipeline is end-to-end functional:
MessageList renders via ChunkRenderer, _handler is wired so popups fire
on click/hover, MoveTooltip repositions native item-tooltips away from
the chat window.
2026-05-27 20:03:52 +02:00
JonKazama-Hellion 4fb5ee6128 feat(message-list): wire ChunkRenderer ctor + AttachPayloadHandler setter
H integrates the chunk-render pipeline into MessageList:

- Extends ctor to 4 params (themes, resolver, fonts, chunkRenderer);
  TokenResolver preserved as load-bearing dep
- Adds private PayloadHandler? _handler field + internal
  AttachPayloadHandler(PayloadHandler) setter
- Switches DrawCompactRow/DrawCardRow render-path to
  _chunkRenderer.DrawChunks(message.Content, wrap, handler, 0f)
  instead of plain TextUnformatted

Setter-injection for PayloadHandler is the §6.2 cycle-resolution
(PayloadHandler → MainWindow → MessageList → PayloadHandler ctor-cycle
broken by post-construction wiring). G's HostedService.StartAsync will
call AttachPayloadHandler after both singletons resolve.

Also extends MessageList DI-reg in PluginHostFactory.cs with the
ChunkRenderer arg (4th GetRequiredService).
2026-05-27 19:24:20 +02:00
JonKazama-Hellion 2e143686af feat(host-factory): register ChunkRenderer + PayloadHandler + Lender (F)
F adds the 3 new DI registrations needed for the v1.7.1 R-Block:

- ChunkRenderer (4-param ctor: themes, fonts, logger, gameFunctions)
- PayloadHandler singleton (7-param ctor: themes, ipc, functions,
  inputBar, mainWindow, chunkRenderer, logger)
- Lender<PayloadHandler> factory (closure over sp, constructs a fresh
  PayloadHandler per Borrow() — used by InputPreview in Sub-Task I)

All three use Factory-Lambdas because Lender<T> has an internal ctor and
ChunkRenderer/PayloadHandler are internal sealed (ActivatorUtilities
can't reflect into internal ctors per [[reference_hellion_chat_di_container_v150]]).

MainWindow DI-reg update is deferred to Sub-Task A2 (split per Flo
2026-05-27 to avoid the DI-cycle that would otherwise emerge from the
PayloadHandler → MainWindow → MessageList → PayloadHandler graph —
cycle resolved via setter-injection on MessageList in G/H).

G is next: wires PayloadHandlerInitHostedService.StartAsync to register
the AddonLifecycle listener for MoveTooltip and call MessageList.
AttachPayloadHandler. H adds the MessageList ChunkRenderer ctor-param +
AttachPayloadHandler setter.
2026-05-27 18:44:46 +02:00
JonKazama-Hellion d6012a9459 feat(payload-handler): wire MoveTooltip (E6 completes PayloadHandler)
E6 closes out the PayloadHandler resurrection. MoveTooltip handles the
cross-viewport AddonLifecycle tooltip-repositioning logic — reads
MainWindow.LastViewport/LastWindowPos/LastWindowSize (from A1) to filter
events and reposition the native item tooltip away from the chat window.

Whole method marked `public unsafe void` per spec §4.2 (matches v1.5.6
exactly — avoids per-read unsafe-block scoping).

LogWarning added on the unexpected-AddonArgs early-out branch (wires
_logger into real use, prevents CS0414 unused-field warning).

PayloadHandler is now feature-complete. F registers it in DI; G wires
the AddonLifecycle.RegisterListener for MoveTooltip from a HostedService;
H adds MessageList.AttachPayloadHandler setter-injection.
2026-05-27 14:31:23 +02:00
JonKazama-Hellion 121c96f79e feat(payload-handler): wire Hover/Click + LeftClick/RightClick/LinkClick paths
E5 fills the hover/click handler layer (10 methods):

- Hover/Click: replaces E1's empty stubs with real 1:1 bodies; Click uses
  unsafe for FFXIVClientStructs pointer access (UIGlobals.PlaySoundEffect
  via PopupSfx const from E2)
- DoHover: §4.2 swap LogWindow.DefaultText → _themes.Active.Colors.TextPrimary
- HoverStatus, HoverItem, HoverEventItem: 2x _chunkRenderer.DrawChunks
  swaps each (name + description rendering)
- HoverUri: pure 1:1, no LogWindow deps
- LeftClickPayload: unsafe-preserved, Plugin.GameGui static stays
- ClickLinkPayload: pure 1:1, Plugin.ChatGui / Plugin.Framework statics stay
- RightClickPayload: sets _popup field (per E1/E2 field-syntax convention)

Adds FFXIVClientStructs.FFXIV.Client.UI using for UIGlobals; adds
Action alias and DalamudPartyFinderPayload/ChatTwoPartyFinderPayload
aliases required by LeftClickPayload switch arms.

E6 will wire MoveTooltip. After E5, PayloadHandler is functionally complete
except for the MoveTooltip AddonLifecycle wiring.
2026-05-27 13:51:18 +02:00
JonKazama-Hellion 6da8ac93fe feat(payload-handler): wire DrawItem/EventItem/Status/Uri popups + InlineIcon
E4 fills the remaining popup-body methods:

- DrawItemPopup: shows item-name, icon (via InlineIcon), and description
  via _chunkRenderer.DrawChunks; dispatches to DrawEventItemPopup when
  payload.Kind == ItemKind.EventItem (per v1.5.6 internal split)
- DrawEventItemPopup: same shape, Sheets.EventItemSheet/EventItemHelpSheet
  reads, _chunkRenderer.DrawChunks for description rendering
- DrawStatusPopup: status-name + description via _chunkRenderer.DrawChunks;
  "Link" action appends " <status>" via _inputBar.AppendPending (per §4.2)
- DrawUriPopup: open-in-browser + copy-link selectables (no LogWindow deps)
- InlineIcon: pure static helper for popup-icon rendering

Replaces E2's TODO(E4) markers in DrawPopups' Item/Status/Uri switch-cases
with real calls + drawn=true. E5 will wire Hover/Click bodies; E6
MoveTooltip.
2026-05-27 13:20:59 +02:00
JonKazama-Hellion abc0617d58 feat(payload-handler): wire DrawPlayerPopup + FindCharacterForPayload (E3)
E3 fills the player-payload right-click menu. DrawPlayerPopup migrates
1:1 from v1.5.6 with all §4.2/§6.9 substitutions:

- Tell-prefix builds via _inputBar.SetPendingMessage (single string build)
  + _inputBar.Activate = true (replaces v1.5.6's 3x LogWindow.Chat
  incremental writes + LogWindow.Activate flip)
- Channel-switch routes through _mainWindow.ActiveTab?.CurrentChannel?
  .SetChannel(channel) (per §6.3, ActiveTab is public getter on
  MainWindow per v1.7.0 refactor)
- SendFriendRequest / AddToBlacklist / AddToMuteList / AddToTermsList
  / SetEurekaTellChannel all route through injected _functions
- Player-name renderings route through _chunkRenderer.DrawChunks

FindCharacterForPayload migrates 1:1 (pure helper, Plugin.ObjectTable
static stays as-is).

Replaces E2's TODO(E3) marker in DrawPopups' PlayerPayload case with
real DrawPlayerPopup(chunk, player) call.

E4 will wire Item/EventItem/Status/Uri popup bodies; E5 the Hover/Click
bodies; E6 MoveTooltip.
2026-05-27 12:50:23 +02:00
JonKazama-Hellion 63f5a28834 feat(payload-handler): wire DrawPopups + Integrations/ContextFooter/StringifyMessage
E2 fills the popup-dispatch layer of PayloadHandler:
- DrawPopups: switch-dispatch over payload types, with TODO(E3)/(E4)
  markers at the deferred Draw{Player,Item,Status,Uri}Popup call sites
- Integrations: invokes registered IPC integrations (LogWindow.Plugin.Ipc
  -> _ipc substitution per §4.2)
- ContextFooter: ScreenshotMode + HideChat checkboxes (Plugin.Config
  static-bridge substitutions per §4.2)
- StringifyMessage: pure helper, 1:1 from v1.5.6

Adds PopupSfx const (E1 polish — needed by E5's Click for
UIGlobals.PlaySoundEffect). Removes #pragma CS0169 for _popup since
DrawPopups now writes the field; the warning no longer triggers.

E3 will fill DrawPlayerPopup + FindCharacterForPayload; E4 the
Item/Status/Uri popups; E5 the Hover/Click bodies; E6 MoveTooltip.
2026-05-27 12:19:50 +02:00
JonKazama-Hellion e46b6a7520 feat(imgui-util): resurrect WrapText pipeline (~220 LOC from v1.5.6)
Replaces C2's no-op WrapText stub with the full word-wrap pipeline
(WrapText / WrapEncodedLine / CalcWordWrap / DrawText / FindFirstSpace).
ChunkRenderer.DrawChunk's text-path now renders properly wrapped text
with payload hover-highlights and click-binding via PostPayload (which
was already full-ported in C2).

Also adds LastLink and PayloadBounds static fields that C2's PostPayload
port required but did not declare; DrawText needs both for per-segment
hover-rectangle accumulation across wrapped lines.

Unblocks E5's Hover paths that depend on functional WrapText for
status/item tooltip rendering. No structural changes — pure body
migration of the v1.5.6 unsafe word-wrap implementation.
2026-05-27 10:27:58 +02:00
JonKazama-Hellion 2067a54467 feat(payload-handler): add skeleton with 7-param ctor + Draw() popup tick
Replaces the 15-LOC C2 forward-stub with the full PayloadHandler
skeleton. Class header flips to `internal sealed` per §4.1; ctor takes
7 DI-registered services (ThemeRegistry, IpcManager, GameFunctions,
InputBar, MainWindow, ChunkRenderer, ILogger) per Flo decision
2026-05-27 (ChunkRenderer was added to the ctor list to satisfy the
§4.2 _chunkRenderer.DrawChunks references in HoverStatus/HoverItem/
DrawItemPopup paths — those land in E2-E5).

Draw() per-frame popup tick is a 1:1 port from v1.5.6 PayloadHandler.
DrawPopups() call is stubbed as TODO(E2) since that method lands in E2.
Hover/Click signatures remain empty (E5 fills the bodies, but the
signatures must compile so ChunkRenderer + ImGuiUtil callers stay live).

Skeleton-only — DrawPopups/Integrations (E2), DrawPlayerPopup (E3),
DrawItemPopup/DrawStatusPopup (E4), Hover/Click bodies (E5),
MoveTooltip (E6) all defer to their respective sub-sub-tasks.
2026-05-27 09:58:22 +02:00
JonKazama-Hellion 61a1e6bf87 feat(chunk-renderer): wire DrawIcon + icon-dispatch + EmoteCache path
Completes the ChunkRenderer pipeline. DrawIcon is a 1:1 port of v1.5.6
ChatLogWindow.DrawIcon (GFD-icon font-relative rendering via
Plugin.TextureProvider + ImGuiUtil.PostPayload). C2's TODO(C3) stub in
DrawChunk's IconChunk branch is replaced with the real dispatch.
EmotePayload special-case wired via EmoteCache.GetEmote (static helper
per §6.8).

Also adds a one-line rationale comment for the surviving _logger discard
(C2 code-quality-review polish — discard kept because _logger is not yet
consumed; E-task wiring will likely add call-sites later).
2026-05-27 09:29:35 +02:00
JonKazama-Hellion dec0daf30c feat(chunk-renderer): add DrawChunks + DrawChunk text-path (C3 stubs icon)
Resurrects v1.5.6 ChatLogWindow's DrawChunks/DrawChunk text-rendering
pipeline into the new ChunkRenderer Components-Layer class. Text-chunk
path is the full v1.5.6 migration (Plugin.Config.ScreenshotMode,
_themes.Active.Colors.TextPrimary, _fonts.ItalicFont/_fonts.AxisItalic
substitutions applied per §4.2/§4.5); icon-chunk dispatch in DrawChunk
is stubbed pending C3 (EmoteCache + DrawIcon path).

ImGuiUtil.WrapText is forward-stubbed in Util/ImGuiUtil.cs as a no-op
TextUnformatted wrapper — Sub-Task D will replace the body with the
full ~220-LOC word-wrap pipeline. ImGuiUtil.PostPayload is also
forward-stubbed (payload hover/click routing belongs to Sub-Task E).
Both stubs are the cleanest cut to keep DrawChunk's body faithful to
v1.5.6 and avoid temporary fallback paths inside ChunkRenderer.

PayloadHandler.cs is a minimal forward-stub class (Hover + Click stubs
only) required by the DrawChunks/DrawChunk and PostPayload signatures.
Sub-Task E will replace this stub with the full implementation.

Discard pattern from C1 removed for _themes/_fonts (now genuinely
consumed by DrawChunks/DrawChunk); _logger discard kept — not yet
consumed in C2, deferred to E-task wiring.
2026-05-27 08:59:23 +02:00
JonKazama-Hellion 7e541ac842 feat(chunk-renderer): add skeleton + per-ctor salt + player-hide helpers
Extracts v1.5.6's `ChatLogWindow.HidePlayerInString` / `HashPlayer` into
a standalone `Ui/Components/ChunkRenderer` class. C1 lands the skeleton
(ctor + DI-deps + salt + two pure helpers); C2 will add DrawChunks/DrawChunk
text-path; C3 will add DrawIcon + EmoteCache integration.

Salt is per-ctor random matching v1.5.6 session-random behavior — hashed
player names change every plugin reload to avoid stable cross-session
linkage (Spec §6.5 decision).

GameFunctions injected via ctor (not static Plugin.Functions) because
Plugin.Functions is a non-static internal property — injection is the
correct Components-layer pattern for this dependency.

Not yet DI-registered (Sub-Task F) and not yet consumed by MessageList
(Sub-Task H) — class compiles standalone.
2026-05-27 08:19:08 +02:00
JonKazama-Hellion 94fdef38ad feat(main-window): track per-frame window pos/size/viewport for PayloadHandler
Replaces the v1.5.6 `LogWindow.LastViewport/LastWindowPos/LastWindowSize`
window-instance state with public/internal MainWindow surfaces refreshed
at the top of Draw() each frame. PayloadHandler.MoveTooltip in Phase 2
will read these to filter cross-viewport AddonLifecycle events and to
reposition the native item tooltip away from the chat window.

LastViewport is `internal unsafe` (not public) — the only consumer is
PayloadHandler.MoveTooltip in the same assembly; keeping the raw pointer
out of the public surface is the safer default.

Split from Sub-Task A — Lender injection lives in A2 (after F's DI-reg).
2026-05-27 08:08:29 +02:00
JonKazama-Hellion 01fc69efda feat(input-bar): add SetPendingMessage/AppendPending mutators + Activate/FocusedPreview flags
Replaces v1.5.6's direct LogWindow.Chat mutation pattern with typed mutators
that LogWarning + clip/drop on BufferCapacity overflow (silent-overwrite
semantics preserved, but overflow is now observable via /xllog).

Plumbing for v1.7.1 PayloadHandler resurrection — DrawPlayerPopup (tell-
prefix) and DrawStatusPopup (status-link append) will call these mutators
instead of mutating a public field.
2026-05-27 07:59:39 +02:00
JonKazama-Hellion f5f9a4e4da feat(config): bump schema v20→v21 with ScreenshotMode field
Adds persisted ScreenshotMode flag to Configuration (was previously a
ChatLogWindow-instance field in v1.5.6). Schema bump is additive — no
breaking change. SelfTest renamed V20→V21 with matching version-gate
flip and new touch-test for the new field.

Pre-flight for v1.7.1 PayloadHandler-Pipeline Resurrection.
2026-05-27 07:47:15 +02:00
JonKazama-Hellion ced22d73b2 chore(format): csharpier line-break LINQ chain in ThemePickerCategoryStep 2026-05-26 23:02:47 +02:00
JonKazama-Hellion d2b2ebf17f test(selftests): verify TypingIpc state matches input bar 2026-05-26 23:01:59 +02:00
JonKazama-Hellion 125a41c6a0 test(selftests): verify OpenMainUi targets MainWindow not Settings 2026-05-26 23:01:26 +02:00
JonKazama-Hellion dc8d2ae8b7 test(selftests): cover Settings window toggle 2026-05-26 23:00:59 +02:00
JonKazama-Hellion 22bf1dd110 test(selftests): cover theme picker category map 2026-05-26 22:57:11 +02:00
JonKazama-Hellion 4595de5efc test(selftests): implement ColorEditorBufferStep against editing buffer 2026-05-26 22:50:13 +02:00
JonKazama-Hellion 730e15d108 chore: remove v1.7.0 'lands in' placeholders 2026-05-26 20:44:41 +02:00
JonKazama-Hellion 545ddfbfcc chore(ui): delete settings stub from v1.6.0 2026-05-26 20:37:58 +02:00
JonKazama-Hellion f510d01f46 feat(plugin): switch SettingsWindow type to new Ui.Windows namespace 2026-05-26 20:29:35 +02:00
JonKazama-Hellion 490da3e908 feat(settings): add About tab with brand, links, credits 2026-05-26 20:20:53 +02:00
JonKazama-Hellion 262fb3022a feat(settings): add Data & Privacy tab with retention and filter 2026-05-26 20:05:52 +02:00
JonKazama-Hellion 0512d4c9d2 feat(settings): add Channels tab with auto-tell and sidebar configs 2026-05-26 19:53:57 +02:00
JonKazama-Hellion 1f9afe182a feat(settings): add Window tab with layout/opacity/resize 2026-05-26 19:26:32 +02:00
JonKazama-Hellion 2c23a88e9d chore(format): csharpier line-break GeneralTab toggle calls 2026-05-26 19:12:02 +02:00
JonKazama-Hellion 2507ed5197 feat(settings): add Chat tab including command help side 2026-05-26 19:12:01 +02:00
JonKazama-Hellion 7e933cb8ba feat(settings): add General tab with direct-save toggles 2026-05-26 18:57:34 +02:00
JonKazama-Hellion 26c395419a feat(settings): wire Appearance tab with import/export row 2026-05-26 18:51:24 +02:00
JonKazama-Hellion 12bf83b826 feat(windows): add SettingsWindow skeleton (W1) 2026-05-26 18:35:30 +02:00
JonKazama-Hellion 6bbdc67089 feat(settings): register LivePreviewPanel in DI 2026-05-26 18:24:29 +02:00
JonKazama-Hellion 13ca241ac7 feat(settings): render six mock elements in live preview 2026-05-26 18:20:57 +02:00
JonKazama-Hellion 304e1aab20 feat(settings): add LivePreviewPanel skeleton 2026-05-26 18:00:53 +02:00
JonKazama-Hellion cce56610fc feat(settings): register ColorPicker in DI 2026-05-26 17:37:47 +02:00
JonKazama-Hellion eed919e961 feat(settings): wire ColorPicker sections for all 21 slots 2026-05-26 17:33:11 +02:00
JonKazama-Hellion 21689655da feat(settings): add ColorPicker skeleton with lifecycle 2026-05-26 17:05:40 +02:00
JonKazama-Hellion c6f7266194 feat(settings): add ThemePicker with five categories and switch lock 2026-05-26 16:36:54 +02:00