mirror of
https://github.com/lukaszraczylo/lolcathost.git
synced 2026-06-05 23:29:18 +00:00
182 lines
4.0 KiB
Go
182 lines
4.0 KiB
Go
// Package tui provides the terminal user interface.
|
|
package tui
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
// Colors - matching kportal style, optimized for dark terminals
|
|
var (
|
|
colorPrimary = lipgloss.Color("205") // Pink/Magenta
|
|
colorSuccess = lipgloss.Color("42") // Green
|
|
colorWarning = lipgloss.Color("220") // Yellow
|
|
colorError = lipgloss.Color("196") // Red
|
|
colorMuted = lipgloss.Color("245") // Gray (brighter for dark terminals)
|
|
colorAccent = lipgloss.Color("141") // Light purple (brighter for dark terminals)
|
|
colorHeader = lipgloss.Color("220") // Yellow for headers
|
|
colorSelectedBg = lipgloss.Color("236") // Gray background for selection
|
|
colorSelectedFg = lipgloss.Color("255") // White foreground for selection
|
|
colorGroupHeader = lipgloss.Color("213") // Light pink for group headers
|
|
)
|
|
|
|
// Title and header styles
|
|
var (
|
|
titleStyle = lipgloss.NewStyle().
|
|
Bold(true).
|
|
Foreground(colorHeader).
|
|
Padding(0, 1)
|
|
)
|
|
|
|
// Status indicators
|
|
var (
|
|
enabledStyle = lipgloss.NewStyle().
|
|
Foreground(colorSuccess).
|
|
Bold(true)
|
|
|
|
disabledStyle = lipgloss.NewStyle().
|
|
Foreground(colorMuted)
|
|
)
|
|
|
|
// Status bar and help
|
|
var (
|
|
statusBarStyle = lipgloss.NewStyle().
|
|
Foreground(colorMuted)
|
|
|
|
connectedStyle = lipgloss.NewStyle().
|
|
Foreground(colorSuccess).
|
|
SetString("Connected")
|
|
|
|
disconnectedStyle = lipgloss.NewStyle().
|
|
Foreground(colorError).
|
|
SetString("Disconnected")
|
|
|
|
helpBarStyle = lipgloss.NewStyle().
|
|
Foreground(colorMuted)
|
|
|
|
helpKeyStyle = lipgloss.NewStyle().
|
|
Foreground(colorHeader).
|
|
Bold(true)
|
|
|
|
helpDescStyle = lipgloss.NewStyle().
|
|
Foreground(colorMuted)
|
|
)
|
|
|
|
// Message styles
|
|
var (
|
|
errorMsgStyle = lipgloss.NewStyle().
|
|
Foreground(colorError).
|
|
Bold(true).
|
|
MarginTop(1)
|
|
|
|
successMsgStyle = lipgloss.NewStyle().
|
|
Foreground(colorSuccess).
|
|
MarginTop(1)
|
|
|
|
updateStyle = lipgloss.NewStyle().
|
|
Foreground(colorSuccess).
|
|
Bold(true)
|
|
)
|
|
|
|
// Form styles
|
|
var (
|
|
inputLabelStyle = lipgloss.NewStyle().
|
|
Foreground(colorPrimary).
|
|
Bold(true)
|
|
|
|
inputStyle = lipgloss.NewStyle().
|
|
Border(lipgloss.RoundedBorder()).
|
|
BorderForeground(colorMuted).
|
|
Padding(0, 1)
|
|
|
|
inputFocusStyle = lipgloss.NewStyle().
|
|
Border(lipgloss.RoundedBorder()).
|
|
BorderForeground(colorPrimary).
|
|
Padding(0, 1)
|
|
)
|
|
|
|
// Dialog/modal styles
|
|
var (
|
|
dialogStyle = lipgloss.NewStyle().
|
|
Border(lipgloss.RoundedBorder()).
|
|
BorderForeground(colorAccent).
|
|
Padding(1, 2)
|
|
|
|
presetItemStyle = lipgloss.NewStyle().
|
|
Padding(0, 1)
|
|
|
|
presetSelectedStyle = lipgloss.NewStyle().
|
|
Background(colorSelectedBg).
|
|
Foreground(colorSelectedFg).
|
|
Padding(0, 1)
|
|
)
|
|
|
|
// WrapHelpText wraps help text to fit within maxWidth, splitting on bullet separators.
|
|
// If maxWidth is 0 or negative, returns the original text.
|
|
func WrapHelpText(text string, maxWidth int) string {
|
|
if maxWidth <= 0 {
|
|
return helpDescStyle.Render(text)
|
|
}
|
|
|
|
separator := " • "
|
|
parts := splitOnSeparator(text, separator)
|
|
|
|
var lines []string
|
|
var currentLine string
|
|
var currentWidth int
|
|
|
|
for i, part := range parts {
|
|
partWidth := len(part)
|
|
sepWidth := 3 // len(" • ")
|
|
|
|
newWidth := currentWidth + partWidth
|
|
if currentWidth > 0 {
|
|
newWidth += sepWidth
|
|
}
|
|
|
|
if newWidth > maxWidth && currentWidth > 0 {
|
|
lines = append(lines, currentLine)
|
|
currentLine = part
|
|
currentWidth = partWidth
|
|
} else {
|
|
if currentWidth > 0 {
|
|
currentLine += separator
|
|
}
|
|
currentLine += part
|
|
if i == 0 {
|
|
currentWidth = partWidth
|
|
} else {
|
|
currentWidth = newWidth
|
|
}
|
|
}
|
|
}
|
|
|
|
if currentLine != "" {
|
|
lines = append(lines, currentLine)
|
|
}
|
|
|
|
// Apply style to each line and join
|
|
var result []string
|
|
for _, line := range lines {
|
|
result = append(result, helpDescStyle.Render(line))
|
|
}
|
|
|
|
return strings.Join(result, "\n")
|
|
}
|
|
|
|
// splitOnSeparator splits a string on the given separator.
|
|
func splitOnSeparator(s, sep string) []string {
|
|
var parts []string
|
|
for {
|
|
idx := strings.Index(s, sep)
|
|
if idx == -1 {
|
|
parts = append(parts, s)
|
|
break
|
|
}
|
|
parts = append(parts, s[:idx])
|
|
s = s[idx+len(sep):]
|
|
}
|
|
return parts
|
|
}
|