Files
wg-admin/cmd/wg-tui/main.go
Calmcacil 5d129562e2 fix: Properly parse compound handshake time and fix q key handling
- 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
2026-01-12 19:27:21 +01:00

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)
}
}