1package main
2
3import (
4 "fmt"
5 "log"
6 "os"
7 "time"
8
9 "github.com/andrinoff/email-cli/config"
10 "github.com/andrinoff/email-cli/sender"
11 "github.com/andrinoff/email-cli/tui"
12 tea "github.com/charmbracelet/bubbletea"
13)
14
15// mainModel now holds the state for the entire application.
16type mainModel struct {
17 current tea.Model
18 config *config.Config
19 width int
20 height int
21 err error
22}
23
24// newInitialModel now returns a pointer, which is crucial for state management.
25func newInitialModel(cfg *config.Config) *mainModel {
26 return &mainModel{
27 current: tui.NewChoice(),
28 config: cfg,
29 }
30}
31
32func (m *mainModel) Init() tea.Cmd {
33 return m.current.Init()
34}
35
36func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
37 var cmd tea.Cmd
38 var cmds []tea.Cmd
39
40 switch msg := msg.(type) {
41 case tea.WindowSizeMsg:
42 m.width = msg.Width
43 m.height = msg.Height
44 // Pass the window size message to the current view
45 m.current, cmd = m.current.Update(msg)
46 cmds = append(cmds, cmd)
47 return m, tea.Batch(cmds...)
48
49 case tea.KeyMsg:
50 if msg.String() == "ctrl+c" {
51 return m, tea.Quit
52 }
53 // Allow ESC to go back to the main menu
54 if msg.String() == "esc" {
55 if _, ok := m.current.(*tui.Choice); !ok {
56 m.current = tui.NewChoice()
57 return m, m.current.Init()
58 }
59 }
60
61 // --- Custom Messages for switching views ---
62 case tui.GoToInboxMsg:
63 m.current = tui.NewInbox()
64 // Manually set the size of the new view
65 m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
66 cmds = append(cmds, m.current.Init())
67
68 case tui.GoToSendMsg:
69 m.current = tui.NewComposer(m.config.Email)
70 m.current, _ = m.current.Update(tea.WindowSizeMsg{Width: m.width, Height: m.height})
71 cmds = append(cmds, m.current.Init())
72
73 case tui.ViewEmailMsg:
74 m.current = tui.NewEmailView(msg.Email, m.width, m.height)
75 cmds = append(cmds, m.current.Init())
76
77 case tui.SendEmailMsg:
78 m.current = tui.NewStatus("Sending email...")
79 cmds = append(cmds, m.current.Init(), sendEmail(m.config, msg))
80
81 case tui.EmailSentMsg:
82 m.current = tui.NewChoice()
83 cmds = append(cmds, m.current.Init())
84 }
85
86 // Pass all other messages to the current view
87 m.current, cmd = m.current.Update(msg)
88 cmds = append(cmds, cmd)
89
90 return m, tea.Batch(cmds...)
91}
92
93func (m *mainModel) View() string {
94 return m.current.View()
95}
96
97// sendEmail is a command that sends an email in the background.
98func sendEmail(cfg *config.Config, msg tui.SendEmailMsg) tea.Cmd {
99 return func() tea.Msg {
100 recipients := []string{msg.To}
101 err := sender.SendEmail(cfg, recipients, msg.Subject, msg.Body)
102 if err != nil {
103 log.Printf("Failed to send email: %v", err) // Log error
104 }
105 time.Sleep(1 * time.Second) // Give user time to see the "Sending" message
106 return tui.EmailSentMsg{}
107 }
108}
109
110func main() {
111 cfg, err := config.LoadConfig()
112 if err != nil {
113 log.Fatalf("could not load config: %v", err)
114 }
115
116 p := tea.NewProgram(newInitialModel(cfg), tea.WithAltScreen())
117
118 if _, err := p.Run(); err != nil {
119 fmt.Printf("Alas, there's been an error: %v", err)
120 os.Exit(1)
121 }
122}