diff --git a/CHANGELOG.md b/CHANGELOG.md index d62c583..294a3a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ loosely follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Auto-summarization settings now save as soon as a changed row is applied, including cadence/provider/toggle changes and model edits, without requiring a separate save step. +- The Agents / Auto-summarization settings screen no longer shows + explicit Save, Cancel, or Back rows, and its footer copy no longer + describes a separate save/cancel flow. - Auto-summarization setting rows now visually separate grey labels from regular-colour values. - The active-thread summary in the tab bar is now constrained to the diff --git a/internal/app/app.go b/internal/app/app.go index baf21a6..427dcc4 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -2048,13 +2048,6 @@ func (st *uiState) closePalette(action paletteAction) { case "proc-restart": st.handleProcRestart(action.childID) - case "settings-close": - st.applySettingsAction(action) - restoreView() - st.drawTabBar() - st.drawSidebar() - st.drawStatusLine() - case "settings-test": st.applySettingsAction(action) restoreView() diff --git a/internal/app/palette.go b/internal/app/palette.go index fbaa237..73fc8bb 100644 --- a/internal/app/palette.go +++ b/internal/app/palette.go @@ -102,10 +102,9 @@ type renameForm struct { } type settingsInputForm struct { - title string - field string - value []rune - subtitle string + title string + field string + value []rune } // paletteState is the in-memory model for the overlay. SPEC §4: a @@ -1311,8 +1310,6 @@ func autoSummaryRows() []autoSummaryRow { {key: "cadence", label: "Cadence"}, {key: "test", label: "Test summarizer"}, {key: "run_now", label: "Summarize current top-level agent now"}, - {key: "save", label: "Save settings"}, - {key: "cancel", label: "Cancel"}, } } @@ -1340,10 +1337,9 @@ func (p *paletteState) activateAutoSummaryRow() (paletteAction, bool, int) { case "codex_model", "opencode_model", "claude_model": provider := strings.TrimSuffix(rows[p.cursor].key, "_model") p.settingsInput = &settingsInputForm{ - title: provider + " model", - field: rows[p.cursor].key, - value: []rune(p.settings.AutoSummary.modelFor(provider)), - subtitle: "model flag passed to " + provider, + title: provider + " model", + field: rows[p.cursor].key, + value: []rune(p.settings.AutoSummary.modelFor(provider)), } p.mode = paletteModeSettingsInput case "cadence": @@ -1361,10 +1357,6 @@ func (p *paletteState) activateAutoSummaryRow() (paletteAction, bool, int) { return p.settingsAction("settings-test"), true, 1 case "run_now": return p.settingsAction("settings-run-now"), true, 1 - case "save": - return p.settingsAction("settings-close"), true, 1 - case "cancel": - return paletteAction{kind: "cancel"}, true, 1 } p.settings.normalize() return paletteAction{}, false, 1 @@ -1397,17 +1389,13 @@ func (p *paletteState) applySettingsInput() bool { return changed } -func (p *paletteState) settingsCloseAction() paletteAction { - return p.settingsAction("settings-close") -} - func (p *paletteState) settingsAction(kind string) paletteAction { st := p.settings.clone() return paletteAction{kind: kind, settings: &st} } func (p *paletteState) renderSettings(out writeFlusher, cols, rows int) { - p.renderSimplePicker(out, cols, rows, "Settings", "esc cancel", "search settings") + p.renderSimplePicker(out, cols, rows, "Settings", "esc close", "search settings") } func (p *paletteState) renderSimplePicker(out writeFlusher, cols, rows int, title, hint, placeholder string) { @@ -1443,7 +1431,7 @@ func (p *paletteState) renderSimplePicker(out writeFlusher, cols, rows int, titl moveTo(&b, row, leftPad) b.WriteString(styleBorder + "├" + strings.Repeat("─", width-2) + "┤" + styleReset) row++ - footer := styleHint + "↵ open · esc cancel · ↑↓ navigate" + styleReset + footer := styleHint + "↵ open · esc close · ↑↓ navigate" + styleReset moveTo(&b, row, leftPad) b.WriteString(styleBorder + "│" + styleReset + " " + footer + strings.Repeat(" ", max(0, content-visibleLen(footer))) + " " + styleBorder + "│" + styleReset) row++ @@ -1459,7 +1447,7 @@ func (p *paletteState) renderAutoSummary(out writeFlusher, cols, rows int) { b.WriteString("\x1b[?25l\x1b[H\x1b[2J\x1b[3J") row := 2 title := "Auto-summarization" - hint := "esc cancel" + hint := "esc close" moveTo(&b, row, leftPad) b.WriteString(styleBorder + "╭─ " + styleActive + title + styleReset + styleBorder + " " + strings.Repeat("─", max(2, width-visibleLen(title)-visibleLen(hint)-9)) + " " + styleHint + hint + styleReset + styleBorder + " ─╮" + styleReset) row++ @@ -1481,7 +1469,7 @@ func (p *paletteState) renderAutoSummary(out writeFlusher, cols, rows int) { moveTo(&b, row, leftPad) b.WriteString(styleBorder + "├" + strings.Repeat("─", width-2) + "┤" + styleReset) row++ - footer := styleHint + "↵ edit/toggle · changes save when applied · esc cancel" + styleReset + footer := styleHint + "↵ edit/toggle · esc close" + styleReset if visibleLen(footer) > content { footer = clipRunes(footer, content-1) + "…" } @@ -1528,19 +1516,10 @@ func (p *paletteState) renderSettingsInput(out writeFlusher, cols, rows int) { b.WriteString("\x1b[?25l\x1b[H\x1b[2J\x1b[3J") row := 2 title := p.settingsInput.title - hint := "esc cancel" + hint := "esc back" moveTo(&b, row, leftPad) b.WriteString(styleBorder + "╭─ " + styleActive + title + styleReset + styleBorder + " " + strings.Repeat("─", max(2, width-visibleLen(title)-visibleLen(hint)-9)) + " " + styleHint + hint + styleReset + styleBorder + " ─╮" + styleReset) row++ - if p.settingsInput.subtitle != "" { - sub := p.settingsInput.subtitle - if visibleLen(sub) > content { - sub = clipRunes(sub, content-1) + "…" - } - moveTo(&b, row, leftPad) - b.WriteString(styleBorder + "│" + styleReset + " " + styleHint + sub + styleReset + strings.Repeat(" ", max(0, content-visibleLen(sub))) + " " + styleBorder + "│" + styleReset) - row++ - } value := string(p.settingsInput.value) if visibleLen(value) > content-2 { value = clipRunes(value, content-3) + "…" @@ -1552,7 +1531,7 @@ func (p *paletteState) renderSettingsInput(out writeFlusher, cols, rows int) { moveTo(&b, row, leftPad) b.WriteString(styleBorder + "├" + strings.Repeat("─", width-2) + "┤" + styleReset) row++ - footer := styleHint + "↵ save · esc cancel · ⌃u clear" + styleReset + footer := styleHint + "↵ apply · esc back · ⌃u clear" + styleReset moveTo(&b, row, leftPad) b.WriteString(styleBorder + "│" + styleReset + " " + footer + strings.Repeat(" ", max(0, content-visibleLen(footer))) + " " + styleBorder + "│" + styleReset) row++ diff --git a/internal/app/palette_ux_test.go b/internal/app/palette_ux_test.go index d56ecc9..e3d81fa 100644 --- a/internal/app/palette_ux_test.go +++ b/internal/app/palette_ux_test.go @@ -1,6 +1,7 @@ package app import ( + "bytes" "strings" "testing" @@ -379,10 +380,34 @@ func TestAutoSummaryCadenceCyclesSoloValues(t *testing.T) { } } -func TestAutoSummaryScreenOmitsBackRow(t *testing.T) { +func TestAutoSummaryScreenOmitsExplicitSaveCancelBackRows(t *testing.T) { + omitted := map[string]bool{ + "Save settings": true, + "Cancel": true, + "Back to Settings": true, + } for _, row := range autoSummaryRows() { - if row.label == "Back to Settings" { - t.Fatal("auto-summary settings should not show Back to Settings") + if omitted[row.label] { + t.Fatalf("auto-summary settings should not show %q", row.label) + } + } +} + +func TestAutoSummaryRenderOmitsStaleSettingsHelp(t *testing.T) { + p := newPalette(nil, "", "", preset.Set{}, defaultSettings()) + p.mode = paletteModeAutoSummary + var b bytes.Buffer + p.renderAutoSummary(wrapWriter(&b), 100, 30) + out := b.String() + for _, text := range []string{ + "Save settings", + "Cancel", + "Back to Settings", + "changes save", + "applies immediately", + } { + if strings.Contains(out, text) { + t.Fatalf("auto-summary render should not contain %q:\n%s", text, out) } } }