Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Support opening new issues from issue browser
Erik Kundt committed 2 years ago
commit 38ad53cd14ffa5a7978a488b298be77d861fc0ab
parent ad493fce604004b610c8c6cd0070919b1765f264
4 files changed +94 -39
modified src/app.rs
@@ -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)?;
+

+
                    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)?;

-
        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."
-
            ))
+
                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(
modified 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<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));
@@ -289,15 +301,23 @@ impl tuirealm::Component<Message, NoUserEvent> for Widget<IssueBrowser> {
                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,
modified 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<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);
        }

modified 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<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)
}