Localize the Hellion Chat surface area (EN + DE)
Add HellionStrings.resx as the English source and HellionStrings.de.resx for German, with a hand-maintained Designer.cs that mirrors the layout of Language.Designer.cs. Resource files live next to the upstream Language.resx but are kept entirely separate so upstream cherry-picks never collide with our translations and any future Hellion-only translation tooling (Crowdin, manual contribution) can target this file without touching the Chat 2 dictionary. Plugin.LanguageChanged now updates HellionStrings.Culture alongside Language.Culture so every UI string flips to the active locale at the same moment. The Privacy tab title, master switch, channel groups (now resolved per frame so the language can change without restart), preset buttons, failsafe toggle, retention section, cleanup section, status messages and notification bodies all read from HellionStrings. The migration toast also takes its title and body from there. Translations follow the project's German style: Du-Form, full diacritics (ä, ö, ü), no em-dashes inside flowing prose, "Whitelist" and "Linkshell" kept as-is because they are the established terms.
This commit is contained in:
@@ -35,6 +35,11 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- HellionChat — Hellion-specific resource bundle (HellionStrings.resx
|
||||
+ HellionStrings.<lang>.resx) is picked up automatically by the SDK
|
||||
default include. Designer.cs is hand-maintained, no auto-gen needed. -->
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="images\" />
|
||||
</ItemGroup>
|
||||
|
||||
+3
-2
@@ -129,8 +129,8 @@ public sealed class Plugin : IDalamudPlugin
|
||||
|
||||
Notification.AddNotification(new Dalamud.Interface.ImGuiNotification.Notification
|
||||
{
|
||||
Title = "Hellion Chat",
|
||||
Content = "Privacy filter activated by default. Settings → Privacy to adjust.",
|
||||
Title = HellionStrings.Migration_Notification_Title,
|
||||
Content = HellionStrings.Migration_Notification_Content,
|
||||
Type = Dalamud.Interface.ImGuiNotification.NotificationType.Info,
|
||||
InitialDuration = TimeSpan.FromSeconds(15),
|
||||
});
|
||||
@@ -392,6 +392,7 @@ public sealed class Plugin : IDalamudPlugin
|
||||
: new CultureInfo(Config.LanguageOverride.Code());
|
||||
|
||||
Language.Culture = info;
|
||||
HellionStrings.Culture = info;
|
||||
}
|
||||
|
||||
private static readonly string[] ChatAddonNames =
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// Hand-maintained strongly-typed accessor for HellionStrings.resx.
|
||||
// Mirrors the layout of Language.Designer.cs so the same Plugin.cs
|
||||
// LanguageChanged handler can update Culture for both classes.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace ChatTwo.Resources;
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
|
||||
internal class HellionStrings
|
||||
{
|
||||
private static global::System.Resources.ResourceManager? resourceMan;
|
||||
private static global::System.Globalization.CultureInfo? resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal HellionStrings() { }
|
||||
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if (resourceMan is null)
|
||||
resourceMan = new global::System.Resources.ResourceManager("ChatTwo.Resources.HellionStrings", typeof(HellionStrings).Assembly);
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo? Culture
|
||||
{
|
||||
get => resourceCulture;
|
||||
set => resourceCulture = value;
|
||||
}
|
||||
|
||||
private static string Get(string key)
|
||||
=> ResourceManager.GetString(key, resourceCulture) ?? key;
|
||||
|
||||
internal static string Privacy_Tab_Title => Get(nameof(Privacy_Tab_Title));
|
||||
internal static string Privacy_FilterEnabled_Name => Get(nameof(Privacy_FilterEnabled_Name));
|
||||
internal static string Privacy_FilterEnabled_Description => Get(nameof(Privacy_FilterEnabled_Description));
|
||||
internal static string Privacy_Whitelist_Help => Get(nameof(Privacy_Whitelist_Help));
|
||||
internal static string Privacy_Preset_PrivacyFirst => Get(nameof(Privacy_Preset_PrivacyFirst));
|
||||
internal static string Privacy_Preset_ClearAll => Get(nameof(Privacy_Preset_ClearAll));
|
||||
internal static string Privacy_Preset_SelectAll => Get(nameof(Privacy_Preset_SelectAll));
|
||||
internal static string Privacy_Group_DirectMessages => Get(nameof(Privacy_Group_DirectMessages));
|
||||
internal static string Privacy_Group_PartyAlliance => Get(nameof(Privacy_Group_PartyAlliance));
|
||||
internal static string Privacy_Group_FreeCompany => Get(nameof(Privacy_Group_FreeCompany));
|
||||
internal static string Privacy_Group_Linkshells => Get(nameof(Privacy_Group_Linkshells));
|
||||
internal static string Privacy_Group_CrossLinkshells => Get(nameof(Privacy_Group_CrossLinkshells));
|
||||
internal static string Privacy_Group_ExtraChat => Get(nameof(Privacy_Group_ExtraChat));
|
||||
internal static string Privacy_Group_PublicChat => Get(nameof(Privacy_Group_PublicChat));
|
||||
internal static string Privacy_Group_SystemLogs => Get(nameof(Privacy_Group_SystemLogs));
|
||||
internal static string Privacy_PersistUnknown_Name => Get(nameof(Privacy_PersistUnknown_Name));
|
||||
internal static string Privacy_PersistUnknown_Description => Get(nameof(Privacy_PersistUnknown_Description));
|
||||
|
||||
internal static string Cleanup_Heading => Get(nameof(Cleanup_Heading));
|
||||
internal static string Cleanup_Help_Intro => Get(nameof(Cleanup_Help_Intro));
|
||||
internal static string Cleanup_Help_SavedNote => Get(nameof(Cleanup_Help_SavedNote));
|
||||
internal static string Cleanup_RefreshPreview => Get(nameof(Cleanup_RefreshPreview));
|
||||
internal static string Cleanup_NoPreview => Get(nameof(Cleanup_NoPreview));
|
||||
internal static string Cleanup_TotalStored => Get(nameof(Cleanup_TotalStored));
|
||||
internal static string Cleanup_WillKeep => Get(nameof(Cleanup_WillKeep));
|
||||
internal static string Cleanup_WillDelete => Get(nameof(Cleanup_WillDelete));
|
||||
internal static string Cleanup_Breakdown => Get(nameof(Cleanup_Breakdown));
|
||||
internal static string Cleanup_Marker_Keep => Get(nameof(Cleanup_Marker_Keep));
|
||||
internal static string Cleanup_Marker_Delete => Get(nameof(Cleanup_Marker_Delete));
|
||||
internal static string Cleanup_Apply_Label => Get(nameof(Cleanup_Apply_Label));
|
||||
internal static string Cleanup_Apply_Tooltip => Get(nameof(Cleanup_Apply_Tooltip));
|
||||
internal static string Cleanup_Running => Get(nameof(Cleanup_Running));
|
||||
internal static string Cleanup_PreviewError => Get(nameof(Cleanup_PreviewError));
|
||||
internal static string Cleanup_Success => Get(nameof(Cleanup_Success));
|
||||
internal static string Cleanup_Error => Get(nameof(Cleanup_Error));
|
||||
|
||||
internal static string Retention_Heading => Get(nameof(Retention_Heading));
|
||||
internal static string Retention_Enabled_Name => Get(nameof(Retention_Enabled_Name));
|
||||
internal static string Retention_Enabled_Description => Get(nameof(Retention_Enabled_Description));
|
||||
internal static string Retention_Default_Label => Get(nameof(Retention_Default_Label));
|
||||
internal static string Retention_Default_Help => Get(nameof(Retention_Default_Help));
|
||||
internal static string Retention_Reset_Spec => Get(nameof(Retention_Reset_Spec));
|
||||
internal static string Retention_Clear_Overrides => Get(nameof(Retention_Clear_Overrides));
|
||||
internal static string Retention_Tree_Heading => Get(nameof(Retention_Tree_Heading));
|
||||
internal static string Retention_Tag_Override => Get(nameof(Retention_Tag_Override));
|
||||
internal static string Retention_Tag_Spec => Get(nameof(Retention_Tag_Spec));
|
||||
internal static string Retention_Tag_Global => Get(nameof(Retention_Tag_Global));
|
||||
internal static string Retention_Reset_Button => Get(nameof(Retention_Reset_Button));
|
||||
internal static string Retention_Apply_Label => Get(nameof(Retention_Apply_Label));
|
||||
internal static string Retention_Apply_Tooltip => Get(nameof(Retention_Apply_Tooltip));
|
||||
internal static string Retention_Running => Get(nameof(Retention_Running));
|
||||
internal static string Retention_LastRun_Never => Get(nameof(Retention_LastRun_Never));
|
||||
internal static string Retention_LastRun_At => Get(nameof(Retention_LastRun_At));
|
||||
internal static string Retention_Success => Get(nameof(Retention_Success));
|
||||
internal static string Retention_Error => Get(nameof(Retention_Error));
|
||||
|
||||
internal static string Migration_Notification_Title => Get(nameof(Migration_Notification_Title));
|
||||
internal static string Migration_Notification_Content => Get(nameof(Migration_Notification_Content));
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Privacy_Tab_Title" xml:space="preserve">
|
||||
<value>Datenschutz</value>
|
||||
</data>
|
||||
<data name="Privacy_FilterEnabled_Name" xml:space="preserve">
|
||||
<value>Datenschutz-Filter aktivieren</value>
|
||||
</data>
|
||||
<data name="Privacy_FilterEnabled_Description" xml:space="preserve">
|
||||
<value>Wenn aktiviert, werden nur Nachrichten aus den erlaubten Kanälen in die Datenbank gespeichert. Beim Deaktivieren gilt wieder das Standard-Verhalten von ChatTwo, also alles außer Battle-Logs wird gespeichert.</value>
|
||||
</data>
|
||||
<data name="Privacy_Whitelist_Help" xml:space="preserve">
|
||||
<value>Wähle aus, welche Kanäle in die lokale Datenbank gespeichert werden. Standard nach Datensparsamkeit: nur deine eigenen Konversationen. Über die Buttons unten kannst du eine Voreinstellung anwenden.</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_PrivacyFirst" xml:space="preserve">
|
||||
<value>Datensparsamkeit (empfohlen)</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_ClearAll" xml:space="preserve">
|
||||
<value>Alle abwählen</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_SelectAll" xml:space="preserve">
|
||||
<value>Alle auswählen</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_DirectMessages" xml:space="preserve">
|
||||
<value>Direktnachrichten</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_PartyAlliance" xml:space="preserve">
|
||||
<value>Gruppe & Allianz</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_FreeCompany" xml:space="preserve">
|
||||
<value>Free Company</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_Linkshells" xml:space="preserve">
|
||||
<value>Linkshells</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_CrossLinkshells" xml:space="preserve">
|
||||
<value>Cross-World-Linkshells</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_ExtraChat" xml:space="preserve">
|
||||
<value>ExtraChat (verschlüsselt)</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_PublicChat" xml:space="preserve">
|
||||
<value>Öffentlicher Chat (Daten Dritter)</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_SystemLogs" xml:space="preserve">
|
||||
<value>System & Spiel-Logs</value>
|
||||
</data>
|
||||
<data name="Privacy_PersistUnknown_Name" xml:space="preserve">
|
||||
<value>Unbekannte Kanal-Typen speichern</value>
|
||||
</data>
|
||||
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
|
||||
<value>Sicherheitsnetz für ChatTypes, die durch zukünftige FFXIV-Patches dazukommen und dem Plugin noch nicht bekannt sind. Standard ist AUS (Datensparsamkeit). Aktivieren, wenn du auch zukünftige Kanäle vollständig mitloggen willst.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Heading" xml:space="preserve">
|
||||
<value>Filter auf bestehende Datenbank anwenden</value>
|
||||
</data>
|
||||
<data name="Cleanup_Help_Intro" xml:space="preserve">
|
||||
<value>Der Datenschutz-Filter wirkt nur auf neue Nachrichten. Über das Aufräumen unten kannst du bereits gespeicherte Nachrichten nachträglich entfernen, die nicht zu deiner gespeicherten Whitelist passen.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
|
||||
<value>Das Aufräumen nutzt deine GESPEICHERTE Whitelist (Plugin.Config), nicht ungespeicherte Änderungen oben. Klicke zuerst Speichern, wenn du deine aktuellen Änderungen anwenden willst.</value>
|
||||
</data>
|
||||
<data name="Cleanup_RefreshPreview" xml:space="preserve">
|
||||
<value>Vorschau aktualisieren</value>
|
||||
</data>
|
||||
<data name="Cleanup_NoPreview" xml:space="preserve">
|
||||
<value>Noch keine Vorschau. Klicke Aktualisieren, um die Auswirkung zu berechnen.</value>
|
||||
</data>
|
||||
<data name="Cleanup_TotalStored" xml:space="preserve">
|
||||
<value>Gespeicherte Nachrichten gesamt: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_WillKeep" xml:space="preserve">
|
||||
<value>Behalten: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_WillDelete" xml:space="preserve">
|
||||
<value>Löschen: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_Breakdown" xml:space="preserve">
|
||||
<value>Aufschlüsselung pro Kanal</value>
|
||||
</data>
|
||||
<data name="Cleanup_Marker_Keep" xml:space="preserve">
|
||||
<value>[BEHALTEN]</value>
|
||||
</data>
|
||||
<data name="Cleanup_Marker_Delete" xml:space="preserve">
|
||||
<value>[LÖSCHEN] </value>
|
||||
</data>
|
||||
<data name="Cleanup_Apply_Label" xml:space="preserve">
|
||||
<value>Aktuellen Filter auf Datenbank anwenden</value>
|
||||
</data>
|
||||
<data name="Cleanup_Apply_Tooltip" xml:space="preserve">
|
||||
<value>Strg+Umschalt: Löscht {0:N0} Nachrichten unwiderruflich und führt danach VACUUM aus. Nicht rückgängig zu machen.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Running" xml:space="preserve">
|
||||
<value>Aufräumen läuft im Hintergrund…</value>
|
||||
</data>
|
||||
<data name="Cleanup_PreviewError" xml:space="preserve">
|
||||
<value>Vorschau konnte nicht berechnet werden, siehe /xllog</value>
|
||||
</data>
|
||||
<data name="Cleanup_Success" xml:space="preserve">
|
||||
<value>Aufräumen abgeschlossen, {0:N0} Nachrichten entfernt.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Error" xml:space="preserve">
|
||||
<value>Aufräumen fehlgeschlagen, siehe /xllog</value>
|
||||
</data>
|
||||
<data name="Retention_Heading" xml:space="preserve">
|
||||
<value>Aufbewahrung von Nachrichten</value>
|
||||
</data>
|
||||
<data name="Retention_Enabled_Name" xml:space="preserve">
|
||||
<value>Nachrichten nach Kanal-Aufbewahrung automatisch löschen</value>
|
||||
</data>
|
||||
<data name="Retention_Enabled_Description" xml:space="preserve">
|
||||
<value>Wenn aktiviert, werden Nachrichten älter als das eingestellte Fenster bei jedem Plugin-Start gelöscht (höchstens einmal pro 24 Stunden). Standard ist AUS, das Plugin löscht ohne deine ausdrückliche Zustimmung nichts.</value>
|
||||
</data>
|
||||
<data name="Retention_Default_Label" xml:space="preserve">
|
||||
<value>Standard-Aufbewahrung (Tage, 0 = nie)</value>
|
||||
</data>
|
||||
<data name="Retention_Default_Help" xml:space="preserve">
|
||||
<value>Gilt für Kanäle, die unten keine eigene Vorgabe haben.</value>
|
||||
</data>
|
||||
<data name="Retention_Reset_Spec" xml:space="preserve">
|
||||
<value>Vorgaben auf Spec-Defaults setzen</value>
|
||||
</data>
|
||||
<data name="Retention_Clear_Overrides" xml:space="preserve">
|
||||
<value>Alle Vorgaben entfernen</value>
|
||||
</data>
|
||||
<data name="Retention_Tree_Heading" xml:space="preserve">
|
||||
<value>Aufbewahrung pro Kanal</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Override" xml:space="preserve">
|
||||
<value>[eigen]</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Spec" xml:space="preserve">
|
||||
<value>[spec]</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Global" xml:space="preserve">
|
||||
<value>[global]</value>
|
||||
</data>
|
||||
<data name="Retention_Reset_Button" xml:space="preserve">
|
||||
<value>zurück</value>
|
||||
</data>
|
||||
<data name="Retention_Apply_Label" xml:space="preserve">
|
||||
<value>Aufbewahrung jetzt anwenden</value>
|
||||
</data>
|
||||
<data name="Retention_Apply_Tooltip" xml:space="preserve">
|
||||
<value>Strg+Umschalt: Führt die Aufbewahrungs-Bereinigung sofort mit der GESPEICHERTEN Vorgabe aus. Speichere deine Änderungen vorher.</value>
|
||||
</data>
|
||||
<data name="Retention_Running" xml:space="preserve">
|
||||
<value>Aufbewahrungs-Bereinigung läuft im Hintergrund…</value>
|
||||
</data>
|
||||
<data name="Retention_LastRun_Never" xml:space="preserve">
|
||||
<value>Letzter Lauf: nie</value>
|
||||
</data>
|
||||
<data name="Retention_LastRun_At" xml:space="preserve">
|
||||
<value>Letzter Lauf: {0:yyyy-MM-dd HH:mm}</value>
|
||||
</data>
|
||||
<data name="Retention_Success" xml:space="preserve">
|
||||
<value>Aufbewahrungs-Bereinigung abgeschlossen, {0:N0} Nachrichten entfernt.</value>
|
||||
</data>
|
||||
<data name="Retention_Error" xml:space="preserve">
|
||||
<value>Aufbewahrungs-Bereinigung fehlgeschlagen, siehe /xllog</value>
|
||||
</data>
|
||||
<data name="Migration_Notification_Title" xml:space="preserve">
|
||||
<value>Hellion Chat</value>
|
||||
</data>
|
||||
<data name="Migration_Notification_Content" xml:space="preserve">
|
||||
<value>Datenschutz-Filter ist standardmäßig aktiviert. Einstellungen → Datenschutz zum Anpassen.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Privacy_Tab_Title" xml:space="preserve">
|
||||
<value>Privacy</value>
|
||||
</data>
|
||||
<data name="Privacy_FilterEnabled_Name" xml:space="preserve">
|
||||
<value>Enable privacy filter</value>
|
||||
</data>
|
||||
<data name="Privacy_FilterEnabled_Description" xml:space="preserve">
|
||||
<value>When enabled, only messages from whitelisted channels are persisted to the database. Disabling restores upstream ChatTwo behavior (everything except battle messages is stored).</value>
|
||||
</data>
|
||||
<data name="Privacy_Whitelist_Help" xml:space="preserve">
|
||||
<value>Pick which channels are stored in the local database. Privacy-First default: only your own conversations. Use the buttons below to apply a preset.</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_PrivacyFirst" xml:space="preserve">
|
||||
<value>Privacy-First (recommended)</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_ClearAll" xml:space="preserve">
|
||||
<value>Clear all</value>
|
||||
</data>
|
||||
<data name="Privacy_Preset_SelectAll" xml:space="preserve">
|
||||
<value>Select all</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_DirectMessages" xml:space="preserve">
|
||||
<value>Direct Messages</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_PartyAlliance" xml:space="preserve">
|
||||
<value>Party & Alliance</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_FreeCompany" xml:space="preserve">
|
||||
<value>Free Company</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_Linkshells" xml:space="preserve">
|
||||
<value>Linkshells</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_CrossLinkshells" xml:space="preserve">
|
||||
<value>Cross-World Linkshells</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_ExtraChat" xml:space="preserve">
|
||||
<value>ExtraChat (Encrypted)</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_PublicChat" xml:space="preserve">
|
||||
<value>Public Chat (third-party data)</value>
|
||||
</data>
|
||||
<data name="Privacy_Group_SystemLogs" xml:space="preserve">
|
||||
<value>System & Game Logs</value>
|
||||
</data>
|
||||
<data name="Privacy_PersistUnknown_Name" xml:space="preserve">
|
||||
<value>Persist unknown channel types</value>
|
||||
</data>
|
||||
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
|
||||
<value>Failsafe for ChatTypes added by future FFXIV patches that this plugin does not yet know about. Default OFF (Privacy-First). Turn ON if you want a complete log including future channels.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Heading" xml:space="preserve">
|
||||
<value>Apply filter to existing database</value>
|
||||
</data>
|
||||
<data name="Cleanup_Help_Intro" xml:space="preserve">
|
||||
<value>The privacy filter only applies to new messages. Use the cleanup below to retroactively remove already-stored messages that don't match your saved whitelist.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
|
||||
<value>Cleanup uses your SAVED whitelist (Plugin.Config), not unsaved edits above. Click Save first if you want to apply your current edits.</value>
|
||||
</data>
|
||||
<data name="Cleanup_RefreshPreview" xml:space="preserve">
|
||||
<value>Refresh preview</value>
|
||||
</data>
|
||||
<data name="Cleanup_NoPreview" xml:space="preserve">
|
||||
<value>No preview yet. Click Refresh to compute the impact.</value>
|
||||
</data>
|
||||
<data name="Cleanup_TotalStored" xml:space="preserve">
|
||||
<value>Total stored messages: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_WillKeep" xml:space="preserve">
|
||||
<value>Will keep: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_WillDelete" xml:space="preserve">
|
||||
<value>Will delete: {0:N0}</value>
|
||||
</data>
|
||||
<data name="Cleanup_Breakdown" xml:space="preserve">
|
||||
<value>Per-channel breakdown</value>
|
||||
</data>
|
||||
<data name="Cleanup_Marker_Keep" xml:space="preserve">
|
||||
<value>[KEEP] </value>
|
||||
</data>
|
||||
<data name="Cleanup_Marker_Delete" xml:space="preserve">
|
||||
<value>[DELETE]</value>
|
||||
</data>
|
||||
<data name="Cleanup_Apply_Label" xml:space="preserve">
|
||||
<value>Apply current filter to database</value>
|
||||
</data>
|
||||
<data name="Cleanup_Apply_Tooltip" xml:space="preserve">
|
||||
<value>Ctrl+Shift: Hard-deletes {0:N0} messages, then runs VACUUM. Cannot be undone.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Running" xml:space="preserve">
|
||||
<value>Cleanup running in background…</value>
|
||||
</data>
|
||||
<data name="Cleanup_PreviewError" xml:space="preserve">
|
||||
<value>Failed to compute cleanup preview, see /xllog</value>
|
||||
</data>
|
||||
<data name="Cleanup_Success" xml:space="preserve">
|
||||
<value>Privacy cleanup complete: {0:N0} messages removed.</value>
|
||||
</data>
|
||||
<data name="Cleanup_Error" xml:space="preserve">
|
||||
<value>Privacy cleanup failed, see /xllog</value>
|
||||
</data>
|
||||
<data name="Retention_Heading" xml:space="preserve">
|
||||
<value>Message retention</value>
|
||||
</data>
|
||||
<data name="Retention_Enabled_Name" xml:space="preserve">
|
||||
<value>Auto-delete messages after a per-channel retention window</value>
|
||||
</data>
|
||||
<data name="Retention_Enabled_Description" xml:space="preserve">
|
||||
<value>When enabled, messages older than the configured window are deleted on every plugin start (at most once per 24 hours). Off by default — the plugin never deletes history without your explicit consent.</value>
|
||||
</data>
|
||||
<data name="Retention_Default_Label" xml:space="preserve">
|
||||
<value>Default retention (days, 0 = never)</value>
|
||||
</data>
|
||||
<data name="Retention_Default_Help" xml:space="preserve">
|
||||
<value>Applies to channels without an explicit override below.</value>
|
||||
</data>
|
||||
<data name="Retention_Reset_Spec" xml:space="preserve">
|
||||
<value>Reset overrides to spec defaults</value>
|
||||
</data>
|
||||
<data name="Retention_Clear_Overrides" xml:space="preserve">
|
||||
<value>Clear all overrides</value>
|
||||
</data>
|
||||
<data name="Retention_Tree_Heading" xml:space="preserve">
|
||||
<value>Per-channel retention overrides</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Override" xml:space="preserve">
|
||||
<value>[override]</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Spec" xml:space="preserve">
|
||||
<value>[spec]</value>
|
||||
</data>
|
||||
<data name="Retention_Tag_Global" xml:space="preserve">
|
||||
<value>[global]</value>
|
||||
</data>
|
||||
<data name="Retention_Reset_Button" xml:space="preserve">
|
||||
<value>reset</value>
|
||||
</data>
|
||||
<data name="Retention_Apply_Label" xml:space="preserve">
|
||||
<value>Apply retention policy now</value>
|
||||
</data>
|
||||
<data name="Retention_Apply_Tooltip" xml:space="preserve">
|
||||
<value>Ctrl+Shift: runs the retention sweep immediately using the SAVED policy. Save your changes first.</value>
|
||||
</data>
|
||||
<data name="Retention_Running" xml:space="preserve">
|
||||
<value>Retention sweep running in background…</value>
|
||||
</data>
|
||||
<data name="Retention_LastRun_Never" xml:space="preserve">
|
||||
<value>Last run: never</value>
|
||||
</data>
|
||||
<data name="Retention_LastRun_At" xml:space="preserve">
|
||||
<value>Last run: {0:yyyy-MM-dd HH:mm}</value>
|
||||
</data>
|
||||
<data name="Retention_Success" xml:space="preserve">
|
||||
<value>Retention sweep complete: {0:N0} messages removed.</value>
|
||||
</data>
|
||||
<data name="Retention_Error" xml:space="preserve">
|
||||
<value>Retention sweep failed, see /xllog</value>
|
||||
</data>
|
||||
<data name="Migration_Notification_Title" xml:space="preserve">
|
||||
<value>Hellion Chat</value>
|
||||
</data>
|
||||
<data name="Migration_Notification_Content" xml:space="preserve">
|
||||
<value>Privacy filter activated by default. Settings → Privacy to adjust.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,5 +1,6 @@
|
||||
using ChatTwo.Code;
|
||||
using ChatTwo.Privacy;
|
||||
using ChatTwo.Resources;
|
||||
using ChatTwo.Util;
|
||||
using Dalamud.Interface.ImGuiNotification;
|
||||
using Dalamud.Interface.Utility.Raii;
|
||||
@@ -12,7 +13,7 @@ internal sealed class Privacy : ISettingsTab
|
||||
private Plugin Plugin { get; }
|
||||
private Configuration Mutable { get; }
|
||||
|
||||
public string Name => "Privacy###tabs-privacy";
|
||||
public string Name => HellionStrings.Privacy_Tab_Title + "###tabs-privacy";
|
||||
|
||||
internal Privacy(Plugin plugin, Configuration mutable)
|
||||
{
|
||||
@@ -20,26 +21,27 @@ internal sealed class Privacy : ISettingsTab
|
||||
Mutable = mutable;
|
||||
}
|
||||
|
||||
// Channels grouped for the UI. Order = display order.
|
||||
private static readonly (string Heading, ChatType[] Types)[] Groups =
|
||||
// (HeadingKey lookup, ChatType list). Heading is resolved per-frame so
|
||||
// a runtime LanguageChanged call updates the labels immediately.
|
||||
private static readonly (Func<string> Heading, ChatType[] Types)[] Groups =
|
||||
[
|
||||
("Direct Messages", [ChatType.TellIncoming, ChatType.TellOutgoing]),
|
||||
("Party & Alliance", [ChatType.Party, ChatType.CrossParty, ChatType.Alliance, ChatType.PvpTeam]),
|
||||
("Free Company", [ChatType.FreeCompany, ChatType.FreeCompanyAnnouncement, ChatType.FreeCompanyLoginLogout]),
|
||||
("Linkshells", [
|
||||
(() => HellionStrings.Privacy_Group_DirectMessages, [ChatType.TellIncoming, ChatType.TellOutgoing]),
|
||||
(() => HellionStrings.Privacy_Group_PartyAlliance, [ChatType.Party, ChatType.CrossParty, ChatType.Alliance, ChatType.PvpTeam]),
|
||||
(() => HellionStrings.Privacy_Group_FreeCompany, [ChatType.FreeCompany, ChatType.FreeCompanyAnnouncement, ChatType.FreeCompanyLoginLogout]),
|
||||
(() => HellionStrings.Privacy_Group_Linkshells, [
|
||||
ChatType.Linkshell1, ChatType.Linkshell2, ChatType.Linkshell3, ChatType.Linkshell4,
|
||||
ChatType.Linkshell5, ChatType.Linkshell6, ChatType.Linkshell7, ChatType.Linkshell8,
|
||||
]),
|
||||
("Cross-World Linkshells", [
|
||||
(() => HellionStrings.Privacy_Group_CrossLinkshells, [
|
||||
ChatType.CrossLinkshell1, ChatType.CrossLinkshell2, ChatType.CrossLinkshell3, ChatType.CrossLinkshell4,
|
||||
ChatType.CrossLinkshell5, ChatType.CrossLinkshell6, ChatType.CrossLinkshell7, ChatType.CrossLinkshell8,
|
||||
]),
|
||||
("ExtraChat (Encrypted)", [
|
||||
(() => HellionStrings.Privacy_Group_ExtraChat, [
|
||||
ChatType.ExtraChatLinkshell1, ChatType.ExtraChatLinkshell2, ChatType.ExtraChatLinkshell3, ChatType.ExtraChatLinkshell4,
|
||||
ChatType.ExtraChatLinkshell5, ChatType.ExtraChatLinkshell6, ChatType.ExtraChatLinkshell7, ChatType.ExtraChatLinkshell8,
|
||||
]),
|
||||
("Public Chat (third-party data)", [ChatType.Say, ChatType.Shout, ChatType.Yell, ChatType.NoviceNetwork, ChatType.CustomEmote, ChatType.StandardEmote]),
|
||||
("System & Game Logs", [
|
||||
(() => HellionStrings.Privacy_Group_PublicChat, [ChatType.Say, ChatType.Shout, ChatType.Yell, ChatType.NoviceNetwork, ChatType.CustomEmote, ChatType.StandardEmote]),
|
||||
(() => HellionStrings.Privacy_Group_SystemLogs, [
|
||||
ChatType.System, ChatType.Notice, ChatType.Urgent, ChatType.Echo,
|
||||
ChatType.NpcDialogue, ChatType.NpcAnnouncement,
|
||||
ChatType.LootNotice, ChatType.LootRoll, ChatType.RetainerSale,
|
||||
@@ -47,9 +49,6 @@ internal sealed class Privacy : ISettingsTab
|
||||
]),
|
||||
];
|
||||
|
||||
// Cleanup preview state. Held in the tab so the user can refresh and
|
||||
// inspect before confirming. Resets when the tab is reopened (acceptable —
|
||||
// a stale preview against a freshly-edited whitelist would be misleading).
|
||||
private Dictionary<int, long>? CleanupCounts;
|
||||
private long CleanupKeepCount;
|
||||
private long CleanupDeleteCount;
|
||||
@@ -61,9 +60,8 @@ internal sealed class Privacy : ISettingsTab
|
||||
{
|
||||
ImGuiUtil.OptionCheckbox(
|
||||
ref Mutable.PrivacyFilterEnabled,
|
||||
"Enable privacy filter",
|
||||
"When enabled, only messages from whitelisted channels are persisted to the database. " +
|
||||
"Disabling restores upstream ChatTwo behavior (everything except battle messages is stored).");
|
||||
HellionStrings.Privacy_FilterEnabled_Name,
|
||||
HellionStrings.Privacy_FilterEnabled_Description);
|
||||
|
||||
ImGui.Spacing();
|
||||
ImGui.Separator();
|
||||
@@ -71,22 +69,19 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
using (ImRaii.Disabled(!Mutable.PrivacyFilterEnabled))
|
||||
{
|
||||
ImGuiUtil.HelpText(
|
||||
"Pick which channels are stored in the local database. " +
|
||||
"Privacy-First default: only your own conversations. " +
|
||||
"Use the buttons below to apply a preset.");
|
||||
ImGuiUtil.HelpText(HellionStrings.Privacy_Whitelist_Help);
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
if (ImGui.Button("Privacy-First (recommended)"))
|
||||
if (ImGui.Button(HellionStrings.Privacy_Preset_PrivacyFirst))
|
||||
Mutable.PrivacyPersistChannels = [..PrivacyDefaults.PrivacyFirstWhitelist];
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Clear all"))
|
||||
if (ImGui.Button(HellionStrings.Privacy_Preset_ClearAll))
|
||||
Mutable.PrivacyPersistChannels.Clear();
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Select all"))
|
||||
if (ImGui.Button(HellionStrings.Privacy_Preset_SelectAll))
|
||||
foreach (var group in Groups)
|
||||
foreach (var t in group.Types)
|
||||
Mutable.PrivacyPersistChannels.Add(t);
|
||||
@@ -97,7 +92,7 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
foreach (var (heading, types) in Groups)
|
||||
{
|
||||
using var tree = ImRaii.TreeNode(heading);
|
||||
using var tree = ImRaii.TreeNode(heading());
|
||||
if (!tree.Success)
|
||||
continue;
|
||||
|
||||
@@ -124,9 +119,8 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
ImGuiUtil.OptionCheckbox(
|
||||
ref Mutable.PrivacyPersistUnknownChannels,
|
||||
"Persist unknown channel types",
|
||||
"Failsafe for ChatTypes added by future FFXIV patches that this plugin does not yet know about. " +
|
||||
"Default OFF (Privacy-First). Turn ON if you want a complete log including future channels.");
|
||||
HellionStrings.Privacy_PersistUnknown_Name,
|
||||
HellionStrings.Privacy_PersistUnknown_Description);
|
||||
}
|
||||
|
||||
ImGui.Spacing();
|
||||
@@ -144,45 +138,44 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
private void DrawRetentionSection()
|
||||
{
|
||||
ImGui.TextUnformatted("Message retention");
|
||||
ImGui.TextUnformatted(HellionStrings.Retention_Heading);
|
||||
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
||||
{
|
||||
ImGuiUtil.OptionCheckbox(
|
||||
ref Mutable.RetentionEnabled,
|
||||
"Auto-delete messages after a per-channel retention window",
|
||||
"When enabled, messages older than the configured window are deleted on every plugin start (at most once per 24 hours). " +
|
||||
"Off by default — the plugin never deletes history without your explicit consent.");
|
||||
HellionStrings.Retention_Enabled_Name,
|
||||
HellionStrings.Retention_Enabled_Description);
|
||||
|
||||
using (ImRaii.Disabled(!Mutable.RetentionEnabled))
|
||||
{
|
||||
ImGui.Spacing();
|
||||
|
||||
var defaultDays = Mutable.RetentionDefaultDays;
|
||||
if (ImGui.InputInt("Default retention (days, 0 = never)", ref defaultDays))
|
||||
if (ImGui.InputInt(HellionStrings.Retention_Default_Label, ref defaultDays))
|
||||
Mutable.RetentionDefaultDays = Math.Max(0, defaultDays);
|
||||
ImGuiUtil.HelpText("Applies to channels without an explicit override below.");
|
||||
ImGuiUtil.HelpText(HellionStrings.Retention_Default_Help);
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
if (ImGui.Button("Reset overrides to spec defaults"))
|
||||
if (ImGui.Button(HellionStrings.Retention_Reset_Spec))
|
||||
{
|
||||
Mutable.RetentionPerChannelDays =
|
||||
PrivacyDefaults.DefaultRetentionDays.ToDictionary(p => p.Key, p => p.Value);
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Clear all overrides"))
|
||||
if (ImGui.Button(HellionStrings.Retention_Clear_Overrides))
|
||||
Mutable.RetentionPerChannelDays.Clear();
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
using (var tree = ImRaii.TreeNode("Per-channel retention overrides"))
|
||||
using (var tree = ImRaii.TreeNode(HellionStrings.Retention_Tree_Heading))
|
||||
{
|
||||
if (tree.Success)
|
||||
{
|
||||
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
||||
foreach (var (heading, types) in Groups)
|
||||
{
|
||||
using var subTree = ImRaii.TreeNode(heading);
|
||||
using var subTree = ImRaii.TreeNode(heading());
|
||||
if (!subTree.Success)
|
||||
continue;
|
||||
|
||||
@@ -195,10 +188,10 @@ internal sealed class Privacy : ISettingsTab
|
||||
days = hasSpecDefault ? specDays : Mutable.RetentionDefaultDays;
|
||||
|
||||
var tag = hasOverride
|
||||
? "[override]"
|
||||
? HellionStrings.Retention_Tag_Override
|
||||
: hasSpecDefault
|
||||
? "[spec]"
|
||||
: "[global]";
|
||||
? HellionStrings.Retention_Tag_Spec
|
||||
: HellionStrings.Retention_Tag_Global;
|
||||
if (ImGui.InputInt($"{type} {tag}##retention-{(int)type}", ref days))
|
||||
{
|
||||
days = Math.Max(0, days);
|
||||
@@ -208,7 +201,7 @@ internal sealed class Privacy : ISettingsTab
|
||||
if (hasOverride)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button($"reset##retention-reset-{(int)type}"))
|
||||
if (ImGui.Button($"{HellionStrings.Retention_Reset_Button}##retention-reset-{(int)type}"))
|
||||
Mutable.RetentionPerChannelDays.Remove(type);
|
||||
}
|
||||
}
|
||||
@@ -220,19 +213,18 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
using (ImRaii.Disabled(RetentionRunning))
|
||||
{
|
||||
if (ImGuiUtil.CtrlShiftButton("Apply retention policy now",
|
||||
"Ctrl+Shift: runs the retention sweep immediately using the SAVED policy. Save your changes first."))
|
||||
if (ImGuiUtil.CtrlShiftButton(HellionStrings.Retention_Apply_Label, HellionStrings.Retention_Apply_Tooltip))
|
||||
StartRetentionRun();
|
||||
}
|
||||
|
||||
if (RetentionRunning)
|
||||
ImGuiUtil.HelpText("Retention sweep running in background…");
|
||||
ImGuiUtil.HelpText(HellionStrings.Retention_Running);
|
||||
|
||||
ImGui.Spacing();
|
||||
var lastRun = Plugin.Config.RetentionLastRunAt;
|
||||
ImGuiUtil.HelpText(lastRun == DateTimeOffset.MinValue
|
||||
? "Last run: never"
|
||||
: $"Last run: {lastRun.ToLocalTime():yyyy-MM-dd HH:mm}");
|
||||
? HellionStrings.Retention_LastRun_Never
|
||||
: string.Format(HellionStrings.Retention_LastRun_At, lastRun.ToLocalTime()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,12 +257,12 @@ internal sealed class Privacy : ISettingsTab
|
||||
}).Wait();
|
||||
}
|
||||
|
||||
WrapperUtil.AddNotification($"Retention sweep complete: {deleted:N0} messages removed.", NotificationType.Success);
|
||||
WrapperUtil.AddNotification(string.Format(HellionStrings.Retention_Success, deleted), NotificationType.Success);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.Error(e, "Manual retention run failed");
|
||||
WrapperUtil.AddNotification("Retention sweep failed, see /xllog", NotificationType.Error);
|
||||
WrapperUtil.AddNotification(HellionStrings.Retention_Error, NotificationType.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -281,37 +273,32 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
private void DrawCleanupSection()
|
||||
{
|
||||
ImGui.TextUnformatted("Apply filter to existing database");
|
||||
ImGui.TextUnformatted(HellionStrings.Cleanup_Heading);
|
||||
using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false))
|
||||
{
|
||||
ImGuiUtil.HelpText(
|
||||
"The privacy filter only applies to new messages. " +
|
||||
"Use the cleanup below to retroactively remove already-stored messages " +
|
||||
"that don't match your saved whitelist.");
|
||||
ImGuiUtil.HelpText(
|
||||
"Cleanup uses your SAVED whitelist (Plugin.Config), not unsaved edits above. " +
|
||||
"Click Save first if you want to apply your current edits.");
|
||||
ImGuiUtil.HelpText(HellionStrings.Cleanup_Help_Intro);
|
||||
ImGuiUtil.HelpText(HellionStrings.Cleanup_Help_SavedNote);
|
||||
|
||||
ImGui.Spacing();
|
||||
|
||||
using (ImRaii.Disabled(CleanupRunning))
|
||||
{
|
||||
if (ImGui.Button("Refresh preview"))
|
||||
if (ImGui.Button(HellionStrings.Cleanup_RefreshPreview))
|
||||
RefreshCleanupPreview();
|
||||
}
|
||||
|
||||
if (CleanupCounts is null)
|
||||
{
|
||||
ImGuiUtil.HelpText("No preview yet. Click Refresh to compute the impact.");
|
||||
ImGuiUtil.HelpText(HellionStrings.Cleanup_NoPreview);
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.Spacing();
|
||||
ImGuiUtil.HelpText($"Total stored messages: {CleanupKeepCount + CleanupDeleteCount:N0}");
|
||||
ImGuiUtil.HelpText($"Will keep: {CleanupKeepCount:N0}");
|
||||
ImGuiUtil.HelpText($"Will delete: {CleanupDeleteCount:N0}");
|
||||
ImGuiUtil.HelpText(string.Format(HellionStrings.Cleanup_TotalStored, CleanupKeepCount + CleanupDeleteCount));
|
||||
ImGuiUtil.HelpText(string.Format(HellionStrings.Cleanup_WillKeep, CleanupKeepCount));
|
||||
ImGuiUtil.HelpText(string.Format(HellionStrings.Cleanup_WillDelete, CleanupDeleteCount));
|
||||
|
||||
using (var tree = ImRaii.TreeNode("Per-channel breakdown"))
|
||||
using (var tree = ImRaii.TreeNode(HellionStrings.Cleanup_Breakdown))
|
||||
{
|
||||
if (tree.Success)
|
||||
{
|
||||
@@ -322,7 +309,7 @@ internal sealed class Privacy : ISettingsTab
|
||||
? ((ChatType)(ushort)chatType).ToString()
|
||||
: $"Unknown({chatType})";
|
||||
var keeps = WouldBeKept(chatType);
|
||||
var marker = keeps ? "[KEEP] " : "[DELETE]";
|
||||
var marker = keeps ? HellionStrings.Cleanup_Marker_Keep : HellionStrings.Cleanup_Marker_Delete;
|
||||
ImGuiUtil.HelpText($"{marker} {name} — {count:N0}");
|
||||
}
|
||||
}
|
||||
@@ -332,13 +319,13 @@ internal sealed class Privacy : ISettingsTab
|
||||
|
||||
using (ImRaii.Disabled(CleanupRunning || CleanupDeleteCount == 0))
|
||||
{
|
||||
if (ImGuiUtil.CtrlShiftButton("Apply current filter to database",
|
||||
$"Ctrl+Shift: Hard-deletes {CleanupDeleteCount:N0} messages, then runs VACUUM. Cannot be undone."))
|
||||
if (ImGuiUtil.CtrlShiftButton(HellionStrings.Cleanup_Apply_Label,
|
||||
string.Format(HellionStrings.Cleanup_Apply_Tooltip, CleanupDeleteCount)))
|
||||
StartCleanup();
|
||||
}
|
||||
|
||||
if (CleanupRunning)
|
||||
ImGuiUtil.HelpText("Cleanup running in background…");
|
||||
ImGuiUtil.HelpText(HellionStrings.Cleanup_Running);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +356,7 @@ internal sealed class Privacy : ISettingsTab
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.Error(e, "Failed to compute cleanup preview");
|
||||
WrapperUtil.AddNotification("Failed to compute cleanup preview, see /xllog", NotificationType.Error);
|
||||
WrapperUtil.AddNotification(HellionStrings.Cleanup_PreviewError, NotificationType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,12 +381,12 @@ internal sealed class Privacy : ISettingsTab
|
||||
Plugin.MessageManager.FilterAllTabsAsync();
|
||||
}).Wait();
|
||||
|
||||
WrapperUtil.AddNotification($"Privacy cleanup complete: {deleted:N0} messages removed.", NotificationType.Success);
|
||||
WrapperUtil.AddNotification(string.Format(HellionStrings.Cleanup_Success, deleted), NotificationType.Success);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Plugin.Log.Error(e, "Privacy cleanup failed");
|
||||
WrapperUtil.AddNotification("Privacy cleanup failed, see /xllog", NotificationType.Error);
|
||||
WrapperUtil.AddNotification(HellionStrings.Cleanup_Error, NotificationType.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user