From 788b52b4ab3461561cec1fb304921c58916b0940 Mon Sep 17 00:00:00 2001 From: Drew Smirnoff Date: Sat, 16 May 2026 20:09:33 +0400 Subject: [PATCH] fix: Ghostty image hyperlink bug (#1297) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What? Emited newlines outside `hyperlink()` call, link sits on single line and works for Ghostty. And a small patch to fix split view rendering images, when rendering was turned off. ## Why? Ghostty terminates hyperlink region at newline boundary, so clickable area was lost. Kitty/WezTerm carry URI across line breaks → worked there. Fixes #1291 --------- Signed-off-by: drew --- main.go | 2 ++ tui/folder_inbox.go | 11 ++++++++++- view/html.go | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index fecd79575741df1c69dad7cff7205254ffe11ade..528802ee42e88efe0cd347c0d1720a30392987e1 100644 --- a/main.go +++ b/main.go @@ -495,6 +495,7 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.folderInbox.SetDateFormat(m.config.GetDateFormat()) m.folderInbox.SetDetailedDates(m.config.EnableDetailedDates) m.folderInbox.SetDefaultThreaded(m.config.EnableThreaded) + m.folderInbox.SetDisableImages(m.config.DisableImages) // Use cached INBOX emails for instant display (memory first, then disk) if cached, ok := m.folderEmails["INBOX"]; ok && len(cached) > 0 { m.folderInbox.SetEmails(cached, m.config.Accounts) @@ -1092,6 +1093,7 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.folderInbox.SetDateFormat(m.config.GetDateFormat()) m.folderInbox.SetDetailedDates(m.config.EnableDetailedDates) m.folderInbox.SetDefaultThreaded(m.config.EnableThreaded) + m.folderInbox.SetDisableImages(m.config.DisableImages) } return m, nil diff --git a/tui/folder_inbox.go b/tui/folder_inbox.go index 529d5d80243936d456e85d132ddef6206bfb3d68..784477a44e42f83ee0fad9524ff24097bb7c3f7a 100644 --- a/tui/folder_inbox.go +++ b/tui/folder_inbox.go @@ -97,6 +97,9 @@ type FolderInbox struct { moveAccountID string moveSourceFolder string + // Image rendering preference, propagated from config. + disableImages bool + // Split pane state previewPane *EmailView previewedUID uint32 @@ -147,6 +150,12 @@ func (m *FolderInbox) SetDefaultThreaded(v bool) { } } +// SetDisableImages propagates the global image-display preference. Affects +// future split-view previews; an already-open preview keeps its current state. +func (m *FolderInbox) SetDisableImages(v bool) { + m.disableImages = v +} + // NewFolderInbox creates a new FolderInbox with the given folders and accounts. func NewFolderInbox(folders []string, accounts []config.Account) *FolderInbox { folders = sortFolders(folders) @@ -366,7 +375,7 @@ func (m *FolderInbox) Update(msg tea.Msg) (tea.Model, tea.Cmd) { previewWidth := m.calculatePreviewWidth() inboxWidth := m.calculateInboxWidth() colOffset := sidebarWidth + 2 + inboxWidth + 2 // borders + padding - m.previewPane = NewEmailViewPreview(*email, previewWidth, m.height, colOffset, false) + m.previewPane = NewEmailViewPreview(*email, previewWidth, m.height, colOffset, m.disableImages) return m, nil } diff --git a/view/html.go b/view/html.go index feaff04472f774c079f4b52c00f011c16eae2e39..7d76f64c357790ec1da1479320b3a9d51ff020c7 100644 --- a/view/html.go +++ b/view/html.go @@ -806,7 +806,7 @@ func renderHTMLToText(htmlBody []byte, inline map[string]string, h1Style, h2Styl debugImageProtocol("no payload for src=%s", src) } if hyperlinkSupported() { - text.WriteString(hyperlink(src, fmt.Sprintf("\n [Click here to view image: %s] \n", alt))) + text.WriteString(fmt.Sprintf("\n %s \n", hyperlink(src, fmt.Sprintf("[Click here to view image: %s]", alt)))) } else { text.WriteString(fmt.Sprintf("\n %s \n", linkStyle().Render(fmt.Sprintf("[Image: %s, %s]", alt, src)))) }