Files
Sybil-2/web/src/hooks/use-workspace-search.ts
T
buzzert dd6cd1ea7b
TestFlight / Build and upload (push) Successful in 1m55s
Add indexed history search across iOS and web
2026-10-07 22:05:49 -07:00

31 lines
1.5 KiB
TypeScript

import { useEffect, useState } from "preact/hooks";
import { searchWorkspaceItems, type WorkspaceItem, type WorkspaceSearchResponse } from "@/lib/api";
import { scheduleWorkspaceSearch } from "@/lib/workspace-search";
type SearchState = WorkspaceSearchResponse & { query: string; revision: number; error: string | null };
const EMPTY_ITEMS: WorkspaceItem[] = [];
export function useWorkspaceSearch(query: string, enabled: boolean, revision: number) {
const trimmed = query.trim();
const [state, setState] = useState<SearchState | null>(null);
const validationError = trimmed.length > 200 ? "Use 200 characters or fewer." : null;
useEffect(() => {
setState(null);
if (!enabled || !trimmed || validationError) return;
return scheduleWorkspaceSearch(trimmed, searchWorkspaceItems,
(result) => setState({ ...result, query: trimmed, revision, error: null }),
(error) => setState({ items: [], hasMore: false, query: trimmed, revision, error: error instanceof Error ? error.message : String(error) })
);
}, [trimmed, enabled, revision, validationError]);
// Hide obsolete results immediately, even before effect cleanup runs.
const current = enabled && state?.query === trimmed && state.revision === revision ? state : null;
return {
items: current?.items ?? EMPTY_ITEMS,
hasMore: current?.hasMore ?? false,
error: validationError ?? current?.error ?? null,
isLoading: enabled && Boolean(trimmed) && !validationError && !current,
};
}