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()