fix: clear-search restores board and enable partial-match search
- useTasks debounced effect bailed when searchQuery transitioned back to undefined (App passes `searchQuery || undefined`), so clearing the input never refetched the unfiltered list. Track previous value via ref and only skip the initial mount. - FTS5 search used bare tokens (exact term match), so "frob" did not match "frobnicator". Append `*` to each token (and to quoted tokens) for prefix matching. LIKE fallback already did substring matching. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2489,12 +2489,14 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
if (this.db.fts5Available) {
|
||||
// For FTS5 MATCH, quote tokens that contain special characters like hyphens
|
||||
// to prevent them from being interpreted as operators
|
||||
// Append `*` to each token for FTS5 prefix matching so partial input
|
||||
// (e.g., "frob") matches indexed terms like "frobnicator".
|
||||
const ftsQuery = sanitizedTokens
|
||||
.map((token) => {
|
||||
if (/[":(){}*^+-]/.test(token)) {
|
||||
return `"${token.replace(/"/g, '\\"')}"`;
|
||||
return `"${token.replace(/"/g, '\\"')}"*`;
|
||||
}
|
||||
return token;
|
||||
return `${token}*`;
|
||||
})
|
||||
.join(" OR ");
|
||||
const whereClause = includeArchived ? "" : ` AND t."column" != 'archived'`;
|
||||
|
||||
@@ -161,8 +161,13 @@ export function useTasks(options?: UseTasksOptions) {
|
||||
}, []);
|
||||
|
||||
// Debounced search effect - separate from refreshTasks to avoid dependency cycle
|
||||
const prevSearchQueryRef = useRef<string | undefined>(searchQuery);
|
||||
useEffect(() => {
|
||||
if (searchQuery === undefined) return;
|
||||
// Skip only the initial mount when query has never been set; the visibility
|
||||
// effect handles the first fetch. Going from a defined value back to
|
||||
// undefined/"" must still trigger a refetch so the filter is cleared.
|
||||
if (searchQuery === undefined && prevSearchQueryRef.current === undefined) return;
|
||||
prevSearchQueryRef.current = searchQuery;
|
||||
const timer = setTimeout(() => {
|
||||
void refreshTasks({ searchQueryOverride: searchQuery });
|
||||
}, 300);
|
||||
|
||||
Reference in New Issue
Block a user