diff --git a/libts/state.go b/libts/state.go index 9b7440d..9c8ae24 100644 --- a/libts/state.go +++ b/libts/state.go @@ -30,6 +30,11 @@ type State struct { // Peer status of the local node. Self *ipnstate.PeerStatus + // Health contains health check problems. + // Empty means everything is good. (or at least that no known + // problems are detected) + Health []string + // Tailnet lock key. Nil if not enabled. LockKey *key.NLPublic // True if the node is locked out by tailnet lock. @@ -79,6 +84,7 @@ func MakeState(status *ipnstate.Status, prefs *ipn.Prefs, lock *ipnstate.Network BackendState: status.BackendState, TSVersion: status.Version, Self: status.Self, + Health: status.Health, SortedExitNodes: getSortedExitNodes(status), } diff --git a/ui/appmenu.go b/ui/appmenu.go index 0aeb657..65f134b 100644 --- a/ui/appmenu.go +++ b/ui/appmenu.go @@ -45,6 +45,7 @@ func (i *AppmenuItem) render(isSelected bool, isAnySubmenuOpen bool) string { arrow := style. Padding(0, 1). Render(">") + return left + right + arrow } diff --git a/view.go b/view.go index 40e3986..79b21f3 100644 --- a/view.go +++ b/view.go @@ -79,6 +79,21 @@ func renderLockedOutWarning(m *model) string { return lipgloss.PlaceHorizontal(m.terminalWidth, lipgloss.Center, lockedOutWarning) } +// Render the locked out warning. Returns static output; should be called conditionally. +func renderWarnings(m *model) string { + bodyText := "Warning: " + + for i, issue := range m.state.Health { + bodyText += issue + + if i != len(m.state.Health)-1 { + bodyText += ", " + } + } + + return bodyText +} + // Format the top header section. func renderHeader(m *model) string { logo := lipgloss.NewStyle(). @@ -113,6 +128,12 @@ func renderHeader(m *model) string { Render("--") } + status += "\n" + + if len(m.state.Health) != 0 { + status += renderWarnings(m) + "\n\n" + } + // App versions. versions := "tsui: " + Version + "\n" versions += "tailscale: "