Изменение вызова действий, проверка наличия действий секции, отображение счетчика выполнения действий в модальном окне, работа над подключением привязки горячих клавиш

This commit is contained in:
XeRo 2026-01-23 17:52:47 +05:00
parent 91b1eea1d4
commit c69a7ae84b
14 changed files with 886 additions and 706 deletions

View file

@ -3,6 +3,7 @@ package setup
import (
"bubble/setup/ui"
"bubble/types"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
@ -17,11 +18,12 @@ type ModalModel struct {
width int //Ширина окна
height int //Высота окна
onResult func(result any) tea.Cmd //Какое действие надо выполнить при нажатии
spinner spinner.Model //Для демонстрации прогресса выполнения действий
}
// NewModalModel создает новую модель модального окна на основе переданного сообщения
func NewModalModel(msg types.ShowModalMsg, width, height int) *ModalModel {
return &ModalModel{
m := &ModalModel{
modalType: msg.Type,
title: msg.Title,
message: msg.Message,
@ -31,14 +33,25 @@ func NewModalModel(msg types.ShowModalMsg, width, height int) *ModalModel {
height: height,
onResult: msg.OnResult,
}
if msg.Type == types.ModalLoading {
s := spinner.New()
s.Spinner = spinner.Line
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
m.spinner = s
}
return m
}
func (m *ModalModel) Init() tea.Cmd {
if m.modalType == types.ModalLoading {
return m.spinner.Tick
}
return nil
}
// Update отслеживает действия с модальным окном
func (m *ModalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
//Отслеживаем и записываем новые размеры окна
@ -64,24 +77,28 @@ func (m *ModalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.focus >= len(m.buttons) {
m.focus = 0
}
case "enter", " ":
case "enter":
//Обработчик клавиши enter нужен для подтверждения кнопки.
//Получаем значение кнопки, а после если у модального окна прописана функция,
//Если у модального окна есть кнопки.
//Получаем значение нажатой кнопки, а после если у модального окна прописана функция,
//то передаем значение кнопки в функцию модального окна.
result := m.buttons[m.focus].Value
var cmd tea.Cmd
if m.onResult != nil {
cmd = m.onResult(result)
if len(m.buttons) > 0 {
result := m.buttons[m.focus].Value
if m.onResult != nil {
cmd = m.onResult(result)
}
//Возвращаем единую команду составленную из двух,
//результата выполнения функции модального окна,
//функцию возвращения сообщения о закрытии модального окна.
return m, tea.Sequence(cmd, func() tea.Msg { return types.CloseModalMsg{} })
}
//Возвращаем единую команду составленную из двух,
//результата выполнения функции модального окна,
//функцию возвращения сообщения о закрытии модального окна.
return m, tea.Batch(
cmd,
func() tea.Msg { return types.CloseModalMsg{} },
)
}
}
//Если это модальное окно загрузки, то обновляем счетчик
if m.modalType == types.ModalLoading {
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
}
return m, nil
}
@ -106,7 +123,9 @@ func (m *ModalModel) View() string {
buttonRow := lipgloss.JoinHorizontal(lipgloss.Center, buttons...)
//Тело контента модального окна
modalBody := lipgloss.JoinVertical(lipgloss.Center, message, "", buttonRow)
if m.modalType == types.ModalLoading {
modalBody = lipgloss.JoinVertical(lipgloss.Center, m.spinner.View(), message)
}
//В зависимости от типа модального окна разные цвета
var borderColor lipgloss.Color
var modalTitleStyle lipgloss.Style