mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-15 07:50:39 +08:00
Support opening new issues from issue browser
This commit is contained in:
+30
-10
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user