refactor(command-palette): return items array directly from source hooks

This commit is contained in:
simosmik
2026-04-30 08:16:42 +00:00
parent 3a264d5109
commit 99495ff9ce
3 changed files with 8 additions and 24 deletions

View File

@@ -95,11 +95,11 @@ export default function CommandPalette({
const showFiles = mode === 'mixed' || mode === 'files'; const showFiles = mode === 'mixed' || mode === 'files';
const showCommits = mode === 'mixed' || mode === 'commits'; const showCommits = mode === 'mixed' || mode === 'commits';
const { items: sessions } = useSessionsSource(projectId, open && showSessions); const sessions = useSessionsSource(projectId, open && showSessions);
const { items: messageMatches } = useSessionMessageSearch(projectId, query, open && showSessions); const messageMatches = useSessionMessageSearch(projectId, query, open && showSessions);
const { items: files } = useFilesSource(projectId, open && showFiles); const files = useFilesSource(projectId, open && showFiles);
const { items: commits } = useCommitsSource(projectId, open && showCommits); const commits = useCommitsSource(projectId, open && showCommits);
const { items: branches } = useBranchesSource(projectId, open && showActions); const branches = useBranchesSource(projectId, open && showActions);
const git = useGitActions(projectId); const git = useGitActions(projectId);
const sessionRows = React.useMemo(() => { const sessionRows = React.useMemo(() => {

View File

@@ -1,33 +1,21 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
export type ApiSourceState<T> = {
items: T[];
isLoading: boolean;
error: Error | null;
};
export function useApiSource<T, R = unknown>(opts: { export function useApiSource<T, R = unknown>(opts: {
enabled: boolean; enabled: boolean;
deps: React.DependencyList; deps: React.DependencyList;
fetcher: (signal: AbortSignal) => Promise<Response>; fetcher: (signal: AbortSignal) => Promise<Response>;
parse: (raw: R) => T[]; parse: (raw: R) => T[];
}): ApiSourceState<T> { }): T[] {
const [items, setItems] = useState<T[]>([]); const [items, setItems] = useState<T[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const { enabled, deps, fetcher, parse } = opts; const { enabled, deps, fetcher, parse } = opts;
useEffect(() => { useEffect(() => {
if (!enabled) { if (!enabled) {
setItems([]); setItems([]);
setError(null);
return; return;
} }
const controller = new AbortController(); const controller = new AbortController();
setIsLoading(true);
setError(null);
fetcher(controller.signal) fetcher(controller.signal)
.then((r) => r.json() as Promise<R>) .then((r) => r.json() as Promise<R>)
@@ -39,15 +27,11 @@ export function useApiSource<T, R = unknown>(opts: {
if (controller.signal.aborted) return; if (controller.signal.aborted) return;
if (err instanceof DOMException && err.name === 'AbortError') return; if (err instanceof DOMException && err.name === 'AbortError') return;
setItems([]); setItems([]);
setError(err instanceof Error ? err : new Error(String(err)));
})
.finally(() => {
if (!controller.signal.aborted) setIsLoading(false);
}); });
return () => controller.abort(); return () => controller.abort();
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [enabled, ...deps]); }, [enabled, ...deps]);
return { items, isLoading, error }; return items;
} }

View File

@@ -94,5 +94,5 @@ export function useSessionMessageSearch(
}; };
}, []); }, []);
return { items }; return items;
} }