@@ -9,14 +9,13 @@ import { Tooltip } from "@opencode-ai/ui/tooltip"
99import { base64Encode } from "@opencode-ai/util/encode"
1010import { getFilename } from "@opencode-ai/util/path"
1111import { A , useNavigate , useParams } from "@solidjs/router"
12- import { type Accessor , createEffect , createMemo , For , type JSX , on , onCleanup , Show } from "solid-js"
13- import { createStore } from "solid-js/store"
12+ import { type Accessor , createMemo , For , type JSX , Match , onCleanup , Show , Switch } from "solid-js"
1413import { useGlobalSync } from "@/context/global-sync"
1514import { useLanguage } from "@/context/language"
1615import { getAvatarColors , type LocalProject , useLayout } from "@/context/layout"
1716import { useNotification } from "@/context/notification"
1817import { usePermission } from "@/context/permission"
19- import { agentColor } from "@/utils/agent"
18+ import { messageAgentColor } from "@/utils/agent"
2019import { sessionPermissionRequest } from "../session/composer/session-request-tree"
2120import { hasProjectPermissions } from "./helpers"
2221
@@ -102,94 +101,46 @@ const SessionRow = (props: {
102101 warmPress : ( ) => void
103102 warmFocus : ( ) => void
104103 cancelHoverPrefetch : ( ) => void
105- } ) : JSX . Element => {
106- const [ slot , setSlot ] = createStore ( {
107- open : false ,
108- show : false ,
109- fade : false ,
110- } )
111-
112- let f : number | undefined
113- const clear = ( ) => {
114- if ( f !== undefined ) window . clearTimeout ( f )
115- f = undefined
116- }
117-
118- onCleanup ( clear )
119- createEffect (
120- on (
121- ( ) => props . isWorking ( ) ,
122- ( on , prev ) => {
123- clear ( )
124- if ( on ) {
125- setSlot ( { open : true , show : true , fade : false } )
126- return
127- }
128- if ( prev ) {
129- setSlot ( { open : false , show : true , fade : true } )
130- f = window . setTimeout ( ( ) => setSlot ( { show : false , fade : false } ) , 260 )
131- return
132- }
133- setSlot ( { open : false , show : false , fade : false } )
134- } ,
135- { defer : true } ,
136- ) ,
137- )
138-
139- return (
140- < A
141- href = { `/${ props . slug } /session/${ props . session . id } ` }
142- class = { `relative flex items-center min-w-0 text-left w-full focus:outline-none transition-[padding] ${ props . mobile ? "pr-7" : "" } group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${ props . dense ? "py-0.5" : "py-1" } ` }
143- onPointerDown = { props . warmPress }
144- onPointerEnter = { props . warmHover }
145- onPointerLeave = { props . cancelHoverPrefetch }
146- onFocus = { props . warmFocus }
147- onClick = { ( ) => {
148- props . setHoverSession ( undefined )
149- if ( props . sidebarOpened ( ) ) return
150- props . clearHoverProjectSoon ( )
151- } }
152- >
153- < Show when = { ! props . isWorking ( ) && ( props . hasPermissions ( ) || props . hasError ( ) || props . unseenCount ( ) > 0 ) } >
154- < div
155- classList = { {
156- "absolute left-0 top-1/2 -translate-y-1/2 size-1.5 rounded-full" : true ,
157- "bg-surface-warning-strong" : props . hasPermissions ( ) ,
158- "bg-text-diff-delete-base" : ! props . hasPermissions ( ) && props . hasError ( ) ,
159- "bg-text-interactive-base" : ! props . hasPermissions ( ) && ! props . hasError ( ) && props . unseenCount ( ) > 0 ,
160- } }
161- aria-hidden = "true"
162- />
163- </ Show >
164-
165- < div class = "flex items-center min-w-0 grow-1" >
166- < div
167- class = "shrink-0 flex items-center justify-center overflow-hidden transition-[width,margin] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]"
168- style = { {
169- width : slot . open ? "16px" : "0px" ,
170- "margin-right" : slot . open ? "8px" : "0px" ,
171- } }
172- aria-hidden = "true"
173- >
174- < Show when = { slot . show } >
175- < div
176- class = "transition-opacity duration-200 ease-out"
177- classList = { {
178- "opacity-0" : slot . fade ,
179- } }
180- >
181- < Spinner class = "size-4" style = { { color : props . tint ( ) ?? "var(--icon-interactive-base)" } } />
182- </ div >
183- </ Show >
184- </ div >
185-
186- < span class = "text-14-regular text-text-strong grow-1 min-w-0 overflow-hidden text-ellipsis truncate" >
187- { props . session . title }
188- </ span >
104+ } ) : JSX . Element => (
105+ < A
106+ href = { `/${ props . slug } /session/${ props . session . id } ` }
107+ class = { `flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${ props . mobile ? "pr-7" : "" } group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${ props . dense ? "py-0.5" : "py-1" } ` }
108+ onPointerDown = { props . warmPress }
109+ onPointerEnter = { props . warmHover }
110+ onPointerLeave = { props . cancelHoverPrefetch }
111+ onFocus = { props . warmFocus }
112+ onClick = { ( ) => {
113+ props . setHoverSession ( undefined )
114+ if ( props . sidebarOpened ( ) ) return
115+ props . clearHoverProjectSoon ( )
116+ } }
117+ >
118+ < div class = "flex items-center gap-1 w-full" >
119+ < div
120+ class = "shrink-0 size-6 flex items-center justify-center"
121+ style = { { color : props . tint ( ) ?? "var(--icon-interactive-base)" } }
122+ >
123+ < Switch fallback = { < Icon name = "dash" size = "small" class = "text-icon-weak" /> } >
124+ < Match when = { props . isWorking ( ) } >
125+ < Spinner class = "size-[15px]" />
126+ </ Match >
127+ < Match when = { props . hasPermissions ( ) } >
128+ < div class = "size-1.5 rounded-full bg-surface-warning-strong" />
129+ </ Match >
130+ < Match when = { props . hasError ( ) } >
131+ < div class = "size-1.5 rounded-full bg-text-diff-delete-base" />
132+ </ Match >
133+ < Match when = { props . unseenCount ( ) > 0 } >
134+ < div class = "size-1.5 rounded-full bg-text-interactive-base" />
135+ </ Match >
136+ </ Switch >
189137 </ div >
190- </ A >
191- )
192- }
138+ < span class = "text-14-regular text-text-strong grow-1 min-w-0 overflow-hidden text-ellipsis truncate" >
139+ { props . session . title }
140+ </ span >
141+ </ div >
142+ </ A >
143+ )
193144
194145const SessionHoverPreview = ( props : {
195146 mobile ?: boolean
@@ -268,19 +219,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
268219 } )
269220
270221 const tint = createMemo ( ( ) => {
271- const messages = sessionStore . message [ props . session . id ]
272- if ( ! messages ) return undefined
273- let user : Message | undefined
274- for ( let i = messages . length - 1 ; i >= 0 ; i -- ) {
275- const message = messages [ i ]
276- if ( message . role !== "user" ) continue
277- user = message
278- break
279- }
280- if ( ! user ?. agent ) return undefined
281-
282- const agent = sessionStore . agent . find ( ( a ) => a . name === user . agent )
283- return agentColor ( user . agent , agent ?. color )
222+ return messageAgentColor ( sessionStore . message [ props . session . id ] , sessionStore . agent )
284223 } )
285224
286225 const hoverMessages = createMemo ( ( ) =>
@@ -359,7 +298,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
359298 return (
360299 < div
361300 data-session-id = { props . session . id }
362- class = "group/session relative w-full rounded-md cursor-default pl-3 pr-3 transition-colors
301+ class = "group/session relative w-full rounded-md cursor-default pl-2 pr-3 transition-colors
363302 hover:bg-surface-raised-base-hover [&:has(:focus-visible)]:bg-surface-raised-base-hover has-[[data-expanded]]:bg-surface-raised-base-hover has-[.active]:bg-surface-base-active"
364303 >
365304 < Show
0 commit comments