batman
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
)
|
||||
|
||||
// --- Messages ---
|
||||
|
||||
type DockerCheckedMsg struct{ Installed bool }
|
||||
type DockerInstalledMsg struct{ Err error }
|
||||
|
||||
// --- Commands ---
|
||||
|
||||
func CheckDockerCmd() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
_, err := exec.LookPath("docker")
|
||||
return DockerCheckedMsg{Installed: err == nil}
|
||||
}
|
||||
}
|
||||
|
||||
func InstallDockerCmd() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
err := exec.Command("sh", "-c", "curl -fsSL https://get.docker.com | sh").Run()
|
||||
return DockerInstalledMsg{Err: err}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package tui
|
||||
@@ -0,0 +1,25 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"charm.land/bubbles/v2/textinput"
|
||||
tea "charm.land/bubbletea/v2"
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
currentStep step
|
||||
dockerInstalled bool
|
||||
isPublicIP bool
|
||||
inputs []textinput.Model
|
||||
cursor int
|
||||
err error
|
||||
}
|
||||
|
||||
func InitialModel() Model {
|
||||
return Model{
|
||||
currentStep: StepCheckDocker,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return CheckDockerCmd()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package tui
|
||||
|
||||
type step int
|
||||
|
||||
const (
|
||||
StepCheckDocker step = iota
|
||||
StepDockerInstall
|
||||
StepIPQuestion
|
||||
StepInstallWireguard
|
||||
StepTextInputs
|
||||
StepDone
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package tui
|
||||
|
||||
import "charm.land/lipgloss/v2"
|
||||
|
||||
const padding = 2
|
||||
|
||||
var (
|
||||
TitleStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#FAFAFA"))
|
||||
HelpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262"))
|
||||
CursorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF75B7"))
|
||||
ErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF5555"))
|
||||
)
|
||||
@@ -0,0 +1,76 @@
|
||||
package tui
|
||||
|
||||
import tea "charm.land/bubbletea/v2"
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
// Global keys first — always handled regardless of step
|
||||
if key, ok := msg.(tea.KeyPressMsg); ok {
|
||||
switch key.String() {
|
||||
case "ctrl+c", "q":
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
|
||||
switch m.currentStep {
|
||||
case StepCheckDocker:
|
||||
return m.updateCheckDocker(msg)
|
||||
case StepDockerInstall:
|
||||
return m.updateDockerInstall(msg)
|
||||
case StepIPQuestion:
|
||||
return m.updateIPQuestion(msg)
|
||||
case StepDone:
|
||||
return m, tea.Quit
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m Model) updateCheckDocker(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if msg, ok := msg.(DockerCheckedMsg); ok {
|
||||
m.dockerInstalled = msg.Installed
|
||||
if msg.Installed {
|
||||
m.currentStep = StepIPQuestion
|
||||
} else {
|
||||
m.currentStep = StepDockerInstall
|
||||
m.cursor = 0 // reset cursor on enter
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m Model) updateDockerInstall(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
const numOptions = 2
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyPressMsg:
|
||||
switch msg.String() {
|
||||
case "up", "k":
|
||||
if m.cursor > 0 {
|
||||
m.cursor--
|
||||
}
|
||||
case "down", "j":
|
||||
if m.cursor < numOptions-1 {
|
||||
m.cursor++
|
||||
}
|
||||
case "enter":
|
||||
switch m.cursor {
|
||||
case 0:
|
||||
return m, InstallDockerCmd()
|
||||
case 1:
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
case DockerInstalledMsg:
|
||||
if msg.Err != nil {
|
||||
m.err = msg.Err
|
||||
} else {
|
||||
m.currentStep = StepIPQuestion
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m Model) updateIPQuestion(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
)
|
||||
|
||||
const header = "App do Dono - Instalador Cliente"
|
||||
|
||||
func (m Model) View() tea.View {
|
||||
pad := strings.Repeat(" ", padding)
|
||||
var body string
|
||||
|
||||
switch m.currentStep {
|
||||
case StepCheckDocker:
|
||||
body = m.viewCheckDocker()
|
||||
case StepDockerInstall:
|
||||
body = m.viewDockerInstall()
|
||||
case StepIPQuestion:
|
||||
body = m.viewIPQuestion()
|
||||
}
|
||||
|
||||
help := HelpStyle.Render("Pressione q ou ctrl+c para sair")
|
||||
|
||||
return tea.NewView(fmt.Sprintf("\n%s%s\n\n%s\n\n%s%s\n",
|
||||
pad, TitleStyle.Render(header),
|
||||
body,
|
||||
pad, help,
|
||||
))
|
||||
}
|
||||
|
||||
func (m Model) viewCheckDocker() string {
|
||||
pad := strings.Repeat(" ", padding)
|
||||
return pad + "Avaliando instalação do Docker. Aguarde..."
|
||||
}
|
||||
|
||||
func (m Model) viewDockerInstall() string {
|
||||
pad := strings.Repeat(" ", padding)
|
||||
options := []string{"Instalar automaticamente", "Instalar manualmente"}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString(pad + "Nenhuma versão do Docker encontrada.\n")
|
||||
sb.WriteString(pad + "Deseja:\n\n")
|
||||
|
||||
for i, opt := range options {
|
||||
cursor := " "
|
||||
if m.cursor == i {
|
||||
cursor = CursorStyle.Render("> ")
|
||||
}
|
||||
sb.WriteString(pad + cursor + opt + "\n")
|
||||
}
|
||||
|
||||
if m.err != nil {
|
||||
sb.WriteString("\n" + pad + ErrorStyle.Render("Erro: "+m.err.Error()))
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (m Model) viewIPQuestion() string {
|
||||
pad := strings.Repeat(" ", padding)
|
||||
return pad + "Existe IP público disponível para a máquina?"
|
||||
}
|
||||
Reference in New Issue
Block a user