96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
from textual.app import ComposeResult
|
|
from textual.binding import Binding
|
|
from textual.widgets import DataTable
|
|
|
|
import imdb
|
|
import media
|
|
from tui.content_pane import ContentPane
|
|
from tui.dialogs import ConfirmDialog, FormDialog, FormField
|
|
|
|
|
|
class MediaPane(ContentPane):
|
|
BINDINGS = [
|
|
Binding("a", "add", "Add"),
|
|
Binding("e", "rate", "Rate"),
|
|
Binding("d", "delete", "Delete"),
|
|
Binding("r", "reload", "Reload"),
|
|
]
|
|
|
|
content_file = "about.json"
|
|
|
|
def __init__(self, kind: str, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.kind = kind
|
|
self.label = media.MEDIA_KINDS[kind]["label"]
|
|
self.border_subtitle = media.MEDIA_KINDS[kind]["key"]
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield DataTable(cursor_type="row", zebra_stripes=True)
|
|
|
|
def on_mount(self):
|
|
table = self.table()
|
|
table.add_column("Rating", key="rating")
|
|
table.add_column("Title", key="title")
|
|
table.add_column("IMDb", key="imdb")
|
|
self.reload()
|
|
|
|
def reload(self, focus_key: str | None = None):
|
|
table = self.table()
|
|
table.clear()
|
|
for item in media.list_items(self.kind):
|
|
identifier = imdb.imdb_id(item.get("url", "")) or item.get("name", "")
|
|
table.add_row(f"{item.get('rating', '?')}/10", item.get("name", ""), identifier, key=identifier)
|
|
self.restore_cursor(focus_key)
|
|
|
|
def action_add(self):
|
|
fields = [
|
|
FormField("link", "IMDb link or ID", placeholder="https://www.imdb.com/title/tt0816692/", required=True),
|
|
FormField("rating", "Your rating (0 to 10)", kind="rating", required=True),
|
|
FormField("name", "Name (looked up on OMDb when empty)"),
|
|
]
|
|
self.app.push_screen(FormDialog(f"Add a {self.label}", fields, "Add"), self.add_item)
|
|
|
|
def add_item(self, values: dict | None):
|
|
if not values:
|
|
return
|
|
identifier = imdb.imdb_id(values["link"])
|
|
|
|
def added(item: dict):
|
|
self.reload(identifier)
|
|
self.notify(f"Added {item['name']} ({item['rating']}/10)")
|
|
|
|
self.run_in_background(
|
|
f"Adding {identifier or values['link']}...",
|
|
lambda: media.add_item(self.kind, values["link"], values["rating"], values["name"]),
|
|
added,
|
|
)
|
|
|
|
def action_rate(self):
|
|
identifier = self.selected_key()
|
|
if not identifier:
|
|
return
|
|
current = next((item for item in media.list_items(self.kind) if imdb.imdb_id(item.get("url", "")) == identifier), {})
|
|
fields = [FormField("rating", f"Rating for {current.get('name', identifier)}", kind="rating", required=True, value=str(current.get("rating", "")))]
|
|
|
|
def rated(values: dict | None):
|
|
if values:
|
|
self.run_now(
|
|
lambda: media.rate_item(self.kind, identifier, values["rating"]),
|
|
lambda item: f"Rated {item['name']} {item['rating']}/10",
|
|
identifier,
|
|
)
|
|
|
|
self.app.push_screen(FormDialog("Change rating", fields), rated)
|
|
|
|
def action_delete(self):
|
|
identifier = self.selected_key()
|
|
if not identifier:
|
|
return
|
|
name = self.table().get_cell(identifier, "title")
|
|
|
|
def confirmed(should_delete: bool | None):
|
|
if should_delete:
|
|
self.run_now(lambda: media.remove_item(self.kind, identifier), f"Removed {name}")
|
|
|
|
self.app.push_screen(ConfirmDialog(f"Remove {name}?"), confirmed)
|