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 -4
View File
@@ -118,6 +118,11 @@ public sealed class Plugin : IAsyncDalamudPlugin
internal Commands Commands { get; private set; } = null!;
internal GameFunctions.GameFunctions Functions { get; private set; } = null!;
internal MessageManager MessageManager { get; private set; } = null!;
// Reached by the gate-wiring self-test, which has to ask the live tab
// whether it sees a held gate.
internal Ui.Components.Settings.Tabs.DataPrivacyTab DataPrivacyTab { get; private set; } =
null!;
internal AutoTellTabsService AutoTellTabsService { get; private set; } = null!;
internal IpcManager Ipc { get; private set; } = null!;
internal ExtraChat ExtraChat { get; private set; } = null!;
@@ -163,10 +168,6 @@ public sealed class Plugin : IAsyncDalamudPlugin
// Idempotency guard — Dalamud may fire DisposeAsync twice in a reload race.
private int _disposeStarted;
// Set in the first DisposeAsync statement so async callbacks scheduled
// via Framework.RunOnTick (v1.4.8 B3 retention sweep) can early-bail
// before they touch state that has already been torn down. Volatile
// because the tick reads it from a different thread than the writer.
// The three hide conditions v1.5.6 evaluated and cf4705e left without a
// reader. Advanced once per draw, before any window is drawn.
private Util.ChatHideReason _hideReason = Util.ChatHideReason.None;
@@ -175,6 +176,10 @@ public sealed class Plugin : IAsyncDalamudPlugin
// A cutscene the user dismissed stays dismissed until it ends.
internal bool ChatActivationRequested;
// Set in the first DisposeAsync statement so async callbacks scheduled
// via Framework.RunOnTick (v1.4.8 B3 retention sweep) can early-bail
// before they touch state that has already been torn down. Volatile
// because the tick reads it from a different thread than the writer.
private volatile bool _isDisposing;
// Read by background workers that outlive a teardown -- the export thread
@@ -414,6 +419,8 @@ public sealed class Plugin : IAsyncDalamudPlugin
InputBar = _host.Services.GetRequiredService<Ui.Components.InputBar>();
MainWindow = _host.Services.GetRequiredService<Ui.Windows.MainWindow>();
SettingsWindow = _host.Services.GetRequiredService<Ui.Windows.SettingsWindow>();
DataPrivacyTab =
_host.Services.GetRequiredService<Ui.Components.Settings.Tabs.DataPrivacyTab>();
DbViewer = _host.Services.GetRequiredService<DbViewer>();
InputPreview = _host.Services.GetRequiredService<InputPreview>();
CommandHelpWindow = _host.Services.GetRequiredService<CommandHelpWindow>();
@@ -485,6 +492,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
new SelfTests.OnOpenMainUiRoutesMainWindowStep(this),
new SelfTests.TypingIpcStateStep(this),
new SelfTests.ConfigMigrationV25Step(this),
new SelfTests.DbGateWiringStep(this),
new SelfTests.ChannelPopoutBindStep(this),
new SelfTests.HoverStateFootprintStep(),
new SelfTests.HonorificHeaderRenderStep(this),
+4 -6
View File
@@ -3,17 +3,15 @@ using HellionChat.Resources;
namespace HellionChat.Privacy;
// The eight buckets the privacy surface sorts channels into. Sixty checkboxes in
// one flat list is not a choice anybody makes; eight named groups is.
// The eight buckets the privacy surface sorts channels into. Eighty-nine
// checkboxes in one flat list is not a choice anybody makes; eight named groups
// is. Shared by the export form and the persist grid so the two screens
// describe channels the same way.
//
// Headings are functions, not strings, so a language switch at runtime relabels
// them on the next frame. A captured string would keep the language the window
// happened to be opened in.
//
// Lives here rather than in a tab because the retention and cleanup screens
// will need the same grouping, and three copies would drift the moment a patch
// adds a channel. Only the export uses it so far.
//
// Game Master channels follow ChatTypeExt.Parent(), which already pairs each of
// them with its player counterpart. Filing them all under system traffic reads
// tidier but puts GmTell -- a private two-person conversation -- outside the
+1 -6
View File
@@ -364,9 +364,9 @@ internal class HellionStrings
internal static string Settings_Theme_ResetUnavailable => Get(nameof(Settings_Theme_ResetUnavailable));
internal static string Settings_Theme_LockedTooltip => Get(nameof(Settings_Theme_LockedTooltip));
internal static string Settings_Theme_Custom => Get(nameof(Settings_Theme_Custom));
internal static string Settings_Tabs_Duplicate => Get(nameof(Settings_Tabs_Duplicate));
internal static string Settings_Theme_ForkActive => Get(nameof(Settings_Theme_ForkActive));
internal static string Settings_Theme_ImportFile => Get(nameof(Settings_Theme_ImportFile));
internal static string Settings_Theme_ExportActive => Get(nameof(Settings_Theme_ExportActive));
internal static string Settings_Theme_ImportPathHint => Get(nameof(Settings_Theme_ImportPathHint));
internal static string Settings_Theme_ExportDialogTitle => Get(nameof(Settings_Theme_ExportDialogTitle));
internal static string Settings_Theme_Category_Cool => Get(nameof(Settings_Theme_Category_Cool));
@@ -395,7 +395,6 @@ internal class HellionStrings
internal static string Settings_Section_Integrations => Get(nameof(Settings_Section_Integrations));
internal static string Settings_Section_Credits => Get(nameof(Settings_Section_Credits));
internal static string Settings_Section_License => Get(nameof(Settings_Section_License));
internal static string Settings_General_ReduceMotion_Description => Get(nameof(Settings_General_ReduceMotion_Description));
internal static string Settings_Keybinds_Hint => Get(nameof(Settings_Keybinds_Hint));
internal static string Settings_Keybinds_CycleNext => Get(nameof(Settings_Keybinds_CycleNext));
internal static string Settings_Keybinds_CyclePrevious => Get(nameof(Settings_Keybinds_CyclePrevious));
@@ -415,8 +414,6 @@ internal class HellionStrings
internal static string Settings_Window_TabPlacement_Description => Get(nameof(Settings_Window_TabPlacement_Description));
internal static string Settings_Window_TitleBar_Name => Get(nameof(Settings_Window_TitleBar_Name));
internal static string Settings_Window_PopoutTitleBar_Name => Get(nameof(Settings_Window_PopoutTitleBar_Name));
internal static string Settings_Window_InactiveOpacity_Name => Get(nameof(Settings_Window_InactiveOpacity_Name));
internal static string Settings_Window_InactiveOpacity_Description => Get(nameof(Settings_Window_InactiveOpacity_Description));
internal static string Settings_Window_AllowMove_Name => Get(nameof(Settings_Window_AllowMove_Name));
internal static string Settings_Window_AllowResize_Name => Get(nameof(Settings_Window_AllowResize_Name));
internal static string Settings_Window_SidebarThreshold_Name => Get(nameof(Settings_Window_SidebarThreshold_Name));
@@ -427,8 +424,6 @@ internal class HellionStrings
internal static string Settings_About_CustomRepo => Get(nameof(Settings_About_CustomRepo));
internal static string Settings_Section_AutoTranslate => Get(nameof(Settings_Section_AutoTranslate));
internal static string Settings_Emotes_Block => Get(nameof(Settings_Emotes_Block));
internal static string Settings_NotifyFailedTell_Name => Get(nameof(Settings_NotifyFailedTell_Name));
internal static string Settings_NotifyFailedTell_Description => Get(nameof(Settings_NotifyFailedTell_Description));
internal static string Settings_Telemetry_None => Get(nameof(Settings_Telemetry_None));
internal static string Settings_Section_Database => Get(nameof(Settings_Section_Database));
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloqueja</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avisa quan un tell no arriba</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>El joc només informa d'un tell fallit al registre. Això mostra una notificació, perquè un missatge a algú desconnectat o en un altre món no passi desapercebut.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Vés al missatge més recent</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Llicència</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Desactiva els fosos del tema, els efectes en passar el cursor i les partícules.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fes clic a un botó i després prem la combinació de tecles. Esc esborra.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra de títol als pop-outs</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacitat inactiva</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>S'aplica mentre una altra finestra té el focus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permet moure</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importa un fitxer de tema…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exporta el tema actiu…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ruta al fitxer JSON (o arrossega'l a la carpeta)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escriu un missatge...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplica</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Zablokovat</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Upozornit, když tell nedorazí</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Hra hlásí neúspěšný tell jen v logu. Toto místo toho zobrazí upozornění, aby zpráva někomu offline nebo na jiném světě nezůstala bez povšimnutí.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Přejít na nejnovější zprávu</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licence</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Vypne prolínání motivů, přechody při najetí myší a poletující částice.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klikni na tlačítko a poté stiskni kombinaci kláves. Esc smaže.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Záhlaví u pop-out oken</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Neprůhlednost při neaktivitě</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Platí, když má fokus jiné okno.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Povolit přesouvání</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importovat soubor motivu…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportovat aktivní motiv…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Cesta k souboru JSON (nebo přetáhni do složky)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Napiš zprávu...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikovat</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloker</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Advar når en tell ikke når frem</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Spillet melder kun en mislykket tell i loggen. Dette giver en notifikation i stedet, så en besked til nogen offline eller på en anden verden ikke overses.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hop til den seneste besked</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licens</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Slår temaovergange, hover-fade og de svævende partikler fra.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klik på en knap, og tryk derefter tastekombinationen. Esc rydder.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Vis titellinje for pop-out-vinduer</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Uigennemsigtighed når inaktiv</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Gælder, mens et andet vindue har fokus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillad flytning</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importér temafil…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Eksportér aktivt tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sti til JSON-fil (eller træk-og-slip i mappen)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv en besked...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikér</value>
</data>
</root>
+3 -18
View File
@@ -1088,12 +1088,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Sperren</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Warnen, wenn ein Flüstern nicht ankommt</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Das Spiel meldet einen fehlgeschlagenen Flüstern nur im Protokoll. Das hier zeigt stattdessen eine Benachrichtigung, damit eine Nachricht an jemanden offline oder auf einer anderen Welt nicht untergeht.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Zur neuesten Nachricht springen</value>
</data>
@@ -1157,9 +1151,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Lizenz</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Schaltet Theme-Überblendungen, Hover-Überblendungen und die schwebenden Partikel ab.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Auf einen Knopf klicken, dann die Tastenkombination drücken. Esc löscht.</value>
</data>
@@ -1217,12 +1208,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Titelleiste für Pop-Outs</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Deckkraft im Hintergrund</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Gilt, solange ein anderes Fenster den Fokus hat.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Verschieben erlauben</value>
</data>
@@ -1301,9 +1286,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Theme-Datei importieren…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Aktives Theme exportieren…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Pfad zur JSON-Datei (oder in den Ordner ziehen)</value>
</data>
@@ -1337,4 +1319,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Nachricht schreiben...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplizieren</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Αποκλεισμός</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Προειδοποίηση όταν ένα tell δεν φτάνει</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Το παιχνίδι αναφέρει ένα αποτυχημένο tell μόνο στο αρχείο καταγραφής. Αυτό εμφανίζει ειδοποίηση, ώστε ένα μήνυμα σε κάποιον εκτός σύνδεσης ή σε άλλον κόσμο να μην περάσει απαρατήρητο.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Μετάβαση στο πιο πρόσφατο μήνυμα</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Άδεια</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Απενεργοποιεί τις μεταβάσεις θέματος, τα εφέ αιώρησης και τα σωματίδια.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Κάντε κλικ σε ένα κουμπί και μετά πατήστε τον συνδυασμό πλήκτρων. Το Esc καθαρίζει.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Εμφάνιση γραμμής τίτλου στα αποσπώμενα παράθυρα</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Αδιαφάνεια όταν ανενεργό</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Ισχύει όσο ένα άλλο παράθυρο έχει την εστίαση.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Να επιτρέπεται η μετακίνηση</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Εισαγωγή αρχείου θέματος…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Εξαγωγή ενεργού θέματος…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Διαδρομή προς αρχείο JSON (ή σύρετε στον φάκελο)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Γράψτε ένα μήνυμα...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Αντιγραφή</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloquear</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avisar cuando un tell no llega</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>El juego solo informa de un tell fallido en el registro. Esto muestra una notificación, para que un mensaje a alguien desconectado o en otro mundo no pase desapercibido.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir al mensaje más reciente</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licencia</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Desactiva las transiciones del tema, los efectos al pasar el cursor y las partículas.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Haz clic en un botón y luego pulsa la combinación de teclas. Esc borra.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra de título en pop-outs</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacidad inactiva</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Se aplica mientras otra ventana tiene el foco.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar archivo de tema…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportar el tema activo…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ruta al archivo JSON (o arrástralo a la carpeta)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escribe un mensaje...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Estä</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Varoita, kun tell ei mene perille</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Peli ilmoittaa epäonnistuneesta tellistä vain lokissa. Tämä näyttää sen sijaan ilmoituksen, jottei viesti offline-tilassa tai toisessa maailmassa olevalle jää huomaamatta.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Siirry uusimpaan viestiin</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisenssi</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Poistaa teemaristihäivytykset, osoitinhäivytykset ja leijuvat hiukkaset käytöstä.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Napsauta painiketta ja paina sitten näppäinyhdistelmää. Esc tyhjentää.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Näytä otsikkopalkki irrotetuissa ikkunoissa</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Läpinäkymättömyys epäaktiivisena</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Koskee, kun toinen ikkuna on kohdistettuna.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Salli siirtäminen</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Tuo teematiedosto…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Vie aktiivinen teema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON-tiedoston polku (tai vedä kansioon)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Kirjoita viesti...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Kahdenna</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloquer</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avertir quand un message privé n'arrive pas</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Le jeu ne signale un message privé échoué que dans le journal. Ceci affiche une notification à la place, pour qu'un message à quelqu'un hors ligne ou sur un autre monde ne passe pas inaperçu.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Aller au message le plus récent</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licence</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Désactive les fondus de thème, les effets de survol et les particules flottantes.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Cliquez sur un bouton, puis appuyez sur la combinaison de touches. Échap efface.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Afficher la barre de titre des fenêtres détachées</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacité inactive</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>S'applique quand une autre fenêtre a le focus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Autoriser le déplacement</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importer un fichier de thème…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exporter le thème actif…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Chemin du fichier JSON (ou glissez-déposez dans le dossier)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Écrivez un message...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliquer</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Letiltás</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Figyelmeztetés, ha egy tell nem érkezik meg</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>A játék csak a naplóban jelzi a sikertelen tellt. Ez helyette értesítést jelenít meg, hogy egy offline vagy másik világon lévő játékosnak küldött üzenet ne maradjon észrevétlen.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ugrás a legutóbbi üzenetre</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licenc</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Kikapcsolja a témaátmeneteket, a rámutatási elhalványulást és a lebegő részecskéket.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Kattints egy gombra, majd nyomd le a billentyűkombinációt. Az Esc törli.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Címsor a pop-out ablakoknál</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Átlátszatlanság inaktívan</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Akkor érvényes, ha másik ablak van fókuszban.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Mozgatás engedélyezése</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Témafájl importálása…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Aktív téma exportálása…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>A JSON-fájl útvonala (vagy húzd a mappába)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Írj egy üzenetet...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Másolat</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Blocca</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avvisa quando un tell non arriva</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Il gioco segnala un tell fallito solo nel registro. Questo mostra invece una notifica, così un messaggio a qualcuno offline o in un altro mondo non passa inosservato.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Vai al messaggio più recente</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licenza</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Disattiva le dissolvenze del tema, gli effetti al passaggio del mouse e le particelle.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fai clic su un pulsante, poi premi la combinazione di tasti. Esc cancella.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra del titolo nei pop-out</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacità finestra inattiva</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Si applica mentre un'altra finestra ha il focus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Consenti lo spostamento</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importa file tema…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Esporta il tema attivo…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Percorso del file JSON (o trascinalo nella cartella)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Scrivi un messaggio...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplica</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>ブロック</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>テルが届かなかったときに警告する</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>ゲームはテルの失敗をログにしか表示しません。この設定では代わりに通知を出すので、オフラインや別ワールドの相手へのメッセージを見落としません。</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>最新のメッセージへ移動</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>ライセンス</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>テーマのクロスフェード、ホバー時のフェード、漂う粒子を無効にします。</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>ボタンをクリックしてからキーの組み合わせを押してください。Esc で解除します。</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>ポップアウトのタイトルバーを表示</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>非アクティブ時の不透明度</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>別のウィンドウがフォーカスされている間に適用されます。</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>移動を許可</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>テーマファイルをインポート…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>現在のテーマをエクスポート…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSONファイルのパス(またはフォルダーにドラッグ&ドロップ)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>メッセージを入力...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>複製</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>차단</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>귓속말이 전달되지 않으면 알림</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>게임은 귓속말 실패를 로그에만 표시합니다. 이 설정은 대신 알림을 띄워, 오프라인이거나 다른 월드에 있는 상대에게 보낸 메시지를 놓치지 않게 합니다.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>최신 메시지로 이동</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>라이선스</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>테마 전환 효과, 마우스 오버 페이드, 떠다니는 입자를 끕니다.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>버튼을 클릭한 뒤 키 조합을 누르세요. Esc로 지웁니다.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>팝아웃 창의 제목 표시줄 보이기</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>비활성 상태 불투명도</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>다른 창이 포커스를 가진 동안 적용됩니다.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>이동 허용</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>테마 파일 가져오기…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>현재 테마 내보내기…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 파일 경로 (또는 폴더로 끌어다 놓기)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>메시지를 입력하세요...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>복제</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Blokker</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Varsle når en tell ikke kommer frem</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Spillet melder en mislykket tell bare i loggen. Dette gir et varsel i stedet, så en melding til noen offline eller på en annen verden ikke blir oversett.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hopp til den nyeste meldingen</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisens</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Slår av temaovergang, hover-toning og de drivende partiklene.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klikk på en knapp, og trykk deretter tastekombinasjonen. Esc tømmer.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Tittellinje for pop-out-vinduer</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Dekkevne når inaktiv</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Gjelder mens et annet vindu har fokus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillat flytting</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importer temafil…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Eksporter aktivt tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sti til JSON-fil (eller dra og slipp i mappen)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv en melding...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliser</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Blokkeren</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Waarschuwen als een tell niet aankomt</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Het spel meldt een mislukte tell alleen in het log. Dit toont in plaats daarvan een melding, zodat een bericht aan iemand offline of op een andere wereld niet onopgemerkt blijft.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ga naar het nieuwste bericht</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licentie</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Schakelt themaovergangen, hover-fades en de zwevende deeltjes uit.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klik op een knop en druk daarna de toetsencombinatie. Esc wist.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Titelbalk voor pop-outvensters</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Dekking bij inactiviteit</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Geldt terwijl een ander venster de focus heeft.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Verplaatsen toestaan</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Themabestand importeren…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Actief thema exporteren…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Pad naar JSON-bestand (of sleep het naar de map)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Typ een bericht...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliceren</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Zablokuj</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Ostrzegaj, gdy tell nie dotrze</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Gra zgłasza nieudany tell tylko w dzienniku. To zamiast tego wyświetla powiadomienie, żeby wiadomość do kogoś offline lub na innym świecie nie umknęła.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Przejdź do najnowszej wiadomości</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licencja</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Wyłącza przenikanie motywów, wygaszanie przy najechaniu i unoszące się cząstki.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Kliknij przycisk, a następnie naciśnij kombinację klawiszy. Esc czyści.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Pokaż pasek tytułu w oknach odłączonych</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Nieprzezroczystość, gdy nieaktywne</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Obowiązuje, gdy inne okno ma fokus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Zezwól na przesuwanie</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importuj plik motywu…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Eksportuj aktywny motyw…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ścieżka do pliku JSON (lub przeciągnij do folderu)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Napisz wiadomość...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikuj</value>
</data>
</root>
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloquear</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avisar quando um tell não chega</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>O jogo relata um tell que falhou apenas no registro. Isto mostra uma notificação, para que uma mensagem a alguém offline ou em outro mundo não passe despercebida.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir para a mensagem mais recente</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licença</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Desativa as transições de tema, os efeitos ao passar o cursor e as partículas.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Clique em um botão e depois pressione a combinação de teclas. Esc limpa.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título nas janelas destacadas</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacidade inativa</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Aplica-se enquanto outra janela está em foco.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar arquivo de tema…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportar o tema ativo…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Caminho do arquivo JSON (ou arraste para a pasta)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Digite uma mensagem...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
</root>
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Bloquear</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avisar quando um tell não chega</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>O jogo comunica um tell falhado apenas no registo. Isto mostra uma notificação, para que uma mensagem a alguém offline ou noutro mundo não passe despercebida.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir para a mensagem mais recente</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licença</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Desativa as transições de tema, os efeitos ao passar o cursor e as partículas.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Clique num botão e depois prima a combinação de teclas. Esc limpa.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título nas janelas destacadas</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacidade inativa</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Aplica-se enquanto outra janela está em foco.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar ficheiro de tema…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportar o tema ativo…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Caminho do ficheiro JSON (ou arraste para a pasta)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escreva uma mensagem...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
</root>
+3 -18
View File
@@ -1114,12 +1114,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Block</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Warn when a tell does not arrive</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>The game reports a failed tell in the log only. This raises a notification instead, so a message to someone offline or on another world does not go unnoticed.</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>off</value>
</data>
@@ -1174,9 +1168,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>License</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Turns off theme crossfades, hover fades and the drifting motes.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Click a button, then press the key combination. Esc clears.</value>
</data>
@@ -1234,12 +1225,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Show title bar for pop-outs</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Inactive opacity</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Applies while another window has focus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Allow movement</value>
</data>
@@ -1318,9 +1303,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Import theme file…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Export active theme…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Path to JSON file (or drag-and-drop into the folder)</value>
</data>
@@ -1354,4 +1336,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Type a message...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicate</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Blochează</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Avertizează când un tell nu ajunge</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Jocul raportează un tell eșuat doar în jurnal. Aceasta afișează în schimb o notificare, ca un mesaj către cineva offline sau aflat pe altă lume să nu treacă neobservat.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Salt la cel mai recent mesaj</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licență</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Dezactivează tranzițiile temei, efectele la trecerea cursorului și particulele.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fă clic pe un buton, apoi apasă combinația de taste. Esc șterge.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Afișează bara de titlu la ferestrele desprinse</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacitate când e inactiv</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Se aplică cât timp altă fereastră are focusul.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permite mutarea</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importă fișier de temă…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportă tema activă…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Calea către fișierul JSON (sau trage-l în folder)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Scrie un mesaj...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplică</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Заблокировать</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Предупреждать, когда tell не доходит</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Игра сообщает о недоставленном tell только в журнале. Здесь вместо этого показывается уведомление, чтобы сообщение офлайн-игроку или игроку с другого мира не осталось незамеченным.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Перейти к последнему сообщению</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Лицензия</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Отключает переходы темы, затухание при наведении и плавающие частицы.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Нажмите кнопку, затем нажмите сочетание клавиш. Esc очищает.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Показывать заголовок в отдельных окнах</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Непрозрачность в неактивном состоянии</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Действует, пока фокус на другом окне.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Разрешить перемещение</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Импортировать файл темы…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Экспортировать активную тему…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Путь к файлу JSON (или перетащите его в папку)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Введите сообщение...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Дублировать</value>
</data>
</root>
+3 -18
View File
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Blockera</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Varna när en tell inte kommer fram</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Spelet rapporterar en misslyckad tell bara i loggen. Det här visar en avisering i stället, så att ett meddelande till någon offline eller på en annan värld inte missas.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hoppa till det senaste meddelandet</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Licens</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Stänger av temaövertoningar, hovertoningar och de svävande partiklarna.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klicka på en knapp och tryck sedan tangentkombinationen. Esc rensar.</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Namnlist för pop-out-fönster</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Opacitet vid inaktivitet</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Gäller medan ett annat fönster har fokus.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillåt flytt</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importera temafil…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Exportera aktivt tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sökväg till JSON-fil (eller dra och släpp i mappen)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv ett meddelande...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicera</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Engelle</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Bir tell ulaşmadığında uyar</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Oyun başarısız bir tell'i yalnızca kayıtta bildirir. Bu ayar bunun yerine bir bildirim gösterir, böylece çevrimdışı ya da başka bir dünyadaki birine gönderilen ileti gözden kaçmaz.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>En son iletiye git</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisans</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Tema geçişlerini, üzerine gelme solmalarını ve süzülen parçacıkları kapatır.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Bir düğmeye tıklayın, ardından tuş kombinasyonuna basın. Esc temizler.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Ayrık pencereler için başlık çubuğunu göster</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Etkin değilken opaklık</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Başka bir pencere odaktayken geçerlidir.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Taşımaya izin ver</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Tema dosyası içe aktar…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Etkin temayı dışa aktar…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON dosyasının yolu (veya klasöre sürükleyip bırakın)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Bir ileti yazın...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Çoğalt</value>
</data>
</root>
+3 -18
View File
@@ -1093,12 +1093,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>Заблокувати</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>Попереджати, коли tell не доходить</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>Гра повідомляє про недоставлений tell лише в журналі. Це натомість показує сповіщення, щоб повідомлення офлайн-гравцю або гравцю з іншого світу не залишилося непоміченим.</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Перейти до останнього повідомлення</value>
</data>
@@ -1162,9 +1156,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>Ліцензія</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>Вимикає переходи теми, згасання при наведенні та плаваючі частинки.</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Натисніть кнопку, потім натисніть комбінацію клавіш. Esc очищає.</value>
</data>
@@ -1222,12 +1213,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Показувати рядок заголовка у відокремлених вікнах</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>Непрозорість у неактивному стані</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>Діє, поки фокус на іншому вікні.</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Дозволити переміщення</value>
</data>
@@ -1306,9 +1291,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Імпортувати файл теми…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>Експортувати активну тему…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Шлях до файлу JSON (або перетягніть у теку)</value>
</data>
@@ -1342,4 +1324,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Введіть повідомлення...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Дублювати</value>
</data>
</root>
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>屏蔽</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>密语未送达时提醒</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>游戏只在日志里提示密语发送失败。此设置改为弹出通知,让发给离线或其他世界玩家的消息不会被忽略。</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>跳到最新消息</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>许可证</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>关闭主题淡入淡出、悬停渐变和漂浮粒子。</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>点击按钮后按下组合键。Esc 清除。</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>显示弹出窗口的标题栏</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>非活动时的不透明度</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>当另一个窗口获得焦点时生效。</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>允许移动</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>导入主题文件…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>导出当前主题…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 文件路径(或拖放到文件夹)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>输入消息...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>复制</value>
</data>
</root>
@@ -1094,12 +1094,6 @@
<data name="Settings_Emotes_Block" xml:space="preserve">
<value>封鎖</value>
</data>
<data name="Settings_NotifyFailedTell_Name" xml:space="preserve">
<value>悄悄話未送達時提醒</value>
</data>
<data name="Settings_NotifyFailedTell_Description" xml:space="preserve">
<value>遊戲只在日誌裡提示悄悄話傳送失敗。此設定改為彈出通知,讓發給離線或其他世界玩家的訊息不會被忽略。</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>跳到最新訊息</value>
</data>
@@ -1163,9 +1157,6 @@
<data name="Settings_Section_License" xml:space="preserve">
<value>授權</value>
</data>
<data name="Settings_General_ReduceMotion_Description" xml:space="preserve">
<value>關閉主題淡入淡出、滑過漸變和漂浮粒子。</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>點擊按鈕後按下組合鍵。Esc 清除。</value>
</data>
@@ -1223,12 +1214,6 @@
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>顯示彈出視窗的標題列</value>
</data>
<data name="Settings_Window_InactiveOpacity_Name" xml:space="preserve">
<value>非作用中的不透明度</value>
</data>
<data name="Settings_Window_InactiveOpacity_Description" xml:space="preserve">
<value>當另一個視窗取得焦點時生效。</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>允許移動</value>
</data>
@@ -1307,9 +1292,6 @@
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>匯入主題檔案…</value>
</data>
<data name="Settings_Theme_ExportActive" xml:space="preserve">
<value>匯出目前主題…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 檔案路徑(或拖放到資料夾)</value>
</data>
@@ -1343,4 +1325,7 @@
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>輸入訊息...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>複製</value>
</data>
</root>
+131
View File
@@ -0,0 +1,131 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Ui.Components.Settings;
using HellionChat.Util;
namespace HellionChat.SelfTests;
// The gate has fourteen unit tests. None of them prove that the workers are
// wired to it, and that is where the mistake actually happened: the metadata
// refresh reached the store without taking the gate at all, and its flag was
// missing from the tab's shared busy state, so a wipe could start while it held
// the read lock.
//
// A unit test cannot see that. It needs the real singleton, the real flags and
// the real settings tab, so it lives here.
internal sealed class DbGateWiringStep : ISelfTestStep
{
private readonly Plugin _plugin;
public DbGateWiringStep(Plugin plugin) => _plugin = plugin;
public string Name => "Hellion Chat - DB gate wiring";
public SelfTestStepResult RunStep()
{
var failures = new List<string>();
// Nothing may be running when the probe starts, or the assertions below
// measure somebody else's operation.
if (_plugin.DbOperations.IsBusy)
failures.Add($"gate already held by {_plugin.DbOperations.Current} before the probe");
CheckEveryOperationRoundTrips(failures);
CheckRefusalLeavesTheOwnerAlone(failures);
CheckRevisionTracksMutations(failures);
CheckTabSeesTheGate(failures);
foreach (var f in failures)
ImGui.Text(f);
SelfTestReport.Append(Name, failures.Count == 0 ? "PASS" : "FAIL", failures);
return failures.Count == 0 ? SelfTestStepResult.Pass : SelfTestStepResult.Fail;
}
private void CheckEveryOperationRoundTrips(List<string> failures)
{
foreach (var op in EnumValues<DbOperation>.All)
{
if (op == DbOperation.None)
continue;
if (!_plugin.DbOperations.TryBegin(op))
{
failures.Add($"{op}: TryBegin refused on a free gate");
continue;
}
if (_plugin.DbOperations.Current != op)
failures.Add($"{op}: gate reports {_plugin.DbOperations.Current} after TryBegin");
if (_plugin.DbOperations.TryBegin(op))
failures.Add($"{op}: a second TryBegin succeeded while it was held");
_plugin.DbOperations.End(op);
if (_plugin.DbOperations.IsBusy)
failures.Add($"{op}: still busy after End");
}
}
private void CheckRefusalLeavesTheOwnerAlone(List<string> failures)
{
if (!_plugin.DbOperations.TryBegin(DbOperation.Export))
{
failures.Add("could not take the gate for the refusal check");
return;
}
// A worker whose TryBegin was refused still runs its finally. Releasing
// there must not hand away somebody else's lock.
_plugin.DbOperations.End(DbOperation.Clear);
if (_plugin.DbOperations.Current != DbOperation.Export)
failures.Add("a foreign End released the gate");
_plugin.DbOperations.End(DbOperation.Export);
}
private void CheckRevisionTracksMutations(List<string> failures)
{
var before = _plugin.DbOperations.Revision;
_plugin.DbOperations.TryBegin(DbOperation.Export);
_plugin.DbOperations.End(DbOperation.Export);
if (_plugin.DbOperations.Revision != before)
failures.Add("export moved the revision; it cannot change a row");
_plugin.DbOperations.TryBegin(DbOperation.Cleanup);
_plugin.DbOperations.End(DbOperation.Cleanup);
if (_plugin.DbOperations.Revision == before)
failures.Add(
"cleanup did not move the revision; a stale preview would pass as current"
);
}
// The settings tab decides whether the destructive buttons are live. If it
// cannot see a held gate, two of them are clickable at once.
private void CheckTabSeesTheGate(List<string> failures)
{
if (!_plugin.DbOperations.TryBegin(DbOperation.Clear))
{
failures.Add("could not take the gate for the tab check");
return;
}
try
{
if (!_plugin.DataPrivacyTab.AnythingRunningForSelfTest)
failures.Add("the data and privacy tab does not see a held gate");
}
finally
{
_plugin.DbOperations.End(DbOperation.Clear);
}
if (_plugin.DataPrivacyTab.AnythingRunningForSelfTest)
failures.Add("the tab still reports busy after the gate was released");
}
public void CleanUp() { }
}
@@ -171,7 +171,12 @@ internal sealed class TabEditor
// already has its sixty channels picked, and Tab.Clone has been ready
// for it since v1.8.0.
ImGui.SameLine();
if (ImGuiUtil.IconButton(FontAwesomeIcon.Copy, tooltip: Language.Options_Tabs_Add))
if (
ImGuiUtil.IconButton(
FontAwesomeIcon.Copy,
tooltip: HellionStrings.Settings_Tabs_Duplicate
)
)
{
var copy = tab.Clone();
copy.Identifier = Guid.NewGuid();
@@ -191,7 +196,6 @@ internal sealed class TabEditor
if (_editing == tab.Identifier)
ClearWorking();
_ = TabLifecycleHelpers.SelectionAfterDelete(tabs, index);
_plugin.SaveConfig();
RequestRefilter();
}
@@ -69,6 +69,11 @@ internal sealed class DataPrivacyTab
// refusal the user has to trigger to discover is not an answer.
private DbOperation CurrentOperation => _plugin.DbOperations.Current;
// The gate-wiring self-test asserts that this sees a held gate. It is the
// one thing about this state that a unit test cannot reach: the flags are
// instance state on a DI singleton and the gate is another.
internal bool AnythingRunningForSelfTest => AnythingRunning;
private bool AnythingRunning =>
_exportRunning
|| _exportDialogOpen
@@ -76,6 +81,7 @@ internal sealed class DataPrivacyTab
|| _cleanupRunning
|| _clearRunning
|| _maintenanceRunning
|| _dbRefreshRunning
|| _plugin.RetentionSweepRunning
|| CurrentOperation != DbOperation.None;
@@ -380,21 +386,27 @@ internal sealed class DataPrivacyTab
ImGuiUtil.Tooltip(Language.Options_Database_Metadata_CopyConfigPath);
}
ImGuiUtil.HelpText(
string.Format(
Language.Options_Database_Metadata_Size,
StringUtil.BytesToString(_dbSize)
)
);
ImGuiUtil.HelpText(
string.Format(
Language.Options_Database_Metadata_LogSize,
StringUtil.BytesToString(_dbLogSize)
)
);
ImGuiUtil.HelpText(
string.Format(Language.Options_Database_Metadata_MessageCount, _dbMessageCount)
);
// Same reason the clear hint below waits: the fields start at zero, and
// "0 B / 0 messages" reads as an empty database rather than as a number
// that has not been fetched yet.
if (_dbEverRefreshed)
{
ImGuiUtil.HelpText(
string.Format(
Language.Options_Database_Metadata_Size,
StringUtil.BytesToString(_dbSize)
)
);
ImGuiUtil.HelpText(
string.Format(
Language.Options_Database_Metadata_LogSize,
StringUtil.BytesToString(_dbLogSize)
)
);
ImGuiUtil.HelpText(
string.Format(Language.Options_Database_Metadata_MessageCount, _dbMessageCount)
);
}
ImGui.Spacing();
@@ -458,11 +470,25 @@ internal sealed class DataPrivacyTab
{
try
{
_dbSize = _plugin.MessageManager.Store.DatabaseSize();
_dbLogSize = _plugin.MessageManager.Store.DatabaseLogSize();
_dbMessageCount = _plugin.MessageManager.Store.MessageCount();
_dbRefreshedAt = Environment.TickCount64;
_dbEverRefreshed = true;
// Takes the gate like every other reader of the store.
// MessageCount holds _readLock, and a VACUUM starting under it
// is exactly the collision this gate was written for -- being a
// read rather than a write does not exempt it.
if (!_plugin.DbOperations.TryBegin(DbOperation.Cleanup))
return;
try
{
_dbSize = _plugin.MessageManager.Store.DatabaseSize();
_dbLogSize = _plugin.MessageManager.Store.DatabaseLogSize();
_dbMessageCount = _plugin.MessageManager.Store.MessageCount();
_dbRefreshedAt = Environment.TickCount64;
_dbEverRefreshed = true;
}
finally
{
_plugin.DbOperations.End(DbOperation.Cleanup);
}
}
catch (Exception e)
{
@@ -561,6 +587,11 @@ internal sealed class DataPrivacyTab
{
_clearRunning = false;
_logger.LogError(e, "Could not start the clear thread");
// The most destructive button in the plugin. Silence here means the
// user pressed it and nothing happened, with no way to tell that
// from a wipe that worked.
Notify(HellionStrings.Settings_Database_ClearError, NotificationType.Error);
}
}
@@ -682,6 +713,11 @@ internal sealed class DataPrivacyTab
catch (Exception e)
{
_logger.LogError(e, "Manual maintenance failed");
// The comment above promises refusals are said out loud. A
// failure that is not is the same silence wearing a different
// hat.
Notify(HellionStrings.Settings_Database_ClearError, NotificationType.Error);
}
finally
{
@@ -1047,7 +1083,7 @@ internal sealed class DataPrivacyTab
{
_cleanupRunning = false;
_logger.LogError(e, "Could not start the cleanup thread");
WrapperUtil.AddNotification(HellionStrings.Cleanup_Error, NotificationType.Error);
Notify(HellionStrings.Cleanup_Error, NotificationType.Error);
}
}
@@ -1106,9 +1142,9 @@ internal sealed class DataPrivacyTab
);
}
// Whole groups rather than sixty individual channels. Nobody makes a
// sixty-way choice, and the eight groups are the same ones the privacy
// wizard already uses, so the two screens describe the world the same way.
// Whole groups rather than eighty-nine individual channels. Nobody makes an
// eighty-nine-way choice, and the same eight groups carry the persist grid
// below, so the two screens describe channels the same way.
private void DrawExportChannels()
{
ImGui.Spacing();
@@ -1334,7 +1370,7 @@ internal sealed class DataPrivacyTab
// The thread never ran, so nothing will clear the flag for us.
_exportRunning = false;
_logger.LogError(e, "Could not start the export thread");
WrapperUtil.AddNotification(HellionStrings.Export_Error, NotificationType.Error);
Notify(HellionStrings.Export_Error, NotificationType.Error);
}
}
@@ -44,7 +44,7 @@ internal sealed class GeneralTab
_w.ToggleRow(
ImGui.GetID("general.behaviour.reducemotion"u8),
HellionStrings.Settings_ThemeAndLayout_ReduceMotion_Name,
HellionStrings.Settings_General_ReduceMotion_Description,
HellionStrings.Settings_ThemeAndLayout_ReduceMotion_Description,
() => Plugin.Config.ReduceMotion,
v => Plugin.Config.ReduceMotion = v
);
@@ -80,8 +80,8 @@ internal sealed class GeneralTab
// is typing does not see it. On by default and never reachable.
_w.ToggleRow(
ImGui.GetID("general.notifications.failedtell"u8),
HellionStrings.Settings_NotifyFailedTell_Name,
HellionStrings.Settings_NotifyFailedTell_Description,
HellionStrings.Settings_Chat_NotifyFailedTell_Name,
HellionStrings.Settings_Chat_NotifyFailedTell_Description,
() => Plugin.Config.NotifyFailedTell,
v => Plugin.Config.NotifyFailedTell = v
);
@@ -93,8 +93,8 @@ internal sealed class WindowTab
);
_w.SliderFloatRow(
ImGui.GetID("window.opacity.inactive"u8),
HellionStrings.Settings_Window_InactiveOpacity_Name,
HellionStrings.Settings_Window_InactiveOpacity_Description,
HellionStrings.Settings_ThemeAndLayout_WindowOpacityInactive_Name,
HellionStrings.Settings_ThemeAndLayout_WindowOpacityInactive_Description,
() => Plugin.Config.WindowOpacityInactive,
v => Plugin.Config.WindowOpacityInactive = v,
0.1f,
@@ -39,7 +39,7 @@ internal sealed class ThemeImportExportRow
}
ImGui.SameLine();
if (ImGui.Button(HellionStrings.Settings_Theme_ExportActive))
if (ImGui.Button(HellionStrings.Settings_Themes_ExportActive))
{
ExportActive();
}
-18
View File
@@ -52,24 +52,6 @@ internal static class TabLifecycleHelpers
return index;
}
// Which tab the editor should select after deleting the one at index.
//
// The next editable tab below, else the one above, else nothing. Returning
// the index the caller should select *after* the removal, so it is already
// shifted.
public static int SelectionAfterDelete(IReadOnlyList<Tab> tabs, int deletedIndex)
{
for (var i = deletedIndex + 1; i < tabs.Count; i++)
if (IsEditable(tabs[i]))
return i - 1;
for (var i = deletedIndex - 1; i >= 0; i--)
if (IsEditable(tabs[i]))
return i;
return -1;
}
// Deleting the last editable tab leaves a window with nothing to draw, and
// the message list has no empty state. The editor offers templates instead
// of a delete in that situation.
+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.
+2 -2
View File
@@ -183,8 +183,8 @@ Check `/xllog` after a plugin reload to see what loaded and what didn't.
4. Watch every plugin window (chat, settings, pop-out) and pick something to fix.
5. Tweak. Reload. Repeat.
Tip: the **Settings → Appearance** picker shows a mini-mockup per theme — your colors are visible before
you switch.
Tip: the **Settings → Appearance** picker shows a mini-mockup per theme — your colors are visible
before you switch.
## Sharing themes