inbox.go

  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}