From 80c1e45a9900baced069dee93dd293fe2bc072b7 Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Fri, 24 Mar 2023 13:44:09 +0100 Subject: [PATCH] tui: Add ui wrapper for patches Signed-off-by: Erik Kundt --- Cargo.lock | 40 ++++++++++++++++- radicle-tui/Cargo.toml | 1 + radicle-tui/src/ui/cob.rs | 1 + radicle-tui/src/ui/cob/patch.rs | 77 +++++++++++++++++++++++++++++++++ radicle-tui/src/ui/theme.rs | 10 +++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 radicle-tui/src/ui/cob.rs create mode 100644 radicle-tui/src/ui/cob/patch.rs diff --git a/Cargo.lock b/Cargo.lock index 84d12329..4759556a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1246,6 +1246,15 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "isolang" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64fd6448ee8a45ce6e4365c58e4fa7d8740cba2ed70db3e9ab4879ebd93eaaa" +dependencies = [ + "phf", +] + [[package]] name = "itoa" version = "1.0.5" @@ -1677,6 +1686,24 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.0.12" @@ -1893,7 +1920,7 @@ dependencies = [ "similar", "tempfile", "thiserror", - "timeago", + "timeago 0.3.1", "ureq", "zeroize", ] @@ -2136,6 +2163,7 @@ dependencies = [ "radicle", "radicle-cli", "radicle-term", + "timeago 0.4.1", "tui-realm-stdlib", "tuirealm", ] @@ -2835,6 +2863,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ec32dde57efb15c035ac074118d7f32820451395f28cb0524a01d4e94983b26" +[[package]] +name = "timeago" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5082dc942361cdfb74eab98bf995762d6015e5bb3a20bf7c5c71213778b4fcb4" +dependencies = [ + "chrono", + "isolang", +] + [[package]] name = "tinyvec" version = "1.6.0" diff --git a/radicle-tui/Cargo.toml b/radicle-tui/Cargo.toml index 8c736d90..d7e47811 100644 --- a/radicle-tui/Cargo.toml +++ b/radicle-tui/Cargo.toml @@ -13,6 +13,7 @@ path = "src/main.rs" [dependencies] anyhow = { version = "1" } lexopt = { version = "0.2" } +timeago = { version = "0.4.1" } tuirealm = { version = "1.8.0", default-features = false, features = [ "with-termion" ] } tui-realm-stdlib = { version = "1.2.0", default-features = false, features = [ "with-termion" ] } diff --git a/radicle-tui/src/ui/cob.rs b/radicle-tui/src/ui/cob.rs new file mode 100644 index 00000000..e268c5ac --- /dev/null +++ b/radicle-tui/src/ui/cob.rs @@ -0,0 +1 @@ +pub mod patch; diff --git a/radicle-tui/src/ui/cob/patch.rs b/radicle-tui/src/ui/cob/patch.rs new file mode 100644 index 00000000..e2d29b94 --- /dev/null +++ b/radicle-tui/src/ui/cob/patch.rs @@ -0,0 +1,77 @@ +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use radicle::Profile; +use timeago; + +use radicle::cob::patch::{Patch, PatchId}; + +use tuirealm::props::{Color, TextSpan}; + +use crate::ui::components::list::List; +use crate::ui::theme::Theme; + +fn format_status(_patch: &Patch) -> String { + String::from(" ⏺ ") +} + +fn format_title(patch: &Patch) -> String { + patch.title().to_string() +} + +fn format_author(patch: &Patch, profile: &Profile) -> String { + let author_did = patch.author().id(); + let start = &author_did.to_human()[0..4]; + let end = &author_did.to_human()[43..47]; + + if *author_did == profile.did() { + format!("did:key:{}...{} (you)", start, end) + } else { + format!("did:key:{}...{}", start, end) + } +} + +fn format_tags(patch: &Patch) -> String { + format!("{:?}", patch.tags().collect::>()) +} + +fn format_timestamp(patch: &Patch) -> String { + let fmt = timeago::Formatter::new(); + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); + + fmt.convert(Duration::from_secs(now - patch.timestamp().as_secs())) +} + +fn format_comments(patch: &Patch) -> String { + let (_, revision) = patch.latest().unwrap(); + let count = revision.discussion().len(); + format!("{}", count) +} + +impl List for (PatchId, Patch) { + fn row(&self, theme: &Theme, profile: &Profile) -> Vec { + let (_, patch) = self; + + let status = format_status(patch); + let status = TextSpan::from(status).fg(Color::Green); + + let title = format_title(patch); + let title = TextSpan::from(title).fg(theme.colors.browser_patch_list_title); + + let author = format_author(patch, profile); + let author = TextSpan::from(author).fg(theme.colors.browser_patch_list_author); + + let tags = format_tags(patch); + let tags = TextSpan::from(tags).fg(theme.colors.browser_patch_list_tags); + + let comments = format_comments(patch); + let comments = TextSpan::from(comments).fg(theme.colors.browser_patch_list_comments); + + let timestamp = format_timestamp(patch); + let timestamp = TextSpan::from(timestamp).fg(theme.colors.browser_patch_list_timestamp); + + vec![status, title, author, tags, comments, timestamp] + } +} diff --git a/radicle-tui/src/ui/theme.rs b/radicle-tui/src/ui/theme.rs index 6d430a9d..9e266917 100644 --- a/radicle-tui/src/ui/theme.rs +++ b/radicle-tui/src/ui/theme.rs @@ -13,6 +13,11 @@ pub struct Colors { pub shortcut_short_fg: Color, pub shortcut_long_fg: Color, pub shortcutbar_divider_fg: Color, + pub browser_patch_list_title: Color, + pub browser_patch_list_author: Color, + pub browser_patch_list_tags: Color, + pub browser_patch_list_comments: Color, + pub browser_patch_list_timestamp: Color, } #[derive(Debug)] @@ -59,6 +64,11 @@ pub fn default_dark() -> Theme { shortcut_short_fg: Color::Rgb(100, 100, 100), shortcut_long_fg: Color::Rgb(70, 70, 70), shortcutbar_divider_fg: Color::Rgb(70, 70, 70), + browser_patch_list_title: Color::Rgb(200, 200, 200), + browser_patch_list_author: Color::Rgb(85, 85, 255), + browser_patch_list_tags: Color::Rgb(220, 140, 40), + browser_patch_list_comments: Color::Rgb(150, 150, 150), + browser_patch_list_timestamp: Color::Rgb(100, 100, 100), }, icons: Icons { property_divider: '∙',