diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index bc04f9ecf..8ee5b3710 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -1961,7 +1961,7 @@ export default function Layout(props: ParentProps) { return (
{(p) => ( <> -
-
+
+
-
+
diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index 17572923e..04d898134 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -9,7 +9,8 @@ import { Tooltip } from "@opencode-ai/ui/tooltip" import { base64Encode } from "@opencode-ai/util/encode" import { getFilename } from "@opencode-ai/util/path" import { A, useNavigate, useParams } from "@solidjs/router" -import { type Accessor, createMemo, For, type JSX, Match, onCleanup, Show, Switch } from "solid-js" +import { type Accessor, createEffect, createMemo, For, type JSX, on, onCleanup, Show } from "solid-js" +import { createStore } from "solid-js/store" import { useGlobalSync } from "@/context/global-sync" import { useLanguage } from "@/context/language" import { getAvatarColors, type LocalProject, useLayout } from "@/context/layout" @@ -101,46 +102,94 @@ const SessionRow = (props: { warmPress: () => void warmFocus: () => void cancelHoverPrefetch: () => void -}): JSX.Element => ( - { - props.setHoverSession(undefined) - if (props.sidebarOpened()) return - props.clearHoverProjectSoon() - }} - > -
-
- }> - - - - -
- - -
- - 0}> -
- - +}): JSX.Element => { + const [slot, setSlot] = createStore({ + open: false, + show: false, + fade: false, + }) + + let f: number | undefined + const clear = () => { + if (f !== undefined) window.clearTimeout(f) + f = undefined + } + + onCleanup(clear) + createEffect( + on( + () => props.isWorking(), + (on, prev) => { + clear() + if (on) { + setSlot({ open: true, show: true, fade: false }) + return + } + if (prev) { + setSlot({ open: false, show: true, fade: true }) + f = window.setTimeout(() => setSlot({ show: false, fade: false }), 260) + return + } + setSlot({ open: false, show: false, fade: false }) + }, + { defer: true }, + ), + ) + + return ( + { + props.setHoverSession(undefined) + if (props.sidebarOpened()) return + props.clearHoverProjectSoon() + }} + > + 0)}> +
0, + }} + aria-hidden="true" + /> + + +
+ + + + {props.session.title} +
- - {props.session.title} - -
-
-) + + ) +} const SessionHoverPreview = (props: { mobile?: boolean @@ -204,8 +253,18 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => { }) const isWorking = createMemo(() => { if (hasPermissions()) return false + const pending = (sessionStore.message[props.session.id] ?? []).findLast( + (message) => + message.role === "assistant" && + typeof (message as { time?: { completed?: unknown } }).time?.completed !== "number", + ) const status = sessionStore.session_status[props.session.id] - return status?.type === "busy" || status?.type === "retry" + return ( + pending !== undefined || + status?.type === "busy" || + status?.type === "retry" || + (status !== undefined && status.type !== "idle") + ) }) const tint = createMemo(() => { @@ -300,7 +359,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => { return (
Promise language: ReturnType }): JSX.Element => ( -