2a6b3830d5
- cmd/tui/main.go: entry point with --server, --token, --version flags
- cmd/tui/config.go: config from ~/.config/dumpster/config.yaml or env vars
- cmd/tui/auth.go: login flow, session cookie management
- cmd/tui/api.go: HTTP client for servers, channels, messages, voice
- cmd/tui/model.go: root bubbletea model with state management
- cmd/tui/theme.go: Gruvbox dark lipgloss styles
- cmd/tui/servers.go: server bar with [D] style initials
- cmd/tui/channels.go: channel list with #text and 🔊 voice
- cmd/tui/chat.go: IRC-style message viewport with colored usernames
- cmd/tui/input.go: message input with > _ prompt
- cmd/tui/members.go: member list with ●/◐/○ status
- cmd/tui/ws.go: WebSocket client for real-time events
- cmd/tui/voice.go: voice state tracking and mute toggle
- cmd/tui/keys.go: vim-style keybindings (j/k, g/G, Tab, /, etc)
- cmd/tui/views.go: multi-pane layout rendering
- Makefile: added build-tui and run-tui targets
- go.mod/go.sum: added charmbracelet dependencies
160 lines
3.5 KiB
Go
160 lines
3.5 KiB
Go
package main
|
|
|
|
import "github.com/charmbracelet/lipgloss"
|
|
|
|
// Gruvbox dark palette
|
|
var (
|
|
bg = lipgloss.Color("#282828")
|
|
bgS = lipgloss.Color("#3c3836")
|
|
bgT = lipgloss.Color("#504945")
|
|
fg = lipgloss.Color("#ebdbb2")
|
|
fgS = lipgloss.Color("#d5c4a1")
|
|
fgF = lipgloss.Color("#a89984")
|
|
red = lipgloss.Color("#fb4934")
|
|
grn = lipgloss.Color("#b8bb26")
|
|
org = lipgloss.Color("#fe8019")
|
|
aqua = lipgloss.Color("#8ec07c")
|
|
yel = lipgloss.Color("#fabd2f")
|
|
)
|
|
|
|
// Styles
|
|
var (
|
|
// Layout panes
|
|
ServerBarStyle = lipgloss.NewStyle().
|
|
Background(bgS).
|
|
Foreground(fg).
|
|
Padding(0, 1).
|
|
Border(lipgloss.NormalBorder(), false, true, false, false).
|
|
BorderForeground(bgT)
|
|
|
|
ChannelListStyle = lipgloss.NewStyle().
|
|
Background(bgS).
|
|
Foreground(fg).
|
|
Padding(0, 1)
|
|
|
|
ChatPaneStyle = lipgloss.NewStyle().
|
|
Background(bg).
|
|
Foreground(fg).
|
|
Padding(0, 1)
|
|
|
|
MemberListStyle = lipgloss.NewStyle().
|
|
Background(bgS).
|
|
Foreground(fg).
|
|
Padding(0, 1)
|
|
|
|
InputPaneStyle = lipgloss.NewStyle().
|
|
Background(bgS).
|
|
Foreground(fg).
|
|
Padding(0, 1)
|
|
|
|
// Focus indicators
|
|
FocusedBorder = lipgloss.NewStyle().
|
|
Border(lipgloss.NormalBorder(), false, false, true, false).
|
|
BorderForeground(aqua)
|
|
|
|
UnfocusedBorder = lipgloss.NewStyle().
|
|
Border(lipgloss.NormalBorder(), false, false, true, false).
|
|
BorderForeground(bgT)
|
|
|
|
// Server list
|
|
ServerActive = lipgloss.NewStyle().
|
|
Background(aqua).
|
|
Foreground(bg).
|
|
Bold(true).
|
|
Padding(0, 1).
|
|
Align(lipgloss.Center)
|
|
|
|
ServerInactive = lipgloss.NewStyle().
|
|
Background(bgS).
|
|
Foreground(fgF).
|
|
Padding(0, 1).
|
|
Align(lipgloss.Center)
|
|
|
|
ServerHover = lipgloss.NewStyle().
|
|
Background(bgT).
|
|
Foreground(fg).
|
|
Padding(0, 1).
|
|
Align(lipgloss.Center)
|
|
|
|
// Channel list
|
|
CategoryStyle = lipgloss.NewStyle().
|
|
Foreground(fgF).
|
|
Bold(true).
|
|
PaddingTop(1)
|
|
|
|
ChannelActive = lipgloss.NewStyle().
|
|
Foreground(fg).
|
|
Bold(true).
|
|
PaddingLeft(1)
|
|
|
|
ChannelInactive = lipgloss.NewStyle().
|
|
Foreground(fgF).
|
|
PaddingLeft(1)
|
|
|
|
ChannelHover = lipgloss.NewStyle().
|
|
Foreground(fg).
|
|
PaddingLeft(1)
|
|
|
|
VoiceChannelPrefix = lipgloss.NewStyle().Foreground(aqua)
|
|
TextChannelPrefix = lipgloss.NewStyle().Foreground(fgF)
|
|
|
|
// Chat
|
|
MessageStyle = lipgloss.NewStyle().
|
|
Foreground(fg)
|
|
|
|
TimestampStyle = lipgloss.NewStyle().
|
|
Foreground(fgF)
|
|
|
|
UsernameStyle = lipgloss.NewStyle().
|
|
Bold(true)
|
|
|
|
MentionStyle = lipgloss.NewStyle().
|
|
Foreground(aqua).
|
|
Bold(true)
|
|
|
|
EditedTag = lipgloss.NewStyle().
|
|
Foreground(fgF).
|
|
Italic(true)
|
|
|
|
// Status indicators
|
|
StatusOnline = lipgloss.NewStyle().Foreground(grn)
|
|
StatusIdle = lipgloss.NewStyle().Foreground(yel)
|
|
StatusOffline = lipgloss.NewStyle().Foreground(fgF)
|
|
|
|
// Voice
|
|
VoiceStatusStyle = lipgloss.NewStyle().
|
|
Background(lipgloss.Color("#1d2021")).
|
|
Foreground(aqua).
|
|
Padding(0, 1)
|
|
|
|
// Error/success
|
|
ErrorStyle = lipgloss.NewStyle().
|
|
Foreground(red).
|
|
Bold(true)
|
|
|
|
SuccessStyle = lipgloss.NewStyle().
|
|
Foreground(grn).
|
|
Bold(true)
|
|
|
|
// Help
|
|
HelpStyle = lipgloss.NewStyle().
|
|
Foreground(fgF).
|
|
Italic(true)
|
|
|
|
// Title
|
|
TitleStyle = lipgloss.NewStyle().
|
|
Foreground(aqua).
|
|
Bold(true).
|
|
Align(lipgloss.Center)
|
|
)
|
|
|
|
// UsernameColor returns a deterministic color for a username based on its content.
|
|
func UsernameColor(username string) lipgloss.Color {
|
|
colors := []lipgloss.Color{red, grn, org, aqua, yel, lipgloss.Color("#d3869b"), lipgloss.Color("#83a598")}
|
|
hash := 0
|
|
for _, c := range username {
|
|
hash += int(c)
|
|
}
|
|
return colors[hash%len(colors)]
|
|
}
|