From d41cfdeacbd30207c4be87bb6e65f8ad4892f75b Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 4 May 2026 00:01:20 -0700 Subject: [PATCH] fix(tui): match gitcrawl action menu behavior --- tui/tui.go | 7 ++++--- tui/tui_test.go | 26 +++++++++++++++----------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tui/tui.go b/tui/tui.go index c6bd385..ccf2e15 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -711,6 +711,7 @@ func (m *model) applyInitialGroupMode() { type paneFocus int const ( + focusNone paneFocus = -1 focusRows paneFocus = iota focusContext focusDetail @@ -1115,9 +1116,9 @@ func (m *model) updateMenuKey(key tea.KeyMsg) tea.Cmd { switch key.String() { case "ctrl+c": return tea.Quit - case "q", "ctrl+d": + case "ctrl+d": return tea.Quit - case "esc": + case "q", "esc": m.closeMenu() case "up", "k": m.menuIndex = m.nextSelectableMenuIndex(-1) @@ -1164,7 +1165,7 @@ func (m *model) updateMenuKey(key tea.KeyMsg) tea.Cmd { } func (m *model) openActionMenu() { - m.openActionMenuFor(m.focus) + m.openActionMenuFor(focusNone) } func (m *model) openActionMenuFor(context paneFocus) { diff --git a/tui/tui_test.go b/tui/tui_test.go index c4015b9..21b3d6e 100644 --- a/tui/tui_test.go +++ b/tui/tui_test.go @@ -423,16 +423,17 @@ func TestVeryNarrowPanesStillShowCompactColumns(t *testing.T) { } } -func TestQQuitsFromMenuAndFilterModes(t *testing.T) { +func TestQClosesMenuAndQuitsFromFilterModes(t *testing.T) { m := newModel(Options{Title: "archive", Items: []Item{{Title: "alpha"}}}) updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}}) m = updated.(model) if !m.menuOpen { t.Fatal("menu did not open") } - _, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}}) - if cmd == nil { - t.Fatal("q in menu should quit") + updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'q'}}) + m = updated.(model) + if cmd != nil || m.menuOpen { + t.Fatalf("q in menu should close only, menu=%v cmd=%v", m.menuOpen, cmd) } m = newModel(Options{Title: "archive", Items: []Item{{Title: "alpha"}}}) @@ -1050,9 +1051,12 @@ func TestKeyboardActionShortcutAliasOpensMenu(t *testing.T) { updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}}) m = updated.(model) - if !m.menuOpen || m.menuTitle != "Row Actions" { + if !m.menuOpen || m.menuTitle != "Actions" { t.Fatalf("action shortcut menu open=%v title=%q", m.menuOpen, m.menuTitle) } + if m.menuFloating { + t.Fatal("keyboard action menu should render in the detail pane") + } } func TestActionMenuUsesGitcrawlDetailChrome(t *testing.T) { @@ -1066,17 +1070,17 @@ func TestActionMenuUsesGitcrawlDetailChrome(t *testing.T) { m.height = 30 updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'a'}}) m = updated.(model) - if m.status != "Channels Actions" { - t.Fatalf("action menu status = %q, want Channels Actions", m.status) + if m.status != "Actions" { + t.Fatalf("action menu status = %q, want Actions", m.status) } view := stripANSI(m.View()) - for _, want := range []string{"Thread full", "Channels Actions", "group scope", "Open selected URL"} { + for _, want := range []string{"Thread full", "Actions", "current selection", "Open selected URL"} { if !strings.Contains(view, want) { t.Fatalf("action menu chrome missing %q:\n%s", want, view) } } - if strings.Contains(view, "Row Actions") { - t.Fatalf("action menu should use semantic pane titles in visible chrome:\n%s", view) + if strings.Contains(view, "Row Actions") || strings.Contains(view, "Channels Actions") { + t.Fatalf("keyboard action menu should use gitcrawl-style generic title:\n%s", view) } if strings.Contains(view, "Detail Row Actions") { t.Fatalf("action menu should keep gitcrawl-style detail chrome:\n%s", view) @@ -1094,7 +1098,7 @@ func TestActionMenuTitlesFollowFocusedPane(t *testing.T) { m.width = 160 m.height = 30 m.focus = focusContext - m.openActionMenu() + m.openActionMenuFor(focusContext) if m.status != "Messages Actions" { t.Fatalf("context action menu status = %q, want Messages Actions", m.status) }