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}