Files
wrapped/pkg/ui/input_screen.go
2026-05-01 14:10:22 -06:00

190 lines
4.1 KiB
Go

package ui
import (
"fmt"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
type inputScreenState int
const (
urlInput inputScreenState = iota
usernameInput
tokenInput
connNameInput
)
type InputScreen struct {
urlField textinput.Model
usernameField textinput.Model
tokenField textinput.Model
connNameField textinput.Model
focusedField inputScreenState
err error
url string
username string
token string
connName string
done bool
}
func NewInputScreen() *InputScreen {
urlField := textinput.New()
urlField.Placeholder = "https://gitea.example.com"
urlField.Focus()
usernameField := textinput.New()
usernameField.Placeholder = "your_username"
tokenField := textinput.New()
tokenField.Placeholder = "your_access_token"
tokenField.EchoMode = textinput.EchoPassword
connNameField := textinput.New()
connNameField.Placeholder = "(optional) Connection name"
return &InputScreen{
urlField: urlField,
usernameField: usernameField,
tokenField: tokenField,
connNameField: connNameField,
focusedField: urlInput,
}
}
func (is *InputScreen) Init() tea.Cmd {
return textinput.Blink
}
func (is *InputScreen) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyCtrlC:
return is, tea.Quit
case tea.KeyEnter:
switch is.focusedField {
case urlInput:
is.url = is.urlField.Value()
is.focusedField = usernameInput
is.usernameField.Focus()
return is, nil
case usernameInput:
is.username = is.usernameField.Value()
is.focusedField = tokenInput
is.tokenField.Focus()
return is, nil
case tokenInput:
is.token = is.tokenField.Value()
is.focusedField = connNameInput
is.connNameField.Focus()
return is, nil
case connNameInput:
is.connName = is.connNameField.Value()
is.done = true
return is, nil
}
case tea.KeyTab, tea.KeyShiftTab:
switch is.focusedField {
case urlInput:
is.url = is.urlField.Value()
case usernameInput:
is.username = is.usernameField.Value()
case tokenInput:
is.token = is.tokenField.Value()
case connNameInput:
is.connName = is.connNameField.Value()
}
if msg.Type == tea.KeyTab {
is.focusedField = (is.focusedField + 1) % 4
} else {
is.focusedField = (is.focusedField - 1 + 4) % 4
}
is.urlField.Blur()
is.usernameField.Blur()
is.tokenField.Blur()
is.connNameField.Blur()
switch is.focusedField {
case urlInput:
is.urlField.Focus()
case usernameInput:
is.usernameField.Focus()
case tokenInput:
is.tokenField.Focus()
case connNameInput:
is.connNameField.Focus()
}
return is, nil
}
case errMsg:
is.err = msg
return is, nil
}
var cmd tea.Cmd
switch is.focusedField {
case urlInput:
is.urlField, cmd = is.urlField.Update(msg)
case usernameInput:
is.usernameField, cmd = is.usernameField.Update(msg)
case tokenInput:
is.tokenField, cmd = is.tokenField.Update(msg)
case connNameInput:
is.connNameField, cmd = is.connNameField.Update(msg)
}
return is, cmd
}
func (is *InputScreen) View() string {
var s string
s += lipgloss.NewStyle().
Foreground(lipgloss.Color("212")).
Bold(true).
Render("Gitea Wrapped") + "\n\n"
s += "Enter your Gitea credentials:\n\n"
s += "Gitea URL\n"
s += is.urlField.View() + "\n\n"
s += "Username\n"
s += is.usernameField.View() + "\n\n"
s += "Access Token\n"
s += is.tokenField.View() + "\n\n"
s += "Connection Name (optional - to save for later)\n"
s += is.connNameField.View() + "\n\n"
if is.err != nil {
s += lipgloss.NewStyle().
Foreground(lipgloss.Color("1")).
Render(fmt.Sprintf("Error: %v", is.err)) + "\n"
}
s += lipgloss.NewStyle().
Foreground(lipgloss.Color("8")).
Render("(Tab to navigate, Enter to continue, Ctrl+C to quit)") + "\n"
return s
}
func (is *InputScreen) IsDone() bool {
return is.done
}
func (is *InputScreen) GetCredentials() (url, username, token, connName string) {
return is.url, is.username, is.token, is.connName
}
type errMsg error