Adjust column widths for emphasis on matches
This commit is contained in:
@@ -149,7 +149,7 @@ func New(debug bool) Model {
|
|||||||
return fmt.Sprintf("#%d %s (%s) – %s", st.StreamNo, st.Language, quality, st.Source)
|
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
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,13 +179,32 @@ func (m Model) renderMainView() string {
|
|||||||
m.matches.View(m.styles, m.focus == focusMatches),
|
m.matches.View(m.styles, m.focus == focusMatches),
|
||||||
m.streams.View(m.styles, m.focus == focusStreams),
|
m.streams.View(m.styles, m.focus == focusStreams),
|
||||||
)
|
)
|
||||||
status := m.styles.Status.Render(m.status)
|
status := m.renderStatusLine()
|
||||||
if m.lastError != nil {
|
|
||||||
status = m.styles.Error.Render(fmt.Sprintf("⚠️ %v", m.lastError))
|
|
||||||
}
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, cols, status, m.help.View(m.keys))
|
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 {
|
func (m Model) renderHelpPanel() string {
|
||||||
header := m.styles.Title.Render("Keybindings Help")
|
header := m.styles.Title.Render("Keybindings Help")
|
||||||
bindings := [][]string{
|
bindings := [][]string{
|
||||||
@@ -256,12 +275,17 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
borderPadding := 4
|
borderPadding := 4
|
||||||
totalBorderSpace := borderPadding * 3
|
totalBorderSpace := borderPadding * 3
|
||||||
availableWidth := totalAvailableWidth - totalBorderSpace
|
availableWidth := totalAvailableWidth - totalBorderSpace
|
||||||
colWidth := availableWidth / 3
|
|
||||||
remainder := availableWidth % 3
|
|
||||||
|
|
||||||
m.sports.SetWidth(colWidth + borderPadding)
|
baseUnit := availableWidth / 6
|
||||||
m.matches.SetWidth(colWidth + borderPadding)
|
remainder := availableWidth % 6
|
||||||
m.streams.SetWidth(colWidth + remainder + borderPadding)
|
|
||||||
|
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.sports.SetHeight(usableHeight)
|
||||||
m.matches.SetHeight(usableHeight)
|
m.matches.SetHeight(usableHeight)
|
||||||
@@ -337,12 +361,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
switch m.focus {
|
switch m.focus {
|
||||||
case focusSports:
|
case focusSports:
|
||||||
if sport, ok := m.sports.Selected(); ok {
|
if sport, ok := m.sports.Selected(); ok {
|
||||||
|
m.lastError = nil
|
||||||
m.status = fmt.Sprintf("Loading matches for %s…", sport.Name)
|
m.status = fmt.Sprintf("Loading matches for %s…", sport.Name)
|
||||||
m.streams.SetItems(nil)
|
m.streams.SetItems(nil)
|
||||||
return m, m.fetchMatchesForSport(sport)
|
return m, m.fetchMatchesForSport(sport)
|
||||||
}
|
}
|
||||||
case focusMatches:
|
case focusMatches:
|
||||||
if mt, ok := m.matches.Selected(); ok {
|
if mt, ok := m.matches.Selected(); ok {
|
||||||
|
m.lastError = nil
|
||||||
m.status = fmt.Sprintf("Loading streams for %s…", mt.Title)
|
m.status = fmt.Sprintf("Loading streams for %s…", mt.Title)
|
||||||
return m, m.fetchStreamsForMatch(mt)
|
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 m.focus == focusStreams {
|
||||||
if st, ok := m.streams.Selected(); ok && st.EmbedURL != "" {
|
if st, ok := m.streams.Selected(); ok && st.EmbedURL != "" {
|
||||||
_ = openBrowser(st.EmbedURL)
|
_ = openBrowser(st.EmbedURL)
|
||||||
|
m.lastError = nil
|
||||||
m.status = fmt.Sprintf("🌐 Opened in browser: %s", st.EmbedURL)
|
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:
|
case sportsLoadedMsg:
|
||||||
m.sports.SetItems(msg)
|
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
|
return m, nil
|
||||||
|
|
||||||
case matchesLoadedMsg:
|
case matchesLoadedMsg:
|
||||||
m.matches.SetTitle(msg.Title)
|
m.matches.SetTitle(msg.Title)
|
||||||
m.matches.SetItems(msg.Matches)
|
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
|
return m, nil
|
||||||
|
|
||||||
case streamsLoadedMsg:
|
case streamsLoadedMsg:
|
||||||
m.streams.SetItems(msg)
|
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
|
m.focus = focusStreams
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case launchStreamMsg:
|
case launchStreamMsg:
|
||||||
|
m.lastError = nil
|
||||||
m.status = fmt.Sprintf("🎥 Launched mpv: %s", msg.URL)
|
m.status = fmt.Sprintf("🎥 Launched mpv: %s", msg.URL)
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case errorMsg:
|
case errorMsg:
|
||||||
m.lastError = msg
|
m.lastError = msg
|
||||||
|
m.status = "Encountered an error while contacting the API"
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type Styles struct {
|
|||||||
Active lipgloss.Style
|
Active lipgloss.Style
|
||||||
Status lipgloss.Style
|
Status lipgloss.Style
|
||||||
Error lipgloss.Style // NEW: for red bold error lines
|
Error lipgloss.Style // NEW: for red bold error lines
|
||||||
|
Subtle lipgloss.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStyles() Styles {
|
func NewStyles() Styles {
|
||||||
@@ -30,6 +31,8 @@ func NewStyles() Styles {
|
|||||||
Padding(0, 1).
|
Padding(0, 1).
|
||||||
MarginRight(1),
|
MarginRight(1),
|
||||||
Status: lipgloss.NewStyle().Foreground(lipgloss.Color("8")).MarginTop(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) {
|
func (c *ListColumn[T]) SetHeight(h int) {
|
||||||
if h > 5 {
|
if h > 6 {
|
||||||
c.height = h - 5
|
c.height = h - 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +112,12 @@ func (c *ListColumn[T]) View(styles Styles, focused bool) string {
|
|||||||
box = styles.Active
|
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{}
|
lines := []string{}
|
||||||
|
|
||||||
if len(c.items) == 0 {
|
if len(c.items) == 0 {
|
||||||
@@ -120,6 +128,7 @@ func (c *ListColumn[T]) View(styles Styles, focused bool) string {
|
|||||||
if end > len(c.items) {
|
if end > len(c.items) {
|
||||||
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++ {
|
for i := start; i < end; i++ {
|
||||||
cursor := " "
|
cursor := " "
|
||||||
lineText := c.render(c.items[i])
|
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")
|
content := strings.Join(lines, "\n")
|
||||||
// IMPORTANT: width = interior content width + 4 (border+padding)
|
// 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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user