package tui import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "git.tukangketik.id/swanadiva/hostkeeper/internal/models" ) // Styles for TUI components var ( TitleStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("86")).Bold(true) SubtitleStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241")) HighlightStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true) ErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("196")).Bold(true) SuccessStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("76")).Bold(true) InfoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("117")) ) // Screen represents different TUI screens type Screen int const ( ScreenHostList Screen = iota ScreenConnection ScreenSettings ) // Model represents the main TUI model type Model struct { CurrentScreen Screen Hosts []*models.Host SelectedIndex int Error error Quit bool } // New creates a new TUI model func New() *Model { return &Model{ CurrentScreen: ScreenHostList, SelectedIndex: 0, Quit: false, } } // Init initializes the TUI func (m *Model) Init() tea.Cmd { return nil } // Update handles messages and updates the model func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": m.Quit = true return m, tea.Quit case "up", "k": if m.SelectedIndex > 0 { m.SelectedIndex-- } case "down", "j": if m.SelectedIndex < len(m.Hosts)-1 { m.SelectedIndex++ } case "enter", " ": if len(m.Hosts) > 0 { return m, tea.Quit } } } return m, nil } // View renders the TUI func (m *Model) View() string { if m.Quit { return "Thanks for using hostkeeper!\n" } switch m.CurrentScreen { case ScreenHostList: return renderHostList(m) default: return "Screen not implemented yet" } } // LoadHosts loads hosts into the TUI model func (m *Model) LoadHosts(hosts []*models.Host) { m.Hosts = hosts if len(hosts) > 0 && m.SelectedIndex >= len(hosts) { m.SelectedIndex = len(hosts) - 1 } }