From 607d2c7241510aeb2cef3f7566321d9104a94184 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 13 May 2026 22:08:32 +0200 Subject: [PATCH] feat(dbviewer): full-text-search toggle wired to FTS5 query API New UseFullTextSearch transient UI bool flips DbViewer.Filter() between the existing local page filter (default) and the FTS5 MATCH path across the whole database. ImRaii.Disabled blocks the toggle while the bulk-insert worker is still building the index; the HelpMarker swaps between two hints, one for the indexing state and one for the phrase-match advisory once the index is ready. Three new HellionStrings entries cover EN + DE + the Designer accessor: - DbViewer_FullTextToggle (label) - DbViewer_FullTextToggle_Hint_Indexing (tooltip while indexing) - DbViewer_FullTextToggle_Hint_PhraseMode (tooltip once ready, warns multi-word terms match as phrases and how to opt into raw MATCH syntax) Filter() short-circuits to the local fallback if the toggle is on but ftsReady has flipped back to false -- defensive against a mid-session Dispose-and-reopen during indexing. v1.4.8 H2 Sub-Task 4.4. --- .../Resources/HellionStrings.Designer.cs | 5 +++ HellionChat/Resources/HellionStrings.de.resx | 9 +++++ HellionChat/Resources/HellionStrings.resx | 9 +++++ HellionChat/Ui/DbViewer.cs | 38 +++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/HellionChat/Resources/HellionStrings.Designer.cs b/HellionChat/Resources/HellionStrings.Designer.cs index 2aaddc8..a9d7037 100644 --- a/HellionChat/Resources/HellionStrings.Designer.cs +++ b/HellionChat/Resources/HellionStrings.Designer.cs @@ -402,4 +402,9 @@ internal class HellionStrings // Hellion Chat — v1.3.0 Honorific title slot tooltip internal static string ChatHeader_HonorificTitle_Tooltip => Get(nameof(ChatHeader_HonorificTitle_Tooltip)); + + // Hellion Chat — v1.4.8 DbViewer full-text search toggle + internal static string DbViewer_FullTextToggle => Get(nameof(DbViewer_FullTextToggle)); + internal static string DbViewer_FullTextToggle_Hint_Indexing => Get(nameof(DbViewer_FullTextToggle_Hint_Indexing)); + internal static string DbViewer_FullTextToggle_Hint_PhraseMode => Get(nameof(DbViewer_FullTextToggle_Hint_PhraseMode)); } diff --git a/HellionChat/Resources/HellionStrings.de.resx b/HellionChat/Resources/HellionStrings.de.resx index e9fc2ff..59542f7 100644 --- a/HellionChat/Resources/HellionStrings.de.resx +++ b/HellionChat/Resources/HellionStrings.de.resx @@ -917,4 +917,13 @@ Custom-Titel von Honorific + + Volltext-Suche + + + Der Volltext-Index wird noch gebaut. Die lokale Suche bleibt verfügbar. + + + Sucht nach der exakten Wortfolge. Mehrere Wörter werden nur gefunden, wenn sie zusammen und in dieser Reihenfolge stehen. Wer rohe FTS5-MATCH-Syntax nutzen will, setzt eigene Anführungszeichen um den Suchbegriff. + diff --git a/HellionChat/Resources/HellionStrings.resx b/HellionChat/Resources/HellionStrings.resx index 8940f46..f0a13b0 100644 --- a/HellionChat/Resources/HellionStrings.resx +++ b/HellionChat/Resources/HellionStrings.resx @@ -917,4 +917,13 @@ Custom title from Honorific + + Full-text search + + + The full-text index is still being built. The local filter remains available. + + + Searches for the exact phrase. Multi-word queries match only when the words appear together in order. To use raw FTS5 MATCH syntax, wrap your term in double quotes yourself. + diff --git a/HellionChat/Ui/DbViewer.cs b/HellionChat/Ui/DbViewer.cs index 1326a29..6773fba 100644 --- a/HellionChat/Ui/DbViewer.cs +++ b/HellionChat/Ui/DbViewer.cs @@ -33,6 +33,12 @@ public class DbViewer : Window private int CurrentPage = 1; private string SimpleSearchTerm = ""; + + // v1.4.8 H2: opt-in full-text search across the whole DB via FTS5. + // Transient UI state (per-session), not persisted -- users opt in fresh + // every time so they always see the page-filter as the default mode. + private bool UseFullTextSearch; + private bool OnlyCurrentCharacter = true; private readonly Dictionary SelectedChannels; @@ -233,6 +239,24 @@ public class DbViewer : Window tooltipRight: Language.Page_ArrowRight_Tooltip ); + // Full-text search toggle (v1.4.8 H2). IsFtsIndexBuilt is a cached + // volatile bool in MessageStore -- single field read per frame, no + // SELECT count(*). ImRaii.Disabled blocks any click while the index + // is still being built, so no defensive force-off branch needed + // inside the if-body. UseFullTextSearch is transient UI state, so we + // do not call SaveConfig here. + var ftsReady = Plugin.MessageManager.Store.IsFtsIndexBuilt; + using (ImRaii.Disabled(!ftsReady)) + { + if (ImGui.Checkbox(HellionStrings.DbViewer_FullTextToggle, ref UseFullTextSearch)) + Filtered = Filter(Messages); + } + ImGuiUtil.HelpMarker( + ftsReady + ? HellionStrings.DbViewer_FullTextToggle_Hint_PhraseMode + : HellionStrings.DbViewer_FullTextToggle_Hint_Indexing + ); + ImGui.SameLine(ImGui.GetContentRegionMax().X - width); ImGui.SetNextItemWidth(width); if ( @@ -452,6 +476,20 @@ public class DbViewer : Window if (SimpleSearchTerm == "") return new ConcurrentStack(messages.Reverse().OrderByDescending(m => m.Date)); + // Full-text mode bypasses the page-bounded messages array and queries + // the FTS5 index across the whole DB. IsFtsIndexBuilt re-check guards + // against the (rare) case of the toggle being on while the index is + // mid-rebuild -- ImRaii.Disabled prevents the user from flipping it, + // but a Dispose-and-reopen during indexing could leave UseFullTextSearch + // true while ftsReady flipped back to false; the local fallback below + // still serves the page. + if (UseFullTextSearch && Plugin.MessageManager.Store.IsFtsIndexBuilt) + { + var hexIds = Plugin.MessageManager.Store.FullTextSearch(SimpleSearchTerm); + var resolved = Plugin.MessageManager.Store.LoadByGuids(hexIds); + return new ConcurrentStack(resolved.OrderByDescending(m => m.Date)); + } + return new ConcurrentStack( messages .Reverse()