From 17f524332c09a0105b04be6619706b2520cb6eee Mon Sep 17 00:00:00 2001 From: Salastil <46979341+Salastil@users.noreply.github.com> Date: Sat, 22 Nov 2025 23:25:47 -0500 Subject: [PATCH] Adjust column widths for emphasis on matches --- internal/app.go | 58 +++++++++++++++++++++++++++++++++++---------- internal/columns.go | 17 +++++++++---- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/internal/app.go b/internal/app.go index 08da211..264db0a 100644 --- a/internal/app.go +++ b/internal/app.go @@ -149,7 +149,7 @@ func New(debug bool) Model { return fmt.Sprintf("#%d %s (%s) – %s", st.StreamNo, st.Language, quality, st.Source) }) - m.status = fmt.Sprintf("Using API %s | Loading…", base) + m.status = fmt.Sprintf("Using API %s | Loading sports and matches…", base) return m } @@ -179,13 +179,32 @@ func (m Model) renderMainView() string { m.matches.View(m.styles, m.focus == focusMatches), m.streams.View(m.styles, m.focus == focusStreams), ) - status := m.styles.Status.Render(m.status) - if m.lastError != nil { - status = m.styles.Error.Render(fmt.Sprintf("⚠️ %v", m.lastError)) - } + status := m.renderStatusLine() return lipgloss.JoinVertical(lipgloss.Left, cols, status, m.help.View(m.keys)) } +func (m Model) renderStatusLine() string { + focusLabel := m.currentFocusLabel() + statusText := fmt.Sprintf("%s | Focus: %s (←/→)", m.status, focusLabel) + if m.lastError != nil { + return m.styles.Error.Render(fmt.Sprintf("⚠️ %v | Focus: %s (Esc to dismiss)", m.lastError, focusLabel)) + } + return m.styles.Status.Render(statusText) +} + +func (m Model) currentFocusLabel() string { + switch m.focus { + case focusSports: + return "Sports" + case focusMatches: + return "Matches" + case focusStreams: + return "Streams" + default: + return "Unknown" + } +} + func (m Model) renderHelpPanel() string { header := m.styles.Title.Render("Keybindings Help") bindings := [][]string{ @@ -256,12 +275,17 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { borderPadding := 4 totalBorderSpace := borderPadding * 3 availableWidth := totalAvailableWidth - totalBorderSpace - colWidth := availableWidth / 3 - remainder := availableWidth % 3 - m.sports.SetWidth(colWidth + borderPadding) - m.matches.SetWidth(colWidth + borderPadding) - m.streams.SetWidth(colWidth + remainder + borderPadding) + baseUnit := availableWidth / 6 + remainder := availableWidth % 6 + + sportsWidth := baseUnit + matchesWidth := baseUnit * 4 + streamsWidth := baseUnit + + m.sports.SetWidth(sportsWidth + borderPadding) + m.matches.SetWidth(matchesWidth + remainder + borderPadding) + m.streams.SetWidth(streamsWidth + borderPadding) m.sports.SetHeight(usableHeight) m.matches.SetHeight(usableHeight) @@ -337,12 +361,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch m.focus { case focusSports: if sport, ok := m.sports.Selected(); ok { + m.lastError = nil m.status = fmt.Sprintf("Loading matches for %s…", sport.Name) m.streams.SetItems(nil) return m, m.fetchMatchesForSport(sport) } case focusMatches: if mt, ok := m.matches.Selected(); ok { + m.lastError = nil m.status = fmt.Sprintf("Loading streams for %s…", mt.Title) return m, m.fetchStreamsForMatch(mt) } @@ -360,6 +386,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.focus == focusStreams { if st, ok := m.streams.Selected(); ok && st.EmbedURL != "" { _ = openBrowser(st.EmbedURL) + m.lastError = nil m.status = fmt.Sprintf("🌐 Opened in browser: %s", st.EmbedURL) } } @@ -369,27 +396,32 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case sportsLoadedMsg: m.sports.SetItems(msg) - m.status = fmt.Sprintf("Loaded %d sports", len(msg)) + m.lastError = nil + m.status = fmt.Sprintf("Loaded %d sports – pick one with Enter or stay on Popular Matches", len(msg)) return m, nil case matchesLoadedMsg: m.matches.SetTitle(msg.Title) m.matches.SetItems(msg.Matches) - m.status = fmt.Sprintf("Loaded %d matches", len(msg.Matches)) + m.lastError = nil + m.status = fmt.Sprintf("Loaded %d matches – choose one to load streams", len(msg.Matches)) return m, nil case streamsLoadedMsg: m.streams.SetItems(msg) - m.status = fmt.Sprintf("Loaded %d streams", len(msg)) + m.lastError = nil + m.status = fmt.Sprintf("Loaded %d streams – Enter to launch mpv, o to open in browser", len(msg)) m.focus = focusStreams return m, nil case launchStreamMsg: + m.lastError = nil m.status = fmt.Sprintf("🎥 Launched mpv: %s", msg.URL) return m, nil case errorMsg: m.lastError = msg + m.status = "Encountered an error while contacting the API" return m, nil } return m, nil diff --git a/internal/columns.go b/internal/columns.go index a4032dd..b2e9745 100644 --- a/internal/columns.go +++ b/internal/columns.go @@ -17,6 +17,7 @@ type Styles struct { Active lipgloss.Style Status lipgloss.Style Error lipgloss.Style // NEW: for red bold error lines + Subtle lipgloss.Style } func NewStyles() Styles { @@ -30,6 +31,8 @@ func NewStyles() Styles { Padding(0, 1). MarginRight(1), Status: lipgloss.NewStyle().Foreground(lipgloss.Color("8")).MarginTop(1), + Error: lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true), + Subtle: lipgloss.NewStyle().Foreground(lipgloss.Color("243")), } } @@ -72,8 +75,8 @@ func (c *ListColumn[T]) SetWidth(w int) { } func (c *ListColumn[T]) SetHeight(h int) { - if h > 5 { - c.height = h - 5 + if h > 6 { + c.height = h - 6 } } @@ -109,7 +112,12 @@ func (c *ListColumn[T]) View(styles Styles, focused bool) string { box = styles.Active } - head := styles.Title.Render(c.title) + titleText := fmt.Sprintf("%s (%d)", c.title, len(c.items)) + if focused { + titleText = fmt.Sprintf("▶ %s", titleText) + } + head := styles.Title.Render(titleText) + meta := styles.Subtle.Render("Waiting for data…") lines := []string{} if len(c.items) == 0 { @@ -120,6 +128,7 @@ func (c *ListColumn[T]) View(styles Styles, focused bool) string { if end > len(c.items) { end = len(c.items) } + meta = styles.Subtle.Render(fmt.Sprintf("Showing %d–%d of %d", start+1, end, len(c.items))) for i := start; i < end; i++ { cursor := " " lineText := c.render(c.items[i]) @@ -145,5 +154,5 @@ func (c *ListColumn[T]) View(styles Styles, focused bool) string { content := strings.Join(lines, "\n") // IMPORTANT: width = interior content width + 4 (border+padding) - return box.Width(c.width + 4).Render(head + "\n" + content) + return box.Width(c.width + 4).Render(head + "\n" + meta + "\n" + content) }