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