From 3e92467beb9351d2c58a515db020725562c37eff Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Thu, 18 Jun 2026 17:05:27 +0100 Subject: [PATCH] adding the options form for the stream view --- tui/internal/controllers/controllers.go | 3 + tui/internal/controllers/device.go | 7 ++- tui/internal/controllers/streaming.go | 30 ++++++++-- tui/internal/views/layoutTool_forms.go | 1 + tui/internal/views/mainFlex.go | 25 --------- tui/internal/views/stream.go | 74 +++++++++++++++++++++++-- 6 files changed, 100 insertions(+), 40 deletions(-) diff --git a/tui/internal/controllers/controllers.go b/tui/internal/controllers/controllers.go index d9f85fc..919fe7a 100644 --- a/tui/internal/controllers/controllers.go +++ b/tui/internal/controllers/controllers.go @@ -24,6 +24,9 @@ func ListFormButtonLabels(form *tview.Form) []string { } func SetFormButtonCallback(form *tview.Form, btnLabel string, fn func()) error { + // NOTE: is there a better way to do this ??? + // Find out + btnIndex := form.GetButtonIndex(btnLabel) if btnIndex == -1 { availableButtons := ListFormButtonLabels(form) diff --git a/tui/internal/controllers/device.go b/tui/internal/controllers/device.go index 01f1689..648de23 100644 --- a/tui/internal/controllers/device.go +++ b/tui/internal/controllers/device.go @@ -2,9 +2,10 @@ package controllers import ( + "fmt" + serv "esdi/tui/internal/services" "esdi/tui/internal/views" - "fmt" "github.com/gdamore/tcell/v2" ) @@ -76,12 +77,12 @@ func (mc *DeviceController) AddDeviceAPIListItems() { AddItem("stream", "stream data to the display", func() { views.AddAndShowPage(mc.DeviceAPIView.DevAPIToolView.Pages, "streaming-tool", - mc.StreamCtrl.StreamView.TextView, + mc.StreamCtrl.StreamView.Flex, ) mc.StreamCtrl.SetInternalState() - mc.App.SetFocus(mc.StreamCtrl.StreamView.TextView) + mc.App.SetFocus(mc.StreamCtrl.StreamView.Options.Form) }) } diff --git a/tui/internal/controllers/streaming.go b/tui/internal/controllers/streaming.go index be85264..4b32839 100644 --- a/tui/internal/controllers/streaming.go +++ b/tui/internal/controllers/streaming.go @@ -1,11 +1,12 @@ package controllers import ( + "fmt" + "sync/atomic" + "esdi/telemetry" "esdi/tui/internal/services" "esdi/tui/internal/views" - "fmt" - "sync/atomic" "github.com/gdamore/tcell/v2" ) @@ -13,7 +14,7 @@ import ( type StreamingCtrl struct { *Controller Service *services.CDashService - StreamView *views.StreamView + StreamView *views.StreamToolView Messages chan string Internal chan string Run bool @@ -34,7 +35,7 @@ func NewStreamingCtrl( Messages: make(chan string, 10), Internal: make(chan string, 10), Run: false, - StreamView: views.NewStreamView(), + StreamView: views.NewStreamToolView(), isRunning: false, } @@ -44,7 +45,7 @@ func NewStreamingCtrl( } func (sc *StreamingCtrl) registerHooks() { - sc.StreamView.TextView.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { + sc.StreamView.Options.Form.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { switch ev.Key() { case tcell.KeyEsc: sc.OnExit() @@ -57,10 +58,22 @@ func (sc *StreamingCtrl) registerHooks() { case 'p': // Pause // sc.Stop() + case 'u': + // Update + // NOTE: run the same routine for the form Update button here } return ev }) + + // Set the options form callbacks + err := SetFormButtonCallback(sc.StreamView.Options.Form, "Update", func() { + sc.updateStream() + }) + if err != nil { + // NOTE: what do we do here? + panic("Failed to set callback for streaming controller form update button") + } } func (sc *StreamingCtrl) Start() { @@ -77,13 +90,18 @@ func (sc *StreamingCtrl) Start() { isDrawing.Store(true) sc.App.QueueUpdateDraw(func() { - sc.StreamView.Update(&msg) + sc.StreamView.Visualizer.Update(&msg) isDrawing.Store(false) }) } }() } +// updateStream will get the new options from the form and update the state accordingly +func (sc *StreamingCtrl) updateStream() { + sc.Messages <- "Request to update stream received - parsing form" +} + // SetInternalState is used to update the stuff in here, for example, the user // goes into the layout tool, sets up the data to transmit to his devices and // then comes here to stream that data. We call this to set the fields the user diff --git a/tui/internal/views/layoutTool_forms.go b/tui/internal/views/layoutTool_forms.go index 378e244..a2a6373 100644 --- a/tui/internal/views/layoutTool_forms.go +++ b/tui/internal/views/layoutTool_forms.go @@ -87,6 +87,7 @@ func NewCreateWindowFormView() *CreateWindowFormView { Form: NewCDashDisplayWindowFormView(), } + // NOTE: is this variable actually used anywhere view.CreateBtn = tview.NewButton("Create") // Need to inject the button functionality later diff --git a/tui/internal/views/mainFlex.go b/tui/internal/views/mainFlex.go index d2115a4..95cefe7 100644 --- a/tui/internal/views/mainFlex.go +++ b/tui/internal/views/mainFlex.go @@ -51,9 +51,6 @@ type DeviceAPIListView struct { func NewDeviceAPIListView() *DeviceAPIListView { deviceAPIList := tview.NewList() - // AddItem("layout", "build a layout for CDashDisplay", 0, func() { - // layoutToolUIOnSelect(bus, doc) - // }) deviceAPIList.SetBorder(true).SetTitle("list") return &DeviceAPIListView{ @@ -75,40 +72,18 @@ func (dl *DeviceAPIListView) AddItem(name, description string, onSelect func()) } func NewDeviceAPIView() (*DeviceAPIView, error) { - // To build the main view we must set the DOM root mainFlex := tview.NewFlex().SetDirection(tview.FlexColumn) - // mainFlexUINode, err := doc.NewUINode(MainFlexID, nil, mainFlex) - // if err != nil { - // return nil, err - // } - // - // doc.SetRoot(mainFlexUINode) deviceAPIList := NewDeviceAPIListView() - // apiListWindowUINode, err := doc.NewUINode(DeviceAPIListID, doc.GetRootElem(), - // deviceAPIList.List) - // if err != nil { - // return nil, err - // } apiToolPages := NewDeviceAPIToolView() - // apiToolPagesNode, err := doc.NewUINode(APIToolPagesID, doc.GetElemByID(RightFlexID), - // apiToolPages.Pages) - // if err != nil { - // return nil, err - // } mainFlex. AddItem(deviceAPIList.List, 0, 1, false). AddItem(apiToolPages.Pages, 0, 4, false) // Output window - outputWin := NewOutputWinView() - // _, err = doc.NewUINode("output-window", nil, outputWin.TextArea) - // if err != nil { - // return nil, err - // } // Flex with debug window // -------------------------------------------------------------------------- diff --git a/tui/internal/views/stream.go b/tui/internal/views/stream.go index ddc8ca6..d3600e8 100644 --- a/tui/internal/views/stream.go +++ b/tui/internal/views/stream.go @@ -1,11 +1,13 @@ package views import ( - telem "esdi/telemetry" "fmt" "strings" "time" + "esdi/providers" + telem "esdi/telemetry" + "github.com/rivo/tview" ) @@ -17,20 +19,51 @@ const ( BrakeBiasLen = 6 ) -type StreamView struct { +// Form to select the game and whatnot ↓↓↓↓ + +// StreamOptionsView will be our view element to show the stream data +type StreamOptionsView struct { + Form *tview.Form + SimDropdown *tview.DropDown + UpdateBtn *tview.Button +} + +func NewStreamOptionsView() *StreamOptionsView { + sov := &StreamOptionsView{} + + sov.Form = tview.NewForm() + sov.Form.SetTitle("Stream Options").SetBorder(true) + + sov.SimDropdown = tview.NewDropDown().SetLabel("SIM").SetCurrentOption(0) + for _, prov := range providers.Providers { + sov.SimDropdown.AddOption(prov.Name, func() {}) + } + sov.Form.AddFormItem(sov.SimDropdown) + + // Inject callback on the controller + sov.Form.AddButton("Update", func() {}) + + return sov +} + +// Form to select the game and whatnot ↑↑↑↑ + +// Area to visualize what data is being passed to the game and whatnot ↓↓↓↓ + +type StreamVisualizerView struct { TextView *tview.TextView } -func NewStreamView() *StreamView { +func NewStreamVisualizerView() *StreamVisualizerView { tv := tview.NewTextView() - tv.SetTitle("Streaming Tool").SetBorder(true) + tv.SetTitle("Streaming Visualizer").SetBorder(true) - return &StreamView{ + return &StreamVisualizerView{ TextView: tv, } } -func (sv *StreamView) Update(data *telem.TelemetryData) { +func (sv *StreamVisualizerView) Update(data *telem.TelemetryData) { sv.TextView.SetText(stringify(data)) } @@ -49,3 +82,32 @@ func stringify(data *telem.TelemetryData) string { return buffer.String() } + +// Area to visualize what data is being passed to the game and whatnot ↑↑↑↑ + +// Stream Tool ↓↓↓↓ + +type StreamToolView struct { + Flex *tview.Flex + Options *StreamOptionsView + Visualizer *StreamVisualizerView +} + +func NewStreamToolView() *StreamToolView { + optionsView := NewStreamOptionsView() + visualizerView := NewStreamVisualizerView() + flex := tview.NewFlex().SetDirection(tview.FlexColumn) + flex.SetTitle("Streaming Tool") + + flex. + AddItem(optionsView.Form, 0, 2, true). + AddItem(visualizerView.TextView, 0, 5, true) + + return &StreamToolView{ + Flex: flex, + Options: optionsView, + Visualizer: visualizerView, + } +} + +// Stream Tool ↑↑↑↑