Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
tui: Fix global navigation subscriptions
Erik Kundt committed 2 years ago
commit d6812310018ed60146287771d05b05b90bead207
parent 33d4ec0f1a2ec0efc531c889d77dce189534f7bf
2 files changed +91 -23
modified radicle-tui/src/app/page.rs
@@ -1,10 +1,9 @@
use anyhow::Result;

-
use radicle::cob::{
-
    issue::{Issue, IssueId},
-
    patch::{Patch, PatchId},
-
};
-
use tuirealm::{Frame, NoUserEvent};
+
use radicle::cob::issue::{Issue, IssueId};
+
use radicle::cob::patch::{Patch, PatchId};
+

+
use tuirealm::{Frame, NoUserEvent, Sub, SubClause};

use radicle_tui::ui::layout;
use radicle_tui::ui::theme::Theme;
@@ -41,6 +40,14 @@ pub trait ViewPage {

    /// Will be called whenever a view page is on top of the page stack and needs to be rendered.
    fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame);
+

+
    /// Will be called whenever this view page is pushed to the stack, or it is on top of the stack again
+
    /// after another view page was popped from the stack.
+
    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()>;
+

+
    /// Will be called whenever this view page is on top of the stack and another view page is pushed
+
    /// to the stack, or if this is popped from the stack.
+
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()>;
}

///
@@ -71,11 +78,7 @@ impl ViewPage for HomeView {
        let issue_browser = widget::home::issues(theme, &context.id, &context.profile).to_boxed();
        let patch_browser = widget::home::patches(theme, &context.id, &context.profile).to_boxed();

-
        app.remount(
-
            Cid::Home(HomeCid::Navigation),
-
            navigation,
-
            subscription::navigation(),
-
        )?;
+
        app.remount(Cid::Home(HomeCid::Navigation), navigation, vec![])?;

        app.remount(Cid::Home(HomeCid::Dashboard), dashboard, vec![])?;
        app.remount(Cid::Home(HomeCid::IssueBrowser), issue_browser, vec![])?;
@@ -114,6 +117,27 @@ impl ViewPage for HomeView {
        app.view(&Cid::Home(HomeCid::Navigation), frame, layout[0]);
        app.view(&self.active_component, frame, layout[1]);
    }
+

+
    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.subscribe(
+
            &Cid::Home(HomeCid::Navigation),
+
            Sub::new(
+
                subscription::navigation_clause::<Cid, _>(),
+
                SubClause::Always,
+
            ),
+
        )?;
+

+
        Ok(())
+
    }
+

+
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.unsubscribe(
+
            &Cid::Home(HomeCid::Navigation),
+
            subscription::navigation_clause::<Cid, _>(),
+
        )?;
+

+
        Ok(())
+
    }
}

///
@@ -171,6 +195,27 @@ impl ViewPage for IssuePage {
        app.view(&Cid::Patch(PatchCid::Navigation), frame, layout[0]);
        app.view(&self.active_component, frame, layout[1]);
    }
+

+
    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.subscribe(
+
            &Cid::Home(HomeCid::Navigation),
+
            Sub::new(
+
                subscription::navigation_clause::<Cid, _>(),
+
                SubClause::Always,
+
            ),
+
        )?;
+

+
        Ok(())
+
    }
+

+
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.unsubscribe(
+
            &Cid::Home(HomeCid::Navigation),
+
            subscription::navigation_clause::<Cid, _>(),
+
        )?;
+

+
        Ok(())
+
    }
}

///
@@ -202,11 +247,7 @@ impl ViewPage for PatchView {
        let activity = widget::patch::activity(theme, (*id, patch), &context.profile).to_boxed();
        let files = widget::patch::files(theme, (*id, patch), &context.profile).to_boxed();

-
        app.remount(
-
            Cid::Patch(PatchCid::Navigation),
-
            navigation,
-
            subscription::navigation(),
-
        )?;
+
        app.remount(Cid::Patch(PatchCid::Navigation), navigation, vec![])?;
        app.remount(Cid::Patch(PatchCid::Activity), activity, vec![])?;
        app.remount(Cid::Patch(PatchCid::Files), files, vec![])?;

@@ -242,6 +283,27 @@ impl ViewPage for PatchView {
        app.view(&Cid::Patch(PatchCid::Navigation), frame, layout[0]);
        app.view(&self.active_component, frame, layout[1]);
    }
+

+
    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.subscribe(
+
            &Cid::Patch(PatchCid::Navigation),
+
            Sub::new(
+
                subscription::navigation_clause::<Cid, _>(),
+
                SubClause::Always,
+
            ),
+
        )?;
+

+
        Ok(())
+
    }
+

+
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.unsubscribe(
+
            &Cid::Patch(PatchCid::Navigation),
+
            subscription::navigation_clause::<Cid, _>(),
+
        )?;
+

+
        Ok(())
+
    }
}

/// View pages need to preserve their state (e.g. selected navigation tab, contents
@@ -265,16 +327,25 @@ impl PageStack {
        context: &Context,
        theme: &Theme,
    ) -> Result<()> {
+
        if let Some(page) = self.pages.last() {
+
            page.unsubscribe(app)?;
+
        }
+

        page.mount(app, context, theme)?;
+
        page.subscribe(app)?;
+

        self.pages.push(page);

        Ok(())
    }

    pub fn pop(&mut self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        self.peek_mut()?.unsubscribe(app)?;
        self.peek_mut()?.unmount(app)?;
        self.pages.pop();

+
        self.peek_mut()?.subscribe(app)?;
+

        Ok(())
    }

modified radicle-tui/src/app/subscription.rs
@@ -3,18 +3,15 @@ use std::hash::Hash;
use tuirealm::event::{Key, KeyEvent, KeyModifiers};
use tuirealm::{Sub, SubClause, SubEventClause};

-
pub fn navigation<Id, UserEvent>() -> Vec<Sub<Id, UserEvent>>
+
pub fn navigation_clause<Id, UserEvent>() -> SubEventClause<UserEvent>
where
    Id: Clone + Hash + Eq + PartialEq,
    UserEvent: Clone + Eq + PartialEq + PartialOrd,
{
-
    vec![Sub::new(
-
        SubEventClause::Keyboard(KeyEvent {
-
            code: Key::Tab,
-
            modifiers: KeyModifiers::NONE,
-
        }),
-
        SubClause::Always,
-
    )]
+
    SubEventClause::Keyboard(KeyEvent {
+
        code: Key::Tab,
+
        modifiers: KeyModifiers::NONE,
+
    })
}

pub fn global<Id, UserEvent>() -> Vec<Sub<Id, UserEvent>>