package components import ( "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) // ConfigDisplayModel represents a configuration display modal type ConfigDisplayModel struct { config string viewport viewport.Model Visible bool Width int Height int scrollPos int } // Styles var ( configModalStyle = lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(lipgloss.Color("62")). Padding(1, 2). Background(lipgloss.Color("235")) configTitleStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("62")). Bold(true). MarginBottom(1) configHelpStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("241")). MarginTop(1) configContentStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("255")). Width(76) ) // NewConfigDisplay creates a new configuration display modal func NewConfigDisplay(config string, width, height int) *ConfigDisplayModel { vp := viewport.New(76, 24) vp.SetContent(config) return &ConfigDisplayModel{ config: config, viewport: vp, Visible: true, Width: width, Height: height, scrollPos: 0, } } // Init initializes the configuration display modal func (m *ConfigDisplayModel) Init() tea.Cmd { return nil } // Update handles messages for the configuration display modal func (m *ConfigDisplayModel) Update(msg tea.Msg) (*ConfigDisplayModel, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "esc", "q": m.Visible = false return m, nil case "up", "k": m.viewport.LineUp(1) case "down", "j": m.viewport.LineDown(1) case "pgup", "b": m.viewport.HalfViewUp() case "pgdown", "f", " ": m.viewport.HalfViewDown() case "g", "home": m.viewport.GotoTop() case "G", "end": m.viewport.GotoBottom() } case tea.WindowSizeMsg: // Update modal dimensions on resize m.Width = msg.Width m.Height = msg.Height } var cmd tea.Cmd m.viewport, cmd = m.viewport.Update(msg) return m, cmd } // View renders the configuration display modal func (m *ConfigDisplayModel) View() string { if !m.Visible { return "" } // Build modal content title := configTitleStyle.Render("📋 Client Configuration") content := m.viewport.View() help := configHelpStyle.Render("↑/j: down • ↓/k: up • pgup/pgdn: page • g/G: top/bottom • Esc: close") fullContent := lipgloss.JoinVertical( lipgloss.Left, title, "", content, help, ) // Apply modal style modal := configModalStyle.Render(fullContent) // Center modal on screen modalWidth := lipgloss.Width(modal) modalHeight := lipgloss.Height(modal) x := (m.Width - modalWidth) / 2 if x < 0 { x = 0 } y := (m.Height - modalHeight) / 2 if y < 0 { y = 0 } return lipgloss.Place(m.Width, m.Height, lipgloss.Left, lipgloss.Top, modal, lipgloss.WithWhitespaceChars(" "), lipgloss.WithWhitespaceForeground(lipgloss.Color("235")), ) } // IsVisible returns true if the modal is visible func (m *ConfigDisplayModel) IsVisible() bool { return m.Visible } // Hide hides the modal func (m *ConfigDisplayModel) Hide() { m.Visible = false } // Show shows the modal func (m *ConfigDisplayModel) Show(config string) { m.config = config m.viewport.SetContent(config) m.viewport.GotoTop() m.Visible = true }