Add storage search foundation

This commit is contained in:
2026-07-12 13:00:12 -05:00
parent 8aafd3061b
commit a1a902c938
10 changed files with 239 additions and 37 deletions
+17 -31
View File
@@ -1,4 +1,5 @@
import { invoke } from '@tauri-apps/api/core'
import { buildVerseSearchIndex } from './searchIndex'
import type {
CommentaryEntry,
DictionaryEntry,
@@ -110,7 +111,6 @@ type BrowserLexiconEntry = {
type BrowserStrongData = {
linksByVerse: Map<string, StrongLink[]>
verseIdsByStrong: Map<string, Set<string>>
}
let browserCatalogCache: Promise<ImportedCatalog> | null = null
@@ -120,6 +120,7 @@ const browserFootnotesCache = new Map<string, Promise<Map<string, Footnote[]>>>(
const browserStudyNotesCache = new Map<string, Promise<Map<string, Footnote[]>>>()
const browserChapterFootnotesCache = new Map<string, Promise<Map<string, Footnote[]>>>()
const browserChapterStudyNotesCache = new Map<string, Promise<Map<string, Footnote[]>>>()
const browserSearchIndexCache = new Map<string, Promise<ReturnType<typeof buildVerseSearchIndex>>>()
let browserCommentaryCache: Promise<Map<string, CommentaryEntry[]>> | null = null
let browserDictionaryCache: Promise<Map<string, DictionaryEntry>> | null = null
const browserVerseSourceIds = new Map<number, string>()
@@ -359,30 +360,8 @@ export async function searchVerses(query: string, translationId = defaultTransla
return invoke<Verse[]>('search_verses', { query })
}
const trimmed = query.trim().toLowerCase()
const verses = await loadBrowserVersesForTranslation(translationId)
if (!trimmed) return verses
if (trimmed.startsWith('tag:')) {
const label = trimmed.slice(4)
return verses.filter((verse) =>
verse.tags.some((tag) => tag.label.toLowerCase() === label),
)
}
if (/^[gh]\d+$/.test(trimmed)) {
const strongData = await loadBrowserStrongData(translationId)
const matchingVerseIds = strongData.verseIdsByStrong.get(trimmed.toUpperCase()) ?? new Set()
return verses.filter((verse) =>
matchingVerseIds.has(browserVerseKey(verse)),
)
}
return verses.filter((verse) =>
`${verse.book} ${verse.chapter}:${verse.verse} ${verse.text}`
.toLowerCase()
.includes(trimmed),
)
const searchIndex = await loadBrowserSearchIndex(translationId)
return searchIndex.search(query)
}
export async function addTagToVerse(
@@ -401,6 +380,7 @@ export async function addTagToVerse(
const tag = existing ?? { id: Date.now(), label, color }
tagsByVerse[verseId] = existing ? current : [...current, tag]
writeBrowserTags(tagsByVerse)
browserSearchIndexCache.delete(translationId)
const verse = (await loadBrowserVersesForTranslation(translationId)).find((item) => item.id === verseId)
if (!verse) throw new Error(`Verse ${verseId} was not found.`)
@@ -441,6 +421,17 @@ async function loadBrowserCatalog(): Promise<ImportedCatalog> {
return browserCatalogCache
}
async function loadBrowserSearchIndex(translationId = defaultTranslationId) {
if (!browserSearchIndexCache.has(translationId)) {
browserSearchIndexCache.set(
translationId,
loadBrowserVersesForTranslation(translationId).then((verses) => buildVerseSearchIndex(verses)),
)
}
return browserSearchIndexCache.get(translationId)!
}
async function loadLibreBibleDevVerses(translationId = defaultTranslationId): Promise<Verse[]> {
const importedVerses = await fetchJsonl<ImportedVerse>(
`${libreBibleDevRoot}/${translationId}/verses.jsonl`,
@@ -652,7 +643,6 @@ async function loadLibreBibleDevStrongData(translationId = defaultTranslationId)
]),
)
const linksByVerse = new Map<string, StrongLink[]>()
const verseIdsByStrong = new Map<string, Set<string>>()
for (const link of importedLinks) {
const entry = lexicon.get(link.strong)
@@ -668,17 +658,13 @@ async function loadLibreBibleDevStrongData(translationId = defaultTranslationId)
const current = linksByVerse.get(link.verse_id) ?? []
current.push(strongLink)
linksByVerse.set(link.verse_id, current)
const strongMatches = verseIdsByStrong.get(link.strong) ?? new Set<string>()
strongMatches.add(link.verse_id)
verseIdsByStrong.set(link.strong, strongMatches)
}
for (const links of linksByVerse.values()) {
links.sort((a, b) => a.position - b.position)
}
return { linksByVerse, verseIdsByStrong }
return { linksByVerse }
}
function strongLanguage(strong: string): 'Hebrew' | 'Greek' {