Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Implement issue browser context on home page
Erik Kundt committed 2 years ago
commit 46f9acd75ef4eacb87ecd177ff7b486538f6bd88
parent 2bf3e69d77a605eb9443c8aa51d6d9c332624cdd
8 files changed +87 -20
modified src/app/page.rs
@@ -6,8 +6,8 @@ use radicle::cob::issue::{Issue, IssueId};
use radicle::cob::patch::{Patch, PatchId};

use radicle_tui::cob;
-
use radicle_tui::ui::widget::common::context::Shortcuts;
-
use tuirealm::{Frame, NoUserEvent, Sub, SubClause};
+
use radicle_tui::ui::widget::common::context::{Progress, Shortcuts};
+
use tuirealm::{Frame, NoUserEvent, StateValue, Sub, SubClause};

use radicle_tui::ui::context::Context;
use radicle_tui::ui::layout;
@@ -119,16 +119,33 @@ impl HomeView {
    fn update_context(
        &self,
        app: &mut Application<Cid, Message, NoUserEvent>,
+
        context: &Context,
        theme: &Theme,
        cid: HomeCid,
    ) -> Result<()> {
+
        use tuirealm::State;
+

        let context = match cid {
            HomeCid::IssueBrowser => {
-
                let context = widget::issue::browse_context(theme);
+
                let state = app.state(&Cid::Home(HomeCid::IssueBrowser))?;
+
                let progress = match state {
+
                    State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
+
                        Progress::Step(step, total)
+
                    }
+
                    _ => Progress::None,
+
                };
+
                let context = widget::issue::browse_context(context, theme, progress);
                Some(context)
            }
            HomeCid::PatchBrowser => {
-
                let context = widget::patch::browse_context(theme);
+
                let state = app.state(&Cid::Home(HomeCid::PatchBrowser))?;
+
                let progress = match state {
+
                    State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
+
                        Progress::Step(step, total)
+
                    }
+
                    _ => Progress::None,
+
                };
+
                let context = widget::patch::browse_context(context, theme, progress);
                Some(context)
            }
            _ => None,
@@ -180,7 +197,7 @@ impl ViewPage for HomeView {
        let active_component = Cid::Home(self.active_component.clone());
        app.active(&active_component)?;
        self.update_shortcuts(app, self.active_component.clone())?;
-
        self.update_context(app, theme, self.active_component.clone())?;
+
        self.update_context(app, context, theme, self.active_component.clone())?;

        Ok(())
    }
@@ -198,7 +215,7 @@ impl ViewPage for HomeView {
    fn update(
        &mut self,
        app: &mut Application<Cid, Message, NoUserEvent>,
-
        _context: &Context,
+
        context: &Context,
        theme: &Theme,
        message: Message,
    ) -> Result<Option<Message>> {
@@ -209,9 +226,10 @@ impl ViewPage for HomeView {
            app.active(&active_component)?;

            self.update_shortcuts(app, self.active_component.clone())?;
-
            self.update_context(app, theme, self.active_component.clone())?;
        }

+
        self.update_context(app, context, theme, self.active_component.clone())?;
+

        Ok(None)
    }

@@ -476,7 +494,6 @@ impl ViewPage for PatchView {
        context: &Context,
        theme: &Theme,
    ) -> Result<()> {
-
        let (id, patch) = &self.patch;
        let navigation = widget::patch::navigation(theme);
        let header = widget::common::app_header(context, theme, Some(navigation)).to_boxed();
        let activity = widget::patch::activity(theme).to_boxed();
modified src/ui/context.rs
@@ -1,3 +1,4 @@
+
use radicle::cob::issue::{Issue, IssueId};
use radicle::prelude::{Id, Project};
use radicle::Profile;

@@ -8,17 +9,20 @@ pub struct Context {
    id: Id,
    project: Project,
    repository: Repository,
+
    issues: Vec<(IssueId, Issue)>,
}

impl Context {
    pub fn new(profile: Profile, id: Id, project: Project) -> Self {
        let repository = profile.storage.repository(id).unwrap();
+
        let issues = crate::cob::issue::all(&repository).unwrap_or_default();

        Self {
            id,
            profile,
            project,
            repository,
+
            issues,
        }
    }

@@ -37,4 +41,8 @@ impl Context {
    pub fn repository(&self) -> &Repository {
        &self.repository
    }
+

+
    pub fn issues(&self) -> &Vec<(IssueId, Issue)> {
+
        &self.issues
+
    }
}
modified src/ui/layout.rs
@@ -206,9 +206,9 @@ pub fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
}

pub fn issue_page(area: Rect, shortcuts_h: u16) -> IssuePage {
-
    let content_h = area.height.saturating_sub(shortcuts_h);
    let header_h = 3u16;
-

+
    let content_h = area.height.saturating_sub(header_h).saturating_sub(shortcuts_h);
+
    
    let root = Layout::default()
        .direction(Direction::Vertical)
        .horizontal_margin(1)
modified src/ui/widget/common/context.rs
@@ -9,6 +9,22 @@ use crate::ui::layout;
use crate::ui::theme::Theme;
use crate::ui::widget::{Widget, WidgetComponent};

+
pub enum Progress {
+
    Percentage(usize),
+
    Step(usize, usize),
+
    None,
+
}
+

+
impl ToString for Progress {
+
    fn to_string(&self) -> std::string::String {
+
        match self {
+
            Progress::Percentage(value) => format!("{value} %"),
+
            Progress::Step(step, total) => format!("{step}/{total}"),
+
            _ => String::new(),
+
        }
+
    }
+
}
+

/// A shortcut that consists of a label displaying the "hotkey", a label that displays
/// the action and a spacer between them.
#[derive(Clone)]
modified src/ui/widget/common/list.rs
@@ -271,7 +271,9 @@ where
    }

    fn state(&self) -> State {
-
        State::None
+
        let selected = self.state.selected().unwrap_or_default();
+
        let len = self.items.len();
+
        State::Tup2((StateValue::Usize(selected), StateValue::Usize(len)))
    }

    fn perform(&mut self, _properties: &Props, cmd: Cmd) -> CmdResult {
modified src/ui/widget/home.rs
@@ -67,11 +67,9 @@ impl IssueBrowser {
        let repo = context.repository();
        let mut items = vec![];

-
        if let Ok(issues) = cob::issue::all(repo) {
-
            for (id, issue) in issues {
-
                if let Ok(item) = IssueItem::try_from((context.profile(), repo, id, issue)) {
-
                    items.push(item);
-
                }
+
        for (id, issue) in context.issues() {
+
            if let Ok(item) = IssueItem::try_from((context.profile(), repo, *id, issue.clone())) {
+
                items.push(item);
            }
        }

modified src/ui/widget/issue.rs
@@ -10,6 +10,7 @@ use tuirealm::tui::layout::Layout;
use super::common::container::Container;
use super::common::container::LabeledContainer;
use super::common::context::ContextBar;
+
use super::common::context::Progress;
use super::common::label::Textarea;
use super::common::list::List;
use super::common::list::Property;
@@ -273,6 +274,27 @@ pub fn details(
    Widget::new(discussion)
}

-
pub fn browse_context(theme: &Theme) -> Widget<ContextBar> {
-
    common::context::bar(theme, "Browse", "", "", "", "")
+
pub fn browse_context(context: &Context, theme: &Theme, progress: Progress) -> Widget<ContextBar> {
+
    use radicle::cob::issue::State;
+

+
    let issues = context.issues();
+
    let open = issues
+
        .iter()
+
        .filter(|issue| *issue.1.state() == State::Open)
+
        .collect::<Vec<_>>()
+
        .len();
+
    let closed = issues
+
        .iter()
+
        .filter(|issue| *issue.1.state() != State::Open)
+
        .collect::<Vec<_>>()
+
        .len();
+

+
    common::context::bar(
+
        theme,
+
        "Browse",
+
        "",
+
        "",
+
        &format!("{open} open | {closed} closed"),
+
        &progress.to_string(),
+
    )
}
modified src/ui/widget/patch.rs
@@ -10,7 +10,7 @@ use super::{Widget, WidgetComponent};

use super::common;
use super::common::container::Tabs;
-
use super::common::context::ContextBar;
+
use super::common::context::{ContextBar, Progress};
use super::common::label::Label;

use crate::ui::context::Context;
@@ -116,6 +116,10 @@ pub fn context(context: &Context, theme: &Theme, patch: (PatchId, Patch)) -> Wid
    common::context::bar(theme, "Patch", &id, title, &author, &comments.to_string())
}

-
pub fn browse_context(theme: &Theme) -> Widget<ContextBar> {
+
pub fn browse_context(
+
    _context: &Context,
+
    theme: &Theme,
+
    _progress: Progress,
+
) -> Widget<ContextBar> {
    common::context::bar(theme, "Browse", "", "", "", "")
}