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
89 lines
1.8 KiB
Go
89 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
var (
|
|
version = "dev"
|
|
commit = "unknown"
|
|
)
|
|
|
|
func main() {
|
|
// Flags
|
|
serverFlag := flag.String("server", "", "Server URL (e.g. https://chat.example.com)")
|
|
tokenFlag := flag.String("token", "", "Session token (skips login)")
|
|
versionFlag := flag.Bool("version", false, "Print version and exit")
|
|
flag.Parse()
|
|
|
|
if *versionFlag {
|
|
fmt.Printf("dumpster-tui %s (%s)\n", version, commit)
|
|
os.Exit(0)
|
|
}
|
|
|
|
// Load config
|
|
cfg, err := LoadConfig()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Apply flags over config
|
|
if *serverFlag != "" {
|
|
cfg.ServerURL = *serverFlag
|
|
}
|
|
if *tokenFlag != "" {
|
|
cfg.Token = *tokenFlag
|
|
}
|
|
|
|
// Create API client
|
|
api := NewAPIClient(cfg.ServerURL)
|
|
|
|
// Auth flow
|
|
if cfg.Token == "" {
|
|
token, err := RunAuth(api)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Authentication failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
cfg.Token = token
|
|
|
|
// Save token for future sessions
|
|
if err := SaveConfig(cfg); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Warning: could not save config: %v\n", err)
|
|
}
|
|
} else {
|
|
api.SetToken(cfg.Token)
|
|
}
|
|
|
|
// Verify auth
|
|
user, err := api.GetMe()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Session invalid or expired: %v\n", err)
|
|
fmt.Fprintf(os.Stderr, "Try logging in again.\n")
|
|
os.Exit(1)
|
|
}
|
|
fmt.Println(SuccessStyle.Render(fmt.Sprintf(" ✓ Logged in as %s", user.Username)))
|
|
|
|
// Start TUI
|
|
m := initialModel(api)
|
|
m.user = *user
|
|
|
|
p := tea.NewProgram(m,
|
|
tea.WithAltScreen(),
|
|
tea.WithMouseCellMotion(),
|
|
)
|
|
|
|
lipgloss.SetHasDarkBackground(true)
|
|
|
|
if _, err := p.Run(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|