fix: v2.7.4 — Changes matches JetBrains (#72), the chat says when Claude waits on a trust prompt (#73), Vietnamese Telex in Safari
- Changes (#72): a file git reports `MM` whose working copy equals HEAD again (a staged change since undone on disk) is no longer listed — JetBrains' GitChangesCollector drops it the same way. Mode-only changes stay listed. statusCounts (the dirty-tree safety checks) is unchanged. - Chat (#73): Claude Code runs no hook before a folder is trusted, so a new pane's session has no row; the chat now says the session has not started, offers Open terminal, and asks before typing a message or /model //effort into the pane (an Enter would pick the trust prompt's "No, exit"). - Terminal: Safari + macOS's own Vietnamese Telex replaces the whole word on each key (insertReplacementText), which xterm.js ignores — only each word's first letter reached the pane. The edit is now sent as DELs + the new tail. - Also: Ctrl+V pastes a screenshot into the terminal as a file path; the folder browser fallback lists files for a file field (`files=1`); the macOS native picker opens in front of the browser; a hidden tab is marked while a chat waits or once a turn ended; chat live line shows running calls, turn time and tokens, and "Done in …".
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
* @file ChatOutline.tsx
|
||||
* @description The right-hand panel of a Chat pane, laid out like
|
||||
* Claude Desktop's activity panel: the session's Progress (its
|
||||
* TaskCreate/TaskUpdate or TodoWrite plan, only when it has one), the Outputs
|
||||
* TaskCreate/TaskUpdate or TodoWrite plan, only when it has one — how many
|
||||
* steps are done of how many, a bar, and the step in progress highlighted), the Outputs
|
||||
* it wrote or edited (name + EXT tag; a click previews the file), and "Used in
|
||||
* this session" — the files attached to its prompts, the files it read and the
|
||||
* memory files it used and its skills (a click opens the list with a
|
||||
@@ -107,7 +108,8 @@ function Section({
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
count?: number;
|
||||
/** Beside the title: a count, or a "3/7". */
|
||||
count?: number | string;
|
||||
action?: ReactNode;
|
||||
/** Takes the panel's free height and scrolls inside it. */
|
||||
grow?: boolean;
|
||||
@@ -211,6 +213,7 @@ export function ChatOutline({
|
||||
}) {
|
||||
const { t } = useTranslation("run");
|
||||
const href = useSettingsHref();
|
||||
const doneSteps = o.progress.filter((p) => p.status === "completed").length;
|
||||
const used = o.uploads.length + o.files.length + o.memory.length + o.skills.length + o.mcp.length;
|
||||
const close = (
|
||||
<button
|
||||
@@ -228,16 +231,40 @@ export function ChatOutline({
|
||||
<aside
|
||||
data-testid="chat-outline"
|
||||
aria-label={t("chat.outline.panel")}
|
||||
// Over the chat in a narrow pane (the container is PaneChat's root),
|
||||
// Over the conversation in a narrow pane (the container is PaneChat's
|
||||
// root; `--chat-area` keeps the prompt box below it uncovered),
|
||||
// beside it once the pane has room, as wide as PaneChat's splitter says.
|
||||
className="absolute inset-y-3 right-3 z-30 flex w-[clamp(15rem,34%,20rem)] max-w-[calc(100%-1.5rem)] flex-shrink-0 flex-col overflow-hidden rounded-xl border border-border bg-surface-1 pb-2 shadow-xl [@container(min-width:40rem)]:static [@container(min-width:40rem)]:m-3 [@container(min-width:40rem)]:ml-0 [@container(min-width:40rem)]:w-[calc(var(--chat-side)-0.75rem)] [@container(min-width:40rem)]:max-w-none [@container(min-width:40rem)]:shadow-none"
|
||||
className="absolute right-3 top-3 bottom-[calc(100%-var(--chat-area,100%)+0.75rem)] z-30 flex w-[clamp(15rem,34%,20rem)] max-w-[calc(100%-1.5rem)] flex-shrink-0 flex-col overflow-hidden rounded-xl border border-border bg-surface-1 pb-2 shadow-xl [@container(min-width:40rem)]:static [@container(min-width:40rem)]:m-3 [@container(min-width:40rem)]:ml-0 [@container(min-width:40rem)]:w-[calc(var(--chat-side)-0.75rem)] [@container(min-width:40rem)]:max-w-none [@container(min-width:40rem)]:shadow-none"
|
||||
>
|
||||
{o.progress.length > 0 && (
|
||||
<Section title={t("chat.outline.progress")} action={close}>
|
||||
<Section
|
||||
title={t("chat.outline.progress")}
|
||||
count={`${doneSteps}/${o.progress.length}`}
|
||||
action={close}
|
||||
>
|
||||
<div
|
||||
role="progressbar"
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={o.progress.length}
|
||||
aria-valuenow={doneSteps}
|
||||
aria-label={t("chat.outline.progress")}
|
||||
className="mx-1.5 mb-1.5 h-1 overflow-hidden rounded-full bg-surface-3"
|
||||
>
|
||||
<div
|
||||
className="h-full rounded-full bg-accent-solid transition-[width] duration-500"
|
||||
style={{ width: `${(doneSteps / o.progress.length) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
{o.progress.map((task) => {
|
||||
const done = task.status === "completed";
|
||||
const now = task.status === "in_progress";
|
||||
return (
|
||||
<div key={task.id} className={rowClass} title={task.subject}>
|
||||
<div
|
||||
key={task.id}
|
||||
className={`${rowClass} ${now ? "bg-accent/10 font-medium" : ""}`}
|
||||
title={task.subject}
|
||||
aria-current={now ? "step" : undefined}
|
||||
>
|
||||
{done ? (
|
||||
<span className="flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-accent-solid text-white">
|
||||
<Check className="h-3 w-3" />
|
||||
|
||||
Reference in New Issue
Block a user