From 0e982c6ade9129009bac0fe3c1e9e289115e6260 Mon Sep 17 00:00:00 2001 From: Hadi <112569860+anotherhadi@users.noreply.github.com> Date: Wed, 20 May 2026 14:49:01 +0200 Subject: [PATCH] add pages "update" label Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com> --- internal/ui/app/pages.go | 6 +++++- internal/ui/app/sidebar.go | 4 ++++ internal/ui/app/update.go | 10 ++++++++++ internal/ui/findings/model.go | 11 ++++++++--- internal/ui/findings/update.go | 3 +++ internal/ui/intercept/model.go | 4 ++++ internal/ui/intercept/update.go | 1 + 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/internal/ui/app/pages.go b/internal/ui/app/pages.go index 26eb2f3..b215032 100644 --- a/internal/ui/app/pages.go +++ b/internal/ui/app/pages.go @@ -37,6 +37,8 @@ type pageEntry struct { isEditing func(m *Model) bool // resize propagates a new (w, h) to the page model. resize func(m *Model, w, h int) + // hasUpdate reports whether the page has unseen updates. + hasUpdate func(m *Model) bool } var pageRegistry = []pageEntry{ @@ -52,6 +54,7 @@ var pageRegistry = []pageEntry{ }, isEditing: func(m *Model) bool { return m.intercept.IsEditing() }, resize: func(m *Model, w, h int) { m.intercept.SetSize(w, h) }, + hasUpdate: func(m *Model) bool { return m.intercept.HasUnread() }, }, { id: pageHistory, @@ -114,7 +117,8 @@ var pageRegistry = []pageEntry{ m.findingsPage = updated.(findingsUI.Model) return cmd }, - resize: func(m *Model, w, h int) { m.findingsPage.SetSize(w, h) }, + resize: func(m *Model, w, h int) { m.findingsPage.SetSize(w, h) }, + hasUpdate: func(m *Model) bool { return m.findingsPage.HasUnread() }, }, { id: pageDocs, diff --git a/internal/ui/app/sidebar.go b/internal/ui/app/sidebar.go index e7f052e..139ce72 100644 --- a/internal/ui/app/sidebar.go +++ b/internal/ui/app/sidebar.go @@ -61,11 +61,15 @@ func (m *Model) renderSidebar() string { lineStyle := lipgloss.NewStyle().Width(inner).Padding(0, 1) var items strings.Builder + badgeUnread := lipgloss.NewStyle().Foreground(s.Warning).Bold(true) + for i, entry := range sidebarEntries { selected := entry.id == m.page badgeStyle, textStyle := badgeNormal, textNormal if selected { badgeStyle, textStyle = badgeSelected, textSelected + } else if entry.hasUpdate != nil && entry.hasUpdate(m) { + badgeStyle = badgeUnread } icon := "" if entry.icon != nil { diff --git a/internal/ui/app/update.go b/internal/ui/app/update.go index 69e2cdc..4403c03 100644 --- a/internal/ui/app/update.go +++ b/internal/ui/app/update.go @@ -37,6 +37,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case intercept.RequestArrivedMsg: updated, cmd := m.intercept.Update(msg) m.intercept = updated.(interceptUI.Model) + if m.page == pageIntercept { + m.intercept.ClearUnread() + } return m, tea.Batch(cmd, intercept.WaitForRequest(m.broker)) case intercept.ResponseArrivedMsg: updated, cmd := m.intercept.Update(msg) @@ -129,6 +132,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case findingsUI.FindingsLoadedMsg: updated, cmd := m.findingsPage.Update(msg) m.findingsPage = updated.(findingsUI.Model) + if m.page == pageFindings { + m.findingsPage.ClearUnread() + } return m, cmd case replayUI.SendToReplayMsg: @@ -258,8 +264,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, m.history.RefreshCmd() } if p == pageFindings { + m.findingsPage.ClearUnread() return m, findingsUI.RefreshCmd(m.database) } + if p == pageIntercept { + m.intercept.ClearUnread() + } } } } diff --git a/internal/ui/findings/model.go b/internal/ui/findings/model.go index ae2a872..2141d50 100644 --- a/internal/ui/findings/model.go +++ b/internal/ui/findings/model.go @@ -19,9 +19,11 @@ import ( ) type Model struct { - database *db.DB - findings []db.Finding - cursor int + database *db.DB + findings []db.Finding + cursor int + hasUnread bool + knownCount int listViewport viewport.Model bodyViewport viewport.Model @@ -46,6 +48,9 @@ func New() Model { func (m Model) Init() tea.Cmd { return nil } +func (m Model) HasUnread() bool { return m.hasUnread } +func (m *Model) ClearUnread() { m.hasUnread = false; m.knownCount = len(m.findings) } + func (m *Model) CurrentMarkdown() string { if len(m.findings) == 0 { return "" diff --git a/internal/ui/findings/update.go b/internal/ui/findings/update.go index 67c309f..fdadbbf 100644 --- a/internal/ui/findings/update.go +++ b/internal/ui/findings/update.go @@ -21,6 +21,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { prevID = m.findings[m.cursor].ID } m.findings = msg.Findings + if len(m.findings) > m.knownCount { + m.hasUnread = true + } if m.cursor >= len(m.findings) { m.cursor = max(0, len(m.findings)-1) } diff --git a/internal/ui/intercept/model.go b/internal/ui/intercept/model.go index 5cde5fd..a2e1015 100644 --- a/internal/ui/intercept/model.go +++ b/internal/ui/intercept/model.go @@ -30,6 +30,7 @@ type Model struct { editing bool interceptEnabled bool + hasUnread bool pendingEdits map[*intercept.PendingRequest]string pendingResponseEdits map[*intercept.PendingResponse]string @@ -76,6 +77,9 @@ func New(broker *intercept.Broker) Model { func (m Model) Init() tea.Cmd { return nil } +func (m Model) HasUnread() bool { return m.hasUnread } +func (m *Model) ClearUnread() { m.hasUnread = false } + func (m Model) IsEditing() bool { return m.editing } func (m Model) IsResponseFocused() bool { diff --git a/internal/ui/intercept/update.go b/internal/ui/intercept/update.go index d2eb8d1..6e06379 100644 --- a/internal/ui/intercept/update.go +++ b/internal/ui/intercept/update.go @@ -31,6 +31,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } wasEmpty := len(m.queue) == 0 m.queue = append(m.queue, msg.Req) + m.hasUnread = true m.refreshListViewport() if wasEmpty && (!m.captureResponse || m.focusedPanel == panelRequests) { m.refreshBody()