view.go
1 package main 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/charmbracelet/lipgloss" 8 ) 9 10 // View renders the entire UI 11 func (m model) View() string { 12 if !m.ready { 13 return "\n Initializing Kamaji TUI..." 14 } 15 16 var sb strings.Builder 17 18 // Header (empty for now, or could add ASCII art) 19 // sb.WriteString("\n") 20 21 // Message viewport 22 sb.WriteString(m.viewport.View()) 23 sb.WriteString("\n") 24 25 // Status bars 26 sb.WriteString(m.renderStatusBars()) 27 sb.WriteString("\n") 28 29 // Input area 30 sb.WriteString(m.renderInputArea()) 31 sb.WriteString("\n") 32 33 // Footer 34 sb.WriteString(m.renderFooter()) 35 36 return sb.String() 37 } 38 39 // renderStatusBars renders provider and shell status 40 func (m model) renderStatusBars() string { 41 // Provider status 42 providerText := fmt.Sprintf("🔧 %s: %s", m.provider, m.model) 43 providerBar := statusBarStyle.Render(providerText) 44 45 // Shell status 46 shellText := fmt.Sprintf("🐚 Shell: %s", m.shellCwd) 47 shellBar := statusBarStyle.Render(shellText) 48 49 // Combine 50 return lipgloss.JoinVertical( 51 lipgloss.Left, 52 providerBar, 53 shellBar, 54 ) 55 } 56 57 // renderInputArea renders the text input field 58 func (m model) renderInputArea() string { 59 if m.loading { 60 spinner := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} 61 frame := spinner[m.spinnerFrame%len(spinner)] 62 loading := lipgloss.NewStyle(). 63 Foreground(accentColor). 64 Bold(true). 65 Render(frame + " Agent is thinking...") 66 return statusBarStyle.Width(m.width).Render(loading) 67 } 68 return m.textarea.View() 69 } 70 71 // renderFooter renders keyboard shortcuts 72 func (m model) renderFooter() string { 73 shortcuts := "Ctrl+C: Quit | Enter: Send | PgUp/PgDn: Scroll" 74 return footerStyle.Render(shortcuts) 75 }