feat(ui): add Monaco changes/files right drawer viewers
Use OpenCode v2 file APIs for browsing and Monaco DiffEditor for session snapshot diffs, with local baseline language metadata and optional CDN language loading.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { createEffect, createSignal, onCleanup, onMount } from "solid-js"
|
||||
import { loadMonaco } from "../../lib/monaco/setup"
|
||||
import { getOrCreateTextModel } from "../../lib/monaco/model-cache"
|
||||
import { inferMonacoLanguageId } from "../../lib/monaco/language"
|
||||
import { ensureMonacoLanguageLoaded } from "../../lib/monaco/setup"
|
||||
import { useTheme } from "../../lib/theme"
|
||||
|
||||
interface MonacoFileViewerProps {
|
||||
scopeKey: string
|
||||
path: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export function MonacoFileViewer(props: MonacoFileViewerProps) {
|
||||
const { isDark } = useTheme()
|
||||
let host: HTMLDivElement | undefined
|
||||
|
||||
let editor: any = null
|
||||
let monaco: any = null
|
||||
const [ready, setReady] = createSignal(false)
|
||||
|
||||
const disposeEditor = () => {
|
||||
try {
|
||||
editor?.setModel(null)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
editor?.dispose()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
editor = null
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
let cancelled = false
|
||||
void (async () => {
|
||||
monaco = await loadMonaco()
|
||||
if (cancelled) return
|
||||
if (!host || !monaco) return
|
||||
|
||||
monaco.editor.setTheme(isDark() ? "vs-dark" : "vs")
|
||||
editor = monaco.editor.create(host, {
|
||||
value: "",
|
||||
language: "plaintext",
|
||||
readOnly: true,
|
||||
automaticLayout: true,
|
||||
lineNumbers: "on",
|
||||
minimap: { enabled: false },
|
||||
scrollBeyondLastLine: false,
|
||||
wordWrap: "off",
|
||||
renderWhitespace: "selection",
|
||||
fontSize: 13,
|
||||
})
|
||||
|
||||
setReady(true)
|
||||
})()
|
||||
|
||||
onCleanup(() => {
|
||||
cancelled = true
|
||||
setReady(false)
|
||||
disposeEditor()
|
||||
})
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (!ready() || !monaco || !editor) return
|
||||
monaco.editor.setTheme(isDark() ? "vs-dark" : "vs")
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (!ready() || !monaco || !editor) return
|
||||
const languageId = inferMonacoLanguageId(monaco, props.path)
|
||||
const cacheKey = `${props.scopeKey}:file:${props.path}`
|
||||
const model = getOrCreateTextModel({ monaco, cacheKey, value: props.content, languageId })
|
||||
editor.setModel(model)
|
||||
|
||||
void ensureMonacoLanguageLoaded(languageId).then(() => {
|
||||
try {
|
||||
monaco.editor.setModelLanguage(model, languageId)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return <div class="monaco-viewer" ref={host} />
|
||||
}
|
||||
Reference in New Issue
Block a user