Browse Source

fix(app): only show files in select dialog when clicking + tab

adamelmore 1 month ago
parent
commit
213c0e18ab

+ 54 - 8
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",

+ 1 - 1
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>