♻️ Rework the Room entity
This commit is contained in:
@@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
for member in &members {
|
||||||
|
if member.is_account_user {
|
||||||
|
account_member = Some(member);
|
||||||
|
} else {
|
||||||
|
other_members.push(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let other_avatars_futures =
|
||||||
|
join_all(other_members.iter().map(|member| member.get_avatar()));
|
||||||
|
|
||||||
|
let (other_avatars, account_avatar) = if let Some(account_member) =
|
||||||
|
account_member
|
||||||
|
{
|
||||||
|
join(other_avatars_futures, account_member.get_avatar()).await
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
join_all(other_members.iter().map(|member| member.get_avatar())).await,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let other_avatars: Vec<Vec<u8>> = other_avatars.into_iter().flatten().collect();
|
||||||
|
|
||||||
|
return Ok(Some(create_mozaik(
|
||||||
|
256,
|
||||||
|
256,
|
||||||
|
&other_avatars,
|
||||||
|
&account_avatar,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("err={}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
|
#[async_trait(?Send)]
|
||||||
|
impl RoomMessagingConsumerInterface for Room {
|
||||||
// pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
|
async fn on_invitation(&self) {
|
||||||
|
trace!("Room::on_invitation");
|
||||||
// #[derive(Clone)]
|
}
|
||||||
// pub struct Room {
|
async fn on_membership(&self, member: RoomMember) {
|
||||||
// // pub matrix_room: Arc<MatrixRoom>,
|
trace!("Room::on_membership({:?})", member);
|
||||||
// pub topic: Option<RefCell<String>>,
|
}
|
||||||
// pub members: HashMap<OwnedUserId, RoomMember>,
|
async fn on_new_topic(&self, topic: Option<String>) {
|
||||||
// pub is_direct: Option<bool>,
|
trace!("Room::on_new_topic({:?})", topic);
|
||||||
// // pub timeline: Arc<Timeline>,
|
}
|
||||||
// }
|
async fn on_new_name(&self, name: Option<String>) {
|
||||||
|
trace!("Room::on_new_name({:?})", name);
|
||||||
// impl Room {
|
}
|
||||||
// pub async fn new(
|
}
|
||||||
// matrix_room: Arc<MatrixRoom>,
|
|
||||||
// topic: Option<RefCell<String>>,
|
|
||||||
// is_direct: Option<bool>,
|
|
||||||
// ) -> Self {
|
|
||||||
// // TODO: Filter events
|
|
||||||
// // let timeline = Arc::new(matrix_room.timeline_builder().build().await.ok().unwrap());
|
|
||||||
// Self {
|
|
||||||
// matrix_room,
|
|
||||||
// topic,
|
|
||||||
// members: HashMap::new(),
|
|
||||||
// is_direct,
|
|
||||||
// // timeline,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self {
|
|
||||||
// let room_topic = matrix_room.topic().map(RefCell::new);
|
|
||||||
|
|
||||||
// Self::new(
|
|
||||||
// Arc::new(matrix_room.to_owned()),
|
|
||||||
// room_topic,
|
|
||||||
// matrix_room.is_direct().await.ok(),
|
|
||||||
// )
|
|
||||||
// .await
|
|
||||||
// // room.timeline.subscribe().await
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn name(&self) -> Option<String> {
|
|
||||||
// self.matrix_room.name()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn id(&self) -> OwnedRoomId {
|
|
||||||
// OwnedRoomId::from(self.matrix_room.room_id())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl PartialEq for Room {
|
|
||||||
// fn eq(&self, other: &Self) -> bool {
|
|
||||||
// // TODO: Look for a better way to compare Matrix rooms
|
|
||||||
// self.matrix_room.room_id() == other.matrix_room.room_id()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
Reference in New Issue
Block a user