Compare commits

..
Author SHA1 Message Date
l0ng-ai 4256194f9e fix(agents): drop the status bar's Changes toggle
The session status bar ended with a Changes toggle that did the same as the
"N changed files" chip right below it. The chip opens and closes the Changes
pane and also shows the line counts, the pane has its own hide button, and the
status-bar toggle was disabled whenever there were no changes, so the status
bar now keeps only the Terminal button. The unused "Show changes" string goes
from the locale catalogs.
2026-11-11 12:04:39 +08:00
11 changed files with 6 additions and 116 deletions

No files matched your search

-31
View File
@@ -54,10 +54,6 @@
align-items: center;
gap: 2px;
}
.statusActions > .changesToggle {
height: var(--h-control-small);
padding: 0 4px;
}
.statusText {
flex: 1 1 0;
min-width: 0;
@@ -1230,33 +1226,6 @@
text-overflow: ellipsis;
}
.changesToggle {
display: inline-flex;
align-items: center;
gap: 4px;
height: var(--h-control);
padding: 0 8px;
border: 0;
border-radius: var(--radius-small);
background: transparent;
color: var(--fg-subtle);
font: inherit;
font-size: var(--fs-small);
cursor: pointer;
}
.changesToggle:hover:not(:disabled) {
background: var(--bg-hover);
color: var(--fg-strong);
}
.changesToggle[aria-pressed="true"] {
background: var(--bg-selected);
color: var(--fg-strong);
}
.changesToggle:disabled {
opacity: 0.4;
cursor: default;
}
/* An open AskUserQuestion: every question with its options, answered at once above the composer. */
.questionCard {
flex: none;
+4 -41
View File
@@ -272,20 +272,8 @@ function useLocalHead(status: AgentTask["status"] | null, root: string | null):
return local ? head : null;
}
/** The task's terminal and changes, at the end of its status line. */
function StatusActions({
task,
changes,
changesOpen,
onToggleChanges,
}: {
task: AgentTask;
changes: AgentChange[] | null;
changesOpen: boolean;
onToggleChanges: () => void;
}) {
const tx = useTx();
const count = changes?.length ?? 0;
/** The task's terminal, at the end of its status line. */
function StatusActions({ task }: { task: AgentTask }) {
return (
<span className={styles.statusActions}>
<IconButton
@@ -294,18 +282,6 @@ function StatusActions({
title="Terminal"
onClick={() => void executeAction("terminal.openAt", task.cwd)}
/>
<button
type="button"
className={styles.changesToggle}
aria-pressed={changesOpen}
disabled={count === 0 && !changesOpen}
aria-label={changesOpen ? tx("Hide changes") : tx("Show changes")}
title={changesOpen ? tx("Hide changes") : tx("Show changes")}
onClick={onToggleChanges}
>
<Icon name="toolwindow-changes" size={14} />
{count > 0 && <span>{count}</span>}
</button>
</span>
);
}
@@ -315,16 +291,10 @@ function SessionStatus({
task,
entries,
head,
changes,
changesOpen,
onToggleChanges,
}: {
task: AgentTask;
entries: AgentEntry[] | null;
head: string | null;
changes: AgentChange[] | null;
changesOpen: boolean;
onToggleChanges: () => void;
}) {
const tx = useTx();
const project = useProject((s) => s.project);
@@ -357,7 +327,7 @@ function SessionStatus({
{task.status === "limited" && task.resetsMs != null && ` · ${tx`resets ${formatSentAt(task.resetsMs)}`}`}
</span>
<Meters task={task} entries={entries} />
<StatusActions task={task} changes={changes} changesOpen={changesOpen} onToggleChanges={onToggleChanges} />
<StatusActions task={task} />
</div>
);
}
@@ -2559,14 +2529,7 @@ function SessionComposer({
);
return (
<div className={styles.composerArea}>
<SessionStatus
task={task}
entries={entries}
head={head}
changes={changes}
changesOpen={changesOpen}
onToggleChanges={onToggleChanges}
/>
<SessionStatus task={task} entries={entries} head={head} />
{task.status === "archived" && (
<div className={styles.banner}>
<span className={styles.bannerText}>
+2 -2
View File
@@ -1124,14 +1124,14 @@ describe("session state across tasks and hosts", () => {
useAgents.setState({ docked: "A", sessionLocation: "toolWindow" });
render(<AgentsView />);
await screen.findByText("Answer A");
await waitFor(() => expect(screen.getByRole("button", { name: "Show changes" })).toBeEnabled());
await screen.findByRole("button", { name: /1 changed file/ });
expect(screen.queryByRole("complementary", { name: "Changes" })).toBeNull();
const markVisible = vi.spyOn(await import("./store"), "markVisible");
vi.spyOn(document, "hasFocus").mockReturnValue(true);
const message = screen.getByRole("textbox", { name: "Message" });
fireEvent.change(message, { target: { value: "Draft to keep" } });
const conversation = stream();
fireEvent.click(screen.getByRole("button", { name: "Show changes" }));
fireEvent.click(screen.getByRole("button", { name: /1 changed file/ }));
expect(screen.getByRole("complementary", { name: "Changes" })).toBeVisible();
expect(screen.getByText("Answer A")).not.toBeVisible();
expect(screen.queryByRole("textbox", { name: "Message" })).toBeNull();
-23
View File
@@ -129,15 +129,6 @@ export function catalogState(
const vendorOf = (authors: readonly string[]) => authors.join(", ");
/** The marketplace's newer version of an installed plugin, if there is one this IDE can load. */
function useMarketUpdate(plugin: PluginInfo): MarketPlugin | undefined {
return usePlugins((s) =>
plugin.source === "installed"
? s.market?.find((m) => m.id === plugin.id && m.compatible && compareVersions(m.version, plugin.version) > 0)
: undefined,
);
}
function PluginIcon({ id, icon, large }: { id: string; icon: PluginIconData | null | undefined; large?: boolean }) {
return (
<span className={clsx(styles.icon, large && styles.iconLarge)} aria-hidden>
@@ -157,7 +148,6 @@ function ListHeader({ title, count }: { title: string; count: number }) {
function InstalledRow({ plugin, selected, onSelect }: { plugin: PluginInfo; selected: boolean; onSelect: () => void }) {
const busy = usePlugins((s) => !!s.busy[plugin.id]);
const update = useMarketUpdate(plugin);
return (
<li className={clsx(styles.row, selected && styles.rowSelected, !plugin.enabled && styles.rowDisabled)}>
<button
@@ -176,7 +166,6 @@ function InstalledRow({ plugin, selected, onSelect }: { plugin: PluginInfo; sele
{plugin.source !== "installed" && (
<span className={styles.devTag}>{plugin.source === "linked" ? tx("linked") : tx("dev")}</span>
)}
{update && <Badge tone="accent">{tx("Update")}</Badge>}
{plugin.status === "failed" && (
<Badge dot tone="danger">
<T>Failed</T>
@@ -555,8 +544,6 @@ function Homepage({ value }: { value: string }) {
function InstalledDetails({ plugin }: { plugin: PluginInfo }) {
const busy = usePlugins((s) => !!s.busy[plugin.id]);
const installing = usePlugins((s) => s.installing);
const update = useMarketUpdate(plugin);
const status = STATUS[plugin.status];
const [confirmUninstall, setConfirmUninstall] = useState(false);
@@ -659,16 +646,6 @@ function InstalledDetails({ plugin }: { plugin: PluginInfo }) {
</div>
<div className={styles.headerActions}>
{busy && <Spinner size={14} label="Working" />}
{update && (
<Button
size="small"
variant="primary"
disabled={busy || installing}
onClick={() => void installFromMarket(update.id)}
>
{tx`Update to ${update.version}`}
</Button>
)}
<Button
size="small"
variant={plugin.enabled ? "secondary" : "primary"}
@@ -1354,19 +1354,6 @@ describe("marketplace", () => {
await waitFor(() => expect(consents.map(([id]) => id)).toEqual(["a", "b"]));
});
it("marks installed plugins with updates and updates one from its details", async () => {
setConsentPrompt(async () => ({ optional: [] }));
const consents = updatesBackend({ a: preview("a", "1.1.0"), b: preview("b", "2.0.0") });
const user = userEvent.setup();
render(<PluginsPage />);
await waitFor(() => expect(usePlugins.getState().market).toHaveLength(3));
const list = screen.getByRole("list", { name: "Installed plugins" });
expect(within(list).getAllByText("Update")).toHaveLength(2);
await user.click(within(list).getAllByRole("button", { name: /^b/i })[0]!);
await user.click(await screen.findByRole("button", { name: "Update to 2.0.0" }));
await waitFor(() => expect(consents.map(([id]) => id)).toEqual(["b"]));
});
it("announces updates with actions to install them or show the plugins", async () => {
updatesBackend({ a: preview("a", "1.1.0"), b: preview("b", "2.0.0") });
handlePluginEvent({
-1
View File
@@ -2016,7 +2016,6 @@
"Show Commit in Git Log": "Mostrar confirmación en el registro de Git",
"Show Container Log": "Mostrar registro del contenedor",
"Show Context Actions": "Mostrar acciones de contexto",
"Show changes": "Mostrar cambios",
"Show Coverage": "Mostrar cobertura",
"Show Debug Tool Window": "Mostrar ventana de herramientas de depuración",
"Show Diff": "Mostrar diferencias",
-1
View File
@@ -1928,7 +1928,6 @@
"Show Commit in Git Log": "Afficher le commit dans le journal Git",
"Show Container Log": "Afficher le journal du conteneur",
"Show Context Actions": "Afficher les actions contextuelles",
"Show changes": "Afficher les modifications",
"Show Coverage": "Afficher la couverture",
"Show Debug Tool Window": "Afficher la fenêtre d'outil Débogage",
"Show Diff": "Afficher le diff",
-1
View File
@@ -2072,7 +2072,6 @@
"Show Commit in Git Log": "Git 로그에서 커밋 표시",
"Show Container Log": "컨테이너 로그 표시",
"Show Context Actions": "컨텍스트 액션 표시",
"Show changes": "변경 사항 표시",
"Show Coverage": "커버리지 표시",
"Show Debug Tool Window": "디버그 도구 창 표시",
"Show Diff": "Diff 표시",
-1
View File
@@ -2003,7 +2003,6 @@
"Show Commit in Git Log": "Pokaż zatwierdzenie w dzienniku Git",
"Show Container Log": "Pokaż dziennik kontenera",
"Show Context Actions": "Pokaż akcje kontekstowe",
"Show changes": "Pokaż zmiany",
"Show Coverage": "Pokaż pokrycie kodu",
"Show Debug Tool Window": "Pokaż okno narzędziowe debugowania",
"Show Diff": "Pokaż różnice (Diff)",
-1
View File
@@ -2004,7 +2004,6 @@
"Show Commit in Git Log": "Mostrar commit no log do Git",
"Show Container Log": "Mostrar log do contêiner",
"Show Context Actions": "Mostrar ações de contexto",
"Show changes": "Mostrar alterações",
"Show Coverage": "Mostrar cobertura",
"Show Debug Tool Window": "Mostrar janela de ferramentas de depuração",
"Show Diff": "Mostrar diff",
-1
View File
@@ -2364,7 +2364,6 @@
"Show Commit in Git Log": "在 Git 日志中显示提交",
"Show Container Log": "显示容器日志",
"Show Context Actions": "显示上下文操作",
"Show changes": "显示更改",
"Show Coverage": "显示覆盖率",
"Show Debug Tool Window": "显示调试工具窗口",
"Show Diff": "显示差异",