feat: wire state form update/view into settings dispatch

This commit is contained in:
Taybin Rutkin 2026-07-22 10:18:37 -04:00
parent d44b8c32eb
commit 4f1e159309
No known key found for this signature in database
GPG key ID: 605FA2C570B6AC9E
3 changed files with 106 additions and 0 deletions

View file

@ -41,6 +41,8 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.updateSettingsAddTag(msg) return m.updateSettingsAddTag(msg)
case modeSettingsAddState: case modeSettingsAddState:
return m.updateSettingsAddState(msg) return m.updateSettingsAddState(msg)
case modeSettingsStateForm:
return m.updateSettingsStateForm(msg)
case modeTagEdit: case modeTagEdit:
return m.updateTagEdit(msg) return m.updateTagEdit(msg)
case modeRename: case modeRename:

View file

@ -5,6 +5,8 @@ import (
"strings" "strings"
"github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
) )
// stateForm backs the add/edit state form (modeSettingsStateForm). // stateForm backs the add/edit state form (modeSettingsStateForm).
@ -114,3 +116,103 @@ func (m *uiModel) applyStateForm() bool {
m.setStatus(fmt.Sprintf("Added state '%s' (saved)", name)) m.setStatus(fmt.Sprintf("Added state '%s' (saved)", name))
return true return true
} }
// updateSettingsStateForm handles key input while the state form is open.
func (m *uiModel) updateSettingsStateForm(msg tea.Msg) (tea.Model, tea.Cmd) {
keyMsg, ok := msg.(tea.KeyMsg)
if !ok {
return m, nil
}
switch keyMsg.Type {
case tea.KeyEsc:
m.mode = modeSettings
return m, nil
case tea.KeyEnter:
if m.applyStateForm() {
if err := m.config.Save(); err != nil {
m.setStatus(fmt.Sprintf("Error auto-saving config: %v", err))
} else {
m.keys = newKeyMapFromConfig(m.config)
m.styles = newStyleMapFromConfig(m.config)
}
m.mode = modeSettings
}
return m, nil
case tea.KeyTab, tea.KeyDown:
m.moveStateFormField(1)
return m, nil
case tea.KeyShiftTab, tea.KeyUp:
m.moveStateFormField(-1)
return m, nil
case tea.KeySpace:
if m.stateForm.field == 2 {
m.stateForm.done = !m.stateForm.done
return m, nil
}
}
// Route printable input to the focused text field.
var cmd tea.Cmd
switch m.stateForm.field {
case 0:
m.stateForm.name, cmd = m.stateForm.name.Update(msg)
case 1:
m.stateForm.color, cmd = m.stateForm.color.Update(msg)
}
return m, cmd
}
// viewSettingsStateForm renders the add/edit state form.
func (m *uiModel) viewSettingsStateForm() string {
var b strings.Builder
title := "Add New State"
if m.stateForm.editing {
title = "Edit State: " + m.config.States.States[m.stateForm.index].Name
}
b.WriteString(m.styles.titleStyle.Render(title) + "\n\n")
cursor := func(field int) string {
if m.stateForm.field == field {
return "▶ "
}
return " "
}
// Name row: editable input when adding, read-only label when editing.
if m.stateForm.editing {
b.WriteString(" Name " + m.stateForm.name.Value() + m.styles.statusStyle.Render(" (fixed)") + "\n")
} else {
b.WriteString(cursor(0) + "Name " + m.stateForm.name.View() + "\n")
}
// Color row with a live swatch.
colorVal := strings.TrimSpace(m.stateForm.color.Value())
swatch := ""
if colorVal != "" {
label := m.stateForm.name.Value()
if label == "" {
label = "sample"
}
sw := lipgloss.NewStyle().Foreground(lipgloss.Color(colorVal))
swatch = " " + sw.Render("●"+label)
}
b.WriteString(cursor(1) + "Color " + m.stateForm.color.View() + swatch + "\n")
// Done row: a checkbox.
box := "[ ] no"
if m.stateForm.done {
box = "[✓] yes"
}
b.WriteString(cursor(2) + "Done " + box + "\n\n")
b.WriteString(m.styles.statusStyle.Render(
"tab/↑↓: move field • space: toggle done • enter: save • esc: cancel") + "\n")
return b.String()
}

View file

@ -92,6 +92,8 @@ func (m uiModel) View() string {
return m.viewSettingsAddTag() return m.viewSettingsAddTag()
case modeSettingsAddState: case modeSettingsAddState:
return m.viewSettingsAddState() return m.viewSettingsAddState()
case modeSettingsStateForm:
return m.viewSettingsStateForm()
case modeTagEdit: case modeTagEdit:
return m.viewTagEdit() return m.viewTagEdit()
case modeRename: case modeRename: