From 0381aa32813e0a7fe7e64c2a43fc81bf663ba287 Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Thu, 6 Apr 2023 21:01:28 +0200 Subject: [PATCH] tui: Add context bar to patch view page --- radicle-tui/src/app.rs | 43 +++++++-------- radicle-tui/src/ui.rs | 34 +++++++++++- radicle-tui/src/ui/cob/patch.rs | 22 +++++--- radicle-tui/src/ui/components/context.rs | 70 ++++++++++++++++++++++++ radicle-tui/src/ui/layout.rs | 24 ++++++++ 5 files changed, 160 insertions(+), 33 deletions(-) diff --git a/radicle-tui/src/app.rs b/radicle-tui/src/app.rs index 2cca21f8..8d861c66 100644 --- a/radicle-tui/src/app.rs +++ b/radicle-tui/src/app.rs @@ -14,7 +14,7 @@ use radicle_tui::cob::patch::{self}; use radicle_tui::subs; use radicle_tui::ui; use radicle_tui::ui::components::container::{GlobalListener, LabeledContainer, Tabs}; -use radicle_tui::ui::components::context::Shortcuts; +use radicle_tui::ui::components::context::{ContextBar, Shortcuts}; use radicle_tui::ui::components::list::PropertyList; use radicle_tui::ui::components::workspace::{Browser, PatchActivity, PatchFiles}; use radicle_tui::ui::layout; @@ -40,6 +40,7 @@ pub enum PatchCid { Navigation, Activity, Files, + Context, } /// All component ids known to this application. @@ -248,16 +249,8 @@ impl ViewPage for Home { )?; app.remount(Cid::Home(HomeCid::Dashboard), dashboard, vec![])?; - app.remount( - Cid::Home(HomeCid::IssueBrowser), - issue_browser, - vec![], - )?; - app.remount( - Cid::Home(HomeCid::PatchBrowser), - patch_browser, - vec![], - )?; + app.remount(Cid::Home(HomeCid::IssueBrowser), issue_browser, vec![])?; + app.remount(Cid::Home(HomeCid::PatchBrowser), patch_browser, vec![])?; app.remount(Cid::Shortcuts, shortcuts, vec![])?; Ok(()) @@ -285,11 +278,7 @@ impl ViewPage for Home { .unwrap_size(); let layout = layout::default_page(area, navigation_h, shortcuts_h); - app.view( - &Cid::Home(HomeCid::Navigation), - frame, - layout[0], - ); + app.view(&Cid::Home(HomeCid::Navigation), frame, layout[0]); app.view(&self.active_component, frame, layout[1]); app.view(&Cid::Shortcuts, frame, layout[2]); } @@ -322,10 +311,11 @@ impl ViewPage for PatchView { context: &Context, theme: &Theme, ) -> Result<()> { - if let Some((_, _)) = context.patches.get(context.selected_patch) { + if let Some((id, patch)) = context.patches.get(context.selected_patch) { let navigation = ui::patch_navigation(theme).to_boxed(); let activity = ui::patch_activity(theme).to_boxed(); let files = ui::patch_files(theme).to_boxed(); + let context = ui::patch_context(theme, (*id, patch), &context.profile).to_boxed(); let shortcuts = ui::shortcuts( theme, vec![ @@ -343,6 +333,7 @@ impl ViewPage for PatchView { )?; app.remount(Cid::Patch(PatchCid::Activity), activity, vec![])?; app.remount(Cid::Patch(PatchCid::Files), files, vec![])?; + app.remount(Cid::Patch(PatchCid::Context), context, vec![])?; app.remount(Cid::Shortcuts, shortcuts, vec![])?; } Ok(()) @@ -361,21 +352,19 @@ impl ViewPage for PatchView { fn view(&mut self, app: &mut Application, frame: &mut Frame) { let area = frame.size(); let navigation_h = 2u16; + let context_h = 1u16; let shortcuts_h = app .query(&Cid::Shortcuts, Attribute::Height) .ok() .flatten() .unwrap_or(AttrValue::Size(0)) .unwrap_size(); - let layout = layout::default_page(area, navigation_h, shortcuts_h); + let layout = layout::page_with_context(area, navigation_h, context_h, shortcuts_h); - app.view( - &Cid::Patch(PatchCid::Navigation), - frame, - layout[0], - ); + app.view(&Cid::Patch(PatchCid::Navigation), frame, layout[0]); app.view(&self.active_component, frame, layout[1]); - app.view(&Cid::Shortcuts, frame, layout[2]); + app.view(&Cid::Patch(PatchCid::Context), frame, layout[2]); + app.view(&Cid::Shortcuts, frame, layout[3]); } fn activate(&self, app: &mut Application) -> Result<()> { @@ -475,6 +464,12 @@ impl tuirealm::Component for Widget { } } +impl tuirealm::Component for Widget { + fn on(&mut self, _event: Event) -> Option { + None + } +} + impl tuirealm::Component for Widget { fn on(&mut self, _event: Event) -> Option { None diff --git a/radicle-tui/src/ui.rs b/radicle-tui/src/ui.rs index 165ab265..02a68025 100644 --- a/radicle-tui/src/ui.rs +++ b/radicle-tui/src/ui.rs @@ -7,7 +7,7 @@ pub mod widget; use radicle::prelude::{Id, Project}; use radicle::Profile; -use tuirealm::props::{AttrValue, Attribute, PropPayload, PropValue, TextSpan}; +use tuirealm::props::{AttrValue, Attribute, Color, PropPayload, PropValue, TextSpan}; use tuirealm::MockComponent; use radicle::cob::patch::{Patch, PatchId}; @@ -19,8 +19,11 @@ use components::list::{Property, PropertyList}; use widget::Widget; +use self::cob::patch; +use self::components::context::ContextBar; use self::components::list::{List, Table}; use self::components::workspace::{Browser, PatchActivity, PatchFiles}; +use self::theme::Theme; pub fn global_listener() -> Widget { Widget::new(GlobalListener::default()) @@ -162,6 +165,35 @@ pub fn patch_files(theme: &theme::Theme) -> Widget { Widget::new(files) } +pub fn patch_context( + _theme: &Theme, + patch: (PatchId, &Patch), + profile: &Profile, +) -> Widget { + let (id, patch) = patch; + let id = patch::format_id(id); + let title = patch.title(); + let author = patch::format_author(patch, profile); + let comments = patch::format_comments(patch); + + let context = label(" patch ").background(Color::Rgb(238, 111, 248)); + let id = label(&format!(" {} ", id)) + .foreground(Color::Rgb(117, 113, 249)) + .background(Color::Rgb(40, 40, 40)); + let title = label(&format!(" {} ", title)) + .foreground(Color::Rgb(70, 70, 70)) + .background(Color::Rgb(40, 40, 40)); + let author = label(&format!(" {} ", author)) + .foreground(Color::Rgb(117, 113, 249)) + .background(Color::Rgb(40, 40, 40)); + let comments = label(&format!(" {} ", comments)) + .foreground(Color::Rgb(70, 70, 70)) + .background(Color::Rgb(50, 50, 50)); + + let context_bar = ContextBar::new(context, id, author, title, comments); + Widget::new(context_bar) +} + pub fn home_navigation(theme: &theme::Theme) -> Widget { tabs( theme, diff --git a/radicle-tui/src/ui/cob/patch.rs b/radicle-tui/src/ui/cob/patch.rs index e2d29b94..e95bc672 100644 --- a/radicle-tui/src/ui/cob/patch.rs +++ b/radicle-tui/src/ui/cob/patch.rs @@ -10,15 +10,19 @@ use tuirealm::props::{Color, TextSpan}; use crate::ui::components::list::List; use crate::ui::theme::Theme; -fn format_status(_patch: &Patch) -> String { +pub fn format_status(_patch: &Patch) -> String { String::from(" ⏺ ") } -fn format_title(patch: &Patch) -> String { +pub fn format_id(id: PatchId) -> String { + id.to_string()[0..10].to_string() +} + +pub fn format_title(patch: &Patch) -> String { patch.title().to_string() } -fn format_author(patch: &Patch, profile: &Profile) -> String { +pub 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]; @@ -30,11 +34,11 @@ fn format_author(patch: &Patch, profile: &Profile) -> String { } } -fn format_tags(patch: &Patch) -> String { +pub fn format_tags(patch: &Patch) -> String { format!("{:?}", patch.tags().collect::>()) } -fn format_timestamp(patch: &Patch) -> String { +pub fn format_timestamp(patch: &Patch) -> String { let fmt = timeago::Formatter::new(); let now = SystemTime::now() .duration_since(UNIX_EPOCH) @@ -44,9 +48,11 @@ fn format_timestamp(patch: &Patch) -> String { 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(); +pub fn format_comments(patch: &Patch) -> String { + let count = match patch.latest() { + Some((_, rev)) => rev.discussion().len(), + None => 0, + }; format!("{}", count) } diff --git a/radicle-tui/src/ui/components/context.rs b/radicle-tui/src/ui/components/context.rs index 8fb8181a..21d8b05c 100644 --- a/radicle-tui/src/ui/components/context.rs +++ b/radicle-tui/src/ui/components/context.rs @@ -102,3 +102,73 @@ impl WidgetComponent for Shortcuts { CmdResult::None } } + +pub struct ContextBar { + context: Widget