One more step closer, revision to jtui style
This commit is contained in:
77
src/main.rs
77
src/main.rs
@@ -2359,53 +2359,61 @@ fn is_downloaded(_it: &core::jellyfin::JfItem) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_played(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) {
|
if it.user_data.as_ref().and_then(|u| u.played) == Some(true) {
|
||||||
return 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 matches!(it.item_type.as_deref(), Some("Season" | "Series")) {
|
||||||
if it.user_data.as_ref().and_then(|u| u.unplayed_item_count) == Some(0) {
|
if it.user_data.as_ref().and_then(|u| u.unplayed_item_count) == Some(0) {
|
||||||
return true;
|
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 let Some(p) = it.user_data.as_ref().and_then(|u| u.played_percentage) {
|
||||||
if p >= 99.9 {
|
return p >= 99.9;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
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 {
|
fn is_in_progress_fast(it: &core::jellyfin::JfItem) -> bool {
|
||||||
if is_played(it) {
|
if is_played(it) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
match it.item_type.as_deref() {
|
match it.item_type.as_deref() {
|
||||||
// Movies/Episodes: only if resume ticks exist
|
|
||||||
Some("Movie" | "Episode") => playback_position_ticks(it).is_some(),
|
Some("Movie" | "Episode") => playback_position_ticks(it).is_some(),
|
||||||
|
|
||||||
// Seasons: only percent-based
|
// THIS is the season fix (jtui-style)
|
||||||
Some("Season") => {
|
Some("Season") => it.user_data
|
||||||
if let Some(p) = it.user_data.as_ref().and_then(|u| u.played_percentage) {
|
.as_ref()
|
||||||
p > 0.1 && p < 99.9
|
.and_then(|u| u.played_percentage)
|
||||||
} else {
|
.is_some_and(|p| p > 0.1 && p < 99.9),
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Series: NO in-progress marker (by your requirement)
|
// Series: you said “complete or nothing”
|
||||||
Some("Series") => false,
|
Some("Series") => false,
|
||||||
|
|
||||||
_ => 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 {
|
fn is_in_progress(it: &core::jellyfin::JfItem) -> bool {
|
||||||
if is_played(it) {
|
if is_played(it) {
|
||||||
return false;
|
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) ---
|
// --- transcoding + resume URL builder (Approach B) ---
|
||||||
fn clamp_mbps_to_bps(mbps: u32) -> u32 {
|
fn clamp_mbps_to_bps(mbps: u32) -> u32 {
|
||||||
mbps.saturating_mul(1_000_000) // Mb/s -> bits/s
|
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)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Panes {
|
struct Panes {
|
||||||
top: Rect,
|
top: Rect,
|
||||||
left_main: Rect,
|
left_main: Rect,
|
||||||
|
|||||||
Reference in New Issue
Block a user