fix(privacy): close the gaps three review passes found in block A
The worst of them made the block's own privacy promise backwards. PrivacyPersistChannels was given a non-empty field initializer so a fresh config would record conversations only. Dalamud deserialises with Json.NET's defaults, which means ObjectCreationHandling.Auto: a collection field that already holds items gets *populated*, not replaced. Verified against Newtonsoft 13.0.3 -- saved [] loads as the initializer, saved [Say] loads as initializer plus Say. So the change would have unioned the privacy-first list into every existing config on load and switched channels back on that the user had unticked, while also making the v24 migration unreachable and its self-test vacuous. The field is empty again and the seeding moved to CreateFresh, which only runs when there is no config file at all. Cleanup could delete a channel it had promised to keep. The allowlist could only name channels that were already in the database when the preview ran, so an unrecognised channel whose first message arrived afterwards fell outside it. Where the failsafe is on, the deletion now names what goes -- known channels that are not on the list -- instead of what stays. The window closes completely, and a listed channel that happens to be empty right now is safe for the same reason. The cleanup preview was the one long operation that never took the shared lock, while holding an open reader across a full-table scan. That is precisely the case the lock was written for. Clearing the history reported success when it failed. ClearMessages purges the full-text index between the delete and the VACUUM; if that step throws, the plaintext stays on disk and the user was told it was gone. It has its own error string now, in all 25 languages. Also: - One busy state for the whole tab. Cleanup, clear, maintenance and export reach the same store, and per-section flags left two destructive buttons live at once. The lock turned that into a refusal rather than damage, but a refusal you have to trigger to discover is not an answer. - The gate carries a revision, bumped by every mutating operation that finishes. A preview taken before a retention sweep no longer passes as current afterwards: comparing it against the settings alone cannot see that the rows it counted are gone. - Database metadata moved to a worker. Checking "is anything busy" first is not enough, because an operation can take the lock in the gap before COUNT(*) runs, and then the game stands still for a whole file rewrite. - The clear hint stays hidden until the count has actually been read. "0 messages are stored" in front of the clear button is a lie told at the worst possible moment. - Refusal notices read the operation once. Guard and name were two reads of the same field, so a run finishing in between printed a sentence that stopped at the colon. - The retention sweep cannot start twice. The gate only goes busy once the worker reaches TryBegin, and the due-check runs every tick. - Teardown waits up to five seconds for the store to come free rather than disposing the connection under a running VACUUM. - Maintenance has its own flag and says so when it is refused; reload gets the same guard as its neighbour; the breakdown tree keeps its open state across a language switch.
This commit is contained in:
@@ -1184,4 +1184,7 @@
|
||||
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
|
||||
<value>Ctrl+Skift: kör gallringen direkt i stället för att vänta på den dagliga körningen. Raderar meddelanden äldre än gränserna ovan.</value>
|
||||
</data>
|
||||
<data name="Settings_Database_ClearError" xml:space="preserve">
|
||||
<value>Raderingen av historiken misslyckades. Ingenting togs bort, se /xllog.</value>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user