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 or edit a 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	isEditMode bool
 19	editIndex  int // index of the mailing list being edited
 20}
 21
 22// NewMailingListEditor creates a new mailing list editor model.
 23func NewMailingListEditor() *MailingListEditor {
 24	tiStyles := ThemedTextInputStyles()
 25
 26	name := textinput.New()
 27	name.Placeholder = "e.g., Team"
 28	name.SetStyles(tiStyles)
 29	name.Focus()
 30
 31	addr := textinput.New()
 32	addr.Placeholder = "e.g., alice@example.com, bob@example.com"
 33	addr.SetStyles(tiStyles)
 34
 35	return &MailingListEditor{
 36		nameInput: name,
 37		addrInput: addr,
 38		focus:     0,
 39		editIndex: -1,
 40	}
 41}
 42
 43// SetEditMode sets the editor to edit an existing mailing list.
 44func (m *MailingListEditor) SetEditMode(index int, name, addresses string) {
 45	m.isEditMode = true
 46	m.editIndex = index
 47	m.nameInput.SetValue(name)
 48	m.addrInput.SetValue(addresses)
 49}
 50
 51// Init initializes the mailing list editor model.
 52func (m *MailingListEditor) Init() tea.Cmd {
 53	return textinput.Blink
 54}
 55
 56// Update handles messages for the mailing list editor model.
 57func (m *MailingListEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 58	var cmd tea.Cmd
 59
 60	switch msg := msg.(type) {
 61	case tea.WindowSizeMsg:
 62		m.width = msg.Width
 63		m.height = msg.Height
 64		m.nameInput.SetWidth(msg.Width - 4)
 65		m.addrInput.SetWidth(msg.Width - 4)
 66		return m, nil
 67
 68	case tea.KeyPressMsg:
 69		switch msg.String() {
 70		case "ctrl+c":
 71			return m, tea.Quit
 72		case "esc":
 73			return m, func() tea.Msg { return GoToSettingsMsg{} }
 74		case "tab", "shift+tab", "up", "down":
 75			if m.focus == 0 {
 76				m.focus = 1
 77				m.nameInput.Blur()
 78				m.addrInput.Focus()
 79			} else {
 80				m.focus = 0
 81				m.addrInput.Blur()
 82				m.nameInput.Focus()
 83			}
 84			return m, nil
 85		case "enter":
 86			if m.focus == 0 {
 87				m.focus = 1
 88				m.nameInput.Blur()
 89				m.addrInput.Focus()
 90				return m, nil
 91			} else {
 92				// Submit on second field
 93				name := strings.TrimSpace(m.nameInput.Value())
 94				addrs := strings.TrimSpace(m.addrInput.Value())
 95				if name != "" && addrs != "" {
 96					editIdx := m.editIndex
 97					return m, func() tea.Msg {
 98						return SaveMailingListMsg{
 99							Name:      name,
100							Addresses: addrs,
101							EditIndex: editIdx,
102						}
103					}
104				}
105			}
106		}
107	}
108
109	if m.focus == 0 {
110		m.nameInput, cmd = m.nameInput.Update(msg)
111	} else {
112		m.addrInput, cmd = m.addrInput.Update(msg)
113	}
114
115	return m, cmd
116}
117
118// View renders the mailing list editor screen.
119func (m *MailingListEditor) View() tea.View {
120	titleText := "Add Mailing List"
121	if m.isEditMode {
122		titleText = "Edit Mailing List"
123	}
124	title := titleStyle.Render(titleText)
125
126	var nameView, addrView string
127	if m.focus == 0 {
128		nameView = focusedStyle.Render("Name:") + "\n" + m.nameInput.View()
129		addrView = blurredStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
130	} else {
131		nameView = blurredStyle.Render("Name:") + "\n" + m.nameInput.View()
132		addrView = focusedStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
133	}
134
135	return tea.NewView(lipgloss.JoinVertical(lipgloss.Left,
136		title,
137		"",
138		nameView,
139		"",
140		addrView,
141		"",
142		helpStyle.Render("tab/↑/↓: switch fields • enter: submit • esc: back"),
143	))
144}