1package main23import (4 "github.com/gdamore/tcell/v2"5)67type UserInterface struct {8 Mails []Mail9 Screen tcell.Screen10 index int11}1213const (14 // Rune used to indicate that the row has been abbreviated.15 abbreviated = '…'16)1718var (19 // Style used for non-selected rows.20 defStyle = tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)2122 // Style used for the currently selected row.23 selStyle = tcell.StyleDefault.Background(tcell.ColorWhite).Foreground(tcell.ColorBlack)24)2526func NewUI(mails []Mail, screen tcell.Screen) *UserInterface {27 return &UserInterface{28 Mails: mails,29 Screen: screen,30 index: 0,31 }32}3334func (ui *UserInterface) Refresh() error {35 var err error36 ui.Mails, err = mscan()37 if err != nil {38 return err39 }4041 // If the last mail was modified, the length of the sequence could42 // have been reduced by 1; therefore, we need to update the index.43 ui.index = min(ui.index, len(ui.Mails)-1)44 return nil45}4647func (ui *UserInterface) visible() int {48 _, ymax := ui.Screen.Size()49 return min(ymax, len(ui.Mails))50}5152func (ui *UserInterface) SelectedMail() Mail {53 return ui.Mails[ui.index]54}5556func (ui *UserInterface) IsSelected(m Mail) bool {57 selected := ui.SelectedMail()58 return selected.Path == m.Path59}6061func (ui *UserInterface) NextMail() {62 if ui.index < len(ui.Mails)-1 {63 ui.index++64 ui.Draw()65 }66}6768func (ui *UserInterface) PrevMail() {69 if ui.index > 0 {70 ui.index--71 ui.Draw()72 }73}7475func (ui *UserInterface) NextPage() {76 ui.index = min(len(ui.Mails)-1, ui.index+ui.visible())77 ui.Draw()78}7980func (ui *UserInterface) PrevPage() {81 visible := ui.visible()82 if ui.index > visible {83 ui.index = ui.index - visible84 } else {85 ui.index = 086 }87 ui.Draw()88}8990func (ui *UserInterface) Draw() {91 xmax, _ := ui.Screen.Size()92 if xmax <= 1 {93 panic("terminal is too small")94 }9596 mails := ui.Mails97 visible := ui.visible()98 if ui.index >= visible {99 start := ui.index - visible100 mails = ui.Mails[start+1:]101 }102103 y := 0104 for _, mail := range mails {105 text := mail.String()106107 var style tcell.Style108 if ui.IsSelected(mail) {109 style = selStyle110 } else {111 style = defStyle112 }113114 truncated := false115 if len(text) >= xmax {116 text = text[0 : len(text)-1]117 truncated = true118 }119 lastCol := drawText(ui.Screen, y, 0, style, text)120 if truncated {121 // TODO: Determine cells needed for abbreviated.122 ui.Screen.SetContent(xmax-1, y, abbreviated, nil, style)123 } else {124 for x := lastCol; x < xmax; x++ {125 ui.Screen.SetContent(x, y, ' ', nil, style)126 }127 }128129 y++130 if y >= visible {131 break132 }133 }134}135136func (ui *UserInterface) withoutScreen(fn func() error) error {137 ui.Screen.Fini()138 err := fn()139 if err != nil {140 return err141 }142143 ui.Screen, err = initScreen()144 if err != nil {145 return err146 }147 ui.Draw()148149 return nil150}