mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-10 07:25:37 -05:00
switch hto monorepo structure
This commit is contained in:
382
backend/internal/tui/views_config.go
Normal file
382
backend/internal/tui/views_config.go
Normal file
@@ -0,0 +1,382 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/backend/internal/config"
|
||||
"github.com/AvengeMedia/DankMaterialShell/backend/internal/deps"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type configDeploymentResult struct {
|
||||
results []config.DeploymentResult
|
||||
error error
|
||||
}
|
||||
|
||||
type ExistingConfigInfo struct {
|
||||
ConfigType string
|
||||
Path string
|
||||
Exists bool
|
||||
}
|
||||
|
||||
type configCheckResult struct {
|
||||
configs []ExistingConfigInfo
|
||||
error error
|
||||
}
|
||||
|
||||
func (m Model) viewDeployingConfigs() string {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString(m.renderBanner())
|
||||
b.WriteString("\n")
|
||||
|
||||
title := m.styles.Title.Render("Deploying Configurations")
|
||||
b.WriteString(title)
|
||||
b.WriteString("\n\n")
|
||||
|
||||
spinner := m.spinner.View()
|
||||
status := m.styles.Normal.Render("Setting up configuration files...")
|
||||
b.WriteString(fmt.Sprintf("%s %s", spinner, status))
|
||||
b.WriteString("\n\n")
|
||||
|
||||
// Show progress information
|
||||
info := m.styles.Subtle.Render("• Creating backups of existing configurations\n• Deploying optimized configurations\n• Detecting system paths")
|
||||
b.WriteString(info)
|
||||
|
||||
// Show live log output if available
|
||||
if len(m.installationLogs) > 0 {
|
||||
b.WriteString("\n\n")
|
||||
logHeader := m.styles.Subtle.Render("Configuration Log:")
|
||||
b.WriteString(logHeader)
|
||||
b.WriteString("\n")
|
||||
|
||||
// Show last few lines of logs
|
||||
maxLines := 5
|
||||
startIdx := 0
|
||||
if len(m.installationLogs) > maxLines {
|
||||
startIdx = len(m.installationLogs) - maxLines
|
||||
}
|
||||
|
||||
for i := startIdx; i < len(m.installationLogs); i++ {
|
||||
if m.installationLogs[i] != "" {
|
||||
logLine := m.styles.Subtle.Render(" " + m.installationLogs[i])
|
||||
b.WriteString(logLine)
|
||||
b.WriteString("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m Model) updateDeployingConfigsState(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if result, ok := msg.(configDeploymentResult); ok {
|
||||
if result.error != nil {
|
||||
m.err = result.error
|
||||
m.state = StateError
|
||||
m.isLoading = false
|
||||
return m, nil
|
||||
}
|
||||
|
||||
for _, deployResult := range result.results {
|
||||
if deployResult.Deployed {
|
||||
logMsg := fmt.Sprintf("✓ %s configuration deployed", deployResult.ConfigType)
|
||||
if deployResult.BackupPath != "" {
|
||||
logMsg += fmt.Sprintf(" (backup: %s)", deployResult.BackupPath)
|
||||
}
|
||||
m.installationLogs = append(m.installationLogs, logMsg)
|
||||
}
|
||||
}
|
||||
|
||||
m.state = StateInstallComplete
|
||||
m.isLoading = false
|
||||
return m, nil
|
||||
}
|
||||
|
||||
return m, m.listenForLogs()
|
||||
}
|
||||
|
||||
func (m Model) deployConfigurations() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
// Determine the selected window manager
|
||||
var wm deps.WindowManager
|
||||
switch m.selectedWM {
|
||||
case 0:
|
||||
wm = deps.WindowManagerNiri
|
||||
case 1:
|
||||
wm = deps.WindowManagerHyprland
|
||||
default:
|
||||
wm = deps.WindowManagerNiri
|
||||
}
|
||||
|
||||
// Determine the selected terminal
|
||||
var terminal deps.Terminal
|
||||
if m.osInfo != nil && m.osInfo.Distribution.ID == "gentoo" {
|
||||
switch m.selectedTerminal {
|
||||
case 0:
|
||||
terminal = deps.TerminalKitty
|
||||
case 1:
|
||||
terminal = deps.TerminalAlacritty
|
||||
default:
|
||||
terminal = deps.TerminalKitty
|
||||
}
|
||||
} else {
|
||||
switch m.selectedTerminal {
|
||||
case 0:
|
||||
terminal = deps.TerminalGhostty
|
||||
case 1:
|
||||
terminal = deps.TerminalKitty
|
||||
default:
|
||||
terminal = deps.TerminalAlacritty
|
||||
}
|
||||
}
|
||||
|
||||
deployer := config.NewConfigDeployer(m.logChan)
|
||||
|
||||
results, err := deployer.DeployConfigurationsSelectiveWithReinstalls(context.Background(), wm, terminal, m.dependencies, m.replaceConfigs, m.reinstallItems)
|
||||
|
||||
return configDeploymentResult{
|
||||
results: results,
|
||||
error: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) viewConfigConfirmation() string {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString(m.renderBanner())
|
||||
b.WriteString("\n")
|
||||
|
||||
title := m.styles.Title.Render("Configuration Deployment")
|
||||
b.WriteString(title)
|
||||
b.WriteString("\n\n")
|
||||
|
||||
if len(m.existingConfigs) == 0 {
|
||||
// No existing configs, proceed directly
|
||||
info := m.styles.Normal.Render("No existing configurations found. Proceeding with deployment...")
|
||||
b.WriteString(info)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Show existing configurations with toggle options
|
||||
for i, configInfo := range m.existingConfigs {
|
||||
if configInfo.Exists {
|
||||
var status string
|
||||
var replaceMarker string
|
||||
|
||||
shouldReplace := m.replaceConfigs[configInfo.ConfigType]
|
||||
if _, exists := m.replaceConfigs[configInfo.ConfigType]; !exists {
|
||||
shouldReplace = true
|
||||
m.replaceConfigs[configInfo.ConfigType] = true
|
||||
}
|
||||
|
||||
if shouldReplace {
|
||||
replaceMarker = "🔄 "
|
||||
status = m.styles.Warning.Render("Will replace")
|
||||
} else {
|
||||
replaceMarker = "✓ "
|
||||
status = m.styles.Success.Render("Keep existing")
|
||||
}
|
||||
|
||||
var line string
|
||||
if i == m.selectedConfig {
|
||||
line = fmt.Sprintf("▶ %s%-15s %s", replaceMarker, configInfo.ConfigType, status)
|
||||
line += fmt.Sprintf("\n %s", configInfo.Path)
|
||||
line = m.styles.SelectedOption.Render(line)
|
||||
} else {
|
||||
line = fmt.Sprintf(" %s%-15s %s", replaceMarker, configInfo.ConfigType, status)
|
||||
line += fmt.Sprintf("\n %s", configInfo.Path)
|
||||
line = m.styles.Normal.Render(line)
|
||||
}
|
||||
|
||||
b.WriteString(line)
|
||||
b.WriteString("\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
backup := m.styles.Success.Render("✓ Replaced configurations will be backed up with timestamp")
|
||||
b.WriteString(backup)
|
||||
b.WriteString("\n\n")
|
||||
|
||||
help := m.styles.Subtle.Render("↑/↓: Navigate, Space: Toggle replace/keep, Enter: Continue")
|
||||
b.WriteString(help)
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m Model) updateConfigConfirmationState(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if result, ok := msg.(configCheckResult); ok {
|
||||
if result.error != nil {
|
||||
m.err = result.error
|
||||
m.state = StateError
|
||||
return m, nil
|
||||
}
|
||||
|
||||
m.existingConfigs = result.configs
|
||||
|
||||
firstExistingSet := false
|
||||
for i, config := range result.configs {
|
||||
if config.Exists {
|
||||
m.replaceConfigs[config.ConfigType] = true
|
||||
if !firstExistingSet {
|
||||
m.selectedConfig = i
|
||||
firstExistingSet = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasExisting := false
|
||||
for _, config := range result.configs {
|
||||
if config.Exists {
|
||||
hasExisting = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasExisting {
|
||||
// No existing configs, proceed directly to deployment
|
||||
m.state = StateDeployingConfigs
|
||||
return m, m.deployConfigurations()
|
||||
}
|
||||
|
||||
// Show confirmation view
|
||||
return m, nil
|
||||
}
|
||||
|
||||
if keyMsg, ok := msg.(tea.KeyMsg); ok {
|
||||
switch keyMsg.String() {
|
||||
case "up":
|
||||
if m.selectedConfig > 0 {
|
||||
for i := m.selectedConfig - 1; i >= 0; i-- {
|
||||
if m.existingConfigs[i].Exists {
|
||||
m.selectedConfig = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case "down":
|
||||
if m.selectedConfig < len(m.existingConfigs)-1 {
|
||||
for i := m.selectedConfig + 1; i < len(m.existingConfigs); i++ {
|
||||
if m.existingConfigs[i].Exists {
|
||||
m.selectedConfig = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case " ":
|
||||
if len(m.existingConfigs) > 0 && m.selectedConfig < len(m.existingConfigs) {
|
||||
configType := m.existingConfigs[m.selectedConfig].ConfigType
|
||||
if m.existingConfigs[m.selectedConfig].Exists {
|
||||
m.replaceConfigs[configType] = !m.replaceConfigs[configType]
|
||||
}
|
||||
}
|
||||
case "enter":
|
||||
m.state = StateDeployingConfigs
|
||||
return m, m.deployConfigurations()
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m Model) checkExistingConfigurations() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
var configs []ExistingConfigInfo
|
||||
|
||||
if m.selectedWM == 0 {
|
||||
niriPath := filepath.Join(os.Getenv("HOME"), ".config", "niri", "config.kdl")
|
||||
niriExists := false
|
||||
if _, err := os.Stat(niriPath); err == nil {
|
||||
niriExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Niri",
|
||||
Path: niriPath,
|
||||
Exists: niriExists,
|
||||
})
|
||||
} else {
|
||||
hyprlandPath := filepath.Join(os.Getenv("HOME"), ".config", "hypr", "hyprland.conf")
|
||||
hyprlandExists := false
|
||||
if _, err := os.Stat(hyprlandPath); err == nil {
|
||||
hyprlandExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Hyprland",
|
||||
Path: hyprlandPath,
|
||||
Exists: hyprlandExists,
|
||||
})
|
||||
}
|
||||
|
||||
if m.osInfo != nil && m.osInfo.Distribution.ID == "gentoo" {
|
||||
if m.selectedTerminal == 0 {
|
||||
kittyPath := filepath.Join(os.Getenv("HOME"), ".config", "kitty", "kitty.conf")
|
||||
kittyExists := false
|
||||
if _, err := os.Stat(kittyPath); err == nil {
|
||||
kittyExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Kitty",
|
||||
Path: kittyPath,
|
||||
Exists: kittyExists,
|
||||
})
|
||||
} else {
|
||||
alacrittyPath := filepath.Join(os.Getenv("HOME"), ".config", "alacritty", "alacritty.toml")
|
||||
alacrittyExists := false
|
||||
if _, err := os.Stat(alacrittyPath); err == nil {
|
||||
alacrittyExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Alacritty",
|
||||
Path: alacrittyPath,
|
||||
Exists: alacrittyExists,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
switch m.selectedTerminal {
|
||||
case 0:
|
||||
ghosttyPath := filepath.Join(os.Getenv("HOME"), ".config", "ghostty", "config")
|
||||
ghosttyExists := false
|
||||
if _, err := os.Stat(ghosttyPath); err == nil {
|
||||
ghosttyExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Ghostty",
|
||||
Path: ghosttyPath,
|
||||
Exists: ghosttyExists,
|
||||
})
|
||||
case 1:
|
||||
kittyPath := filepath.Join(os.Getenv("HOME"), ".config", "kitty", "kitty.conf")
|
||||
kittyExists := false
|
||||
if _, err := os.Stat(kittyPath); err == nil {
|
||||
kittyExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Kitty",
|
||||
Path: kittyPath,
|
||||
Exists: kittyExists,
|
||||
})
|
||||
default:
|
||||
alacrittyPath := filepath.Join(os.Getenv("HOME"), ".config", "alacritty", "alacritty.toml")
|
||||
alacrittyExists := false
|
||||
if _, err := os.Stat(alacrittyPath); err == nil {
|
||||
alacrittyExists = true
|
||||
}
|
||||
configs = append(configs, ExistingConfigInfo{
|
||||
ConfigType: "Alacritty",
|
||||
Path: alacrittyPath,
|
||||
Exists: alacrittyExists,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return configCheckResult{
|
||||
configs: configs,
|
||||
error: nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user