tui: Add setting view with support for changing the current model
This commit is contained in:
137
pkg/tui/views/settings/settings.go
Normal file
137
pkg/tui/views/settings/settings.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/bubbles/list"
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/model"
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/shared"
|
||||
"git.mlow.ca/mlow/lmcli/pkg/tui/styles"
|
||||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
App *model.AppModel
|
||||
prevView shared.View
|
||||
content viewport.Model
|
||||
modelList list.Model
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
type modelOpt struct {
|
||||
provider string
|
||||
model string
|
||||
}
|
||||
|
||||
const (
|
||||
modelListId int = iota + 1
|
||||
)
|
||||
|
||||
func Settings(app *model.AppModel) *Model {
|
||||
m := &Model{
|
||||
App: app,
|
||||
content: viewport.New(0, 0),
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Model) Init() tea.Cmd {
|
||||
m.modelList = list.NewWithGroups(m.getModelOptions())
|
||||
m.modelList.ID = modelListId
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
m.modelList, cmd = m.modelList.Update(msg)
|
||||
if cmd != nil {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
switch msg.String() {
|
||||
case "esc":
|
||||
return m, func() tea.Msg {
|
||||
return shared.MsgViewChange(m.prevView)
|
||||
}
|
||||
}
|
||||
case shared.MsgViewEnter:
|
||||
m.prevView = shared.View(msg)
|
||||
m.modelList.Focus()
|
||||
m.content.SetContent(m.renderContent())
|
||||
case tea.WindowSizeMsg:
|
||||
m.width, m.height = msg.Width, msg.Height
|
||||
m.content.Width = msg.Width
|
||||
m.content.Height = msg.Height
|
||||
m.content.SetContent(m.renderContent())
|
||||
case list.MsgOptionSelected:
|
||||
switch msg.ID {
|
||||
case modelListId:
|
||||
if modelOpt, ok := msg.Option.Value.(modelOpt); ok {
|
||||
m.App.Model = modelOpt.model
|
||||
m.App.ProviderName = modelOpt.provider
|
||||
}
|
||||
return m, shared.ChangeView(m.prevView)
|
||||
}
|
||||
}
|
||||
|
||||
m.modelList, cmd = m.modelList.Update(msg)
|
||||
if cmd != nil {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
m.content.SetContent(m.renderContent())
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Model) getModelOptions() []list.OptionGroup {
|
||||
modelOpts := []list.OptionGroup{}
|
||||
for _, p := range m.App.Ctx.Config.Providers {
|
||||
provider := p.Name
|
||||
if provider == "" {
|
||||
provider = p.Kind
|
||||
}
|
||||
providerLabel := p.Display
|
||||
if providerLabel == "" {
|
||||
providerLabel = strings.ToUpper(provider[:1]) + provider[1:]
|
||||
}
|
||||
group := list.OptionGroup{
|
||||
Name: providerLabel,
|
||||
}
|
||||
for _, model := range p.Models {
|
||||
group.Options = append(group.Options, list.Option{
|
||||
Label: model,
|
||||
Value: modelOpt{provider, model},
|
||||
})
|
||||
}
|
||||
modelOpts = append(modelOpts, group)
|
||||
}
|
||||
return modelOpts
|
||||
}
|
||||
|
||||
func (m *Model) Header(width int) string {
|
||||
boldStyle := lipgloss.NewStyle().Bold(true)
|
||||
// TODO: update header depending on active settings mode (model, agent, etc)
|
||||
header := boldStyle.Render("Model selection")
|
||||
return styles.Header.Width(width).Render(header)
|
||||
}
|
||||
|
||||
func (m *Model) Content(width, height int) string {
|
||||
// TODO: see Header()
|
||||
currentModel := " Active model: " + m.App.ActiveModel(lipgloss.NewStyle())
|
||||
m.modelList.Width, m.modelList.Height = width, height - 2
|
||||
return "\n" + currentModel + "\n" + m.modelList.View()
|
||||
}
|
||||
|
||||
func (m *Model) Footer(width int) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Model) renderContent() string {
|
||||
return m.modelList.View()
|
||||
}
|
||||
Reference in New Issue
Block a user