feat: add CLI with TUI, self-update, install script, and terminal section on landing page
- Full-screen Bubble Tea TUI with cream background fill using PadLine/FillBlankLines - Self-update command (--update) pulling from GitHub releases - install.sh for curl one-liner installation - Terminal Lovers section on web landing page with install command and CLI features - All 7 format categories, glob/directory batch support, auto-download ffmpeg
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"strings"
|
||||
|
||||
"charm.land/lipgloss/v2"
|
||||
)
|
||||
|
||||
// ─── Pastel palette (matching the web app) ───────────────────
|
||||
|
||||
var (
|
||||
Pink = lipgloss.Color("#f472b6")
|
||||
Purple = lipgloss.Color("#a78bfa")
|
||||
Blue = lipgloss.Color("#60a5fa")
|
||||
Mint = lipgloss.Color("#34d399")
|
||||
Orange = lipgloss.Color("#fb923c")
|
||||
Teal = lipgloss.Color("#2dd4bf")
|
||||
|
||||
Cream = lipgloss.Color("#fdf6ef")
|
||||
Warm = lipgloss.Color("#faf0e6")
|
||||
Peach = lipgloss.Color("#fce8d5")
|
||||
|
||||
Dark = lipgloss.Color("#2d1f14")
|
||||
Mid = lipgloss.Color("#8b7355")
|
||||
Light = lipgloss.Color("#bfa98a")
|
||||
|
||||
Red = lipgloss.Color("#f43f5e")
|
||||
DimBg = lipgloss.Color("#f6f6f6")
|
||||
BorderCl = lipgloss.Color("#e8e0d4")
|
||||
|
||||
// Full-screen background
|
||||
ScreenBg = lipgloss.Color("#fdf6ef") // Cream — matches the web app
|
||||
)
|
||||
|
||||
// ─── Category colors ─────────────────────────────────────────
|
||||
|
||||
func CategoryColor(cat string) color.Color {
|
||||
switch cat {
|
||||
case "image":
|
||||
return Pink
|
||||
case "document":
|
||||
return Blue
|
||||
case "audio":
|
||||
return Purple
|
||||
case "video":
|
||||
return Orange
|
||||
case "data":
|
||||
return Mint
|
||||
case "font":
|
||||
return Teal
|
||||
case "spreadsheet":
|
||||
return Mint
|
||||
default:
|
||||
return Light
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Reusable styles ─────────────────────────────────────────
|
||||
|
||||
var (
|
||||
// Title bar
|
||||
TitleBar = lipgloss.NewStyle().
|
||||
Bold(true).
|
||||
Foreground(Dark).
|
||||
Background(ScreenBg).
|
||||
Padding(0, 2)
|
||||
|
||||
// Header / breadcrumb
|
||||
Breadcrumb = lipgloss.NewStyle().
|
||||
Foreground(Mid).
|
||||
Bold(false)
|
||||
|
||||
BreadcrumbActive = lipgloss.NewStyle().
|
||||
Foreground(Dark).
|
||||
Bold(true)
|
||||
|
||||
// File row
|
||||
FileName = lipgloss.NewStyle().
|
||||
Foreground(Dark).
|
||||
Bold(true)
|
||||
|
||||
FileSize = lipgloss.NewStyle().
|
||||
Foreground(Light)
|
||||
|
||||
ExtBadge = func(c color.Color) lipgloss.Style {
|
||||
return lipgloss.NewStyle().
|
||||
Foreground(c).
|
||||
Bold(true)
|
||||
}
|
||||
|
||||
// Status indicators
|
||||
StatusIdle = lipgloss.NewStyle().
|
||||
Foreground(Light).
|
||||
Italic(true)
|
||||
|
||||
StatusConverting = lipgloss.NewStyle().
|
||||
Foreground(Pink).
|
||||
Bold(true)
|
||||
|
||||
StatusDone = lipgloss.NewStyle().
|
||||
Foreground(Mint).
|
||||
Bold(true)
|
||||
|
||||
StatusError = lipgloss.NewStyle().
|
||||
Foreground(Red).
|
||||
Bold(true)
|
||||
|
||||
// Buttons / actions
|
||||
ButtonPrimary = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#ffffff")).
|
||||
Background(Pink).
|
||||
Bold(true).
|
||||
Padding(0, 2)
|
||||
|
||||
ButtonSecondary = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#ffffff")).
|
||||
Background(Mint).
|
||||
Bold(true).
|
||||
Padding(0, 2)
|
||||
|
||||
// Progress bar
|
||||
ProgressFilled = lipgloss.NewStyle().
|
||||
Foreground(Pink)
|
||||
|
||||
ProgressEmpty = lipgloss.NewStyle().
|
||||
Foreground(BorderCl)
|
||||
|
||||
// Help / footer
|
||||
Help = lipgloss.NewStyle().
|
||||
Foreground(Light).
|
||||
Italic(true)
|
||||
|
||||
// Cursor / selection
|
||||
Selected = lipgloss.NewStyle().
|
||||
Bold(true).
|
||||
Foreground(Pink)
|
||||
|
||||
Unselected = lipgloss.NewStyle().
|
||||
Foreground(Dark)
|
||||
|
||||
// Divider
|
||||
Divider = lipgloss.NewStyle().
|
||||
Foreground(BorderCl)
|
||||
|
||||
// Logo / branding
|
||||
Logo = lipgloss.NewStyle().
|
||||
Foreground(Pink).
|
||||
Bold(true)
|
||||
)
|
||||
|
||||
// PadLine pads a single rendered line to the given width with the screen
|
||||
// background color. This ensures every line carries the background color
|
||||
// all the way to the right edge of the terminal.
|
||||
func PadLine(line string, width int) string {
|
||||
w := lipgloss.Width(line)
|
||||
if w >= width {
|
||||
return line
|
||||
}
|
||||
pad := lipgloss.NewStyle().
|
||||
Background(ScreenBg).
|
||||
Render(strings.Repeat(" ", width-w))
|
||||
return line + pad
|
||||
}
|
||||
|
||||
// FillBlankLines returns n blank lines fully painted with the screen
|
||||
// background color at the given width.
|
||||
func FillBlankLines(n, width int) string {
|
||||
if n <= 0 {
|
||||
return ""
|
||||
}
|
||||
blankLine := lipgloss.NewStyle().
|
||||
Background(ScreenBg).
|
||||
Render(strings.Repeat(" ", width))
|
||||
lines := make([]string, n)
|
||||
for i := range lines {
|
||||
lines[i] = blankLine
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
Reference in New Issue
Block a user