"""One-line status / key hint bar.""" from __future__ import annotations from typing import TYPE_CHECKING, cast from rich.cells import cell_len from rich.console import RenderableType from rich.text import Text from textual.widget import Widget from .common import compact_count, state_glyph, truncate if TYPE_CHECKING: from ..app import BeefyPlayerApp HINTS_LONG = ( "SPACE pause ↑↓ station ENTER tune +/- vol f ★ / filter " "v visual r refresh ? help q quit" ) HINTS_MEDIUM = ( "space pause · ↑↓ station · enter tune · +/- vol · f ★ · / filter · ? help · q quit" ) HINTS_SHORT = "↑↓ station · space play · ? help · q quit" class StatusBar(Widget): can_focus = False def render(self) -> RenderableType: app = cast("BeefyPlayerApp", self.app) width = max(20, self.size.width) glyph, colour = state_glyph(app.playing_state) frame = app.spectrum.snapshot() session = app.media.label status = app.media.status_label backend = app.player.backend or "no audio" analyser = frame.label listeners = "" if app.current is not None and app.current.listeners: listeners = f"♪ {compact_count(app.current.listeners)} " state = app.playing_state volume = f"vol {app.volume:>3}%" # From most to least informative; pick the first combination that fits. right_variants = ( f"{state} {listeners}{volume} {backend} {session} {status} {analyser}", f"{state} {volume} {session} {status} {analyser}", f"{state} {volume} {analyser}", f"{state} {volume}", volume, ) options = ( (HINTS_LONG, right_variants[0]), (HINTS_MEDIUM, right_variants[0]), (HINTS_LONG, right_variants[1]), (HINTS_MEDIUM, right_variants[1]), (HINTS_SHORT, right_variants[1]), (HINTS_SHORT, right_variants[2]), (HINTS_SHORT, right_variants[3]), (HINTS_SHORT, right_variants[4]), ) chosen: tuple[int, str, str] | None = None for hint, right_text in options: right_width = cell_len(glyph) + 1 + cell_len(right_text) if cell_len(hint) + right_width + 2 <= width: chosen = (right_width, right_text, hint) break if chosen is None: right_text = right_variants[-1] right_width = cell_len(glyph) + 1 + cell_len(right_text) if width <= right_width + 2: line = Text(no_wrap=True) line.append( truncate(f"{glyph} {right_text}", width), style="dim" ) return line chosen = (right_width, right_text, "") right_width, right_text, hint = chosen left_width = max(0, width - right_width - 2) left = app.notice or hint left_style = "italic yellow" if app.notice else "dim" line = Text(no_wrap=True) line.append(truncate(left, left_width), style=left_style) line.append(" " * max(0, width - left_width - right_width)) line.append(f"{glyph} ", style=f"bold {colour}") line.append(right_text, style="dim") return line