Skip to content
Snippets Groups Projects
statusscreen.go 3.22 KiB
Newer Older
package statusscreen

import (
capossele's avatar
capossele committed
	"sync"
capossele's avatar
capossele committed
	"time"

	"golang.org/x/crypto/ssh/terminal"

capossele's avatar
capossele committed
	"github.com/gdamore/tcell"
	"github.com/iotaledger/goshimmer/packages/daemon"
	"github.com/iotaledger/goshimmer/packages/events"
	"github.com/iotaledger/goshimmer/packages/node"
	"github.com/rivo/tview"
)

var statusMessages = make(map[string]*StatusMessage)
var messageLog = make([]*StatusMessage, 0)
capossele's avatar
capossele committed
var mutex sync.RWMutex

var app *tview.Application

func configure(plugin *node.Plugin) {
	if !terminal.IsTerminal(int(os.Stdin.Fd())) {
		return
	}

capossele's avatar
capossele committed
	node.DEFAULT_LOGGER.SetEnabled(false)
capossele's avatar
capossele committed
	DEFAULT_LOGGER.SetEnabled(true)
capossele's avatar
capossele committed
	plugin.Node.AddLogger(DEFAULT_LOGGER)
capossele's avatar
capossele committed
	daemon.Events.Shutdown.Attach(events.NewClosure(func() {
capossele's avatar
capossele committed
		node.DEFAULT_LOGGER.SetEnabled(true)
capossele's avatar
capossele committed
		if app != nil {
			app.Stop()
		}
	}))
}

func run(plugin *node.Plugin) {
	if !terminal.IsTerminal(int(os.Stdin.Fd())) {
		return
	}

capossele's avatar
capossele committed
	newPrimitive := func(text string) *tview.TextView {
		textView := tview.NewTextView()

		textView.
			SetTextAlign(tview.AlignLeft).
			SetText(" " + text)

		return textView
	}

	app = tview.NewApplication()

	headerBar := NewUIHeaderBar()

	content := tview.NewGrid()
	content.SetBackgroundColor(tcell.ColorWhite)
	content.SetColumns(0)
	content.SetBorders(false)
	content.SetOffset(0, 0)
	content.SetGap(0, 0)
capossele's avatar
capossele committed

	footer := newPrimitive("")
	footer.SetBackgroundColor(tcell.ColorDarkMagenta)
	footer.SetTextColor(tcell.ColorWhite)

	grid := tview.NewGrid().
		SetRows(10, 0, 1).
		SetColumns(0).
		SetBorders(false).
		AddItem(headerBar.Primitive, 0, 0, 1, 1, 0, 0, false).
		AddItem(content, 1, 0, 1, 1, 0, 0, false).
		AddItem(footer, 2, 0, 1, 1, 0, 0, false)

	frame := tview.NewFrame(grid).
		SetBorders(1, 1, 0, 0, 2, 2)
	frame.SetBackgroundColor(tcell.ColorDarkGray)

	app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
		if event.Key() == tcell.KeyCtrlC || event.Key() == tcell.KeyESC {
			daemon.Shutdown()

			return nil
		}

		return event
	})

	app.SetBeforeDrawFunc(func(screen tcell.Screen) bool {
		mutex.RLock()
		defer mutex.RUnlock()
capossele's avatar
capossele committed
		headerBar.Update()

		rows := make([]int, 2)
capossele's avatar
capossele committed
		rows[0] = 1
capossele's avatar
capossele committed
		_, _, _, height := content.GetRect()
		for i := 0; i < len(messageLog) && i < height-2; i++ {
			rows = append(rows, 1)
		}

		content.Clear()
		content.SetRows(rows...)

		blankLine := newPrimitive("")
		blankLine.SetBackgroundColor(tcell.ColorWhite)
		content.AddItem(blankLine, 0, 0, 1, 1, 0, 0, false)

		logStart := len(messageLog) - (len(rows) - 2)
		if logStart < 0 {
			logStart = 0
		}

		for i, message := range messageLog[logStart:] {
capossele's avatar
capossele committed
			if i < height-2 {
				content.AddItem(NewUILogEntry(*message).Primitive, i+1, 0, 1, 1, 0, 0, false)
			}
		}

		blankLine = newPrimitive("")
		blankLine.SetBackgroundColor(tcell.ColorWhite)
		content.AddItem(blankLine, height-1, 0, 1, 1, 0, 0, false)

capossele's avatar
capossele committed
		return false
	})

	daemon.BackgroundWorker("Statusscreen Refresher", func() {
capossele's avatar
capossele committed
		for {
			select {
			case <-daemon.ShutdownSignal:
				return
			case <-time.After(1 * time.Second):
				app.QueueUpdateDraw(func() {})
			}
		}
	})

	daemon.BackgroundWorker("Statusscreen App", func() {
capossele's avatar
capossele committed
		if err := app.SetRoot(frame, true).SetFocus(frame).Run(); err != nil {
			panic(err)
		}
	})
var PLUGIN = node.NewPlugin("Status Screen", node.Enabled, configure, run)