Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
inbox: Use base view
Erik Kundt committed 2 years ago
commit 18a35f3afab62aaca6fb863f9de647c9e1d8327e
parent 0a0d43a5bb972f632326505ffe9aba6f0f516671
1 file changed +60 -61
modified bin/commands/inbox/select/ui.rs
@@ -21,7 +21,7 @@ use tui::ui::widget::container::{
};
use tui::ui::widget::input::{TextField, TextFieldProps, TextFieldState};
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
-
use tui::ui::widget::{self, TableUtils};
+
use tui::ui::widget::{self, BaseView, TableUtils};
use tui::ui::widget::{
    Column, EventCallback, Properties, Shortcuts, ShortcutsProps, Table, TableProps,
    UpdateCallback, View, Widget,
@@ -108,14 +108,8 @@ impl<'a> From<&State> for BrowsePageProps<'a> {
impl<'a> Properties for BrowsePageProps<'a> {}

pub struct BrowsePage<'a, B> {
-
    /// Internal properties
-
    props: BrowsePageProps<'a>,
-
    /// Message sender
-
    action_tx: UnboundedSender<Action>,
-
    /// Custom update handler
-
    on_update: Option<UpdateCallback<State>>,
-
    /// Additional custom event handler
-
    on_event: Option<EventCallback<Action>>,
+
    /// Internal base
+
    base: BaseView<State, Action, BrowsePageProps<'a>>,
    /// Notifications widget
    notifications: BoxedWidget<B>,
    /// Search widget
@@ -137,8 +131,12 @@ where
        };

        Self {
-
            action_tx: action_tx.clone(),
-
            props: BrowsePageProps::from(state),
+
            base: BaseView {
+
                action_tx: action_tx.clone(),
+
                props: props.clone(),
+
                on_update: None,
+
                on_event: None,
+
            },
            notifications: Container::new(state, action_tx.clone())
                .header(
                    Header::new(state, action_tx.clone())
@@ -190,23 +188,21 @@ where
                .to_boxed(),
            search: Search::new(state, action_tx.clone()).to_boxed(),
            shortcuts: Shortcuts::new(state, action_tx.clone()).to_boxed(),
-
            on_update: None,
-
            on_event: None,
        }
    }

    fn on_event(mut self, callback: EventCallback<Action>) -> Self {
-
        self.on_event = Some(callback);
+
        self.base.on_event = Some(callback);
        self
    }

    fn on_update(mut self, callback: UpdateCallback<State>) -> Self {
-
        self.on_update = Some(callback);
+
        self.base.on_update = Some(callback);
        self
    }

    fn update(&mut self, state: &State) {
-
        self.props = BrowsePageProps::from_callback(self.on_update, state)
+
        self.base.props = BrowsePageProps::from_callback(self.base.on_update, state)
            .unwrap_or(BrowsePageProps::from(state));

        self.notifications.update(state);
@@ -215,32 +211,34 @@ where
    }

    fn handle_key_event(&mut self, key: Key) {
-
        if self.props.show_search {
+
        if self.base.props.show_search {
            self.search.handle_key_event(key);
        } else {
            match key {
                Key::Esc | Key::Ctrl('c') => {
-
                    let _ = self.action_tx.send(Action::Exit { selection: None });
+
                    let _ = self.base.action_tx.send(Action::Exit { selection: None });
                }
                Key::Char('?') => {
-
                    let _ = self.action_tx.send(Action::OpenHelp);
+
                    let _ = self.base.action_tx.send(Action::OpenHelp);
                }
                Key::Char('/') => {
-
                    let _ = self.action_tx.send(Action::OpenSearch);
+
                    let _ = self.base.action_tx.send(Action::OpenSearch);
                }
                Key::Char('\n') => {
-
                    self.props
+
                    self.base
+
                        .props
                        .selected
-
                        .and_then(|selected| self.props.notifications.get(selected))
+
                        .and_then(|selected| self.base.props.notifications.get(selected))
                        .and_then(|notif| {
-
                            let selection = match self.props.mode.selection() {
+
                            let selection = match self.base.props.mode.selection() {
                                SelectionMode::Operation => Selection::default()
                                    .with_operation(InboxOperation::Show.to_string())
                                    .with_id(notif.id),
                                SelectionMode::Id => Selection::default().with_id(notif.id),
                            };

-
                            self.action_tx
+
                            self.base
+
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(selection),
                                })
@@ -248,11 +246,13 @@ where
                        });
                }
                Key::Char('c') => {
-
                    self.props
+
                    self.base
+
                        .props
                        .selected
-
                        .and_then(|selected| self.props.notifications.get(selected))
+
                        .and_then(|selected| self.base.props.notifications.get(selected))
                        .and_then(|notif| {
-
                            self.action_tx
+
                            self.base
+
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(
                                        Selection::default()
@@ -341,7 +341,7 @@ where
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
        let props = props
            .and_then(BrowsePageProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .unwrap_or(self.base.props.clone());

        let page_size = area.height.saturating_sub(6) as usize;

@@ -385,18 +385,18 @@ where
        );

        if page_size != props.page_size {
-
            let _ = self.action_tx.send(Action::BrowserPageSize(page_size));
+
            let _ = self.base.action_tx.send(Action::BrowserPageSize(page_size));
        }
    }
}

+
pub struct SearchProps {}
+

+
impl Properties for SearchProps {}
+

pub struct Search<B: Backend> {
-
    /// Message sender
-
    action_tx: UnboundedSender<Action>,
-
    /// Custom update handler
-
    on_update: Option<UpdateCallback<State>>,
-
    /// Additional custom event handler
-
    on_event: Option<EventCallback<Action>>,
+
    /// Internal base
+
    base: BaseView<State, Action, SearchProps>,
    /// Search input field
    input: BoxedWidget<B>,
}
@@ -425,20 +425,23 @@ impl<B: Backend> View<State, Action> for Search<B> {
            })
            .to_boxed();
        Self {
-
            action_tx,
+
            base: BaseView {
+
                action_tx: action_tx.clone(),
+
                props: SearchProps {},
+
                on_update: None,
+
                on_event: None,
+
            },
            input,
-
            on_update: None,
-
            on_event: None,
        }
    }

    fn on_update(mut self, callback: UpdateCallback<State>) -> Self {
-
        self.on_update = Some(callback);
+
        self.base.on_update = Some(callback);
        self
    }

    fn on_event(mut self, callback: EventCallback<Action>) -> Self {
-
        self.on_event = Some(callback);
+
        self.base.on_event = Some(callback);
        self
    }

@@ -449,10 +452,10 @@ impl<B: Backend> View<State, Action> for Search<B> {
    fn handle_key_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc => {
-
                let _ = self.action_tx.send(Action::CloseSearch);
+
                let _ = self.base.action_tx.send(Action::CloseSearch);
            }
            Key::Char('\n') => {
-
                let _ = self.action_tx.send(Action::ApplySearch);
+
                let _ = self.base.action_tx.send(Action::ApplySearch);
            }
            _ => {
                self.input.handle_key_event(key);
@@ -499,14 +502,8 @@ pub struct HelpPage<'a, B>
where
    B: Backend,
{
-
    /// Internal properties
-
    props: HelpPageProps<'a>,
-
    /// Message sender
-
    action_tx: UnboundedSender<Action>,
-
    /// Custom update handler
-
    on_update: Option<UpdateCallback<State>>,
-
    /// Additional custom event handler
-
    on_event: Option<EventCallback<Action>>,
+
    /// Internal base
+
    base: BaseView<State, Action, HelpPageProps<'a>>,
    /// Content widget
    content: BoxedWidget<B>,
    /// Shortcut widget
@@ -522,8 +519,12 @@ where
        Self: Sized,
    {
        Self {
-
            action_tx: action_tx.clone(),
-
            props: HelpPageProps::from(state),
+
            base: BaseView {
+
                action_tx: action_tx.clone(),
+
                props: HelpPageProps::from(state),
+
                on_update: None,
+
                on_event: None,
+
            },
            content: Container::new(state, action_tx.clone())
                .header(
                    Header::new(state, action_tx.clone())
@@ -583,23 +584,21 @@ where
                )
                .to_boxed(),
            shortcuts: Shortcuts::new(state, action_tx.clone()).to_boxed(),
-
            on_update: None,
-
            on_event: None,
        }
    }

    fn on_update(mut self, callback: UpdateCallback<State>) -> Self {
-
        self.on_update = Some(callback);
+
        self.base.on_update = Some(callback);
        self
    }

    fn on_event(mut self, callback: EventCallback<Action>) -> Self {
-
        self.on_event = Some(callback);
+
        self.base.on_event = Some(callback);
        self
    }

    fn update(&mut self, state: &State) {
-
        self.props = HelpPageProps::from_callback(self.on_update, state)
+
        self.base.props = HelpPageProps::from_callback(self.base.on_update, state)
            .unwrap_or(HelpPageProps::from(state));

        self.content.update(state);
@@ -608,10 +607,10 @@ where
    fn handle_key_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc | Key::Ctrl('c') => {
-
                let _ = self.action_tx.send(Action::Exit { selection: None });
+
                let _ = self.base.action_tx.send(Action::Exit { selection: None });
            }
            Key::Char('?') => {
-
                let _ = self.action_tx.send(Action::LeavePage);
+
                let _ = self.base.action_tx.send(Action::LeavePage);
            }
            _ => {
                self.content.handle_key_event(key);
@@ -627,7 +626,7 @@ where
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
        let props = props
            .and_then(HelpPageProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .unwrap_or(self.base.props.clone());

        let page_size = area.height.saturating_sub(6) as usize;

@@ -646,7 +645,7 @@ where
        );

        if page_size != props.page_size {
-
            let _ = self.action_tx.send(Action::HelpPageSize(page_size));
+
            let _ = self.base.action_tx.send(Action::HelpPageSize(page_size));
        }
    }
}