Add indexed history search across iOS and web
TestFlight / Build and upload (push) Successful in 1m55s
TestFlight / Build and upload (push) Successful in 1m55s
This commit is contained in:
+7
-1
@@ -33,7 +33,9 @@ export type SearchWorkspaceItem = SearchSummary & {
|
||||
type: "search";
|
||||
};
|
||||
|
||||
export type WorkspaceItem = ChatWorkspaceItem | SearchWorkspaceItem;
|
||||
export type WorkspaceItem = (ChatWorkspaceItem | SearchWorkspaceItem) & { searchSnippet?: string | null };
|
||||
|
||||
export type WorkspaceSearchResponse = { items: WorkspaceItem[]; hasMore: boolean };
|
||||
|
||||
export type Message = {
|
||||
id: string;
|
||||
@@ -272,6 +274,10 @@ export async function listWorkspaceItems() {
|
||||
return data.items;
|
||||
}
|
||||
|
||||
export function searchWorkspaceItems(query: string, signal?: AbortSignal) {
|
||||
return api<WorkspaceSearchResponse>(`/v1/workspace-items?${new URLSearchParams({ q: query })}`, { signal });
|
||||
}
|
||||
|
||||
export async function verifySession() {
|
||||
return api<{ authenticated: true; mode: "open" | "token" }>("/v1/auth/session");
|
||||
}
|
||||
|
||||
@@ -2,6 +2,16 @@ export type SidebarSelection = { kind: "chat" | "search"; id: string };
|
||||
|
||||
type WorkspaceSelectionItem = { type: SidebarSelection["kind"]; id: string };
|
||||
|
||||
export function retainSelectedHistoryItem<T extends WorkspaceSelectionItem>(
|
||||
items: T[], selection: SidebarSelection | null, retained: T | null
|
||||
): T[] {
|
||||
if (retained && selection?.kind === retained.type && selection.id === retained.id &&
|
||||
!items.some((item) => item.type === retained.type && item.id === retained.id)) {
|
||||
return [...items, retained];
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
type ResolveSidebarSelectionOptions = {
|
||||
initialSelection?: SidebarSelection;
|
||||
selectFallback?: boolean;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { WorkspaceSearchResponse } from "./api";
|
||||
|
||||
// Cleanup cancels both the debounce and fetch, and also rejects late responses
|
||||
// from transports that finish after cancellation.
|
||||
export function scheduleWorkspaceSearch(
|
||||
query: string,
|
||||
request: (query: string, signal: AbortSignal) => Promise<WorkspaceSearchResponse>,
|
||||
onResult: (result: WorkspaceSearchResponse) => void,
|
||||
onError: (error: unknown) => void
|
||||
) {
|
||||
const controller = new AbortController();
|
||||
const timer = setTimeout(async () => {
|
||||
try {
|
||||
const result = await request(query, controller.signal);
|
||||
if (!controller.signal.aborted) onResult(result);
|
||||
} catch (error) {
|
||||
if (!controller.signal.aborted) onError(error);
|
||||
}
|
||||
}, 300);
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
controller.abort();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user