Комментирование, правки кода, исправление модальных окон
This commit is contained in:
parent
2e8eee135e
commit
300afb5d26
8 changed files with 299 additions and 618 deletions
105
setup/modal.go
105
setup/modal.go
|
|
@ -7,21 +7,20 @@ import (
|
|||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
// ModalModel структура описывающая модель отрисовки модального окна
|
||||
type ModalModel struct {
|
||||
modalType types.ModalType
|
||||
title string
|
||||
message string
|
||||
buttons []types.ModalButton
|
||||
focus int
|
||||
width int
|
||||
height int
|
||||
onResult func(result any) tea.Cmd
|
||||
modalType types.ModalType //Тип модального окна
|
||||
title string //Заголовок модального окна
|
||||
message string //Сообщение модального окна
|
||||
buttons []types.ModalButton //Кнопки модального окна
|
||||
focus int //Фокус для отслеживания с каким объектом надо работать
|
||||
width int //Ширина окна
|
||||
height int //Высота окна
|
||||
onResult func(result any) tea.Cmd //Какое действие надо выполнить при нажатии
|
||||
}
|
||||
|
||||
// NewModalModel создает новую модель модального окна на основе переданного сообщения
|
||||
func NewModalModel(msg types.ShowModalMsg, width, height int) *ModalModel {
|
||||
if len(msg.ModalButtons) == 0 {
|
||||
msg.ModalButtons = []types.ModalButton{{Text: "Ok", Value: true}}
|
||||
}
|
||||
return &ModalModel{
|
||||
modalType: msg.Type,
|
||||
title: msg.Title,
|
||||
|
|
@ -38,32 +37,46 @@ func (m *ModalModel) Init() tea.Cmd {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Update отслеживает действия с модальным окном
|
||||
func (m *ModalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
//Отслеживаем и записываем новые размеры окна
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
return m, nil
|
||||
case tea.KeyMsg:
|
||||
//Отслеживаем нажатие клавиш модального окна
|
||||
switch msg.String() {
|
||||
case "left", "h", "shift+tab":
|
||||
case "left", "shift+tab":
|
||||
//Обработчик нажатия клавиш left и shift+tab нужен для перевода фокуса на прошлую кнопку.
|
||||
//Уменьшаем фокус, если фокус стал меньше 0, значит он вышел за пределы кнопок,
|
||||
//переводим его на последнюю кнопку.
|
||||
m.focus--
|
||||
if m.focus < 0 {
|
||||
m.focus = len(m.buttons) - 1
|
||||
}
|
||||
case "right", "l", "tab":
|
||||
case "right", "tab":
|
||||
//Обработчик нажатия клавиш right и tab нужен для перевода фокуса на следующую кнопку.
|
||||
//Увеличиваем фокус, если фокус стал равен количество кнопок, значит он вышел за их пределы,
|
||||
//переводим его на первую позицию, то есть на 0
|
||||
m.focus++
|
||||
if m.focus >= len(m.buttons) {
|
||||
m.focus = 0
|
||||
}
|
||||
case "enter", " ":
|
||||
//вытаскиваем значение кнопки
|
||||
//Обработчик клавиши enter нужен для подтверждения кнопки.
|
||||
//Получаем значение кнопки, а после если у модального окна прописана функция,
|
||||
//то передаем значение кнопки в функцию модального окна.
|
||||
result := m.buttons[m.focus].Value
|
||||
var cmd tea.Cmd
|
||||
if m.onResult != nil { //если функция кнопки не пустая, мы передаем в функцию значение кнопки
|
||||
if m.onResult != nil {
|
||||
cmd = m.onResult(result)
|
||||
}
|
||||
return m, tea.Batch( //объединяем 2 действия, функцию кнопки и закрытие модального окна
|
||||
//Возвращаем единую команду составленную из двух,
|
||||
//результата выполнения функции модального окна,
|
||||
//функцию возвращения сообщения о закрытии модального окна.
|
||||
return m, tea.Batch(
|
||||
cmd,
|
||||
func() tea.Msg { return types.CloseModalMsg{} },
|
||||
)
|
||||
|
|
@ -72,13 +85,14 @@ func (m *ModalModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m, nil
|
||||
}
|
||||
|
||||
// View формирует строку для вывода модального окна и её контента
|
||||
func (m *ModalModel) View() string {
|
||||
|
||||
//Данные о размерах контейнера
|
||||
containerWidth, containerHeight, _, _ := ui.ContentSizes(m.width, m.height)
|
||||
|
||||
//Модальное окно не должно занимать все пространство, поэтому получаем минимально допустимые размеры
|
||||
modalWidth := min(containerWidth, ui.ModalMaxWidth)
|
||||
modalHeight := min(containerHeight, ui.ModalMaxHeight)
|
||||
|
||||
//Формируем просто сообщение и кнопки с учетом фокуса
|
||||
message := lipgloss.NewStyle().Render(m.message)
|
||||
var buttons []string
|
||||
for i, button := range m.buttons {
|
||||
|
|
@ -88,12 +102,14 @@ func (m *ModalModel) View() string {
|
|||
}
|
||||
buttons = append(buttons, style.Render(button.Text))
|
||||
}
|
||||
//Строка кнопок
|
||||
buttonRow := lipgloss.JoinHorizontal(lipgloss.Center, buttons...)
|
||||
//Тело контента модального окна
|
||||
modalBody := lipgloss.JoinVertical(lipgloss.Center, message, "", buttonRow)
|
||||
|
||||
//В зависимости от типа модального окна разные цвета
|
||||
var borderColor lipgloss.Color
|
||||
var modalTitleStyle lipgloss.Style
|
||||
|
||||
switch m.modalType {
|
||||
case types.ModalError:
|
||||
borderColor = ui.ColorError
|
||||
|
|
@ -105,33 +121,19 @@ func (m *ModalModel) View() string {
|
|||
borderColor = ui.ColorAccent
|
||||
modalTitleStyle = ui.ModalTitleDefault
|
||||
}
|
||||
//
|
||||
//switch m.modalType {
|
||||
//case types.ModalError:
|
||||
// modalStyle = ui.ModalBorderError
|
||||
// modalTitleStyle = ui.ModalTitleError
|
||||
//case types.ModalWarning, types.ModalConfirm:
|
||||
// modalStyle = ui.ModalBorderWarning
|
||||
// modalTitleStyle = ui.ModalTitleWarning
|
||||
//default:
|
||||
// modalStyle = ui.ModalBorderInfo
|
||||
// modalTitleStyle = ui.ModalTitleDefault
|
||||
//}
|
||||
var modalView string
|
||||
//Формируем модальный контейнер с контентом внутри и указанным цветом границ.
|
||||
modalView := ui.ModalContainer.
|
||||
Width(modalWidth).
|
||||
Height(modalHeight).
|
||||
Align(lipgloss.Center).
|
||||
Border(lipgloss.DoubleBorder()).
|
||||
BorderForeground(borderColor).
|
||||
Render(modalBody)
|
||||
|
||||
symbolToRepeat := "*"
|
||||
//Если у модального окна есть заголовок, то в modalView записываем новое значение,
|
||||
//ставя заголовок сверху модального контейнера
|
||||
if m.title != "" {
|
||||
modalView = ui.ModalContainer.
|
||||
Width(modalWidth).
|
||||
Height(modalHeight).
|
||||
Align(lipgloss.Center, lipgloss.Center).
|
||||
Border(lipgloss.DoubleBorder()).
|
||||
BorderForeground(borderColor).
|
||||
Render(modalBody)
|
||||
//modalView = ui.ModalContainer.
|
||||
// Width(modalWidth).
|
||||
// Height(modalHeight).
|
||||
// BorderForeground(borderColor).
|
||||
// Render(modalBody)
|
||||
//repeatCount := modalWidth - utf8.RuneCountInString(m.title)
|
||||
//if repeatCount < 0 {
|
||||
// repeatCount = 0
|
||||
|
|
@ -139,19 +141,6 @@ func (m *ModalModel) View() string {
|
|||
//symbolFill := strings.Repeat(symbolToRepeat, repeatCount/2)
|
||||
//modalView = lipgloss.JoinVertical(lipgloss.Center, modalTitleStyle.Render(symbolFill+m.title+symbolFill), modalView)
|
||||
modalView = lipgloss.JoinVertical(lipgloss.Center, modalTitleStyle.Render(m.title), modalView)
|
||||
} else {
|
||||
modalView = ui.ModalContainer.
|
||||
Width(modalWidth).
|
||||
Height(modalHeight).
|
||||
BorderStyle(lipgloss.ASCIIBorder()).
|
||||
BorderForeground(borderColor).
|
||||
Render(modalBody)
|
||||
//modalView = modalStyle.
|
||||
// Width(modalWidth).
|
||||
// Height(modalHeight).
|
||||
// Padding(1, 3).
|
||||
// Border(lipgloss.DoubleBorder()).
|
||||
// Render(modalBody)
|
||||
}
|
||||
return lipgloss.Place(m.width, m.height,
|
||||
lipgloss.Center, lipgloss.Center,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue