matrix_sdk_ui/room_list_service/sorters/
name.rs

1// Copyright 2024 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::cmp::Ordering;
16
17use super::{RoomListItem, Sorter};
18
19fn cmp<'a, 'b, F>(names: F, left: &'a RoomListItem, right: &'b RoomListItem) -> Ordering
20where
21    F: Fn(&'a RoomListItem, &'b RoomListItem) -> (Option<&'a str>, Option<&'b str>),
22{
23    let (left_name, right_name) = names(left, right);
24
25    left_name.cmp(&right_name)
26}
27
28/// Create a new sorter that will sort two [`RoomListItem`] by name, i.e. by
29/// comparing their display names. A lexicographically ordering is applied, i.e.
30/// "a" < "b".
31pub fn new_sorter() -> impl Sorter {
32    fn names<'a, 'b>(
33        left: &'a RoomListItem,
34        right: &'b RoomListItem,
35    ) -> (Option<&'a str>, Option<&'b str>) {
36        (left.cached_display_name.as_deref(), right.cached_display_name.as_deref())
37    }
38
39    move |left, right| -> Ordering { cmp(names, left, right) }
40}
41
42#[cfg(test)]
43mod tests {
44    use matrix_sdk::test_utils::logged_in_client_with_server;
45    use matrix_sdk_test::async_test;
46    use ruma::room_id;
47
48    use super::{super::super::filters::new_rooms, *};
49
50    #[async_test]
51    async fn test_with_two_names() {
52        let (client, server) = logged_in_client_with_server().await;
53        let [room_a, room_b] =
54            new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server).await;
55
56        // `room_a` has a “greater name” than `room_b`.
57        {
58            assert_eq!(
59                cmp(|_left, _right| (Some("Foo"), Some("Baz")), &room_a, &room_b),
60                Ordering::Greater
61            );
62        }
63
64        // `room_a` has a “lesser name” than `room_b`.
65        {
66            assert_eq!(
67                cmp(|_left, _right| (Some("Bar"), Some("Baz")), &room_a, &room_b),
68                Ordering::Less
69            );
70        }
71
72        // `room_a` has the same name than `room_b`.
73        {
74            assert_eq!(
75                cmp(|_left, _right| (Some("Baz"), Some("Baz")), &room_a, &room_b),
76                Ordering::Equal
77            );
78        }
79    }
80
81    #[async_test]
82    async fn test_with_one_name() {
83        let (client, server) = logged_in_client_with_server().await;
84        let [room_a, room_b] =
85            new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server).await;
86
87        // `room_a` has a name, `room_b` has no name.
88        {
89            assert_eq!(
90                cmp(|_left, _right| (Some("Foo"), None), &room_a, &room_b),
91                Ordering::Greater
92            );
93        }
94
95        // `room_a` has no name, `room_b` has a name.
96        {
97            assert_eq!(cmp(|_left, _right| (None, Some("Bar")), &room_a, &room_b), Ordering::Less);
98        }
99    }
100
101    #[async_test]
102    async fn test_with_zero_name() {
103        let (client, server) = logged_in_client_with_server().await;
104        let [room_a, room_b] =
105            new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server).await;
106
107        // `room_a` and `room_b` has no name.
108        {
109            assert_eq!(cmp(|_left, _right| (None, None), &room_a, &room_b), Ordering::Equal);
110        }
111    }
112}