diff --git a/internal/tui/data.go b/internal/tui/data.go index 23e48d5..a04ff25 100644 --- a/internal/tui/data.go +++ b/internal/tui/data.go @@ -104,7 +104,7 @@ func (m *Model) refreshLive() { ordered = filterSites(ordered, m.filterText) } m.sites = ordered - m.logViewport.SetContent(strings.Join(m.engine.GetLogs(), "\n")) + m.refreshLogContent() if m.currentTab == 0 && m.selectedID != 0 { for i, s := range m.sites { diff --git a/internal/tui/tab_logs.go b/internal/tui/tab_logs.go index 480e8f3..3769a3e 100644 --- a/internal/tui/tab_logs.go +++ b/internal/tui/tab_logs.go @@ -82,18 +82,15 @@ func (m Model) renderLogLine(line string) string { return fmt.Sprintf(" %s %s", tag, msg) } -func (m Model) viewLogsTab() string { - content := m.logViewport.View() - if strings.TrimSpace(content) == "" || content == "Waiting for logs..." { - return m.emptyState("No log entries yet.", "Logs appear as monitors run checks") - } - - lines := strings.Split(content, "\n") +// refreshLogContent rebuilds the log viewport from the full engine log list, +// filtering before windowing so the entry count and "(n hidden)" reflect all +// logs, not just the visible viewport slice. +func (m *Model) refreshLogContent() { var rendered []string total := 0 shown := 0 - for _, line := range lines { + for _, line := range m.engine.GetLogs() { if strings.TrimSpace(line) == "" { continue } @@ -106,18 +103,27 @@ func (m Model) viewLogsTab() string { rendered = append(rendered, m.renderLogLine(line)) } + m.logTotal = total + m.logShown = shown + m.logViewport.SetContent(strings.Join(rendered, "\n")) +} + +func (m Model) viewLogsTab() string { + if m.logTotal == 0 { + return m.emptyState("No log entries yet.", "Logs appear as monitors run checks") + } + filterLabel := "All" if m.logFilterImportant { filterLabel = "Important" } header := m.st.subtleStyle.Render(fmt.Sprintf( - " %d entries Filter: %s", shown, filterLabel)) + " %d entries Filter: %s", m.logShown, filterLabel)) - if m.logFilterImportant && shown < total { - header += m.st.subtleStyle.Render(fmt.Sprintf(" (%d hidden)", total-shown)) + if m.logFilterImportant && m.logShown < m.logTotal { + header += m.st.subtleStyle.Render(fmt.Sprintf(" (%d hidden)", m.logTotal-m.logShown)) } - m.logViewport.SetContent(strings.Join(rendered, "\n")) return "\n" + header + "\n\n" + m.logViewport.View() } diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 36fa3b4..0b9647f 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -121,6 +121,8 @@ type Model struct { logViewport viewport.Model logFilterImportant bool + logTotal int + logShown int historyViewport viewport.Model historyChanges []models.StateChange diff --git a/internal/tui/update.go b/internal/tui/update.go index 194d396..e476617 100644 --- a/internal/tui/update.go +++ b/internal/tui/update.go @@ -527,6 +527,7 @@ func (m *Model) handleDashboardKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { case "f": if m.state == stateLogs { m.logFilterImportant = !m.logFilterImportant + m.refreshLogContent() return m, nil } case "tab":