mailing_list.go

  1package tui
  2
  3import (
  4	"strings"
  5
  6	"charm.land/bubbles/v2/textinput"
  7	tea "charm.land/bubbletea/v2"
  8	"charm.land/lipgloss/v2"
  9)
 10
 11// MailingListEditor displays the screen to add a new mailing list.
 12type MailingListEditor struct {
 13	nameInput textinput.Model
 14	addrInput textinput.Model
 15	focus     int // 0 = name, 1 = addresses
 16	width     int
 17	height    int
 18}
 19
 20// NewMailingListEditor creates a new mailing list editor model.
 21func NewMailingListEditor() *MailingListEditor {
 22	name := textinput.New()
 23	name.Placeholder = "e.g., Team"
 24	name.Focus()
 25
 26	addr := textinput.New()
 27	addr.Placeholder = "e.g., alice@example.com, bob@example.com"
 28
 29	return &MailingListEditor{
 30		nameInput: name,
 31		addrInput: addr,
 32		focus:     0,
 33	}
 34}
 35
 36// Init initializes the mailing list editor model.
 37func (m *MailingListEditor) Init() tea.Cmd {
 38	return textinput.Blink
 39}
 40
 41// Update handles messages for the mailing list editor model.
 42func (m *MailingListEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 43	var cmd tea.Cmd
 44
 45	switch msg := msg.(type) {
 46	case tea.WindowSizeMsg:
 47		m.width = msg.Width
 48		m.height = msg.Height
 49		m.nameInput.SetWidth(msg.Width - 4)
 50		m.addrInput.SetWidth(msg.Width - 4)
 51		return m, nil
 52
 53	case tea.KeyPressMsg:
 54		switch msg.String() {
 55		case "ctrl+c":
 56			return m, tea.Quit
 57		case "esc":
 58			return m, func() tea.Msg { return GoToSettingsMsg{} }
 59		case "tab", "shift+tab", "up", "down":
 60			if m.focus == 0 {
 61				m.focus = 1
 62				m.nameInput.Blur()
 63				m.addrInput.Focus()
 64			} else {
 65				m.focus = 0
 66				m.addrInput.Blur()
 67				m.nameInput.Focus()
 68			}
 69			return m, nil
 70		case "enter":
 71			if m.focus == 0 {
 72				m.focus = 1
 73				m.nameInput.Blur()
 74				m.addrInput.Focus()
 75				return m, nil
 76			} else {
 77				// Submit on second field
 78				name := strings.TrimSpace(m.nameInput.Value())
 79				addrs := strings.TrimSpace(m.addrInput.Value())
 80				if name != "" && addrs != "" {
 81					return m, func() tea.Msg {
 82						return SaveMailingListMsg{
 83							Name:      name,
 84							Addresses: addrs,
 85						}
 86					}
 87				}
 88			}
 89		}
 90	}
 91
 92	if m.focus == 0 {
 93		m.nameInput, cmd = m.nameInput.Update(msg)
 94	} else {
 95		m.addrInput, cmd = m.addrInput.Update(msg)
 96	}
 97
 98	return m, cmd
 99}
100
101// View renders the mailing list editor screen.
102func (m *MailingListEditor) View() tea.View {
103	title := titleStyle.Render("Add Mailing List")
104
105	var nameView, addrView string
106	if m.focus == 0 {
107		nameView = focusedStyle.Render("Name:") + "\n" + m.nameInput.View()
108		addrView = blurredStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
109	} else {
110		nameView = blurredStyle.Render("Name:") + "\n" + m.nameInput.View()
111		addrView = focusedStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
112	}
113
114	return tea.NewView(lipgloss.JoinVertical(lipgloss.Left,
115		title,
116		"",
117		nameView,
118		"",
119		addrView,
120		"",
121		helpStyle.Render("tab/↑/↓: switch fields • enter: submit • esc: back"),
122	))
123}