fix: close what the style review found, starting with a gate the metadata skipped

The real defect first. RefreshDatabaseMetadata was the one worker of six
that never took the shared lock, and its flag was the one of six missing
from the tab's busy state. It calls MessageCount, which holds the read
lock, so a wipe could start while it was in there -- and the tab would
not have known to grey the button, because it could not see the worker.
Both halves fixed. The pattern is why: seven near-copies of one worker
skeleton, and each copy decided something slightly different.

The clear button failed silently when its thread could not start. The
most destructive control in the plugin, pressed, and nothing happens,
with no way to tell that from a wipe that worked -- while the three
harmless workers beside it do report. Maintenance was the mirror: its
comment promises refusals are said out loud, and then swallowed the
actual failure. Three start-failure paths also bypassed the notify
helper that carries the teardown check, three weeks after it was added
for exactly that.

The database numbers now wait for a real read, like the clear hint
already did. Zero bytes and zero messages read as an empty database, not
as a number nobody has fetched.

SelectionAfterDelete is gone, with its three tests. The accordion has no
selection, so its return value went into a discard -- a function
answering a question the interface does not ask, with green tests
guarding nothing. The project's own self-test README calls that the
anti-pattern of record.

Six new keys replaced by the translated orphans that already said the
same thing. A commit earlier in this cycle is literally called "stop
duplicating a key" and these went past it. The duplicate button also had
the label "Add", which is the one string out of ninety-four that was
never written.

Tests: CleanupDeleteTypes had none, and with the failsafe on -- how a
fresh config ships -- it is the path every cleanup takes. Four now,
including the one that matters: an empty list deletes nothing rather
than everything.

And a self-test for the gate wiring, which is what would have caught the
metadata worker. The unit tests prove the gate works; nothing proved the
workers use it.
This commit is contained in:
2026-08-19 07:09:54 +02:00
parent e7b76fb21b
commit 9ea9e96145
37 changed files with 310 additions and 529 deletions
+12 -10
View File
@@ -22,8 +22,8 @@ Last reviewed: 2026-08-18 (HellionChat v1.12.0).
no remote update check beyond what Dalamud itself does.
- One outbound network call exists by design: the BetterTTV emote service (for chat emotes). It is
documented in detail below and can be reasoned about per request.
- You can export every message the plugin has stored, in Markdown, JSON or CSV. You can delete it
by channel, by age, or all of it at once.
- You can export every message the plugin has stored, in Markdown, JSON or CSV. You can delete it by
channel, by age, or all of it at once.
---
@@ -96,8 +96,9 @@ font is bundled instead.
incoming chat message contains a token matching one of the cached IDs. These are cached locally
(`EmoteCacheV1/`) and reused across sessions.
- **Cached:** Yes, in `EmoteCacheV1/`. A given emote is downloaded once per machine and reused.
- **How to opt out:** Turn off the **Show emotes** option in Settings → Chat → Display modes. With it disabled, the
emote cache does not load and no requests to BetterTTV are made for the rest of the session.
- **How to opt out:** Turn off the **Show emotes** option in Settings → Chat → Display modes. With
it disabled, the emote cache does not load and no requests to BetterTTV are made for the rest of
the session.
- **BetterTTV's privacy policy:** <https://betterttv.com/privacy>
Source: `HellionChat/EmoteCache.cs`.
@@ -119,10 +120,10 @@ Cached `FFXIV_Lodestone_SSF.ttf` files left over from earlier versions remain in
### Links you click yourself (no automatic traffic)
The About tab contains buttons that open external pages in your browser when you click them: the
Hellion Forge Discord invite, the HellionChat Gitea repository, its custom-repo manifest, and -- when
the Honorific integration row is shown -- that plugin's GitHub repository and its author's profile.
Nothing happens until you click. They are documented here for completeness, not because they
generate background traffic.
Hellion Forge Discord invite, the HellionChat Gitea repository, its custom-repo manifest, and --
when the Honorific integration row is shown -- that plugin's GitHub repository and its author's
profile. Nothing happens until you click. They are documented here for completeness, not because
they generate background traffic.
---
@@ -150,8 +151,8 @@ locally, those rights translate directly into plugin features:
### Right to access (Art. 15)
Settings → Data & Privacy → Export. You can export to **Markdown**, **JSON** or **CSV**, narrowed
by channel group, by age in days, or by a substring of the sender's name. The export goes through a
Settings → Data & Privacy → Export. You can export to **Markdown**, **JSON** or **CSV**, narrowed by
channel group, by age in days, or by a substring of the sender's name. The export goes through a
Dalamud file dialog and writes wherever you point it, on your machine. It reads the database on its
own connection and writes to a temporary file first, so a run that is interrupted leaves the
previous export in place rather than a file that looks complete and is not.
@@ -183,6 +184,7 @@ Two options:
channel is stored and nothing contradicts your settings; with no channel selected, a cleanup
would delete everything, and that is what the clear button is for. Both cases say so instead of
offering a button that does not do what it looks like.
2. **Full deletion.** Close the game and delete the `pluginConfigs/HellionChat/` directory. The next
plugin start will produce a fresh, empty configuration.