Search query string.
Array of manga match results.
Array of matched results with scores.
export async function fuzzySearchManga(
query: string,
matches: MangaMatchResult[],
): Promise<MangaMatchResult[]> {
if (!query.trim()) {
return matches;
}
// Extract text tokens for fuzzy search
const tokens = parseQuerySyntax(query);
const textTokens = tokens.filter((t) => t.type === "text");
if (textTokens.length === 0) {
// Only field tokens, no fuzzy search needed
return matches;
}
// Combine text tokens for search
const searchQuery = textTokens.map((t) => t.value).join(" ");
// Use worker pool for large datasets (100+ items) to prevent UI blocking
// Small datasets use main thread for faster execution (less overhead)
if (matches.length >= 100) {
try {
const pool = getFuzzySearchWorkerPool();
await pool.initialize();
const result = await pool.search(
matches,
searchQuery,
[
{ name: "kenmeiManga.title", weight: 0.5 },
{ name: "selectedMatch.title.romaji", weight: 0.3 },
{ name: "selectedMatch.title.english", weight: 0.3 },
{ name: "selectedMatch.synonyms", weight: 0.1 },
],
{ useExtendedSearch: true },
100,
);
return result.results;
} catch (error) {
console.warn(
"[fuzzySearchManga] Worker pool search failed, falling back to main thread:",
error,
);
// Fall through to main thread implementation below
}
}
// Main thread implementation for small datasets
const fuse = createMangaFuseInstance(matches);
const results = fuse.search(searchQuery);
// Return top 100 results
return results.slice(0, 100).map((result) => result.item);
}
Performs fuzzy search on manga matches.
Returns top 100 results ordered by relevance score. Uses worker pool for large datasets (100+ items) to prevent UI blocking. Falls back to main thread for small datasets.