fix: global search case-insensitive + keyboard layout swap
Unified search normalization across InternalLinkPicker and GlobalSearch: 1. GlobalSearch.svelte: multi-variant search (same as InternalLinkPicker) - expandKeyboardVariants() for RU/EN layout swap - Parallel Search queries with dedup by type+nodeId+targetId+title - 180ms debounce preserved 2. Backend: fix LOWER() in SQL for links/actions - Replace LOWER(column) LIKE with lowercased columns (title_lower, url_lower, etc.) - Migration 020: add lowercased columns + indexes for links and actions - BackfillLinksLower() + BackfillActionsLower() in storage.go - Update INSERT in bindings_links.go and action.go to populate lowercased columns 3. FTS5 search: Unicode case-insensitive - Index lowercased title/content/tags in search_index - sanitizeFTS() now lowercases query before MATCH - RebuildFTS() called after migrations 4. Case-insensitive search for nodes (already done in previous commit, verified): - title_lower column with Go strings.ToLower - Search() queries title_lower with lowercased query All test suites PASS, full build OK.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import { createEventDispatcher, onDestroy, onMount, tick } from 'svelte'
|
||||
import { t } from './i18n'
|
||||
import { expandKeyboardVariants } from './util/keyboardLayout'
|
||||
|
||||
export let wailsCall = async () => []
|
||||
export let typeLabel = (type) => type || ''
|
||||
@@ -42,9 +43,36 @@
|
||||
}
|
||||
loading = true
|
||||
try {
|
||||
results = await wailsCall('Search', q) || []
|
||||
// Build query variants: original + keyboard-swapped + lowercased
|
||||
const variants = expandKeyboardVariants(q)
|
||||
// Deduplicate preserving order
|
||||
const seenVariants = new Set()
|
||||
const queries = []
|
||||
for (const v of variants) {
|
||||
if (!seenVariants.has(v)) {
|
||||
seenVariants.add(v)
|
||||
queries.push(v)
|
||||
}
|
||||
}
|
||||
// Execute all variant queries in parallel, collect results
|
||||
const allResults = await Promise.all(
|
||||
queries.map(v => wailsCall('Search', v).catch(() => []))
|
||||
)
|
||||
// Merge and deduplicate by node ID (or type+title for links/actions)
|
||||
const merged = new Map()
|
||||
// First pass: results from the original query get priority
|
||||
for (let qi = 0; qi < allResults.length; qi++) {
|
||||
const arr = allResults[qi] || []
|
||||
for (const r of arr) {
|
||||
const key = r.type + ':' + r.nodeId + ':' + (r.targetId || '') + ':' + r.title
|
||||
if (!merged.has(key)) {
|
||||
merged.set(key, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
results = Array.from(merged.values())
|
||||
selectedIndex = 0
|
||||
open = true
|
||||
open = results.length > 0
|
||||
} catch (e) {
|
||||
results = []
|
||||
open = false
|
||||
|
||||
Reference in New Issue
Block a user