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", keyShiftTab, "up", keyDown:
 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 keyEnter:
 88			if m.focus == 0 {
 89				m.focus = 1
 90				m.nameInput.Blur()
 91				m.addrInput.Focus()
 92				return m, nil
 93			}
 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	if m.focus == 0 {
111		m.nameInput, cmd = m.nameInput.Update(msg)
112	} else {
113		m.addrInput, cmd = m.addrInput.Update(msg)
114	}
115
116	return m, cmd
117}
118
119// View renders the mailing list editor screen.
120func (m *MailingListEditor) View() tea.View {
121	titleText := "Add Mailing List"
122	if m.isEditMode {
123		titleText = "Edit Mailing List"
124	}
125	title := titleStyle.Render(titleText)
126
127	var nameView, addrView string
128	if m.focus == 0 {
129		nameView = focusedStyle.Render("Name:") + "\n" + m.nameInput.View()
130		addrView = blurredStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
131	} else {
132		nameView = blurredStyle.Render("Name:") + "\n" + m.nameInput.View()
133		addrView = focusedStyle.Render("Addresses (comma-separated):") + "\n" + m.addrInput.View()
134	}
135
136	return tea.NewView(lipgloss.JoinVertical(lipgloss.Left,
137		title,
138		"",
139		nameView,
140		"",
141		addrView,
142		"",
143		helpStyle.Render("tab/↑/↓: switch fields • enter: submit • esc: back"),
144	))
145}