Files
LazyPM/pkg/task/taskui.go

142 lines
3.2 KiB
Go

package task
import (
"fmt"
"strings"
"charm.land/bubbles/v2/key"
"charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/style"
)
type TaskDetails = models.TaskDetails
type TaskModel struct {
TaskDetails
keys TaskHelpKeys
width, height int
userQuit bool
aboutVisible bool
}
type TaskHelpKeys struct {
Quit key.Binding
Start key.Binding
About key.Binding
}
var DefaultTaskKeys = TaskHelpKeys{
Quit: key.NewBinding(
key.WithKeys("q", "ctrl+c"),
key.WithHelp("q", "Quit"),
),
Start: key.NewBinding(
key.WithKeys("enter"),
key.WithHelp("enter", "Start"),
),
About: key.NewBinding(
key.WithKeys("?"),
key.WithHelp("?", "Details about the interface"),
),
}
func NewTaskModel(details TaskDetails) TaskModel {
return TaskModel{
TaskDetails: details,
keys: DefaultTaskKeys,
}
}
func (m TaskModel) Init() tea.Cmd {
return nil
}
func (m TaskModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.SetSize(msg.Width, msg.Height)
case tea.KeyPressMsg:
switch {
case key.Matches(msg, m.keys.Quit):
m.userQuit = true
return m, tea.Quit
case key.Matches(msg, m.keys.Start):
return m, tea.Quit
case key.Matches(msg, m.keys.About):
m.aboutVisible = !m.aboutVisible
return m, nil
}
}
return m, nil
}
func (m TaskModel) View() tea.View {
if m.width < 55 || m.height < 16 {
content := lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center,
style.TextStyle.Render("Terminal too small."))
v := tea.NewView(content)
v.AltScreen = true
return v
}
boxWidth := min(m.width-10, 120)
detailsText := fmt.Sprintf("Interface Type: %s | Time to complete: %s | Difficulty: %s", m.InterfaceType, m.TimeToComplete, m.Difficulty)
boxStyle := style.BorderStyle.Padding(2, 4).Width(boxWidth)
var b strings.Builder
b.WriteString(style.TitleStyle.Render(m.Title))
b.WriteString("\n")
content := lipgloss.JoinVertical(
lipgloss.Center,
style.TextStyle.Render(m.Description),
"\n",
style.TextStyle.Foreground(style.SecondaryColor).Render(detailsText),
)
if m.aboutVisible {
b.WriteString(boxStyle.Render(m.InterfaceDescription))
} else {
b.WriteString(boxStyle.Render(content))
}
b.WriteString("\n")
helpText := "Press " + m.keys.Start.Help().Key + " to start • " + m.getQuitHelpText() + " • " + m.keys.About.Help().Key + " " + m.keys.About.Help().Desc
b.WriteString(style.HelpStyle.Render(helpText))
final := lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, b.String())
v := tea.NewView(final)
v.AltScreen = true
return v
}
func (m TaskModel) getQuitHelpText() string {
switch m.InterfaceType {
case models.InterfaceTypeWeb:
return "Press esc/q in the terminal to skip the task"
case models.InterfaceTypeTUI:
return "Press 'q' to skip task during the survey"
case models.InterfaceTypeCLI, models.InterfaceTypeREPL:
return "Write 'exit' to skip task during the survey"
default:
return m.keys.Quit.Help().Key + " to quit"
}
}
func (m *TaskModel) SetSize(width, height int) {
m.width, m.height = width, height
}
func (m TaskModel) GetUserQuit() bool {
return m.userQuit
}