diff --git a/src/app.rs b/src/app.rs index c2bbb8c8..4039dc8f 100644 --- a/src/app.rs +++ b/src/app.rs @@ -78,7 +78,7 @@ pub enum IssueCobMessage { #[derive(Clone, Debug, Eq, PartialEq)] pub enum IssueMessage { - Show(IssueId), + Show(Option), Changed(IssueId), Focus(IssueCid), Created(IssueId), @@ -168,21 +168,41 @@ impl App { fn view_issue( &mut self, app: &mut Application, - id: IssueId, + id: Option, theme: &Theme, ) -> Result<()> { let repo = self.context.repository(); + match id { + Some(id) => { + if let Some(issue) = cob::issue::find(repo, &id)? { + let view = Box::new(IssuePage::new(&self.context, theme, Some((id, issue)))); + self.pages.push(view, app, &self.context, theme)?; - if let Some(issue) = cob::issue::find(repo, &id)? { - let view = Box::new(IssuePage::new(&self.context, theme, (id, issue))); - self.pages.push(view, app, &self.context, theme)?; + Ok(()) + } else { + Err(anyhow::anyhow!( + "Could not mount 'page::IssueView'. Issue not found." + )) + } + } + None => { + let view = Box::new(IssuePage::new(&self.context, theme, None)); + self.pages.push(view, app, &self.context, theme)?; - Ok(()) - } else { - Err(anyhow::anyhow!( - "Could not mount 'page::IssueView'. Issue not found." - )) + Ok(()) + } } + + // if let Some(issue) = cob::issue::find(repo, &id)? { + // let view = Box::new(IssuePage::new(&self.context, theme, (id, issue))); + // self.pages.push(view, app, &self.context, theme)?; + + // Ok(()) + // } else { + // Err(anyhow::anyhow!( + // "Could not mount 'page::IssueView'. Issue not found." + // )) + // } } fn process( diff --git a/src/app/event.rs b/src/app/event.rs index a54714c8..bccd7081 100644 --- a/src/app/event.rs +++ b/src/app/event.rs @@ -1,3 +1,4 @@ +use radicle::cob::issue::IssueId; use tuirealm::command::{Cmd, CmdResult, Direction as MoveDirection, Position}; use tuirealm::event::{Event, Key, KeyEvent, KeyModifiers}; use tuirealm::{MockComponent, NoUserEvent, State, StateValue}; @@ -277,6 +278,17 @@ impl tuirealm::Component for Widget { impl tuirealm::Component for Widget { fn on(&mut self, event: Event) -> Option { + let mut submit = || -> Option { + let result = self.perform(Cmd::Submit); + match result { + CmdResult::Submit(State::One(StateValue::Usize(selected))) => { + let item = self.items().get(selected)?; + Some(item.id().to_owned()) + } + _ => None, + } + }; + match event { Event::Keyboard(KeyEvent { code: Key::Up, .. }) => { self.perform(Cmd::Move(MoveDirection::Up)); @@ -288,16 +300,24 @@ impl tuirealm::Component for Widget { self.perform(Cmd::Move(MoveDirection::Down)); Some(Message::Tick) } + Event::Keyboard(KeyEvent { + code: Key::Char('n'), + .. + }) => { + let id = submit(); + Some(Message::Batch(vec![ + Message::Issue(IssueMessage::Show(id)), + Message::Issue(IssueMessage::OpenForm), + ])) + } Event::Keyboard(KeyEvent { code: Key::Enter, .. }) => { - let result = self.perform(Cmd::Submit); - match result { - CmdResult::Submit(State::One(StateValue::Usize(selected))) => { - let item = self.items().get(selected)?; - Some(Message::Issue(IssueMessage::Show(item.id().to_owned()))) - } - _ => None, + let id = submit(); + if id.is_some() { + Some(Message::Issue(IssueMessage::Show(id))) + } else { + None } } _ => None, diff --git a/src/app/page.rs b/src/app/page.rs index d5c18595..7b70a19e 100644 --- a/src/app/page.rs +++ b/src/app/page.rs @@ -94,6 +94,7 @@ impl HomeView { widget::common::shortcut(theme, "tab", "section"), widget::common::shortcut(theme, "↑/↓", "navigate"), widget::common::shortcut(theme, "enter", "show"), + widget::common::shortcut(theme, "n", "new issue"), widget::common::shortcut(theme, "q", "quit"), ], ), @@ -275,13 +276,13 @@ impl ViewPage for HomeView { /// Issue detail page /// pub struct IssuePage { - issue: (IssueId, Issue), + issue: Option<(IssueId, Issue)>, active_component: IssueCid, shortcuts: HashMap>, } impl IssuePage { - pub fn new(_context: &Context, theme: &Theme, issue: (IssueId, Issue)) -> Self { + pub fn new(_context: &Context, theme: &Theme, issue: Option<(IssueId, Issue)>) -> Self { let shortcuts = Self::build_shortcuts(theme); let active_component = IssueCid::List; @@ -413,22 +414,23 @@ impl ViewPage for IssuePage { context: &Context, theme: &Theme, ) -> Result<()> { - let (id, issue) = &self.issue; let header = widget::common::app_header(context, theme, None).to_boxed(); - let comments = issue.comments().collect::>(); - - let list = widget::issue::list(context, theme, (*id, issue.clone())).to_boxed(); - let details = widget::issue::details( - context, - theme, - (*id, issue.clone()), - comments.first().copied(), - ) - .to_boxed(); + let list = widget::issue::list(context, theme, self.issue.clone()).to_boxed(); app.remount(Cid::Issue(IssueCid::Header), header, vec![])?; app.remount(Cid::Issue(IssueCid::List), list, vec![])?; - app.remount(Cid::Issue(IssueCid::Details), details, vec![])?; + + if let Some((id, issue)) = &self.issue { + let comments = issue.comments().collect::>(); + let details = widget::issue::details( + context, + theme, + (*id, issue.clone()), + comments.first().copied(), + ) + .to_boxed(); + app.remount(Cid::Issue(IssueCid::Details), details, vec![])?; + } app.active(&Cid::Issue(self.active_component.clone()))?; @@ -441,12 +443,17 @@ impl ViewPage for IssuePage { fn unmount(&self, app: &mut Application) -> Result<()> { app.umount(&Cid::Issue(IssueCid::Header))?; app.umount(&Cid::Issue(IssueCid::List))?; - app.umount(&Cid::Issue(IssueCid::Details))?; app.umount(&Cid::Issue(IssueCid::Context))?; + app.umount(&Cid::Issue(IssueCid::Shortcuts))?; + + if app.mounted(&Cid::Issue(IssueCid::Details)) { + app.umount(&Cid::Issue(IssueCid::Details))?; + } + if app.mounted(&Cid::Issue(IssueCid::Form)) { app.umount(&Cid::Issue(IssueCid::Form))?; } - app.umount(&Cid::Issue(IssueCid::Shortcuts))?; + Ok(()) } @@ -462,7 +469,8 @@ impl ViewPage for IssuePage { let repo = context.repository(); if let Some(issue) = cob::issue::find(repo, &id)? { - let list = widget::issue::list(context, theme, (id, issue.clone())).to_boxed(); + let list = + widget::issue::list(context, theme, Some((id, issue.clone()))).to_boxed(); let comments = issue.comments().collect::>(); let details = widget::issue::details( @@ -517,6 +525,10 @@ impl ViewPage for IssuePage { self.activate(app, IssueCid::List)?; self.update_shortcuts(app, IssueCid::List)?; + + if self.issue.is_none() { + return Ok(Some(Message::Issue(IssueMessage::Leave))); + } } _ => {} } @@ -536,7 +548,7 @@ impl ViewPage for IssuePage { if app.mounted(&Cid::Issue(IssueCid::Form)) { app.view(&Cid::Issue(IssueCid::Form), frame, layout.right); - } else { + } else if app.mounted(&Cid::Issue(IssueCid::Details)) { app.view(&Cid::Issue(IssueCid::Details), frame, layout.right); } diff --git a/src/ui/widget/issue.rs b/src/ui/widget/issue.rs index b3e393b6..ccd68830 100644 --- a/src/ui/widget/issue.rs +++ b/src/ui/widget/issue.rs @@ -8,7 +8,6 @@ use radicle::cob::issue::IssueId; use tuirealm::tui::layout::{Constraint, Direction, Layout}; use tuirealm::StateValue; - use super::common::container::{Container, LabeledContainer}; use super::common::context::{ContextBar, Progress}; use super::common::form::Form; @@ -336,8 +335,12 @@ impl WidgetComponent for NewForm { } } -pub fn list(context: &Context, theme: &Theme, issue: (IssueId, Issue)) -> Widget { - let list = LargeList::new(context, theme, Some(issue)); +pub fn list( + context: &Context, + theme: &Theme, + issue: Option<(IssueId, Issue)>, +) -> Widget { + let list = LargeList::new(context, theme, issue); Widget::new(list) }