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