Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
bin: Improve event callback
Erik Kundt committed 2 years ago
commit 0d43859bcffebae00460a8b5890110a22a1c3df9
parent 2c88e8f9a3a608a3a9dd24263a3cb83514ca5424
3 files changed +118 -119
modified bin/commands/inbox/select/ui.rs
@@ -1,7 +1,6 @@
use std::collections::HashMap;
use std::str::FromStr;

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

use termion::event::Key;
@@ -19,9 +18,9 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps, SectionGroup,
    SectionGroupProps,
};
-
use tui::ui::widget::input::{TextField, TextFieldProps, TextFieldState};
+
use tui::ui::widget::input::{TextField, TextFieldProps};
use tui::ui::widget::list::{Table, TableProps, TableUtils};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps};
use tui::ui::widget::window::{Shortcuts, ShortcutsProps};
use tui::ui::widget::{BaseView, BoxedAny, Properties, RenderProps, Widget};

@@ -152,14 +151,13 @@ impl<'a: 'static> Widget for Browser<'a> {
                )
                .content(Box::<Table<State, Action, NotificationItem, 9>>::new(
                    Table::new(state, action_tx.clone())
-
                        .on_event(|table, action_tx| {
-
                            TableState::from_boxed_any(table).and_then(|table| {
-
                                action_tx
-
                                    .send(Action::Select {
-
                                        selected: table.selected(),
-
                                    })
-
                                    .ok()
-
                            });
+
                        .on_event(|table| {
+
                            table
+
                                .downcast_mut::<Table<State, Action, NotificationItem, 9>>()
+
                                .and_then(|table| {
+
                                    let selected = table.selected();
+
                                    table.base_mut().send(Action::Select { selected }).ok()
+
                                });
                        })
                        .on_update(|state| {
                            let props = BrowserProps::from(state);
@@ -198,7 +196,7 @@ impl<'a: 'static> Widget for Browser<'a> {
        } else {
            match key {
                Key::Char('/') => {
-
                    let _ = self.base.action_tx.send(Action::OpenSearch);
+
                    let _ = self.base.send(Action::OpenSearch);
                }
                Key::Char('\n') => {
                    self.props
@@ -213,7 +211,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                            };

                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(selection),
                                })
@@ -226,7 +223,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.notifications.get(selected))
                        .and_then(|notif| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(
                                        Selection::default()
@@ -354,10 +350,10 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
        if self.props.handle_keys {
            match key {
                Key::Esc | Key::Ctrl('c') => {
-
                    let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                    let _ = self.base.send(Action::Exit { selection: None });
                }
                Key::Char('?') => {
-
                    let _ = self.base.action_tx.send(Action::OpenHelp);
+
                    let _ = self.base.send(Action::OpenHelp);
                }
                _ => {}
            }
@@ -388,7 +384,7 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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

@@ -419,14 +415,16 @@ impl Widget for Search {
        Self: Sized,
    {
        let input = TextField::new(state, action_tx.clone())
-
            .on_event(|field, action_tx| {
-
                TextFieldState::from_boxed_any(field).and_then(|field| {
-
                    action_tx
-
                        .send(Action::UpdateSearch {
-
                            value: field.text.clone().unwrap_or_default(),
-
                        })
-
                        .ok()
-
                });
+
            .on_event(|field| {
+
                field
+
                    .downcast_mut::<TextField<State, Action>>()
+
                    .and_then(|field| {
+
                        let text = field.text().unwrap_or(&String::new()).to_string();
+
                        field
+
                            .base_mut()
+
                            .send(Action::UpdateSearch { value: text })
+
                            .ok()
+
                    });
            })
            .on_update(|state| {
                TextFieldProps::default()
@@ -450,10 +448,10 @@ impl Widget for Search {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc => {
-
                let _ = self.base.action_tx.send(Action::CloseSearch);
+
                let _ = self.base.send(Action::CloseSearch);
            }
            Key::Char('\n') => {
-
                let _ = self.base.action_tx.send(Action::ApplySearch);
+
                let _ = self.base.send(Action::ApplySearch);
            }
            _ => {
                self.input.handle_event(key);
@@ -539,6 +537,17 @@ impl<'a: 'static> Widget for HelpPage<'a> {
                )
                .content(
                    Paragraph::new(state, action_tx.clone())
+
                        .on_event(|paragraph| {
+
                            paragraph
+
                                .downcast_mut::<Paragraph<'_, State, Action>>()
+
                                .and_then(|paragraph| {
+
                                    let progress = paragraph.progress();
+
                                    paragraph
+
                                        .base_mut()
+
                                        .send(Action::ScrollHelp { progress })
+
                                        .ok()
+
                                });
+
                        })
                        .on_update(|state| {
                            let props = HelpPageProps::from(state);

@@ -547,15 +556,6 @@ impl<'a: 'static> Widget for HelpPage<'a> {
                                .page_size(props.page_size)
                                .to_boxed()
                        })
-
                        .on_event(|paragraph, action_tx| {
-
                            ParagraphState::from_boxed_any(paragraph).and_then(|paragraph| {
-
                                action_tx
-
                                    .send(Action::ScrollHelp {
-
                                        progress: paragraph.progress,
-
                                    })
-
                                    .ok()
-
                            });
-
                        })
                        .to_boxed(),
                )
                .footer(
@@ -593,10 +593,10 @@ impl<'a: 'static> Widget for HelpPage<'a> {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc | Key::Ctrl('c') => {
-
                let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                let _ = self.base.send(Action::Exit { selection: None });
            }
            Key::Char('?') => {
-
                let _ = self.base.action_tx.send(Action::LeavePage);
+
                let _ = self.base.send(Action::LeavePage);
            }
            _ => {
                self.content.handle_event(key);
@@ -624,7 +624,7 @@ impl<'a: 'static> Widget for HelpPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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

modified bin/commands/issue/select/ui.rs
@@ -3,7 +3,6 @@ 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;
@@ -21,9 +20,9 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps, SectionGroup,
    SectionGroupProps,
};
-
use tui::ui::widget::input::{TextField, TextFieldProps, TextFieldState};
+
use tui::ui::widget::input::{TextField, TextFieldProps};
use tui::ui::widget::list::{Table, TableProps, TableUtils};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps};
use tui::ui::widget::window::{Shortcuts, ShortcutsProps};
use tui::ui::widget::{BaseView, BoxedAny, Properties, RenderProps, Widget};

@@ -166,14 +165,13 @@ impl<'a: 'static> Widget for Browser<'a> {
                )
                .content(Box::<Table<State, Action, IssueItem, 8>>::new(
                    Table::new(state, action_tx.clone())
-
                        .on_event(|table, action_tx| {
-
                            TableState::from_boxed_any(table).and_then(|table| {
-
                                action_tx
-
                                    .send(Action::Select {
-
                                        selected: table.selected(),
-
                                    })
-
                                    .ok()
-
                            });
+
                        .on_event(|table| {
+
                            table
+
                                .downcast_mut::<Table<State, Action, IssueItem, 8>>()
+
                                .and_then(|table| {
+
                                    let selected = table.selected();
+
                                    table.base_mut().send(Action::Select { selected }).ok()
+
                                });
                        })
                        .on_update(|state| {
                            let props = BrowserProps::from(state);
@@ -214,7 +212,7 @@ impl<'a: 'static> Widget for Browser<'a> {
        } else {
            match key {
                Key::Char('/') => {
-
                    let _ = self.base.action_tx.send(Action::OpenSearch);
+
                    let _ = self.base.send(Action::OpenSearch);
                }
                Key::Char('\n') => {
                    let operation = match self.props.mode {
@@ -227,7 +225,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.issues.get(selected))
                        .and_then(|issue| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(Selection {
                                        operation,
@@ -244,7 +241,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.issues.get(selected))
                        .and_then(|issue| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(Selection {
                                        operation: Some(IssueOperation::Edit.to_string()),
@@ -373,10 +369,10 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
        if self.props.handle_keys {
            match key {
                Key::Esc | Key::Ctrl('c') => {
-
                    let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                    let _ = self.base.send(Action::Exit { selection: None });
                }
                Key::Char('?') => {
-
                    let _ = self.base.action_tx.send(Action::OpenHelp);
+
                    let _ = self.base.send(Action::OpenHelp);
                }
                _ => {}
            }
@@ -407,7 +403,7 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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

@@ -438,14 +434,16 @@ impl Widget for Search {
        Self: Sized,
    {
        let input = TextField::new(state, action_tx.clone())
-
            .on_event(|field, action_tx| {
-
                TextFieldState::from_boxed_any(field).and_then(|field| {
-
                    action_tx
-
                        .send(Action::UpdateSearch {
-
                            value: field.text.clone().unwrap_or_default(),
-
                        })
-
                        .ok()
-
                });
+
            .on_event(|field| {
+
                field
+
                    .downcast_mut::<TextField<State, Action>>()
+
                    .and_then(|field| {
+
                        let text = field.text().unwrap_or(&String::new()).to_string();
+
                        field
+
                            .base_mut()
+
                            .send(Action::UpdateSearch { value: text })
+
                            .ok()
+
                    });
            })
            .on_update(|state| {
                TextFieldProps::default()
@@ -469,10 +467,10 @@ impl Widget for Search {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc => {
-
                let _ = self.base.action_tx.send(Action::CloseSearch);
+
                let _ = self.base.send(Action::CloseSearch);
            }
            Key::Char('\n') => {
-
                let _ = self.base.action_tx.send(Action::ApplySearch);
+
                let _ = self.base.send(Action::ApplySearch);
            }
            _ => {
                self.input.handle_event(key);
@@ -563,14 +561,16 @@ impl<'a: 'static> Widget for HelpPage<'a> {
                                .page_size(props.page_size)
                                .to_boxed()
                        })
-
                        .on_event(|paragraph, action_tx| {
-
                            ParagraphState::from_boxed_any(paragraph).and_then(|paragraph| {
-
                                action_tx
-
                                    .send(Action::ScrollHelp {
-
                                        progress: paragraph.progress,
-
                                    })
-
                                    .ok()
-
                            });
+
                        .on_event(|paragraph| {
+
                            paragraph
+
                                .downcast_mut::<Paragraph<'_, State, Action>>()
+
                                .and_then(|paragraph| {
+
                                    let progress = paragraph.progress();
+
                                    paragraph
+
                                        .base_mut()
+
                                        .send(Action::ScrollHelp { progress })
+
                                        .ok()
+
                                });
                        })
                        .to_boxed(),
                )
@@ -609,10 +609,10 @@ impl<'a: 'static> Widget for HelpPage<'a> {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc | Key::Ctrl('c') => {
-
                let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                let _ = self.base.send(Action::Exit { selection: None });
            }
            Key::Char('?') => {
-
                let _ = self.base.action_tx.send(Action::LeavePage);
+
                let _ = self.base.send(Action::LeavePage);
            }
            _ => {
                self.content.handle_event(key);
@@ -640,7 +640,7 @@ impl<'a: 'static> Widget for HelpPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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

modified bin/commands/patch/select/ui.rs
@@ -2,7 +2,6 @@ use std::collections::HashMap;
use std::str::FromStr;
use std::vec;

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

use termion::event::Key;
@@ -22,9 +21,9 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps, SectionGroup,
    SectionGroupProps,
};
-
use tui::ui::widget::input::{TextField, TextFieldProps, TextFieldState};
+
use tui::ui::widget::input::{TextField, TextFieldProps};
use tui::ui::widget::list::{Table, TableProps, TableUtils};
-
use tui::ui::widget::text::{Paragraph, ParagraphProps, ParagraphState};
+
use tui::ui::widget::text::{Paragraph, ParagraphProps};
use tui::ui::widget::window::{Shortcuts, ShortcutsProps};
use tui::ui::widget::{BaseView, BoxedAny, Properties, RenderProps, Widget};

@@ -166,14 +165,13 @@ impl<'a: 'static> Widget for Browser<'a> {
                )
                .content(Box::<Table<State, Action, PatchItem, 9>>::new(
                    Table::new(state, action_tx.clone())
-
                        .on_event(|table, action_tx| {
-
                            TableState::from_boxed_any(table).and_then(|table| {
-
                                action_tx
-
                                    .send(Action::Select {
-
                                        selected: table.selected(),
-
                                    })
-
                                    .ok()
-
                            });
+
                        .on_event(|table| {
+
                            table
+
                                .downcast_mut::<Table<State, Action, PatchItem, 9>>()
+
                                .and_then(|table| {
+
                                    let selected = table.selected();
+
                                    table.base_mut().send(Action::Select { selected }).ok()
+
                                });
                        })
                        .on_update(|state| {
                            let props = BrowserProps::from(state);
@@ -214,13 +212,13 @@ impl<'a: 'static> Widget for Browser<'a> {
        } else {
            match key {
                Key::Esc | Key::Ctrl('c') => {
-
                    let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                    let _ = self.base.send(Action::Exit { selection: None });
                }
                Key::Char('?') => {
-
                    let _ = self.base.action_tx.send(Action::OpenHelp);
+
                    let _ = self.base.send(Action::OpenHelp);
                }
                Key::Char('/') => {
-
                    let _ = self.base.action_tx.send(Action::OpenSearch);
+
                    let _ = self.base.send(Action::OpenSearch);
                }
                Key::Char('\n') => {
                    let operation = match self.props.mode {
@@ -233,7 +231,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.patches.get(selected))
                        .and_then(|patch| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(Selection {
                                        operation,
@@ -250,7 +247,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.patches.get(selected))
                        .and_then(|patch| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(Selection {
                                        operation: Some(PatchOperation::Checkout.to_string()),
@@ -267,7 +263,6 @@ impl<'a: 'static> Widget for Browser<'a> {
                        .and_then(|selected| self.props.patches.get(selected))
                        .and_then(|patch| {
                            self.base
-
                                .action_tx
                                .send(Action::Exit {
                                    selection: Some(Selection {
                                        operation: Some(PatchOperation::Diff.to_string()),
@@ -397,10 +392,10 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
        if self.props.handle_keys {
            match key {
                Key::Esc | Key::Ctrl('c') => {
-
                    let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                    let _ = self.base.send(Action::Exit { selection: None });
                }
                Key::Char('?') => {
-
                    let _ = self.base.action_tx.send(Action::OpenHelp);
+
                    let _ = self.base.send(Action::OpenHelp);
                }
                _ => {}
            }
@@ -431,7 +426,7 @@ impl<'a: 'static> Widget for BrowserPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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

@@ -462,14 +457,16 @@ impl Widget for Search {
        Self: Sized,
    {
        let input = TextField::new(state, action_tx.clone())
-
            .on_event(|field, action_tx| {
-
                TextFieldState::from_boxed_any(field).and_then(|field| {
-
                    action_tx
-
                        .send(Action::UpdateSearch {
-
                            value: field.text.clone().unwrap_or_default(),
-
                        })
-
                        .ok()
-
                });
+
            .on_event(|field| {
+
                field
+
                    .downcast_mut::<TextField<State, Action>>()
+
                    .and_then(|field| {
+
                        let text = field.text().unwrap_or(&String::new()).to_string();
+
                        field
+
                            .base_mut()
+
                            .send(Action::UpdateSearch { value: text })
+
                            .ok()
+
                    });
            })
            .on_update(|state| {
                TextFieldProps::default()
@@ -493,10 +490,10 @@ impl Widget for Search {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc => {
-
                let _ = self.base.action_tx.send(Action::CloseSearch);
+
                let _ = self.base.send(Action::CloseSearch);
            }
            Key::Char('\n') => {
-
                let _ = self.base.action_tx.send(Action::ApplySearch);
+
                let _ = self.base.send(Action::ApplySearch);
            }
            _ => {
                self.input.handle_event(key);
@@ -579,6 +576,17 @@ impl<'a: 'static> Widget for HelpPage<'a> {
                )
                .content(
                    Paragraph::new(state, action_tx.clone())
+
                        .on_event(|paragraph| {
+
                            paragraph
+
                                .downcast_mut::<Paragraph<'_, State, Action>>()
+
                                .and_then(|paragraph| {
+
                                    let progress = paragraph.progress();
+
                                    paragraph
+
                                        .base_mut()
+
                                        .send(Action::ScrollHelp { progress })
+
                                        .ok()
+
                                });
+
                        })
                        .on_update(|state| {
                            let props = HelpPageProps::from(state);

@@ -587,15 +595,6 @@ impl<'a: 'static> Widget for HelpPage<'a> {
                                .page_size(props.page_size)
                                .to_boxed()
                        })
-
                        .on_event(|paragraph, action_tx| {
-
                            ParagraphState::from_boxed_any(paragraph).and_then(|paragraph| {
-
                                action_tx
-
                                    .send(Action::ScrollHelp {
-
                                        progress: paragraph.progress,
-
                                    })
-
                                    .ok()
-
                            });
-
                        })
                        .to_boxed(),
                )
                .footer(
@@ -633,10 +632,10 @@ impl<'a: 'static> Widget for HelpPage<'a> {
    fn handle_event(&mut self, key: termion::event::Key) {
        match key {
            Key::Esc | Key::Ctrl('c') => {
-
                let _ = self.base.action_tx.send(Action::Exit { selection: None });
+
                let _ = self.base.send(Action::Exit { selection: None });
            }
            Key::Char('?') => {
-
                let _ = self.base.action_tx.send(Action::LeavePage);
+
                let _ = self.base.send(Action::LeavePage);
            }
            _ => {
                self.content.handle_event(key);
@@ -663,7 +662,7 @@ impl<'a: 'static> Widget for HelpPage<'a> {
            .render(frame, RenderProps::from(shortcuts_area));

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