[fractal/fractal-next] session: Load rooms and handle sync response in RoomList and Room



commit d356745f1d57726ab389fb16781221dc2c08bcaa
Author: Kévin Commaille <zecakeh tedomum fr>
Date:   Wed May 26 08:29:04 2021 +0200

    session: Load rooms and handle sync response in RoomList and Room

 src/session/categories/room_list.rs | 121 +++++++++++++++++++++++++++--------
 src/session/mod.rs                  | 124 +++---------------------------------
 src/session/room/room.rs            |  73 ++++++++++++++++++++-
 3 files changed, 173 insertions(+), 145 deletions(-)
---
diff --git a/src/session/categories/room_list.rs b/src/session/categories/room_list.rs
index 3cc09788..fc9e4394 100644
--- a/src/session/categories/room_list.rs
+++ b/src/session/categories/room_list.rs
@@ -1,6 +1,6 @@
 use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
 use indexmap::map::IndexMap;
-use matrix_sdk::{identifiers::RoomId, Client};
+use matrix_sdk::{deserialized_responses::Rooms as ResponseRooms, identifiers::RoomId, Client};
 
 use crate::session::{room::Room, user::User};
 
@@ -84,51 +84,116 @@ impl RoomList {
         priv_.list.borrow().contains_key(room_id)
     }
 
-    pub fn insert(&self, rooms: Vec<(RoomId, Room)>) {
+    pub fn remove(&self, room_id: &RoomId) {
         let priv_ = imp::RoomList::from_instance(&self);
 
-        let rooms: Vec<(RoomId, Room)> = {
-            rooms
-                .into_iter()
-                .filter(|(room_id, _)| !priv_.list.borrow().contains_key(room_id))
-                .collect()
+        let removed = {
+            let mut list = priv_.list.borrow_mut();
+
+            list.shift_remove_full(room_id)
         };
 
-        let added = rooms.len();
+        if let Some((position, _, _)) = removed {
+            self.items_changed(position as u32, 1, 0);
+        }
+    }
 
-        if added > 0 {
-            let position = priv_.list.borrow().len();
+    fn items_added(&self, added: usize) {
+        let priv_ = imp::RoomList::from_instance(&self);
 
+        let list = priv_.list.borrow();
+
+        let position = list.len() - added;
+
+        for (_room_id, room) in list.iter().skip(position) {
+            room.connect_notify_local(
+                Some("category"),
+                clone!(@weak self as obj => move |r, _| {
+                    if let Some((position, _, _)) = obj.get_full(&r.matrix_room_id()) {
+                        obj.items_changed(position as u32, 1, 1);
+                    }
+                }),
+            );
+        }
+
+        self.items_changed(position as u32, 0, added as u32);
+    }
+
+    pub fn load(&self) {
+        let priv_ = imp::RoomList::from_instance(&self);
+
+        let matrix_rooms = priv_.client.get().unwrap().rooms();
+        let added = matrix_rooms.len();
+
+        if added > 0 {
             {
                 let mut list = priv_.list.borrow_mut();
-                for (room_id, room) in rooms {
-                    room.connect_notify_local(
-                        Some("category"),
-                        clone!(@weak self as obj => move |r, _| {
-                            if let Some((position, _, _)) = obj.get_full(&r.matrix_room_id()) {
-                                obj.items_changed(position as u32, 1, 1);
-                            }
-                        }),
-                    );
-                    list.insert(room_id, room);
+                for matrix_room in matrix_rooms {
+                    let room = Room::new(matrix_room, priv_.user.get().unwrap());
+
+                    list.insert(room.matrix_room_id(), room);
                 }
             }
 
-            self.items_changed(position as u32, 0, added as u32);
+            self.items_added(added);
         }
     }
 
-    pub fn remove(&self, room_id: &RoomId) {
+    pub fn handle_response_rooms(&self, rooms: ResponseRooms) {
         let priv_ = imp::RoomList::from_instance(&self);
 
-        let removed = {
-            let mut list = priv_.list.borrow_mut();
+        let mut added = 0;
 
-            list.shift_remove_full(room_id)
-        };
+        for (room_id, left_room) in rooms.leave {
+            let matrix_room = priv_.client.get().unwrap().get_room(&room_id).unwrap();
 
-        if let Some((position, _, _)) = removed {
-            self.items_changed(position as u32, 1, 0);
+            let room = priv_
+                .list
+                .borrow_mut()
+                .entry(room_id)
+                .or_insert_with(|| {
+                    added += 1;
+                    Room::new(matrix_room.clone(), priv_.user.get().unwrap())
+                })
+                .clone();
+
+            room.handle_left_response(left_room, matrix_room);
+        }
+
+        for (room_id, joined_room) in rooms.join {
+            let matrix_room = priv_.client.get().unwrap().get_room(&room_id).unwrap();
+
+            let room = priv_
+                .list
+                .borrow_mut()
+                .entry(room_id)
+                .or_insert_with(|| {
+                    added += 1;
+                    Room::new(matrix_room.clone(), priv_.user.get().unwrap())
+                })
+                .clone();
+
+            room.handle_joined_response(joined_room, matrix_room);
+        }
+
+        for (room_id, invited_room) in rooms.invite {
+            let matrix_room = priv_.client.get().unwrap().get_room(&room_id).unwrap();
+
+            let room = priv_
+                .list
+                .borrow_mut()
+                .entry(room_id)
+                .or_insert_with(|| {
+                    added += 1;
+                    Room::new(matrix_room.clone(), priv_.user.get().unwrap())
+                })
+                .clone();
+
+            room.handle_invited_response(invited_room, matrix_room);
+        }
+
+        if added > 0 {
+            self.items_added(added);
         }
     }
 }
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 4e48e929..af99f7ab 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -10,7 +10,6 @@ use self::room::Room;
 use self::sidebar::Sidebar;
 pub use self::user::User;
 
-use crate::event_from_sync_event;
 use crate::secret;
 use crate::secret::StoredSession;
 use crate::utils::do_async;
@@ -25,12 +24,8 @@ use gtk_macros::send;
 use log::error;
 use matrix_sdk::api::r0::filter::{FilterDefinition, LazyLoadOptions, RoomEventFilter, RoomFilter};
 use matrix_sdk::{
-    self, assign,
-    deserialized_responses::SyncResponse,
-    events::{AnyRoomEvent, AnySyncRoomEvent},
-    identifiers::RoomId,
-    uuid::Uuid,
-    Client, ClientConfig, RequestConfig, SyncSettings,
+    self, assign, deserialized_responses::SyncResponse, uuid::Uuid, Client, ClientConfig,
+    RequestConfig, SyncSettings,
 };
 use rand::{distributions::Alphanumeric, thread_rng, Rng};
 use std::fs;
@@ -329,6 +324,8 @@ impl Session {
         priv_.user.set(user).unwrap();
     }
 
+    // FIXME: Leaving this method for now, if it's never used it should be removed at some point.
+    #[allow(dead_code)]
     fn user(&self) -> &User {
         let priv_ = &imp::Session::from_instance(self);
         priv_.user.get().unwrap()
@@ -358,18 +355,8 @@ impl Session {
     /// loading much via this function.
     pub fn load(&self) {
         let priv_ = imp::Session::from_instance(self);
-        let rooms = priv_.client.get().unwrap().rooms();
 
-        let mut new_rooms = Vec::with_capacity(rooms.len());
-
-        for matrix_room in rooms {
-            new_rooms.push((
-                matrix_room.room_id().clone(),
-                Room::new(matrix_room, self.user()),
-            ));
-        }
-
-        priv_.categories.room_list().insert(new_rooms);
+        priv_.categories.room_list().load();
     }
 
     /// Returns and consumes the `error` that was generated when the session failed to login,
@@ -393,103 +380,10 @@ impl Session {
 
     fn handle_sync_response(&self, response: SyncResponse) {
         let priv_ = imp::Session::from_instance(self);
-        let rooms_map = priv_.categories.room_list();
-
-        let rooms_id = response
-            .rooms
-            .join
-            .iter()
-            .map(|(room_id, _)| room_id)
-            .chain(response.rooms.leave.iter().map(|(room_id, _)| room_id))
-            .chain(response.rooms.invite.iter().map(|(room_id, _)| room_id));
-        let (old_rooms_id, new_rooms_id): (Vec<RoomId>, Vec<RoomId>) = rooms_id
-            .cloned()
-            .partition(|room_id| rooms_map.contains_key(room_id));
-
-        let mut new_rooms = Vec::new();
-
-        for room_id in new_rooms_id {
-            if let Some(matrix_room) = priv_.client.get().unwrap().get_room(&room_id) {
-                new_rooms.push((room_id, Room::new(matrix_room, self.user())));
-            }
-        }
-
-        for room_id in old_rooms_id {
-            let room = rooms_map.get(&room_id).unwrap();
-            if let Some(matrix_room) = priv_.client.get().unwrap().get_room(&room_id) {
-                room.set_matrix_room(matrix_room);
-            }
-        }
-
-        rooms_map.insert(new_rooms);
-
-        for (room_id, matrix_room) in response.rooms.leave {
-            if matrix_room.timeline.events.is_empty() {
-                continue;
-            }
-            if let Some(room) = rooms_map.get(&room_id) {
-                room.append_events(
-                    matrix_room
-                        .timeline
-                        .events
-                        .into_iter()
-                        .filter_map(|event| {
-                            if let Ok(event) = event.event.deserialize() {
-                                Some(event)
-                            } else {
-                                error!("Couldn't deserialize event: {:?}", event);
-                                None
-                            }
-                        })
-                        .map(|event| event_from_sync_event!(event, room_id))
-                        .collect(),
-                );
-            }
-        }
-
-        for (room_id, matrix_room) in response.rooms.join {
-            if matrix_room.timeline.events.is_empty() {
-                continue;
-            }
 
-            if let Some(room) = rooms_map.get(&room_id) {
-                room.append_events(
-                    matrix_room
-                        .timeline
-                        .events
-                        .into_iter()
-                        .filter_map(|event| {
-                            if let Ok(event) = event.event.deserialize() {
-                                Some(event)
-                            } else {
-                                error!("Couldn't deserialize event: {:?}", event);
-                                None
-                            }
-                        })
-                        .map(|event| event_from_sync_event!(event, room_id))
-                        .collect(),
-                );
-            }
-        }
-
-        for (room_id, matrix_room) in response.rooms.invite {
-            if let Some(room) = rooms_map.get(&room_id) {
-                room.handle_invite_events(
-                    matrix_room
-                        .invite_state
-                        .events
-                        .into_iter()
-                        .filter_map(|event| {
-                            if let Ok(event) = event.deserialize() {
-                                Some(event)
-                            } else {
-                                error!("Couldn't deserialize event: {:?}", event);
-                                None
-                            }
-                        })
-                        .collect(),
-                )
-            }
-        }
+        priv_
+            .categories
+            .room_list()
+            .handle_response_rooms(response.rooms);
     }
 }
diff --git a/src/session/room/room.rs b/src/session/room/room.rs
index 63e7f045..2a6f52ac 100644
--- a/src/session/room/room.rs
+++ b/src/session/room/room.rs
@@ -2,6 +2,8 @@ use gettextrs::gettext;
 use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
 use log::{debug, error, warn};
 use matrix_sdk::{
+    api::r0::sync::sync_events::InvitedRoom,
+    deserialized_responses::{JoinedRoom, LeftRoom},
     events::{
         room::{
             member::{MemberEventContent, MembershipState},
@@ -10,8 +12,8 @@ use matrix_sdk::{
             },
         },
         tag::TagName,
-        AnyMessageEvent, AnyRoomEvent, AnyStateEvent, AnyStrippedStateEvent, MessageEvent,
-        StateEvent, Unsigned,
+        AnyMessageEvent, AnyRoomEvent, AnyStateEvent, AnyStrippedStateEvent, AnySyncRoomEvent,
+        MessageEvent, StateEvent, Unsigned,
     },
     identifiers::{EventId, RoomId, UserId},
     room::Room as MatrixRoom,
@@ -20,6 +22,7 @@ use matrix_sdk::{
 };
 use std::cell::RefCell;
 
+use crate::event_from_sync_event;
 use crate::session::{
     categories::CategoryType,
     room::{HighlightFlags, Timeline},
@@ -586,4 +589,70 @@ impl Room {
             Ok(())
         }
     }
+
+    pub fn handle_left_response(&self, response_room: LeftRoom, matrix_room: MatrixRoom) {
+        self.set_matrix_room(matrix_room);
+
+        let room_id = self.matrix_room_id();
+
+        self.append_events(
+            response_room
+                .timeline
+                .events
+                .into_iter()
+                .filter_map(|event| {
+                    if let Ok(event) = event.event.deserialize() {
+                        Some(event)
+                    } else {
+                        error!("Couldn't deserialize event: {:?}", event);
+                        None
+                    }
+                })
+                .map(|event| event_from_sync_event!(event, room_id))
+                .collect(),
+        );
+    }
+
+    pub fn handle_joined_response(&self, response_room: JoinedRoom, matrix_room: MatrixRoom) {
+        self.set_matrix_room(matrix_room);
+
+        let room_id = self.matrix_room_id();
+
+        self.append_events(
+            response_room
+                .timeline
+                .events
+                .into_iter()
+                .filter_map(|event| {
+                    if let Ok(event) = event.event.deserialize() {
+                        Some(event)
+                    } else {
+                        error!("Couldn't deserialize event: {:?}", event);
+                        None
+                    }
+                })
+                .map(|event| event_from_sync_event!(event, room_id))
+                .collect(),
+        );
+    }
+
+    pub fn handle_invited_response(&self, response_room: InvitedRoom, matrix_room: MatrixRoom) {
+        self.set_matrix_room(matrix_room);
+
+        self.handle_invite_events(
+            response_room
+                .invite_state
+                .events
+                .into_iter()
+                .filter_map(|event| {
+                    if let Ok(event) = event.deserialize() {
+                        Some(event)
+                    } else {
+                        error!("Couldn't deserialize event: {:?}", event);
+                        None
+                    }
+                })
+                .collect(),
+        )
+    }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]