Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
bin: Fix table and help progress
Erik Kundt committed 2 years ago
commit ef6e800b89282cfde5218a96c43c46008b8b2079
parent ac4be947390fb6039d047220266728345f5838f7
9 files changed +132 -88
modified bin/commands/inbox/select.rs
@@ -46,7 +46,6 @@ pub struct App {
pub struct UIState {
    page_size: usize,
    show_search: bool,
-
    show_help: bool,
}

impl Default for UIState {
@@ -54,7 +53,6 @@ impl Default for UIState {
        Self {
            page_size: 1,
            show_search: false,
-
            show_help: false,
        }
    }
}
@@ -66,8 +64,15 @@ pub struct NotificationsState {
}

#[derive(Clone, Debug)]
+
pub struct HelpState {
+
    show: bool,
+
    progress: usize,
+
}
+

+
#[derive(Clone, Debug)]
pub struct State {
    notifications: NotificationsState,
+
    help: HelpState,
    mode: Mode,
    project: Project,
    filter: NotificationItemFilter,
@@ -79,7 +84,7 @@ impl State {
    pub fn shortcuts(&self) -> Vec<(&str, &str)> {
        if self.ui.show_search {
            vec![("esc", "cancel"), ("enter", "apply")]
-
        } else if self.ui.show_help {
+
        } else if self.help.show {
            vec![("?", "close")]
        } else {
            match self.mode.selection() {
@@ -199,6 +204,10 @@ impl TryFrom<&Context> for State {
                items: notifications,
                selected: Some(0),
            },
+
            help: HelpState {
+
                show: false,
+
                progress: 0,
+
            },
            mode: mode.clone(),
            project,
            filter,
@@ -218,6 +227,7 @@ pub enum Action {
    CloseSearch,
    OpenHelp,
    CloseHelp,
+
    ScrollHelp { progress: usize },
}

impl store::State<Action, Selection> for State {
@@ -259,11 +269,15 @@ impl store::State<Action, Selection> for State {
                None
            }
            Action::OpenHelp => {
-
                self.ui.show_help = true;
+
                self.help.show = true;
                None
            }
            Action::CloseHelp => {
-
                self.ui.show_help = false;
+
                self.help.show = false;
+
                None
+
            }
+
            Action::ScrollHelp { progress } => {
+
                self.help.progress = progress;
                None
            }
        }
modified bin/commands/inbox/select/ui.rs
@@ -2,6 +2,7 @@ use std::any::Any;
use std::collections::HashMap;
use std::str::FromStr;

+
use ratatui::widgets::TableState;
use tokio::sync::mpsc::UnboundedSender;

use termion::event::Key;
@@ -17,7 +18,7 @@ use tui::ui::items::{NotificationItem, NotificationItemFilter, NotificationState
use tui::ui::span;
use tui::ui::widget::container::{Footer, FooterProps, Header, HeaderProps};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
use tui::ui::widget::{self, TableUtils};
use tui::ui::widget::{
    Column, EventCallback, Properties, Shortcuts, ShortcutsProps, Table, TableProps,
@@ -40,7 +41,7 @@ impl From<&State> for ListPageProps {
    fn from(state: &State) -> Self {
        Self {
            show_search: state.ui.show_search,
-
            show_help: state.ui.show_help,
+
            show_help: state.help.show,
        }
    }
}
@@ -188,7 +189,7 @@ impl<'a> From<&State> for NotificationsProps<'a> {

        Self {
            notifications,
-
            selected: None,
+
            selected: state.notifications.selected,
            mode: state.mode.clone(),
            stats,
            columns: [
@@ -261,25 +262,23 @@ where
                            .focus(props.focus)
                            .to_boxed(),
                    )
-
                    .on_change(|props, action_tx| {
-
                        props
-
                            .downcast_ref::<TableProps<'_, NotificationItem>>()
-
                            .and_then(|props| {
-
                                action_tx
-
                                    .send(Action::Select {
-
                                        selected: props.selected,
-
                                    })
-
                                    .ok()
-
                            });
+
                    .on_change(|state, action_tx| {
+
                        state.downcast_ref::<TableState>().and_then(|state| {
+
                            action_tx
+
                                .send(Action::Select {
+
                                    selected: state.selected(),
+
                                })
+
                                .ok()
+
                        });
                    })
                    .on_update(|state| {
                        let props = NotificationsProps::from(state);

-
                            TableProps::default()
-
                                .columns(props.columns)
-
                                .items(state.notifications())
-
                                .footer(!state.ui.show_search)
-
                                .page_size(state.ui.page_size)
+
                        TableProps::default()
+
                            .columns(props.columns)
+
                            .items(state.notifications())
+
                            .footer(!state.ui.show_search)
+
                            .page_size(state.ui.page_size)
                            .cutoff(props.cutoff, props.cutoff_after)
                            .to_boxed()
                    }),
@@ -438,7 +437,7 @@ where

        let header_height = 3_usize;

-
        let page_size = if self.props.show_search {
+
        let page_size = if props.show_search {
            self.table.render(frame, area, &());

            (area.height as usize).saturating_sub(header_height)
@@ -455,7 +454,7 @@ where
            (area.height as usize).saturating_sub(header_height)
        };

-
        if page_size != self.props.page_size {
+
        if page_size != props.page_size {
            let _ = self.action_tx.send(Action::PageSize(page_size));
        }
    }
@@ -550,6 +549,7 @@ pub struct HelpProps<'a> {
    content: Text<'a>,
    focus: bool,
    page_size: usize,
+
    progress: usize,
}

impl<'a> From<&State> for HelpProps<'a> {
@@ -686,6 +686,7 @@ impl<'a> From<&State> for HelpProps<'a> {
            content,
            focus: false,
            page_size: state.ui.page_size,
+
            progress: state.help.progress,
        }
    }
}
@@ -728,6 +729,15 @@ impl<'a, B: Backend> View<State, Action> for Help<'a, B> {
                        .focus(props.focus)
                        .to_boxed()
                })
+
                .on_change(|state, action_tx| {
+
                    state.downcast_ref::<ParagraphState>().and_then(|state| {
+
                        action_tx
+
                            .send(Action::ScrollHelp {
+
                                progress: state.progress,
+
                            })
+
                            .ok()
+
                    });
+
                })
                .to_boxed(),
            footer: Footer::new(state, action_tx).to_boxed(),
            on_update: None,
@@ -781,7 +791,7 @@ where
            Constraint::Length(3),
        ])
        .areas(area);
-
        let progress = span::default(format!("{}%", 0)).dim();
+
        let progress = span::default(format!("{}%", props.progress)).dim();

        self.header.render(
            frame,
modified bin/commands/issue/select.rs
@@ -42,7 +42,6 @@ pub struct App {
pub struct UIState {
    page_size: usize,
    show_search: bool,
-
    show_help: bool,
}

impl Default for UIState {
@@ -50,7 +49,6 @@ impl Default for UIState {
        Self {
            page_size: 1,
            show_search: false,
-
            show_help: false,
        }
    }
}
@@ -62,8 +60,15 @@ pub struct IssuesState {
}

#[derive(Clone, Debug)]
+
pub struct HelpState {
+
    show: bool,
+
    progress: usize,
+
}
+

+
#[derive(Clone, Debug)]
pub struct State {
    issues: IssuesState,
+
    help: HelpState,
    mode: Mode,
    filter: IssueItemFilter,
    search: StateValue<String>,
@@ -74,7 +79,7 @@ impl State {
    pub fn shortcuts(&self) -> Vec<(&str, &str)> {
        if self.ui.show_search {
            vec![("esc", "cancel"), ("enter", "apply")]
-
        } else if self.ui.show_help {
+
        } else if self.help.show {
            vec![("?", "close")]
        } else {
            match self.mode {
@@ -121,6 +126,10 @@ impl TryFrom<&Context> for State {
                items,
                selected: Some(0),
            },
+
            help: HelpState {
+
                show: false,
+
                progress: 0,
+
            },
            mode: context.mode.clone(),
            filter,
            search,
@@ -139,6 +148,7 @@ pub enum Action {
    CloseSearch,
    OpenHelp,
    CloseHelp,
+
    ScrollHelp { progress: usize },
}

impl store::State<Action, Selection> for State {
@@ -178,11 +188,15 @@ impl store::State<Action, Selection> for State {
                None
            }
            Action::OpenHelp => {
-
                self.ui.show_help = true;
+
                self.help.show = true;
                None
            }
            Action::CloseHelp => {
-
                self.ui.show_help = false;
+
                self.help.show = false;
+
                None
+
            }
+
            Action::ScrollHelp { progress } => {
+
                self.help.progress = progress;
                None
            }
        }
modified bin/commands/issue/select/ui.rs
@@ -4,6 +4,7 @@ use std::str::FromStr;
use std::vec;

use radicle::issue::{self, CloseReason};
+
use ratatui::widgets::TableState;
use tokio::sync::mpsc::UnboundedSender;

use termion::event::Key;
@@ -17,12 +18,12 @@ use radicle_tui as tui;

use tui::ui::items::{IssueItem, IssueItemFilter};
use tui::ui::span;
+
use tui::ui::widget;
use tui::ui::widget::container::{Footer, FooterProps, Header, HeaderProps};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps};
-
use tui::ui::widget::{self, TableUtils};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
use tui::ui::widget::{
-
    Column, EventCallback, Properties, Shortcuts, ShortcutsProps, Table, TableProps,
+
    Column, EventCallback, Properties, Shortcuts, ShortcutsProps, Table, TableProps, TableUtils,
    UpdateCallback, View, Widget,
};
use tui::Selection;
@@ -43,7 +44,7 @@ impl From<&State> for ListPageProps {
    fn from(state: &State) -> Self {
        Self {
            show_search: state.ui.show_search,
-
            show_help: state.ui.show_help,
+
            show_help: state.help.show,
        }
    }
}
@@ -266,12 +267,14 @@ where
                            .focus(props.focus)
                            .to_boxed(),
                    )
-
                    .on_change(|props, action_tx| {
-
                        if let Some(props) = props.downcast_ref::<TableProps<IssueItem>>() {
-
                            let _ = action_tx.send(Action::Select {
-
                                selected: props.selected,
-
                            });
-
                        }
+
                    .on_change(|state, action_tx| {
+
                        state.downcast_ref::<TableState>().and_then(|state| {
+
                            action_tx
+
                                .send(Action::Select {
+
                                    selected: state.selected(),
+
                                })
+
                                .ok()
+
                        });
                    })
                    .on_update(|state| {
                        let props = IssuesProps::from(state);
@@ -571,6 +574,7 @@ pub struct HelpProps<'a> {
    content: Text<'a>,
    focus: bool,
    page_size: usize,
+
    progress: usize,
}

impl<'a> From<&State> for HelpProps<'a> {
@@ -707,6 +711,7 @@ impl<'a> From<&State> for HelpProps<'a> {
            content,
            focus: false,
            page_size: state.ui.page_size,
+
            progress: state.help.progress,
        }
    }
}
@@ -747,6 +752,15 @@ impl<'a, B: Backend> View<State, Action> for Help<'a, B> {
                        .focus(props.focus)
                        .to_boxed()
                })
+
                .on_change(|state, action_tx| {
+
                    state.downcast_ref::<ParagraphState>().and_then(|state| {
+
                        action_tx
+
                            .send(Action::ScrollHelp {
+
                                progress: state.progress,
+
                            })
+
                            .ok()
+
                    });
+
                })
                .to_boxed(),
            footer: Footer::new(state, action_tx).to_boxed(),
            on_update: None,
@@ -800,7 +814,7 @@ where
            Constraint::Length(3),
        ])
        .areas(area);
-
        let progress = span::default(format!("{}%", 0)).dim();
+
        let progress = span::default(format!("{}%", props.progress)).dim();

        self.header.render(
            frame,
modified bin/commands/patch/select.rs
@@ -41,7 +41,6 @@ pub struct App {
pub struct UIState {
    page_size: usize,
    show_search: bool,
-
    show_help: bool,
}

impl Default for UIState {
@@ -49,7 +48,6 @@ impl Default for UIState {
        Self {
            page_size: 1,
            show_search: false,
-
            show_help: false,
        }
    }
}
@@ -62,24 +60,25 @@ pub struct PatchesState {

#[derive(Clone, Debug)]
pub struct HelpState {
+
    show: bool,
    progress: usize,
}

#[derive(Clone, Debug)]
pub struct State {
    patches: PatchesState,
+
    help: HelpState,
    mode: Mode,
    filter: PatchItemFilter,
    search: store::StateValue<String>,
    ui: UIState,
-
    help: HelpState,
}

impl State {
    pub fn shortcuts(&self) -> Vec<(&str, &str)> {
        if self.ui.show_search {
            vec![("esc", "cancel"), ("enter", "apply")]
-
        } else if self.ui.show_help {
+
        } else if self.help.show {
            vec![("?", "close")]
        } else {
            match self.mode {
@@ -127,13 +126,14 @@ impl TryFrom<&Context> for State {
                items,
                selected: Some(0),
            },
+
            help: HelpState {
+
                show: false,
+
                progress: 0,
+
            },
            mode: context.mode.clone(),
            filter,
            search,
            ui: UIState::default(),
-
            help: HelpState {
-
                progress: 0,
-
            }
        })
    }
}
@@ -148,7 +148,7 @@ pub enum Action {
    CloseSearch,
    OpenHelp,
    CloseHelp,
-
    HelpScroll { progress: usize },
+
    ScrollHelp { progress: usize },
}

impl store::State<Action, Selection> for State {
@@ -188,14 +188,14 @@ impl store::State<Action, Selection> for State {
                None
            }
            Action::OpenHelp => {
-
                self.ui.show_help = true;
+
                self.help.show = true;
                None
            }
            Action::CloseHelp => {
-
                self.ui.show_help = false;
+
                self.help.show = false;
                None
            }
-
            Action::HelpScroll { progress } => {
+
            Action::ScrollHelp { progress } => {
                self.help.progress = progress;
                None
            }
modified bin/commands/patch/select/ui.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap;
use std::str::FromStr;
use std::vec;

+
use ratatui::widgets::TableState;
use tokio::sync::mpsc::UnboundedSender;

use termion::event::Key;
@@ -20,7 +21,7 @@ use tui::ui::items::{PatchItem, PatchItemFilter};
use tui::ui::span;
use tui::ui::widget::container::{Footer, FooterProps, Header, HeaderProps};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
use tui::ui::widget::{self, TableUtils};
use tui::ui::widget::{
    Column, EventCallback, Properties, Shortcuts, ShortcutsProps, Table, TableProps,
@@ -44,7 +45,7 @@ impl From<&State> for ListPageProps {
    fn from(state: &State) -> Self {
        Self {
            show_search: state.ui.show_search,
-
            show_help: state.ui.show_help,
+
            show_help: state.help.show,
        }
    }
}
@@ -264,16 +265,14 @@ where
                            .focus(props.focus)
                            .to_boxed(),
                    )
-
                    .on_change(|props, action_tx| {
-
                        props
-
                            .downcast_ref::<TableProps<'_, PatchItem>>()
-
                            .and_then(|props| {
-
                                action_tx
-
                                    .send(Action::Select {
-
                                        selected: props.selected,
-
                                    })
-
                                    .ok()
-
                            });
+
                    .on_change(|state, action_tx| {
+
                        state.downcast_ref::<TableState>().and_then(|state| {
+
                            action_tx
+
                                .send(Action::Select {
+
                                    selected: state.selected(),
+
                                })
+
                                .ok()
+
                        });
                    })
                    .on_update(|state| {
                        let props = PatchesProps::from(state);
@@ -786,8 +785,8 @@ impl<'a, B: Backend> View<State, Action> for Help<'a, B> {
                .on_change(|props, action_tx| {
                    props.downcast_ref::<ParagraphProps>().and_then(|props| {
                        action_tx
-
                            .send(Action::HelpScroll {
-
                                progress: props.progress.clone(),
+
                            .send(Action::ScrollHelp {
+
                                progress: props.progress,
                            })
                            .ok()
                    });
@@ -801,6 +800,15 @@ impl<'a, B: Backend> View<State, Action> for Help<'a, B> {
                        .focus(props.focus)
                        .to_boxed()
                })
+
                .on_change(|state, action_tx| {
+
                    state.downcast_ref::<ParagraphState>().and_then(|state| {
+
                        action_tx
+
                            .send(Action::ScrollHelp {
+
                                progress: state.progress,
+
                            })
+
                            .ok()
+
                    });
+
                })
                .to_boxed(),
            footer: Footer::new(state, action_tx).to_boxed(),
            on_update: None,
modified src/ui/widget.rs
@@ -178,11 +178,7 @@ impl<S, A> View<S, A> for Shortcuts<S, A> {
    fn update(&mut self, state: &S) {
        self.props = self
            .on_update
-
            .and_then(|on_update| {
-
                (on_update)(state)
-
                    .downcast_ref::<ShortcutsProps>()
-
                    .map(|props| props.clone())
-
            })
+
            .and_then(|on_update| (on_update)(state).downcast_ref::<ShortcutsProps>().cloned())
            .unwrap_or(self.props.clone())
    }
}
@@ -438,7 +434,7 @@ where
            .and_then(|on_update| {
                (on_update)(state)
                    .downcast_ref::<TableProps<'_, R>>()
-
                    .map(|props| props.clone())
+
                    .cloned()
            })
            .unwrap_or(self.props.clone());

modified src/ui/widget/container.rs
@@ -104,11 +104,7 @@ impl<'a: 'static, S, A> View<S, A> for Header<'a, S, A> {
    fn update(&mut self, state: &S) {
        self.props = self
            .on_update
-
            .and_then(|on_update| {
-
                (on_update)(state)
-
                    .downcast_ref::<HeaderProps>()
-
                    .map(|props| props.clone())
-
            })
+
            .and_then(|on_update| (on_update)(state).downcast_ref::<HeaderProps>().cloned())
            .unwrap_or(self.props.clone());
    }

@@ -272,11 +268,7 @@ impl<'a: 'static, S, A> View<S, A> for Footer<'a, S, A> {
    fn update(&mut self, state: &S) {
        self.props = self
            .on_update
-
            .and_then(|on_update| {
-
                (on_update)(state)
-
                    .downcast_ref::<FooterProps>()
-
                    .map(|props| props.clone())
-
            })
+
            .and_then(|on_update| (on_update)(state).downcast_ref::<FooterProps>().cloned())
            .unwrap_or(self.props.clone());
    }

modified src/ui/widget/text.rs
@@ -178,11 +178,7 @@ impl<'a: 'static, S, A> View<S, A> for Paragraph<'a, S, A> {
    fn update(&mut self, state: &S) {
        self.props = self
            .on_update
-
            .and_then(|on_update| {
-
                (on_update)(state)
-
                    .downcast_ref::<ParagraphProps>()
-
                    .map(|props| props.clone())
-
            })
+
            .and_then(|on_update| (on_update)(state).downcast_ref::<ParagraphProps>().cloned())
            .unwrap_or(self.props.clone());
    }