One more step closer, revision to jtui style

This commit is contained in:
2026-02-16 12:58:40 -06:00
parent 46d50de1a9
commit 6a6a491681

View File

@@ -2359,53 +2359,61 @@ fn is_downloaded(_it: &core::jellyfin::JfItem) -> bool {
}
fn is_played(it: &core::jellyfin::JfItem) -> bool {
// direct played flag
if it.user_data.as_ref().and_then(|u| u.played) == Some(true) {
return true;
}
// aggregate containers: Season/Series can have UnplayedItemCount
// Jellyfin often provides this for Season/Series
if matches!(it.item_type.as_deref(), Some("Season" | "Series")) {
if it.user_data.as_ref().and_then(|u| u.unplayed_item_count) == Some(0) {
return true;
}
}
// percent-based fallback (works for many types)
if let Some(p) = it.user_data.as_ref().and_then(|u| u.played_percentage) {
if p >= 99.9 {
return true;
}
return p >= 99.9;
}
false
}
fn playback_position_ticks(it: &core::jellyfin::JfItem) -> Option<u64> {
it.user_data
.as_ref()
.and_then(|u| u.playback_position_ticks)
.and_then(|v| if v > 0 { Some(v as u64) } else { None })
}
fn is_in_progress_fast(it: &core::jellyfin::JfItem) -> bool {
if is_played(it) {
return false;
}
match it.item_type.as_deref() {
// Movies/Episodes: only if resume ticks exist
Some("Movie" | "Episode") => playback_position_ticks(it).is_some(),
// Seasons: only percent-based
Some("Season") => {
if let Some(p) = it.user_data.as_ref().and_then(|u| u.played_percentage) {
p > 0.1 && p < 99.9
} else {
false
}
}
// THIS is the season fix (jtui-style)
Some("Season") => it.user_data
.as_ref()
.and_then(|u| u.played_percentage)
.is_some_and(|p| p > 0.1 && p < 99.9),
// Series: NO in-progress marker (by your requirement)
// Series: you said “complete or nothing”
Some("Series") => false,
_ => false,
}
}
fn emoji_prefix_for(_app: &App, it: &core::jellyfin::JfItem) -> &'static str {
if is_music_item(it) { return ""; }
if is_played(it) { return ""; }
if is_in_progress_fast(it) { return "🟠 "; }
""
}
fn is_in_progress(it: &core::jellyfin::JfItem) -> bool {
if is_played(it) {
return false;
@@ -2428,32 +2436,6 @@ fn is_in_progress(it: &core::jellyfin::JfItem) -> bool {
}
}
fn playback_position_ticks(it: &core::jellyfin::JfItem) -> Option<u64> {
it.user_data
.as_ref()
.and_then(|u| u.playback_position_ticks)
.and_then(|v| if v > 0 { Some(v as u64) } else { None })
}
fn emoji_prefix_for(_app: &App, it: &core::jellyfin::JfItem) -> &'static str {
// no emoji for music
if is_music_item(it) {
return "";
}
if is_played(it) {
return "";
}
if is_in_progress(it) {
return "🟠 ";
}
""
}
// --- transcoding + resume URL builder (Approach B) ---
fn clamp_mbps_to_bps(mbps: u32) -> u32 {
mbps.saturating_mul(1_000_000) // Mb/s -> bits/s
@@ -2495,17 +2477,6 @@ fn mpv_cmd_reply(socket: &PathBuf, cmd: &str) -> Result<Value, String> {
Ok(v)
}
struct Panes {
top: Rect,
left_main: Rect,