Commit Graph
1654 Commits
Author SHA1 Message Date
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
JonKazama-Hellion a73cad1534 feat(settings): add ContentArea wrapper 2026-05-26 16:08:27 +02:00
JonKazama-Hellion bb37e19176 feat(settings): add TabSidebar with seven entries 2026-05-26 15:59:01 +02:00
JonKazama-Hellion ffef5634ed feat(util): add RgbaToVector4 and Vector4ToRgba helpers for color picker 2026-05-26 15:25:31 +02:00
JonKazama-Hellion 947c4b2061 fix(themes): bump example-theme.json to schemaVersion 2 2026-05-26 14:47:02 +02:00
JonKazama-Hellion d156ff4c56 fix(plugin): route OpenMainUi to MainWindow instead of Settings 2026-05-26 14:11:34 +02:00
JonKazama-Hellion 7979568165 refactor(ipc): drop this.-qualifier and trim BuildState comments
Same shadowing-via-instance-property as Plugin.CurrentTab above. Comments
trimmed to default 1-3 line density; security/threading WHY-blocks earn
their lines when they document non-obvious invariants, not standard C#
name resolution.
2026-05-26 14:04:46 +02:00
JonKazama-Hellion 93bfd408bc feat(ipc): wire TypingIpc state from InputBar API 2026-05-26 13:38:21 +02:00
JonKazama-Hellion e01de0403a feat(input): expose state API, wire settings cog, add test hooks 2026-05-26 13:31:00 +02:00
JonKazama-Hellion 11eb7b9e90 fix(themes): tighten editing-buffer save path (tmp cleanup, log-PII, line-refs)
Three review-pass fixes on SaveEditingBuffer:

- Wrap File.Move in try/catch that deletes the .tmp sibling on failure
  (AV-scanner lock, EXDEV, share-violation) then rethrows so the outer
  IOException catch still owns the error path. Avoids accumulating
  '<slug>.json.tmp' litter in the themes dir on retry storms.

- Reduce PII in the five new LogWarning calls that previously included
  full paths containing the user's home directory. Filename-only via
  Path.GetFileName is sufficient for triage; the two forensics-critical
  path-escape log calls keep full paths because diagnosing the escape
  needs the resolved target. WHY-comment anchors the v1.8.0 PII
  re-audit roadmap.

- Replace seven hardcoded 'ThemeRegistry.cs:<line>' references in
  comments with method-name + symbol descriptions so future Switch/
  RefreshCustomCache refactors do not bit-rot the comments.

Build 0/0, csharpier clean.
2026-05-26 13:16:57 +02:00
JonKazama-Hellion 4f81cd1f24 feat(themes): add editing buffer with begin/update/save/discard 2026-05-26 13:03:30 +02:00