tconsole: add status bar
This adds a status bar to the bottom of the tconsole. It contains a page
selector and clock.
Change-Id: Ia932fe793ff067f3d096046d8bd93c060bac807a
Reviewed-on: https://review.monogon.dev/c/monogon/+/3381
Tested-by: Jenkins CI
Reviewed-by: Leopold Schabel <leo@monogon.tech>
diff --git a/metropolis/node/core/tconsole/tconsole.go b/metropolis/node/core/tconsole/tconsole.go
index 52885bd..963be34 100644
--- a/metropolis/node/core/tconsole/tconsole.go
+++ b/metropolis/node/core/tconsole/tconsole.go
@@ -5,6 +5,7 @@
"crypto/sha256"
"encoding/hex"
"strings"
+ "time"
"github.com/gdamore/tcell/v2"
@@ -29,6 +30,9 @@
height int
// palette chosen for the given terminal.
palette palette
+ // activePage expressed within [0...num pages). The number/layout of pages is
+ // constructed dynamically in Run.
+ activePage int
network event.Value[*network.Status]
roles event.Value[*cpb.NodeRoles]
@@ -65,15 +69,17 @@
}
width, height := screen.Size()
+
return &Console{
- ttyPath: ttyPath,
- tty: tty,
- screen: screen,
- width: width,
- height: height,
- network: network,
- palette: pal,
- Quit: make(chan struct{}),
+ ttyPath: ttyPath,
+ tty: tty,
+ screen: screen,
+ width: width,
+ height: height,
+ network: network,
+ palette: pal,
+ Quit: make(chan struct{}),
+ activePage: 0,
roles: roles,
curatorConn: curatorConn,
@@ -92,6 +98,9 @@
if ev.Key() == tcell.KeyCtrlC {
close(c.Quit)
}
+ if ev.Key() == tcell.KeyTab {
+ c.activePage += 1
+ }
case *tcell.EventResize:
c.width, c.height = ev.Size()
}
@@ -120,6 +129,7 @@
}
supervisor.Signal(ctx, supervisor.SignalHealthy)
+ // Per-page data.
pageStatus := pageStatusData{
netAddr: "Waiting...",
roles: "Waiting...",
@@ -127,10 +137,32 @@
fingerprint: "Waiting...",
}
+ // Page references and names.
+ pages := []func(){
+ func() { c.pageStatus(&pageStatus) },
+ }
+ pageNames := []string{
+ "Status",
+ }
+
+ // Ticker used to maintain redraws at minimum 10Hz, to eg. update the clock in
+ // the status bar.
+ ticker := time.NewTicker(time.Second / 10)
+ defer ticker.Stop()
+
for {
- c.pageStatus(&pageStatus)
+ // Draw active page.
+ c.activePage %= len(pages)
+ pages[c.activePage]()
+
+ // Draw status bar.
+ c.statusBar(c.activePage, pageNames...)
+
+ // Sync to screen.
+ c.screen.Show()
select {
+ case <-ticker.C:
case <-ctx.Done():
return ctx.Err()
case ev := <-evC: