♻️ Rework the Room entity

This commit is contained in:
2024-05-10 19:13:46 +02:00
parent 4f9e5c538e
commit 0190cf9165

View File

@@ -1,24 +1,52 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::{collections::HashMap, sync::Arc}; use std::collections::HashMap;
use std::rc::Rc;
use async_trait::async_trait;
use futures::future::{join, join_all};
use matrix_sdk::ruma::OwnedRoomId; use matrix_sdk::ruma::OwnedRoomId;
use matrix_sdk::{Room as MatrixRoom, RoomState as MatrixRoomState}; use matrix_sdk::RoomState as MatrixRoomState;
use tracing::error; use tracing::{debug, error, trace};
pub(crate) type RoomId = OwnedRoomId; use super::{
common::{Avatar, UserId},
messaging_interface::{RoomMessagingConsumerInterface, RoomMessagingProviderInterface},
room_member::RoomMember,
space::SpaceId,
store_interface::RoomStoreProviderInterface,
};
#[derive(Clone, Debug)] use crate::infrastructure::services::mozaik_builder::create_mozaik;
pub(crate) struct Room {
pub type RoomId = OwnedRoomId;
pub struct Room {
id: RoomId, id: RoomId,
name: Option<String>,
#[allow(dead_code)]
spaces: Vec<SpaceId>,
name: RefCell<Option<String>>,
topic: Option<String>, topic: Option<String>,
is_direct: Option<bool>, is_direct: Option<bool>,
state: Option<MatrixRoomState>, state: Option<MatrixRoomState>,
avatar: RefCell<Option<Avatar>>,
members: RefCell<HashMap<UserId, RoomMember>>,
messaging_provider: Option<Rc<dyn RoomMessagingProviderInterface>>,
store: RefCell<Option<Box<dyn RoomStoreProviderInterface>>>,
}
impl PartialEq for Room {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
} }
impl Room { impl Room {
fn new( pub fn new(
id: RoomId, id: RoomId,
spaces: Vec<SpaceId>,
name: Option<String>, name: Option<String>,
topic: Option<String>, topic: Option<String>,
is_direct: Option<bool>, is_direct: Option<bool>,
@@ -26,120 +54,156 @@ impl Room {
) -> Self { ) -> Self {
Self { Self {
id, id,
name,
spaces,
name: RefCell::new(name),
topic, topic,
is_direct, is_direct,
state, state,
avatar: RefCell::new(None),
members: RefCell::new(HashMap::new()),
messaging_provider: None,
store: RefCell::new(None),
} }
} }
// TODO: Use a factory instead... pub fn set_messaging_provider(
pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self { &mut self,
// let room_topic = matrix_room.topic().map(RefCell::new); messaging_provider: Rc<dyn RoomMessagingProviderInterface>,
) {
let id = RoomId::from(matrix_room.room_id()); self.messaging_provider = Some(messaging_provider);
let name = matrix_room.name();
let room_topic = matrix_room.topic();
let is_direct = match matrix_room.is_direct().await {
Ok(is_direct) => Some(is_direct),
Err(err) => {
error!("Unable to know if the room \"{id}\" is direct: {err}");
None
}
};
let state = Some(matrix_room.state());
Self::new(id, name, room_topic, is_direct, state)
// room.timeline.subscribe().await
// Arc::new(matrix_room.to_owned()),
} }
pub fn id(&self) -> &OwnedRoomId { pub fn set_store(&self, store: Option<Box<dyn RoomStoreProviderInterface>>) {
*self.store.borrow_mut() = store;
}
pub fn id(&self) -> &RoomId {
&self.id &self.id
} }
pub fn name(&self) -> &Option<String> { pub fn name(&self) -> Option<String> {
&self.name self.name.borrow().clone()
} }
#[allow(dead_code)]
pub fn topic(&self) -> &Option<String> { pub fn topic(&self) -> &Option<String> {
&self.topic &self.topic
} }
#[allow(dead_code)]
pub fn set_topic(&mut self, topic: Option<String>) { pub fn set_topic(&mut self, topic: Option<String>) {
self.topic = topic; self.topic = topic;
} }
#[allow(dead_code)]
pub fn is_direct(&self) -> &Option<bool> { pub fn is_direct(&self) -> &Option<bool> {
&self.is_direct &self.is_direct
} }
#[allow(dead_code)]
pub fn state(&self) -> &Option<MatrixRoomState> { pub fn state(&self) -> &Option<MatrixRoomState> {
&self.state &self.state
} }
#[allow(dead_code)]
pub fn is_invited(&self) -> Option<bool> { pub fn is_invited(&self) -> Option<bool> {
match self.state { self.state.map(|state| state == MatrixRoomState::Invited)
Some(state) => Some(state == MatrixRoomState::Invited), }
None => None,
#[allow(dead_code)]
fn add_member(&self, member: RoomMember) {
self.members.borrow_mut().insert(member.id.clone(), member);
}
pub async fn get_avatar(&self) -> Option<Avatar> {
if self.avatar.borrow().is_none() {
if let Some(requester) = &self.messaging_provider {
let resp = requester.get_avatar(&self.id).await;
if let Ok(avatar) = resp {
if let Some(avatar) = avatar {
return Some(avatar);
} else {
debug!("The room has no avatar... let's generate one");
match self.render_room_avatar_with_members().await {
Ok(avatar) => {
if let Some(avatar) = avatar {
return Some(avatar);
}
}
Err(err) => {
error!("err={}", err);
} }
} }
} }
} else {
error!("err={:?}", resp);
}
}
}
self.avatar.borrow().clone()
}
pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>; async fn render_room_avatar_with_members(&self) -> anyhow::Result<Option<Avatar>> {
if let Some(requester) = &self.messaging_provider {
match requester.get_members(&self.id).await {
Ok(members) => {
let mut account_member = None::<&RoomMember>;
let mut other_members = Vec::<&RoomMember>::new();
// pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>; for member in &members {
if member.is_account_user {
account_member = Some(member);
} else {
other_members.push(member);
}
}
// #[derive(Clone)] let other_avatars_futures =
// pub struct Room { join_all(other_members.iter().map(|member| member.get_avatar()));
// // pub matrix_room: Arc<MatrixRoom>,
// pub topic: Option<RefCell<String>>,
// pub members: HashMap<OwnedUserId, RoomMember>,
// pub is_direct: Option<bool>,
// // pub timeline: Arc<Timeline>,
// }
// impl Room { let (other_avatars, account_avatar) = if let Some(account_member) =
// pub async fn new( account_member
// matrix_room: Arc<MatrixRoom>, {
// topic: Option<RefCell<String>>, join(other_avatars_futures, account_member.get_avatar()).await
// is_direct: Option<bool>, } else {
// ) -> Self { (
// // TODO: Filter events join_all(other_members.iter().map(|member| member.get_avatar())).await,
// // let timeline = Arc::new(matrix_room.timeline_builder().build().await.ok().unwrap()); None,
// Self { )
// matrix_room, };
// topic,
// members: HashMap::new(),
// is_direct,
// // timeline,
// }
// }
// pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self { let other_avatars: Vec<Vec<u8>> = other_avatars.into_iter().flatten().collect();
// let room_topic = matrix_room.topic().map(RefCell::new);
// Self::new( return Ok(Some(create_mozaik(
// Arc::new(matrix_room.to_owned()), 256,
// room_topic, 256,
// matrix_room.is_direct().await.ok(), &other_avatars,
// ) &account_avatar,
// .await )));
// // room.timeline.subscribe().await }
// } Err(err) => {
error!("err={}", err);
}
}
}
Ok(None)
}
}
// pub fn name(&self) -> Option<String> { #[async_trait(?Send)]
// self.matrix_room.name() impl RoomMessagingConsumerInterface for Room {
// } async fn on_invitation(&self) {
trace!("Room::on_invitation");
// pub fn id(&self) -> OwnedRoomId { }
// OwnedRoomId::from(self.matrix_room.room_id()) async fn on_membership(&self, member: RoomMember) {
// } trace!("Room::on_membership({:?})", member);
// } }
async fn on_new_topic(&self, topic: Option<String>) {
// impl PartialEq for Room { trace!("Room::on_new_topic({:?})", topic);
// fn eq(&self, other: &Self) -> bool { }
// // TODO: Look for a better way to compare Matrix rooms async fn on_new_name(&self, name: Option<String>) {
// self.matrix_room.room_id() == other.matrix_room.room_id() trace!("Room::on_new_name({:?})", name);
// } }
// } }