Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
all: Support table paging keys
Archived did:key:z6MkgFq6...nBGz opened 2 years ago

Add support for Home, End, PgUp and PgDown.

5 files changed +110 -90 b6ff4ddc 93bd47b7
modified bin/commands/inbox/flux/select/ui.rs
@@ -226,36 +226,35 @@ impl Widget<InboxState, Action> for Notifications {
        match key {
            Key::Up | Key::Char('k') => {
                self.table.prev();
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.notifications.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(notif) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: notif.clone(),
-
                    });
-
                }
            }
            Key::Down | Key::Char('j') => {
                self.table.next(self.props.notifications.len());
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.notifications.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(notif) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: notif.clone(),
-
                    });
-
                }
+
            }
+
            Key::PageUp => {
+
                self.table.prev_page(self.props.page_size);
+
            }
+
            Key::PageDown => {
+
                self.table
+
                    .next_page(self.props.notifications.len(), self.props.page_size);
+
            }
+
            Key::Home => {
+
                self.table.begin();
+
            }
+
            Key::End => {
+
                self.table.end(self.props.notifications.len());
            }
            _ => {}
        }
+
        self.table
+
            .selected()
+
            .and_then(|selected| self.props.notifications.get(selected))
+
            .and_then(|notif| {
+
                self.action_tx
+
                    .send(Action::Select {
+
                        item: notif.clone(),
+
                    })
+
                    .ok()
+
            });
    }
}

modified bin/commands/issue/flux/select/ui.rs
@@ -260,36 +260,35 @@ impl Widget<IssuesState, Action> for Issues {
        match key {
            Key::Up | Key::Char('k') => {
                self.table.prev();
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.issues.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(notif) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: notif.clone(),
-
                    });
-
                }
            }
            Key::Down | Key::Char('j') => {
                self.table.next(self.props.issues.len());
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.issues.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(notif) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: notif.clone(),
-
                    });
-
                }
+
            }
+
            Key::PageUp => {
+
                self.table.prev_page(self.props.page_size);
+
            }
+
            Key::PageDown => {
+
                self.table
+
                    .next_page(self.props.issues.len(), self.props.page_size);
+
            }
+
            Key::Home => {
+
                self.table.begin();
+
            }
+
            Key::End => {
+
                self.table.end(self.props.issues.len());
            }
            _ => {}
        }
+
        self.table
+
            .selected()
+
            .and_then(|selected| self.props.issues.get(selected))
+
            .and_then(|issue| {
+
                self.action_tx
+
                    .send(Action::Select {
+
                        item: issue.clone(),
+
                    })
+
                    .ok()
+
            });
    }
}

modified bin/commands/patch/flux/select/ui.rs
@@ -291,36 +291,35 @@ impl Widget<PatchesState, Action> for Patches {
        match key {
            Key::Up | Key::Char('k') => {
                self.table.prev();
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.patches.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(patch) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: patch.clone(),
-
                    });
-
                }
            }
            Key::Down | Key::Char('j') => {
                self.table.next(self.props.patches.len());
-

-
                let selected = self
-
                    .table
-
                    .selected()
-
                    .and_then(|selected| self.props.patches.get(selected));
-

-
                // TODO: propagate error
-
                if let Some(patch) = selected {
-
                    let _ = self.action_tx.send(Action::Select {
-
                        item: patch.clone(),
-
                    });
-
                }
+
            }
+
            Key::PageUp => {
+
                self.table.prev_page(self.props.page_size);
+
            }
+
            Key::PageDown => {
+
                self.table
+
                    .next_page(self.props.patches.len(), self.props.page_size);
+
            }
+
            Key::Home => {
+
                self.table.begin();
+
            }
+
            Key::End => {
+
                self.table.end(self.props.patches.len());
            }
            _ => {}
        }
+
        self.table
+
            .selected()
+
            .and_then(|selected| self.props.patches.get(selected))
+
            .and_then(|patch| {
+
                self.action_tx
+
                    .send(Action::Select {
+
                        item: patch.clone(),
+
                    })
+
                    .ok()
+
            });
    }
}

modified src/flux/ui/widget.rs
@@ -145,12 +145,13 @@ impl<A> Table<A> {
        self.state.selected()
    }

-
    pub fn prev(&mut self) {
+
    pub fn prev(&mut self) -> Option<usize> {
        let selected = self.selected().map(|current| current.saturating_sub(1));
        self.state.select(selected);
+
        selected
    }

-
    pub fn next(&mut self, len: usize) {
+
    pub fn next(&mut self, len: usize) -> Option<usize> {
        let selected = self.selected().map(|current| {
            if current < len.saturating_sub(1) {
                current.saturating_add(1)
@@ -159,6 +160,37 @@ impl<A> Table<A> {
            }
        });
        self.state.select(selected);
+
        selected
+
    }
+

+
    pub fn prev_page(&mut self, page_size: usize) -> Option<usize> {
+
        let selected = self
+
            .selected()
+
            .map(|current| current.saturating_sub(page_size));
+
        self.state.select(selected);
+
        selected
+
    }
+

+
    pub fn next_page(&mut self, len: usize, page_size: usize) -> Option<usize> {
+
        let selected = self.selected().map(|current| {
+
            if current < len.saturating_sub(1) {
+
                cmp::min(current.saturating_add(page_size), len.saturating_sub(1))
+
            } else {
+
                current
+
            }
+
        });
+
        self.state.select(selected);
+
        selected
+
    }
+

+
    pub fn begin(&mut self) -> Option<usize> {
+
        self.state.select(Some(0));
+
        self.state.selected()
+
    }
+

+
    pub fn end(&mut self, len: usize) -> Option<usize> {
+
        self.state.select(Some(len.saturating_sub(1)));
+
        self.state.selected()
    }

    pub fn progress(&self, len: usize) -> (usize, usize) {
@@ -176,16 +208,16 @@ impl<A> Table<A> {
        let len = len as f64;

        let lines = page_size + step.saturating_sub(page_size as usize) as f64;
-
        let progress = (lines / len * 100_f64).ceil() as usize;
+
        let progress = (lines / len * 100.0).ceil();

-
        if progress > 97 {
-
            Self::map_range((0, progress), (0, 100), progress)
+
        if progress > 97.0 {
+
            Self::map_range((0.0, progress), (0.0, 100.0), progress) as usize
        } else {
-
            progress
+
            progress as usize
        }
    }

-
    fn map_range(from: (usize, usize), to: (usize, usize), value: usize) -> usize {
+
    fn map_range(from: (f64, f64), to: (f64, f64), value: f64) -> f64 {
        to.0 + (value - from.0) * (to.1 - to.0) / (from.1 - from.0)
    }
}
modified src/flux/ui/widget/container.rs
@@ -77,16 +77,8 @@ impl<A> Footer<A> {

impl<'a, A, const W: usize> Render<FooterProps<'a, W>> for Footer<A> {
    fn render<B: Backend>(&self, frame: &mut ratatui::Frame, area: Rect, props: FooterProps<W>) {
-
        let widths = props.widths.to_vec();
-
        let widths = if area.width < props.cutoff as u16 {
-
            widths
-
                .into_iter()
-
                .take(props.cutoff_after)
-
                .collect::<Vec<_>>()
-
        } else {
-
            widths.into_iter().collect::<Vec<_>>()
-
        };
-
        let widths = widths
+
        let widths = props
+
            .widths
            .into_iter()
            .map(|c| match c {
                Constraint::Min(min) => Constraint::Length(min.saturating_add(3)),
@@ -101,7 +93,6 @@ impl<'a, A, const W: usize> Render<FooterProps<'a, W>> for Footer<A> {
        let len = cells.len();

        for (i, (cell, area)) in cells.into_iter().enumerate() {
-
            // let last = cells.len().saturating_sub(1);
            let block_type = match i {
                0 if len == 1 => FooterBlockType::Single,
                0 => FooterBlockType::Begin,