Support opening new issues from issue browser

This commit is contained in:
Erik Kundt
2023-08-11 11:45:07 +02:00
parent ad493fce60
commit 38ad53cd14
4 changed files with 93 additions and 38 deletions
+30 -10
View File
@@ -78,7 +78,7 @@ pub enum IssueCobMessage {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum IssueMessage {
Show(IssueId),
Show(Option<IssueId>),
Changed(IssueId),
Focus(IssueCid),
Created(IssueId),
@@ -168,21 +168,41 @@ impl App {
fn view_issue(
&mut self,
app: &mut Application<Cid, Message, NoUserEvent>,
id: IssueId,
id: Option<IssueId>,
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(
+27 -7
View File
@@ -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<Message, NoUserEvent> for Widget<PatchBrowser> {
impl tuirealm::Component<Message, NoUserEvent> for Widget<IssueBrowser> {
fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
let mut submit = || -> Option<IssueId> {
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<Message, NoUserEvent> for Widget<IssueBrowser> {
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,
+30 -18
View File
@@ -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<IssueCid, Widget<Shortcuts>>,
}
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::<Vec<_>>();
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::<Vec<_>>();
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<Cid, Message, NoUserEvent>) -> 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::<Vec<_>>();
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);
}
+6 -3
View File
@@ -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<LargeList> {
let list = LargeList::new(context, theme, Some(issue));
pub fn list(
context: &Context,
theme: &Theme,
issue: Option<(IssueId, Issue)>,
) -> Widget<LargeList> {
let list = LargeList::new(context, theme, issue);
Widget::new(list)
}