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.
Loader returns Theme? — null is the silent hard-cut skip for v1 files so
the v2.x refactor stays free of legacy-mapping code. v2 adds an optional
typography{} block with overrideGlobalFontSizePt and overrideSymbolsFontSizePt
slots, both nullable. ThemeRegistry.RefreshCustomCache gets a null guard
so the yield path drops skipped files cleanly. Writer emits typography{}
with explicit nulls so hand-edited files show the available knobs.
Three new private fields plus TryGetActiveCrossfade entry-point, plus
SwitchSilent variant for the plugin-load init path. ArmCrossfade
captures a value-copy of the active AbgrCache and stamps TickCount64;
mid-crossfade Switch composes the current lerped state as the next
fade origin so back-to-back theme switches stay smooth.
Same-slug Switch is a no-op (no identity-crossfade).
Slice D shrinks vs the original plan: three of the six files cannot
take an ILogger ctor arg without breaking external contracts.
Migrated (8 LogProxy sites across 4 files):
- Commands: 2 sites (Warning, Error). New ctor takes ILogger<Commands>.
- Themes/ThemeRegistry: 1 site (Debug). ILogger<ThemeRegistry>? is
optional (default null) so the existing Build-Suite tests that
construct `new ThemeRegistry()` parameterless keep working without
changes. _logger?.LogDebug guards the call site.
- PayloadHandler: 3 sites (Error, Warning, Error). New ctor takes
ILogger<PayloadHandler>. ChatLogWindow's two `new PayloadHandler(this)`
sites (the direct field and the Lender lambda) now hand a fresh
CreateLogger<PayloadHandler>() from the existing _loggerFactory.
Not migrated (5 sites stay on Plugin.LogProxy, plan drifts D12-D14):
- D12 - Configuration (1 site): IPluginConfiguration, instantiated by
Dalamud's Interface.GetPluginConfig() via reflection on the
parameterless ctor. Adding an ILogger arg would break GetPluginConfig.
- D13 - Message (4 sites): partial data class with two ctor overloads,
mass-instantiated across 3 plugin sites plus Newtonsoft JSON
deserialisation. Ctor extension would be invasive across ~20 call
sites with low payoff (data-class logger is unusual).
- D14 - FontManager (2 sites): both Plugin.LogProxy calls live in
static methods (TryGetHellionFontBytes, AddFontWithFallback) that
cannot reach an instance _logger. Same root cause as D8 in
GameFunctions. FontManager joins the static-bucket alongside
EmoteCache et al.; the ctor + _logger field added mid-Slice-D were
rolled back to keep the class clean.
Plugin.LogProxy surface after C9 (8 file buckets, ~12 sites total):
- 4 originally-static consumers: EmoteCache, AutoTranslate,
MemoryUtil, WrapperUtil
- 3 cannot-take-ctor-arg consumers: Configuration, Message, FontManager
- 1 single-static-method consumer: GameFunctions.TryOpenAdventurerPlate
(D8 from Slice B)
Smoke 2 is now due.
When the user edits their active custom theme JSON in an external editor
and saves, the change now propagates to HellionChat within ~1 second
without re-selecting the theme in the picker.
RefreshActiveIfStale runs from Plugin.Draw on every frame but the actual
File.GetLastWriteTimeUtc stat is 1Hz-throttled -- 60fps would otherwise
mean 3600 stats/min, more on Wine. Built-in themes short-circuit on the
IsBuiltIn check; custom themes without a captured source path (Switch
fell to default) short-circuit on the null check.
Switch() now captures the source path of custom themes via an out-param
on LoadCustomBySlug, which now reverse-looks-up against the existing
_customCache (no re-parse, no extra disk IO). Plugin.LoadAsync warms the
cache via AllCustom() once before the first Switch so a Config.Theme
pointing at a custom slug does not fall through to the built-in default
on a cold registry.
Switch's lookup order is now built-in-first to match Get(slug), so a
user-authored JSON that declares a built-in slug is consistently
ignored in both code paths.
Pure-helper ThemeStampDiff isolates the stamp-diff rules for the
Build-Suite (covers DateTime.MinValue hold-the-line semantics).
v1.4.8 B2.
Crystal Nocturne (royal sapphire + electric magenta on obsidian, by
CRYSTALLITE) replaces Moonlit Bloom in the built-in roster. The same
chat-channel tinting convention applies: sapphire-blue identity on
party/team channels, accent-magenta on tells, and an alternating
mint/yellow/peach palette across the eight linkshell slots so each
LS stays individually distinguishable on the dark obsidian background.
Users who had Moonlit Bloom selected fall back to the default Hellion
Arctic on the first plugin load. A custom JSON copy of Moonlit Bloom
dropped into pluginConfigs/HellionChat/themes/ keeps working as a
user theme.
Plus a cosmetic re-sort of the registry: insertion order now drives a
deliberate Theme-Picker grid layout (3 columns) — blue family in row 1,
purple to magenta in row 2, green/warm/classic in row 3, Synthwave
Sunset alone in row 4 as a retro bonus.
- Translated project documentation (LEARNING-JOURNEY, CONTRIBUTORS, AI_DISCLOSURE) to English for better accessibility.
- Standardized internal code documentation by converting XML-doc blocks to standard comment format.
- Cleaned up inline comments and removed redundant versioning metadata across the codebase.
- Refactored non-functional text elements to improve readability and maintain a consistent style.
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.
Hellion Arctic, Event Horizon, Moonlit Bloom and Mint Grove each
ship a distinct chat-channel palette tinted toward their brand
family while preserving the FFXIV channel identity (Say light, Yell
yellow, Shout orange, Tell pink-magenta, Party blue, FC cyan, NN
green). Chat 2 Klassik intentionally ships without — users picking
that theme keep their existing channel colours.