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,88 @@
|
||||
package main
|
||||
|
||||
import "github.com/charmbracelet/bubbles/key"
|
||||
|
||||
type keyMap struct {
|
||||
Up key.Binding
|
||||
Down key.Binding
|
||||
Top key.Binding
|
||||
Bottom key.Binding
|
||||
Tab key.Binding
|
||||
ShiftTab key.Binding
|
||||
FocusInput key.Binding
|
||||
Unfocus key.Binding
|
||||
Quit key.Binding
|
||||
Help key.Binding
|
||||
Send key.Binding
|
||||
MemberToggle key.Binding
|
||||
ChannelPicker key.Binding
|
||||
}
|
||||
|
||||
var keys = keyMap{
|
||||
Up: key.NewBinding(
|
||||
key.WithKeys("k", "up"),
|
||||
key.WithHelp("k/↑", "up"),
|
||||
),
|
||||
Down: key.NewBinding(
|
||||
key.WithKeys("j", "down"),
|
||||
key.WithHelp("j/↓", "down"),
|
||||
),
|
||||
Top: key.NewBinding(
|
||||
key.WithKeys("g"),
|
||||
key.WithHelp("g", "top"),
|
||||
),
|
||||
Bottom: key.NewBinding(
|
||||
key.WithKeys("G"),
|
||||
key.WithHelp("G", "bottom"),
|
||||
),
|
||||
Tab: key.NewBinding(
|
||||
key.WithKeys("tab"),
|
||||
key.WithHelp("tab", "next pane"),
|
||||
),
|
||||
ShiftTab: key.NewBinding(
|
||||
key.WithKeys("shift+tab"),
|
||||
key.WithHelp("shift+tab", "prev pane"),
|
||||
),
|
||||
FocusInput: key.NewBinding(
|
||||
key.WithKeys("i"),
|
||||
key.WithHelp("i", "focus input"),
|
||||
),
|
||||
Unfocus: key.NewBinding(
|
||||
key.WithKeys("esc"),
|
||||
key.WithHelp("esc", "unfocus"),
|
||||
),
|
||||
Quit: key.NewBinding(
|
||||
key.WithKeys("q", "ctrl+c"),
|
||||
key.WithHelp("q", "quit"),
|
||||
),
|
||||
Help: key.NewBinding(
|
||||
key.WithKeys("?"),
|
||||
key.WithHelp("?", "help"),
|
||||
),
|
||||
Send: key.NewBinding(
|
||||
key.WithKeys("enter"),
|
||||
key.WithHelp("enter", "send"),
|
||||
),
|
||||
MemberToggle: key.NewBinding(
|
||||
key.WithKeys("m"),
|
||||
key.WithHelp("m", "toggle members"),
|
||||
),
|
||||
ChannelPicker: key.NewBinding(
|
||||
key.WithKeys("/"),
|
||||
key.WithHelp("/", "channels"),
|
||||
),
|
||||
}
|
||||
|
||||
// helpItems returns relevant help items based on the current focus.
|
||||
func helpItems(focused focusArea) []key.Binding {
|
||||
switch focused {
|
||||
case focusInput:
|
||||
return []key.Binding{keys.Send, keys.Unfocus}
|
||||
default:
|
||||
return []key.Binding{
|
||||
keys.Up, keys.Down, keys.Top, keys.Bottom,
|
||||
keys.Tab, keys.FocusInput, keys.MemberToggle,
|
||||
keys.ChannelPicker, keys.Help, keys.Quit,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user