This commit is contained in:
@@ -3,6 +3,7 @@ package steps
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"miasma-installer/tui/styles"
|
"miasma-installer/tui/styles"
|
||||||
|
"strings"
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
@@ -52,20 +53,32 @@ func (m ConfirmModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m ConfirmModel) View() string {
|
func (m ConfirmModel) View() string {
|
||||||
s := styles.TitleStyle.Render("Confirm Installation")
|
var content strings.Builder
|
||||||
s += "\n\n"
|
|
||||||
s += "Please review your installation settings:\n\n"
|
|
||||||
s += fmt.Sprintf(" Disk: %s\n", m.Disk)
|
|
||||||
s += fmt.Sprintf(" Encryption: %s\n", map[bool]string{true: "Enabled (LUKS2)", false: "Disabled"}[m.EnableLUKS])
|
|
||||||
s += fmt.Sprintf(" Hostname: %s\n", m.Hostname)
|
|
||||||
s += fmt.Sprintf(" Username: %s\n", m.Username)
|
|
||||||
s += fmt.Sprintf(" Filesystem: btrfs\n")
|
|
||||||
s += fmt.Sprintf(" Desktop: Cosmic Desktop\n")
|
|
||||||
s += fmt.Sprintf(" Kernel: linux-hardened\n")
|
|
||||||
s += fmt.Sprintf(" Bootloader: systemd-boot (UEFI)\n")
|
|
||||||
s += "\n"
|
|
||||||
s += styles.HelpStyle.Render("WARNING: This will ERASE ALL DATA on ") + m.Disk + "\n\n"
|
|
||||||
s += styles.HelpStyle.Render("[y] Proceed with installation [n] Cancel")
|
|
||||||
|
|
||||||
return styles.MainStyle.Render(s)
|
content.WriteString(styles.TitleStyle.Render("✓ Confirm Installation"))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString("Review your installation settings:\n\n")
|
||||||
|
|
||||||
|
settings := []string{
|
||||||
|
styles.RenderKeyValue("Disk", m.Disk),
|
||||||
|
styles.RenderKeyValue("Encryption", map[bool]string{true: "Enabled (LUKS2)", false: "Disabled"}[m.EnableLUKS]),
|
||||||
|
styles.RenderKeyValue("Hostname", m.Hostname),
|
||||||
|
styles.RenderKeyValue("Username", m.Username),
|
||||||
|
styles.RenderKeyValue("Filesystem", "btrfs"),
|
||||||
|
styles.RenderKeyValue("Desktop", "Cosmic Desktop"),
|
||||||
|
styles.RenderKeyValue("Kernel", "linux-hardened"),
|
||||||
|
styles.RenderKeyValue("Bootloader", "systemd-boot (UEFI)"),
|
||||||
|
}
|
||||||
|
|
||||||
|
content.WriteString(styles.BoxStyle.Render(strings.Join(settings, "\n")))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
warning := fmt.Sprintf("⚠️ WARNING: This will ERASE ALL DATA on %s", m.Disk)
|
||||||
|
content.WriteString(styles.WarningBoxStyle.Render(warning))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.RenderHelp("y", "Proceed with installation", "n", "Cancel"))
|
||||||
|
|
||||||
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,13 +157,27 @@ func (m DiskSelModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m DiskSelModel) View() string {
|
func (m DiskSelModel) View() string {
|
||||||
|
var content strings.Builder
|
||||||
|
|
||||||
if m.loading {
|
if m.loading {
|
||||||
return styles.MainStyle.Render(styles.TitleStyle.Render("Scanning disks..."))
|
content.WriteString(styles.TitleStyle.Render("💿 Scanning Disks..."))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
content.WriteString(styles.SpinnerStyle.Render("● Detecting available storage devices..."))
|
||||||
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
s := m.list.View()
|
content.WriteString(styles.TitleStyle.Render("💿 Select Installation Disk"))
|
||||||
s += "\n" + styles.HelpStyle.Render("Use ↑/↓ to navigate, [Enter] to select disk.")
|
content.WriteString("\n\n")
|
||||||
return s
|
|
||||||
|
warning := "⚠️ All data on the selected disk will be erased!"
|
||||||
|
content.WriteString(styles.WarningBoxStyle.Render(warning))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(m.list.View())
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
content.WriteString(styles.RenderHelp("↑/↓", "Navigate", "Enter", "Select"))
|
||||||
|
|
||||||
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatBytes(bytes uint64) string {
|
func formatBytes(bytes uint64) string {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EncryptionModel struct {
|
type EncryptionModel struct {
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ package steps
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"miasma-installer/tui/styles"
|
"miasma-installer/tui/styles"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HostnameModel struct {
|
type HostnameModel struct {
|
||||||
Hostname string
|
Hostname string
|
||||||
input textinput.Model
|
input textinput.Model
|
||||||
Finished bool
|
Finished bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHostnameModel() HostnameModel {
|
func NewHostnameModel() HostnameModel {
|
||||||
@@ -18,6 +19,7 @@ func NewHostnameModel() HostnameModel {
|
|||||||
ti.Placeholder = "miasma"
|
ti.Placeholder = "miasma"
|
||||||
ti.Focus()
|
ti.Focus()
|
||||||
ti.CharLimit = 63
|
ti.CharLimit = 63
|
||||||
|
ti.Width = 40
|
||||||
|
|
||||||
return HostnameModel{
|
return HostnameModel{
|
||||||
input: ti,
|
input: ti,
|
||||||
@@ -51,11 +53,21 @@ func (m HostnameModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m HostnameModel) View() string {
|
func (m HostnameModel) View() string {
|
||||||
s := styles.TitleStyle.Render("System Hostname")
|
var content strings.Builder
|
||||||
s += "\n\n"
|
|
||||||
s += "Enter a hostname for your system:\n\n"
|
|
||||||
s += m.input.View() + "\n\n"
|
|
||||||
s += styles.HelpStyle.Render("[Enter] Continue")
|
|
||||||
|
|
||||||
return styles.MainStyle.Render(s)
|
content.WriteString(styles.TitleStyle.Render("💻 System Hostname"))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
info := "Choose a name for your computer.\nThis will be used to identify your system on the network."
|
||||||
|
content.WriteString(styles.InfoBoxStyle.Render(info))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.LabelStyle.Render("Hostname:"))
|
||||||
|
content.WriteString("\n")
|
||||||
|
content.WriteString(styles.FocusedInputStyle.Render(m.input.View()))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.RenderHelp("Enter", "Continue"))
|
||||||
|
|
||||||
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,19 +421,37 @@ func (m InstallModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m InstallModel) View() string {
|
func (m InstallModel) View() string {
|
||||||
s := styles.TitleStyle.Render("Installing Miasma OS")
|
var content strings.Builder
|
||||||
s += "\n\n"
|
|
||||||
s += fmt.Sprintf("Step %d/%d: %s\n\n", m.currentStep, m.totalSteps, m.status)
|
content.WriteString(styles.TitleStyle.Render("⚙️ Installing Miasma OS"))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
progress := fmt.Sprintf("Step %d/%d", m.currentStep, m.totalSteps)
|
||||||
|
content.WriteString(styles.ProgressTextStyle.Render(progress))
|
||||||
|
content.WriteString("\n")
|
||||||
|
|
||||||
|
bar := strings.Repeat("█", m.currentStep) + strings.Repeat("░", m.totalSteps-m.currentStep)
|
||||||
|
content.WriteString(styles.ProgressBarStyle.Render(bar))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.SpinnerStyle.Render("● ") + m.status)
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
if m.err != nil {
|
if m.err != nil {
|
||||||
s += styles.HelpStyle.Render(fmt.Sprintf("Error: %v\n", m.err))
|
errMsg := fmt.Sprintf("✗ Error: %v", m.err)
|
||||||
|
content.WriteString(styles.ErrorBoxStyle.Render(errMsg))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
content.WriteString(styles.HelpStyle.Render("Press Ctrl+C to exit"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Finished && m.err == nil {
|
if m.Finished && m.err == nil {
|
||||||
s += "\n" + styles.HelpStyle.Render("Installation successful! You can now reboot.\nPress Ctrl+C to exit")
|
success := "✓ Installation successful!\n\nYou can now reboot your system."
|
||||||
|
content.WriteString(styles.BoxStyle.Render(success))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
content.WriteString(styles.RenderHelp("Ctrl+C", "Exit"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return styles.MainStyle.Render(s)
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func readLines(path string) ([]string, error) {
|
func readLines(path string) ([]string, error) {
|
||||||
|
|||||||
@@ -2,19 +2,20 @@ package steps
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"miasma-installer/tui/styles"
|
"miasma-installer/tui/styles"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserModel struct {
|
type UserModel struct {
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
usernameInput textinput.Model
|
usernameInput textinput.Model
|
||||||
passwordInput textinput.Model
|
passwordInput textinput.Model
|
||||||
confirmInput textinput.Model
|
confirmInput textinput.Model
|
||||||
focusIndex int
|
focusIndex int
|
||||||
Finished bool
|
Finished bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserModel() UserModel {
|
func NewUserModel() UserModel {
|
||||||
@@ -22,14 +23,17 @@ func NewUserModel() UserModel {
|
|||||||
ui.Placeholder = "username"
|
ui.Placeholder = "username"
|
||||||
ui.Focus()
|
ui.Focus()
|
||||||
ui.CharLimit = 32
|
ui.CharLimit = 32
|
||||||
|
ui.Width = 40
|
||||||
|
|
||||||
pi := textinput.New()
|
pi := textinput.New()
|
||||||
pi.Placeholder = "password"
|
pi.Placeholder = "password"
|
||||||
pi.EchoMode = textinput.EchoPassword
|
pi.EchoMode = textinput.EchoPassword
|
||||||
|
pi.Width = 40
|
||||||
|
|
||||||
ci := textinput.New()
|
ci := textinput.New()
|
||||||
ci.Placeholder = "confirm password"
|
ci.Placeholder = "confirm password"
|
||||||
ci.EchoMode = textinput.EchoPassword
|
ci.EchoMode = textinput.EchoPassword
|
||||||
|
ci.Width = 40
|
||||||
|
|
||||||
return UserModel{
|
return UserModel{
|
||||||
usernameInput: ui,
|
usernameInput: ui,
|
||||||
@@ -103,23 +107,53 @@ func (m UserModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m UserModel) View() string {
|
func (m UserModel) View() string {
|
||||||
s := styles.TitleStyle.Render("User Account")
|
var content strings.Builder
|
||||||
s += "\n\n"
|
|
||||||
s += "Create your user account:\n\n"
|
content.WriteString(styles.TitleStyle.Render("👤 User Account"))
|
||||||
s += "Username:\n"
|
content.WriteString("\n\n")
|
||||||
s += m.usernameInput.View() + "\n\n"
|
|
||||||
s += "Password:\n"
|
info := "Create your user account.\nThis user will have sudo privileges."
|
||||||
s += m.passwordInput.View() + "\n\n"
|
content.WriteString(styles.InfoBoxStyle.Render(info))
|
||||||
s += "Confirm Password:\n"
|
content.WriteString("\n\n")
|
||||||
s += m.confirmInput.View() + "\n\n"
|
|
||||||
|
content.WriteString(styles.LabelStyle.Render("Username:"))
|
||||||
|
content.WriteString("\n")
|
||||||
|
usernameStyle := styles.InputStyle
|
||||||
|
if m.focusIndex == 0 {
|
||||||
|
usernameStyle = styles.FocusedInputStyle
|
||||||
|
}
|
||||||
|
content.WriteString(usernameStyle.Render(m.usernameInput.View()))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.LabelStyle.Render("Password:"))
|
||||||
|
content.WriteString("\n")
|
||||||
|
passwordStyle := styles.InputStyle
|
||||||
|
if m.focusIndex == 1 {
|
||||||
|
passwordStyle = styles.FocusedInputStyle
|
||||||
|
}
|
||||||
|
content.WriteString(passwordStyle.Render(m.passwordInput.View()))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
|
content.WriteString(styles.LabelStyle.Render("Confirm Password:"))
|
||||||
|
content.WriteString("\n")
|
||||||
|
confirmStyle := styles.InputStyle
|
||||||
|
if m.focusIndex == 2 {
|
||||||
|
confirmStyle = styles.FocusedInputStyle
|
||||||
|
}
|
||||||
|
content.WriteString(confirmStyle.Render(m.confirmInput.View()))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
|
||||||
if m.passwordInput.Value() != "" && m.confirmInput.Value() != "" {
|
if m.passwordInput.Value() != "" && m.confirmInput.Value() != "" {
|
||||||
if m.passwordInput.Value() != m.confirmInput.Value() {
|
if m.passwordInput.Value() != m.confirmInput.Value() {
|
||||||
s += styles.HelpStyle.Render("Passwords do not match\n")
|
content.WriteString(styles.ErrorStyle.Render("✗ Passwords do not match"))
|
||||||
|
content.WriteString("\n\n")
|
||||||
|
} else {
|
||||||
|
content.WriteString(styles.SuccessStyle.Render("✓ Passwords match"))
|
||||||
|
content.WriteString("\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s += styles.HelpStyle.Render("[Tab] Switch fields [Enter] Continue")
|
content.WriteString(styles.RenderHelp("Tab", "Switch fields", "Enter", "Continue"))
|
||||||
|
|
||||||
return styles.MainStyle.Render(s)
|
return styles.AppStyle.Render(content.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type WelcomeModel struct {
|
type WelcomeModel struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user