info almost done
This commit is contained in:
121
src/main.rs
121
src/main.rs
@@ -24,7 +24,7 @@ use crossterm::{
|
||||
use ratatui::{
|
||||
layout::{Constraint, Layout, Rect, Spacing},
|
||||
symbols::merge::MergeStrategy,
|
||||
widgets::{Block, List, ListItem, ListState, Paragraph},
|
||||
widgets::{Block, List, ListItem, ListState, Paragraph, Wrap},
|
||||
style::{Modifier, Style},
|
||||
Frame, Terminal,
|
||||
};
|
||||
@@ -976,6 +976,119 @@ fn ensure_loaded_to_end(app: &mut App) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn ticks_to_runtime_str(ticks: Option<i64>) -> Option<String> {
|
||||
// Jellyfin ticks are 10,000,000 per second
|
||||
let t = ticks?;
|
||||
if t <= 0 { return None; }
|
||||
|
||||
let total_seconds = (t as u64 / 10_000_000) as u64;
|
||||
let minutes = total_seconds / 60;
|
||||
let seconds = total_seconds % 60;
|
||||
|
||||
if minutes >= 60 {
|
||||
let h = minutes / 60;
|
||||
let m = minutes % 60;
|
||||
Some(format!("{h}h {m}m"))
|
||||
} else {
|
||||
Some(format!("{minutes}m {seconds:02}s"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn join_genres(genres: &[String]) -> String {
|
||||
if genres.is_empty() { "-".into() } else { genres.join(", ") }
|
||||
}
|
||||
|
||||
fn join_studios(studios: &[core::jellyfin::JfStudio]) -> String {
|
||||
let names: Vec<String> = studios
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.filter(|s| !s.trim().is_empty())
|
||||
.collect();
|
||||
|
||||
if names.is_empty() { "-".into() } else { names.join(", ") }
|
||||
}
|
||||
|
||||
fn year_str(y: Option<i32>) -> String {
|
||||
y.map(|v| v.to_string()).unwrap_or_else(|| "-".into())
|
||||
}
|
||||
|
||||
fn overview_str(o: &Option<String>) -> String {
|
||||
o.as_deref()
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.unwrap_or("-")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn format_details(it: &core::jellyfin::JfItem) -> String {
|
||||
let ty = it.item_type.as_deref().unwrap_or("");
|
||||
|
||||
match ty {
|
||||
"Series" => format!(
|
||||
"Name: {}\nYear: {}\nGenres: {}\nStudio: {}\n\nOverview:\n{}",
|
||||
it.name,
|
||||
year_str(it.production_year),
|
||||
join_genres(&it.genres),
|
||||
join_studios(&it.studios),
|
||||
overview_str(&it.overview),
|
||||
),
|
||||
|
||||
"Movie" => format!(
|
||||
"Name: {}\nYear: {}\nRuntime: {}\nGenres: {}\nStudio: {}\n\nOverview:\n{}",
|
||||
it.name,
|
||||
year_str(it.production_year),
|
||||
ticks_to_runtime_str(it.run_time_ticks).unwrap_or_else(|| "-".into()),
|
||||
join_genres(&it.genres),
|
||||
join_studios(&it.studios),
|
||||
overview_str(&it.overview),
|
||||
),
|
||||
|
||||
// Episodes: show SeriesName if present
|
||||
"Episode" => {
|
||||
let series = it.series_name.clone().unwrap_or_else(|| "-".into());
|
||||
let se = match (it.parent_index_number, it.index_number) {
|
||||
(Some(s), Some(e)) => format!("{:02}x{:02}", s, e),
|
||||
_ => "-".into(),
|
||||
};
|
||||
|
||||
format!(
|
||||
"Series: {}\nEpisode: {} {}\nYear: {}\n\nOverview:\n{}",
|
||||
series,
|
||||
se,
|
||||
it.name,
|
||||
year_str(it.production_year),
|
||||
overview_str(&it.overview),
|
||||
)
|
||||
}
|
||||
|
||||
// Music: you asked only Name + Runtime
|
||||
"Audio" => format!(
|
||||
"Name: {}\nRuntime: {}",
|
||||
it.name,
|
||||
ticks_to_runtime_str(it.run_time_ticks).unwrap_or_else(|| "-".into()),
|
||||
),
|
||||
|
||||
// fallback
|
||||
_ => format!(
|
||||
"Name: {}\nId: {}\nType: {:?}\nYear: {:?}",
|
||||
it.name, it.id, it.item_type, it.production_year
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fn ui(frame: &mut Frame, app: &App) {
|
||||
let area = frame.area();
|
||||
let panes = layout(area);
|
||||
@@ -1214,16 +1327,14 @@ fn render_library(
|
||||
|
||||
let detail = if len > 0 {
|
||||
let it = &items[selected];
|
||||
format!(
|
||||
"Name: {}\nId: {}\nType: {:?}\nYear: {:?}",
|
||||
it.name, it.id, it.item_type, it.production_year
|
||||
)
|
||||
format_details(it)
|
||||
} else {
|
||||
"No items returned".to_string()
|
||||
};
|
||||
|
||||
frame.render_widget(
|
||||
Paragraph::new(detail)
|
||||
.wrap(Wrap { trim: false })
|
||||
.block(Block::bordered().title("Details").merge_borders(MergeStrategy::Exact)),
|
||||
right,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user