diff --git a/HellionChat/Ui/DbViewer.cs b/HellionChat/Ui/DbViewer.cs index 66eecb7..c033e9f 100644 --- a/HellionChat/Ui/DbViewer.cs +++ b/HellionChat/Ui/DbViewer.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Numerics; using System.Text; +using System.Threading; using Dalamud.Bindings.ImGui; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Interface; @@ -44,6 +45,10 @@ public class DbViewer : Window private bool IsProcessing; private long ProcessingStart = Environment.TickCount64; + + // Bumped per trigger so a late worker drops itself instead of overwriting + // a newer result. + private long _ftsFilterSeq; private (DateTime Min, DateTime Max, int Page, bool Local, int ChannelCount) LastProcessed; private string MinDateString = ""; @@ -249,7 +254,7 @@ public class DbViewer : Window using (ImRaii.Disabled(!ftsReady)) { if (ImGui.Checkbox(HellionStrings.DbViewer_FullTextToggle, ref UseFullTextSearch)) - Filtered = Filter(Messages); + TriggerFilterRefresh(); } ImGuiUtil.HelpMarker( ftsReady @@ -267,7 +272,7 @@ public class DbViewer : Window 30 ) ) - Filtered = Filter(Messages); + TriggerFilterRefresh(); // Third row @@ -471,6 +476,34 @@ public class DbViewer : Window } } + // FTS path hits SQLite per keystroke -- dispatch to a worker, drop stale + // results via _ftsFilterSeq. Page-filter path is in-memory LINQ, stays + // inline. + private void TriggerFilterRefresh() + { + if (!UseFullTextSearch || !Plugin.MessageManager.Store.IsFtsIndexBuilt) + { + Filtered = Filter(Messages); + return; + } + + var snapshot = Messages; + var mySeq = Interlocked.Increment(ref _ftsFilterSeq); + Task.Run(() => + { + try + { + var result = Filter(snapshot); + if (Interlocked.Read(ref _ftsFilterSeq) == mySeq) + Filtered = result; + } + catch (Exception ex) + { + Plugin.LogProxy.Error(ex, "FTS filter worker failed"); + } + }); + } + private ConcurrentStack Filter(Message[] messages) { if (SimpleSearchTerm == "")