diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-07 09:07:05 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-07 09:24:18 +0300 |
| commit | f2b75267a6085f28a415bc8464cf2a70b650e65f (patch) | |
| tree | b420c89466161dd627011b1267f423accbb9bca5 | |
| parent | 0aee798f25d09203742361c173e9dcd1a300d700 (diff) | |
ui: fix priority black spot and q/esc search-clear in ultra mode
Priority field: the no-priority dash (-) was rendered with terminal-
default (black) background because the priority badge path unconditionally
passed bg="" to suppress the badge colour. Now only H/M/L pass bg="" to
preserve their coloured pill; the dash case inherits the card bg.
q/esc with active search: first press clears the ultra search filter
(regex + filtered index + cursor reset) and stays in ultra mode, same
as esc behaves in normal table mode. A second press with no active
search exits ultra / quits the app as before. Tests updated accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| -rw-r--r-- | internal/ui/keyhandlers.go | 11 | ||||
| -rw-r--r-- | internal/ui/table_test.go | 44 | ||||
| -rw-r--r-- | internal/ui/ultra.go | 7 |
3 files changed, 45 insertions, 17 deletions
diff --git a/internal/ui/keyhandlers.go b/internal/ui/keyhandlers.go index d68a7f5..ffd52b1 100644 --- a/internal/ui/keyhandlers.go +++ b/internal/ui/keyhandlers.go @@ -157,6 +157,15 @@ func (m *Model) handleQuitOrEscape() (tea.Model, tea.Cmd) { return m, nil } if m.showUltra { + // Active search: q/esc clears the search filter first, same as in + // normal table mode. Only proceed to exit/quit when no search is active. + if m.ultraSearchRegex != nil { + m.ultraSearchRegex = nil + m.ultraFiltered = nil + m.ultraCursor = 0 + m.ultraOffset = 0 + return m, nil + } // When started via --ultra flag there is no table view to return to, // so q/esc exits the application directly. if m.ultraStartup { @@ -164,8 +173,6 @@ func (m *Model) handleQuitOrEscape() (tea.Model, tea.Cmd) { } m.ultraClearFocusedID() m.showUltra = false - m.ultraSearchRegex = nil - m.ultraFiltered = nil m.ultraSearchInput.SetValue("") return m, nil } diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go index 0acbfab..a065ca7 100644 --- a/internal/ui/table_test.go +++ b/internal/ui/table_test.go @@ -898,22 +898,30 @@ func TestUltraExitHotkeysClearUltraState(t *testing.T) { m.ultraSearchInput.SetValue("ultra needle") m.ultraFocusedID = 17 + // First q clears the active search but stays in ultra mode. mv, cmd = (&m).Update(tea.KeyPressMsg{Code: 'q', Text: "q"}) if cmd != nil { - t.Fatalf("q in ultra mode unexpectedly returned a command") + t.Fatalf("q with active search unexpectedly returned a command") } m = *mv.(*Model) - if m.showUltra { - t.Fatalf("q did not exit ultra mode") + if !m.showUltra { + t.Fatalf("q with active search should stay in ultra mode") } if m.ultraSearchRegex != nil { - t.Fatalf("q did not clear ultraSearchRegex") + t.Fatalf("first q did not clear ultraSearchRegex") } if m.ultraFiltered != nil { - t.Fatalf("q did not clear ultraFiltered") + t.Fatalf("first q did not clear ultraFiltered") } - if got := m.ultraSearchInput.Value(); got != "" { - t.Fatalf("q did not clear ultraSearchInput, got %q", got) + + // Second q (no active search) exits ultra mode. + mv, cmd = (&m).Update(tea.KeyPressMsg{Code: 'q', Text: "q"}) + if cmd != nil { + t.Fatalf("q in ultra mode (no search) unexpectedly returned a command") + } + m = *mv.(*Model) + if m.showUltra { + t.Fatalf("second q did not exit ultra mode") } if m.ultraFocusedID != 0 { t.Fatalf("q did not clear ultraFocusedID, got %d", m.ultraFocusedID) @@ -929,22 +937,30 @@ func TestUltraExitHotkeysClearUltraState(t *testing.T) { m.ultraFiltered = []int{2} m.ultraSearchInput.SetValue("second needle") + // First esc clears the active search, stays in ultra. mv, cmd = (&m).Update(tea.KeyPressMsg{Code: tea.KeyEsc}) if cmd != nil { - t.Fatalf("esc in ultra mode unexpectedly returned a command") + t.Fatalf("esc with active search unexpectedly returned a command") } m = *mv.(*Model) - if m.showUltra { - t.Fatalf("esc did not exit ultra mode") + if !m.showUltra { + t.Fatalf("esc with active search should stay in ultra mode") } if m.ultraSearchRegex != nil { - t.Fatalf("esc did not clear ultraSearchRegex") + t.Fatalf("first esc did not clear ultraSearchRegex") } if m.ultraFiltered != nil { - t.Fatalf("esc did not clear ultraFiltered") + t.Fatalf("first esc did not clear ultraFiltered") + } + + // Second esc (no active search) exits ultra mode. + mv, cmd = (&m).Update(tea.KeyPressMsg{Code: tea.KeyEsc}) + if cmd != nil { + t.Fatalf("esc in ultra mode (no search) unexpectedly returned a command") } - if got := m.ultraSearchInput.Value(); got != "" { - t.Fatalf("esc did not clear ultraSearchInput, got %q", got) + m = *mv.(*Model) + if m.showUltra { + t.Fatalf("second esc did not exit ultra mode") } if m.ultraFocusedID != 0 { t.Fatalf("esc did not clear ultraFocusedID, got %d", m.ultraFocusedID) diff --git a/internal/ui/ultra.go b/internal/ui/ultra.go index 9fccc0c..e2ad3e9 100644 --- a/internal/ui/ultra.go +++ b/internal/ui/ultra.go @@ -654,7 +654,12 @@ func (m *Model) renderUltraHeaderWithRegex(t task.Task, width int, re *regexp.Re sep := ultraFieldSep(bg) id := m.ultraStyledText(re, lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("253")), idText, bg) - priority := m.ultraStyledText(re, ultraPriorityStyle(m.theme, t.Priority), priorityText, "") // priority badge keeps its own bg + // H/M/L badges keep their own coloured background; plain "-" uses the card bg. + priorityBG := bg + if t.Priority == "H" || t.Priority == "M" || t.Priority == "L" { + priorityBG = "" + } + priority := m.ultraStyledText(re, ultraPriorityStyle(m.theme, t.Priority), priorityText, priorityBG) status := m.ultraStyledText(re, lipgloss.NewStyle().Foreground(lipgloss.Color("246")), statusText, bg) urgency := m.ultraStyledText(re, lipgloss.NewStyle().Foreground(lipgloss.Color("214")), urgencyText, bg) age := m.ultraStyledText(re, lipgloss.NewStyle().Foreground(lipgloss.Color("240")), ageText, bg) |
