Phase 5: TUI client (Bubbletea)
- 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
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ServerItem renders a single server in the server bar.
|
||||
func ServerItem(server Server, isActive, isHovered bool, width int) string {
|
||||
// Show first letter(s) of server name as icon
|
||||
name := server.Name
|
||||
if len(name) > 2 {
|
||||
name = name[:2]
|
||||
}
|
||||
// Use icon if available
|
||||
if server.Icon != "" {
|
||||
name = server.Icon
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
|
||||
style := ServerInactive
|
||||
if isActive {
|
||||
style = ServerActive
|
||||
} else if isHovered {
|
||||
style = ServerHover
|
||||
}
|
||||
|
||||
return style.Width(width - 2).Render(fmt.Sprintf(" %s ", name))
|
||||
}
|
||||
|
||||
// ServerBar renders the vertical server list.
|
||||
func ServerBar(servers []Server, activeIdx, hoverIdx, height int) string {
|
||||
if len(servers) == 0 {
|
||||
return ServerBarStyle.
|
||||
Width(6).
|
||||
Height(height).
|
||||
Render(HelpStyle.Render("No\nservers"))
|
||||
}
|
||||
|
||||
var items []string
|
||||
for i, s := range servers {
|
||||
items = append(items, ServerItem(s, i == activeIdx, i == hoverIdx, 6))
|
||||
}
|
||||
|
||||
bar := strings.Join(items, "\n")
|
||||
return ServerBarStyle.
|
||||
Width(6).
|
||||
Height(height).
|
||||
Render(bar)
|
||||
}
|
||||
|
||||
// ServerInitials returns 2-char initials for a server name.
|
||||
func ServerInitials(name string) string {
|
||||
if len(name) == 0 {
|
||||
return "??"
|
||||
}
|
||||
parts := strings.Fields(name)
|
||||
if len(parts) >= 2 {
|
||||
return strings.ToUpper(string([]rune(parts[0])[0:1]) + string([]rune(parts[1])[0:1]))
|
||||
}
|
||||
if len(name) >= 2 {
|
||||
return strings.ToUpper(name[:2])
|
||||
}
|
||||
return strings.ToUpper(name) + " "
|
||||
}
|
||||
Reference in New Issue
Block a user