diff --git a/docs/tui.md b/docs/tui.md index b95d8102..85c50790 100644 --- a/docs/tui.md +++ b/docs/tui.md @@ -64,6 +64,8 @@ uppercase belongs to Labels: A thread opens on its latest message; `k` steps back through the ones before it and `j` forward again. +Sending a reply or a forward from a thread closes the thread and returns you to the list you opened it from — the Imbox, a search, a bundle. A send that fails keeps the form open. + While reading a thread, the From header shows the actual send-as address when HEY records one separately from the account user. While reading a thread, links can be selected without a mouse. Tab selects the next link in document order and Shift+Tab selects the previous one; both wrap at the ends. A fixed row above the shortcut bar shows the complete selected destination without moving the thread. Press Enter to open it; opening stays unavailable until the terminal is wide enough to show the complete destination. Press Escape once to clear the selection, and Escape again to leave the thread. A thread with no selectable links keeps the normal global Tab focus behavior. Existing OSC 8 mouse links remain available. diff --git a/internal/tui/compose.go b/internal/tui/compose.go index fb7c7d7a..31e87cad 100644 --- a/internal/tui/compose.go +++ b/internal/tui/compose.go @@ -82,6 +82,7 @@ const ( type composeForm struct { mode composeMode topicName string + topicID int64 // the thread a reply or forward was written from; 0 for a new message entryID int64 // reply target (composeReply only) replySubject string // the "Re: …" subject a reply goes out under (composeReply only) replyActingSenderID int64 // the sender a reply goes out as; 0 = account default (composeReply only) @@ -140,6 +141,7 @@ func placeholderFor(label string) string { func newReplyForm(ctxMsg replyContextLoadedMsg, s styles) *composeForm { f := newComposeForm(composeReply, s) f.topicName = ctxMsg.topicName + f.topicID = ctxMsg.topicID f.entryID = ctxMsg.entryID f.replySubject = ctxMsg.subject f.replyActingSenderID = ctxMsg.actingSenderID @@ -154,6 +156,7 @@ func newReplyForm(ctxMsg replyContextLoadedMsg, s styles) *composeForm { func newForwardForm(ctxMsg forwardContextLoadedMsg, s styles) *composeForm { f := newComposeForm(composeForward, s) f.topicName = ctxMsg.topicName + f.topicID = ctxMsg.topicID f.sendSDK = ctxMsg.sdk f.forwardedContent = ctxMsg.content f.inputs[fieldSubject].SetValue(ctxMsg.subject) diff --git a/internal/tui/compose_test.go b/internal/tui/compose_test.go index 4866e802..ee5054d0 100644 --- a/internal/tui/compose_test.go +++ b/internal/tui/compose_test.go @@ -496,13 +496,16 @@ func TestForwardFormLoadsLatestEntryAndSends(t *testing.T) { // Sending from inside a thread used to leave its confirmation in the posting list's // header, which a thread covers — so it was said to nobody. A toast belongs to the -// model and is drawn over whatever the section is showing. -func TestForwardCompletionIsSaidFromInsideAThread(t *testing.T) { +// model and is drawn over whatever the section is showing. The send also finishes with +// the thread, so the reader is back on the list they opened it from. +func TestForwardFromAThreadReturnsToTheList(t *testing.T) { v := mailWithPostings() v.Resize(80, 30) v.inThread = true + v.topicID = 123 v.topicViewport.SetContent("Original thread") v.modal = newForwardForm(forwardContextLoadedMsg{ + topicID: 123, topicName: "Quarterly planning", subject: "Fwd: Quarterly planning", content: "