From 238d055859b8bd3d1bd94ab65fc63b6bc87070b1 Mon Sep 17 00:00:00 2001 From: Drew Smirnoff Date: Sun, 18 Jan 2026 14:32:10 +0400 Subject: [PATCH] fix: make the reply text hidden (#106) (#107) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- config/cache.go | 1 + main.go | 26 +++++++++++++++++++++----- tui/composer.go | 18 ++++++++++++++++++ tui/messages.go | 1 + 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/config/cache.go b/config/cache.go index 7f77addb05ecb43fb6bb3771c5ee86189355c719..c76e32c12bf935f9a82a159dda6c4d17a98cfaed 100644 --- a/config/cache.go +++ b/config/cache.go @@ -237,6 +237,7 @@ type Draft struct { AccountID string `json:"account_id"` InReplyTo string `json:"in_reply_to,omitempty"` References []string `json:"references,omitempty"` + QuotedText string `json:"quoted_text,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } diff --git a/main.go b/main.go index 6f7c79324a9271e0965d62948275e01fbc9bbcae..4acab2508bc187512912e3ebdd33bfdd5ff6718c 100644 --- a/main.go +++ b/main.go @@ -495,20 +495,32 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tui.ReplyToEmailMsg: to := msg.Email.From - subject := "Re: " + msg.Email.Subject - body := fmt.Sprintf("\n\nOn %s, %s wrote:\n> %s", msg.Email.Date.Format("Jan 2, 2006 at 3:04 PM"), msg.Email.From, strings.ReplaceAll(msg.Email.Body, "\n", "\n> ")) + subject := msg.Email.Subject + normalizedSubject := strings.ToLower(strings.TrimSpace(subject)) + if !strings.HasPrefix(normalizedSubject, "re:") { + subject = "Re: " + subject + } + quotedText := fmt.Sprintf("\n\nOn %s, %s wrote:\n> %s", msg.Email.Date.Format("Jan 2, 2006 at 3:04 PM"), msg.Email.From, strings.ReplaceAll(msg.Email.Body, "\n", "\n> ")) + var composer *tui.Composer if m.config != nil && len(m.config.Accounts) > 0 { // Use the account that received the email accountID := msg.Email.AccountID if accountID == "" { accountID = m.config.GetFirstAccount().ID } - composer := tui.NewComposerWithAccounts(m.config.Accounts, accountID, to, subject, body) - m.current = composer + composer = tui.NewComposerWithAccounts(m.config.Accounts, accountID, to, subject, "") } else { - m.current = tui.NewComposer("", to, subject, body) + composer = tui.NewComposer("", to, subject, "") } + composer.SetQuotedText(quotedText) + + // Set reply headers + inReplyTo := msg.Email.MessageID + references := append(msg.Email.References, msg.Email.MessageID) + composer.SetReplyContext(inReplyTo, references) + + m.current = composer m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height}) return m, m.current.Init() @@ -1024,6 +1036,10 @@ func sendEmail(account *config.Account, msg tui.SendEmailMsg) tea.Cmd { recipients := []string{msg.To} body := msg.Body + // Append quoted text if present (for replies) + if msg.QuotedText != "" { + body = body + msg.QuotedText + } images := make(map[string][]byte) attachments := make(map[string][]byte) diff --git a/tui/composer.go b/tui/composer.go index 505a9822e33027f11fd52b505567b9fbd97e0dff..533700fe51846cf09448da062b8861ea43c1fd14 100644 --- a/tui/composer.go +++ b/tui/composer.go @@ -69,6 +69,9 @@ type Composer struct { // Reply context inReplyTo string references []string + + // Hidden quoted text (appended to body when sending, but not shown in editor) + quotedText string } // NewComposer initializes a new composer model. @@ -303,6 +306,9 @@ func (m *Composer) Update(msg tea.Msg) (tea.Model, tea.Cmd) { Body: m.bodyInput.Value(), AttachmentPath: m.attachmentPath, AccountID: accountID, + QuotedText: m.quotedText, + InReplyTo: m.inReplyTo, + References: m.references, } } } @@ -502,6 +508,16 @@ func (m *Composer) SetReplyContext(inReplyTo string, references []string) { m.references = references } +// SetQuotedText sets the hidden quoted text that will be appended when sending. +func (m *Composer) SetQuotedText(text string) { + m.quotedText = text +} + +// GetQuotedText returns the hidden quoted text. +func (m *Composer) GetQuotedText() string { + return m.quotedText +} + // GetInReplyTo returns the In-Reply-To header value. func (m *Composer) GetInReplyTo() string { return m.inReplyTo @@ -523,6 +539,7 @@ func (m *Composer) ToDraft() config.Draft { AccountID: m.GetSelectedAccountID(), InReplyTo: m.inReplyTo, References: m.references, + QuotedText: m.quotedText, } } @@ -533,5 +550,6 @@ func NewComposerFromDraft(draft config.Draft, accounts []config.Account) *Compos m.attachmentPath = draft.AttachmentPath m.inReplyTo = draft.InReplyTo m.references = draft.References + m.quotedText = draft.QuotedText return m } diff --git a/tui/messages.go b/tui/messages.go index 3cfc52efc0144c5be7335575613ba70cb4fc0ae4..45e862dc0c5a08bde3e3d90a2ab11e0f80a3caa0 100644 --- a/tui/messages.go +++ b/tui/messages.go @@ -27,6 +27,7 @@ type SendEmailMsg struct { InReplyTo string References []string AccountID string // ID of the account to send from + QuotedText string // Hidden quoted text appended when sending } type Credentials struct {