Updated .editorconfig to set indent_style=space and indent_size=4 for C# files. Reformat all .cs files to apply the new indentation settings. No code logic changes, just whitespace reformatting.
also updated some comments in files in shorter and Precise way. No logic changes, just comment rewording for clarity and conciseness.
Add .prettierrc.json, .markdownlint.json, .yamllint.yaml, .gitattributes
Run CSharpier, Prettier and markdownlint across the entire codebase.
No logic changes — formatting, using order and line endings only.
Migrations: all current users are on schema v16, the v9 to v16 migration
chain ran in v1.2.1 and earlier. Replace the seven in-LoadAsync migration
blocks with a hard schema-gate in the Phase-1 ctor; older configs trigger
a clear "install v1.4.2 first" error. Code-hygiene change, fast-path
saving is negligible. Remove the now-unused TryReadPreV13ThemeOpacity
helper that only served the v13 to v14 block.
AutoTranslate.PreloadCache: was sync ~300 ms in LoadAsync. Move to
Task.Run so plugin-load returns ~300 ms earlier. Trade-off: first
auto-translate use of a session may have a sub-second hitch if the
cache hasn't finished warming. Acceptable, it is first-use cost
instead of every-load cost.
The previous fire-and-forget Task.Run pattern could leave Plugin.FontManager
null when the first UiBuilder.Draw tick fires (ChatLogWindow dereferences
FontManager.FontAwesome / RegularFont / ItalicFont in its draw paths).
Allocate FontManager and call BuildFonts() synchronously, mirroring
ChatTwo Plugin.cs:152. BuildFonts itself is non-blocking — it just
registers IFontHandles with Dalamud's atlas; the actual atlas rebuild
runs on Dalamud's pipeline a few frames later, so the perceived-load
win still holds (LoadAsync no longer waits for atlas build).
BuildFontsAsync in FontManager.cs stays for the Settings-driven manual
rebuild path.
Phase-1 was still doing 7 schema migrations and 25+ service allocations
synchronously, blocking the ctor return. Move all of that to LoadAsync,
keeping only bootstrap-essentials in the ctor: conflict detection,
config load, language init, ImGui init, WindowSystem skeleton.
Decouple the font task from the LoadAsync await — font-build runs
fire-and-forget, so first frames render with Dalamud's default font
until the Hellion-Exo2/NotoSans atlas rebuild completes (visible
"font-pop"). Mirrors ChatTwo's pattern; the perceived-load win comes
from "Finished loading" landing earlier, not from a faster atlas build.
Smoke test in Task 6 surfaced a NullReferenceException at Plugin.cs:885 —
the retention sweep was scheduled in Phase 1 but dereferences
MessageManager.Store, which is only allocated in Phase 2 (LoadAsync).
Move the call after MessageManager init. Drop the comment that wrongly
claimed independence from Phase-2 services.
I-1: rewrite property-shape comment to reflect that all properties (not
just Phase-2 ones) moved to { get; private set; } = null!;.
I-3: drop plan-jargon (Q1=A / Q3=B / Task 5) from source comments;
replace with durable rationale and a version-anchored TODO for the
FontManager.BuildFontsAsync follow-up.
I-4: remove German-word leak ("pflicht") from English comment in
DisposeAsync.
M-5: wrap each cleanup line inside Framework.RunOnFrameworkThread with
CaptureFailure so a single Dispose throw no longer strands subsequent
cleanup. Drops the inline try/swallow on SetChatInteractable. Mirrors
Lightless DisposeFrameworkBoundServicesAsync pattern.
Renames HellionChat/SelfTest/ to HellionChat/SelfTests/ (plural) to
match the folder convention used throughout the Build Suite Plan v4
Phase 6 file list. The singular name was introduced as a known
discrepancy in cb327b8 and is now resolved.
- git mv preserves full history via rename detection
- Namespace updated: HellionChat.SelfTest → HellionChat.SelfTests
- Plugin.cs qualifier updated: SelfTest. → SelfTests.
- Build: 0 errors, 0 warnings
Registers a single SelfTestStep that exercises Plugin.ThemeRegistry.Switch
through the live theme list. Verified in-game via /xldev SelfTest tab on
2026-05-08; Plugin loads cleanly with the RegisterTestSteps call and the
step runs the theme cycle as expected.
Folder is HellionChat/SelfTest/ (singular). Future steps may rename to
SelfTests/ to match the local Plan v4 convention.
UI:
- SettingsOverview cards now wrap subtext to two lines (DrawList wrap-
width) and the card height grew from 96 to 110 px. Single-line
fitting clipped most of the bilingual subtitles.
- HellionStyle pushes ChildBg with alpha 0 when WindowOpacity < 1.0
to keep stacked BeginChild layers from compounding the deckgrade
past what the slider suggests.
- WindowOpacity slider helpmarker now points to Dalamud's per-window
hamburger menu for opacity / blur / pin / click-through overrides.
UX defaults (v15 → v16 migration adopts new values only when the user
is still on the previous default — bool flips are heuristic, the prior
defaults are from the v1.2.0 cycle and rarely toggled):
- UseCompactDensity false → true (single-line message style is cleaner)
- HideInNewGamePlusMenu false → true (consistent with other hide-flags)
- HideSameTimestamps false → true (cleaner log)
- MaxLinesToRender 5000 → 2500 (mid-range hardware friendlier)
- ChatColours empty → Hellion brand preset (the first-run wizard does
not offer a preset choice, so fresh installs get the brand colours
out of the box)
- Split Appearance into ThemeAndLayout (theme + window-style + timestamps)
and FontsAndColours (fonts + per-channel colours)
- Merge Database into DataManagement together with Retention/Cleanup/Export
from Privacy
- Move HistoryPreload from Privacy to Chat → Auto-Tell-Tabs
- Move KeybindMode from General/Language to General/Input
- Drop OverrideStyle, ChosenStyle, WindowAlpha, ShowThemeQuickPicker
- Migration v15 → v16 maps WindowAlpha → WindowOpacity if Opacity at default
- Add card-subtext per overview card so users do not have to guess where
a setting lives
HellionStyle.PushGlobal nimmt jetzt eine Theme-Instance + Window-Opacity
und liest alle Color- und Style-Slots aus dem aktiven Theme statt aus
einer fixen Konstanten-Tabelle. Plugin hält die ThemeRegistry und schaltet
beim Init auf das in Config.Theme gespeicherte Slug.
Configuration v13 → v14:
- Neue Felder Theme (slug), WindowOpacity, ReduceMotion, UseCompactDensity,
ShowThemeQuickPicker
- HellionThemeEnabled und HellionThemeWindowOpacity sind ab v14 [Obsolete]
und bleiben bis v1.2.0 als JSON-Safety-Net erhalten
- Migration setzt alle Bestandsuser auf hellion-arctic; chat2-classic
bleibt im Themes-Tab als Upstream-Look wählbar
- WindowOpacity übernimmt den Wert von HellionThemeWindowOpacity, alte
HellionThemeEnabled-Flag entfällt funktional (Theme-Engine ist immer aktiv)
Konsumenten der alten Felder (ChatLogWindow.BgAlpha, Popout.BgAlpha) lesen
jetzt das neue WindowOpacity. Die Settings-UI in Appearance.cs schreibt
übergangsweise weiter in die Obsolete-Felder; Phase J ersetzt diesen Block
durch den dedizierten Themes-Tab. CS0612/CS0618 sind dort gezielt mit
pragma gekapselt.
General code-quality and robustness pass across the plugin: thread-
safety on IPC state, resource-disposal cleanups, input validation,
defensive null-checks and a few small UX glitches. Compliance docs
(THIRD_PARTY_NOTICES, PRIVACY, COPYRIGHT) refreshed to v1.0.3.
Highlights
- ExtraChat IPC state synchronised across threads
- ChatLogWindow autocomplete no longer leaks the unmanaged
ImGuiListClipper allocation
- ChatLogWindow + Popout style stack stays balanced when config
toggles mid-frame
- Retention sweep and privacy cleanup wait for the actual filter
pass instead of the fire-and-forget Task that started it
- Configuration.LatestVersion bumped to 13 to match the active
migration path
- GameFunctions placeholder buffer guarded against oversized
replacement names
- TellTarget.IsSet, ResolveTempInputChannel, InputPreview, IconUtil,
Lender, Payloads, ExtraPayload all hardened against null / empty /
EOF / cycle inputs
- FontManager Lodestone download stays in scope for a follow-up
(timeout + lazy init pending)
- AutoTranslate replaced the msvcrt.dll memcmp P/Invoke with a
managed Span comparison
- Privacy cleanup worker thread marked IsBackground = true
- Database cleanup now removes both legacy files in one click
- Tell-target name redacted in the verbose debug log
Compliance
- THIRD_PARTY_NOTICES: last-reviewed bumped to v1.0.3, Pidgin 3.5.1,
SQLitePCLRaw.lib.e_sqlite3 3.50.3 listed as direct dependency with
CVE-2025-6965 / CVE-2025-7709 rationale
- PRIVACY: last-reviewed bumped to v1.0.3, BetterTTV trigger wording
clarified (list fetch at startup vs. on-demand image fetch)
- COPYRIGHT: upstream attribution range widened
Build: 0 warnings, 0 errors. No behavioural changes that would alter
existing user configuration or stored chat history.
Four small backlog items bundled:
- New: hide chat (and every other plugin window) while the New Game+
menu is open. Settings -> Window -> Frame, default off. Skips the
whole WindowSystem.Draw() pass while QuestRedo is visible, mirroring
the existing HideInLoadingScreens pattern.
- New: tint the channel selector button in the active channel colour.
Settings -> Appearance -> Colours, default on. Reuses the existing
inputColour computation (incl. ExtraChat override) and adds an
ImGuiCol.Button push around the selector. New ColourUtil helper
AdjustBrightness derives hover/active variants.
- Fix: PayloadHandler.InlineIcon hardcoded all hover icons to 32x32.
Replaced with float-based aspect-ratio-preserving shrink, single
scale-factor, zero-size guard, named MaxInlineIconSize constant.
Affects six call sites (status, item, achievement and other inline
hover paths).
- Diagnostic: HideState transitions log on Verbose level for both
ChatLogWindow and Popout.
Manifest bumped to 1.0.2 across csproj, yaml, repo.json. CHANGELOG
entry added, README version line updated. yaml + repo.json changelog
trimmed to the slim 4-version window (1.0.2, 1.0.1, 1.0.0, 0.6.1).
Aligns the first-run tab layout with the sharpened defaults that
external testers asked for. Three changes in one commit:
1. VanillaGeneral now contains only Say/Yell/Shout. The previous
30-channel kitchen-sink (party, FC, every linkshell, all gameplay
events) buried the actual immediate-surroundings conversation
under loot rolls, crafting and PF pings.
2. HellionSystem absorbs the gameplay-event streams that used to live
in General — NpcDialogue, LootNotice, LootRoll, Crafting, Gathering,
PeriodicRecruitmentNotification — plus the announcement and battle-
system noise (BattleSystem, FreeCompanyAnnouncement,
PvpTeamAnnouncement) that previously had no fixed home.
3. The first-run / wipe default no longer adds HellionBeginner
conditionally and no longer adds a static VanillaTellExclusive tab.
Auto-Tell-Tabs spawns per-conversation tabs on demand, the static
tell-bucket is redundant. NoviceNetwork users can still add the
Beginner preset from Settings -> Tabs.
A new v12 -> v13 migration triggers a hard tab-wipe on existing
installs because per-channel mapping from the old General preset to
the new General/System split is ambiguous. The wipe scope is
narrow: only Config.Tabs is cleared, every other knob (Privacy,
Retention, Theme, etc.) keeps its current value. A pre-v13 backup
of the live config is written alongside it for manual restore.
Users see the existing SettingsRefactor migration notification.