about summary refs log tree commit diff stats
path: root/src/comments/display.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/comments/display.rs')
-rw-r--r--src/comments/display.rs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/comments/display.rs b/src/comments/display.rs
new file mode 100644
index 0000000..7000063
--- /dev/null
+++ b/src/comments/display.rs
@@ -0,0 +1,117 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::fmt::Write;
+
+use chrono::{Local, TimeZone};
+use chrono_humanize::{Accuracy, HumanTime, Tense};
+
+use crate::comments::comment::CommentExt;
+
+use super::comment::Comments;
+
+impl Comments {
+    pub fn render(&self, color: bool) -> String {
+        self.render_help(color).expect("This should never fail.")
+    }
+
+    fn render_help(&self, color: bool) -> Result<String, std::fmt::Error> {
+        let mut f = String::new();
+
+        macro_rules! c {
+            ($color_str:expr, $write:ident, $color:expr) => {
+                if $color {
+                    $write.write_str(concat!("\x1b[", $color_str, "m"))?
+                }
+            };
+        }
+
+        fn format(
+            comment: &CommentExt,
+            f: &mut String,
+            ident_count: u32,
+            color: bool,
+        ) -> std::fmt::Result {
+            let ident = &(0..ident_count).map(|_| " ").collect::<String>();
+            let value = &comment.value;
+
+            f.write_str(ident)?;
+
+            if value.author_is_uploader {
+                c!("91;1", f, color);
+            } else {
+                c!("35", f, color);
+            }
+
+            f.write_str(&value.author)?;
+            c!("0", f, color);
+            if value.edited || value.is_favorited {
+                f.write_str("[")?;
+                if value.edited {
+                    f.write_str("")?;
+                }
+                if value.edited && value.is_favorited {
+                    f.write_str(" ")?;
+                }
+                if value.is_favorited {
+                    f.write_str("")?;
+                }
+                f.write_str("]")?;
+            }
+
+            c!("36;1", f, color);
+            write!(
+                f,
+                " {}",
+                HumanTime::from(
+                    Local
+                        .timestamp_opt(value.timestamp, 0)
+                        .single()
+                        .expect("This should be valid")
+                )
+                .to_text_en(Accuracy::Rough, Tense::Past)
+            )?;
+            c!("0", f, color);
+
+            // c!("31;1", f);
+            // f.write_fmt(format_args!(" [{}]", comment.value.like_count))?;
+            // c!("0", f);
+
+            f.write_str(":\n")?;
+            f.write_str(ident)?;
+
+            f.write_str(&value.text.replace('\n', &format!("\n{}", ident)))?;
+            f.write_str("\n")?;
+
+            if !comment.replies.is_empty() {
+                let mut children = comment.replies.clone();
+                children.sort_by(|a, b| a.value.timestamp.cmp(&b.value.timestamp));
+
+                for child in children {
+                    format(&child, f, ident_count + 4, color)?;
+                }
+            } else {
+                f.write_str("\n")?;
+            }
+
+            Ok(())
+        }
+
+        if !&self.vec.is_empty() {
+            let mut children = self.vec.clone();
+            children.sort_by(|a, b| b.value.like_count.cmp(&a.value.like_count));
+
+            for child in children {
+                format(&child, &mut f, 0, color)?
+            }
+        }
+        Ok(f)
+    }
+}