Added status and prompt

This commit is contained in:
Leon Mika 2022-03-27 11:40:32 +11:00
parent b0909ffe4e
commit 81cd1d0971
5 changed files with 157 additions and 9 deletions

View file

@ -6,7 +6,6 @@ import (
"fmt"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/brianvoe/gofakeit/v6"
tea "github.com/charmbracelet/bubbletea"
"github.com/lmika/awstools/internal/common/ui/commandctrl"
"github.com/lmika/awstools/internal/common/ui/dispatcher"
@ -19,6 +18,7 @@ import (
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/modal"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/statusandprompt"
"github.com/lmika/gopkgs/cli"
"log"
"os"
@ -65,9 +65,12 @@ func main() {
_ = uiModel
// END TEMP
model := layout.FullScreen(layout.NewVBox(
frame.NewFrame("This is the header", layout.Model(newTestModel("this is the top"))),
frame.NewFrame("This is another header", layout.Model(newTestModel("this is the bottom"))),
model := layout.FullScreen(statusandprompt.New(
layout.NewVBox(
frame.NewFrame("This is the header", true, layout.Model(newTestModel("this is the top"))),
frame.NewFrame("This is another header", false, layout.Model(newTestModel("this is the bottom"))),
),
"Hello world",
))
//frameSet := frameset.New([]frameset.Frame{
@ -126,7 +129,9 @@ func newTestModel(descr string) tea.Model {
OnKeyPressed: func(k string) tea.Cmd {
log.Println("got key press: " + k)
if k == "enter" {
return modal.PushMode(newTestModel("this is mode " + gofakeit.CarModel() + " (press k to end)"))
return statusandprompt.Prompt("What is your car? ", func(val string) tea.Cmd {
return statusandprompt.SetStatus("Your car is = " + val)
})
} else if k == "k" {
return modal.PopMode
}

View file

@ -13,17 +13,22 @@ var (
Bold(true).
Foreground(lipgloss.Color("#ffffff")).
Background(lipgloss.Color("#4479ff"))
inactiveHeaderStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#000000")).
Background(lipgloss.Color("#d1d1d1"))
)
// Frame is a frame that appears in the
type Frame struct {
header string
active bool
model layout.ResizingModel
width int
}
func NewFrame(header string, model layout.ResizingModel) Frame {
return Frame{header, model, 0}
func NewFrame(header string, active bool, model layout.ResizingModel) Frame {
return Frame{header, active, model, 0}
}
func (f Frame) Init() tea.Cmd {
@ -31,6 +36,14 @@ func (f Frame) Init() tea.Cmd {
}
func (f Frame) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.(type) {
case tea.KeyMsg:
// If frame is not active, do not receive key messages
if !f.active {
return f, nil
}
}
newModel, cmd := f.model.Update(msg)
f.model = newModel.(layout.ResizingModel)
return f, cmd
@ -48,8 +61,13 @@ func (f Frame) Resize(w, h int) layout.ResizingModel {
}
func (f Frame) headerView() string {
style := inactiveHeaderStyle
if f.active {
style = activeHeaderStyle
}
titleText := f.header
title := activeHeaderStyle.Render(titleText)
line := activeHeaderStyle.Render(strings.Repeat(" ", utils.Max(0, f.width-lipgloss.Width(title))))
title := style.Render(titleText)
line := style.Render(strings.Repeat(" ", utils.Max(0, f.width-lipgloss.Width(title))))
return lipgloss.JoinHorizontal(lipgloss.Left, title, line)
}

View file

@ -0,0 +1,25 @@
package statusandprompt
import tea "github.com/charmbracelet/bubbletea"
type setStatusMsg string
type startPromptMsg struct {
prompt string
onDone func(val string) tea.Cmd
}
func SetStatus(newStatus string) tea.Cmd {
return func() tea.Msg {
return setStatusMsg(newStatus)
}
}
func Prompt(prompt string, onDone func(val string) tea.Cmd) tea.Cmd {
return func() tea.Msg {
return startPromptMsg{
prompt: prompt,
onDone: onDone,
}
}
}

View file

@ -0,0 +1,94 @@
package statusandprompt
import (
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/utils"
)
// StatusAndPrompt is a resizing model which displays a submodel and a status bar. When the start prompt
// event is received, focus will be torn away and the user will be given a prompt the enter text.
type StatusAndPrompt struct {
model layout.ResizingModel
statusMessage string
pendingInput *startPromptMsg
textInput textinput.Model
width int
}
func New(model layout.ResizingModel, initialMsg string) StatusAndPrompt {
textInput := textinput.New()
return StatusAndPrompt{model: model, statusMessage: initialMsg, textInput: textInput}
}
func (s StatusAndPrompt) Init() tea.Cmd {
return s.model.Init()
}
func (s StatusAndPrompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case setStatusMsg:
s.statusMessage = string(msg)
case startPromptMsg:
if s.pendingInput != nil {
// ignore, already in an input
return s, nil
}
s.textInput.Prompt = msg.prompt
s.textInput.Focus()
s.textInput.SetValue("")
s.pendingInput = &msg
return s, nil
case tea.KeyMsg:
if s.pendingInput != nil {
switch msg.String() {
case "ctrl+c", "esc":
s.pendingInput = nil
case "enter":
pendingInput := s.pendingInput
s.pendingInput = nil
return s, pendingInput.onDone(s.textInput.Value())
}
}
}
if s.pendingInput != nil {
var cc utils.CmdCollector
newTextInput, cmd := s.textInput.Update(msg)
cc.Add(cmd)
s.textInput = newTextInput
if _, isKey := msg.(tea.Key); !isKey {
s.model = cc.Collect(s.model.Update(msg)).(layout.ResizingModel)
}
return s, cc.Cmd()
}
newModel, cmd := s.model.Update(msg)
s.model = newModel.(layout.ResizingModel)
return s, cmd
}
func (s StatusAndPrompt) View() string {
return lipgloss.JoinVertical(lipgloss.Top, s.model.View(), s.viewStatus())
}
func (s StatusAndPrompt) Resize(w, h int) layout.ResizingModel {
s.width = w
submodelHeight := h - lipgloss.Height(s.viewStatus())
s.model = s.model.Resize(w, submodelHeight)
return s
}
func (s StatusAndPrompt) viewStatus() string {
if s.pendingInput != nil {
return s.textInput.View()
}
return s.statusMessage
}

View file

@ -6,6 +6,12 @@ type CmdCollector struct {
cmds []tea.Cmd
}
func (c *CmdCollector) Add(cmd tea.Cmd) {
if cmd != nil {
c.cmds = append(c.cmds, cmd)
}
}
func (c *CmdCollector) Collect(m tea.Model, cmd tea.Cmd) tea.Model {
if cmd != nil {
c.cmds = append(c.cmds, cmd)