♻️ Render Room avatar using the RoomMember ones, if not set

This commit is contained in:
2024-05-22 16:42:20 +02:00
parent 35e191eb62
commit 19d64d7ac5
7 changed files with 126 additions and 109 deletions

View File

@@ -61,8 +61,8 @@ pub trait SpaceMessagingProviderInterface {}
pub trait MemberMessagingProviderInterface {
async fn get_avatar(
&self,
room_id: &RoomId,
user_id: &UserId,
avatar_url: &Option<AvatarUrl>,
avatar_url: Option<AvatarUrl>,
room_id: RoomId,
user_id: UserId,
) -> anyhow::Result<Option<Avatar>>;
}

View File

@@ -79,11 +79,12 @@ impl PartialEq for Room {
impl Room {
pub fn new(
id: RoomId,
spaces: Vec<SpaceId>,
// TODO: move space at the end of the list of params
name: Option<String>,
topic: Option<String>,
is_direct: Option<bool>,
state: Option<MatrixRoomState>,
spaces: Vec<SpaceId>,
) -> Self {
Self {
id,
@@ -93,10 +94,8 @@ impl Room {
is_direct,
state,
avatar: RefCell::new(None),
invitations: RefCell::new(HashMap::new()),
members: RefCell::new(HashMap::new()),
spaces,
messaging_provider: None,
@@ -133,11 +132,6 @@ impl Room {
self.topic = topic;
}
#[allow(dead_code)]
pub fn is_direct(&self) -> &Option<bool> {
&self.is_direct
}
#[allow(dead_code)]
pub fn state(&self) -> &Option<MatrixRoomState> {
&self.state
@@ -160,6 +154,29 @@ impl Room {
store.on_invitation(invitation);
}
}
#[instrument(name = "Room", skip_all)]
fn add_member(&self, member: RoomMember) {
let mut members = self.members.borrow_mut();
members.insert(member.id().clone(), member.clone());
// USe the member display name to name the room if it's direct and has no name set.
if self.name.borrow().is_none() && members.len() == 1 {
if let Some(member_display_name) = member.display_name() {
let name = Some(member_display_name.clone());
self.name.borrow_mut().clone_from(&name);
if let Some(store) = self.store.borrow().as_ref() {
store.on_new_name(name);
}
}
}
if let Some(store) = self.store.borrow().as_ref() {
store.on_new_member(member);
}
}
pub async fn get_avatar(&self) -> Option<Avatar> {
@@ -171,7 +188,7 @@ impl Room {
return Some(avatar);
} else {
debug!("The room has no avatar... let's generate one");
match self.render_room_avatar_with_members().await {
match self.gen_room_avatar_with_members().await {
Ok(avatar) => {
if let Some(avatar) = avatar {
return Some(avatar);
@@ -190,50 +207,42 @@ impl Room {
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();
#[instrument(name = "Room", skip_all)]
async fn gen_room_avatar_with_members(&self) -> anyhow::Result<Option<Avatar>> {
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);
}
let members = self.members.borrow();
for member in members.values() {
if member.is_account_user() {
account_member = Some(member);
} else {
other_members.push(member);
}
}
Ok(None)
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();
if account_avatar.is_some() || !other_avatars.is_empty() {
let _guard = debug_span!("AvatarRendering").entered();
Ok(Some(
create_mozaik(256, 256, other_avatars, account_avatar).await,
))
} else {
Ok(None)
}
}
}
@@ -277,6 +286,10 @@ impl RoomMessagingConsumerInterface for Room {
#[instrument(name = "Room", skip_all)]
async fn on_new_avatar(&self, avatar: Option<Avatar>) {
trace!("on_new_avatar");
self.avatar.borrow_mut().clone_from(&avatar);
if let Some(store) = self.store.borrow().as_ref() {
store.on_new_avatar(avatar);
}
}
}
@@ -294,6 +307,10 @@ impl RoomStoreConsumerInterface for Room {
self.name.borrow().clone()
}
async fn avatar(&self) -> Option<Avatar> {
self.get_avatar().await
}
fn spaces(&self) -> &Vec<SpaceId> {
&self.spaces
}

View File

@@ -4,7 +4,7 @@ use std::{
rc::Rc,
};
use matrix_sdk::{room::RoomMember as MatrixRoomMember, ruma::OwnedRoomId};
use matrix_sdk::ruma::OwnedMxcUri;
use tracing::error;
use super::{
@@ -13,9 +13,14 @@ use super::{
room::RoomId,
};
pub type AvatarUrl = OwnedMxcUri;
#[derive(Clone)]
pub struct RoomMember {
id: UserId,
display_name: Option<String>,
avatar_url: Option<AvatarUrl>,
room_id: RoomId,
is_account_user: bool,
@@ -26,14 +31,18 @@ pub struct RoomMember {
}
impl RoomMember {
fn new(
pub fn new(
id: UserId,
display_name: Option<String>,
avatar_url: Option<AvatarUrl>,
room_id: RoomId,
is_account_user: bool,
messaging_provider: Rc<dyn MemberMessagingProviderInterface>,
) -> Self {
Self {
id,
display_name,
avatar_url,
room_id,
is_account_user,
avatar: RefCell::new(None),
@@ -41,24 +50,14 @@ impl RoomMember {
}
}
// TODO: Use a factory instead...
pub async fn from_matrix(
matrix_room_member: &MatrixRoomMember,
room_id: &OwnedRoomId,
messaging_provider: Rc<dyn MemberMessagingProviderInterface>,
) -> Self {
Self::new(
UserId::from(matrix_room_member.user_id()),
room_id.clone(),
matrix_room_member.is_account_user(),
messaging_provider,
)
}
pub fn id(&self) -> &UserId {
&self.id
}
pub fn display_name(&self) -> &Option<String> {
&self.display_name
}
#[allow(dead_code)]
pub fn room_id(&self) -> &RoomId {
&self.room_id
@@ -71,7 +70,11 @@ impl RoomMember {
pub async fn get_avatar(&self) -> Option<Avatar> {
match self
.messaging_provider
.get_avatar(&self.room_id, &self.id)
.get_avatar(
self.avatar_url.clone(),
self.room_id.clone(),
self.id.clone(),
)
.await
{
Ok(avatar) => avatar,