package setup import ( "bubble/setup/ui" "bubble/types" "fmt" "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/table" ) type FinalModel struct { variables []types.Variable table *table.Table viewport viewport.Model ready bool width int height int } func NewFinalModel(variables []types.Variable, width, height int) *FinalModel { m := &FinalModel{ variables: variables, width: width, height: height, ready: false, } if width > 0 && height > 0 { m.initViewport(width, height) } return m } func (m *FinalModel) Init() tea.Cmd { return nil } func (m *FinalModel) initViewport(width, height int) { m.viewport = viewport.New(width, height-4) m.viewport.Width = width - 4 m.viewport.Height = height - 6 m.ready = true m.rebuildTable(m.viewport.Width) m.viewport.SetContent(m.table.Render()) } func (m *FinalModel) rebuildTable(width int) { if len(m.variables) == 0 { m.table = table.New().Headers("Нет переменных") return } availableWidth := width - 8 // примерно: 2 (отступы) + 4 (бордер) + запас if availableWidth < 60 { availableWidth = 60 } t := table.New(). Border(lipgloss.ThickBorder()). BorderStyle(ui.TableBorderStyle). StyleFunc(func(row, col int) lipgloss.Style { var style lipgloss.Style switch { case row == table.HeaderRow: return ui.TableHeaderStyle case row%2 == 0: style = ui.TableEvenRowStyle default: style = ui.TableOddRowStyle } switch col { case 0, 1: style = style.Width(25) case 2: style = style.Width(availableWidth - 50 - 10) } return style }). Headers("Variable name", "Default value", "Used value") for _, v := range m.variables { used := fmt.Sprintf("%v", v.Value) if used == "" { used = "<пусто>" } t.Row(v.Name, v.Default, used) } m.table = t } func (m *FinalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit case "up": m.viewport.ScrollUp(1) case "down": m.viewport.ScrollDown(1) case "pageup": m.viewport.HalfPageUp() case "pagedown": m.viewport.HalfPageDown() case "home": m.viewport.GotoTop() case "end": m.viewport.GotoBottom() } case tea.WindowSizeMsg: if !m.ready { m.initViewport(msg.Width, msg.Height) } else { m.viewport.Width = msg.Width - 4 m.viewport.Height = msg.Height - 6 } m.rebuildTable(m.viewport.Width) rendered := m.table.Render() m.viewport.SetContent(rendered) } m.viewport, cmd = m.viewport.Update(msg) return m, cmd } func (m *FinalModel) View() string { if !m.ready { return "Загрузка таблицы" } header := lipgloss.NewStyle(). Width(m.viewport.Width). Align(lipgloss.Center). Bold(true). Background(ui.ColorPurple). Foreground(ui.ColorWhite). Padding(1). Render("Итоговые значения переменных") footer := lipgloss.NewStyle(). Width(m.viewport.Width). Align(lipgloss.Center). Foreground(ui.ColorGrey). Padding(0, 1). Render(fmt.Sprintf("Строк: %d • q — выход • ↑↓ / jk — скролл", len(m.variables))) body := m.viewport.View() return lipgloss.JoinVertical(lipgloss.Center, header, body, footer, ) }