diff --git a/radicle-tui/src/app.rs b/radicle-tui/src/app.rs index d0a6879d..a4578085 100644 --- a/radicle-tui/src/app.rs +++ b/radicle-tui/src/app.rs @@ -39,6 +39,7 @@ pub enum PatchCid { #[derive(Debug, Eq, PartialEq, Clone, Hash)] pub enum IssueCid { List, + Details, Shortcuts, } @@ -58,6 +59,7 @@ pub enum HomeMessage {} #[derive(Debug, Eq, PartialEq)] pub enum IssueMessage { Show(IssueId), + Changed(IssueId), Leave, } @@ -186,7 +188,9 @@ impl Tui for App { } Message::Quit => self.quit = true, _ => { - self.pages.peek_mut()?.update(app, message)?; + self.pages + .peek_mut()? + .update(app, &self.context, &theme, message)?; } } } diff --git a/radicle-tui/src/app/event.rs b/radicle-tui/src/app/event.rs index 4b23481b..fd1b1f71 100644 --- a/radicle-tui/src/app/event.rs +++ b/radicle-tui/src/app/event.rs @@ -52,20 +52,38 @@ impl tuirealm::Component for Widget { Some(Message::Issue(IssueMessage::Leave)) } Event::Keyboard(KeyEvent { code: Key::Up, .. }) => { - self.perform(Cmd::Move(MoveDirection::Up)); - Some(Message::Tick) + let result = self.perform(Cmd::Move(MoveDirection::Up)); + match result { + CmdResult::Changed(State::One(StateValue::Usize(selected))) => { + let item = self.items().get(selected)?; + Some(Message::Issue(IssueMessage::Changed(item.id().to_owned()))) + } + _ => None, + } } Event::Keyboard(KeyEvent { code: Key::Down, .. }) => { - self.perform(Cmd::Move(MoveDirection::Down)); - Some(Message::Tick) + let result = self.perform(Cmd::Move(MoveDirection::Down)); + match result { + CmdResult::Changed(State::One(StateValue::Usize(selected))) => { + let item = self.items().get(selected)?; + Some(Message::Issue(IssueMessage::Changed(item.id().to_owned()))) + } + _ => None, + } } _ => None, } } } +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 { match event { diff --git a/radicle-tui/src/app/page.rs b/radicle-tui/src/app/page.rs index 2490cadb..c080eca3 100644 --- a/radicle-tui/src/app/page.rs +++ b/radicle-tui/src/app/page.rs @@ -3,6 +3,7 @@ use anyhow::Result; use radicle::cob::issue::{Issue, IssueId}; use radicle::cob::patch::{Patch, PatchId}; +use radicle_tui::cob; use tuirealm::{Frame, NoUserEvent, Sub, SubClause}; use radicle_tui::ui::context::Context; @@ -10,7 +11,7 @@ use radicle_tui::ui::layout; use radicle_tui::ui::theme::Theme; use radicle_tui::ui::widget; -use super::{subscription, Application, Cid, HomeCid, IssueCid, Message, PatchCid}; +use super::{subscription, Application, Cid, HomeCid, IssueCid, IssueMessage, Message, PatchCid}; /// `tuirealm`'s event and prop system is designed to work with flat component hierarchies. /// Building deep nested component hierarchies would need a lot more additional effort to @@ -36,6 +37,8 @@ pub trait ViewPage { fn update( &mut self, app: &mut Application, + context: &Context, + theme: &Theme, message: Message, ) -> Result<()>; @@ -101,6 +104,8 @@ impl ViewPage for HomeView { fn update( &mut self, app: &mut Application, + _context: &Context, + _theme: &Theme, message: Message, ) -> Result<()> { if let Message::NavigationChanged(index) = message { @@ -162,8 +167,9 @@ impl ViewPage for IssuePage { context: &Context, theme: &Theme, ) -> Result<()> { - let (id, issue) = self.issue.clone(); - let list = widget::issue::list(context, theme, (id, issue)).to_boxed(); + let (id, issue) = &self.issue; + let list = widget::issue::list(context, theme, (*id, issue.clone())).to_boxed(); + let details = widget::issue::details(context, theme, (*id, issue.clone())).to_boxed(); let shortcuts = widget::common::shortcuts( theme, vec![ @@ -174,6 +180,7 @@ impl ViewPage for IssuePage { .to_boxed(); app.remount(Cid::Issue(IssueCid::List), list, vec![])?; + app.remount(Cid::Issue(IssueCid::Details), details, vec![])?; app.remount(Cid::Issue(IssueCid::Shortcuts), shortcuts, vec![])?; app.active(&self.active_component)?; @@ -183,6 +190,7 @@ impl ViewPage for IssuePage { fn unmount(&self, app: &mut Application) -> Result<()> { app.umount(&Cid::Issue(IssueCid::List))?; + app.umount(&Cid::Issue(IssueCid::Details))?; app.umount(&Cid::Issue(IssueCid::Shortcuts))?; Ok(()) } @@ -190,8 +198,17 @@ impl ViewPage for IssuePage { fn update( &mut self, app: &mut Application, - _message: Message, + context: &Context, + theme: &Theme, + message: Message, ) -> Result<()> { + if let Message::Issue(IssueMessage::Changed(id)) = message { + let repo = context.repository(); + if let Some(issue) = cob::issue::find(repo, &id)? { + let details = widget::issue::details(context, theme, (id, issue)).to_boxed(); + app.remount(Cid::Issue(IssueCid::Details), details, vec![])?; + } + } app.active(&self.active_component)?; Ok(()) @@ -203,6 +220,7 @@ impl ViewPage for IssuePage { let layout = layout::issue_preview(area, shortcuts_h); app.view(&Cid::Issue(IssueCid::List), frame, layout.left); + app.view(&Cid::Issue(IssueCid::Details), frame, layout.details); app.view(&Cid::Issue(IssueCid::Shortcuts), frame, layout.shortcuts); } @@ -263,6 +281,8 @@ impl ViewPage for PatchView { fn update( &mut self, app: &mut Application, + _context: &Context, + _theme: &Theme, message: Message, ) -> Result<()> { if let Message::NavigationChanged(index) = message { diff --git a/radicle-tui/src/ui/cob.rs b/radicle-tui/src/ui/cob.rs index 9c6f206d..9ffe9981 100644 --- a/radicle-tui/src/ui/cob.rs +++ b/radicle-tui/src/ui/cob.rs @@ -33,6 +33,16 @@ pub struct AuthorItem { is_you: bool, } +impl AuthorItem { + pub fn did(&self) -> Did { + self.did + } + + pub fn is_you(&self) -> bool { + self.is_you + } +} + /// A patch item that can be used in tables, list or trees. /// /// Breaks up dependencies to [`Profile`] and [`Repository`] that diff --git a/radicle-tui/src/ui/layout.rs b/radicle-tui/src/ui/layout.rs index 71dc7232..f259a0f3 100644 --- a/radicle-tui/src/ui/layout.rs +++ b/radicle-tui/src/ui/layout.rs @@ -4,7 +4,8 @@ use tuirealm::MockComponent; pub struct IssuePreview { pub left: Rect, - pub right: Rect, + pub details: Rect, + pub discussion: Rect, pub shortcuts: Rect, } @@ -158,9 +159,15 @@ pub fn issue_preview(area: Rect, shortcuts_h: u16) -> IssuePreview { .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) .split(root[0]); + let right = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Length(6), Constraint::Min(0)].as_ref()) + .split(split[1]); + IssuePreview { left: split[0], - right: split[1], + details: right[0], + discussion: right[1], shortcuts: root[1], } } diff --git a/radicle-tui/src/ui/widget/common.rs b/radicle-tui/src/ui/widget/common.rs index 71ddf51c..a1648b0b 100644 --- a/radicle-tui/src/ui/widget/common.rs +++ b/radicle-tui/src/ui/widget/common.rs @@ -11,7 +11,8 @@ use context::{Shortcut, Shortcuts}; use label::Label; use list::{Property, PropertyList}; -use self::list::ColumnWidth; +use self::container::Container; +use self::list::{ColumnWidth, PropertyTable}; use super::Widget; @@ -43,6 +44,11 @@ pub fn container_header(theme: &Theme, label: Widget