From ca7840ad66508489b8e767e448bd0a8a45165e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Monta=C3=B1es=20Ojados?= Date: Fri, 16 Jan 2026 22:52:10 +0100 Subject: [PATCH] Refactor TUI input handling (isolate shortcuts) and polish layout alignment --- cmd/tui/model.go | 74 +++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/cmd/tui/model.go b/cmd/tui/model.go index c7c8a40..7ea3020 100644 --- a/cmd/tui/model.go +++ b/cmd/tui/model.go @@ -400,9 +400,9 @@ func (m *Model) updateChannelList(channels []*ts3client.Channel) { } func (m *Model) handleKeyPress(msg tea.KeyMsg) (tea.Model, tea.Cmd) { - // Global keys (work regardless of focus) + // 1. Absolute Globals (Always active) switch msg.String() { - case "ctrl+c", "q": + case "ctrl+c": if m.client != nil { m.client.Disconnect() } @@ -419,6 +419,28 @@ func (m *Model) handleKeyPress(msg tea.KeyMsg) (tea.Model, tea.Cmd) { // Cycle focus m.focus = (m.focus + 1) % 3 return m, nil + } + + // 2. Input Focus Priority + // If typing, ignore all other shortcuts except the absolute globals above + if m.focus == FocusInput { + return m.handleInputKeys(msg) + } + + // 3. Global Shortcuts (Only when NOT in Input) + switch msg.String() { + case "q": + // Quit (same as ctrl+c) + if m.client != nil { + m.client.Disconnect() + } + if m.audioPlayer != nil { + m.audioPlayer.Close() + } + if m.audioCapturer != nil { + m.audioCapturer.Close() + } + return m, tea.Quit case "m", "M": // Toggle mute @@ -451,31 +473,25 @@ func (m *Model) handleKeyPress(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return m, nil case "v", "V": - // Toggle voice (PTT) - V to start/stop transmitting - if m.focus != FocusInput { - m.isPTT = !m.isPTT - if m.isPTT { - // Start capturing when PTT enabled - if m.audioCapturer != nil { - m.audioCapturer.Start() - } - m.addLog("🎤 Transmitting...") - } else { - // Stop capturing when PTT disabled - if m.audioCapturer != nil { - m.audioCapturer.Stop() - } - m.addLog("🎤 Stopped transmitting") + // Toggle voice (PTT) + m.isPTT = !m.isPTT + if m.isPTT { + if m.audioCapturer != nil { + m.audioCapturer.Start() } - return m, nil + m.addLog("🎤 Transmitting...") + } else { + if m.audioCapturer != nil { + m.audioCapturer.Stop() + } + m.addLog("🎤 Stopped transmitting") } + return m, nil case "l", "L": // Toggle Log/Chat view - if m.focus != FocusInput { - m.showLog = !m.showLog - return m, nil - } + m.showLog = !m.showLog + return m, nil } // Focus-specific keys @@ -563,25 +579,31 @@ func (m *Model) View() string { // panels should be height - 5 (1 for header, 3 for input with border, 1 for help) panelHeight := m.height - 7 + // Calculate explicit widths to fit exactly (Width is content width) + // Box Width = Content + 2 (Border) + 2 (Padding) = Content + 4 + // We want LeftBox + RightBox = m.width + leftBoxWidth := m.width / 4 + rightBoxWidth := m.width - leftBoxWidth + channelPanelStyle := lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(lipgloss.Color("63")). Padding(0, 1). - Width(m.width/3 - 2). + Width(leftBoxWidth - 4). Height(panelHeight) chatPanelStyle := lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(lipgloss.Color("63")). Padding(0, 1). - Width(m.width*2/3 - 2). + Width(rightBoxWidth - 4). Height(panelHeight) inputStyle := lipgloss.NewStyle(). Border(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("63")). Padding(0, 1). - Width(m.width - 4) + Width(m.width - 6) // Header with status bar header := m.renderStatusBar() @@ -618,7 +640,7 @@ func (m *Model) View() string { } // Calculate available width for text - textWidth := (m.width * 2 / 3) - 6 + textWidth := (rightBoxWidth - 4) - 2 // Content width - margin if textWidth < 10 { textWidth = 10 }