From 5322e9bcdfd25cff6009b0120f03e50c532c42e6 Mon Sep 17 00:00:00 2001 From: Julian Sparber Date: Thu, 20 May 2021 14:05:48 +0200 Subject: [PATCH] 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 = { - 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, Vec) = 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, + pub matrix_room: RefCell>, pub user: OnceCell, pub name: RefCell>, pub avatar: RefCell>, @@ -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