GoSetup-bubble/setup/modal.go

162 lines
4.4 KiB
Go
Raw Normal View History

package setup
import (
"bubble/setup/ui"
"bubble/types"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
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
}
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,
message: msg.Message,
buttons: msg.ModalButtons,
focus: 0,
width: width,
height: height,
onResult: msg.OnResult,
}
}
func (m *ModalModel) Init() tea.Cmd {
return nil
}
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":
m.focus--
if m.focus < 0 {
m.focus = len(m.buttons) - 1
}
case "right", "l", "tab":
m.focus++
if m.focus >= len(m.buttons) {
m.focus = 0
}
case "enter", " ":
//вытаскиваем значение кнопки
result := m.buttons[m.focus].Value
var cmd tea.Cmd
if m.onResult != nil { //если функция кнопки не пустая, мы передаем в функцию значение кнопки
cmd = m.onResult(result)
}
return m, tea.Batch( //объединяем 2 действия, функцию кнопки и закрытие модального окна
cmd,
func() tea.Msg { return types.CloseModalMsg{} },
)
}
}
return m, nil
}
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 {
style := ui.ModalButtonNormal
if i == m.focus {
style = ui.ModalButtonFocused
}
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
modalTitleStyle = ui.ModalTitleError
case types.ModalWarning, types.ModalConfirm:
borderColor = ui.ColorWarning
modalTitleStyle = ui.ModalTitleWarning
default:
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
symbolToRepeat := "*"
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
//}
//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,
modalView,
lipgloss.WithWhitespaceChars(symbolToRepeat),
lipgloss.WithWhitespaceForeground(ui.ColorGrey))
}