1package tui
2
3import (
4 "github.com/charmbracelet/bubbles/textinput"
5 tea "github.com/charmbracelet/bubbletea"
6 "github.com/charmbracelet/lipgloss"
7)
8
9// Login holds the state for the login form.
10type Login struct {
11 focusIndex int
12 inputs []textinput.Model
13}
14
15// NewLogin creates a new login model.
16func NewLogin() tea.Model {
17 m := Login{
18 inputs: make([]textinput.Model, 4), // Increased to 4 for provider, name, email, and password
19 }
20
21 var t textinput.Model
22 for i := range m.inputs {
23 t = textinput.New()
24 t.Cursor.Style = focusedStyle
25 t.CharLimit = 64
26
27 switch i {
28 case 0:
29 t.Placeholder = "Provider (gmail or icloud)"
30 t.Focus()
31 t.Prompt = "☁️ > "
32 case 1:
33 t.Placeholder = "Name"
34 t.Prompt = "👤 > "
35 case 2:
36 t.Placeholder = "Email"
37 t.Prompt = "✉️ > "
38 case 3:
39 t.Placeholder = "Password"
40 t.EchoMode = textinput.EchoPassword
41 t.Prompt = "🔑 > "
42 }
43 m.inputs[i] = t
44 }
45
46 return m
47}
48
49// Init initializes the login model.
50func (m Login) Init() tea.Cmd {
51 return textinput.Blink
52}
53
54// Update handles messages for the login model.
55func (m Login) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
56 switch msg := msg.(type) {
57 case tea.KeyMsg:
58 switch msg.Type {
59 // On Enter, if we are on the last field, submit the credentials.
60 case tea.KeyEnter:
61 if m.focusIndex == len(m.inputs)-1 {
62 return m, func() tea.Msg {
63 return Credentials{
64 Provider: m.inputs[0].Value(),
65 Name: m.inputs[1].Value(),
66 Email: m.inputs[2].Value(),
67 Password: m.inputs[3].Value(),
68 }
69 }
70 }
71 fallthrough
72 // Cycle focus between inputs.
73 case tea.KeyTab, tea.KeyShiftTab, tea.KeyUp, tea.KeyDown:
74 s := msg.String()
75 if s == "up" || s == "shift+tab" {
76 m.focusIndex--
77 } else {
78 m.focusIndex++
79 }
80
81 if m.focusIndex >= len(m.inputs) {
82 m.focusIndex = 0
83 } else if m.focusIndex < 0 {
84 m.focusIndex = len(m.inputs) - 1
85 }
86
87 cmds := make([]tea.Cmd, len(m.inputs))
88 for i := 0; i < len(m.inputs); i++ {
89 if i == m.focusIndex {
90 cmds[i] = m.inputs[i].Focus()
91 } else {
92 m.inputs[i].Blur()
93 }
94 }
95 return m, tea.Batch(cmds...)
96 }
97 }
98
99 // Update the focused input field.
100 var cmds = make([]tea.Cmd, len(m.inputs))
101 for i := range m.inputs {
102 m.inputs[i], cmds[i] = m.inputs[i].Update(msg)
103 }
104 return m, tea.Batch(cmds...)
105}
106
107// View renders the login form.
108func (m Login) View() string {
109 return lipgloss.JoinVertical(lipgloss.Left,
110 titleStyle.Render("Account Settings"),
111 "Update your credentials.",
112 m.inputs[0].View(),
113 m.inputs[1].View(),
114 m.inputs[2].View(),
115 m.inputs[3].View(),
116 helpStyle.Render("\nenter: save • tab: next field • esc: back to menu"),
117 )
118}