feat(tui): show voice activity with green color and speaker icon when users talk
This commit is contained in:
@@ -71,6 +71,12 @@ type Model struct {
|
||||
|
||||
// Error handling
|
||||
lastError string
|
||||
|
||||
// Voice activity
|
||||
talkingClients map[uint16]bool // ClientID -> isTalking
|
||||
|
||||
// Program reference for sending messages from event handlers
|
||||
program *tea.Program
|
||||
}
|
||||
|
||||
// addLog adds a message to the log panel
|
||||
@@ -86,15 +92,21 @@ func (m *Model) addLog(format string, args ...any) {
|
||||
// NewModel creates a new TUI model
|
||||
func NewModel(serverAddr, nickname string) *Model {
|
||||
return &Model{
|
||||
serverAddr: serverAddr,
|
||||
nickname: nickname,
|
||||
focus: FocusChannels,
|
||||
channels: []ChannelNode{},
|
||||
chatMessages: []ChatMessage{},
|
||||
logMessages: []string{"Starting..."},
|
||||
serverAddr: serverAddr,
|
||||
nickname: nickname,
|
||||
focus: FocusChannels,
|
||||
channels: []ChannelNode{},
|
||||
chatMessages: []ChatMessage{},
|
||||
logMessages: []string{"Starting..."},
|
||||
talkingClients: make(map[uint16]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// SetProgram sets the tea.Program reference for sending messages from event handlers
|
||||
func (m *Model) SetProgram(p *tea.Program) {
|
||||
m.program = p
|
||||
}
|
||||
|
||||
// Init is called when the program starts
|
||||
func (m *Model) Init() tea.Cmd {
|
||||
return tea.Batch(
|
||||
@@ -151,6 +163,11 @@ type chatMsg struct {
|
||||
message string
|
||||
}
|
||||
|
||||
type talkingStatusMsg struct {
|
||||
clientID uint16
|
||||
talking bool
|
||||
}
|
||||
|
||||
type errorMsg struct {
|
||||
err string
|
||||
}
|
||||
@@ -172,6 +189,16 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.client = msg.client
|
||||
m.connecting = true
|
||||
|
||||
// Register event handlers that need to send messages to the TUI
|
||||
if m.program != nil {
|
||||
m.client.On(ts3client.EventTalkingStatus, func(e *ts3client.TalkingStatusEvent) {
|
||||
m.program.Send(talkingStatusMsg{
|
||||
clientID: e.ClientID,
|
||||
talking: e.Talking,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Connect asynchronously
|
||||
m.client.ConnectAsync()
|
||||
|
||||
@@ -229,6 +256,15 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.lastError = msg.err
|
||||
return m, nil
|
||||
|
||||
case talkingStatusMsg:
|
||||
// Update talking status for client
|
||||
if msg.talking {
|
||||
m.talkingClients[msg.clientID] = true
|
||||
} else {
|
||||
delete(m.talkingClients, msg.clientID)
|
||||
}
|
||||
return m, nil
|
||||
|
||||
case logMsg:
|
||||
// External log message
|
||||
m.addLog("%s", string(msg))
|
||||
@@ -264,6 +300,7 @@ func (m *Model) updateChannelList(channels []*ts3client.Channel) {
|
||||
ID: cl.ID,
|
||||
Nickname: cl.Nickname,
|
||||
IsMe: cl.ID == m.selfID,
|
||||
Talking: m.talkingClients[cl.ID],
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -478,10 +515,16 @@ func (m *Model) renderChannels() string {
|
||||
for _, user := range ch.Users {
|
||||
userPrefix := " └─ "
|
||||
userStyle := lipgloss.NewStyle().Faint(true)
|
||||
if user.IsMe {
|
||||
|
||||
// Talking users get bright green color and speaker icon
|
||||
if user.Talking {
|
||||
userStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("46")) // Bright green
|
||||
userPrefix = " └─ 🔊 "
|
||||
} else if user.IsMe {
|
||||
userStyle = userStyle.Foreground(lipgloss.Color("82"))
|
||||
userPrefix = " └─ ► "
|
||||
}
|
||||
|
||||
lines = append(lines, userStyle.Render(userPrefix+user.Nickname))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user