Commit Graph
1650 Commits
Author SHA1 Message Date
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
JonKazama-Hellion 8e7149cadc fix(ui): guard sidebar row at min drag and widen system-icon match
DrawRow asserted on a zero-width InvisibleButton when the window was
dragged below the pop-out hit threshold — the row now drops out cleanly
under 2px of remaining sidebar width, and the pop-out button only
splits off when there's room for both hit areas. The trailing pop-out
icon is hidden too when its strip is collapsed, so the row stays as a
single selectable strip on extreme drags.

System icon path: ResolveTabIcon used to look only at the first key in
SelectedChannels, so a System tab whose first filter happened to be a
generic ChatType slipped through to Comment. The resolve now walks
every key and keeps the first non-Comment match, and a final
case-insensitive name match flips the icon to fa-cog when the user's
filter set falls completely outside the channel-type table.
2026-05-23 21:08:22 +02:00
JonKazama-Hellion 2f099fd4e1 fix(ui): clickable channel pill, auto-seed channel, kill outer scrollbar
Three smoke bugs from the second in-game test:

1. The channel pill was draw-list only, so it didn't react to clicks
   and there was no way to switch channels inside a tab. The pill now
   has a hit area on top and opens a popup that lists every ChatType
   in tab.SelectedChannels with a ToInputChannel mapping; selecting
   one writes through CurrentChannel.SetChannel.

2. Switching to Allgemein / Gruppe / Linkshell still showed "—"
   because tab.CurrentChannel.Channel stayed at Invalid until somebody
   set it. The sidebar now seeds CurrentChannel on tab activation by
   walking SelectedChannels for the first key with a valid mapping,
   so every tab opens with its own real channel instead of inheriting
   the FC default.

3. MainWindow still surfaced an outer scrollbar next to the message
   list's own scroll. Adding NoScrollbar + NoScrollWithMouse to the
   window flags strips the second bar — the body child owns scroll on
   its own.

Plus the system-icon path: System / BattleSystem / GatheringSystem /
Error / Notice / LootNotice all map to fa-cog now, so the System tab
renders the gear instead of falling back to the generic comment.
2026-05-23 20:58:50 +02:00
JonKazama-Hellion 52b0fa7c67 fix(ui): wire chat send and fix sidebar icons, channel pill, scrollbar
Five smoke bugs from the first in-game test:

1. Sidebar showed fa-comment for every tab because the resolve path
   only honoured tab.Icon. Channel-type fallback restored — auto-tell
   tabs render the envelope, the rest map their first SelectedChannels
   key onto FontAwesome (Linkshells → link, FC → users, Party →
   user-friends, System/Echo → cog, emotes → comments).

2. InputBar's channel pill read from tab.Channel (the saved default),
   which is null on most non-FC tabs and rendered as "—". The pill now
   reads tab.CurrentChannel.Channel first so the runtime input state
   surfaces on every tab, with the saved default as a second fallback.

3. MessageList was making its own ImRaii.Child inside the main-area
   child MainWindow already owns. That nested scroll created the second
   scrollbar on the outer window. The component now lays out directly
   into the parent's scroll region.

4. The input field reserved 90px for the three FontAwesome buttons,
   which clipped them on standard frame padding. Reserve raised to
   130px so the trailing buttons fully render.

5. Pressing Enter dropped the buffer — there was no send wiring. The
   field now uses ImGuiInputTextFlags.EnterReturnsTrue and routes the
   pending message through GameFunctions.ChatBox.SendMessage. Lines
   that don't start with a slash get the active channel's prefix
   prepended so typing in /fc lands on the FC channel instead of the
   current game-side default.

InputBar gains an ILogger<InputBar> for the send-failure path; the
DI registration in PluginHostFactory is updated to match.
2026-05-23 20:50:54 +02:00
JonKazama-Hellion 0109bfd222 test(selftests): add v1.6.0 SelfTest steps from sub-spec
Six new ISelfTestStep entries register with the Dalamud SelfTestRegistry:
SidebarModeAutoSwitch probes the width threshold both above and below the
exact boundary so the >= contract stays pinned; ColorEditorBuffer is a
placeholder until the picker arrives; ConfigMigrationV20 asserts the
schema stamp and the five v20 field defaults; HoverSheenAlloc drives 100
hovered frames against three constant keys and a final un-hover sweep to
exercise the cleanup branch; HonorificHeaderRender runs one Draw call on
the live component to catch IPC fallback crashes; PerformanceBaseline
prints a JSON line of the IO counters so the cycle notes can pick up a
snapshot. MainWindow gets internal accessors so the probes can reach the
sidebar and honorific header without widening the public surface.
2026-05-23 20:35:01 +02:00