Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Adapt patch page to new structure
Erik Kundt committed 2 years ago
commit 5e9b0699606a3a20279a29cd6d56b0182ee51ac1
parent 1899411c0a650a5fc94efe01caf5d9b142657209
5 files changed +149 -144
modified src/app.rs
@@ -36,6 +36,8 @@ pub enum PatchCid {
    Header,
    Activity,
    Files,
+
    Context,
+
    Shortcuts,
}

#[derive(Debug, Eq, PartialEq, Clone, Hash)]
@@ -134,7 +136,7 @@ impl App {
        let repo = self.context.repository();

        if let Some(patch) = cob::patch::find(repo, &id)? {
-
            let view = Box::new(PatchView::new((id, patch)));
+
            let view = Box::new(PatchView::new(theme.clone(), (id, patch)));
            self.pages.push(view, app, &self.context, theme)?;

            Ok(())
modified src/app/page.rs
@@ -373,16 +373,64 @@ impl ViewPage for IssuePage {
/// Patch detail page
///
pub struct PatchView {
-
    active_component: Cid,
+
    active_component: PatchCid,
    patch: (PatchId, Patch),
+
    shortcuts: HashMap<PatchCid, Widget<Shortcuts>>,
}

impl PatchView {
-
    pub fn new(patch: (PatchId, Patch)) -> Self {
+
    pub fn new(theme: Theme, patch: (PatchId, Patch)) -> Self {
+
        let shortcuts = Self::build_shortcuts(&theme);
        PatchView {
-
            active_component: Cid::Patch(PatchCid::Activity),
+
            active_component: PatchCid::Activity,
            patch,
+
            shortcuts,
+
        }
+
    }
+

+
    fn build_shortcuts(theme: &Theme) -> HashMap<PatchCid, Widget<Shortcuts>> {
+
        [
+
            (
+
                PatchCid::Activity,
+
                widget::common::shortcuts(
+
                    theme,
+
                    vec![
+
                        widget::common::shortcut(theme, "esc", "back"),
+
                        widget::common::shortcut(theme, "tab", "section"),
+
                        widget::common::shortcut(theme, "q", "quit"),
+
                    ],
+
                ),
+
            ),
+
            (
+
                PatchCid::Files,
+
                widget::common::shortcuts(
+
                    theme,
+
                    vec![
+
                        widget::common::shortcut(theme, "esc", "back"),
+
                        widget::common::shortcut(theme, "tab", "section"),
+
                        widget::common::shortcut(theme, "q", "quit"),
+
                    ],
+
                ),
+
            ),
+
        ]
+
        .iter()
+
        .cloned()
+
        .collect()
+
    }
+

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

@@ -396,15 +444,18 @@ impl ViewPage for PatchView {
        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, (*id, patch), context.profile()).to_boxed();
-
        let files = widget::patch::files(theme, (*id, patch), context.profile()).to_boxed();
+
        let activity = widget::patch::activity(theme).to_boxed();
+
        let files = widget::patch::files(theme).to_boxed();
+
        let context = widget::patch::context(context, theme, self.patch.clone()).to_boxed();

        app.remount(Cid::Patch(PatchCid::Header), header, vec![])?;
        app.remount(Cid::Patch(PatchCid::Activity), activity, vec![])?;
        app.remount(Cid::Patch(PatchCid::Files), files, vec![])?;
+
        app.remount(Cid::Patch(PatchCid::Context), context, vec![])?;

-
        app.active(&self.active_component)?;
+
        let active_component = Cid::Patch(self.active_component.clone());
+
        app.active(&active_component)?;
+
        self.update_shortcuts(app, self.active_component.clone())?;

        Ok(())
    }
@@ -413,6 +464,8 @@ impl ViewPage for PatchView {
        app.umount(&Cid::Patch(PatchCid::Header))?;
        app.umount(&Cid::Patch(PatchCid::Activity))?;
        app.umount(&Cid::Patch(PatchCid::Files))?;
+
        app.umount(&Cid::Patch(PatchCid::Context))?;
+
        app.umount(&Cid::Patch(PatchCid::Shortcuts))?;
        Ok(())
    }

@@ -424,9 +477,12 @@ impl ViewPage for PatchView {
        message: Message,
    ) -> Result<Option<Message>> {
        if let Message::NavigationChanged(index) = message {
-
            self.active_component = Cid::Patch(PatchCid::from(index as usize));
+
            self.active_component = PatchCid::from(index as usize);
+

+
            let active_component = Cid::Patch(self.active_component.clone());
+
            app.active(&active_component)?;
+
            self.update_shortcuts(app, self.active_component.clone())?;
        }
-
        app.active(&self.active_component)?;

        Ok(None)
    }
@@ -437,7 +493,13 @@ impl ViewPage for PatchView {
        let layout = layout::default_page(area, shortcuts_h);

        app.view(&Cid::Patch(PatchCid::Header), frame, layout.navigation);
-
        app.view(&self.active_component, frame, layout.component);
+
        app.view(
+
            &Cid::Patch(self.active_component.clone()),
+
            frame,
+
            layout.component,
+
        );
+
        app.view(&Cid::Patch(PatchCid::Context), frame, layout.context);
+
        app.view(&Cid::Patch(PatchCid::Shortcuts), frame, layout.shortcuts);
    }

    fn subscribe(&self, app: &mut Application<Cid, Message, NoUserEvent>) -> Result<()> {
modified src/ui/theme.rs
@@ -31,11 +31,10 @@ pub struct Colors {
    pub browser_patch_list_added: Color,
    pub browser_patch_list_removed: Color,
    pub context_bg: Color,
-
    pub context_light_bg: Color,
+
    pub context_light: Color,
+
    pub context_dark: Color,
    pub context_badge_bg: Color,
-
    pub context_id_fg: Color,
-
    pub context_id_bg: Color,
-
    pub context_id_author_fg: Color,
+
    pub context_color_fg: Color,
    pub container_border_fg: Color,
    pub container_border_focus_fg: Color,
}
@@ -102,11 +101,10 @@ pub fn default_dark() -> Theme {
            browser_patch_list_added: Color::Green,
            browser_patch_list_removed: Color::Red,
            context_bg: COLOR_DEFAULT_DARKEST,
-
            context_light_bg: Color::Gray,
+
            context_light: Color::Gray,
+
            context_dark: COLOR_DEFAULT_DARK,
            context_badge_bg: Color::LightRed,
-
            context_id_fg: Color::Cyan,
-
            context_id_bg: COLOR_DEFAULT_DARKEST,
-
            context_id_author_fg: Color::Gray,
+
            context_color_fg: Color::Cyan,
            container_border_fg: COLOR_DEFAULT_DARKEST,
            container_border_focus_fg: COLOR_DEFAULT_DARK,
        },
modified src/ui/widget/common/context.rs
@@ -6,6 +6,7 @@ use tuirealm::{Frame, MockComponent, State};
use super::label::Label;

use crate::ui::layout;
+
use crate::ui::theme::Theme;
use crate::ui::widget::{Widget, WidgetComponent};

/// A shortcut that consists of a label displaying the "hotkey", a label that displays
@@ -106,27 +107,27 @@ impl WidgetComponent for Shortcuts {
}

pub struct ContextBar {
-
    context: Widget<Label>,
-
    id: Widget<Label>,
-
    author: Widget<Label>,
-
    title: Widget<Label>,
-
    comments: Widget<Label>,
+
    label_0: Widget<Label>,
+
    label_1: Widget<Label>,
+
    label_2: Widget<Label>,
+
    label_3: Widget<Label>,
+
    label_4: Widget<Label>,
}

impl ContextBar {
    pub fn new(
-
        context: Widget<Label>,
-
        id: Widget<Label>,
-
        author: Widget<Label>,
-
        title: Widget<Label>,
-
        comments: Widget<Label>,
+
        label_0: Widget<Label>,
+
        label_1: Widget<Label>,
+
        label_2: Widget<Label>,
+
        label_3: Widget<Label>,
+
        label_4: Widget<Label>,
    ) -> Self {
        Self {
-
            context,
-
            id,
-
            author,
-
            title,
-
            comments,
+
            label_0,
+
            label_1,
+
            label_2,
+
            label_3,
+
            label_4,
        }
    }
}
@@ -137,25 +138,25 @@ impl WidgetComponent for ContextBar {
            .get_or(Attribute::Display, AttrValue::Flag(true))
            .unwrap_flag();

-
        let context_w = self.context.query(Attribute::Width).unwrap().unwrap_size();
-
        let id_w = self.id.query(Attribute::Width).unwrap().unwrap_size();
-
        let author_w = self.author.query(Attribute::Width).unwrap().unwrap_size();
-
        let count_w = self.comments.query(Attribute::Width).unwrap().unwrap_size();
+
        let label_0_w = self.label_0.query(Attribute::Width).unwrap().unwrap_size();
+
        let label_1_w = self.label_1.query(Attribute::Width).unwrap().unwrap_size();
+
        let label_2_w = self.label_2.query(Attribute::Width).unwrap().unwrap_size();
+
        let label_4_w = self.label_4.query(Attribute::Width).unwrap().unwrap_size();

        if display {
            let layout = layout::h_stack(
                vec![
-
                    self.context.clone().to_boxed(),
-
                    self.id.clone().to_boxed(),
-
                    self.title
+
                    self.label_0.clone().to_boxed(),
+
                    self.label_1.clone().to_boxed(),
+
                    self.label_3
                        .clone()
                        .width(
                            area.width
-
                                .saturating_sub(context_w + id_w + author_w + count_w),
+
                                .saturating_sub(label_0_w + label_1_w + label_2_w + label_4_w),
                        )
                        .to_boxed(),
-
                    self.author.clone().to_boxed(),
-
                    self.comments.clone().to_boxed(),
+
                    self.label_2.clone().to_boxed(),
+
                    self.label_4.clone().to_boxed(),
                ],
                area,
            );
@@ -174,3 +175,30 @@ impl WidgetComponent for ContextBar {
        CmdResult::None
    }
}
+

+
pub fn bar(
+
    theme: &Theme,
+
    label_0: &str,
+
    label_1: &str,
+
    label_2: &str,
+
    label_3: &str,
+
    label_4: &str,
+
) -> Widget<ContextBar> {
+
    let context = super::label(&format!(" {label_0} ")).background(theme.colors.context_badge_bg);
+
    let id = super::label(&format!(" {label_1} "))
+
        .foreground(theme.colors.context_color_fg)
+
        .background(theme.colors.context_bg);
+
    let title = super::label(&format!(" {label_2} "))
+
        .foreground(theme.colors.default_fg)
+
        .background(theme.colors.context_bg);
+
    let author = super::label(&format!(" {label_3} "))
+
        .foreground(theme.colors.context_light)
+
        .background(theme.colors.context_bg);
+
    let comments = super::label(&format!(" {label_4} "))
+
        .foreground(theme.colors.context_dark)
+
        .background(theme.colors.context_light);
+

+
    let context_bar = ContextBar::new(context, id, author, title, comments);
+

+
    Widget::new(context_bar).height(1)
+
}
modified src/ui/widget/patch.rs
@@ -1,10 +1,8 @@
use radicle::cob::patch::{Patch, PatchId};
-
use radicle::Profile;

use radicle_cli::terminal::format;

use tuirealm::command::{Cmd, CmdResult};
-
use tuirealm::props::Color;
use tuirealm::tui::layout::Rect;
use tuirealm::{AttrValue, Attribute, Frame, MockComponent, Props, State};

@@ -12,29 +10,20 @@ use super::{Widget, WidgetComponent};

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

+
use crate::ui::context::Context;
use crate::ui::theme::Theme;
use crate::ui::{cob, layout};

pub struct Activity {
    label: Widget<Label>,
-
    context: Widget<ContextBar>,
-
    shortcuts: Widget<Shortcuts>,
}

impl Activity {
-
    pub fn new(
-
        label: Widget<Label>,
-
        context: Widget<ContextBar>,
-
        shortcuts: Widget<Shortcuts>,
-
    ) -> Self {
-
        Self {
-
            label,
-
            context,
-
            shortcuts,
-
        }
+
    pub fn new(label: Widget<Label>) -> Self {
+
        Self { label }
    }
}

@@ -45,22 +34,9 @@ impl WidgetComponent for Activity {
            .query(Attribute::Width)
            .unwrap_or(AttrValue::Size(1))
            .unwrap_size();
-
        let context_h = self
-
            .context
-
            .query(Attribute::Height)
-
            .unwrap_or(AttrValue::Size(0))
-
            .unwrap_size();
-
        let shortcuts_h = self
-
            .shortcuts
-
            .query(Attribute::Height)
-
            .unwrap_or(AttrValue::Size(0))
-
            .unwrap_size();
-
        let layout = layout::root_component_with_context(area, context_h, shortcuts_h);

        self.label
-
            .view(frame, layout::centered_label(label_w, layout[0]));
-
        self.context.view(frame, layout[1]);
-
        self.shortcuts.view(frame, layout[2]);
+
            .view(frame, layout::centered_label(label_w, area));
    }

    fn state(&self) -> State {
@@ -74,21 +50,11 @@ impl WidgetComponent for Activity {

pub struct Files {
    label: Widget<Label>,
-
    context: Widget<ContextBar>,
-
    shortcuts: Widget<Shortcuts>,
}

impl Files {
-
    pub fn new(
-
        label: Widget<Label>,
-
        context: Widget<ContextBar>,
-
        shortcuts: Widget<Shortcuts>,
-
    ) -> Self {
-
        Self {
-
            label,
-
            context,
-
            shortcuts,
-
        }
+
    pub fn new(label: Widget<Label>) -> Self {
+
        Self { label }
    }
}

@@ -99,22 +65,9 @@ impl WidgetComponent for Files {
            .query(Attribute::Width)
            .unwrap_or(AttrValue::Size(1))
            .unwrap_size();
-
        let context_h = self
-
            .context
-
            .query(Attribute::Height)
-
            .unwrap_or(AttrValue::Size(0))
-
            .unwrap_size();
-
        let shortcuts_h = self
-
            .shortcuts
-
            .query(Attribute::Height)
-
            .unwrap_or(AttrValue::Size(0))
-
            .unwrap_size();
-
        let layout = layout::root_component_with_context(area, context_h, shortcuts_h);

        self.label
-
            .view(frame, layout::centered_label(label_w, layout[0]));
-
        self.context.view(frame, layout[1]);
-
        self.shortcuts.view(frame, layout[2]);
+
            .view(frame, layout::centered_label(label_w, area));
    }

    fn state(&self) -> State {
@@ -136,67 +89,29 @@ pub fn navigation(theme: &Theme) -> Widget<Tabs> {
    )
}

-
pub fn activity(theme: &Theme, patch: (PatchId, &Patch), profile: &Profile) -> Widget<Activity> {
-
    let (id, patch) = patch;
-
    let shortcuts = common::shortcuts(
-
        theme,
-
        vec![
-
            common::shortcut(theme, "esc", "back"),
-
            common::shortcut(theme, "tab", "section"),
-
            common::shortcut(theme, "q", "quit"),
-
        ],
-
    );
-
    let context = context(theme, (id, patch), profile);
-

+
pub fn activity(theme: &Theme) -> Widget<Activity> {
    let not_implemented = common::label("not implemented").foreground(theme.colors.default_fg);
-
    let activity = Activity::new(not_implemented, context, shortcuts);
+
    let activity = Activity::new(not_implemented);

    Widget::new(activity)
}

-
pub fn files(theme: &Theme, patch: (PatchId, &Patch), profile: &Profile) -> Widget<Activity> {
-
    let (id, patch) = patch;
-
    let shortcuts = common::shortcuts(
-
        theme,
-
        vec![
-
            common::shortcut(theme, "esc", "back"),
-
            common::shortcut(theme, "tab", "section"),
-
            common::shortcut(theme, "q", "quit"),
-
        ],
-
    );
-
    let context = context(theme, (id, patch), profile);
-

+
pub fn files(theme: &Theme) -> Widget<Files> {
    let not_implemented = common::label("not implemented").foreground(theme.colors.default_fg);
-
    let files = Activity::new(not_implemented, context, shortcuts);
+
    let files = Files::new(not_implemented);

    Widget::new(files)
}

-
pub fn context(theme: &Theme, patch: (PatchId, &Patch), profile: &Profile) -> Widget<ContextBar> {
+
pub fn context(context: &Context, theme: &Theme, patch: (PatchId, Patch)) -> Widget<ContextBar> {
    let (id, patch) = patch;
    let (_, rev) = patch.latest();
-
    let is_you = *patch.author().id() == profile.did();
+
    let is_you = *patch.author().id() == context.profile().did();

    let id = format::cob(&id);
    let title = patch.title();
    let author = cob::format_author(patch.author().id(), is_you);
    let comments = rev.discussion().len();

-
    let context = common::label(" patch ").background(theme.colors.context_badge_bg);
-
    let id = common::label(&format!(" {id} "))
-
        .foreground(theme.colors.context_id_fg)
-
        .background(theme.colors.context_id_bg);
-
    let title = common::label(&format!(" {title} "))
-
        .foreground(theme.colors.default_fg)
-
        .background(theme.colors.context_bg);
-
    let author = common::label(&format!(" {author} "))
-
        .foreground(theme.colors.context_id_author_fg)
-
        .background(theme.colors.context_bg);
-
    let comments = common::label(&format!(" {comments} "))
-
        .foreground(Color::Rgb(70, 70, 70))
-
        .background(theme.colors.context_light_bg);
-

-
    let context_bar = ContextBar::new(context, id, author, title, comments);
-

-
    Widget::new(context_bar).height(1)
+
    common::context::bar(theme, "Patch", &id, title, &author, &comments.to_string())
}