diff --git a/crates/synd_term/src/types/time.rs b/crates/synd_term/src/types/time.rs index 06c56306..84edf9dd 100644 --- a/crates/synd_term/src/types/time.rs +++ b/crates/synd_term/src/types/time.rs @@ -2,10 +2,15 @@ pub type Time = synd_feed::types::Time; pub trait TimeExt { fn local_ymd(&self) -> String; + fn local_ymd_hm(&self) -> String; } impl TimeExt for Time { fn local_ymd(&self) -> String { self.naive_local().format("%Y-%m-%d").to_string() } + + fn local_ymd_hm(&self) -> String { + self.naive_local().format("%Y-%m-%d %H:%M").to_string() + } } diff --git a/crates/synd_term/src/ui/components/entries.rs b/crates/synd_term/src/ui/components/entries.rs index 2240ceda..2a833958 100644 --- a/crates/synd_term/src/ui/components/entries.rs +++ b/crates/synd_term/src/ui/components/entries.rs @@ -116,7 +116,7 @@ impl Entries { let [entries_area, summary_area] = vertical.areas(area); self.render_entries(entries_area, buf, cx); - self.render_summary(summary_area, buf, cx); + self.render_detail(summary_area, buf, cx); } fn render_entries(&self, area: Rect, buf: &mut Buffer, cx: &Context<'_>) { @@ -183,7 +183,7 @@ impl Entries { } }; let header = Row::new([ - Cell::from(" Published"), + Cell::from(concat!(icon!(calendar), " Published")), Cell::from(format!("󰯂 Entry {n}/{m}")), Cell::from("󰑫 Feed"), Cell::from(concat!(icon!(requirement), " Req")), @@ -237,7 +237,7 @@ impl Entries { ) } - fn render_summary(&self, area: Rect, buf: &mut Buffer, cx: &Context<'_>) { + fn render_detail(&self, area: Rect, buf: &mut Buffer, cx: &Context<'_>) { let block = Block::new() .padding(Padding::horizontal(2)) .borders(Borders::TOP) @@ -249,15 +249,61 @@ impl Entries { let Some(entry) = self.selected_entry() else { return; }; + + let vertical = Layout::vertical([ + Constraint::Length(1), + Constraint::Length(1), + Constraint::Length(1), + Constraint::Length(1), + Constraint::Length(1), + Constraint::Min(0), + ]); + let [title_area, url_area, published_area, _, summary_heading_area, summary_area] = + vertical.areas(inner); + + Line::from(vec![ + Span::from(concat!(icon!(entry), " Entry")).bold(), + Span::from(" "), + Span::from(entry.title.as_deref().unwrap_or(ui::UNKNOWN_SYMBOL)), + ]) + .render(title_area, buf); + + Line::from(vec![ + Span::from(concat!(icon!(open), " URL")).bold(), + Span::from(" "), + Span::from(entry.website_url.as_deref().unwrap_or_default()), + ]) + .render(url_area, buf); + + Line::from(vec![ + Span::from(concat!(icon!(calendar), " Published")).bold(), + Span::from(" "), + Span::from( + entry + .published + .as_ref() + .or(entry.updated.as_ref()) + .map_or_else(|| ui::UNKNOWN_SYMBOL.to_string(), TimeExt::local_ymd_hm), + ), + ]) + .render(published_area, buf); + let Some(summary) = entry.summary_text(inner.width.into()) else { return; }; - // should to Lines? + + Line::from( + Span::from(concat!(icon!(summary), " Summary")) + .bold() + .underlined(), + ) + .render(summary_heading_area, buf); + let paragraph = Paragraph::new(Text::from(summary)) .wrap(Wrap { trim: false }) .style(cx.theme.entries.summary) .alignment(Alignment::Left); - Widget::render(paragraph, inner, buf); + Widget::render(paragraph, summary_area, buf); } } diff --git a/crates/synd_term/src/ui/components/status.rs b/crates/synd_term/src/ui/components/status.rs index 65dd9b22..44a5af00 100644 --- a/crates/synd_term/src/ui/components/status.rs +++ b/crates/synd_term/src/ui/components/status.rs @@ -62,7 +62,7 @@ impl StatusLine { let per_screen_keys = match tab { Some(Tab::Feeds) => pre_keys .iter() - .chain(&[("Ent", "󰏌"), ("a", "󰑫"), ("e", ""), ("d", "󰼡")]) + .chain(&[("Ent", icon!(open)), ("a", "󰑫"), ("e", ""), ("d", "󰼡")]) .chain(suf_keys), Some(Tab::Entries) => pre_keys.iter().chain(&[("Ent", "󰏌")]).chain(suf_keys), // Imply login diff --git a/crates/synd_term/src/ui/components/subscription.rs b/crates/synd_term/src/ui/components/subscription.rs index a8af7b87..567455fa 100644 --- a/crates/synd_term/src/ui/components/subscription.rs +++ b/crates/synd_term/src/ui/components/subscription.rs @@ -20,7 +20,7 @@ use crate::{ self, components::filter::{FeedFilter, FilterResult}, extension::RectExt, - Context, + icon, Context, }, }; @@ -249,7 +249,7 @@ impl Subscription { let header = Row::new([ Cell::from(" Updated"), Cell::from(format!("󰑫 Feed {n}/{m}")), - Cell::from(" URL"), + Cell::from(concat!(icon!(open), " URL")), Cell::from("󰎞 Description"), Cell::from(" Req"), ]); @@ -415,9 +415,9 @@ impl Subscription { }; let header = Row::new([ - Cell::new(Span::from(" Published")), - Cell::new(Span::from("󰯂 Entry")), - Cell::new(Span::from("󱙓 Summary")), + Cell::new(Span::from(concat!(icon!(calendar), " Published"))), + Cell::new(Span::from(concat!(icon!(entry), " Entry"))), + Cell::new(Span::from(concat!(icon!(summary), " Summary"))), ]); let rows = feed.entries.iter().map(entry); diff --git a/crates/synd_term/src/ui/icon.rs b/crates/synd_term/src/ui/icon.rs index d6005182..26bea195 100644 --- a/crates/synd_term/src/ui/icon.rs +++ b/crates/synd_term/src/ui/icon.rs @@ -2,15 +2,27 @@ macro_rules! icon { (category) => { "" }; + (calendar) => { + "" + }; + (entry) => { + "󰯂" + }; (filter) => { "󰈶" }; (requirement) => { "" }; + (open) => { + "󰏌" + }; (search) => { "" }; + (summary) => { + "󱙓" + }; } pub(crate) use icon;