Работа над стилями, работа над модальными окнами, изменение списка приложений, работа с размерами окон

This commit is contained in:
XeRo 2025-12-29 17:46:48 +05:00
parent 5203032b83
commit ada7db46cf
12 changed files with 1161 additions and 130 deletions

View file

@ -7,6 +7,8 @@ import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/lipgloss"
"github.com/muesli/reflow/wordwrap"
"github.com/sirupsen/logrus"
"strings"
)
@ -16,9 +18,11 @@ type FormModel struct {
FieldModels []fields.FieldModel
focus int
renderedContent string
width int
height int
}
func NewFormModel(application *types.PackageApplication, sectionIdx, focus int) *FormModel {
func NewFormModel(application *types.PackageApplication, sectionIdx, focus, width, height int) *FormModel {
currentSection := &application.Sections[sectionIdx]
var fieldModels []fields.FieldModel
for _, sectionField := range currentSection.Fields {
@ -69,12 +73,14 @@ func NewFormModel(application *types.PackageApplication, sectionIdx, focus int)
FieldModels: fieldModels,
focus: focus,
CurrentSection: currentSection,
width: width,
height: height,
}
if currentSection.Type == "abouta" { //"about" {
if currentSection.Type == types.SectionAbout {
md := strings.Join(currentSection.Paragraphs, "\n\n")
renderer, _ := glamour.NewTermRenderer(
glamour.WithAutoStyle(),
glamour.WithWordWrap(80))
glamour.WithWordWrap(width-10))
rendered, _ := renderer.Render(md)
m.renderedContent = rendered
m.focus = 0
@ -88,23 +94,61 @@ func (m *FormModel) Init() tea.Cmd {
func (m *FormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
if m.CurrentSection.Type == types.SectionAbout {
md := strings.Join(m.CurrentSection.Paragraphs, "\n\n")
renderer, _ := glamour.NewTermRenderer(
glamour.WithAutoStyle(),
glamour.WithWordWrap(m.width-10),
)
rendered, _ := renderer.Render(md)
m.renderedContent = rendered
}
return m, nil
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
case "esc":
for _, field := range m.FieldModels {
if field.CaptureKeys() {
return m, m.updateFields(msg)
}
}
return m, func() tea.Msg {
return types.ShowModalMsg{
Type: types.ModalWarning,
Title: "Прервать настройку",
Message: "Вы уверены, что хотите прервать настройку?\nВсе введенные данные будут потеряны.",
ModalButtons: []types.ModalButton{
{Text: "Да, выйти", Value: true},
{Text: "Продолжить настройку", Value: false},
},
OnResult: func(result any) tea.Cmd {
if result == true {
return func() tea.Msg { return types.BackToListMsg{} }
}
return nil
},
}
}
//вернуться к списку приложений, чтобы выбрать другое приложение.
case "enter":
logrus.Infof("sections %s, focus %d, fields len %d", m.CurrentSection.Name, m.focus, len(m.FieldModels))
if len(m.FieldModels) == m.focus {
m.focus = 0
return m, func() tea.Msg {
return types.NextSectionMsg{}
}
}
case "tab", "down", "shift+tab", "up":
//Итак, тут надо учесть динамические поля.
//
key := msg.String()
if m.focus != len(m.FieldModels) {
logrus.Infof("1")
logrus.Infof("1, focus is %d", m.focus)
//todo исправить фокус
field := m.FieldModels[m.focus]
logrus.Infof("field %s, capture keys %t", field.GetLabel(), field.CaptureKeys())
@ -137,30 +181,66 @@ func (m *FormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (m *FormModel) View() string {
res := ""
contentWidth := ui.ContentWidth(m.width)
if len(m.FieldModels) > 0 {
for i := range m.FieldModels {
inputView := m.FieldModels[i].View()
if m.focus == i {
res += ui.FormFocusedStyle.Render(inputView)
} else {
res += ui.FormUnfocusedStyle.Render(inputView)
}
res += "\n"
var res strings.Builder
for i, field := range m.FieldModels {
fieldStr := wordwrap.String(field.View(), contentWidth-10)
if i == m.focus {
res.WriteString(ui.FormFieldFocused.Render(fieldStr))
} else {
res.WriteString(ui.FormFieldUnfocused.Render(fieldStr))
}
res.WriteString("\n\n")
}
button := "\n[ next section ]"
if m.CurrentSection.Type == "about" {
res += m.renderedContent
if m.CurrentSection.Type == types.SectionAbout {
res.WriteString(m.renderedContent)
}
nextBtn := "[ next section ]"
if m.focus == len(m.FieldModels) {
res += ui.FormFocusedStyle.Render(button)
res.WriteString(ui.FormNextButton.Render(nextBtn))
} else {
res += ui.FormUnfocusedStyle.Render(button)
res.WriteString(ui.FormFieldUnfocused.Render(nextBtn))
}
return ui.FormStyle.Render(res)
container := ui.FormContainer.Width(contentWidth).Render(res.String())
return lipgloss.Place(m.width, m.height,
lipgloss.Center, lipgloss.Center,
container,
lipgloss.WithWhitespaceChars(" "),
)
//for i, field := range m.FieldModels {
// fieldStr := wordwrap.String(field.View(), contentWidth-8)
// if i == m.focus {
// res.WriteString(ui.FormFocusedStyle.Render(fieldStr))
// } else {
// res.WriteString(ui.FormUnfocusedStyle.Render(fieldStr))
// }
// res.WriteString("\n\n")
//}
//
//if m.CurrentSection.Type == types.SectionAbout {
// res.WriteString("\n\n" + m.renderedContent)
//}
//
//button := "[ next section ]"
//if m.focus == len(m.FieldModels) {
// res.WriteString(ui.FormFocusedStyle.Render(button))
//} else {
// res.WriteString(ui.FormUnfocusedStyle.Render(button))
//}
//
//container := ui.FormStyle.Width(contentWidth).Render(res.String())
//
//return lipgloss.Place(m.width, m.height,
// lipgloss.Center, lipgloss.Top,
// container,
// lipgloss.WithWhitespaceChars(" "),
//)
}
func (m *FormModel) updateFields(msg tea.Msg) tea.Cmd {