Tighten session list status slot

This commit is contained in:
wuyang6
2026-06-12 18:42:20 +08:00
parent cdf27e5bd2
commit c4f9cca2d7
@@ -482,7 +482,7 @@ const ClawSessionList: FC = () => {
return ( return (
<div <div
key={`claw-session-${session.session_id}-${session.modified_at}`} key={`claw-session-${session.session_id}-${session.modified_at}`}
className="aui-thread-list-item group relative flex h-9 items-center gap-2 rounded-lg transition-colors hover:bg-muted data-[active=true]:bg-muted" className="aui-thread-list-item group relative flex h-9 items-center rounded-lg transition-colors hover:bg-muted data-[active=true]:bg-muted"
data-active={active} data-active={active}
> >
{renamingSessionId === session.session_id ? ( {renamingSessionId === session.session_id ? (
@@ -515,7 +515,7 @@ const ClawSessionList: FC = () => {
) : ( ) : (
<button <button
type="button" type="button"
className="aui-thread-list-item-trigger flex h-full min-w-0 flex-1 items-center truncate px-3 text-start text-sm" className="aui-thread-list-item-trigger flex h-full min-w-0 flex-1 items-center overflow-hidden px-3 text-start text-sm"
onClick={async () => { onClick={async () => {
console.log("[session-list] click", { console.log("[session-list] click", {
sessionId: session.session_id, sessionId: session.session_id,
@@ -525,33 +525,24 @@ const ClawSessionList: FC = () => {
await openSession(session.session_id); await openSession(session.session_id);
}} }}
> >
<span className="truncate"> <span className="min-w-0 overflow-hidden text-clip whitespace-nowrap">
{loading {loading
? "回放中..." ? "回放中..."
: session.preview || session.session_id} : session.preview || session.session_id}
</span> </span>
</button> </button>
)} )}
<SessionRunBadge <SessionActionSlot
running={badge?.running === true} running={badge?.running === true}
unread={badge?.unread === true} unread={badge?.unread === true}
/> busy={deletingSessionId === session.session_id}
<button open={openMenuSessionId === session.session_id}
type="button" onOpenChange={() => {
className="aui-thread-list-item-more mr-2 flex size-7 shrink-0 items-center justify-center rounded-md p-0 text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100 data-[busy=true]:opacity-100 data-[open=true]:bg-accent data-[open=true]:opacity-100"
data-busy={deletingSessionId === session.session_id}
data-open={openMenuSessionId === session.session_id}
aria-expanded={openMenuSessionId === session.session_id}
aria-label="打开历史会话菜单"
title="更多选项"
onClick={() => {
setOpenMenuSessionId((current) => setOpenMenuSessionId((current) =>
current === session.session_id ? null : session.session_id, current === session.session_id ? null : session.session_id,
); );
}} }}
> />
<MoreHorizontalIcon className="size-4" />
</button>
{openMenuSessionId === session.session_id ? ( {openMenuSessionId === session.session_id ? (
<div className="aui-thread-list-item-more-content absolute top-8 right-1 z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md"> <div className="aui-thread-list-item-more-content absolute top-8 right-1 z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md">
<button <button
@@ -712,34 +703,49 @@ function useSessionRunBadges(
return { bySessionId, markRead }; return { bySessionId, markRead };
} }
function SessionRunBadge({ function SessionActionSlot({
running, running,
unread, unread,
busy,
open,
onOpenChange,
}: { }: {
running: boolean; running: boolean;
unread: boolean; unread: boolean;
busy: boolean;
open: boolean;
onOpenChange: () => void;
}) { }) {
if (running) { const hasBadge = running || unread;
return ( return (
<div className="relative mr-2 flex size-7 shrink-0 items-center justify-center">
<span <span
className="flex size-5 shrink-0 items-center justify-center text-muted-foreground" aria-hidden={!hasBadge}
title="运行中" className="pointer-events-none absolute inset-0 flex items-center justify-center text-muted-foreground transition-opacity group-hover:opacity-0 data-[hidden=true]:opacity-0 data-[open=true]:opacity-0"
data-hidden={!hasBadge}
data-open={open || busy}
title={running ? "运行中" : unread ? "已完成,未查看" : undefined}
> >
<Loader2Icon className="size-3.5 animate-spin" /> {running ? (
<Loader2Icon className="size-3.5 animate-spin" />
) : unread ? (
<span className="size-2 rounded-full bg-sky-300" />
) : null}
</span> </span>
); <button
} type="button"
if (unread) { className="aui-thread-list-item-more absolute inset-0 flex items-center justify-center rounded-md p-0 text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100 data-[busy=true]:opacity-100 data-[open=true]:bg-accent data-[open=true]:opacity-100"
return ( data-busy={busy}
<span data-open={open}
className="flex size-5 shrink-0 items-center justify-center" aria-expanded={open}
title="已完成,未查看" aria-label="打开历史会话菜单"
title="更多选项"
onClick={onOpenChange}
> >
<span className="size-2 rounded-full bg-sky-300" /> <MoreHorizontalIcon className="size-4" />
</span> </button>
); </div>
} );
return <span aria-hidden="true" className="size-5 shrink-0" />;
} }
function dedupeSessions(payload: unknown[]) { function dedupeSessions(payload: unknown[]) {