trash_archive.go

  1package tui
  2
  3import (
  4	"strings"
  5
  6	"charm.land/bubbles/v2/key"
  7	tea "charm.land/bubbletea/v2"
  8	"charm.land/lipgloss/v2"
  9	"github.com/floatpane/matcha/config"
 10	"github.com/floatpane/matcha/fetcher"
 11)
 12
 13var (
 14	mailboxTabStyle       = lipgloss.NewStyle().Padding(0, 3)
 15	activeMailboxTabStyle = lipgloss.NewStyle().Padding(0, 3).Foreground(lipgloss.Color("42")).Bold(true).Underline(true)
 16	mailboxTabBarStyle    = lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).PaddingBottom(1).MarginBottom(1)
 17)
 18
 19// TrashArchive is a combined view for trash and archive emails with a toggle
 20type TrashArchive struct {
 21	trashInbox   *Inbox
 22	archiveInbox *Inbox
 23	activeView   MailboxKind // MailboxTrash or MailboxArchive
 24	width        int
 25	height       int
 26	accounts     []config.Account
 27}
 28
 29// NewTrashArchive creates a new combined trash/archive view
 30func NewTrashArchive(trashEmails, archiveEmails []fetcher.Email, accounts []config.Account) *TrashArchive {
 31	return &TrashArchive{
 32		trashInbox:   NewTrashInbox(trashEmails, accounts),
 33		archiveInbox: NewArchiveInbox(archiveEmails, accounts),
 34		activeView:   MailboxTrash,
 35		accounts:     accounts,
 36	}
 37}
 38
 39func (m *TrashArchive) Init() tea.Cmd {
 40	return nil
 41}
 42
 43func (m *TrashArchive) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 44	switch msg := msg.(type) {
 45	case tea.KeyPressMsg:
 46		switch msg.String() {
 47		case "tab":
 48			// Toggle between trash and archive
 49			if m.activeView == MailboxTrash {
 50				m.activeView = MailboxArchive
 51			} else {
 52				m.activeView = MailboxTrash
 53			}
 54			return m, nil
 55		}
 56	case tea.WindowSizeMsg:
 57		m.width = msg.Width
 58		m.height = msg.Height
 59		// Pass to both inboxes
 60		m.trashInbox.Update(msg)
 61		m.archiveInbox.Update(msg)
 62		return m, nil
 63
 64	case FetchingMoreEmailsMsg, EmailsAppendedMsg, RefreshingEmailsMsg, EmailsRefreshedMsg:
 65		// Forward to the appropriate inbox based on mailbox
 66		if m.activeView == MailboxTrash {
 67			m.trashInbox.Update(msg)
 68		} else {
 69			m.archiveInbox.Update(msg)
 70		}
 71		return m, nil
 72	}
 73
 74	// Forward other messages to the active inbox
 75	var cmd tea.Cmd
 76	if m.activeView == MailboxTrash {
 77		_, cmd = m.trashInbox.Update(msg)
 78	} else {
 79		_, cmd = m.archiveInbox.Update(msg)
 80	}
 81	return m, cmd
 82}
 83
 84func (m *TrashArchive) View() tea.View {
 85	var b strings.Builder
 86
 87	// Render the mailbox toggle tabs
 88	var tabViews []string
 89	if m.activeView == MailboxTrash {
 90		tabViews = append(tabViews, activeMailboxTabStyle.Render("Trash"))
 91		tabViews = append(tabViews, mailboxTabStyle.Render("Archive"))
 92	} else {
 93		tabViews = append(tabViews, mailboxTabStyle.Render("Trash"))
 94		tabViews = append(tabViews, activeMailboxTabStyle.Render("Archive"))
 95	}
 96	tabBar := mailboxTabBarStyle.Render(lipgloss.JoinHorizontal(lipgloss.Top, tabViews...))
 97	b.WriteString(tabBar)
 98	b.WriteString("\n")
 99
100	// Add help text for tab switching
101	helpText := helpStyle.Render("Press tab to switch between Trash and Archive")
102	b.WriteString(helpText)
103	b.WriteString("\n\n")
104
105	// Render the active inbox
106	if m.activeView == MailboxTrash {
107		b.WriteString(m.trashInbox.View().Content)
108	} else {
109		b.WriteString(m.archiveInbox.View().Content)
110	}
111
112	return tea.NewView(b.String())
113}
114
115// GetActiveMailbox returns the currently active mailbox kind
116func (m *TrashArchive) GetActiveMailbox() MailboxKind {
117	return m.activeView
118}
119
120// GetActiveInbox returns the currently active inbox
121func (m *TrashArchive) GetActiveInbox() *Inbox {
122	if m.activeView == MailboxTrash {
123		return m.trashInbox
124	}
125	return m.archiveInbox
126}
127
128// RemoveEmail removes an email from the appropriate inbox
129func (m *TrashArchive) RemoveEmail(uid uint32, accountID string, mailbox MailboxKind) {
130	if mailbox == MailboxTrash {
131		m.trashInbox.RemoveEmail(uid, accountID)
132	} else if mailbox == MailboxArchive {
133		m.archiveInbox.RemoveEmail(uid, accountID)
134	}
135}
136
137// SetTrashEmails updates the trash emails
138func (m *TrashArchive) SetTrashEmails(emails []fetcher.Email, accounts []config.Account) {
139	m.trashInbox.SetEmails(emails, accounts)
140	m.accounts = accounts
141}
142
143// SetArchiveEmails updates the archive emails
144func (m *TrashArchive) SetArchiveEmails(emails []fetcher.Email, accounts []config.Account) {
145	m.archiveInbox.SetEmails(emails, accounts)
146	m.accounts = accounts
147}
148
149// AdditionalShortHelpKeys returns additional help keys for the trash/archive view
150func (m *TrashArchive) AdditionalShortHelpKeys() []key.Binding {
151	return []key.Binding{
152		key.NewBinding(key.WithKeys("tab"), key.WithHelp("tab", "switch view")),
153	}
154}