Ztorrent/ui/styles.go

265 lines
11 KiB
Go

package ui
import (
"strings"
"github.com/charmbracelet/lipgloss"
)
// Color definitions (Hex palette)
const (
ColorBg = "#0b1017" // Dark slate background
ColorCardBg = "#121a24" // Dark grey cards
ColorBorder = "#2e3b4e" // Dark slate borders
ColorText = "#e0ecf6" // Light grey text
ColorSubdued = "#8c9ba5" // Subdued slate text
ColorCyan = "#00ffd2" // Bright teal/cyan accent
ColorPink = "#ff2a85" // Hot pink accent
ColorGreen = "#3cd58c" // Vibrant green (completed)
ColorYellow = "#f4b942" // Amber/yellow (downloading)
ColorRed = "#ff5555" // Bright red (error/missing)
ColorBlue = "#00aeff" // Vibrant blue (dht)
)
var (
// Base styles
StyleBg = lipgloss.NewStyle().
Background(lipgloss.Color(ColorBg)).
Foreground(lipgloss.Color(ColorText))
StyleTitle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorCyan)).
Border(lipgloss.DoubleBorder(), true).
BorderForeground(lipgloss.Color(ColorCyan)).
Padding(0, 2).
MarginBottom(1)
StyleHeader = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorPink)).
MarginBottom(1)
// Status states
StyleStatusIdle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorSubdued))
StyleStatusActive = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorYellow))
StyleStatusDone = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorGreen))
StyleStatusError = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorRed))
// KPI Cards
StyleCard = lipgloss.NewStyle().
Background(lipgloss.Color(ColorCardBg)).
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color(ColorBorder)).
Padding(0, 1).
Align(lipgloss.Left)
StyleCardActive = StyleCard.
BorderForeground(lipgloss.Color(ColorCyan))
StyleCardTitle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorSubdued))
StyleCardValue = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorText))
// Tabs
StyleTab = lipgloss.NewStyle().
Padding(0, 2).
Background(lipgloss.Color(ColorCardBg)).
Foreground(lipgloss.Color(ColorSubdued)).
Border(lipgloss.NormalBorder(), false, true, false, false).
BorderForeground(lipgloss.Color(ColorBorder))
StyleActiveTab = lipgloss.NewStyle().
Bold(true).
Padding(0, 2).
Background(lipgloss.Color(ColorCardBg)).
Foreground(lipgloss.Color(ColorCyan)).
Border(lipgloss.NormalBorder(), true, true, false, true).
BorderForeground(lipgloss.Color(ColorCyan))
StyleTabsRow = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, true, false).
BorderForeground(lipgloss.Color(ColorBorder)).
MarginBottom(1)
// Input form
StyleInputLabel = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorCyan)).
Width(15)
StyleInputFocused = lipgloss.NewStyle().
Foreground(lipgloss.Color(ColorCyan)).
BorderForeground(lipgloss.Color(ColorCyan))
StyleInputUnfocused = lipgloss.NewStyle().
Foreground(lipgloss.Color(ColorSubdued)).
BorderForeground(lipgloss.Color(ColorBorder))
// Help bar
StyleHelp = lipgloss.NewStyle().
Foreground(lipgloss.Color(ColorSubdued)).
MarginTop(1)
StyleKey = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorPink))
// Tables
StyleTableHeader = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(ColorCyan))
StyleTableRowSelected = lipgloss.NewStyle().
Background(lipgloss.Color(ColorBorder)).
Foreground(lipgloss.Color(ColorCyan)).
Bold(true)
// Grid colors
StylePieceCompleted = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorGreen))
StylePieceDownloading = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorYellow))
StylePieceMissing = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBorder))
// ── Кэшированные стили для горячих путей рендеринга ──────────────────────
// Dashboard header
StyleHeaderBrand = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink)).Bold(true)
StyleHeaderSep = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBorder))
StyleHeaderName = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText))
StyleHeaderIcon = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleHeaderLine = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, true, false).
BorderForeground(lipgloss.Color(ColorBorder)).
PaddingBottom(0)
// Phase status styles
StylePhaseStopped = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued)).Bold(true)
StylePhaseFailed = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorRed)).Bold(true)
StylePhaseSeeding = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorGreen)).Bold(true)
StylePhaseDownload = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan)).Bold(true)
StylePhaseDefault = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorYellow)).Bold(true)
// KPI cards
StyleKPIProgress = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorCyan))
StyleKPIDown = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorGreen))
StyleKPIUp = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorYellow))
StyleKPIEta = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorPink))
StyleKPIPeers = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorText))
StyleKPIBarFill = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan))
StyleKPIBarEmpty = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBorder))
// Menu styles
StyleMenuText = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText))
StyleMenuDesc = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleMenuActive = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan)).Bold(true)
StyleMenuCursor = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink))
StyleMenuHelp = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued)).MarginTop(2)
StyleMenuBorder = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBorder))
StyleMenuPadding = lipgloss.NewStyle().Padding(2, 4)
StyleMenuBox = lipgloss.NewStyle().Padding(2, 0)
// Log overlay styles
StyleLogTime = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleLogEngine = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink)).Bold(true)
StyleLogDHT = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBlue)).Bold(true)
StyleLogPeer = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorGreen)).Bold(true)
StyleLogSys = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan)).Bold(true)
StyleLogDefault = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText)).Bold(true)
StyleLogError = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorRed)).Bold(true)
StyleLogWarn = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorYellow)).Bold(true)
StyleLogInfo = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan))
StyleLogDebug = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleLogMsg = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText))
StyleLogMsgError = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorRed))
// Overview styles
StyleSectionTitle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorCyan))
StyleDim = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleVal = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText))
StyleSpeedDown = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorGreen)).Bold(true)
StyleSpeedUp = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorYellow)).Bold(true)
StyleETA = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink)).Bold(true)
StyleErrText = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorRed)).Bold(true)
// HelpBar
StyleHelpKey = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink)).Bold(true)
StyleHelpDesc = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued))
StyleHelpSep = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorBorder))
StyleHelpBar = lipgloss.NewStyle().
Foreground(lipgloss.Color(ColorSubdued)).
Border(lipgloss.NormalBorder(), true, false, false, false).
BorderForeground(lipgloss.Color(ColorBorder)).
MarginTop(1).
PaddingTop(0)
// Logo
StyleLogoTorrent = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText)).Bold(true)
StyleLogoZ = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorGreen)).Bold(true)
// Settings indicator
StyleSettingsCursor = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink))
StyleSettingsActive = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorCyan)).Bold(true)
StyleSettingsLabel = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorSubdued)).Width(26)
// Additional menu
StyleAdditCyan = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(ColorCyan))
StyleAdditPink = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorPink)).Bold(true)
StyleAdditVal = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorText))
StyleAdditShort = lipgloss.NewStyle().Foreground(lipgloss.Color(ColorYellow))
)
// Статичные строки, вычисляемые один раз
var (
// Статичный "torrent" ASCII-арт (не меняется никогда)
cachedTorrentArt = StyleLogoTorrent.Render(strings.Join([]string{
"████████╗ ██████╗ ██████╗ ██████╗ ███████╗███╗ ██╗████████╗",
"╚══██╔══╝██╔═══██╗██╔══██╗██╔══██╗██╔════╝████╗ ██║╚══██╔══╝",
" ██║ ██║ ██║██████╔╝██████╔╝█████╗ ██╔██╗ ██║ ██║ ",
" ██║ ██║ ██║██╔══██╗██╔══██╗██╔══╝ ██║╚████║ ██║ ",
" ██║ ╚██████╔╝██║ ██║██║ ██║███████╗██║ ╚███║ ██║ ",
" ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚══╝ ╚═╝ ",
}, "\n"))
// Статичный Z-логотип (при отключённых анимациях)
cachedStaticZArt = StyleLogoZ.Render(strings.Join([]string{
" ",
" ",
"███████╗",
"╚════██║",
" ██╔╝",
" ██╔╝ ",
" ██╔╝ ",
" ███████╗",
" ╚══════╝",
" ",
" ",
" ",
}, "\n"))
// Статичный help bar главного меню
cachedMenuHelp = StyleMenuHelp.Render(" ↓↑ — выбор Enter — подтвердить Q — выход")
// Статичные строки рамки меню (зависят от boxWidth=85, не меняются)
cachedMenuTopBorder = StyleMenuBorder.Render("╭" + strings.Repeat("─", 85) + "╮")
cachedMenuBottomBorder = StyleMenuBorder.Render("╰" + strings.Repeat("─", 85) + "╯")
cachedMenuLeftEdge = StyleMenuBorder.Render("│")
cachedMenuRightEdge = StyleMenuBorder.Render("│")
// Help bar dashboard
cachedHelpSep = StyleHelpSep.Render(" │ ")
)