@@ -0,0 +1,88 @@
1+package models
2+
3+import (
4+ "fmt"
5+ "strings"
6+
7+ "github.com/charmbracelet/bubbles/v2/textinput"
8+ tea "github.com/charmbracelet/bubbletea/v2"
9+ "github.com/charmbracelet/crush/internal/config"
10+ "github.com/charmbracelet/crush/internal/tui/styles"
11+ "github.com/charmbracelet/lipgloss/v2"
12+)
13+
14+type APIKeyInput struct {
15+ input textinput.Model
16+ width int
17+ height int
18+}
19+
20+func NewAPIKeyInput() *APIKeyInput {
21+ t := styles.CurrentTheme()
22+
23+ ti := textinput.New()
24+ ti.Placeholder = "Enter your API key..."
25+ ti.SetWidth(50)
26+ ti.SetVirtualCursor(false)
27+ ti.Prompt = "> "
28+ ti.SetStyles(t.S().TextInput)
29+ ti.Focus()
30+
31+ return &APIKeyInput{
32+ input: ti,
33+ width: 60,
34+ }
35+}
36+
37+func (a *APIKeyInput) Init() tea.Cmd {
38+ return textinput.Blink
39+}
40+
41+func (a *APIKeyInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
42+ switch msg := msg.(type) {
43+ case tea.WindowSizeMsg:
44+ a.width = msg.Width
45+ a.height = msg.Height
46+ }
47+
48+ var cmd tea.Cmd
49+ a.input, cmd = a.input.Update(msg)
50+ return a, cmd
51+}
52+
53+func (a *APIKeyInput) View() tea.View {
54+ t := styles.CurrentTheme()
55+
56+ title := t.S().Base.
57+ Foreground(t.Secondary).
58+ Bold(true).
59+ Render("Enter your Anthropic API Key")
60+
61+ inputView := a.input.View()
62+
63+ dataPath := config.GlobalConfigData()
64+ dataPath = strings.Replace(dataPath, config.HomeDir(), "~", 1)
65+ helpText := t.S().Muted.
66+ Render(fmt.Sprintf("This will be written to the global configuration: %s", dataPath))
67+
68+ content := lipgloss.JoinVertical(
69+ lipgloss.Left,
70+ title,
71+ "",
72+ inputView,
73+ "",
74+ helpText,
75+ )
76+
77+ view := tea.NewView(content)
78+ cursor := a.input.Cursor()
79+ if cursor != nil {
80+ cursor.Y += 2 // Adjust for title and spacing
81+ }
82+ view.SetCursor(cursor)
83+ return view
84+}
85+
86+func (a *APIKeyInput) Value() string {
87+ return a.input.Value()
88+}