diff --git a/bin/commands/inbox/flux/select.rs b/bin/commands/inbox/flux/select.rs index 9f8b43f8..5179dbfd 100644 --- a/bin/commands/inbox/flux/select.rs +++ b/bin/commands/inbox/flux/select.rs @@ -15,7 +15,7 @@ use radicle_tui as tui; use tui::common::cob::inbox::{self}; use tui::flux::store::{State, Store}; use tui::flux::task::{self, Interrupted}; -use tui::flux::ui::cob::NotificationItem; +use tui::flux::ui::items::NotificationItem; use tui::flux::ui::Frontend; use tui::Exit; diff --git a/bin/commands/inbox/flux/select/ui.rs b/bin/commands/inbox/flux/select/ui.rs index 7a4f2ef3..6286c5f4 100644 --- a/bin/commands/inbox/flux/select/ui.rs +++ b/bin/commands/inbox/flux/select/ui.rs @@ -13,7 +13,7 @@ use radicle::identity::Project; use radicle_tui as tui; -use tui::flux::ui::cob::NotificationItem; +use tui::flux::ui::items::NotificationItem; use tui::flux::ui::span; use tui::flux::ui::widget::container::{Footer, FooterProps, Header, HeaderProps}; use tui::flux::ui::widget::{ diff --git a/bin/commands/issue/flux/select.rs b/bin/commands/issue/flux/select.rs index e5c6afdc..1706fcd5 100644 --- a/bin/commands/issue/flux/select.rs +++ b/bin/commands/issue/flux/select.rs @@ -12,7 +12,7 @@ use radicle_tui as tui; use tui::common::cob::issue::{self, Filter}; use tui::flux::store::{self, StateValue}; use tui::flux::task::{self, Interrupted}; -use tui::flux::ui::cob::IssueItem; +use tui::flux::ui::items::IssueItem; use tui::flux::ui::Frontend; use tui::Exit; diff --git a/bin/commands/issue/flux/select/ui.rs b/bin/commands/issue/flux/select/ui.rs index c55bf7ff..3dd2eb89 100644 --- a/bin/commands/issue/flux/select/ui.rs +++ b/bin/commands/issue/flux/select/ui.rs @@ -14,7 +14,7 @@ use ratatui::text::Line; use radicle_tui as tui; -use tui::flux::ui::cob::{IssueItem, IssueItemFilter}; +use tui::flux::ui::items::{IssueItem, IssueItemFilter}; use tui::flux::ui::span; use tui::flux::ui::widget::container::{Footer, FooterProps, Header, HeaderProps}; use tui::flux::ui::widget::input::{TextField, TextFieldProps}; diff --git a/bin/commands/patch/flux/select.rs b/bin/commands/patch/flux/select.rs index 07213ec4..736df1c7 100644 --- a/bin/commands/patch/flux/select.rs +++ b/bin/commands/patch/flux/select.rs @@ -12,7 +12,7 @@ use radicle_tui as tui; use tui::common::cob::patch::{self, Filter}; use tui::flux::store::{State, StateValue, Store}; use tui::flux::task::{self, Interrupted}; -use tui::flux::ui::cob::PatchItem; +use tui::flux::ui::items::PatchItem; use tui::flux::ui::Frontend; use tui::Exit; diff --git a/bin/commands/patch/flux/select/ui.rs b/bin/commands/patch/flux/select/ui.rs index ba915627..009dd749 100644 --- a/bin/commands/patch/flux/select/ui.rs +++ b/bin/commands/patch/flux/select/ui.rs @@ -16,7 +16,7 @@ use ratatui::text::Line; use radicle_tui as tui; use tui::flux::store::StateValue; -use tui::flux::ui::cob::{PatchItem, PatchItemFilter}; +use tui::flux::ui::items::{PatchItem, PatchItemFilter}; use tui::flux::ui::span; use tui::flux::ui::widget::container::{Footer, FooterProps, Header, HeaderProps}; use tui::flux::ui::widget::input::{TextField, TextFieldProps}; diff --git a/src/common/cob.rs b/src/common/cob.rs index acf64da8..0ce05f56 100644 --- a/src/common/cob.rs +++ b/src/common/cob.rs @@ -5,7 +5,6 @@ use anyhow::Result; use radicle::cob::Label; use radicle::prelude::Did; -pub mod format; pub mod inbox; pub mod issue; pub mod patch; diff --git a/src/common/cob/format.rs b/src/common/cob/format.rs deleted file mode 100644 index 22c4249a..00000000 --- a/src/common/cob/format.rs +++ /dev/null @@ -1,7 +0,0 @@ -use radicle::identity::Did; - -/// Format a DID. -pub fn did(did: &Did) -> String { - let nid = did.as_key().to_human(); - format!("{}…{}", &nid[..7], &nid[nid.len() - 7..]) -} diff --git a/src/flux/ui.rs b/src/flux/ui.rs index 31788791..ab056a8e 100644 --- a/src/flux/ui.rs +++ b/src/flux/ui.rs @@ -1,6 +1,6 @@ -pub mod cob; pub mod ext; pub mod format; +pub mod items; pub mod layout; pub mod span; pub mod theme; diff --git a/src/flux/ui/format.rs b/src/flux/ui/format.rs index 42db0ff0..943784a5 100644 --- a/src/flux/ui/format.rs +++ b/src/flux/ui/format.rs @@ -1,5 +1,11 @@ +use radicle::cob::Label; use radicle::cob::{ObjectId, Timestamp}; +use radicle::crypto::PublicKey; +use radicle::issue; +use radicle::node::Alias; +use radicle::patch; use radicle::prelude::Did; +use ratatui::style::Color; /// Format a git Oid. pub fn oid(oid: impl Into) -> String { @@ -25,3 +31,65 @@ pub fn timestamp(time: &Timestamp) -> String { fmt.convert(duration) } + +pub fn issue_state(state: &issue::State) -> (String, Color) { + match state { + issue::State::Open => (" ● ".into(), Color::Green), + issue::State::Closed { reason: _ } => (" ● ".into(), Color::Red), + } +} + +pub fn patch_state(state: &patch::State) -> (String, Color) { + match state { + patch::State::Open { conflicts: _ } => (" ● ".into(), Color::Green), + patch::State::Archived => (" ● ".into(), Color::Yellow), + patch::State::Draft => (" ● ".into(), Color::Gray), + patch::State::Merged { + revision: _, + commit: _, + } => (" ✔ ".into(), Color::Magenta), + } +} + +pub fn labels(labels: &[Label]) -> String { + let mut output = String::new(); + let mut labels = labels.iter().peekable(); + + while let Some(label) = labels.next() { + output.push_str(&label.to_string()); + + if labels.peek().is_some() { + output.push(','); + } + } + output +} + +pub fn author(did: &Did, alias: &Option, is_you: bool) -> String { + let author = match alias { + Some(alias) => format!("{alias}"), + None => self::did(did), + }; + + if is_you { + format!("{} (you)", author) + } else { + author + } +} + +pub fn assignees(assignees: &[(Option, Option, bool)]) -> String { + let mut output = String::new(); + let mut assignees = assignees.iter().peekable(); + + while let Some((assignee, alias, is_you)) = assignees.next() { + if let Some(assignee) = assignee { + output.push_str(&self::author(&Did::from(assignee), alias, *is_you)); + } + + if assignees.peek().is_some() { + output.push(','); + } + } + output +} diff --git a/src/flux/ui/cob.rs b/src/flux/ui/items.rs similarity index 92% rename from src/flux/ui/cob.rs rename to src/flux/ui/items.rs index 4a9baf1f..87ed14e3 100644 --- a/src/flux/ui/cob.rs +++ b/src/flux/ui/items.rs @@ -6,7 +6,6 @@ use nom::sequence::{delimited, preceded}; use nom::{IResult, Parser}; use radicle::cob::{Label, ObjectId, Timestamp, TypedId}; -use radicle::crypto::PublicKey; use radicle::git::Oid; use radicle::identity::{Did, Identity}; use radicle::issue::{self, CloseReason, Issue, IssueId, Issues}; @@ -18,7 +17,7 @@ use radicle::storage::git::Repository; use radicle::storage::{ReadRepository, ReadStorage, RefUpdate, WriteRepository}; use radicle::Profile; -use ratatui::style::{Color, Style, Stylize}; +use ratatui::style::{Style, Stylize}; use ratatui::widgets::Cell; use super::super::git; @@ -359,7 +358,7 @@ impl IssueItem { impl ToRow<8> for IssueItem { fn to_row(&self) -> [Cell; 8] { - let (state, state_color) = format_issue_state(&self.state); + let (state, state_color) = format::issue_state(&self.state); let state = span::default(state).style(Style::default().fg(state_color)); let id = span::primary(format::cob(&self.id)); @@ -382,13 +381,13 @@ impl ToRow<8> for IssueItem { Some(nid) => span::alias(format::did(&Did::from(nid))).dim(), None => span::alias("".to_string()), }; - let labels = span::labels(format_labels(&self.labels)); + let labels = span::labels(format::labels(&self.labels)); let assignees = self .assignees .iter() .map(|author| (author.nid, author.alias.clone(), author.you)) .collect::>(); - let assignees = span::alias(format_assignees(&assignees)); + let assignees = span::alias(format::assignees(&assignees)); let opened = span::timestamp(format::timestamp(&self.timestamp)); [ @@ -608,7 +607,7 @@ impl PatchItem { impl ToRow<9> for PatchItem { fn to_row(&self) -> [Cell; 9] { - let (state, color) = format_patch_state(&self.state); + let (state, color) = format::patch_state(&self.state); let state = span::default(state).style(Style::default().fg(color)); let id = span::primary(format::cob(&self.id)); @@ -752,68 +751,6 @@ impl FromStr for PatchItemFilter { } } -pub fn format_issue_state(state: &issue::State) -> (String, Color) { - match state { - issue::State::Open => (" ● ".into(), Color::Green), - issue::State::Closed { reason: _ } => (" ● ".into(), Color::Red), - } -} - -pub fn format_patch_state(state: &patch::State) -> (String, Color) { - match state { - patch::State::Open { conflicts: _ } => (" ● ".into(), Color::Green), - patch::State::Archived => (" ● ".into(), Color::Yellow), - patch::State::Draft => (" ● ".into(), Color::Gray), - patch::State::Merged { - revision: _, - commit: _, - } => (" ✔ ".into(), Color::Magenta), - } -} - -pub fn format_labels(labels: &[Label]) -> String { - let mut output = String::new(); - let mut labels = labels.iter().peekable(); - - while let Some(label) = labels.next() { - output.push_str(&label.to_string()); - - if labels.peek().is_some() { - output.push(','); - } - } - output -} - -pub fn format_author(did: &Did, alias: &Option, is_you: bool) -> String { - let author = match alias { - Some(alias) => format!("{alias}"), - None => format::did(did), - }; - - if is_you { - format!("{} (you)", author) - } else { - author - } -} - -pub fn format_assignees(assignees: &[(Option, Option, bool)]) -> String { - let mut output = String::new(); - let mut assignees = assignees.iter().peekable(); - - while let Some((assignee, alias, is_you)) = assignees.next() { - if let Some(assignee) = assignee { - output.push_str(&format_author(&Did::from(assignee), alias, *is_you)); - } - - if assignees.peek().is_some() { - output.push(','); - } - } - output -} - #[cfg(test)] mod tests { use anyhow::Result;