52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
"""Jellyfin library browser UI pieces."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import pandas as pd
|
|
import streamlit as st
|
|
|
|
from media_library_viewer.domain.media import media_streams
|
|
from media_library_viewer.utils import ticks_to_minutes
|
|
|
|
|
|
def show_item_card(client, item: dict[str, Any]) -> None:
|
|
"""Render a poster card in the Jellyfin library grid."""
|
|
try:
|
|
st.image(client.image_url(item["Id"]), use_container_width=True)
|
|
except Exception:
|
|
st.caption("No image")
|
|
st.markdown(f"**{item.get('Name', 'Untitled')}**")
|
|
meta = [item.get("Type", "")]
|
|
if item.get("ProductionYear"):
|
|
meta.append(str(item["ProductionYear"]))
|
|
minutes = ticks_to_minutes(item.get("RunTimeTicks"))
|
|
if minutes:
|
|
meta.append(f"{minutes} min")
|
|
st.caption(" - ".join([m for m in meta if m]))
|
|
if st.button("Open", key=f"open-{item['Id']}"):
|
|
st.session_state["selected_item_id"] = item["Id"]
|
|
|
|
|
|
def show_item_detail(client, item: dict[str, Any]) -> None:
|
|
"""Render detailed Jellyfin item metadata for the selected poster card."""
|
|
st.header(item.get("Name", "Untitled"))
|
|
left, right = st.columns([1, 2])
|
|
with left:
|
|
st.image(client.image_url(item["Id"]), use_container_width=True)
|
|
with right:
|
|
st.write(item.get("Overview") or "No overview.")
|
|
st.write("**Path:**", item.get("Path") or "Not exposed by Jellyfin")
|
|
st.write("**Genres:**", ", ".join(item.get("Genres", [])) or "-")
|
|
st.write("**Rating:**", item.get("CommunityRating") or "-")
|
|
st.write("**Official rating:**", item.get("OfficialRating") or "-")
|
|
|
|
streams = media_streams(item)
|
|
if streams:
|
|
st.subheader("Jellyfin media streams")
|
|
st.dataframe(pd.DataFrame(streams), use_container_width=True)
|
|
|
|
with st.expander("Raw Jellyfin JSON"):
|
|
st.json(item)
|