Files
beefy-player/beefy_player/widgets/providers.py
T

88 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Catalogue picker: switch between SomaFM, tilderadio and whatever comes next."""
from __future__ import annotations
from rich.console import Group
from rich.text import Text
from textual.app import ComposeResult
from textual.screen import ModalScreen
from textual.widgets import Static
from ..providers import PROVIDERS, available_providers
from .common import SPECTRUM_STOPS, gradient, truncate
class ProviderScreen(ModalScreen[str | None]):
"""A list of catalogues; enter selects, esc leaves everything as it was."""
def __init__(self, current_id: str = "") -> None:
super().__init__()
self.slugs: tuple[str, ...] = available_providers()
self.current_id = current_id
self.index = self.slugs.index(current_id) if current_id in self.slugs else 0
def compose(self) -> ComposeResult:
yield Static(self._body(), id="providers")
def _body(self) -> Group:
header = Text()
header.append("◤ ", style=f"bold {gradient(SPECTRUM_STOPS, 0.9)}")
header.append("CATALOGUES", style=f"bold {gradient(SPECTRUM_STOPS, 0.55)}")
header.append(" pick a station catalogue", style="dim")
rows: list[Text] = []
for index, slug in enumerate(self.slugs):
provider = PROVIDERS[slug]
selected = index == self.index
row = Text(no_wrap=True)
row.append("▶ " if selected else " ", style="bold magenta" if selected else "")
row.append(f"{index + 1} ", style="dim")
name_style = "bold underline" if selected else "bold"
row.append(f"{provider.name:<12}", style=name_style)
row.append(f" {provider.brand}", style="dim")
if slug == self.current_id:
row.append(" ●", style="bold green")
rows.append(row)
detail = Text(no_wrap=True)
detail.append(" ", style="")
detail.append(truncate(provider.tagline, 54), style="italic dim")
rows.append(detail)
current = PROVIDERS.get(self.current_id)
footer = Text()
footer.append("\n")
if current is not None:
footer.append(
f"now: {current.name} — {current.station_source}\n", style="dim"
)
footer.append(
"↑ ↓ choose · 1–9 jump · enter switch · esc cancel",
style="dim",
)
return Group(header, Text(""), *rows, footer)
# -- interaction ----------------------------------------------------- #
def _move(self, delta: int) -> None:
self.index = (self.index + delta) % len(self.slugs)
self.query_one("#providers", Static).update(self._body())
def on_key(self, event) -> None:
key = event.key
if key in ("up", "k", "shift+tab"):
self._move(-1)
elif key in ("down", "j", "tab"):
self._move(1)
elif key in ("enter", "space"):
self.dismiss(self.slugs[self.index])
elif key == "escape" or key == "q":
self.dismiss(None)
elif key.isdigit() and key != "0":
choice = int(key) - 1
if 0 <= choice < len(self.slugs):
self.dismiss(self.slugs[choice])
else:
return
event.stop()