diff --git a/apps/desktop/src/components/main/body/sessions/note-input/transcript/search-context.tsx b/apps/desktop/src/components/main/body/sessions/note-input/transcript/search-context.tsx index b2bdffff20..81fe7f6836 100644 --- a/apps/desktop/src/components/main/body/sessions/note-input/transcript/search-context.tsx +++ b/apps/desktop/src/components/main/body/sessions/note-input/transcript/search-context.tsx @@ -35,12 +35,21 @@ function getMatchingElements( return []; } + const queryTerms = query + .toLowerCase() + .split(/\s+/) + .filter((term) => term.length > 0); + + if (queryTerms.length === 0) { + return []; + } + const allSpans = Array.from( container.querySelectorAll("[data-word-id]"), ); return allSpans.filter((span) => { - const text = span.textContent || ""; - return text.toLowerCase().includes(query.toLowerCase()); + const text = (span.textContent || "").toLowerCase(); + return queryTerms.some((term) => text.includes(term)); }); } diff --git a/apps/desktop/src/components/main/body/sessions/note-input/transcript/shared/word-span.tsx b/apps/desktop/src/components/main/body/sessions/note-input/transcript/shared/word-span.tsx index c4a4329a56..e508bf0007 100644 --- a/apps/desktop/src/components/main/body/sessions/note-input/transcript/shared/word-span.tsx +++ b/apps/desktop/src/components/main/body/sessions/note-input/transcript/shared/word-span.tsx @@ -154,21 +154,52 @@ function useTranscriptSearchHighlights(word: SegmentWord) { function createSegments(text: string, query: string): HighlightSegment[] { const lowerText = text.toLowerCase(); - const lowerQuery = query.toLowerCase(); - const segments: HighlightSegment[] = []; + const queryTerms = query + .toLowerCase() + .split(/\s+/) + .filter((term) => term.length > 0); - let cursor = 0; - let index = lowerText.indexOf(lowerQuery, cursor); + if (queryTerms.length === 0) { + return [{ text, isMatch: false }]; + } + + const matches: Array<{ start: number; end: number }> = []; + + for (const term of queryTerms) { + let index = lowerText.indexOf(term); + while (index !== -1) { + matches.push({ start: index, end: index + term.length }); + index = lowerText.indexOf(term, index + 1); + } + } - while (index !== -1) { - if (index > cursor) { - segments.push({ text: text.slice(cursor, index), isMatch: false }); + if (matches.length === 0) { + return [{ text, isMatch: false }]; + } + + matches.sort((a, b) => a.start - b.start); + + const merged: Array<{ start: number; end: number }> = []; + for (const match of matches) { + if (merged.length === 0 || match.start > merged[merged.length - 1].end) { + merged.push({ ...match }); + } else { + merged[merged.length - 1].end = Math.max( + merged[merged.length - 1].end, + match.end, + ); } + } - const end = index + query.length; - segments.push({ text: text.slice(index, end), isMatch: true }); - cursor = end; - index = lowerText.indexOf(lowerQuery, cursor); + const segments: HighlightSegment[] = []; + let cursor = 0; + + for (const match of merged) { + if (match.start > cursor) { + segments.push({ text: text.slice(cursor, match.start), isMatch: false }); + } + segments.push({ text: text.slice(match.start, match.end), isMatch: true }); + cursor = match.end; } if (cursor < text.length) {