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}