Files
mail/history_cmd.go

188 lines
4.0 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"io"
"charm.land/bubbles/v2/list"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
)
type HistoryItem struct {
id int64
from string
to string
subject string
status string
createdAt string
sentAt string
}
func (h HistoryItem) FilterValue() string {
return fmt.Sprintf("%s %s %s", h.from, h.to, h.subject)
}
func (h HistoryItem) Title() string {
statusIcon := "📤"
if h.status == "draft" {
statusIcon = "📝"
}
return fmt.Sprintf("%s %s -> %s", statusIcon, h.from, h.to)
}
func (h HistoryItem) Description() string {
return h.subject
}
type HistoryModel struct {
list list.Model
items []HistoryItem
loading bool
err error
}
func runHistory() error {
m := NewHistoryModel()
m.loading = true
histories, err := GetEmailHistory("")
if err != nil {
m.err = err
m.loading = false
p := tea.NewProgram(m)
if _, err := p.Run(); err != nil {
return err
}
return nil
}
items := make([]list.Item, len(histories))
for i, h := range histories {
status := "sent"
if h.Status == "draft" {
status = "draft"
}
sentAtStr := ""
if h.SentAt != nil {
sentAtStr = h.SentAt.Format("2006-01-02 15:04")
}
items[i] = HistoryItem{
id: h.ID,
from: h.From,
to: h.To,
subject: h.Subject,
status: status,
createdAt: h.CreatedAt.Format("2006-01-02 15:04"),
sentAt: sentAtStr,
}
}
m.items = make([]HistoryItem, len(items))
for i := range items {
m.items[i] = items[i].(HistoryItem)
}
m.list.SetItems(items)
m.loading = false
p := tea.NewProgram(m)
if _, err := p.Run(); err != nil {
return fmt.Errorf("failed to run history: %w", err)
}
return nil
}
func NewHistoryModel() *HistoryModel {
l := list.New(nil, historyDelegate{}, 0, 10)
l.Title = "发送历史"
l.Styles.Title = historyTitleStyle
l.Styles.NoItems = historyNoItemsStyle
l.SetShowHelp(true)
l.SetShowPagination(false)
return &HistoryModel{
list: l,
items: []HistoryItem{},
}
}
func (m *HistoryModel) Init() tea.Cmd {
return nil
}
func (m *HistoryModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if msg.String() == "ctrl+c" {
return m, tea.Quit
}
case tea.WindowSizeMsg:
m.list.SetWidth(msg.Width)
}
var cmd tea.Cmd
m.list, cmd = m.list.Update(msg)
return m, cmd
}
func (m *HistoryModel) View() tea.View {
if m.loading {
return tea.NewView(historyLoadingStyle.Render("正在加载历史..."))
}
if m.err != nil {
return tea.NewView(historyErrorStyle.Render(fmt.Sprintf("错误: %v", m.err)))
}
if len(m.items) == 0 {
return tea.NewView(historyNoItemsStyle.Render("暂无发送历史"))
}
return tea.NewView(m.list.View())
}
var (
historyTitleStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("86")).
Bold(true)
historyNoItemsStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("241")).
Padding(1, 2)
historyLoadingStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("86")).
Padding(1, 2)
historyErrorStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("196")).
Padding(1, 2)
historyItemTitleStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("255"))
historyItemDescStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("241"))
)
type historyDelegate struct{}
func (d historyDelegate) Height() int { return 1 }
func (d historyDelegate) Spacing() int { return 0 }
func (d historyDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
func (d historyDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
h, ok := item.(HistoryItem)
if !ok {
return
}
isSelected := index == m.Index()
titleStyle := historyItemTitleStyle
descStyle := historyItemDescStyle
if isSelected {
titleStyle = titleStyle.Background(lipgloss.Color("68"))
descStyle = descStyle.Background(lipgloss.Color("68"))
}
fmt.Fprintf(w, "%s\n%s", titleStyle.Render(h.Title()), descStyle.Render(h.Description()))
}