From ecc89e34c5d22311cb73a9502d117c5c01c71b08 Mon Sep 17 00:00:00 2001 From: XeRo Date: Fri, 16 Jan 2026 17:44:03 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BD=D0=B5=D0=BD=D1=83=D0=B6=D0=BD=D1=8B=D1=85=20?= =?UTF-8?q?=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B9,=20?= =?UTF-8?q?=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D1=83?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B4=D0=B0=20update=20viewport=20final,=20=D0=B8?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=20=D1=82?= =?UTF-8?q?=D0=B8=D0=BF=D0=BE=D0=B2,=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=20=D0=BD=D0=B0=D0=B4=20viewport=20form,=20=D0=B8=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D1=85=20=D1=81=D0=B5=D0=BA=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/load.go | 9 +- setup/condition.go | 4 - setup/fields/dirSelect.go | 9 +- setup/fields/fieldModel.go | 2 + setup/fields/fileSelect.go | 9 +- setup/fields/select.go | 9 +- setup/final.go | 21 +---- setup/form.go | 180 ++++++++++++++++++++++++++----------- setup/main.go | 50 +++++------ types/msg.go | 15 ---- types/types.go | 2 +- 11 files changed, 168 insertions(+), 142 deletions(-) diff --git a/bootstrap/load.go b/bootstrap/load.go index 63db0c4..0ce9c44 100644 --- a/bootstrap/load.go +++ b/bootstrap/load.go @@ -7,6 +7,7 @@ import ( "io/fs" "os" "path/filepath" + "strings" ) const ConfDir = "./confs/" @@ -61,7 +62,13 @@ func connectVariables(app types.PackageApplication) types.PackageApplication { varMap := make(map[string]*types.Variable) for i := range app.Variables { v := &app.Variables[i] - v.Value = v.Default // сразу устанавливаем дефолт + // сразу устанавливаем дефолт + switch v.Type { + case "bool": + v.Value = strings.ToLower(v.Default) == "true" + default: + v.Value = v.Default + } varMap[v.Name] = v } diff --git a/setup/condition.go b/setup/condition.go index b12b8b2..58be7c6 100644 --- a/setup/condition.go +++ b/setup/condition.go @@ -162,10 +162,6 @@ func Recompute(app *types.PackageApplication) { for j := range section.Fields { field := §ion.Fields[j] if field.FieldType == "compute" && field.Compute != "" { - if field.Variable != nil { - // todo почему мы пропускаем? - continue - } value, err := ComputeValue(field.Compute, app) if err != nil { value = fmt.Sprintf("Ошибка вычисления: %v", err) diff --git a/setup/fields/dirSelect.go b/setup/fields/dirSelect.go index 4fed6ef..7c1d786 100644 --- a/setup/fields/dirSelect.go +++ b/setup/fields/dirSelect.go @@ -2,7 +2,6 @@ package fields import ( "bubble/setup/ui" - "bubble/types" "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" @@ -82,14 +81,8 @@ func (m *DirSelectModel) Update(msg tea.Msg) (FieldModel, tea.Cmd) { m.dir = newValue m.input.CursorEnd() m.open = false - selected := types.SelectedDirMsg{ - DirectoryName: fileName, - Index: m.focus, - } m.focus = 0 - return m, func() tea.Msg { - return selected - } + return m, nil } } } else { diff --git a/setup/fields/fieldModel.go b/setup/fields/fieldModel.go index 1950609..12e5463 100644 --- a/setup/fields/fieldModel.go +++ b/setup/fields/fieldModel.go @@ -2,6 +2,8 @@ package fields import tea "github.com/charmbracelet/bubbletea" +// todo комментарии к полям +// todo описание поля выводить type FieldModel interface { Init() tea.Cmd Update(msg tea.Msg) (FieldModel, tea.Cmd) diff --git a/setup/fields/fileSelect.go b/setup/fields/fileSelect.go index c84c2ee..2c421d0 100644 --- a/setup/fields/fileSelect.go +++ b/setup/fields/fileSelect.go @@ -2,7 +2,6 @@ package fields import ( "bubble/setup/ui" - "bubble/types" "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" @@ -92,15 +91,9 @@ func (m *FileSelectModel) Update(msg tea.Msg) (FieldModel, tea.Cmd) { m.file = fullPath m.input.SetValue(fullPath) m.open = false - selected := types.SelectedFileMsg{ - Filename: fileName, - Index: m.focus, - } m.input.CursorEnd() m.focus = 0 - return m, func() tea.Msg { - return selected - } + return m, nil } } } else { diff --git a/setup/fields/select.go b/setup/fields/select.go index 6e956d9..4506895 100644 --- a/setup/fields/select.go +++ b/setup/fields/select.go @@ -1,7 +1,6 @@ package fields import ( - "bubble/types" "fmt" "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" @@ -60,15 +59,9 @@ func (m *SelectModel) Update(msg tea.Msg) (FieldModel, tea.Cmd) { return m, nil } m.chosen = m.options[m.focus] - selected := types.SelectedOptionMsg{ - FieldIndex: m.focus, - Value: m.chosen, - } m.open = false m.focus = len(m.options) - return m, func() tea.Msg { - return selected - } + return m, nil } } else { switch msg.String() { diff --git a/setup/final.go b/setup/final.go index 455bc3f..e62d2fe 100644 --- a/setup/final.go +++ b/setup/final.go @@ -43,24 +43,6 @@ func (m *FinalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.KeyMsg: //Отслеживаем нажатие клавиш switch msg.String() { - case "up": - //Обработчик up для прокручивания вверх на 1 позицию - m.viewport.ScrollUp(1) - case "down": - //Обработчик down для прокручивания вниз на 1 позицию - m.viewport.ScrollDown(1) - case "left": - //Обработчик left для прокручивания влево на 1 позицию - m.viewport.ScrollLeft(1) - case "right": - //Обработчик right для прокручивания вправо на 1 позицию - m.viewport.ScrollRight(1) - case "pageup": - //Обработчик pageup для прокручивания вверх на половину допустимой высоты viewport - m.viewport.HalfPageUp() - case "pagedown": - //Обработчик pagedown для прокручивания вниз на половину допустимой высоты viewport - m.viewport.HalfPageDown() case "home": //Обработчик home для перехода в самый вверх m.viewport.GotoTop() @@ -75,7 +57,6 @@ func (m *FinalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.initViewport(msg.Width, msg.Height) } //Если сообщение было иным, передаем его напрямую в viewport - //todo проверить есть ли эти функции уже у viewport.Update, возможно мой код дублирует m.viewport, cmd = m.viewport.Update(msg) return m, cmd } @@ -123,7 +104,7 @@ func (m *FinalModel) initViewport(width, height int) { //Создание видимой области, куда будет помещена таблица m.viewport = viewport.New(contentWidth, tableHeight) - + m.viewport.SetHorizontalStep(1) //Обновление таблицы m.rebuildTable(tableWidth) } diff --git a/setup/form.go b/setup/form.go index 049d9ff..74a2377 100644 --- a/setup/form.go +++ b/setup/form.go @@ -5,6 +5,7 @@ import ( "bubble/setup/ui" "bubble/types" "fmt" + "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/muesli/reflow/wordwrap" @@ -17,7 +18,8 @@ type FormModel struct { CurrentSection *types.Section //Указатель секции с которой надо работать FieldModels []fields.FieldModel //Массив моделей полей focus int //Фокус для отслеживания с каким объектом надо работать - renderedContent string //Строка хранения информации о приложении + renderedContent string //Строка хранения информации о приложении // todo поместить во viewport + viewport viewport.Model //Объект куда помещена информация о приложении для возможности прокручивать её width int //Ширина окна height int //Высота окна } @@ -80,10 +82,13 @@ func NewFormModel(application *types.PackageApplication, sectionIdx, focus, widt width: width, height: height, } - //Формируем описание приложения если секция установлена About - if currentSection.Type == types.SectionAbout { - m.renderedContent = simpleAboutRender(currentSection.Paragraphs, width) - m.focus = 0 + ////Формируем описание приложения если секция установлена About + //if currentSection.Type == types.SectionAbout { + // m.renderedContent = simpleAboutRender(currentSection.Paragraphs, width) + // m.focus = 0 + //} + if width > 0 && height > 0 { + m.initViewport(width, height) } return m } @@ -100,9 +105,10 @@ func (m *FormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { //Отслеживаем и записываем новые размеры окна, обновляем рендер about m.width = msg.Width m.height = msg.Height - if m.CurrentSection.Type == types.SectionAbout { - m.renderedContent = simpleAboutRender(m.CurrentSection.Paragraphs, m.width) - } + m.initViewport(m.width, m.height) + //if m.CurrentSection.Type == types.SectionAbout { + // m.renderedContent = simpleAboutRender(m.CurrentSection.Paragraphs, m.width) + //} return m, nil case tea.KeyMsg: //Отслеживаем нажатие клавиш формы @@ -152,13 +158,20 @@ func (m *FormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "tab", "shift+tab", "down", "up": //Обработчик клавиш tab, shift+tab, down, up на форме нужен для перехода между объектами формы. //Получаем точное имя клавиши нажатия, после проверяем где сейчас находится фокус. - //Если фокус не равен количеству полей, то значит фокус сейчас у поля формы. + //Если фокус меньше количества полей, то значит фокус сейчас на поле формы. + // Подробнее. У нас фокус в двух состояниях так сказать, + // фокус равен количество полей, значит он на кнопке следующей секции, + // если меньше количества полей или равен 0, значит фокус на поле формы. + // Если у нас нет полей на форме (секция About), значит количество полей равно 0, а фокус по умолчанию устанавливается 0. + // Чтобы m.FieldModels[m.focus] вызвало ошибку "индекс вне массива", + // нужно чтобы в условие m.focus < len(m.FieldModels) попал фокус меньше 0 (-1,-2 и тд). + // Чтобы этого избежать, есть проверка, которая устанавливает m.focus на последнюю позицию (количество полей на форме). + // Чтобы эта проверка дала сбой, нужно после неё прописать изменение фокуса формы на отрицательный принудительно, так как такое не может произойти в текущем коде. //Получаем имя поля (так как это старый фокус, то и поле на котором мы находимся это предыдущее поле, отсюда и название переменной), //Если поле не открыто, то мы можем перейти на следующее поле, увеличив или уменьшив фокус. //Если фокус равен количеству полей, значит он находится на кнопке переключения секций. Увеличиваем или уменьшаем фокус. key := msg.String() - if m.focus != len(m.FieldModels) { - //todo исправить фокус + if m.focus < len(m.FieldModels) { prevField := m.FieldModels[m.focus] if !prevField.CaptureKeys() { if key == "tab" || key == "down" { @@ -185,59 +198,81 @@ func (m *FormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.focus = len(m.FieldModels) } } - case types.SelectedOptionMsg: - //Отслеживаем выбор опции в поле типа select - //todo тут вообще логика нужна? Мы ведь в select, через m.chosen записываем значение, а после GetValue метод возвращаем m.chosen - logrus.Infof("chose %+v", msg) } //Если не было возвращено сообщений, значит действие было произведено с полем, а не с самой формой. //Возвращаем результат функции обновления полей. - return m, m.updateFields(msg) + var cmd tea.Cmd + if m.CurrentSection.Type == types.SectionAbout { + m.viewport, cmd = m.viewport.Update(msg) + return m, cmd + } else { + return m, m.updateFields(msg) + } } // View формирует строку для вывода формы и её контента. func (m *FormModel) View() string { - //Данные о размерах контейнера и ширины контента внутри - containerWidth, containerHeight, contentWidth, _ := ui.ContentSizes(m.width, m.height) - formWidth := contentWidth - 2*1 - var strokes []string //отображаемые строки - for i, field := range m.FieldModels { - //Строка с учетом переноса поля. - //Имеется ввиду, что если вводимое значение слишком длинное, то оно будет делиться на несколько строк. - fieldStroke := wordwrap.String(field.View(), formWidth) - //Если фокус равен текущему полю, то выделяем его. - if i == m.focus { - strokes = append(strokes, ui.FormFieldFocused.Render(fieldStroke)) - } else { - strokes = append(strokes, ui.FormFieldUnfocused.Render(fieldStroke)) - } - } - //Если текущая секция это секция About, то выводим её информацию. - //Не предполагается, что информация о приложении и поля для настройки будут в одной секции, поэтому тут идет обнуление прошлых строк. - if m.CurrentSection.Type == types.SectionAbout { - strokes = append([]string{}, m.renderedContent) - } - //Строка кнопки переключения секций. - //Если позиция фокуса равняется количеству полей, значит он сейчас находится на кнопке. - nextBtn := "[ next section ]" - if m.focus == len(m.FieldModels) { - strokes = append(strokes, ui.FormNextButton.Render(nextBtn)) - } else { - strokes = append(strokes, ui.FormFieldUnfocused.Render(nextBtn)) - } - //Основной контейнер приложения. - //Устанавливаем ему ширину и высоту, объединяем все строки в одну с соединением, через двойной перевод строки. + containerWidth, containerHeight, contentWidth, contentHeight := ui.ContentSizes(m.width, m.height) + + formWidth := contentWidth - 2*1 + //formHeight:=contentHeight-2*1 + _ = contentHeight - 2*1 + + m.rebuildContent(formWidth) container := ui.AppContainer. Width(containerWidth). Height(containerHeight). - Render(strings.Join(strokes, "\n\n")) + Render(m.renderedContent) return lipgloss.Place( m.width, m.height, lipgloss.Center, lipgloss.Center, container, - lipgloss.WithWhitespaceChars(" "), + lipgloss.WithWhitespaceChars("0"), + lipgloss.WithWhitespaceForeground(ui.ColorError), ) + + ////Данные о размерах контейнера и ширины контента внутри + //containerWidth, containerHeight, contentWidth, _ := ui.ContentSizes(m.width, m.height) + //formWidth := contentWidth - 2*1 + //var strokes []string //отображаемые строки + //for i, field := range m.FieldModels { + // //Строка с учетом переноса поля. + // //Имеется ввиду, что если вводимое значение слишком длинное, то оно будет делиться на несколько строк. + // fieldStroke := wordwrap.String(field.View(), formWidth) + // //Если фокус равен текущему полю, то выделяем его. + // if i == m.focus { + // strokes = append(strokes, ui.FormFieldFocused.Render(fieldStroke)) + // } else { + // strokes = append(strokes, ui.FormFieldUnfocused.Render(fieldStroke)) + // } + //} + ////Если текущая секция это секция About, то выводим её информацию. + ////Не предполагается, что информация о приложении и поля для настройки будут в одной секции, поэтому тут идет обнуление прошлых строк. + //if m.CurrentSection.Type == types.SectionAbout { + // strokes = append([]string{}, m.renderedContent) + //} + ////Строка кнопки переключения секций. + ////Если позиция фокуса равняется количеству полей, значит он сейчас находится на кнопке. + //nextBtn := "[ next section ]" + //if m.focus == len(m.FieldModels) { + // strokes = append(strokes, ui.FormNextButton.Render(nextBtn)) + //} else { + // strokes = append(strokes, ui.FormFieldUnfocused.Render(nextBtn)) + //} + // + ////Основной контейнер приложения. + ////Устанавливаем ему ширину и высоту, объединяем все строки в одну с соединением, через двойной перевод строки. + //container := ui.AppContainer. + // Width(containerWidth). + // Height(containerHeight). + // Render(strings.Join(strokes, "\n\n")) + //return lipgloss.Place( + // m.width, m.height, + // lipgloss.Center, lipgloss.Center, + // container, + // lipgloss.WithWhitespaceChars(" "), + //) } // updateFields обновляет поля и их внутренние данные, формирует единую команду действий для всех полей, в том числе возврат SugarMsg @@ -260,15 +295,19 @@ func (m *FormModel) updateFields(msg tea.Msg) tea.Cmd { } //Если поле успешно вернуло обновленное поле, то необходимо: //обновить модель поля в текущей форме; - //проверить изменилось ли значение переменной в настройках приложения, + //проверить у поля не типа Compute изменилось ли значение переменной в настройках приложения, //если изменилось, в массив команд помещаем команду по возврату сообщения Sugar if updated != nil { m.FieldModels[i] = updated for _, sectionField := range m.CurrentSection.Fields { - if sectionField.Name == fieldModel.GetLabel() { + if sectionField.Name == fieldModel.GetLabel() && sectionField.FieldType != "compute" { oldValue := sectionField.Variable.Value newValue := fieldModel.GetValue() + logrus.Debugf("label %s, oldValue(%v,%T), newValue(%v,%T), equal %t, field info %+v", + sectionField.Name, oldValue, oldValue, newValue, newValue, oldValue == newValue, sectionField, + ) if oldValue != newValue { + sectionField.Variable.Value = newValue //Записываем в переменную новое значение cmds = append(cmds, func() tea.Msg { return types.SugarMsg{ VariableName: sectionField.VariableName, @@ -277,8 +316,7 @@ func (m *FormModel) updateFields(msg tea.Msg) tea.Cmd { Focus: m.focus, } }) - sectionField.Variable.Value = newValue //recompute вызывать. - //todo что? надо на гите посмотреть в истории, может я это уже сделал, ведь sugar Msg отправляется + } } } @@ -292,6 +330,44 @@ func (m *FormModel) updateFields(msg tea.Msg) tea.Cmd { return tea.Batch(cmds...) } +func (m *FormModel) initViewport(width, height int) { + _, _, contentWidth, contentHeight := ui.ContentSizes(width, height) + formWidth := contentWidth - 2*1 + formHeight := contentHeight - 2*4 + m.viewport = viewport.New(contentWidth, formHeight) + m.viewport.SetHorizontalStep(1) + m.rebuildContent(formWidth) +} + +func (m *FormModel) rebuildContent(width int) { + var strokes []string + if m.CurrentSection.Type == types.SectionAbout { + strokes = append(strokes, simpleAboutRender(m.CurrentSection.Paragraphs, width)) + } else { + for i, field := range m.FieldModels { + //Строка с учетом переноса поля. + //Имеется ввиду, что если вводимое значение слишком длинное, то оно будет делиться на несколько строк. + fieldStroke := wordwrap.String(field.View(), width) + //Если фокус равен текущему полю, то выделяем его. + if i == m.focus { + strokes = append(strokes, ui.FormFieldFocused.Render(fieldStroke)) + } else { + strokes = append(strokes, ui.FormFieldUnfocused.Render(fieldStroke)) + } + } + } + //Строка кнопки переключения секций. + //Если позиция фокуса равняется количеству полей, значит он сейчас находится на кнопке. + nextBtn := "[ next section ]" + if m.focus == len(m.FieldModels) { + strokes = append(strokes, ui.FormNextButton.Render(nextBtn)) + } else { + strokes = append(strokes, ui.FormFieldUnfocused.Render(nextBtn)) + } + m.renderedContent = strings.Join(strokes, "\n\n") + m.viewport.SetContent(m.renderedContent) +} + // simpleAboutRender формирует единую строку, описывающую настраиваемое приложение. func simpleAboutRender(paragraphs []string, width int) string { var sb strings.Builder diff --git a/setup/main.go b/setup/main.go index 4b65b44..30de334 100644 --- a/setup/main.go +++ b/setup/main.go @@ -13,6 +13,7 @@ func Start() { } } +// todo подсказка горячие клавиши // Main структура описывающая объект настроек type Main struct { current tea.Model //Текущая модель для отображения @@ -94,38 +95,40 @@ func (m *Main) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case types.NextSectionMsg: //Получаем сообщение о переходе на следующую секцию настраиваемого приложения. - //Увеличиваем индекс текущей секции. - m.CurrentSectionIdx++ - //Если новый индекс равен - if m.CurrentSectionIdx == len(m.CurrentApplication.Sections) { - //todo что делать когда секций больше нужного? - return m, tea.Quit - } - for sectionIdx := m.CurrentSectionIdx; sectionIdx < len(m.CurrentApplication.Sections); sectionIdx++ { - //todo переделать. Учесть динамические индексы. + //Ищем индекс следующей секции, если он остался 0, то следующие секции недоступны. + //Возвращаем модальное окно с выходом к списку приложений + nextSectionIndex := 0 + for sectionIdx := m.CurrentSectionIdx + 1; sectionIdx < len(m.CurrentApplication.Sections); sectionIdx++ { section := m.CurrentApplication.Sections[sectionIdx] if CheckCondition(section.Condition, m.CurrentApplication) { - m.CurrentSectionIdx = sectionIdx - m.CurrentSection = §ion + nextSectionIndex = sectionIdx break } } - if m.CurrentSection == nil { + if nextSectionIndex == 0 { return m, func() tea.Msg { return types.ShowModalMsg{ - Type: types.ModalError, - Title: "Ошибка конфигурации", - Message: "Это приложение не имеет доступных секций для настройки\n" + - "Возможно оно повреждено или не поддерживается", - ModalButtons: []types.ModalButton{{Text: "Выйти", Value: true}}, + Type: types.ModalWarning, + Title: "Ошибка секций приложения", + Message: "Указанное приложение не имеет больше доступных секций для обработки", + ModalButtons: []types.ModalButton{{ + Text: "Вернутся", + Value: true, + }}, OnResult: func(result any) tea.Cmd { - return tea.Quit + return func() tea.Msg { + return types.BackToListMsg{} + } }, } } } - //todo переделать. Учесть динамические индексы. - if m.CurrentSectionIdx == len(m.CurrentApplication.Sections)-1 && m.CurrentSection.Type == types.SectionFinal { + + //Если следующая секция доступна записываем секцию и её индекс. + //Выводим либо финальную форму, если секция последняя и её тип SectionFinal, либо следующую простую секцию. + m.CurrentSectionIdx = nextSectionIndex + m.CurrentSection = &m.CurrentApplication.Sections[nextSectionIndex] + if nextSectionIndex == len(m.CurrentApplication.Sections)-1 && m.CurrentSection.Type == types.SectionFinal { m.current = NewFinalModel(m.CurrentApplication.Variables, m.Width, m.Height) } else { m.current = NewFormModel(m.CurrentApplication, m.CurrentSectionIdx, 0, m.Width, m.Height) @@ -152,7 +155,7 @@ func (m *Main) Update(msg tea.Msg) (tea.Model, tea.Cmd) { Title: "Ошибка", Message: "Ошибка выбора приложения. Указанное приложение не имеет доступных секций." + "Проверьте конфиг настраиваемого приложения на предмет выполнения условий секций", - ModalButtons: []types.ModalButton{{Text: "Вернуться к списку приложений", Value: true}}, + ModalButtons: []types.ModalButton{{Text: "Вернуться", Value: true}}, OnResult: func(result any) tea.Cmd { return func() tea.Msg { return types.BackToListMsg{} @@ -204,11 +207,8 @@ func (m *Main) Sugar(sugar types.SugarMsg) { m.DeactivateField(sugar.VariableName, sugar.FieldName) } //Если от переменной поля зависит секции или поля, - //то вызываем перерасчет значений compute полей и формируем новую форму с учетом прошлого фокуса на форме + //то формируем новую форму с учетом прошлого фокуса if IsParent(sugar.VariableName, m.CurrentApplication.Sections) { - if sugar.Compute != "" { - Recompute(m.CurrentApplication) - } m.current = NewFormModel(m.CurrentApplication, m.CurrentSectionIdx, sugar.Focus, m.Width, m.Height) } } diff --git a/types/msg.go b/types/msg.go index 5918059..afc48ae 100644 --- a/types/msg.go +++ b/types/msg.go @@ -8,11 +8,6 @@ type SelectedAppMsg struct { type BackToListMsg struct{} -type SelectedOptionMsg struct { - FieldIndex int - Value string -} - type NextSectionMsg struct{} type SugarMsg struct { @@ -22,16 +17,6 @@ type SugarMsg struct { Focus int } -type SelectedDirMsg struct { - DirectoryName string - Index int -} - -type SelectedFileMsg struct { - Filename string - Index int -} - type ShowModalMsg struct { Type ModalType Title string diff --git a/types/types.go b/types/types.go index 9cecb19..8baa096 100644 --- a/types/types.go +++ b/types/types.go @@ -44,7 +44,7 @@ type SectionField struct { Description string `yaml:"description"` Condition string `yaml:"condition"` Options []interface{} `yaml:"options"` - SpecialValue string `yaml:"special-Value"` + SpecialValue string `yaml:"special-value"` Compute string `yaml:"compute"` Validate []FieldValidate `yaml:"validate"` Parent []string `yaml:"parent"`