[fractal/fractal-next] session: Track changes of room type



commit 5322e9bcdfd25cff6009b0120f03e50c532c42e6
Author: Julian Sparber <julian sparber net>
Date:   Thu May 20 14:05:48 2021 +0200

    session: Track changes of room type

 src/session/categories/room_list.rs |  2 +-
 src/session/mod.rs                  | 36 +++++++++----------
 src/session/room/room.rs            | 70 +++++++++++++++++++++++++------------
 3 files changed, 65 insertions(+), 43 deletions(-)
---
diff --git a/src/session/categories/room_list.rs b/src/session/categories/room_list.rs
index 7b5056b5..d2848c11 100644
--- a/src/session/categories/room_list.rs
+++ b/src/session/categories/room_list.rs
@@ -103,7 +103,7 @@ impl RoomList {
                     room.connect_notify_local(
                         Some("category"),
                         clone!(@weak self as obj => move |r, _| {
-                            if let Some((position, _, _)) = obj.get_full(r.matrix_room().room_id()) {
+                            if let Some((position, _, _)) = obj.get_full(&r.matrix_room_id()) {
                                 obj.items_changed(position as u32, 1, 1);
                             }
                         }),
diff --git a/src/session/mod.rs b/src/session/mod.rs
index 65aa6586..c6b6147c 100644
--- a/src/session/mod.rs
+++ b/src/session/mod.rs
@@ -390,24 +390,16 @@ impl Session {
         let priv_ = imp::Session::from_instance(self);
         let rooms_map = priv_.categories.room_list();
 
-        let new_rooms_id: Vec<RoomId> = {
-            let new_left_rooms = response.rooms.leave.iter().filter_map(|(room_id, _)| {
-                if !rooms_map.contains_key(room_id) {
-                    Some(room_id)
-                } else {
-                    None
-                }
-            });
-
-            let new_joined_rooms = response.rooms.join.iter().filter_map(|(room_id, _)| {
-                if !rooms_map.contains_key(room_id) {
-                    Some(room_id)
-                } else {
-                    None
-                }
-            });
-            new_joined_rooms.chain(new_left_rooms).cloned().collect()
-        };
+        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();
 
@@ -417,6 +409,13 @@ impl Session {
             }
         }
 
+        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 {
@@ -467,7 +466,6 @@ impl Session {
                 );
             }
         }
-
         // TODO: handle StrippedStateEvents for invited rooms
     }
 }
diff --git a/src/session/room/room.rs b/src/session/room/room.rs
index f1782205..aa65b253 100644
--- a/src/session/room/room.rs
+++ b/src/session/room/room.rs
@@ -1,7 +1,7 @@
 use comrak::{markdown_to_html, ComrakOptions};
 use gettextrs::gettext;
 use gtk::{gio, glib, glib::clone, prelude::*, subclass::prelude::*};
-use log::{error, warn};
+use log::{debug, error, warn};
 use matrix_sdk::{
     events::{
         room::{
@@ -14,11 +14,12 @@ use matrix_sdk::{
         tag::TagName,
         AnyMessageEvent, AnyRoomEvent, AnyStateEvent, MessageEvent, StateEvent, Unsigned,
     },
-    identifiers::{EventId, UserId},
+    identifiers::{EventId, RoomId, UserId},
     room::Room as MatrixRoom,
     uuid::Uuid,
     RoomMember,
 };
+use std::cell::RefCell;
 use std::time::SystemTime;
 
 use crate::session::{
@@ -31,12 +32,12 @@ use crate::utils::do_async;
 mod imp {
     use super::*;
     use once_cell::sync::{Lazy, OnceCell};
-    use std::cell::{Cell, RefCell};
+    use std::cell::Cell;
     use std::collections::HashMap;
 
     #[derive(Debug, Default)]
     pub struct Room {
-        pub matrix_room: OnceCell<MatrixRoom>,
+        pub matrix_room: RefCell<Option<MatrixRoom>>,
         pub user: OnceCell<User>,
         pub name: RefCell<Option<String>>,
         pub avatar: RefCell<Option<gio::LoadableIcon>>,
@@ -63,7 +64,7 @@ mod imp {
                         "Matrix room",
                         "The underlaying matrix room.",
                         BoxedMatrixRoom::static_type(),
-                        glib::ParamFlags::WRITABLE | glib::ParamFlags::CONSTRUCT_ONLY,
+                        glib::ParamFlags::WRITABLE | glib::ParamFlags::CONSTRUCT,
                     ),
                     glib::ParamSpec::new_string(
                         "display-name",
@@ -152,7 +153,8 @@ mod imp {
         }
 
         fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
-            let matrix_room = self.matrix_room.get().unwrap();
+            let matrix_room = self.matrix_room.borrow();
+            let matrix_room = matrix_room.as_ref().unwrap();
             match pspec.name() {
                 "user" => obj.user().to_value(),
                 "display-name" => obj.display_name().to_value(),
@@ -192,21 +194,46 @@ impl Room {
             .expect("Failed to create Room")
     }
 
-    pub fn matrix_room(&self) -> &MatrixRoom {
+    pub fn matrix_room_id(&self) -> RoomId {
         let priv_ = imp::Room::from_instance(self);
-        priv_.matrix_room.get().unwrap()
+        priv_
+            .matrix_room
+            .borrow()
+            .as_ref()
+            .unwrap()
+            .room_id()
+            .clone()
     }
 
-    fn set_matrix_room(&self, matrix_room: MatrixRoom) {
+    fn matrix_room(&self) -> MatrixRoom {
         let priv_ = imp::Room::from_instance(self);
+        priv_.matrix_room.borrow().as_ref().unwrap().clone()
+    }
 
-        priv_.matrix_room.set(matrix_room).unwrap();
-        priv_.timeline.set(Timeline::new(self)).unwrap();
+    /// Set the new sdk room struct represented by this `Room`
+    pub fn set_matrix_room(&self, matrix_room: MatrixRoom) {
+        let priv_ = imp::Room::from_instance(self);
+
+        // Check if the previous type was different
+        if let Some(ref old_matrix_room) = *priv_.matrix_room.borrow() {
+            let changed = match old_matrix_room {
+                MatrixRoom::Joined(_) => !matches!(matrix_room, MatrixRoom::Joined(_)),
+                MatrixRoom::Left(_) => !matches!(matrix_room, MatrixRoom::Left(_)),
+                MatrixRoom::Invited(_) => !matches!(matrix_room, MatrixRoom::Invited(_)),
+            };
+            if changed {
+                debug!("The matrix room struct for `Room` changed");
+            } else {
+                return;
+            }
+        }
+
+        priv_.matrix_room.replace(Some(matrix_room));
+        // We create the timeline once
+        priv_.timeline.get_or_init(|| Timeline::new(self));
 
-        // We only need to load the room members once, because updates we will receive via state events
         self.load_members();
         self.load_display_name();
-        // TODO: change category when room type changes
         self.load_category();
     }
 
@@ -232,7 +259,7 @@ impl Room {
     }
 
     pub fn load_category(&self) {
-        let matrix_room = self.matrix_room().clone();
+        let matrix_room = self.matrix_room();
 
         match matrix_room {
             MatrixRoom::Joined(_) => {
@@ -273,7 +300,8 @@ impl Room {
         let priv_ = imp::Room::from_instance(&self);
         let count = priv_
             .matrix_room
-            .get()
+            .borrow()
+            .as_ref()
             .unwrap()
             .unread_notification_counts()
             .highlight_count;
@@ -303,8 +331,7 @@ impl Room {
     }
 
     fn load_display_name(&self) {
-        let priv_ = imp::Room::from_instance(&self);
-        let matrix_room = priv_.matrix_room.get().unwrap().clone();
+        let matrix_room = self.matrix_room();
         do_async(
             glib::PRIORITY_DEFAULT_IDLE,
             async move { matrix_room.display_name().await },
@@ -390,9 +417,7 @@ impl Room {
     }
 
     fn load_members(&self) {
-        let priv_ = imp::Room::from_instance(self);
-
-        let matrix_room = priv_.matrix_room.get().unwrap().clone();
+        let matrix_room = self.matrix_room();
         do_async(
             glib::PRIORITY_LOW,
             async move { matrix_room.active_members().await },
@@ -425,8 +450,7 @@ impl Room {
 
     pub fn send_text_message(&self, body: &str, markdown_enabled: bool) {
         use std::convert::TryFrom;
-        let priv_ = imp::Room::from_instance(self);
-        if let MatrixRoom::Joined(matrix_room) = priv_.matrix_room.get().unwrap().clone() {
+        if let MatrixRoom::Joined(matrix_room) = self.matrix_room() {
             let is_emote = body.starts_with("/me ");
 
             // Don't use markdown for emotes
@@ -482,7 +506,7 @@ impl Room {
         let priv_ = imp::Room::from_instance(self);
         let content = event.content();
 
-        if let MatrixRoom::Joined(matrix_room) = priv_.matrix_room.get().unwrap().clone() {
+        if let MatrixRoom::Joined(matrix_room) = self.matrix_room() {
             let pending_id = event.event_id().clone();
             priv_
                 .timeline


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