diff options
| author | shuv <[email protected]> | 2026-01-04 16:39:15 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-04 18:39:15 -0600 |
| commit | 52ad134d554bef8a4e017f7dc4c5002fcf12a785 (patch) | |
| tree | 0bf8b971f29d57fd4ff7c4fd04f604adda9d91ea /packages | |
| parent | 3e09abbfda931a91e31282cff0f6af64307f8d36 (diff) | |
| download | opencode-52ad134d554bef8a4e017f7dc4c5002fcf12a785.tar.gz opencode-52ad134d554bef8a4e017f7dc4c5002fcf12a785.zip | |
feat(app): add SVG preview support in session viewer (#6868)
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/app/src/pages/session.tsx | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 4011ea890..1aeb4757b 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -24,7 +24,7 @@ import { useSync } from "@/context/sync" import { useTerminal, type LocalPTY } from "@/context/terminal" import { useLayout } from "@/context/layout" import { Terminal } from "@/components/terminal" -import { checksum } from "@opencode-ai/util/encode" +import { checksum, base64Decode } from "@opencode-ai/util/encode" import { useDialog } from "@opencode-ai/ui/context/dialog" import { DialogSelectFile } from "@/components/dialog-select-file" import { DialogSelectModel } from "@/components/dialog-select-model" @@ -1013,7 +1013,29 @@ export default function Page() { const cacheKey = createMemo(() => checksum(contents())) const isImage = createMemo(() => { const c = state()?.content - return c?.encoding === "base64" && c?.mimeType?.startsWith("image/") + return ( + c?.encoding === "base64" && + c?.mimeType?.startsWith("image/") && + c?.mimeType !== "image/svg+xml" + ) + }) + const isSvg = createMemo(() => { + const c = state()?.content + return c?.mimeType === "image/svg+xml" + }) + const svgContent = createMemo(() => { + if (!isSvg()) return + const c = state()?.content + if (!c) return + if (c.encoding === "base64") return base64Decode(c.content) + return c.content + }) + const svgPreviewUrl = createMemo(() => { + if (!isSvg()) return + const c = state()?.content + if (!c) return + if (c.encoding === "base64") return `data:image/svg+xml;base64,${c.content}` + return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(c.content)}` }) const imageDataUrl = createMemo(() => { if (!isImage()) return @@ -1144,6 +1166,32 @@ export default function Page() { <img src={imageDataUrl()} alt={path()} class="max-w-full" /> </div> </Match> + <Match when={state()?.loaded && isSvg()}> + <div class="flex flex-col gap-4 px-6 py-4"> + <Dynamic + component={codeComponent} + file={{ + name: path() ?? "", + contents: svgContent() ?? "", + cacheKey: cacheKey(), + }} + enableLineSelection + selectedLines={selectedLines()} + onLineSelected={(range: SelectedLineRange | null) => { + const p = path() + if (!p) return + file.setSelectedLines(p, range) + }} + overflow="scroll" + class="select-text" + /> + <Show when={svgPreviewUrl()}> + <div class="flex justify-center pb-40"> + <img src={svgPreviewUrl()} alt={path()} class="max-w-full max-h-96" /> + </div> + </Show> + </div> + </Match> <Match when={state()?.loaded}> <Dynamic component={codeComponent} |
