summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/app/src')
-rw-r--r--packages/app/src/components/dialog-select-file.tsx62
-rw-r--r--packages/app/src/pages/session.tsx2
2 files changed, 55 insertions, 9 deletions
diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx
index 8ba1ce618..83baa7a5e 100644
--- a/packages/app/src/components/dialog-select-file.tsx
+++ b/packages/app/src/components/dialog-select-file.tsx
@@ -24,13 +24,16 @@ type Entry = {
path?: string
}
-export function DialogSelectFile() {
+type DialogSelectFileMode = "all" | "files"
+
+export function DialogSelectFile(props: { mode?: DialogSelectFileMode }) {
const command = useCommand()
const language = useLanguage()
const layout = useLayout()
const file = useFile()
const dialog = useDialog()
const params = useParams()
+ const filesOnly = () => props.mode === "files"
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
const tabs = createMemo(() => layout.tabs(sessionKey))
const view = createMemo(() => layout.view(sessionKey))
@@ -46,11 +49,12 @@ export function DialogSelectFile() {
]
const limit = 5
- const allowed = createMemo(() =>
- command.options.filter(
+ const allowed = createMemo(() => {
+ if (filesOnly()) return []
+ return command.options.filter(
(option) => !option.disabled && !option.id.startsWith("suggested.") && option.id !== "file.open",
- ),
- )
+ )
+ })
const commandItem = (option: CommandOption): Entry => ({
id: "command:" + option.id,
@@ -99,10 +103,50 @@ export function DialogSelectFile() {
return items.slice(0, limit)
})
- const items = async (filter: string) => {
- const query = filter.trim()
+ const root = createMemo(() => {
+ const nodes = file.tree.children("")
+ const paths = nodes
+ .filter((node) => node.type === "file")
+ .map((node) => node.path)
+ .sort((a, b) => a.localeCompare(b))
+ return paths.slice(0, limit).map(fileItem)
+ })
+
+ const unique = (items: Entry[]) => {
+ const seen = new Set<string>()
+ const out: Entry[] = []
+ for (const item of items) {
+ if (seen.has(item.id)) continue
+ seen.add(item.id)
+ out.push(item)
+ }
+ return out
+ }
+
+ const items = async (text: string) => {
+ const query = text.trim()
setGrouped(query.length > 0)
+
+ if (!query && filesOnly()) {
+ const loaded = file.tree.state("")?.loaded
+ const pending = loaded ? Promise.resolve() : file.tree.list("")
+ const next = unique([...recent(), ...root()])
+
+ if (loaded || next.length > 0) {
+ void pending
+ return next
+ }
+
+ await pending
+ return unique([...recent(), ...root()])
+ }
+
if (!query) return [...picks(), ...recent()]
+
+ if (filesOnly()) {
+ const files = await file.searchFiles(query)
+ return files.map(fileItem)
+ }
const files = await file.searchFiles(query)
const entries = files.map(fileItem)
return [...list(), ...entries]
@@ -146,7 +190,9 @@ export function DialogSelectFile() {
<Dialog class="pt-3 pb-0 !max-h-[480px]" transition>
<List
search={{
- placeholder: language.t("palette.search.placeholder"),
+ placeholder: filesOnly()
+ ? language.t("session.header.searchFiles")
+ : language.t("palette.search.placeholder"),
autofocus: true,
hideIcon: true,
class: "pl-3 pr-2 !mb-0",
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index 9fcf68a87..871d3b753 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -2016,7 +2016,7 @@ export default function Page() {
icon="plus-small"
variant="ghost"
iconSize="large"
- onClick={() => dialog.show(() => <DialogSelectFile />)}
+ onClick={() => dialog.show(() => <DialogSelectFile mode="files" />)}
aria-label={language.t("command.file.open")}
/>
</TooltipKeybind>