feat: replace clipboard copy with config display for SSH sessions
Created ConfigDisplay component that shows full client configuration in a scrollable modal window, replacing non-functional clipboard copy. Benefits: - Works over SSH sessions (no clipboard API needed) - Shows complete configuration, not just public key - Scrollable for long configs with keyboard navigation - Users can select and copy text directly in terminal Changes: - Created internal/tui/components/config-display.go - Updated detail.go to replace copyPublicKey with loadConfig - Removed clipboard-related fields and message type - Updated help text: 'c' now shows config - Key bindings for scrolling: ↑↓, pgup/pgdn, g/G, Esc/q to close Fixes: wg-admin-qtb
This commit is contained in:
@@ -12,15 +12,15 @@ import (
|
||||
|
||||
// DetailScreen displays detailed information about a single WireGuard client
|
||||
type DetailScreen struct {
|
||||
client wireguard.Client
|
||||
status string
|
||||
lastHandshake time.Time
|
||||
transferRx string
|
||||
transferTx string
|
||||
confirmModal *components.DeleteConfirmModel
|
||||
showConfirm bool
|
||||
clipboardCopied bool
|
||||
clipboardTimer int
|
||||
client wireguard.Client
|
||||
status string
|
||||
lastHandshake time.Time
|
||||
transferRx string
|
||||
transferTx string
|
||||
confirmModal *components.DeleteConfirmModel
|
||||
showConfirm bool
|
||||
configDisplay *components.ConfigDisplayModel
|
||||
showConfig bool
|
||||
}
|
||||
|
||||
// Styles
|
||||
@@ -71,15 +71,6 @@ func (s *DetailScreen) Init() tea.Cmd {
|
||||
func (s *DetailScreen) Update(msg tea.Msg) (Screen, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
// Handle clipboard copy timeout
|
||||
if s.clipboardCopied {
|
||||
s.clipboardTimer++
|
||||
if s.clipboardTimer > 2 {
|
||||
s.clipboardCopied = false
|
||||
s.clipboardTimer = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Handle confirmation modal
|
||||
if s.showConfirm && s.confirmModal != nil {
|
||||
_, cmd = s.confirmModal.Update(msg)
|
||||
@@ -100,10 +91,21 @@ func (s *DetailScreen) Update(msg tea.Msg) (Screen, tea.Cmd) {
|
||||
return s, cmd
|
||||
}
|
||||
|
||||
// Handle config display modal
|
||||
if s.showConfig && s.configDisplay != nil {
|
||||
_, cmd = s.configDisplay.Update(msg)
|
||||
|
||||
// Handle modal close
|
||||
if !s.configDisplay.IsVisible() {
|
||||
s.showConfig = false
|
||||
return s, nil
|
||||
}
|
||||
|
||||
return s, cmd
|
||||
}
|
||||
|
||||
// Handle normal screen messages
|
||||
switch msg := msg.(type) {
|
||||
case clipboardCopiedMsg:
|
||||
s.clipboardCopied = true
|
||||
case clientStatusLoadedMsg:
|
||||
s.status = msg.status
|
||||
s.lastHandshake = msg.lastHandshake
|
||||
@@ -123,8 +125,8 @@ func (s *DetailScreen) Update(msg tea.Msg) (Screen, tea.Cmd) {
|
||||
)
|
||||
s.showConfirm = true
|
||||
case "c":
|
||||
// Copy public key to clipboard
|
||||
return s, s.copyPublicKey()
|
||||
// Show client configuration
|
||||
return s, s.loadConfig()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +135,12 @@ func (s *DetailScreen) Update(msg tea.Msg) (Screen, tea.Cmd) {
|
||||
|
||||
// View renders the detail screen
|
||||
func (s *DetailScreen) View() string {
|
||||
// Handle config display modal
|
||||
if s.showConfig && s.configDisplay != nil {
|
||||
return s.configDisplay.View()
|
||||
}
|
||||
|
||||
// Handle confirmation modal
|
||||
if s.showConfirm && s.confirmModal != nil {
|
||||
// Render underlying content dimmed
|
||||
content := s.renderContent()
|
||||
@@ -186,14 +194,9 @@ func (s *DetailScreen) renderContent() string {
|
||||
)
|
||||
|
||||
// Add help text
|
||||
helpText := detailHelpStyle.Render("Actions: [d] Delete • [c] Copy Public Key • [b] Back")
|
||||
helpText := detailHelpStyle.Render("Actions: [d] Delete • [c] View Config • [b] Back")
|
||||
content = lipgloss.JoinVertical(lipgloss.Left, content, helpText)
|
||||
|
||||
// Show clipboard confirmation
|
||||
if s.clipboardCopied {
|
||||
content += "\n" + lipgloss.NewStyle().Foreground(lipgloss.Color("46")).Render("✓ Public key copied to clipboard!")
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
@@ -252,13 +255,22 @@ func (s *DetailScreen) loadClientStatus() tea.Msg {
|
||||
}
|
||||
}
|
||||
|
||||
// copyPublicKey copies the public key to clipboard
|
||||
func (s *DetailScreen) copyPublicKey() tea.Cmd {
|
||||
// loadConfig loads and displays the client configuration
|
||||
func (s *DetailScreen) loadConfig() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
// Note: In a real implementation, you would use a clipboard library like
|
||||
// github.com/atotto/clipboard or implement platform-specific clipboard access
|
||||
// For now, we'll just simulate the action
|
||||
return clipboardCopiedMsg{}
|
||||
config, err := wireguard.GetClientConfigContent(s.client.Name)
|
||||
if err != nil {
|
||||
return errMsg{fmt.Errorf("failed to load client config: %w", err)}
|
||||
}
|
||||
|
||||
// Create or update config display modal
|
||||
if s.configDisplay == nil {
|
||||
s.configDisplay = components.NewConfigDisplay(config, 80, 24)
|
||||
} else {
|
||||
s.configDisplay.Show(config)
|
||||
}
|
||||
s.showConfig = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +296,3 @@ type clientStatusLoadedMsg struct {
|
||||
transferRx string
|
||||
transferTx string
|
||||
}
|
||||
|
||||
// clipboardCopiedMsg is sent when public key is copied to clipboard
|
||||
type clipboardCopiedMsg struct{}
|
||||
|
||||
Reference in New Issue
Block a user