This commit replaces Fuse.js with Fzf for client-side thread searching
within the web application, offering potentially improved performance and
a different fuzzy matching algorithm.
Key changes include:
- Updated `package.json` to remove `fuse.js` and add `fzf`.
- Refactored `useThreads.ts` hook:
- Replaced Fuse.js instantiation and search logic with Fzf.
- Integrated a new `highlightFzfMatch` utility to return thread
titles with HTML highlighting for matched characters.
- Created `utils/highlight.ts` for the `highlightFzfMatch` function.
- Updated `ThreadList.tsx`:
- Renders highlighted thread titles using `dangerouslySetInnerHTML`.
- Ensures the rename functionality uses and edits a plain text
version of the title, stripping any highlight tags.
- Updated `index.css`:
- Modified the `.search-highlight` class to use `font-bold` and
`color-mix(in srgb, currentColor 80%, white 20%)` for a
subtly brighter text effect on highlighted matches, replacing
previous styling.
This provides a more robust search experience with clear visual feedback
for matched terms in the thread list.
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
// web-app/src/utils/highlight.ts
|
|
export function highlightFzfMatch(text: string, positions: number[], highlightClassName: string = "search-highlight") {
|
|
if (!text || !positions || !positions.length) return text;
|
|
|
|
const parts: { text: string; highlight: boolean }[] = [];
|
|
let lastIndex = 0;
|
|
|
|
// Sort positions to ensure we process them in order
|
|
const sortedPositions = [...positions].sort((a, b) => a - b);
|
|
|
|
sortedPositions.forEach((pos) => {
|
|
if (pos > lastIndex) {
|
|
parts.push({
|
|
text: text.substring(lastIndex, pos),
|
|
highlight: false
|
|
});
|
|
}
|
|
if (pos < text.length) { // Ensure pos is within bounds
|
|
parts.push({
|
|
text: text[pos],
|
|
highlight: true
|
|
});
|
|
}
|
|
lastIndex = pos + 1;
|
|
});
|
|
|
|
if (lastIndex < text.length) {
|
|
parts.push({
|
|
text: text.substring(lastIndex),
|
|
highlight: false
|
|
});
|
|
}
|
|
|
|
return parts
|
|
.map(part =>
|
|
part.highlight
|
|
? `<span class="${highlightClassName}">${part.text}</span>`
|
|
: part.text
|
|
)
|
|
.join('');
|
|
} |