}
}
+fn format_date(date: DateTime<Utc>) -> String {
+ date.with_timezone(&Local).format("%a %b %e %H:%M:%S %Y").to_string()
+}
+
impl TextFragment for SeparatorLine {
fn render(&self, width: usize) -> Vec<ColouredString> {
let mut suffix = ColouredString::plain("");
let display_post = ColouredString::uniform("]--", 'S');
match self.timestamp {
Some(date) => {
- let datestr = date.with_timezone(&Local)
- .format("%a %b %e %H:%M:%S %Y").to_string();
+ let datestr = format_date(date);
suffix = &display_pre +
ColouredString::uniform(&datestr, 'D') +
&display_post + suffix;
para
}
+
+ pub fn render_indented(&self, width: usize, indent: usize) ->
+ Vec<ColouredString>
+ {
+ let prefix = ColouredString::plain(" ").repeat(indent);
+ self.render(width.saturating_sub(indent))
+ .into_iter()
+ .map(|line| &prefix + line)
+ .collect()
+ }
}
impl TextFragment for Html {
impl TextFragment for NotificationLog {
fn render(&self, width: usize) -> Vec<ColouredString> {
let mut full_para = Paragraph::new().set_indent(0, 2);
- let datestr = self.timestamp.with_timezone(&Local)
- .format("%a %b %e %H:%M:%S %Y ").to_string();
+ let datestr = format_date(self.timestamp);
full_para.push_text(&ColouredString::uniform(&datestr, ' '), false);
// FIXME: highlight account_desc if active
full_para.push_text(
pub struct ExamineUserDisplay {
name: Paragraph,
+ webaccount: Paragraph,
+ dispname: Paragraph,
+ bio_header: Paragraph,
+ bio: Html,
+ info_header: Paragraph,
+ info_fields: Vec<(Paragraph, Html)>,
+ id: Paragraph,
+ creation: Paragraph,
+ last_post: Paragraph,
+ post_count: Paragraph,
+ followers_count: Paragraph,
+ following_count: Paragraph,
+ blank: BlankLine,
}
impl ExamineUserDisplay {
let name = Paragraph::new()
.add(&ColouredString::plain("Account name: "))
.add(&ColouredString::uniform(&client.fq(&ac.acct), 'f'));
+ let webaccount = Paragraph::new()
+ .add(&ColouredString::plain("On the web: "))
+ .add(&ColouredString::uniform(&client.fq(&ac.url), 'u'));
+
+ let dispname = Paragraph::new()
+ .add(&ColouredString::plain("Display name: "))
+ .add(&ColouredString::plain(&ac.display_name));
+ let bio_header = Paragraph::new()
+ .add(&ColouredString::plain("Bio:"));
+ let bio = Html::new(&ac.note);
+
+ let info_header = Paragraph::new()
+ .add(&ColouredString::plain("Information:"));
+ let info_fields = ac.fields.iter().map(|field| {
+ let colour = if field.verified_at.is_some() { 'f' } else { ' ' };
+ let title_text = field.name.trim();
+ let title_text = title_text.strip_suffix(":").unwrap_or(title_text);
+ let title_text = title_text.to_owned() + ":";
+ let title = Paragraph::new()
+ .add(&ColouredString::uniform(&title_text, colour))
+ .set_indent(2, 2);
+ let content = Html::new(&field.value);
+ (title, content)
+ }).collect();
+
+ let id = Paragraph::new()
+ .add(&ColouredString::plain("Account id: "))
+ .add(&ColouredString::plain(&ac.id));
+ let creation = Paragraph::new()
+ .add(&ColouredString::plain("Account created: "))
+ .add(&Self::format_option_approx_date(Some(ac.created_at)));
+ let last_post = Paragraph::new()
+ .add(&ColouredString::plain("Latest post: "))
+ .add(&Self::format_option_approx_date(ac.last_status_at));
+ let post_count = Paragraph::new()
+ .add(&ColouredString::plain(
+ &format!("Number of posts: {}", ac.statuses_count)));
+ let followers_count = Paragraph::new()
+ .add(&ColouredString::plain(
+ &format!("Number of followers: {}", ac.followers_count)));
+ let following_count = Paragraph::new()
+ .add(&ColouredString::plain(
+ &format!("Number of users followed: {}", ac.following_count)));
Ok(ExamineUserDisplay {
name,
+ webaccount,
+ dispname,
+ bio_header,
+ bio,
+ info_header,
+ info_fields,
+ id,
+ creation,
+ last_post,
+ post_count,
+ followers_count,
+ following_count,
+ blank: BlankLine::new(),
})
}
+
+ fn format_option_approx_date(date: Option<ApproxDate>) -> ColouredString
+ {
+ // Used for account creation dates and last-post times, which
+ // don't seem to bother having precise timestamps
+ match date {
+ None => ColouredString::uniform("none", '0'),
+ Some(ApproxDate(date)) => ColouredString::plain(
+ &date.format("%a %b %e %Y").to_string()),
+ }
+ }
}
impl TextFragment for ExamineUserDisplay {
let mut lines = Vec::new();
push_fragment(&mut lines, self.name.render(width));
+ push_fragment(&mut lines, self.webaccount.render(width));
+ push_fragment(&mut lines, self.blank.render(width));
+
+ push_fragment(&mut lines, self.dispname.render(width));
+ push_fragment(&mut lines, self.bio_header.render(width));
+ push_fragment(&mut lines, self.bio.render_indented(width, 2));
+ push_fragment(&mut lines, self.blank.render(width));
+
+ if !self.info_fields.is_empty() {
+ push_fragment(&mut lines, self.info_header.render(width));
+ for (key, value) in &self.info_fields {
+ push_fragment(&mut lines, key.render(width));
+ push_fragment(&mut lines, value.render_indented(width, 4));
+ }
+ push_fragment(&mut lines, self.blank.render(width));
+ }
+
+ // FIXME: relationships list
+
+ push_fragment(&mut lines, self.id.render(width));
+ push_fragment(&mut lines, self.creation.render(width));
+ push_fragment(&mut lines, self.last_post.render(width));
+ push_fragment(&mut lines, self.post_count.render(width));
+ push_fragment(&mut lines, self.blank.render(width));
+
+ push_fragment(&mut lines, self.followers_count.render(width));
+ push_fragment(&mut lines, self.following_count.render(width));
+ push_fragment(&mut lines, self.blank.render(width));
lines
}