wip: desktop work

This commit is contained in:
Adam
2025-10-31 09:45:57 -05:00
parent 485135cf5c
commit 0ac943de90
5 changed files with 80 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ import {
DiffChanges,
ProgressCircle,
Message,
Typewriter,
} from "@opencode-ai/ui"
import { FileIcon } from "@/ui"
import FileTree from "@/components/file-tree"
@@ -544,7 +545,6 @@ export default function Page() {
<For each={local.session.userMessages()}>
{(message) => {
const diffs = createMemo(() => message.summary?.diffs ?? [])
return (
<li
class="group/li flex items-center gap-x-2 py-1 self-stretch cursor-default"
@@ -570,9 +570,9 @@ export default function Page() {
<div class="flex flex-col items-start gap-50 pb-50">
<For each={local.session.userMessages()}>
{(message) => {
const [initialized, setInitialized] = createSignal(!!message.summary?.title)
const [expanded, setExpanded] = createSignal(false)
const parts = createMemo(() => sync.data.part[message.id])
const prompt = createMemo(() => local.session.getMessageText(message))
const title = createMemo(() => message.summary?.title)
const summary = createMemo(() => message.summary?.body)
const assistantMessages = createMemo(() => {
@@ -581,6 +581,9 @@ export default function Page() {
) as AssistantMessageType[]
})
const working = createMemo(() => !summary())
createEffect(() => {
setTimeout(() => setInitialized(!!title()), 10_000)
})
return (
<div
@@ -589,9 +592,11 @@ export default function Page() {
>
{/* Title */}
<div class="py-2 flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger z-10">
<h1 class="text-14-medium text-text-strong overflow-hidden text-ellipsis min-w-0">
{title() ?? prompt()}
</h1>
<div class="text-14-medium text-text-strong overflow-hidden text-ellipsis min-w-0">
<Show when={initialized()} fallback={<Typewriter as="h1" text={title()} />}>
<h1>{title()}</h1>
</Show>
</div>
</div>
<Show when={title}>
<div class="-mt-8">

View File

@@ -20,6 +20,7 @@ export * from "./select-dialog"
export * from "./tabs"
export * from "./basic-tool"
export * from "./tooltip"
export * from "./typewriter"
export * from "../context/helper"
export * from "../context/shiki"

View File

@@ -0,0 +1,14 @@
@keyframes blink {
0%,
50% {
opacity: 1;
}
51%,
100% {
opacity: 0;
}
}
.blinking-cursor {
animation: blink 1s step-end infinite;
}

View File

@@ -0,0 +1,54 @@
import { createEffect, Show, type ValidComponent } from "solid-js"
import { createStore } from "solid-js/store"
import { Dynamic } from "solid-js/web"
export const Typewriter = <T extends ValidComponent = "p">(props: {
text?: string
class?: string
as?: T
}) => {
const [store, setStore] = createStore({
typing: false,
displayed: "",
cursor: true,
})
createEffect(() => {
const text = props.text
if (!text) return
let i = 0
setStore("typing", true)
setStore("displayed", "")
setStore("cursor", true)
const getTypingDelay = () => {
const random = Math.random()
if (random < 0.05) return 150 + Math.random() * 100
if (random < 0.15) return 80 + Math.random() * 60
return 30 + Math.random() * 50
}
const type = () => {
if (i < text.length) {
setStore("displayed", text.slice(0, i + 1))
i++
setTimeout(type, getTypingDelay())
} else {
setStore("typing", false)
setTimeout(() => setStore("cursor", false), 2000)
}
}
setTimeout(type, 200)
})
return (
<Dynamic component={props.as || "p"} class={props.class}>
{store.displayed}
<Show when={store.cursor}>
<span classList={{ "blinking-cursor": !store.typing }}></span>
</Show>
</Dynamic>
)
}

View File

@@ -25,5 +25,6 @@
@import "../components/select-dialog.css" layer(components);
@import "../components/tabs.css" layer(components);
@import "../components/tooltip.css" layer(components);
@import "../components/typewriter.css" layer(components);
@import "./utilities.css" layer(utilities);