From 47f66de8dda535de9f2e2c3bfdbeaad774ad6e82 Mon Sep 17 00:00:00 2001
From: Luke Parker <10430890+Hona@users.noreply.github.com>
Date: Fri, 18 Sep 2026 19:32:15 +1000
Subject: [PATCH] perf(app): load draft image bytes on demand (#49703)
---
packages/app/src/composer/editor/editor.tsx | 29 ++++---
packages/app/src/composer/model.ts | 5 +-
packages/app/src/composer/schema.test.ts | 8 +-
packages/app/src/composer/schema.ts | 7 +-
packages/app/src/composer/state.test.ts | 9 ++
packages/app/src/composer/submit.ts | 16 +++-
.../src/runtime/persistence/drafts.test.ts | 25 +++++-
.../app/src/runtime/persistence/drafts.ts | 25 +++++-
.../test-browser/draft-history-cache.test.ts | 83 ++++++++-----------
.../test-browser/prompt-persistence.test.ts | 18 ++--
10 files changed, 139 insertions(+), 86 deletions(-)
diff --git a/packages/app/src/composer/editor/editor.tsx b/packages/app/src/composer/editor/editor.tsx
index 51ad419a36a..b7b563bdec3 100644
--- a/packages/app/src/composer/editor/editor.tsx
+++ b/packages/app/src/composer/editor/editor.tsx
@@ -1,9 +1,10 @@
-import { createEffect, createMemo, createSignal, For, onCleanup, onMount, Show, type JSX } from "solid-js"
+import { createEffect, createMemo, createResource, createSignal, For, onCleanup, onMount, Show, type JSX } from "solid-js"
import { createStore } from "solid-js/store"
import { FileIcon } from "@opencode/ui/file-icon"
import { Icon } from "@opencode/ui/icon"
import { IconButton } from "@opencode/ui/icon-button"
import { createAnimatedPresence } from "@/runtime/animated-presence"
+import { resolveBlobUrl } from "@/runtime/persistence/drafts"
import { ProviderIcon } from "@opencode/ui/provider-icon"
import { useI18n } from "@opencode/ui/context/i18n"
import { Button } from "@opencode/ui/button"
@@ -545,17 +546,21 @@ export function ComposerAttachments(props: {
}
>
- {(image) => (
- <>
-
props.onAttachmentClick?.(attachment)}
- />
-
- >
- )}
+ {(image) => {
+ // Restored drafts and history carry image ids only; bytes load when shown.
+ const [url] = createResource(() => image().blob, resolveBlobUrl)
+ return (
+ <>
+
props.onAttachmentClick?.(attachment)}
+ />
+
+ >
+ )
+ }}