feat(webui): add lightweight session messaging via mentions
This commit is contained in:
@@ -50,6 +50,7 @@ import {
|
||||
} from "@/components/ui/tooltip";
|
||||
import { MAX_WORKBENCH_PANES } from "@/components/workbench/workbench-model";
|
||||
import { SIDEBAR_SELECTION_ITEM_CLASS } from "@/components/SidebarSelectionHighlight";
|
||||
import { SessionHandleHighlight, sessionHandleColor } from "@/components/CliAppMentionText";
|
||||
import { deriveTitle, relativeTime, visibleSessionPreview } from "@/lib/format";
|
||||
import {
|
||||
COLLAPSED_CHATS_VISIBLE_COUNT,
|
||||
@@ -103,8 +104,10 @@ function SidebarItemTooltip({
|
||||
|
||||
function SidebarSelectionTrack({
|
||||
active,
|
||||
handle,
|
||||
}: {
|
||||
active: boolean;
|
||||
handle: ChatSummary["handle"];
|
||||
}) {
|
||||
return (
|
||||
<span
|
||||
@@ -112,14 +115,31 @@ function SidebarSelectionTrack({
|
||||
data-active={active ? "true" : "false"}
|
||||
aria-hidden
|
||||
className={cn(
|
||||
"pointer-events-none absolute inset-x-0 bottom-0 h-0.5 origin-left rounded-full bg-current",
|
||||
"pointer-events-none absolute inset-x-0 bottom-0 h-0.5 origin-left rounded-full",
|
||||
"transition-transform duration-200 ease-out motion-reduce:transition-none",
|
||||
active ? "scale-x-100" : "scale-x-0",
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: handle ? sessionHandleColor(handle.color_slot) : "currentColor",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function SidebarSessionHandle({ handle }: { handle: ChatSummary["handle"] }) {
|
||||
if (!handle) return null;
|
||||
return (
|
||||
<span
|
||||
data-sidebar-handle-handle
|
||||
className="flex max-w-20 shrink-0 items-center overflow-hidden whitespace-nowrap text-[11px] font-medium leading-5"
|
||||
>
|
||||
<SessionHandleHighlight handle={handle}>
|
||||
@{handle.name}
|
||||
</SessionHandleHighlight>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function readCollapsedPaneGroups(): Set<string> {
|
||||
try {
|
||||
const value = JSON.parse(window.localStorage.getItem(
|
||||
@@ -160,6 +180,7 @@ export interface SidebarPaneGroup {
|
||||
key: string;
|
||||
chatId: string;
|
||||
title: string;
|
||||
handle?: ChatSummary["handle"];
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -965,27 +986,29 @@ export const ChatList = memo(function ChatList({
|
||||
partial={tabPartiallySelected}
|
||||
/>
|
||||
) : null}
|
||||
<span className="min-w-0 flex-1 overflow-hidden">
|
||||
{projectMode ? (
|
||||
<span className="relative flex w-full min-w-0 items-baseline gap-2">
|
||||
<span className="min-w-0 flex-1 truncate font-medium leading-5">
|
||||
{title}
|
||||
</span>
|
||||
{isPinned ? <PinnedChatIndicator /> : null}
|
||||
<span className="min-w-0 flex-1 overflow-hidden">
|
||||
{projectMode ? (
|
||||
<span className="relative flex w-full min-w-0 items-baseline gap-2">
|
||||
<SidebarSessionHandle handle={s.handle} />
|
||||
<span className="min-w-0 flex-1 truncate font-medium leading-5">
|
||||
{title}
|
||||
</span>
|
||||
{isPinned ? <PinnedChatIndicator /> : null}
|
||||
{timestamp ? (
|
||||
<span className="shrink-0 text-[11.5px] font-medium text-muted-foreground/58">
|
||||
{timestamp}
|
||||
</span>
|
||||
) : null}
|
||||
<SidebarSelectionTrack active={topicActive} />
|
||||
<SidebarSelectionTrack active={topicActive} handle={s.handle} />
|
||||
</span>
|
||||
) : (
|
||||
<span className="relative flex w-full min-w-0 items-center gap-1.5">
|
||||
<SidebarSessionHandle handle={s.handle} />
|
||||
<span className="min-w-0 flex-1 truncate font-medium leading-5">
|
||||
{title}
|
||||
</span>
|
||||
{isPinned ? <PinnedChatIndicator /> : null}
|
||||
<SidebarSelectionTrack active={topicActive} />
|
||||
<SidebarSelectionTrack active={topicActive} handle={s.handle} />
|
||||
</span>
|
||||
)}
|
||||
{showPreview ? (
|
||||
@@ -1405,7 +1428,9 @@ function ActivePaneRows({
|
||||
&& "bg-sidebar-accent/55 text-sidebar-accent-foreground",
|
||||
)}
|
||||
>
|
||||
<SidebarItemTooltip label={pane.title}>
|
||||
<SidebarItemTooltip
|
||||
label={pane.handle ? `@${pane.handle.name} · ${pane.title}` : pane.title}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(event) => {
|
||||
@@ -1437,9 +1462,10 @@ function ActivePaneRows({
|
||||
<SelectionIndicator checked={selected} partial={false} />
|
||||
) : null}
|
||||
<span className="relative flex min-w-0 flex-1 items-center gap-2 overflow-hidden">
|
||||
<SidebarSessionHandle handle={pane.handle} />
|
||||
<span className="min-w-0 flex-1 truncate">{pane.title}</span>
|
||||
{isPinned ? <PinnedChatIndicator /> : null}
|
||||
<SidebarSelectionTrack active={active} />
|
||||
<SidebarSelectionTrack active={active} handle={pane.handle} />
|
||||
</span>
|
||||
</button>
|
||||
</SidebarItemTooltip>
|
||||
|
||||
Reference in New Issue
Block a user