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