room: Always keep own member

This is useful to always have the proper room membership, among other
things
This commit is contained in:
Kévin Commaille 2023-12-21 23:42:43 +01:00
parent 7cd80c2b0c
commit ad9deced91
No known key found for this signature in database
GPG Key ID: 29A48C1F03620416
2 changed files with 51 additions and 3 deletions

View File

@ -15,7 +15,7 @@ use matrix_sdk::{
use tracing::error;
use super::{Event, Member, Membership, Room};
use crate::{spawn, spawn_tokio, utils::LoadingState};
use crate::{prelude::*, spawn, spawn_tokio, utils::LoadingState};
mod imp {
use std::cell::{Cell, RefCell};
@ -67,6 +67,12 @@ mod imp {
/// Set the room these members belong to.
fn set_room(&self, room: Room) {
let obj = self.obj();
let own_member = room.own_member();
self.members
.borrow_mut()
.insert(own_member.user_id(), own_member);
self.room.set(Some(&room));
obj.notify_room();
@ -90,7 +96,9 @@ glib::wrapper! {
impl MemberList {
pub fn new(room: &Room) -> Self {
glib::Object::builder().property("room", room).build()
glib::Object::builder::<Self>()
.property("room", room)
.build()
}
/// Set whether this list is being loaded.

View File

@ -72,7 +72,7 @@ mod imp {
/// The room API of the SDK.
pub matrix_room: OnceCell<MatrixRoom>,
/// The current session.
#[property(get, construct_only)]
#[property(get, set = Self::set_session, construct_only)]
pub session: glib::WeakRef<Session>,
/// The name that is set for this room.
///
@ -92,6 +92,9 @@ mod imp {
/// The timeline of this room.
#[property(get)]
pub timeline: OnceCell<Timeline>,
/// The member corresponding to our own user.
#[property(get)]
pub own_member: OnceCell<Member>,
/// The members of this room.
#[property(get)]
pub members: glib::WeakRef<MemberList>,
@ -179,6 +182,14 @@ mod imp {
impl SidebarItemImpl for Room {}
impl Room {
/// Set the current session
fn set_session(&self, session: Session) {
self.session.set(Some(&session));
let own_member = Member::new(&self.obj(), session.user_id());
self.own_member.set(own_member).unwrap();
}
/// The room API of the SDK.
pub fn matrix_room(&self) -> &MatrixRoom {
self.matrix_room.get().unwrap()
@ -293,6 +304,13 @@ impl Room {
})
);
spawn!(
glib::Priority::DEFAULT_IDLE,
clone!(@weak self as obj => async move {
obj.load_own_member().await;
})
);
spawn!(
glib::Priority::DEFAULT_IDLE,
clone!(@weak self as obj => async move {
@ -807,6 +825,24 @@ impl Room {
typing_list.update(members);
}
/// Create and load our own member from the store.
async fn load_own_member(&self) {
let own_member = self.own_member();
let user_id = own_member.user_id();
let matrix_room = self.matrix_room().clone();
let handle = spawn_tokio!(async move { matrix_room.get_member_no_sync(&user_id).await });
match handle.await.unwrap() {
Ok(Some(matrix_member)) => own_member.update_from_room_member(&matrix_member),
Ok(None) => {}
Err(error) => error!(
"Failed to load own member for room {}: {error}",
self.room_id()
),
}
}
/// The members of this room.
///
/// This creates the [`MemberList`] if no strong reference to it exists.
@ -984,6 +1020,8 @@ impl Room {
.iter()
.flat_map(|e| e.event.deserialize().ok())
.collect();
let own_member = self.own_member();
let own_user_id = own_member.user_id();
for event in events.iter() {
if let AnySyncTimelineEvent::State(state_event) = event {
@ -991,6 +1029,8 @@ impl Room {
AnySyncStateEvent::RoomMember(SyncStateEvent::Original(event)) => {
if let Some(members) = self.members() {
members.update_member_for_member_event(event);
} else if event.state_key == own_user_id {
own_member.update_from_member_event(event);
}
// If we show the other user's avatar or name, a member event might change