diff --git a/ChatTwo/Resources/HellionStrings.Designer.cs b/ChatTwo/Resources/HellionStrings.Designer.cs index 671109f..61ead5b 100644 --- a/ChatTwo/Resources/HellionStrings.Designer.cs +++ b/ChatTwo/Resources/HellionStrings.Designer.cs @@ -64,6 +64,7 @@ internal class HellionStrings 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_Preview_Stale => Get(nameof(Cleanup_Preview_Stale)); internal static string Retention_Help_SavedNote => Get(nameof(Retention_Help_SavedNote)); internal static string Cleanup_RefreshPreview => Get(nameof(Cleanup_RefreshPreview)); internal static string Cleanup_NoPreview => Get(nameof(Cleanup_NoPreview)); diff --git a/ChatTwo/Resources/HellionStrings.de.resx b/ChatTwo/Resources/HellionStrings.de.resx index d82ef5a..2a586ae 100644 --- a/ChatTwo/Resources/HellionStrings.de.resx +++ b/ChatTwo/Resources/HellionStrings.de.resx @@ -81,6 +81,9 @@ Der manuelle Lauf nutzt deine GESPEICHERTE Retention-Policy, nicht die Slider-Werte oben. Klicke zuerst Speichern, wenn der Lauf deine aktuellen Änderungen anwenden soll. + + Vorschau veraltet, deine Whitelist hat sich seit dem letzten Aktualisieren geändert. Klicke Aktualisieren, um neu zu berechnen. + Vorschau aktualisieren diff --git a/ChatTwo/Resources/HellionStrings.resx b/ChatTwo/Resources/HellionStrings.resx index 6617440..817c3c7 100644 --- a/ChatTwo/Resources/HellionStrings.resx +++ b/ChatTwo/Resources/HellionStrings.resx @@ -81,6 +81,9 @@ The manual sweep uses your SAVED retention policy, not the slider values above. Click Save first if you want the run to apply your current edits. + + Preview is out of date — your whitelist has changed since the last refresh. Click Refresh to recalculate. + Refresh preview diff --git a/ChatTwo/Ui/SettingsTabs/Privacy.cs b/ChatTwo/Ui/SettingsTabs/Privacy.cs index eb3bea3..6126230 100644 --- a/ChatTwo/Ui/SettingsTabs/Privacy.cs +++ b/ChatTwo/Ui/SettingsTabs/Privacy.cs @@ -3,6 +3,7 @@ using ChatTwo.Export; using ChatTwo.Privacy; using ChatTwo.Resources; using ChatTwo.Util; +using Dalamud.Interface.Colors; using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; @@ -55,6 +56,8 @@ internal sealed class Privacy : ISettingsTab private long CleanupKeepCount; private long CleanupDeleteCount; private bool CleanupRunning; + private bool CleanupPreviewStale; + private HashSet? CleanupPreviewSnapshot; // The retention-running state lives on Plugin so the auto-sweep and // this manual button see the same flag. UI reads stay lock-free @@ -484,6 +487,21 @@ internal sealed class Privacy : ISettingsTab ImGui.Spacing(); + // Drift-detection between the snapshot taken at last refresh + // and the current Mutable whitelist. Cleanup itself runs on + // the SAVED policy (Cleanup_Help_SavedNote covers that), but + // the user usually expects "the preview reflects what I just + // ticked" — so we surface the divergence instead of silently + // showing stale numbers. + if (CleanupPreviewSnapshot is not null + && !CleanupPreviewSnapshot.SetEquals(Mutable.PrivacyPersistChannels)) + { + CleanupPreviewStale = true; + } + + using (var emphasis = CleanupPreviewStale + ? ImRaii.PushColor(ImGuiCol.Button, ImGuiColors.HealerGreen with { W = 0.6f }) + : null) using (ImRaii.Disabled(CleanupRunning)) { if (ImGui.Button(HellionStrings.Cleanup_RefreshPreview)) @@ -496,10 +514,22 @@ internal sealed class Privacy : ISettingsTab return; } + if (CleanupPreviewStale) + { + ImGui.Spacing(); + ImGuiUtil.HelpText(HellionStrings.Cleanup_Preview_Stale); + } + ImGui.Spacing(); - 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 staleColor = CleanupPreviewStale + ? ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey) + : null) + { + 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(HellionStrings.Cleanup_Breakdown)) { @@ -555,6 +585,13 @@ internal sealed class Privacy : ISettingsTab else CleanupDeleteCount += count; } + + // Snapshot the whitelist as it stood at preview-time so the + // render pass can flag the user about subsequent edits. Only + // updated on success — if the preview throws, the previous + // snapshot stays in place so stale-detection keeps working. + CleanupPreviewSnapshot = new HashSet(Mutable.PrivacyPersistChannels); + CleanupPreviewStale = false; } catch (Exception e) {