diff --git a/packages/app/src/composer/attachments/attachments.ts b/packages/app/src/composer/attachments/attachments.ts index 4fa2a7a3ab4..450dff48a4d 100644 --- a/packages/app/src/composer/attachments/attachments.ts +++ b/packages/app/src/composer/attachments/attachments.ts @@ -201,12 +201,15 @@ export function createComposerAttachments( cancel(id: string) { uploads.items().find((item) => item.id === id)?.cancel() }, - pick(fallback: () => void) { + pick(fallback: () => void, done: () => void) { if (!input.picker) { fallback() return } - void input.picker({ defaultPath: input.directory(), multiple: true }, (file) => add(file)).catch(input.onError) + void input + .picker({ defaultPath: input.directory(), multiple: true }, (file) => add(file)) + .then(done) + .catch(input.onError) }, } } diff --git a/packages/app/src/composer/editor/editor.tsx b/packages/app/src/composer/editor/editor.tsx index b7b563bdec3..5a02e4fe196 100644 --- a/packages/app/src/composer/editor/editor.tsx +++ b/packages/app/src/composer/editor/editor.tsx @@ -1,4 +1,15 @@ -import { createEffect, createMemo, createResource, createSignal, For, onCleanup, onMount, Show, type JSX } from "solid-js" +import { + createEffect, + createMemo, + createResource, + createSignal, + For, + onCleanup, + onMount, + Show, + Suspense, + type JSX, +} from "solid-js" import { createStore } from "solid-js/store" import { FileIcon } from "@opencode/ui/file-icon" import { Icon } from "@opencode/ui/icon" @@ -551,12 +562,15 @@ export function ComposerAttachments(props: { const [url] = createResource(() => image().blob, resolveBlobUrl) return ( <> - {attachment.filename} props.onAttachmentClick?.(attachment)} - /> + {/* Keep loading local; the route boundary would detach the screen and drop editor focus. */} + }> + {attachment.filename} props.onAttachmentClick?.(attachment)} + /> +
) diff --git a/packages/app/src/composer/editor/interaction.ts b/packages/app/src/composer/editor/interaction.ts index a332e3ea035..44167081896 100644 --- a/packages/app/src/composer/editor/interaction.ts +++ b/packages/app/src/composer/editor/interaction.ts @@ -102,7 +102,11 @@ export function createComposerEditor(input: { input.view.add?.onAttach() return } - attachments.pick(() => fileInput?.click()) + // The add menu leaves focus on its trigger, so return it to the editor once files are picked. + attachments.pick( + () => fileInput?.click(), + () => restoreFocus(), + ) } const contextList = useFilteredList({ items: async (query) => { @@ -449,7 +453,9 @@ export function createComposerEditor(input: { fileInput = element }, addAttachments(files: File[]) { - if (attachments) void attachments.addAttachments(files) + if (!attachments) return + void attachments.addAttachments(files) + restoreFocus() }, setQuery(value: string) { dispatch({ type: "popover.query", value })