working on implementing viewport model for bubbletea
This commit is contained in:
parent
957a606aae
commit
fb803dc68c
163
tui.go
163
tui.go
@ -9,6 +9,7 @@ import (
|
||||
term "github.com/muesli/termenv"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"io"
|
||||
"os"
|
||||
"protomolecule/src/dust"
|
||||
"protomolecule/src/eros"
|
||||
@ -20,6 +21,18 @@ import (
|
||||
|
||||
var _ScanMgr *scanStuff.Meta
|
||||
|
||||
const (
|
||||
// optional, only works when using the tea.EnterAltScreen;
|
||||
// which makes the tui utilize the full terminal.
|
||||
//
|
||||
// from what I understand this will update the screen more often
|
||||
// this should account for window resizes properly when combined with rendering all "cmd"s during the "update"
|
||||
fastrender = true
|
||||
|
||||
headerHeight = 3
|
||||
footerHeight = 3
|
||||
)
|
||||
|
||||
type model struct {
|
||||
choices []string // items on the device list
|
||||
cursor int // which device item our cursor is pointing at
|
||||
@ -27,10 +40,6 @@ type model struct {
|
||||
spinner spinner.Model
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func getSpinner() spinner.Model {
|
||||
s := spinner.NewModel()
|
||||
s.Spinner = spinner.Dot
|
||||
@ -49,8 +58,12 @@ var initialModel = model{
|
||||
cursor: 1,
|
||||
}
|
||||
|
||||
var reader *PipeReader
|
||||
var writer *PipeWriter
|
||||
|
||||
func init() {
|
||||
term.ClearScreen()
|
||||
|
||||
reader, writer = io.Pipe()
|
||||
|
||||
// print banner for style points
|
||||
// dust.Splash()
|
||||
@ -94,7 +107,7 @@ func init() {
|
||||
|
||||
// define pretty printer
|
||||
consoleWriter := zerolog.ConsoleWriter{
|
||||
Out: os.Stderr,
|
||||
Out: writer,
|
||||
}
|
||||
|
||||
// initialize simultaneous pretty printing and json logging
|
||||
@ -111,24 +124,12 @@ func init() {
|
||||
eros.Awaken()
|
||||
}
|
||||
|
||||
// this tomfoolery was taken from the example for viewports
|
||||
// i think the reasoning is aligned with the dynamic initialization that comes with this type of model
|
||||
//
|
||||
// tldr; initialization happens repeatedly in the update function
|
||||
func (m model) Init() tea.Cmd {
|
||||
|
||||
return tea.Batch(
|
||||
func() tea.Msg {
|
||||
var scanID int
|
||||
var scan *scanStuff.Scan
|
||||
|
||||
scanID = _ScanMgr.NewScan()
|
||||
scan = _ScanMgr.Scans[scanID]
|
||||
|
||||
//time.Sleep(30 * time.Millisecond)
|
||||
dust.Must("Scan", scan.Start())
|
||||
|
||||
return nil
|
||||
},
|
||||
listenForScanResults,
|
||||
spinner.Tick,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFormattedRow(dev projVars.DiscoveredDevice) string {
|
||||
@ -147,35 +148,45 @@ func getFormattedRow(dev projVars.DiscoveredDevice) string {
|
||||
}(dev.ScanResult.RSSI))
|
||||
}
|
||||
|
||||
// Update is processing "msg"s (messages) which appear to be bubbletea's utilization of channels for IPC
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
|
||||
var (
|
||||
cmd tea.Cmd
|
||||
cmds []tea.Cmd
|
||||
)
|
||||
|
||||
switch msg := msg.(type) {
|
||||
|
||||
case projVars.DiscoveredDevice:
|
||||
for k, v := range m.choices {
|
||||
if strings.HasPrefix(v, msg.ScanResult.Address.String()) {
|
||||
m.choices[k] = getFormattedRow(msg)
|
||||
case tea.WindowSizeMsg:
|
||||
verticalMargins := headerHeight + footerHeight
|
||||
|
||||
return m, listenForScanResults
|
||||
// getting the size of the window happens asynchronously so
|
||||
// we wait to receive them (ready) to determine the viewport dimensions
|
||||
if !m.ready {
|
||||
m.viewport = viewport.Model{
|
||||
Width: msg.Width,
|
||||
Height: msg.Height - verticalMargins,
|
||||
}
|
||||
|
||||
m.viewport.YPosition = headerHeight
|
||||
m.viewport.HighPerformanceRendering = fastrender
|
||||
|
||||
// so it looks like this is fetching data from our io.Pipe (io.reader) for every update
|
||||
// i defined said pipe on line 65
|
||||
m.viewport.SetContent(m.content)
|
||||
|
||||
m.ready = true
|
||||
} else {
|
||||
// now that we've figured out window dimensions we define viewport dimensions
|
||||
m.viewport.Width = msg.Width
|
||||
m.viewport.Height = msg.Height - verticalMargins
|
||||
}
|
||||
|
||||
/* m.choices = append(m.choices[func(lLength int) int {
|
||||
if lLength >= 10 {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}(len(m.choices)):],
|
||||
fmt.Sprintf("address: %s rssi: %d", msg.ScanResult.Address.String(), msg.ScanResult.RSSI)) */
|
||||
|
||||
m.choices = append(m.choices, getFormattedRow(msg))
|
||||
|
||||
return m, listenForScanResults
|
||||
|
||||
case spinner.TickMsg:
|
||||
var cmd tea.Cmd
|
||||
m.spinner, cmd = m.spinner.Update(msg)
|
||||
return m, cmd
|
||||
if fastrender {
|
||||
// see explanation on line 29
|
||||
cmds = append(cmds, viewport.Sync(m.viewport))
|
||||
}
|
||||
|
||||
// Is it a key press?
|
||||
case tea.KeyMsg:
|
||||
@ -209,14 +220,68 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.selected[m.cursor] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// spin that spinner
|
||||
case spinner.TickMsg:
|
||||
var cmd tea.Cmd
|
||||
m.spinner, cmd = m.spinner.Update(msg)
|
||||
return m, cmd
|
||||
|
||||
// **************************************************
|
||||
// actual protomolecule IPC for bubbletea starts here
|
||||
// **************************************************
|
||||
|
||||
case projVars.DiscoveredDevice:
|
||||
for k, v := range m.choices {
|
||||
if strings.HasPrefix(v, msg.ScanResult.Address.String()) {
|
||||
m.choices[k] = getFormattedRow(msg)
|
||||
|
||||
return m, listenForScanResults
|
||||
}
|
||||
}
|
||||
|
||||
/* m.choices = append(m.choices[func(lLength int) int {
|
||||
if lLength >= 10 {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}(len(m.choices)):],
|
||||
fmt.Sprintf("address: %s rssi: %d", msg.ScanResult.Address.String(), msg.ScanResult.RSSI)) */
|
||||
|
||||
m.choices = append(m.choices, getFormattedRow(msg))
|
||||
|
||||
return m, listenForScanResults
|
||||
|
||||
}
|
||||
|
||||
// Return the updated model to the Bubble Tea runtime for processing.
|
||||
// Note that we're not returning a command.
|
||||
return m, nil
|
||||
|
||||
return tea.Batch(
|
||||
func() tea.Msg {
|
||||
var scanID int
|
||||
var scan *scanStuff.Scan
|
||||
|
||||
scanID = _ScanMgr.NewScan()
|
||||
scan = _ScanMgr.Scans[scanID]
|
||||
|
||||
//time.Sleep(30 * time.Millisecond)
|
||||
dust.Must("Scan", scan.Start())
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
listenForScanResults,
|
||||
spinner.Tick,
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
if !m.ready {
|
||||
return "\n Loading ProtoMolecule..."
|
||||
}
|
||||
|
||||
// The header
|
||||
s := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#FAFAFA")).Background(lipgloss.Color("#7D56F4")).PaddingTop(0).PaddingLeft(0).Width(78).Render("protomolecule"+strings.Repeat(" ", 78-24)+"[q] - exit") + "\n\n"
|
||||
|
||||
@ -268,7 +333,7 @@ func listenForScanResults() tea.Msg {
|
||||
//time.Sleep( 1 * time.Second)
|
||||
return dev
|
||||
} else {
|
||||
time.Sleep(1 * time.Second)
|
||||
time.Sleep(250 * time.MilliSecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user