- Fix parseHandshake to correctly parse number-unit pairs from '14 hours, 24 minutes, 40 seconds ago' Previous logic tried to parse unit words instead of finding associated numbers Now correctly accumulates all time units (hours, minutes, seconds) - Fix q key handling to properly check screen type before quitting Only quit application when 'q' is pressed on list screen Other screens (detail, add, help) now handle 'q' to navigate back Note: q key navigation may still need investigation for edge cases
146 lines
4.1 KiB
Go
146 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
|
|
"github.com/calmcacil/wg-admin/internal/config"
|
|
"github.com/calmcacil/wg-admin/internal/tui/screens"
|
|
)
|
|
|
|
const version = "0.1.0"
|
|
|
|
var (
|
|
styleTitle = lipgloss.NewStyle().Foreground(lipgloss.Color("62")).Bold(true)
|
|
styleSubtitle = lipgloss.NewStyle().Foreground(lipgloss.Color("241"))
|
|
styleSuccess = lipgloss.NewStyle().Foreground(lipgloss.Color("46"))
|
|
styleError = lipgloss.NewStyle().Foreground(lipgloss.Color("196"))
|
|
styleHelpKey = lipgloss.NewStyle().Foreground(lipgloss.Color("63")).Bold(true)
|
|
)
|
|
|
|
type model struct {
|
|
currentScreen screens.Screen
|
|
previousScreen screens.Screen
|
|
quitting bool
|
|
initialized bool
|
|
}
|
|
|
|
func (m model) Init() tea.Cmd {
|
|
if os.Geteuid() != 0 {
|
|
fmt.Println(styleError.Render("ERROR: Must run as root"))
|
|
os.Exit(1)
|
|
}
|
|
_, _ = config.LoadConfig()
|
|
return nil
|
|
}
|
|
|
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
// Handle initialization on first update after Init
|
|
if !m.initialized {
|
|
m.initialized = true
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
}
|
|
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
// Only quit on 'q' or ctrl+c when on list screen
|
|
// Other screens handle their own navigation keys
|
|
if msg.String() == "q" || msg.String() == "ctrl+c" {
|
|
if _, ok := m.currentScreen.(*screens.ListScreen); ok {
|
|
m.quitting = true
|
|
return m, tea.Quit
|
|
}
|
|
// For other screens, let them handle the key
|
|
}
|
|
switch msg.String() {
|
|
case "?":
|
|
// Switch to help screen
|
|
m.previousScreen = m.currentScreen
|
|
m.currentScreen = screens.NewHelpScreen(m.previousScreen)
|
|
return m, m.currentScreen.Init()
|
|
case "l":
|
|
// Switch to list screen
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
case "a":
|
|
// Switch to add screen
|
|
m.previousScreen = m.currentScreen
|
|
m.currentScreen = screens.NewAddScreen()
|
|
return m, m.currentScreen.Init()
|
|
}
|
|
case screens.ClientSelectedMsg:
|
|
// User selected a client - show detail screen
|
|
m.previousScreen = m.currentScreen
|
|
m.currentScreen = screens.NewDetailScreen(msg.Client.Client)
|
|
return m, m.currentScreen.Init()
|
|
case screens.ClientDeletedMsg:
|
|
// Client was deleted - show success message and return to list
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
case screens.ClientCreatedMsg:
|
|
// Client was created - return to list screen
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
case screens.RestoreCompletedMsg:
|
|
// Restore completed - return to list screen to refresh clients
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
case screens.CloseDetailScreenMsg:
|
|
// Detail screen closed - go back to previous screen
|
|
if m.previousScreen != nil {
|
|
m.currentScreen = m.previousScreen
|
|
m.previousScreen = nil
|
|
return m, m.currentScreen.Init()
|
|
}
|
|
m.currentScreen = screens.NewListScreen()
|
|
return m, m.currentScreen.Init()
|
|
}
|
|
|
|
// Pass messages to current screen
|
|
if m.currentScreen != nil {
|
|
newScreen, cmd := m.currentScreen.Update(msg)
|
|
// If screen returns nil, go back to previous screen
|
|
if newScreen == nil {
|
|
if m.previousScreen != nil {
|
|
m.currentScreen = m.previousScreen
|
|
m.previousScreen = nil
|
|
}
|
|
} else if newScreen != m.currentScreen {
|
|
// Screen is switching to a different screen
|
|
m.previousScreen = m.currentScreen
|
|
m.currentScreen = newScreen
|
|
}
|
|
return m, cmd
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func (m model) View() string {
|
|
if m.quitting {
|
|
return "\nGoodbye!\n"
|
|
}
|
|
|
|
if m.currentScreen != nil && m.initialized {
|
|
return m.currentScreen.View()
|
|
}
|
|
|
|
title := styleTitle.Render("WireGuard Client Manager")
|
|
subtitle := styleSubtitle.Render(fmt.Sprintf("v%s", version))
|
|
bar := fmt.Sprintf("Press %s for help, %s to quit", styleHelpKey.Render("?"), styleHelpKey.Render("q"))
|
|
|
|
return title + " " + subtitle + "\n\nInitializing...\n\n" + bar
|
|
}
|
|
|
|
func main() {
|
|
p := tea.NewProgram(model{}, tea.WithAltScreen())
|
|
if _, err := p.Run(); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|