Commit Graph
1437 Commits
Author SHA1 Message Date
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
JonKazama-Hellion cf4705e01f refactor(ui): retire ChatLogWindow and the v1.5.6 chat-window layer
The legacy ChatLogWindow.cs and its tightly coupled neighbours are gone:
PayloadHandler, Popout, ChatInputBar, AutoCompleteInfo, AutoTellTabTint,
the three tab-icon helpers, the old Ui/StatusBar and Ui/SymbolPicker
behind the components-layer replacements, HellionStyle + helpers, the
CompactInputSubmitter test mirror and the QuickPickerSelfTestStep. The
new component layer (MainWindow + the five components + GlobalStyleScope)
now drives the whole chat surface.

InputPreview, CommandHelpWindow and Debugger lose their ChatLogWindow
backref. The first two are skeleton windows for now — DrawConditions
always returns false until the new chat layer exposes equivalent state.
Debugger keeps the current-tab and vanilla-chat blocks; the payload
counters are explicitly marked offline. DbViewer renders Sender/Content
columns as plain TextValue strings instead of the removed DrawChunks.

GameFunctions.Chat and GameFunctions.KeybindManager keep the hook
plumbing intact but mark every ChatLogWindow.Activated /
ChangeTabDelta / TellSpecial site as offline so the FFXIV-side
integration still compiles and runs without an Activated entry point.
TypingIpc.BuildState reports the IPC state as not-typing / not-focused
until the new chat layer surfaces real focus and buffer state again.

Plugin.cs Draw uses StyleEngine.GlobalStyleScope.Push for the per-frame
theme push and stops calling BeginFrame / FinalizeFrame / HideStateCheck
/ DefaultText through the dead window. ImGuiUtil drops PostPayload +
WrapText + the surrounding word-wrap pipeline. PluginHostFactory and
PluginLifecycle drop the legacy DI singletons and AddWindow entries.

Build is clean and csharpier is clean across the trimmed 131-file tree.
2026-05-23 20:31:12 +02:00
JonKazama-Hellion c9e746a8e3 refactor(settings): reduce SettingsWindow to a stub and drop the tab system
The seven settings tabs and the overview helper are removed. The new
settings UI lands in a later cycle and will be rebuilt from scratch on
the v2.x component layer; keeping the v1.5.6 tab classes around in the
meantime would only carry dead dependencies through the rest of this
cycle. The window stays registered so /hellion settings, the slash
command path, and the UiBuilder open handlers all still resolve.
2026-05-23 20:12:16 +02:00
JonKazama-Hellion ec02a5f381 feat(commands): consolidate /hellion and /clearhellion in Plugin.SetupCommands
/hellion routes through one handler with three subcommands: empty arg
toggles the main window, "settings" toggles the settings stub (full
settings UI lands later), "reset" calls ThemeRegistry.SwitchSilent on the
default slug so a broken custom theme can be unloaded without a settings
UI. /clearhellion now lives next to /hellion instead of inside the chat
window. ChatLogWindow loses its old register/unregister pair so the two
slash-commands stop double-binding.
2026-05-23 20:08:09 +02:00
JonKazama-Hellion 576cd6dafd feat(ui): assemble MainWindow from the components layer
Top-level chat window composes HonorificHeader, Sidebar, MessageList,
InputBar and StatusBar in the layout from the master spec: header row,
horizontal body (sidebar + main area with messages + input), status
strip pinned to the bottom. Component types are fully qualified through
the Ui.Components prefix so the v1.5.6 Ui.StatusBar type cannot shadow
the new layer through parent-namespace resolution before it is removed.
Toggle is a new-shadow on Window.Toggle so the open path also writes
Config.MainWindowOpen; OnClose covers the close path through the base
behaviour. InputBar.Height is now public so the layout math can reach
it from outside the components folder.
2026-05-23 19:52:37 +02:00
JonKazama-Hellion 0fc2512f3e feat(ui): rebuild StatusBar inside the components layer
Same 1Hz-cached slot layout (channel indicator, privacy badge, counts,
tells, version + brand) but ThemeRegistry and FontManager arrive via
constructor injection rather than the Plugin static bridge, and Draw
takes the active tab directly so the component does not have to reach
back through Plugin.CurrentTab. Pure helpers (FormatCounts, FormatTells,
AggregateForStatusBar) stay static so the build suite can pin them
without an ImGui frame. The v1.5.6 Ui/StatusBar.cs stays in place until
the cleanup block removes it.
2026-05-23 19:35:50 +02:00
JonKazama-Hellion 36afce21e5 feat(ui): add InputBar with channel pill and symbol picker overlay
Channel pill picks Token.AccentEmber when the tab is a tell (matched by
IsTempTab + a set TellTarget) and Token.AccentPrimary otherwise, so the
tinted background reads as the channel type at a glance. SymbolPicker
runs as an overlay popup — the inserted fragment splices straight into
the pending buffer up to a 500-char cap. Send wiring and the settings
button arrive when the main window assembles the components.
2026-05-23 19:17:25 +02:00
JonKazama-Hellion bdfb1298ad feat(ui): migrate SymbolPicker into the components layer
Lifted out of Ui/ into Ui/Components and registered as a DI singleton so
the new InputBar can consume it via constructor injection. PUA tab still
sources from SeIconChar, BMP tab keeps the server-verified whitelist
verbatim. The old Ui/SymbolPicker.cs stays in place until the cleanup
block removes the v1.5.6 file.
2026-05-23 19:12:18 +02:00
JonKazama-Hellion eb95968750 feat(ui): add MessageList with two-mode virtualisation
Compact mode reuses ImGuiListClipper because rows are a constant line
height; card mode falls back to a linear render with a per-message height
cache and an IsItemVisible skip path so off-screen rows place a Dummy of
the cached height instead of running the full render. Bottom-lock detects
whether the user was pinned to the bottom before the layout pass and
re-pins after new rows land. Renders text-only via SeString.TextValue for
this cycle — full chunk and payload rendering re-attaches later, so the
component shape stays correct without dragging the v1.5.6 chunk pipeline
into the new layer.
2026-05-23 18:53:38 +02:00
JonKazama-Hellion 6ab2e9cece feat(ui): add Sidebar component with width auto-switch
Channel-list panel for the chat window's left side. Auto-switches between
icon-only (38px) and expanded (150px) based on
Config.SidebarAutoSwitchThresholdPx. Each row renders a FontAwesome tab
icon, an expanded-mode name label, a hover-sheen sweep keyed on the tab
identifier, and a pop-out affordance — both the trailing hover button and
the right-click context menu route through a log stub until the channel
popout pool comes online. Glyph table is inlined so the Ui layer carries
its own lookup after the standalone mapping file is removed.
2026-05-23 18:30:29 +02:00
JonKazama-Hellion 0e0c563608 feat(ui): add HonorificHeader component
30px header row pinned to the top of the chat window. Crown always renders
as a brand anchor — even with the Honorific IPC down — while the bracketed
title only appears when CurrentTitle has content. First-frame guard reads
FontManager.FontsReady so layout math never runs against placeholder font
metrics.
2026-05-23 18:17:33 +02:00
JonKazama-Hellion 9c490fa066 feat(services): add TellRouterService stub
Skeleton for the upcoming auto-open routing. Subscribes to
ChatGui.ChatMessageUnhandled and Dispose unsubscribes — when the routing
logic lands, it drops into OnChatMessage without touching the DI graph or
Plugin.cs registration.
2026-05-23 18:12:18 +02:00
JonKazama-Hellion 44c14ace2c feat(fonts): add FontsReady gate property
Returns true once every required atlas-owned handle reports Available.
Components will gate their first-frame draw on this so the layout math
runs against the real atlas rather than placeholder metrics. ItalicFont
null counts as ready because that means italics are disabled in config.
2026-05-23 18:10:36 +02:00
JonKazama-Hellion 53ed154103 feat(config): bump schema to v20 with style-refactor visibility fields
Adds MainWindowOpen, SettingsWindowOpen, MaxParallelPopouts (channel popout
pool size), TellAutoOpenMode (Off/Sidebar/TopTab/Popout) and
SidebarAutoSwitchThresholdPx. Migration is additive — field initializers
fill defaults for v19 configs, the Plugin.cs schema gate bumps the version
stamp after load. UpdateFrom gets explicit sync statements for all five so
settings-save edits do not drop them.
2026-05-23 18:08:34 +02:00