initial commit
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I4a6b498153eccd5407510dd541b7f4816a6a6964
This commit is contained in:
commit
6a73d11c4b
124 changed files with 34856 additions and 0 deletions
223
crates/pinakes-tui/src/ui/detail.rs
Normal file
223
crates/pinakes-tui/src/ui/detail.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
use ratatui::Frame;
|
||||
use ratatui::layout::{Constraint, Direction, Layout, Rect};
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::{Line, Span};
|
||||
use ratatui::widgets::{Block, Borders, Paragraph};
|
||||
|
||||
use super::{format_date, format_duration, format_size, media_type_color};
|
||||
use crate::app::AppState;
|
||||
|
||||
pub fn render(f: &mut Frame, state: &AppState, area: Rect) {
|
||||
let item = match &state.selected_media {
|
||||
Some(item) => item,
|
||||
None => {
|
||||
let msg = Paragraph::new("No item selected")
|
||||
.block(Block::default().borders(Borders::ALL).title(" Detail "));
|
||||
f.render_widget(msg, area);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Min(0)])
|
||||
.split(area);
|
||||
|
||||
let label_style = Style::default()
|
||||
.fg(Color::Yellow)
|
||||
.add_modifier(Modifier::BOLD);
|
||||
let value_style = Style::default().fg(Color::White);
|
||||
let dim_style = Style::default().fg(Color::DarkGray);
|
||||
|
||||
let pad = " ";
|
||||
let label_width = 14;
|
||||
let make_label = |name: &str| -> String { format!("{name:<label_width$}") };
|
||||
|
||||
let mut lines: Vec<Line> = Vec::new();
|
||||
|
||||
// Section: File Info
|
||||
lines.push(Line::from(Span::styled(
|
||||
"--- File Info ---",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Name"), label_style),
|
||||
Span::styled(&item.file_name, value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Path"), label_style),
|
||||
Span::styled(&item.path, dim_style),
|
||||
]));
|
||||
|
||||
let type_color = media_type_color(&item.media_type);
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Type"), label_style),
|
||||
Span::styled(&item.media_type, Style::default().fg(type_color)),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Size"), label_style),
|
||||
Span::styled(format_size(item.file_size), value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Hash"), label_style),
|
||||
Span::styled(&item.content_hash, dim_style),
|
||||
]));
|
||||
|
||||
if item.has_thumbnail {
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Thumbnail"), label_style),
|
||||
Span::styled("Yes", Style::default().fg(Color::Green)),
|
||||
]));
|
||||
}
|
||||
|
||||
lines.push(Line::default()); // blank line
|
||||
|
||||
// Section: Metadata
|
||||
lines.push(Line::from(Span::styled(
|
||||
"--- Metadata ---",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Title"), label_style),
|
||||
Span::styled(item.title.as_deref().unwrap_or("-"), value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Artist"), label_style),
|
||||
Span::styled(item.artist.as_deref().unwrap_or("-"), value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Album"), label_style),
|
||||
Span::styled(item.album.as_deref().unwrap_or("-"), value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Genre"), label_style),
|
||||
Span::styled(item.genre.as_deref().unwrap_or("-"), value_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Year"), label_style),
|
||||
Span::styled(
|
||||
item.year
|
||||
.map(|y| y.to_string())
|
||||
.unwrap_or_else(|| "-".to_string()),
|
||||
value_style,
|
||||
),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Duration"), label_style),
|
||||
Span::styled(
|
||||
item.duration_secs
|
||||
.map(format_duration)
|
||||
.unwrap_or_else(|| "-".to_string()),
|
||||
value_style,
|
||||
),
|
||||
]));
|
||||
|
||||
// Description
|
||||
if let Some(ref desc) = item.description
|
||||
&& !desc.is_empty()
|
||||
{
|
||||
lines.push(Line::default());
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Description"), label_style),
|
||||
Span::styled(desc.as_str(), value_style),
|
||||
]));
|
||||
}
|
||||
|
||||
// Custom fields
|
||||
if !item.custom_fields.is_empty() {
|
||||
lines.push(Line::default());
|
||||
lines.push(Line::from(Span::styled(
|
||||
"--- Custom Fields ---",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)));
|
||||
let mut fields: Vec<_> = item.custom_fields.iter().collect();
|
||||
fields.sort_by_key(|(k, _)| k.as_str());
|
||||
for (key, field) in fields {
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(format!("{key:<label_width$}"), label_style),
|
||||
Span::styled(
|
||||
format!("{} ({})", field.value, field.field_type),
|
||||
value_style,
|
||||
),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
// Tags section
|
||||
if !state.tags.is_empty() {
|
||||
lines.push(Line::default());
|
||||
lines.push(Line::from(Span::styled(
|
||||
"--- Tags ---",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)));
|
||||
let tag_names: Vec<&str> = state.tags.iter().map(|t| t.name.as_str()).collect();
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(tag_names.join(", "), Style::default().fg(Color::Green)),
|
||||
]));
|
||||
}
|
||||
|
||||
lines.push(Line::default());
|
||||
|
||||
// Section: Timestamps
|
||||
lines.push(Line::from(Span::styled(
|
||||
"--- Timestamps ---",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Created"), label_style),
|
||||
Span::styled(format_date(&item.created_at), dim_style),
|
||||
]));
|
||||
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(pad),
|
||||
Span::styled(make_label("Updated"), label_style),
|
||||
Span::styled(format_date(&item.updated_at), dim_style),
|
||||
]));
|
||||
|
||||
let title = if let Some(ref title_str) = item.title {
|
||||
format!(" Detail: {} ", title_str)
|
||||
} else {
|
||||
format!(" Detail: {} ", item.file_name)
|
||||
};
|
||||
|
||||
let detail = Paragraph::new(lines).block(Block::default().borders(Borders::ALL).title(title));
|
||||
|
||||
f.render_widget(detail, chunks[0]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue