1
2
3package tui
4
5import (
6 "fmt"
7 "strings"
8
9 "github.com/andrinoff/email-cli/config"
10 "github.com/andrinoff/email-cli/fetcher"
11 "github.com/charmbracelet/bubbles/list"
12 "github.com/charmbracelet/bubbles/spinner"
13 tea "github.com/charmbracelet/bubbletea"
14 "github.com/charmbracelet/lipgloss"
15)
16
17type inboxModel struct {
18 spinner spinner.Model
19 loading bool
20 emails []fetcher.Email
21 list list.Model
22 err error
23 config *config.Config
24 selected bool
25}
26
27func (m inboxModel) Init() tea.Cmd {
28 return m.spinner.Tick
29}
30
31func (m inboxModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
32 switch msg := msg.(type) {
33 case tea.KeyMsg:
34 if msg.String() == "ctrl+c" || msg.String() == "q" {
35 return m, tea.Quit
36 }
37 if msg.String() == "enter" {
38 m.selected = true
39 return m, nil
40 }
41 case tea.WindowSizeMsg:
42 h, v := DialogBoxStyle.GetFrameSize()
43 m.list.SetSize(msg.Width-h, msg.Height-v)
44 case []fetcher.Email:
45 m.loading = false
46 m.emails = msg
47 items := make([]list.Item, len(m.emails))
48 for i, email := range m.emails {
49 items[i] = item{
50 title: email.Subject,
51 desc: fmt.Sprintf("From: %s", email.From),
52 }
53 }
54 m.list.SetItems(items)
55
56 case error:
57 m.err = msg
58 return m, nil
59 }
60
61 var cmd tea.Cmd
62 if m.loading {
63 m.spinner, cmd = m.spinner.Update(msg)
64 } else {
65 m.list, cmd = m.list.Update(msg)
66 }
67 return m, cmd
68}
69
70func (m inboxModel) View() string {
71 if m.err != nil {
72 return InfoStyle.Render(fmt.Sprintf("\n Error: %v \n\n Press any key to exit.", m.err))
73 }
74 if m.loading {
75 return InfoStyle.Render(fmt.Sprintf("\n %s Fetching emails... \n\n", m.spinner.View()))
76 }
77 if m.selected {
78 i, ok := m.list.SelectedItem().(item)
79 if !ok {
80 return "error"
81 }
82 var selectedEmail fetcher.Email
83 for _, email := range m.emails {
84 if email.Subject == i.Title() {
85 selectedEmail = email
86 break
87 }
88 }
89 var s strings.Builder
90 s.WriteString(fmt.Sprintf("From: %s\n", selectedEmail.From))
91 s.WriteString(fmt.Sprintf("Subject: %s\n", selectedEmail.Subject))
92 s.WriteString(fmt.Sprintf("Date: %s\n\n", selectedEmail.Date.Format("2006-01-02 15:04:05")))
93 s.WriteString(selectedEmail.Body)
94 s.WriteString(HelpStyle.Render("\n\n(q to quit)"))
95 return DialogBoxStyle.Render(s.String())
96
97 }
98 return DialogBoxStyle.Render(m.list.View())
99}
100
101func initialInboxModel(cfg *config.Config) inboxModel {
102 s := spinner.New()
103 s.Spinner = spinner.Dot
104 s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
105 l := list.New([]list.Item{}, list.NewDefaultDelegate(), 0, 0)
106 l.Title = "Inbox"
107 l.Styles.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).Bold(true)
108 return inboxModel{
109 spinner: s,
110 loading: true,
111 config: cfg,
112 list: l,
113 }
114}
115
116func RunInbox(cfg *config.Config) error {
117 m := initialInboxModel(cfg)
118 p := tea.NewProgram(m, tea.WithAltScreen())
119
120 go func() {
121 emails, err := fetcher.FetchEmails(cfg)
122 if err != nil {
123 p.Send(err)
124 }
125 p.Send(emails)
126 }()
127
128 _, err := p.Run()
129 return err
130}