Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
patch-select: Fix module names
Erik Kundt committed 2 years ago
commit dca98c1bebb657ca112b9ed32c020b6715b2d476
parent 19d7e3b0380ca1d545d36c377847b950a31e8fea
7 files changed +361 -361
deleted bin/commands/patch/list/event.rs
@@ -1,107 +0,0 @@
-
use tuirealm::command::{Cmd, CmdResult, Direction as MoveDirection};
-
use tuirealm::event::{Event, Key, KeyEvent};
-
use tuirealm::{MockComponent, NoUserEvent, State, StateValue};
-

-
use radicle_tui as tui;
-

-
use tui::ui::widget::container::{AppHeader, GlobalListener, LabeledContainer, Popup};
-
use tui::ui::widget::context::{ContextBar, Shortcuts};
-
use tui::ui::widget::list::PropertyList;
-

-
use tui::ui::widget::Widget;
-

-
use super::super::common;
-
use super::{Message, PopupMessage};
-

-
/// Since the framework does not know the type of messages that are being
-
/// passed around in the app, the following handlers need to be implemented for
-
/// each component used.
-
///
-
/// TODO: should handle `Event::WindowResize`, which is not emitted by `termion`.
-
impl tuirealm::Component<Message, NoUserEvent> for Widget<GlobalListener> {
-
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
-
        match event {
-
            Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => Some(Message::Quit(None)),
-
            _ => None,
-
        }
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<common::ui::PatchBrowser> {
-
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
-
        match event {
-
            Event::Keyboard(KeyEvent { code: Key::Up, .. })
-
            | Event::Keyboard(KeyEvent {
-
                code: Key::Char('k'),
-
                ..
-
            }) => {
-
                self.perform(Cmd::Move(MoveDirection::Up));
-
                Some(Message::Tick)
-
            }
-
            Event::Keyboard(KeyEvent {
-
                code: Key::Down, ..
-
            })
-
            | Event::Keyboard(KeyEvent {
-
                code: Key::Char('j'),
-
                ..
-
            }) => {
-
                self.perform(Cmd::Move(MoveDirection::Down));
-
                Some(Message::Tick)
-
            }
-
            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::Quit(Some(item.id().to_owned())))
-
                    }
-
                    _ => None,
-
                }
-
            }
-
            _ => None,
-
        }
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<Popup> {
-
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
-
        match event {
-
            Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => {
-
                Some(Message::Popup(PopupMessage::Hide))
-
            }
-
            _ => None,
-
        }
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<AppHeader> {
-
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
-
        None
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<LabeledContainer> {
-
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
-
        None
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<PropertyList> {
-
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
-
        None
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<ContextBar> {
-
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
-
        None
-
    }
-
}
-

-
impl tuirealm::Component<Message, NoUserEvent> for Widget<Shortcuts> {
-
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
-
        None
-
    }
-
}
deleted bin/commands/patch/list/page.rs
@@ -1,160 +0,0 @@
-
use std::collections::HashMap;
-

-
use anyhow::Result;
-

-
use tuirealm::{Frame, NoUserEvent, State, StateValue, Sub, SubClause};
-

-
use radicle_tui as tui;
-

-
use tui::context::Context;
-
use tui::ui::theme::Theme;
-
use tui::ui::widget::context::{Progress, Shortcuts};
-
use tui::ui::widget::Widget;
-
use tui::ui::{layout, subscription};
-
use tui::ViewPage;
-

-
use super::{ui, Application, Cid, ListCid, Message};
-

-
///
-
/// Home
-
///
-
pub struct ListView {
-
    active_component: ListCid,
-
    shortcuts: HashMap<ListCid, Widget<Shortcuts>>,
-
}
-

-
impl ListView {
-
    pub fn new(theme: Theme) -> Self {
-
        let shortcuts = Self::build_shortcuts(&theme);
-
        Self {
-
            active_component: ListCid::PatchBrowser,
-
            shortcuts,
-
        }
-
    }
-

-
    fn build_shortcuts(theme: &Theme) -> HashMap<ListCid, Widget<Shortcuts>> {
-
        [(
-
            ListCid::PatchBrowser,
-
            tui::ui::shortcuts(
-
                theme,
-
                vec![
-
                    tui::ui::shortcut(theme, "tab", "section"),
-
                    tui::ui::shortcut(theme, "↑/↓", "navigate"),
-
                    tui::ui::shortcut(theme, "enter", "show"),
-
                    tui::ui::shortcut(theme, "q", "quit"),
-
                ],
-
            ),
-
        )]
-
        .iter()
-
        .cloned()
-
        .collect()
-
    }
-

-
    fn update_context(
-
        &self,
-
        app: &mut Application<Cid, Message, NoUserEvent>,
-
        context: &Context,
-
        theme: &Theme,
-
    ) -> Result<()> {
-
        let state = app.state(&Cid::List(ListCid::PatchBrowser))?;
-
        let progress = match state {
-
            State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
-
                Progress::Step(step.saturating_add(1), total)
-
            }
-
            _ => Progress::None,
-
        };
-
        let context = ui::browse_context(context, theme, progress);
-

-
        app.remount(Cid::List(ListCid::Context), context.to_boxed(), vec![])?;
-

-
        Ok(())
-
    }
-

-
    fn update_shortcuts(
-
        &self,
-
        app: &mut Application<Cid, Message, NoUserEvent>,
-
        cid: ListCid,
-
    ) -> Result<()> {
-
        if let Some(shortcuts) = self.shortcuts.get(&cid) {
-
            app.remount(
-
                Cid::List(ListCid::Shortcuts),
-
                shortcuts.clone().to_boxed(),
-
                vec![],
-
            )?;
-
        }
-
        Ok(())
-
    }
-
}
-

-
impl ViewPage<Cid, Message> for ListView {
-
    fn mount(
-
        &self,
-
        app: &mut Application<Cid, Message, NoUserEvent>,
-
        context: &Context,
-
        theme: &Theme,
-
    ) -> Result<()> {
-
        let navigation = ui::list_navigation(theme);
-
        let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
-
        let patch_browser = ui::patches(context, theme, None).to_boxed();
-

-
        app.remount(Cid::List(ListCid::Header), header, vec![])?;
-
        app.remount(Cid::List(ListCid::PatchBrowser), patch_browser, vec![])?;
-

-
        app.active(&Cid::List(self.active_component.clone()))?;
-
        self.update_shortcuts(app, self.active_component.clone())?;
-
        self.update_context(app, context, theme)?;
-

-
        Ok(())
-
    }
-

-
    fn unmount(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
-
        app.umount(&Cid::List(ListCid::Header))?;
-
        app.umount(&Cid::List(ListCid::PatchBrowser))?;
-
        app.umount(&Cid::List(ListCid::Context))?;
-
        app.umount(&Cid::List(ListCid::Shortcuts))?;
-
        Ok(())
-
    }
-

-
    fn update(
-
        &mut self,
-
        app: &mut Application<Cid, Message, NoUserEvent>,
-
        context: &Context,
-
        theme: &Theme,
-
        _message: Message,
-
    ) -> Result<Option<Message>> {
-
        self.update_context(app, context, theme)?;
-

-
        Ok(None)
-
    }
-

-
    fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame) {
-
        let area = frame.size();
-
        let layout = layout::default_page(area);
-

-
        app.view(
-
            &Cid::List(self.active_component.clone()),
-
            frame,
-
            layout.component,
-
        );
-

-
        app.view(&Cid::List(ListCid::Context), frame, layout.context);
-
    }
-

-
    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
-
        app.subscribe(
-
            &Cid::List(ListCid::Header),
-
            Sub::new(subscription::navigation_clause(), SubClause::Always),
-
        )?;
-

-
        Ok(())
-
    }
-

-
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
-
        app.unsubscribe(
-
            &Cid::List(ListCid::Header),
-
            subscription::navigation_clause(),
-
        )?;
-

-
        Ok(())
-
    }
-
}
deleted bin/commands/patch/list/ui.rs
@@ -1,91 +0,0 @@
-
use radicle::cob::patch::{Patch, PatchId};
-

-
use radicle_tui as tui;
-

-
use tui::context::Context;
-
use tui::ui::theme::{style, Theme};
-
use tui::ui::widget::Widget;
-

-
use tui::ui::widget::container::Tabs;
-
use tui::ui::widget::context::{ContextBar, Progress};
-
use tui::ui::widget::label::{self};
-

-
use super::super::common;
-

-
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
-
    tui::ui::tabs(
-
        theme,
-
        vec![label::reversable("Patches").style(style::cyan())],
-
    )
-
}
-

-
pub fn patches(
-
    context: &Context,
-
    theme: &Theme,
-
    selected: Option<(PatchId, Patch)>,
-
) -> Widget<common::ui::PatchBrowser> {
-
    Widget::new(common::ui::PatchBrowser::new(context, theme, selected))
-
}
-

-
pub fn browse_context(context: &Context, _theme: &Theme, progress: Progress) -> Widget<ContextBar> {
-
    use radicle::cob::patch::State;
-

-
    let mut draft = 0;
-
    let mut open = 0;
-
    let mut archived = 0;
-
    let mut merged = 0;
-

-
    let patches = context.patches().as_ref().unwrap();
-
    for (_, patch) in patches {
-
        match patch.state() {
-
            State::Draft => draft += 1,
-
            State::Open { conflicts: _ } => open += 1,
-
            State::Archived => archived += 1,
-
            State::Merged {
-
                commit: _,
-
                revision: _,
-
            } => merged += 1,
-
        }
-
    }
-

-
    let context = label::badge(" Patches ");
-
    let divider = label::default_reversed(" | ");
-

-
    let draft_n = label::default_reversed(&format!("{draft}"));
-
    let draft = label::default_reversed(" Draft");
-

-
    let open_n = label::default(&format!("{open}")).style(style::green_default_reversed());
-
    let open = label::default_reversed(" Open");
-

-
    let archived_n = label::default(&format!("{archived}")).style(style::yellow_default_reversed());
-
    let archived = label::default_reversed(" Archived");
-

-
    let merged_n = label::default(&format!("{merged}")).style(style::cyan_default_reversed());
-
    let merged = label::default_reversed(" Merged ");
-

-
    let progress =
-
        label::default(&format!(" {} ", progress.to_string())).style(style::magenta_reversed());
-
    let spacer = label::default_reversed("");
-

-
    let context_bar = ContextBar::new(
-
        label::group(&[context]),
-
        label::group(&[spacer.clone()]),
-
        label::group(&[spacer]),
-
        label::group(&[
-
            draft_n,
-
            draft,
-
            divider.clone(),
-
            open_n,
-
            open,
-
            divider.clone(),
-
            archived_n,
-
            archived,
-
            divider,
-
            merged_n,
-
            merged,
-
        ]),
-
        label::group(&[progress]),
-
    );
-

-
    Widget::new(context_bar).height(1)
-
}
modified bin/commands/patch/select.rs
@@ -1,8 +1,8 @@
-
#[path = "list/event.rs"]
+
#[path = "select/event.rs"]
mod event;
-
#[path = "list/page.rs"]
+
#[path = "select/page.rs"]
mod page;
-
#[path = "list/ui.rs"]
+
#[path = "select/ui.rs"]
mod ui;

use std::hash::Hash;
added bin/commands/patch/select/event.rs
@@ -0,0 +1,107 @@
+
use tuirealm::command::{Cmd, CmdResult, Direction as MoveDirection};
+
use tuirealm::event::{Event, Key, KeyEvent};
+
use tuirealm::{MockComponent, NoUserEvent, State, StateValue};
+

+
use radicle_tui as tui;
+

+
use tui::ui::widget::container::{AppHeader, GlobalListener, LabeledContainer, Popup};
+
use tui::ui::widget::context::{ContextBar, Shortcuts};
+
use tui::ui::widget::list::PropertyList;
+

+
use tui::ui::widget::Widget;
+

+
use super::super::common;
+
use super::{Message, PopupMessage};
+

+
/// Since the framework does not know the type of messages that are being
+
/// passed around in the app, the following handlers need to be implemented for
+
/// each component used.
+
///
+
/// TODO: should handle `Event::WindowResize`, which is not emitted by `termion`.
+
impl tuirealm::Component<Message, NoUserEvent> for Widget<GlobalListener> {
+
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
+
        match event {
+
            Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => Some(Message::Quit(None)),
+
            _ => None,
+
        }
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<common::ui::PatchBrowser> {
+
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
+
        match event {
+
            Event::Keyboard(KeyEvent { code: Key::Up, .. })
+
            | Event::Keyboard(KeyEvent {
+
                code: Key::Char('k'),
+
                ..
+
            }) => {
+
                self.perform(Cmd::Move(MoveDirection::Up));
+
                Some(Message::Tick)
+
            }
+
            Event::Keyboard(KeyEvent {
+
                code: Key::Down, ..
+
            })
+
            | Event::Keyboard(KeyEvent {
+
                code: Key::Char('j'),
+
                ..
+
            }) => {
+
                self.perform(Cmd::Move(MoveDirection::Down));
+
                Some(Message::Tick)
+
            }
+
            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::Quit(Some(item.id().to_owned())))
+
                    }
+
                    _ => None,
+
                }
+
            }
+
            _ => None,
+
        }
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<Popup> {
+
    fn on(&mut self, event: Event<NoUserEvent>) -> Option<Message> {
+
        match event {
+
            Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => {
+
                Some(Message::Popup(PopupMessage::Hide))
+
            }
+
            _ => None,
+
        }
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<AppHeader> {
+
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
+
        None
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<LabeledContainer> {
+
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
+
        None
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<PropertyList> {
+
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
+
        None
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<ContextBar> {
+
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
+
        None
+
    }
+
}
+

+
impl tuirealm::Component<Message, NoUserEvent> for Widget<Shortcuts> {
+
    fn on(&mut self, _event: Event<NoUserEvent>) -> Option<Message> {
+
        None
+
    }
+
}
added bin/commands/patch/select/page.rs
@@ -0,0 +1,160 @@
+
use std::collections::HashMap;
+

+
use anyhow::Result;
+

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

+
use radicle_tui as tui;
+

+
use tui::context::Context;
+
use tui::ui::theme::Theme;
+
use tui::ui::widget::context::{Progress, Shortcuts};
+
use tui::ui::widget::Widget;
+
use tui::ui::{layout, subscription};
+
use tui::ViewPage;
+

+
use super::{ui, Application, Cid, ListCid, Message};
+

+
///
+
/// Home
+
///
+
pub struct ListView {
+
    active_component: ListCid,
+
    shortcuts: HashMap<ListCid, Widget<Shortcuts>>,
+
}
+

+
impl ListView {
+
    pub fn new(theme: Theme) -> Self {
+
        let shortcuts = Self::build_shortcuts(&theme);
+
        Self {
+
            active_component: ListCid::PatchBrowser,
+
            shortcuts,
+
        }
+
    }
+

+
    fn build_shortcuts(theme: &Theme) -> HashMap<ListCid, Widget<Shortcuts>> {
+
        [(
+
            ListCid::PatchBrowser,
+
            tui::ui::shortcuts(
+
                theme,
+
                vec![
+
                    tui::ui::shortcut(theme, "tab", "section"),
+
                    tui::ui::shortcut(theme, "↑/↓", "navigate"),
+
                    tui::ui::shortcut(theme, "enter", "show"),
+
                    tui::ui::shortcut(theme, "q", "quit"),
+
                ],
+
            ),
+
        )]
+
        .iter()
+
        .cloned()
+
        .collect()
+
    }
+

+
    fn update_context(
+
        &self,
+
        app: &mut Application<Cid, Message, NoUserEvent>,
+
        context: &Context,
+
        theme: &Theme,
+
    ) -> Result<()> {
+
        let state = app.state(&Cid::List(ListCid::PatchBrowser))?;
+
        let progress = match state {
+
            State::Tup2((StateValue::Usize(step), StateValue::Usize(total))) => {
+
                Progress::Step(step.saturating_add(1), total)
+
            }
+
            _ => Progress::None,
+
        };
+
        let context = ui::browse_context(context, theme, progress);
+

+
        app.remount(Cid::List(ListCid::Context), context.to_boxed(), vec![])?;
+

+
        Ok(())
+
    }
+

+
    fn update_shortcuts(
+
        &self,
+
        app: &mut Application<Cid, Message, NoUserEvent>,
+
        cid: ListCid,
+
    ) -> Result<()> {
+
        if let Some(shortcuts) = self.shortcuts.get(&cid) {
+
            app.remount(
+
                Cid::List(ListCid::Shortcuts),
+
                shortcuts.clone().to_boxed(),
+
                vec![],
+
            )?;
+
        }
+
        Ok(())
+
    }
+
}
+

+
impl ViewPage<Cid, Message> for ListView {
+
    fn mount(
+
        &self,
+
        app: &mut Application<Cid, Message, NoUserEvent>,
+
        context: &Context,
+
        theme: &Theme,
+
    ) -> Result<()> {
+
        let navigation = ui::list_navigation(theme);
+
        let header = tui::ui::app_header(context, theme, Some(navigation)).to_boxed();
+
        let patch_browser = ui::patches(context, theme, None).to_boxed();
+

+
        app.remount(Cid::List(ListCid::Header), header, vec![])?;
+
        app.remount(Cid::List(ListCid::PatchBrowser), patch_browser, vec![])?;
+

+
        app.active(&Cid::List(self.active_component.clone()))?;
+
        self.update_shortcuts(app, self.active_component.clone())?;
+
        self.update_context(app, context, theme)?;
+

+
        Ok(())
+
    }
+

+
    fn unmount(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.umount(&Cid::List(ListCid::Header))?;
+
        app.umount(&Cid::List(ListCid::PatchBrowser))?;
+
        app.umount(&Cid::List(ListCid::Context))?;
+
        app.umount(&Cid::List(ListCid::Shortcuts))?;
+
        Ok(())
+
    }
+

+
    fn update(
+
        &mut self,
+
        app: &mut Application<Cid, Message, NoUserEvent>,
+
        context: &Context,
+
        theme: &Theme,
+
        _message: Message,
+
    ) -> Result<Option<Message>> {
+
        self.update_context(app, context, theme)?;
+

+
        Ok(None)
+
    }
+

+
    fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame) {
+
        let area = frame.size();
+
        let layout = layout::default_page(area);
+

+
        app.view(
+
            &Cid::List(self.active_component.clone()),
+
            frame,
+
            layout.component,
+
        );
+

+
        app.view(&Cid::List(ListCid::Context), frame, layout.context);
+
    }
+

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

+
        Ok(())
+
    }
+

+
    fn unsubscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
+
        app.unsubscribe(
+
            &Cid::List(ListCid::Header),
+
            subscription::navigation_clause(),
+
        )?;
+

+
        Ok(())
+
    }
+
}
added bin/commands/patch/select/ui.rs
@@ -0,0 +1,91 @@
+
use radicle::cob::patch::{Patch, PatchId};
+

+
use radicle_tui as tui;
+

+
use tui::context::Context;
+
use tui::ui::theme::{style, Theme};
+
use tui::ui::widget::Widget;
+

+
use tui::ui::widget::container::Tabs;
+
use tui::ui::widget::context::{ContextBar, Progress};
+
use tui::ui::widget::label::{self};
+

+
use super::super::common;
+

+
pub fn list_navigation(theme: &Theme) -> Widget<Tabs> {
+
    tui::ui::tabs(
+
        theme,
+
        vec![label::reversable("Patches").style(style::cyan())],
+
    )
+
}
+

+
pub fn patches(
+
    context: &Context,
+
    theme: &Theme,
+
    selected: Option<(PatchId, Patch)>,
+
) -> Widget<common::ui::PatchBrowser> {
+
    Widget::new(common::ui::PatchBrowser::new(context, theme, selected))
+
}
+

+
pub fn browse_context(context: &Context, _theme: &Theme, progress: Progress) -> Widget<ContextBar> {
+
    use radicle::cob::patch::State;
+

+
    let mut draft = 0;
+
    let mut open = 0;
+
    let mut archived = 0;
+
    let mut merged = 0;
+

+
    let patches = context.patches().as_ref().unwrap();
+
    for (_, patch) in patches {
+
        match patch.state() {
+
            State::Draft => draft += 1,
+
            State::Open { conflicts: _ } => open += 1,
+
            State::Archived => archived += 1,
+
            State::Merged {
+
                commit: _,
+
                revision: _,
+
            } => merged += 1,
+
        }
+
    }
+

+
    let context = label::badge(" Patches ");
+
    let divider = label::default_reversed(" | ");
+

+
    let draft_n = label::default_reversed(&format!("{draft}"));
+
    let draft = label::default_reversed(" Draft");
+

+
    let open_n = label::default(&format!("{open}")).style(style::green_default_reversed());
+
    let open = label::default_reversed(" Open");
+

+
    let archived_n = label::default(&format!("{archived}")).style(style::yellow_default_reversed());
+
    let archived = label::default_reversed(" Archived");
+

+
    let merged_n = label::default(&format!("{merged}")).style(style::cyan_default_reversed());
+
    let merged = label::default_reversed(" Merged ");
+

+
    let progress =
+
        label::default(&format!(" {} ", progress.to_string())).style(style::magenta_reversed());
+
    let spacer = label::default_reversed("");
+

+
    let context_bar = ContextBar::new(
+
        label::group(&[context]),
+
        label::group(&[spacer.clone()]),
+
        label::group(&[spacer]),
+
        label::group(&[
+
            draft_n,
+
            draft,
+
            divider.clone(),
+
            open_n,
+
            open,
+
            divider.clone(),
+
            archived_n,
+
            archived,
+
            divider,
+
            merged_n,
+
            merged,
+
        ]),
+
        label::group(&[progress]),
+
    );
+

+
    Widget::new(context_bar).height(1)
+
}