chiark / gitweb /
Filled in most of the Examine User data.
authorSimon Tatham <anakin@pobox.com>
Mon, 1 Jan 2024 11:36:50 +0000 (11:36 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 1 Jan 2024 11:36:50 +0000 (11:36 +0000)
The missing part is Relationships, because those are a separate
server-side data structure.

src/text.rs

index d5ca2422d360772deac33a918b59180d8eaea08c..4cfcb81b89ae782f487ea8413edc5a8b95f89c2f 100644 (file)
@@ -66,6 +66,10 @@ impl SeparatorLine {
     }
 }
 
+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("");
@@ -73,8 +77,7 @@ impl TextFragment for SeparatorLine {
         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;
@@ -570,6 +573,16 @@ impl Html {
 
         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 {
@@ -819,8 +832,7 @@ impl NotificationLog {
 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(
@@ -1468,6 +1480,19 @@ impl TextFragment for StatusDisplay {
 
 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 {
@@ -1475,11 +1500,78 @@ 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 {
@@ -1487,6 +1579,34 @@ 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
     }