From 0ca758e13516d96180cc11631e02e5f7929ba4b0 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 11 Dec 2025 09:32:53 -0600 Subject: wip(desktop): progress --- packages/desktop/src/context/layout.tsx | 47 ++++++++++++++++++++------------- packages/desktop/src/context/local.tsx | 28 +++++++++----------- 2 files changed, 42 insertions(+), 33 deletions(-) (limited to 'packages/desktop/src/context') diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index 24ba55a53..ea5962b40 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -45,15 +45,18 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( name: "default-layout.v7", }, ) - const [ephemeral, setEphemeral] = createStore({ + const [ephemeral, setEphemeral] = createStore<{ connect: { - provider: undefined as undefined | string, - state: undefined as undefined | "pending" | "complete" | "error", - error: undefined as undefined | string, - }, + provider?: string + state?: "pending" | "complete" | "error" + error?: string + } dialog: { - open: undefined as undefined | Dialog, - }, + open?: Dialog + } + }>({ + connect: {}, + dialog: {}, }) const usedColors = new Set() @@ -177,22 +180,30 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( dialog: { opened: createMemo(() => ephemeral.dialog?.open), open(dialog: Dialog) { - setEphemeral("dialog", "open", dialog) - if (dialog !== "connect") { - setEphemeral("connect", {}) - } + batch(() => { + // if (dialog !== "connect") { + // setEphemeral("connect", {}) + // } + setEphemeral("dialog", "open", dialog) + }) }, close(dialog: Dialog) { - if (ephemeral.dialog?.open === dialog) { - setEphemeral("dialog", "open", undefined) - setEphemeral("connect", {}) + if (ephemeral.dialog.open === dialog) { + setEphemeral( + produce((state) => { + state.dialog.open = undefined + state.connect = {} + }), + ) } }, connect(provider: string) { - batch(() => { - setEphemeral("dialog", "open", "connect") - setEphemeral("connect", { provider, state: "pending" }) - }) + setEphemeral( + produce((state) => { + state.dialog.open = "connect" + state.connect = { provider, state: "pending" } + }), + ) }, }, connect: { diff --git a/packages/desktop/src/context/local.tsx b/packages/desktop/src/context/local.tsx index d8dfa732a..39fd1f987 100644 --- a/packages/desktop/src/context/local.tsx +++ b/packages/desktop/src/context/local.tsx @@ -41,10 +41,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const providers = useProviders() function isModelValid(model: ModelKey) { - const provider = providers().all.find((x) => x.id === model.providerID) + const provider = providers.all().find((x) => x.id === model.providerID) return ( !!provider?.models[model.modelID] && - providers() + providers .connected() .map((p) => p.id) .includes(model.providerID) @@ -123,16 +123,14 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ }) const list = createMemo(() => - providers() - .connected() - .flatMap((p) => - Object.values(p.models).map((m) => ({ - ...m, - name: m.name.replace("(latest)", "").trim(), - provider: p, - latest: m.name.includes("(latest)"), - })), - ), + providers.connected().flatMap((p) => + Object.values(p.models).map((m) => ({ + ...m, + name: m.name.replace("(latest)", "").trim(), + provider: p, + latest: m.name.includes("(latest)"), + })), + ), ) const find = (key: ModelKey) => list().find((m) => m.id === key?.modelID && m.provider.id === key.providerID) @@ -153,11 +151,11 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } } - for (const p of providers().connected()) { - if (p.id in providers().default) { + for (const p of providers.connected()) { + if (p.id in providers.default()) { return { providerID: p.id, - modelID: providers().default[p.id], + modelID: providers.default()[p.id], } } } -- cgit v1.2.3 From b34f434332f2ce7eee60d9dfbef2142e167ac0ec Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:46:18 -0600 Subject: fix: message order ascending --- packages/desktop/src/context/session.tsx | 4 ++-- packages/enterprise/src/routes/share/[shareID].tsx | 2 +- packages/ui/src/components/message-nav.tsx | 2 +- packages/ui/src/components/session-turn.tsx | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/desktop/src/context') diff --git a/packages/desktop/src/context/session.tsx b/packages/desktop/src/context/session.tsx index db2b3af7c..860c1a14f 100644 --- a/packages/desktop/src/context/session.tsx +++ b/packages/desktop/src/context/session.tsx @@ -62,10 +62,10 @@ export const { use: useSession, provider: SessionProvider } = createSimpleContex const userMessages = createMemo(() => messages() .filter((m) => m.role === "user") - .sort((a, b) => b.id.localeCompare(a.id)), + .sort((a, b) => a.id.localeCompare(b.id)), ) const lastUserMessage = createMemo(() => { - return userMessages()?.at(0) + return userMessages()?.at(-1) }) const activeMessage = createMemo(() => { if (!store.messageId) return lastUserMessage() diff --git a/packages/enterprise/src/routes/share/[shareID].tsx b/packages/enterprise/src/routes/share/[shareID].tsx index 1dae09c22..7cce15906 100644 --- a/packages/enterprise/src/routes/share/[shareID].tsx +++ b/packages/enterprise/src/routes/share/[shareID].tsx @@ -209,7 +209,7 @@ export default function () { const messages = createMemo(() => data().sessionID ? (data().message[data().sessionID]?.filter((m) => m.role === "user") ?? []).sort( - (a, b) => b.time.created - a.time.created, + (a, b) => a.time.created - b.time.created, ) : [], ) diff --git a/packages/ui/src/components/message-nav.tsx b/packages/ui/src/components/message-nav.tsx index 29b465c8c..a2db11348 100644 --- a/packages/ui/src/components/message-nav.tsx +++ b/packages/ui/src/components/message-nav.tsx @@ -15,7 +15,7 @@ export function MessageNav( ) { const [local, others] = splitProps(props, ["messages", "current", "size", "working", "onMessageSelect"]) const lastUserMessage = createMemo(() => { - return local.messages?.at(0) + return local.messages?.at(-1) }) const content = () => ( diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx index 5e73c6772..f97a3224c 100644 --- a/packages/ui/src/components/session-turn.tsx +++ b/packages/ui/src/components/session-turn.tsx @@ -42,10 +42,10 @@ export function SessionTurn( const userMessages = createMemo(() => messages() .filter((m) => m.role === "user") - .sort((a, b) => b.id.localeCompare(a.id)), + .sort((a, b) => a.id.localeCompare(b.id)), ) const lastUserMessage = createMemo(() => { - return userMessages()?.at(0) + return userMessages()?.at(-1) }) const message = createMemo(() => userMessages()?.find((m) => m.id === props.messageID)) -- cgit v1.2.3 From e149b7c1e276281b37a47997bf98d8954a4674ba Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 11 Dec 2025 15:39:38 -0600 Subject: fix: avatar colors --- packages/desktop/src/context/layout.tsx | 40 ++++++++++++++++++++------------- packages/desktop/src/pages/layout.tsx | 8 +++---- packages/ui/src/components/avatar.css | 3 ++- packages/ui/src/components/avatar.tsx | 13 ++++++++++- 4 files changed, 42 insertions(+), 22 deletions(-) (limited to 'packages/desktop/src/context') diff --git a/packages/desktop/src/context/layout.tsx b/packages/desktop/src/context/layout.tsx index ea5962b40..9cafdce96 100644 --- a/packages/desktop/src/context/layout.tsx +++ b/packages/desktop/src/context/layout.tsx @@ -6,18 +6,26 @@ import { useGlobalSync } from "./global-sync" import { useGlobalSDK } from "./global-sdk" import { Project } from "@opencode-ai/sdk/v2" -const PASTEL_COLORS = [ - "#FCEAFD", // pastel pink - "#FFDFBA", // pastel peach - "#FFFFBA", // pastel yellow - "#BAFFC9", // pastel green - "#EAF6FD", // pastel blue - "#EFEAFD", // pastel lavender - "#FEC8D8", // pastel rose - "#D4F0F0", // pastel cyan - "#FDF0EA", // pastel coral - "#C1E1C1", // pastel mint -] +const AVATAR_COLOR_KEYS = ["pink", "mint", "orange", "purple", "cyan", "lime"] as const + +export type AvatarColorKey = (typeof AVATAR_COLOR_KEYS)[number] + +export function isAvatarColorKey(value: string): value is AvatarColorKey { + return AVATAR_COLOR_KEYS.includes(value as AvatarColorKey) +} + +export function getAvatarColors(key?: string) { + if (key && isAvatarColorKey(key)) { + return { + background: `var(--avatar-background-${key})`, + foreground: `var(--avatar-text-${key})`, + } + } + return { + background: "var(--surface-info-base)", + foreground: "var(--text-base)", + } +} type Dialog = "provider" | "model" | "connect" @@ -58,11 +66,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( connect: {}, dialog: {}, }) - const usedColors = new Set() + const usedColors = new Set() - function pickAvailableColor() { - const available = PASTEL_COLORS.filter((c) => !usedColors.has(c)) - if (available.length === 0) return PASTEL_COLORS[Math.floor(Math.random() * PASTEL_COLORS.length)] + function pickAvailableColor(): AvatarColorKey { + const available = AVATAR_COLOR_KEYS.filter((c) => !usedColors.has(c)) + if (available.length === 0) return AVATAR_COLOR_KEYS[Math.floor(Math.random() * AVATAR_COLOR_KEYS.length)] return available[Math.floor(Math.random() * available.length)] } diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx index 05386c1fb..70764292f 100644 --- a/packages/desktop/src/pages/layout.tsx +++ b/packages/desktop/src/pages/layout.tsx @@ -1,7 +1,7 @@ import { createEffect, createMemo, For, Match, onCleanup, onMount, ParentProps, Show, Switch, type JSX } from "solid-js" import { DateTime } from "luxon" import { A, useNavigate, useParams } from "@solidjs/router" -import { useLayout } from "@/context/layout" +import { useLayout, getAvatarColors } from "@/context/layout" import { useGlobalSync } from "@/context/global-sync" import { base64Decode, base64Encode } from "@opencode-ai/util/encode" import { Mark } from "@opencode-ai/ui/logo" @@ -180,7 +180,7 @@ export default function Layout(props: ParentProps) { @@ -200,7 +200,7 @@ export default function Layout(props: ParentProps) { @@ -231,7 +231,7 @@ export default function Layout(props: ParentProps) { { fallback: string src?: string background?: string + foreground?: string size?: "small" | "normal" | "large" } export function Avatar(props: AvatarProps) { - const [split, rest] = splitProps(props, ["fallback", "src", "background", "size", "class", "classList", "style"]) + const [split, rest] = splitProps(props, [ + "fallback", + "src", + "background", + "foreground", + "size", + "class", + "classList", + "style", + ]) const src = split.src // did this so i can zero it out to test fallback return (
-- cgit v1.2.3