Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
bin/ui/items: Reorganize notification filters
Erik Kundt committed 6 months ago
commit df8eedef7a81a92e66fec7edaab05988d4491241
parent 5b90f92b5fcc3a9d5a14b5e99d5645dd019d53ca
5 files changed +77 -58
modified bin/commands/inbox/list.rs
@@ -34,9 +34,9 @@ use tui::ui::Column;
use tui::{BoxedAny, Channel, Exit, PageStack};

use crate::cob::inbox;
+
use crate::ui::items::filter::Filter;
use crate::ui::items::notification::filter::NotificationFilter;
use crate::ui::items::notification::Notification;
-
use crate::ui::items::Filter;

use self::ui::Browser;
use self::ui::BrowserProps;
modified bin/commands/patch/list/imui.rs
@@ -20,7 +20,8 @@ use tui::{store, Exit};

use crate::cob::patch;
use crate::tui_patch::common::{Mode, PatchOperation};
-
use crate::ui::items::{Filter, PatchItem, PatchItemFilter};
+
use crate::ui::items::filter::Filter;
+
use crate::ui::items::{PatchItem, PatchItemFilter};

use super::{Context, Selection};

modified bin/ui/items.rs
@@ -51,8 +51,63 @@ use crate::ui;
use super::super::git;
use super::format;

-
pub trait Filter<T> {
-
    fn matches(&self, item: &T) -> bool;
+
pub mod filter {
+
    use std::str::FromStr;
+

+
    use nom::bytes::complete::{tag_no_case, take};
+
    use nom::character::complete::{char, multispace0};
+
    use nom::combinator::map;
+
    use nom::multi::separated_list1;
+
    use nom::sequence::{delimited, tuple};
+
    use nom::IResult;
+

+
    use radicle::prelude::Did;
+

+
    /// A generic filter that needs be implemented for item filters in order to
+
    /// apply it.
+
    pub trait Filter<T> {
+
        fn matches(&self, item: &T) -> bool;
+
    }
+

+
    #[derive(Debug, Clone, PartialEq)]
+
    pub enum DidFilter {
+
        Single(Did),
+
        Or(Vec<Did>),
+
    }
+

+
    fn parse_did(input: &str) -> IResult<&str, Did> {
+
        match Did::from_str(input) {
+
            Ok(did) => IResult::Ok(("", did)),
+
            Err(_) => IResult::Err(nom::Err::Error(nom::error::Error::new(
+
                input,
+
                nom::error::ErrorKind::Verify,
+
            ))),
+
        }
+
    }
+

+
    pub fn parse_did_single(input: &str) -> IResult<&str, DidFilter> {
+
        map(parse_did, DidFilter::Single)(input)
+
    }
+

+
    pub fn parse_did_or(input: &str) -> IResult<&str, DidFilter> {
+
        map(
+
            delimited(
+
                tuple((multispace0, char('('), multispace0)),
+
                separated_list1(
+
                    delimited(multispace0, tag_no_case("or"), multispace0),
+
                    take(56_usize),
+
                ),
+
                tuple((multispace0, char(')'), multispace0)),
+
            ),
+
            |dids: Vec<&str>| {
+
                DidFilter::Or(
+
                    dids.iter()
+
                        .filter_map(|did| Did::from_str(did).ok())
+
                        .collect::<Vec<_>>(),
+
                )
+
            },
+
        )(input)
+
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
@@ -197,7 +252,7 @@ impl IssueItemFilter {
    }
}

-
impl Filter<IssueItem> for IssueItemFilter {
+
impl filter::Filter<IssueItem> for IssueItemFilter {
    fn matches(&self, issue: &IssueItem) -> bool {
        use fuzzy_matcher::skim::SkimMatcherV2;
        use fuzzy_matcher::FuzzyMatcher;
@@ -449,7 +504,7 @@ impl PatchItemFilter {
    }
}

-
impl Filter<PatchItem> for PatchItemFilter {
+
impl filter::Filter<PatchItem> for PatchItemFilter {
    fn matches(&self, patch: &PatchItem) -> bool {
        use fuzzy_matcher::skim::SkimMatcherV2;
        use fuzzy_matcher::FuzzyMatcher;
modified bin/ui/items/notification.rs
@@ -7,7 +7,7 @@ use radicle::node;

use radicle::patch::Patches;
use radicle::storage::git::Repository;
-
use radicle::storage::{ReadRepository, ReadStorage, RefUpdate};
+
use radicle::storage::{ReadRepository, RefUpdate};
use radicle::Profile;

use radicle_tui::ui::theme::style;
@@ -19,7 +19,7 @@ use radicle_tui as tui;
use tui::ui::span;
use tui::ui::ToRow;

-
use super::{AuthorItem, Filter};
+
use super::AuthorItem;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum NotificationType {
@@ -295,22 +295,23 @@ pub mod filter {
    use std::str::FromStr;

    use nom::branch::alt;
-
    use nom::bytes::complete::{tag_no_case, take, take_while1};
+
    use nom::bytes::complete::{tag_no_case, take_while1};
    use nom::character::complete::{char, multispace0};
    use nom::combinator::{map, value};
    use nom::multi::{many0, separated_list1};
    use nom::sequence::{delimited, preceded, tuple};
    use nom::IResult;

-
    use radicle::prelude::Did;
+
    use crate::ui::items::filter;
+
    use crate::ui::items::filter::{DidFilter, Filter};

-
    use super::{Filter, Notification, NotificationKind, NotificationState, NotificationType};
+
    use super::{Notification, NotificationKind, NotificationState, NotificationType};

    #[derive(Debug, Clone, PartialEq)]
    pub enum NotificationFilter {
        State(NotificationState),
        Type(NotificationTypeFilter),
-
        Author(NotificationAuthorFilter),
+
        Author(DidFilter),
        Search(String),
        And(Vec<NotificationFilter>),
    }
@@ -330,12 +331,6 @@ pub mod filter {
        Or(Vec<NotificationType>),
    }

-
    #[derive(Debug, Clone, PartialEq)]
-
    pub enum NotificationAuthorFilter {
-
        Single(Did),
-
        Or(Vec<Did>),
-
    }
-

    impl Filter<Notification> for NotificationFilter {
        fn matches(&self, notif: &Notification) -> bool {
            use fuzzy_matcher::skim::SkimMatcherV2;
@@ -376,8 +371,8 @@ pub mod filter {
                    }
                },
                NotificationFilter::Author(author_filter) => match author_filter {
-
                    NotificationAuthorFilter::Single(author) => notif.author.nid == Some(**author),
-
                    NotificationAuthorFilter::Or(authors) => authors
+
                    DidFilter::Single(author) => notif.author.nid == Some(**author),
+
                    DidFilter::Or(authors) => authors
                        .iter()
                        .any(|other| notif.author.nid == Some(**other)),
                },
@@ -411,16 +406,6 @@ pub mod filter {
        type Err = anyhow::Error;

        fn from_str(filter_exp: &str) -> Result<Self, Self::Err> {
-
            fn parse_did(input: &str) -> IResult<&str, Did> {
-
                match Did::from_str(input) {
-
                    Ok(did) => IResult::Ok(("", did)),
-
                    Err(_) => IResult::Err(nom::Err::Error(nom::error::Error::new(
-
                        input,
-
                        nom::error::ErrorKind::Verify,
-
                    ))),
-
                }
-
            }
-

            fn parse_state(input: &str) -> IResult<&str, NotificationState> {
                alt((
                    value(NotificationState::Seen, tag_no_case("seen")),
@@ -485,30 +470,6 @@ pub mod filter {
                )(input)
            }

-
            fn parse_author_single(input: &str) -> IResult<&str, NotificationAuthorFilter> {
-
                map(parse_did, NotificationAuthorFilter::Single)(input)
-
            }
-

-
            fn parse_author_or(input: &str) -> IResult<&str, NotificationAuthorFilter> {
-
                map(
-
                    delimited(
-
                        tuple((multispace0, char('('), multispace0)),
-
                        separated_list1(
-
                            delimited(multispace0, tag_no_case("or"), multispace0),
-
                            take(56_usize),
-
                        ),
-
                        tuple((multispace0, char(')'), multispace0)),
-
                    ),
-
                    |dids: Vec<&str>| {
-
                        NotificationAuthorFilter::Or(
-
                            dids.iter()
-
                                .filter_map(|did| Did::from_str(did).ok())
-
                                .collect::<Vec<_>>(),
-
                        )
-
                    },
-
                )(input)
-
            }
-

            fn parse_author_filter(input: &str) -> IResult<&str, NotificationFilter> {
                map(
                    preceded(
@@ -518,7 +479,7 @@ pub mod filter {
                            tag_no_case("="),
                            multispace0,
                        )),
-
                        alt((parse_author_single, parse_author_or)),
+
                        alt((filter::parse_did_single, filter::parse_did_or)),
                    ),
                    NotificationFilter::Author,
                )(input)
@@ -578,6 +539,8 @@ mod tests {
    use anyhow::Result;
    use radicle::prelude::Did;

+
    use crate::ui::items::filter::DidFilter;
+

    use super::filter::*;
    use super::*;

@@ -599,7 +562,7 @@ mod tests {
        let search = r#"author=did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB"#;
        let actual = NotificationFilter::from_str(search)?;

-
        let expected = NotificationFilter::Author(NotificationAuthorFilter::Single(Did::from_str(
+
        let expected = NotificationFilter::Author(DidFilter::Single(Did::from_str(
            "did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB",
        )?));

@@ -631,7 +594,7 @@ mod tests {
                NotificationType::Patch,
                NotificationType::Issue,
            ])),
-
            NotificationFilter::Author(NotificationAuthorFilter::Or(vec![
+
            NotificationFilter::Author(DidFilter::Or(vec![
                Did::from_str("did:key:z6MkkpTPzcq1ybmjQyQpyre15JUeMvZY6toxoZVpLZ8YarsB")?,
                Did::from_str("did:key:z6Mku8hpprWTmCv3BqkssCYDfr2feUdyLSUnycVajFo9XVAx")?,
            ])),
modified bin/ui/rm.rs
@@ -17,7 +17,7 @@ use tui::ui::{layout, span, BufferedValue};
use super::format;
use super::items::IssueItem;

-
use crate::ui::items::Filter;
+
use crate::ui::items::filter::Filter;

/// A `BrowserState` represents the internal state of a browser widget.
/// A browser widget would consist of 2 child widgets: a list of items and a