core: keep file @mentions responsive on first search
This commit is contained in:
parent
8379612c52
commit
0ca507fd00
3 changed files with 28 additions and 6 deletions
|
|
@ -573,14 +573,17 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||||
const seen = new Set(open)
|
const seen = new Set(open)
|
||||||
const pinned: AtOption[] = open.map((path) => ({ type: "file", path, display: path, recent: true }))
|
const pinned: AtOption[] = open.map((path) => ({ type: "file", path, display: path, recent: true }))
|
||||||
if (!query.trim()) return [...agents, ...pinned]
|
if (!query.trim()) return [...agents, ...pinned]
|
||||||
|
const pathy = /[./\\]/.test(query)
|
||||||
const paths = await files.searchFiles(query)
|
const paths = await files.searchFiles(query)
|
||||||
const fileOptions: AtOption[] = paths
|
const fileOptions: AtOption[] = paths
|
||||||
.filter((path) => !seen.has(path))
|
.filter((path) => !seen.has(path))
|
||||||
.map((path) => ({ type: "file", path, display: path }))
|
.map((path) => ({ type: "file", path, display: path }))
|
||||||
|
if (pathy) return fileOptions
|
||||||
return [...agents, ...pinned, ...fileOptions]
|
return [...agents, ...pinned, ...fileOptions]
|
||||||
},
|
},
|
||||||
key: atKey,
|
key: atKey,
|
||||||
filterKeys: ["display"],
|
filterKeys: ["display"],
|
||||||
|
stale: false,
|
||||||
groupBy: (item) => {
|
groupBy: (item) => {
|
||||||
if (item.type === "agent") return "agent"
|
if (item.type === "agent") return "agent"
|
||||||
if (item.recent) return "recent"
|
if (item.recent) return "recent"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { Instance } from "../project/instance"
|
||||||
import { Filesystem } from "../util/filesystem"
|
import { Filesystem } from "../util/filesystem"
|
||||||
import { Glob } from "../util/glob"
|
import { Glob } from "../util/glob"
|
||||||
import { Log } from "../util/log"
|
import { Log } from "../util/log"
|
||||||
|
import { Fff } from "./fff"
|
||||||
import { Protected } from "./protected"
|
import { Protected } from "./protected"
|
||||||
|
|
||||||
export namespace File {
|
export namespace File {
|
||||||
|
|
@ -660,15 +661,31 @@ export namespace File {
|
||||||
dirs?: boolean
|
dirs?: boolean
|
||||||
type?: "file" | "directory"
|
type?: "file" | "directory"
|
||||||
}) {
|
}) {
|
||||||
|
const query = input.query.trim()
|
||||||
|
const limit = input.limit ?? 100
|
||||||
|
const kind = input.type ?? (input.dirs === false ? "file" : "all")
|
||||||
|
log.info("search", { query, kind })
|
||||||
|
|
||||||
|
if (query && kind === "file") {
|
||||||
|
const fast = yield* Effect.promise(() =>
|
||||||
|
Fff.files({
|
||||||
|
cwd: Instance.directory,
|
||||||
|
query,
|
||||||
|
size: limit,
|
||||||
|
})
|
||||||
|
.then((out) => Array.from(new Set(out.items.map((item) => item.relativePath.replaceAll("\\", "/")))))
|
||||||
|
.catch(() => []),
|
||||||
|
)
|
||||||
|
if (fast.length) {
|
||||||
|
log.info("search", { query, kind, results: fast.length, mode: "fff" })
|
||||||
|
return fast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
yield* ensure()
|
yield* ensure()
|
||||||
const { cache } = yield* InstanceState.get(state)
|
const { cache } = yield* InstanceState.get(state)
|
||||||
|
|
||||||
return yield* Effect.promise(async () => {
|
return yield* Effect.promise(async () => {
|
||||||
const query = input.query.trim()
|
|
||||||
const limit = input.limit ?? 100
|
|
||||||
const kind = input.type ?? (input.dirs === false ? "file" : "all")
|
|
||||||
log.info("search", { query, kind })
|
|
||||||
|
|
||||||
const result = cache
|
const result = cache
|
||||||
const preferHidden = query.startsWith(".") || query.includes("/.")
|
const preferHidden = query.startsWith(".") || query.includes("/.")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export interface FilteredListProps<T> {
|
||||||
sortGroupsBy?: (a: { category: string; items: T[] }, b: { category: string; items: T[] }) => number
|
sortGroupsBy?: (a: { category: string; items: T[] }, b: { category: string; items: T[] }) => number
|
||||||
onSelect?: (value: T | undefined, index: number) => void
|
onSelect?: (value: T | undefined, index: number) => void
|
||||||
noInitialSelection?: boolean
|
noInitialSelection?: boolean
|
||||||
|
stale?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFilteredList<T>(props: FilteredListProps<T>) {
|
export function useFilteredList<T>(props: FilteredListProps<T>) {
|
||||||
|
|
@ -51,8 +52,9 @@ export function useFilteredList<T>(props: FilteredListProps<T>) {
|
||||||
)
|
)
|
||||||
|
|
||||||
const flat = createMemo(() => {
|
const flat = createMemo(() => {
|
||||||
|
const groups = props.stale === false && grouped.loading ? empty : grouped.latest || []
|
||||||
return pipe(
|
return pipe(
|
||||||
grouped.latest || [],
|
groups,
|
||||||
flatMap((x) => x.items),
|
flatMap((x) => x.items),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue