package setup import ( "bubble/setup/ui" "bubble/types" "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/muesli/reflow/wordwrap" "strings" ) // LogModel структура описывающая модель отрисовки окна логирования type LogModel struct { logs []string //Массив строк логирования viewport viewport.Model //Видимая область логов width int //Ширина height int //Высота } // NewLogModel создает новую модель логирования func NewLogModel(width, height int) *LogModel { l := &LogModel{ logs: make([]string, 0), width: width, height: height, } if width > 0 && height > 0 { l.initViewport(width, height) } return l } func (m *LogModel) Init() tea.Cmd { return nil } // Update отслеживает действия логов func (m *LogModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.WindowSizeMsg: //Отслеживает и записывает новый размеры окна, обновляет область действий m.height = msg.Height m.width = msg.Width m.initViewport(m.width, m.height) return m, nil case types.ActionClearLogsMsg: //Отслеживаем сообщение об очистке сообщений m.logs = make([]string, 0) m.rebuildContent(m.width) case tea.KeyMsg: //Передаем нажатия клавиш для обновления области действий m.viewport, cmd = m.viewport.Update(msg) return m, cmd } return m, cmd } func (m *LogModel) View() string { containerWidth, containerHeight, contentWidth, _ := ui.ContentSizes(m.width, m.height) m.rebuildContent(contentWidth) container := ui.AppContainer. Width(containerWidth). Height(containerHeight). Render(m.viewport.View()) return lipgloss.Place( m.width, m.height, lipgloss.Center, lipgloss.Center, container, lipgloss.WithWhitespaceChars("&"), ) } func (m *LogModel) initViewport(width, height int) { _, _, contentWidth, contentHeight := ui.ContentSizes(width, height) m.viewport = viewport.New(contentWidth, contentHeight) m.viewport.SetHorizontalStep(1) m.rebuildContent(contentWidth) } // rebuildContent обновляем содержимое логов func (m *LogModel) rebuildContent(width int) { var sb strings.Builder for i, log := range m.logs { //Строка логирования с переносом слов logString := wordwrap.String(log, width) //Рендер строки логов logString = lipgloss.NewStyle().Foreground(lipgloss.Color("#fff")).Render(logString) if i != len(m.logs)-1 { logString += "\n\n" } else { logString += "\n" } sb.WriteString(logString) } m.viewport.SetContent(sb.String()) }