Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions internal/tui/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -1799,14 +1799,31 @@ func (v *mailView) switchBox(index int) tea.Cmd {
return nil
}
if index == v.boxIndex {
// The box under the seen screen: its number or tab closes the screen the
// way esc does, landing on the list that is already there.
if v.seenActive {
v.clearSeen()
// The box already under a thread, a search, a bundle or the seen screen: its
// number closes whatever is open over it and lands on the list that is already
// there. Answering with nothing would let the key fall through to the thread,
// which swallows it, so 1 from a thread opened in the Imbox did nothing at all.
if !v.inThread && !v.searchActive && !v.bundleActive && !v.seenActive {
return nil
}
v.closeOverlays()
if v.requests.kind != mailRequestPostings {
v.requests.cancel()
Comment on lines +1809 to 1811
}
return nil
v.notice = ""
return func() tea.Msg { return nil }
}
v.closeOverlays()
v.requests.cancel()
v.notice = ""
v.postingList.setPostings(nil)
v.boxIndex = index
return v.requestPostings(v.boxes[index])
}

// closeOverlays puts away everything a box's list can have open over it — a thread, a
// search, a bundle, the Previously Seen screen — leaving the list itself.
func (v *mailView) closeOverlays() {
Comment on lines +1824 to +1826
v.inThread = false
v.threadNotice = ""
v.threadPosting = mail.Posting{}
Expand All @@ -1816,11 +1833,6 @@ func (v *mailView) switchBox(index int) tea.Cmd {
v.clearSearch()
v.clearBundle()
v.clearSeen()
v.requests.cancel()
v.notice = ""
v.postingList.setPostings(nil)
v.boxIndex = index
return v.requestPostings(v.boxes[index])
}

// openPreviouslySeen jumps to the Imbox's Previously Seen threads on their own screen,
Expand Down
43 changes: 43 additions & 0 deletions internal/tui/tui_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,49 @@ func openLinkThreadThroughModel(t *testing.T) model {
return m
}

// A box's number works from inside a thread, including the box the thread was opened
// from: 1 in a thread read from the Imbox lands on the Imbox's list rather than falling
// through to the thread, which swallowed it.
func TestBoxNumbersLeaveAThread(t *testing.T) {
for _, testCase := range []struct {
key string
wantBox int
}{
{key: "1", wantBox: 0},
{key: "2", wantBox: 1},
} {
t.Run(testCase.key, func(t *testing.T) {
m := openLinkThreadThroughModel(t)

updated, _ := m.Update(keyPress(testCase.key))
m = updated.(model)

if m.mailView.InThread() {
t.Errorf("%s left the thread open", testCase.key)
}
if m.mailView.boxIndex != testCase.wantBox {
t.Errorf("%s landed on box %d, want %d", testCase.key, m.mailView.boxIndex, testCase.wantBox)
}
if testCase.key == "1" && !strings.Contains(stripANSI(m.View().Content), "Meeting notes") {
t.Errorf("the Imbox's list is not on screen:\n%s", stripANSI(m.View().Content))
}
})
}
}

func TestBoxNumberForTheCurrentBoxClosesASearch(t *testing.T) {
v := mailWithPostings()
v.searchActive = true
v.searchQuery = "invoice"

if cmd := v.handleBoxShortcut("1"); cmd == nil {
t.Fatal("1 over a search in the Imbox should be handled")
}
if v.searchActive || v.boxIndex != 0 {
t.Errorf("searchActive=%v box=%d, want the Imbox's list", v.searchActive, v.boxIndex)
}
}

func TestRootModelKeepsGlobalTabForALinklessThread(t *testing.T) {
m := modelWithBoxes()
m.mailView.inThread = true
Expand Down
Loading