1package tui
2
3import (
4 "github.com/charmbracelet/bubbles/textinput"
5 tea "github.com/charmbracelet/bubbletea"
6 "github.com/charmbracelet/lipgloss"
7)
8
9type Composer struct {
10 focusIndex int
11 inputs []textinput.Model
12 fromAddr string
13}
14
15func NewComposer(from string) Composer {
16 m := Composer{
17 inputs: make([]textinput.Model, 3),
18 fromAddr: from,
19 }
20
21 var t textinput.Model
22 for i := range m.inputs {
23 t = textinput.New()
24 t.Cursor.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
25 t.CharLimit = 0 // no limit
26
27 switch i {
28 case 0:
29 t.Placeholder = "To"
30 t.Focus()
31 t.Prompt = "> "
32 case 1:
33 t.Placeholder = "Subject"
34 t.Prompt = "> "
35 case 2:
36 t.Placeholder = "Body..."
37 t.Prompt = "> "
38 }
39 m.inputs[i] = t
40 }
41 return m
42}
43
44func (m Composer) Init() tea.Cmd {
45 return textinput.Blink
46}
47
48func (m Composer) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
49 switch msg := msg.(type) {
50 case tea.KeyMsg:
51 s := msg.String()
52 switch s {
53 case "tab", "shift+tab", "enter", "up", "down":
54 if s == "enter" {
55 // If we're on the last input, send the email
56 if m.focusIndex == len(m.inputs)-1 {
57 return m, func() tea.Msg {
58 return SendEmailMsg{
59 To: m.inputs[0].Value(),
60 Subject: m.inputs[1].Value(),
61 Body: m.inputs[2].Value(),
62 }
63 }
64 }
65 }
66
67 // Cycle focus
68 if s == "up" || s == "shift+tab" {
69 m.focusIndex--
70 } else {
71 m.focusIndex++
72 }
73
74 if m.focusIndex > len(m.inputs)-1 {
75 m.focusIndex = 0
76 } else if m.focusIndex < 0 {
77 m.focusIndex = len(m.inputs) - 1
78 }
79
80 cmds := make([]tea.Cmd, len(m.inputs))
81 for i := 0; i < len(m.inputs); i++ {
82 if i == m.focusIndex {
83 cmds[i] = m.inputs[i].Focus()
84 } else {
85 m.inputs[i].Blur()
86 }
87 }
88 return m, tea.Batch(cmds...)
89 }
90 }
91
92 // Update the focused input
93 cmd := m.updateInputs(msg)
94 return m, cmd
95}
96
97func (m *Composer) updateInputs(msg tea.Msg) tea.Cmd {
98 var cmds = make([]tea.Cmd, len(m.inputs))
99 for i := range m.inputs {
100 m.inputs[i], cmds[i] = m.inputs[i].Update(msg)
101 }
102 return tea.Batch(cmds...)
103}
104
105func (m Composer) View() string {
106 return lipgloss.JoinVertical(
107 lipgloss.Left,
108 "Compose Email (Press Enter on Body to Send)",
109 m.inputs[0].View(),
110 m.inputs[1].View(),
111 m.inputs[2].View(),
112 )
113}