tui: add response waiting spinner

This commit is contained in:
Matt Low 2024-03-14 05:58:31 +00:00
parent 41916eb7b3
commit 3756f6d9e4

View File

@ -11,10 +11,12 @@ import (
"context"
"fmt"
"strings"
"time"
cmdutil "git.mlow.ca/mlow/lmcli/pkg/cmd/util"
"git.mlow.ca/mlow/lmcli/pkg/lmcli"
models "git.mlow.ca/mlow/lmcli/pkg/lmcli/model"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
@ -53,6 +55,7 @@ type model struct {
// ui elements
content viewport.Model
input textarea.Model
spinner spinner.Model
}
type message struct {
@ -97,6 +100,7 @@ var (
func (m model) Init() tea.Cmd {
return tea.Batch(
textarea.Blink,
m.spinner.Tick,
m.loadConversation(m.convShortname),
m.waitForChunk(),
m.waitForReply(),
@ -218,22 +222,28 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.err = error(msg)
}
if len(cmds) > 0 {
return m, tea.Batch(cmds...)
}
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
if cmd != nil {
cmds = append(cmds, cmd)
}
inputCaptured := false
m.input, cmd = m.input.Update(msg)
if cmd != nil {
return m, cmd
inputCaptured = true
cmds = append(cmds, cmd)
}
m.content, cmd = m.content.Update(msg)
if cmd != nil {
return m, cmd
if !inputCaptured {
m.content, cmd = m.content.Update(msg)
if cmd != nil {
cmds = append(cmds, cmd)
}
}
return m, cmd
return m, tea.Batch(cmds...)
}
func (m model) View() string {
@ -343,9 +353,14 @@ func (m *model) footerView() string {
saving = segmentStyle.Copy().Bold(true).Foreground(lipgloss.Color("1")).Render("❌💾")
}
status := m.status
if m.waitingForReply {
status += m.spinner.View()
}
leftSegments := []string{
saving,
segmentStyle.Render(m.status),
segmentStyle.Render(status),
}
rightSegments := []string{
segmentStyle.Render(fmt.Sprintf("Model: %s", *m.ctx.Config.Defaults.Model)),
@ -391,7 +406,19 @@ func initialModel(ctx *lmcli.Context, convShortname string) model {
m.input.SetHeight(4)
m.input.Focus()
m.updateContent()
m.spinner = spinner.New(spinner.WithSpinner(
spinner.Spinner{
Frames: []string{
". ",
".. ",
"...",
".. ",
". ",
" ",
},
FPS: time.Second / 3,
},
))
m.waitingForReply = false
m.status = "Press ctrl+s to send"
@ -453,7 +480,7 @@ func (m *model) handleInputKey(msg tea.KeyMsg) tea.Cmd {
m.content.GotoBottom()
m.waitingForReply = true
m.status = "Waiting for response, press ctrl+c to cancel..."
m.status = "Press ctrl+c to cancel"
return m.promptLLM()
}
return nil