diff --git a/main.go b/main.go index f053734c89cdf444beb2dd215a455f71665937bd..9b01a6b9fbc05b7842cfa8b0485c7ddbae7a90d3 100644 --- a/main.go +++ b/main.go @@ -187,12 +187,20 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } // Check if we're editing an existing account + isEdit := false if login, ok := m.current.(*tui.Login); ok && login.IsEditMode() { - // Find and update the existing account + isEdit = true + // Find and update the existing account, preserving S/MIME settings existingID := login.GetAccountID() for i, acc := range m.config.Accounts { if acc.ID == existingID { account.ID = existingID + account.SMIMECert = acc.SMIMECert + account.SMIMEKey = acc.SMIMEKey + account.SMIMESignByDefault = acc.SMIMESignByDefault + if account.Password == "" { + account.Password = acc.Password + } m.config.Accounts[i] = account break } @@ -206,7 +214,11 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Quit } - m.current = tui.NewChoice() + if isEdit { + m.current = tui.NewSettings(m.config) + } else { + m.current = tui.NewChoice() + } m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height}) return m, m.current.Init() @@ -556,6 +568,24 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height}) return m, m.current.Init() + case tui.GoToEditAccountMsg: + hideTips := false + if m.config != nil { + hideTips = m.config.HideTips + } + login := tui.NewLogin(hideTips) + login.SetEditMode(msg.AccountID, msg.Provider, msg.Name, msg.Email, msg.FetchEmail, msg.IMAPServer, msg.IMAPPort, msg.SMTPServer, msg.SMTPPort) + m.current = login + m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height}) + return m, m.current.Init() + + case tui.GoToEditMailingListMsg: + editor := tui.NewMailingListEditor() + editor.SetEditMode(msg.Index, msg.Name, msg.Addresses) + m.current = editor + m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height}) + return m, m.current.Init() + case tui.SaveMailingListMsg: if m.config != nil { var addrs []string @@ -564,10 +594,17 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { addrs = append(addrs, trimmed) } } - m.config.MailingLists = append(m.config.MailingLists, config.MailingList{ - Name: msg.Name, - Addresses: addrs, - }) + if msg.EditIndex >= 0 && msg.EditIndex < len(m.config.MailingLists) { + m.config.MailingLists[msg.EditIndex] = config.MailingList{ + Name: msg.Name, + Addresses: addrs, + } + } else { + m.config.MailingLists = append(m.config.MailingLists, config.MailingList{ + Name: msg.Name, + Addresses: addrs, + }) + } if err := config.SaveConfig(m.config); err != nil { log.Printf("could not save config: %v", err) } diff --git a/tui/mailing_list.go b/tui/mailing_list.go index 5d18cbb1908e6c84d799fabb5715a5d464cdfd44..2a79da2cabb69daca4c136aafe23a566d5267adc 100644 --- a/tui/mailing_list.go +++ b/tui/mailing_list.go @@ -8,13 +8,15 @@ import ( "charm.land/lipgloss/v2" ) -// MailingListEditor displays the screen to add a new mailing list. +// MailingListEditor displays the screen to add or edit a mailing list. type MailingListEditor struct { - nameInput textinput.Model - addrInput textinput.Model - focus int // 0 = name, 1 = addresses - width int - height int + nameInput textinput.Model + addrInput textinput.Model + focus int // 0 = name, 1 = addresses + width int + height int + isEditMode bool + editIndex int // index of the mailing list being edited } // NewMailingListEditor creates a new mailing list editor model. @@ -27,12 +29,21 @@ func NewMailingListEditor() *MailingListEditor { addr.Placeholder = "e.g., alice@example.com, bob@example.com" return &MailingListEditor{ - nameInput: name, - addrInput: addr, - focus: 0, + nameInput: name, + addrInput: addr, + focus: 0, + editIndex: -1, } } +// SetEditMode sets the editor to edit an existing mailing list. +func (m *MailingListEditor) SetEditMode(index int, name, addresses string) { + m.isEditMode = true + m.editIndex = index + m.nameInput.SetValue(name) + m.addrInput.SetValue(addresses) +} + // Init initializes the mailing list editor model. func (m *MailingListEditor) Init() tea.Cmd { return textinput.Blink @@ -78,10 +89,12 @@ func (m *MailingListEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) { name := strings.TrimSpace(m.nameInput.Value()) addrs := strings.TrimSpace(m.addrInput.Value()) if name != "" && addrs != "" { + editIdx := m.editIndex return m, func() tea.Msg { return SaveMailingListMsg{ Name: name, Addresses: addrs, + EditIndex: editIdx, } } } @@ -100,7 +113,11 @@ func (m *MailingListEditor) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // View renders the mailing list editor screen. func (m *MailingListEditor) View() tea.View { - title := titleStyle.Render("Add Mailing List") + titleText := "Add Mailing List" + if m.isEditMode { + titleText = "Edit Mailing List" + } + title := titleStyle.Render(titleText) var nameView, addrView string if m.focus == 0 { diff --git a/tui/messages.go b/tui/messages.go index 49dacc941a9de8e60b58acd6912bc885ee8373ff..94d3da3af0b99c8531354e398f5a14c1c00e1f67 100644 --- a/tui/messages.go +++ b/tui/messages.go @@ -184,10 +184,31 @@ type GoToAddAccountMsg struct{} // GoToAddMailingListMsg signals navigation to the add mailing list screen. type GoToAddMailingListMsg struct{} -// SaveMailingListMsg signals that a new mailing list should be saved. +// GoToEditAccountMsg signals navigation to edit an existing account. +type GoToEditAccountMsg struct { + AccountID string + Provider string + Name string + Email string + FetchEmail string + IMAPServer string + IMAPPort int + SMTPServer string + SMTPPort int +} + +// GoToEditMailingListMsg signals navigation to edit an existing mailing list. +type GoToEditMailingListMsg struct { + Index int + Name string + Addresses string +} + +// SaveMailingListMsg signals that a new or edited mailing list should be saved. type SaveMailingListMsg struct { Name string Addresses string + EditIndex int // -1 means new, >= 0 means editing existing } // AddAccountMsg signals that a new account should be added. diff --git a/tui/settings.go b/tui/settings.go index 0f9aa7e4b57f63786fbf6cf86e8899ba6f258140..73b7f48ce99415911428b684760f7bd843aac1fc 100644 --- a/tui/settings.go +++ b/tui/settings.go @@ -200,6 +200,24 @@ func (m *Settings) updateAccounts(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { if m.cursor < len(m.cfg.Accounts) && len(m.cfg.Accounts) > 0 { m.confirmingDelete = true } + case "e": + // Edit selected account + if m.cursor < len(m.cfg.Accounts) { + acc := m.cfg.Accounts[m.cursor] + return m, func() tea.Msg { + return GoToEditAccountMsg{ + AccountID: acc.ID, + Provider: acc.ServiceProvider, + Name: acc.Name, + Email: acc.Email, + FetchEmail: acc.FetchEmail, + IMAPServer: acc.IMAPServer, + IMAPPort: acc.IMAPPort, + SMTPServer: acc.SMTPServer, + SMTPPort: acc.SMTPPort, + } + } + } case "enter": // If cursor is on "Add Account" if m.cursor == len(m.cfg.Accounts) { @@ -322,6 +340,19 @@ func (m *Settings) updateMailingLists(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) if m.cursor < len(m.cfg.MailingLists) && len(m.cfg.MailingLists) > 0 { m.confirmingDelete = true } + case "e": + // Edit selected mailing list + if m.cursor < len(m.cfg.MailingLists) { + list := m.cfg.MailingLists[m.cursor] + idx := m.cursor + return m, func() tea.Msg { + return GoToEditMailingListMsg{ + Index: idx, + Name: list.Name, + Addresses: strings.Join(list.Addresses, ", "), + } + } + } case "enter": if m.cursor == len(m.cfg.MailingLists) { return m, func() tea.Msg { return GoToAddMailingListMsg{} } @@ -500,7 +531,7 @@ func (m *Settings) viewAccounts() string { b.WriteString("\n") mainContent := b.String() - helpView := helpStyle.Render("↑/↓: navigate • enter: select • d: delete account • esc: back") + helpView := helpStyle.Render("↑/↓: navigate • enter: select • e: edit • d: delete • esc: back") if m.height > 0 { currentHeight := lipgloss.Height(docStyle.Render(mainContent + helpView)) @@ -629,7 +660,7 @@ func (m *Settings) viewMailingLists() string { } b.WriteString("\n") - helpView := helpStyle.Render("↑/↓: navigate • enter: select • d: delete • esc: back") + helpView := helpStyle.Render("↑/↓: navigate • enter: select • e: edit • d: delete • esc: back") mainContent := b.String() if m.height > 0 {