feat: Introduce the Filter trait alias.

This patch introduces the
`matrix_sdk_ui::room_list_service::filters::Filter` trait alias.

This patch also cleans up a little bit the filters by renaming some
methods for the sake of consistency across all the existing filters.
This commit is contained in:
Ivan Enderlin
2024-01-29 14:23:05 +01:00
parent 4e8c63e4e0
commit 344a96a80f
6 changed files with 55 additions and 36 deletions

View File

@@ -1,7 +1,9 @@
use matrix_sdk::RoomListEntry;
use super::Filter;
/// Create a new filter that will accept all filled or invalidated entries.
pub fn new_filter() -> impl Fn(&RoomListEntry) -> bool {
pub fn new_filter() -> impl Filter {
|room_list_entry| -> bool {
matches!(room_list_entry, RoomListEntry::Filled(_) | RoomListEntry::Invalidated(_))
}

View File

@@ -1,11 +1,19 @@
use matrix_sdk::{Client, RoomListEntry};
use matrix_sdk_base::RoomState;
struct NonLeftRoomMatcher<F: Fn(&RoomListEntry) -> Option<RoomState>> {
use super::Filter;
struct NonLeftRoomMatcher<F>
where
F: Fn(&RoomListEntry) -> Option<RoomState>,
{
get_state: F,
}
impl<F: Fn(&RoomListEntry) -> Option<RoomState>> NonLeftRoomMatcher<F> {
impl<F> NonLeftRoomMatcher<F>
where
F: Fn(&RoomListEntry) -> Option<RoomState>,
{
fn matches(&self, room: &RoomListEntry) -> bool {
if !matches!(room, RoomListEntry::Filled(_) | RoomListEntry::Invalidated(_)) {
return false;
@@ -21,7 +29,7 @@ impl<F: Fn(&RoomListEntry) -> Option<RoomState>> NonLeftRoomMatcher<F> {
/// Create a new filter that will accept all filled or invalidated entries, but
/// filters out left rooms.
pub fn new_filter(client: &Client) -> impl Fn(&RoomListEntry) -> bool {
pub fn new_filter(client: &Client) -> impl Filter {
let client = client.clone();
let matcher = NonLeftRoomMatcher {

View File

@@ -1,7 +1,7 @@
pub use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher as _};
use matrix_sdk::{Client, RoomListEntry};
use matrix_sdk::Client;
use super::normalize_string;
use super::{normalize_string, Filter};
struct FuzzyMatcher {
matcher: SkimMatcherV2,
@@ -19,7 +19,7 @@ impl FuzzyMatcher {
self
}
fn fuzzy_match(&self, subject: &str) -> bool {
fn matches(&self, subject: &str) -> bool {
// No pattern means there is a match.
let Some(pattern) = self.pattern.as_ref() else { return true };
@@ -31,7 +31,7 @@ impl FuzzyMatcher {
///
/// Rooms are fetched from the `Client`. The pattern and the room names are
/// normalized with `normalize_string`.
pub fn new_filter(client: &Client, pattern: &str) -> impl Fn(&RoomListEntry) -> bool {
pub fn new_filter(client: &Client, pattern: &str) -> impl Filter {
let searcher = FuzzyMatcher::new().with_pattern(pattern);
let client = client.clone();
@@ -41,7 +41,7 @@ pub fn new_filter(client: &Client, pattern: &str) -> impl Fn(&RoomListEntry) ->
let Some(room) = client.get_room(room_id) else { return false };
let Some(room_name) = room.name() else { return false };
searcher.fuzzy_match(&room_name)
searcher.matches(&room_name)
}
}
@@ -55,14 +55,14 @@ mod tests {
fn test_no_pattern() {
let matcher = FuzzyMatcher::new();
assert!(matcher.fuzzy_match("hello"));
assert!(matcher.matches("hello"));
}
#[test]
fn test_empty_pattern() {
let matcher = FuzzyMatcher::new();
assert!(matcher.fuzzy_match("hello"));
assert!(matcher.matches("hello"));
}
#[test]
@@ -70,10 +70,10 @@ mod tests {
let matcher = FuzzyMatcher::new();
let matcher = matcher.with_pattern("mtx");
assert!(matcher.fuzzy_match("matrix"));
assert!(matcher.matches("matrix"));
let matcher = matcher.with_pattern("mxt");
assert!(matcher.fuzzy_match("matrix").not());
assert!(matcher.matches("matrix").not());
}
#[test]
@@ -81,10 +81,10 @@ mod tests {
let matcher = FuzzyMatcher::new();
let matcher = matcher.with_pattern("mtx");
assert!(matcher.fuzzy_match("MaTrIX"));
assert!(matcher.matches("MaTrIX"));
let matcher = matcher.with_pattern("mxt");
assert!(matcher.fuzzy_match("MaTrIX").not());
assert!(matcher.matches("MaTrIX").not());
}
#[test]
@@ -92,12 +92,12 @@ mod tests {
let matcher = FuzzyMatcher::new();
let matcher = matcher.with_pattern("mtx");
assert!(matcher.fuzzy_match("matrix"));
assert!(matcher.fuzzy_match("Matrix"));
assert!(matcher.matches("matrix"));
assert!(matcher.matches("Matrix"));
let matcher = matcher.with_pattern("Mtx");
assert!(matcher.fuzzy_match("matrix").not());
assert!(matcher.fuzzy_match("Matrix"));
assert!(matcher.matches("matrix").not());
assert!(matcher.matches("Matrix"));
}
#[test]
@@ -110,10 +110,10 @@ mod tests {
assert_eq!(matcher.pattern, Some("ubete".to_owned()));
// Second, assert that the subject is normalized too.
assert!(matcher.fuzzy_match("un bel été"));
assert!(matcher.matches("un bel été"));
// Another concrete test.
let matcher = matcher.with_pattern("stf");
assert!(matcher.fuzzy_match("Ștefan"));
assert!(matcher.matches("Ștefan"));
}
}

View File

@@ -7,10 +7,19 @@ mod normalized_match_room_name;
pub use all::new_filter as new_filter_all;
pub use all_non_left::new_filter as new_filter_all_non_left;
pub use fuzzy_match_room_name::new_filter as new_filter_fuzzy_match_room_name;
use matrix_sdk::RoomListEntry;
pub use none::new_filter as new_filter_none;
pub use normalized_match_room_name::new_filter as new_filter_normalized_match_room_name;
use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
/// A trait “alias” that represents a _filter_.
///
/// A filter is simply a function that receives a `&RoomListEntry` and returns a
/// `bool`.
pub trait Filter: Fn(&RoomListEntry) -> bool {}
impl<F> Filter for F where F: Fn(&RoomListEntry) -> bool {}
/// Normalize a string, i.e. decompose it into NFD (Normalization Form D, i.e. a
/// canonical decomposition, see http://www.unicode.org/reports/tr15/) and
/// filter out the combining marks.

View File

@@ -1,7 +1,7 @@
use matrix_sdk::RoomListEntry;
use super::Filter;
/// Create a new filter that will reject all entries.
pub fn new_filter() -> impl Fn(&RoomListEntry) -> bool {
pub fn new_filter() -> impl Filter {
|_room_list_entry| -> bool { false }
}

View File

@@ -1,6 +1,6 @@
use matrix_sdk::{Client, RoomListEntry};
use matrix_sdk::Client;
use super::normalize_string;
use super::{normalize_string, Filter};
struct NormalizedMatcher {
pattern: Option<String>,
@@ -17,7 +17,7 @@ impl NormalizedMatcher {
self
}
fn normalized_match(&self, subject: &str) -> bool {
fn matches(&self, subject: &str) -> bool {
// No pattern means there is a match.
let Some(pattern) = self.pattern.as_ref() else { return true };
@@ -31,7 +31,7 @@ impl NormalizedMatcher {
///
/// Rooms are fetched from the `Client`. The pattern and the room names are
/// normalized with `normalize_string`.
pub fn new_filter(client: &Client, pattern: &str) -> impl Fn(&RoomListEntry) -> bool {
pub fn new_filter(client: &Client, pattern: &str) -> impl Filter {
let searcher = NormalizedMatcher::new().with_pattern(pattern);
let client = client.clone();
@@ -41,7 +41,7 @@ pub fn new_filter(client: &Client, pattern: &str) -> impl Fn(&RoomListEntry) ->
let Some(room) = client.get_room(room_id) else { return false };
let Some(room_name) = room.name() else { return false };
searcher.normalized_match(&room_name)
searcher.matches(&room_name)
}
}
@@ -55,14 +55,14 @@ mod tests {
fn test_no_pattern() {
let matcher = NormalizedMatcher::new();
assert!(matcher.normalized_match("hello"));
assert!(matcher.matches("hello"));
}
#[test]
fn test_empty_pattern() {
let matcher = NormalizedMatcher::new();
assert!(matcher.normalized_match("hello"));
assert!(matcher.matches("hello"));
}
#[test]
@@ -70,10 +70,10 @@ mod tests {
let matcher = NormalizedMatcher::new();
let matcher = matcher.with_pattern("matrix");
assert!(matcher.normalized_match("matrix"));
assert!(matcher.matches("matrix"));
let matcher = matcher.with_pattern("matrxi");
assert!(matcher.normalized_match("matrix").not());
assert!(matcher.matches("matrix").not());
}
#[test]
@@ -81,10 +81,10 @@ mod tests {
let matcher = NormalizedMatcher::new();
let matcher = matcher.with_pattern("matrix");
assert!(matcher.normalized_match("MaTrIX"));
assert!(matcher.matches("MaTrIX"));
let matcher = matcher.with_pattern("matrxi");
assert!(matcher.normalized_match("MaTrIX").not());
assert!(matcher.matches("MaTrIX").not());
}
#[test]
@@ -97,10 +97,10 @@ mod tests {
assert_eq!(matcher.pattern, Some("un ete".to_owned()));
// Second, assert that the subject is normalized too.
assert!(matcher.normalized_match("un été magnifique"));
assert!(matcher.matches("un été magnifique"));
// Another concrete test.
let matcher = matcher.with_pattern("stefan");
assert!(matcher.normalized_match("Ștefan"));
assert!(matcher.matches("Ștefan"));
}
}