mirror of
https://github.com/sst/opencode.git
synced 2025-08-04 13:30:52 +00:00
docs: share handle slow loading pages
This commit is contained in:
parent
5a0910ea79
commit
3e2a0c7281
2 changed files with 959 additions and 991 deletions
|
@ -1,8 +1,6 @@
|
||||||
import {
|
import {
|
||||||
type JSX,
|
type JSX,
|
||||||
onCleanup,
|
|
||||||
splitProps,
|
splitProps,
|
||||||
createEffect,
|
|
||||||
createResource,
|
createResource,
|
||||||
} from "solid-js"
|
} from "solid-js"
|
||||||
import { codeToHtml } from "shiki"
|
import { codeToHtml } from "shiki"
|
||||||
|
@ -12,15 +10,15 @@ import { transformerNotationDiff } from "@shikijs/transformers"
|
||||||
interface CodeBlockProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
interface CodeBlockProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
||||||
code: string
|
code: string
|
||||||
lang?: string
|
lang?: string
|
||||||
onRendered?: () => void
|
|
||||||
}
|
}
|
||||||
function CodeBlock(props: CodeBlockProps) {
|
function CodeBlock(props: CodeBlockProps) {
|
||||||
const [local, rest] = splitProps(props, ["code", "lang", "onRendered"])
|
const [local, rest] = splitProps(props, ["code", "lang"])
|
||||||
let containerRef!: HTMLDivElement
|
|
||||||
|
|
||||||
const [html] = createResource(
|
const [html] = createResource(
|
||||||
() => [local.code, local.lang],
|
() => [local.code, local.lang],
|
||||||
async ([code, lang]) => {
|
async ([code, lang]) => {
|
||||||
|
// TODO: For testing delays
|
||||||
|
// await new Promise((resolve) => setTimeout(resolve, 3000))
|
||||||
return (await codeToHtml(code || "", {
|
return (await codeToHtml(code || "", {
|
||||||
lang: lang || "text",
|
lang: lang || "text",
|
||||||
themes: {
|
themes: {
|
||||||
|
@ -32,25 +30,7 @@ function CodeBlock(props: CodeBlockProps) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
onCleanup(() => {
|
return <div innerHTML={html()} class={styles.codeblock} {...rest}></div >
|
||||||
if (containerRef) containerRef.innerHTML = ""
|
|
||||||
})
|
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
if (html() && containerRef) {
|
|
||||||
containerRef.innerHTML = html() as string
|
|
||||||
|
|
||||||
local.onRendered?.()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{html() ? (
|
|
||||||
<div ref={containerRef} class={styles.codeblock} {...rest}></div>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodeBlock
|
export default CodeBlock
|
||||||
|
|
|
@ -5,11 +5,13 @@ import {
|
||||||
Match,
|
Match,
|
||||||
Switch,
|
Switch,
|
||||||
onMount,
|
onMount,
|
||||||
|
Suspense,
|
||||||
onCleanup,
|
onCleanup,
|
||||||
splitProps,
|
splitProps,
|
||||||
createMemo,
|
createMemo,
|
||||||
createEffect,
|
createEffect,
|
||||||
createSignal,
|
createSignal,
|
||||||
|
SuspenseList,
|
||||||
} from "solid-js"
|
} from "solid-js"
|
||||||
import map from "lang-map"
|
import map from "lang-map"
|
||||||
import { DateTime } from "luxon"
|
import { DateTime } from "luxon"
|
||||||
|
@ -22,7 +24,6 @@ import {
|
||||||
IconAnthropic,
|
IconAnthropic,
|
||||||
} from "./icons/custom"
|
} from "./icons/custom"
|
||||||
import {
|
import {
|
||||||
IconFolder,
|
|
||||||
IconHashtag,
|
IconHashtag,
|
||||||
IconSparkles,
|
IconSparkles,
|
||||||
IconGlobeAlt,
|
IconGlobeAlt,
|
||||||
|
@ -486,6 +487,7 @@ function TerminalPart(props: TerminalPartProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
checkOverflow()
|
||||||
window.addEventListener("resize", checkOverflow)
|
window.addEventListener("resize", checkOverflow)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -510,7 +512,6 @@ function TerminalPart(props: TerminalPartProps) {
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
data-section="error"
|
data-section="error"
|
||||||
lang="text"
|
lang="text"
|
||||||
onRendered={checkOverflow}
|
|
||||||
ref={(el) => (preEl = el)}
|
ref={(el) => (preEl = el)}
|
||||||
code={local.error || ""}
|
code={local.error || ""}
|
||||||
/>
|
/>
|
||||||
|
@ -518,7 +519,6 @@ function TerminalPart(props: TerminalPartProps) {
|
||||||
<Match when={local.result}>
|
<Match when={local.result}>
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
lang="console"
|
lang="console"
|
||||||
onRendered={checkOverflow}
|
|
||||||
ref={(el) => (preEl = el)}
|
ref={(el) => (preEl = el)}
|
||||||
code={local.result || ""}
|
code={local.result || ""}
|
||||||
/>
|
/>
|
||||||
|
@ -596,7 +596,6 @@ export default function Share(props: {
|
||||||
messages: Record<string, Message.Info>
|
messages: Record<string, Message.Info>
|
||||||
}) {
|
}) {
|
||||||
let lastScrollY = 0
|
let lastScrollY = 0
|
||||||
let hasScrolled = false
|
|
||||||
let scrollTimeout: number | undefined
|
let scrollTimeout: number | undefined
|
||||||
|
|
||||||
const id = props.id
|
const id = props.id
|
||||||
|
@ -606,12 +605,6 @@ export default function Share(props: {
|
||||||
const [showScrollButton, setShowScrollButton] = createSignal(false)
|
const [showScrollButton, setShowScrollButton] = createSignal(false)
|
||||||
const [isButtonHovered, setIsButtonHovered] = createSignal(false)
|
const [isButtonHovered, setIsButtonHovered] = createSignal(false)
|
||||||
|
|
||||||
const anchorId = createMemo<string | null>(() => {
|
|
||||||
const raw = window.location.hash.slice(1)
|
|
||||||
const [id] = raw.split("-")
|
|
||||||
return id
|
|
||||||
})
|
|
||||||
|
|
||||||
const [store, setStore] = createStore<{
|
const [store, setStore] = createStore<{
|
||||||
info?: Session.Info
|
info?: Session.Info
|
||||||
messages: Record<string, Message.Info>
|
messages: Record<string, Message.Info>
|
||||||
|
@ -677,11 +670,6 @@ export default function Share(props: {
|
||||||
if (type === "message") {
|
if (type === "message") {
|
||||||
const [, messageID] = splits
|
const [, messageID] = splits
|
||||||
setStore("messages", messageID, reconcile(d.content))
|
setStore("messages", messageID, reconcile(d.content))
|
||||||
|
|
||||||
if (!hasScrolled && messageID === anchorId()) {
|
|
||||||
scrollToAnchor(window.location.hash.slice(1))
|
|
||||||
hasScrolled = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error parsing WebSocket message:", error)
|
console.error("Error parsing WebSocket message:", error)
|
||||||
|
@ -789,20 +777,8 @@ export default function Share(props: {
|
||||||
for (let i = 0; i < messages().length; i++) {
|
for (let i = 0; i < messages().length; i++) {
|
||||||
const msg = messages()[i]
|
const msg = messages()[i]
|
||||||
|
|
||||||
// TODO: Cleanup
|
|
||||||
// const system = result.messages.length === 0 && msg.role === "system"
|
|
||||||
const assistant = msg.metadata?.assistant
|
const assistant = msg.metadata?.assistant
|
||||||
|
|
||||||
// if (system) {
|
|
||||||
// for (const part of msg.parts) {
|
|
||||||
// if (part.type === "text") {
|
|
||||||
// result.system.push(part.text)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// result.created = msg.metadata?.time.created
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
result.messages.push(msg)
|
result.messages.push(msg)
|
||||||
|
|
||||||
if (assistant) {
|
if (assistant) {
|
||||||
|
@ -889,8 +865,10 @@ export default function Share(props: {
|
||||||
fallback={<p>Waiting for messages...</p>}
|
fallback={<p>Waiting for messages...</p>}
|
||||||
>
|
>
|
||||||
<div class={styles.parts}>
|
<div class={styles.parts}>
|
||||||
|
<SuspenseList>
|
||||||
<For each={data().messages}>
|
<For each={data().messages}>
|
||||||
{(msg, msgIndex) => (
|
{(msg, msgIndex) => (
|
||||||
|
<Suspense>
|
||||||
<For each={msg.parts}>
|
<For each={msg.parts}>
|
||||||
{(part, partIndex) => {
|
{(part, partIndex) => {
|
||||||
if (
|
if (
|
||||||
|
@ -930,6 +908,14 @@ export default function Share(props: {
|
||||||
|
|
||||||
return { metadata, args, result, duration }
|
return { metadata, args, result, duration }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const hash = window.location.hash.slice(1)
|
||||||
|
if (hash !== "" && hash === anchor()) {
|
||||||
|
scrollToAnchor(hash)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
{/* User text */}
|
{/* User text */}
|
||||||
|
@ -1875,8 +1861,10 @@ export default function Share(props: {
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</For>
|
</For>
|
||||||
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
</SuspenseList>
|
||||||
<div data-section="part" data-part-type="summary">
|
<div data-section="part" data-part-type="summary">
|
||||||
<div data-section="decoration">
|
<div data-section="decoration">
|
||||||
<span data-status={connectionStatus()[0]}></span>
|
<span data-status={connectionStatus()[0]}></span>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue