♻️ Render Room avatar using the RoomMember ones, if not set
This commit is contained in:
@@ -40,7 +40,6 @@ pub async fn login(mut rx: UnboundedReceiver<bool>, session: &GlobalSignal<Sessi
|
|||||||
let requester = Rc::new(requester);
|
let requester = Rc::new(requester);
|
||||||
|
|
||||||
dioxus::prelude::spawn(async move {
|
dioxus::prelude::spawn(async move {
|
||||||
// ACCOUNT.write().set_messaging_provider(requester.clone());
|
|
||||||
ACCOUNT.write().set_messaging_provider(requester.clone());
|
ACCOUNT.write().set_messaging_provider(requester.clone());
|
||||||
|
|
||||||
let _ = requester
|
let _ = requester
|
||||||
|
@@ -61,8 +61,8 @@ pub trait SpaceMessagingProviderInterface {}
|
|||||||
pub trait MemberMessagingProviderInterface {
|
pub trait MemberMessagingProviderInterface {
|
||||||
async fn get_avatar(
|
async fn get_avatar(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
avatar_url: Option<AvatarUrl>,
|
||||||
user_id: &UserId,
|
room_id: RoomId,
|
||||||
avatar_url: &Option<AvatarUrl>,
|
user_id: UserId,
|
||||||
) -> anyhow::Result<Option<Avatar>>;
|
) -> anyhow::Result<Option<Avatar>>;
|
||||||
}
|
}
|
||||||
|
@@ -79,11 +79,12 @@ impl PartialEq for Room {
|
|||||||
impl Room {
|
impl Room {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: RoomId,
|
id: RoomId,
|
||||||
spaces: Vec<SpaceId>,
|
// TODO: move space at the end of the list of params
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
topic: Option<String>,
|
topic: Option<String>,
|
||||||
is_direct: Option<bool>,
|
is_direct: Option<bool>,
|
||||||
state: Option<MatrixRoomState>,
|
state: Option<MatrixRoomState>,
|
||||||
|
spaces: Vec<SpaceId>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
@@ -93,10 +94,8 @@ impl Room {
|
|||||||
is_direct,
|
is_direct,
|
||||||
state,
|
state,
|
||||||
avatar: RefCell::new(None),
|
avatar: RefCell::new(None),
|
||||||
|
|
||||||
invitations: RefCell::new(HashMap::new()),
|
invitations: RefCell::new(HashMap::new()),
|
||||||
members: RefCell::new(HashMap::new()),
|
members: RefCell::new(HashMap::new()),
|
||||||
|
|
||||||
spaces,
|
spaces,
|
||||||
|
|
||||||
messaging_provider: None,
|
messaging_provider: None,
|
||||||
@@ -133,11 +132,6 @@ impl Room {
|
|||||||
self.topic = topic;
|
self.topic = topic;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn is_direct(&self) -> &Option<bool> {
|
|
||||||
&self.is_direct
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn state(&self) -> &Option<MatrixRoomState> {
|
pub fn state(&self) -> &Option<MatrixRoomState> {
|
||||||
&self.state
|
&self.state
|
||||||
@@ -160,6 +154,29 @@ impl Room {
|
|||||||
store.on_invitation(invitation);
|
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> {
|
pub async fn get_avatar(&self) -> Option<Avatar> {
|
||||||
@@ -171,7 +188,7 @@ impl Room {
|
|||||||
return Some(avatar);
|
return Some(avatar);
|
||||||
} else {
|
} else {
|
||||||
debug!("The room has no avatar... let's generate one");
|
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) => {
|
Ok(avatar) => {
|
||||||
if let Some(avatar) = avatar {
|
if let Some(avatar) = avatar {
|
||||||
return Some(avatar);
|
return Some(avatar);
|
||||||
@@ -190,50 +207,42 @@ impl Room {
|
|||||||
self.avatar.borrow().clone()
|
self.avatar.borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render_room_avatar_with_members(&self) -> anyhow::Result<Option<Avatar>> {
|
#[instrument(name = "Room", skip_all)]
|
||||||
if let Some(requester) = &self.messaging_provider {
|
async fn gen_room_avatar_with_members(&self) -> anyhow::Result<Option<Avatar>> {
|
||||||
match requester.get_members(&self.id).await {
|
let mut account_member = None::<&RoomMember>;
|
||||||
Ok(members) => {
|
let mut other_members = Vec::<&RoomMember>::new();
|
||||||
let mut account_member = None::<&RoomMember>;
|
|
||||||
let mut other_members = Vec::<&RoomMember>::new();
|
|
||||||
|
|
||||||
for member in &members {
|
let members = self.members.borrow();
|
||||||
if member.is_account_user() {
|
for member in members.values() {
|
||||||
account_member = Some(member);
|
if member.is_account_user() {
|
||||||
} else {
|
account_member = Some(member);
|
||||||
other_members.push(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)
|
|
||||||
|
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)]
|
#[instrument(name = "Room", skip_all)]
|
||||||
async fn on_new_avatar(&self, avatar: Option<Avatar>) {
|
async fn on_new_avatar(&self, avatar: Option<Avatar>) {
|
||||||
trace!("on_new_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()
|
self.name.borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn avatar(&self) -> Option<Avatar> {
|
||||||
|
self.get_avatar().await
|
||||||
|
}
|
||||||
|
|
||||||
fn spaces(&self) -> &Vec<SpaceId> {
|
fn spaces(&self) -> &Vec<SpaceId> {
|
||||||
&self.spaces
|
&self.spaces
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use matrix_sdk::{room::RoomMember as MatrixRoomMember, ruma::OwnedRoomId};
|
use matrix_sdk::ruma::OwnedMxcUri;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -13,9 +13,14 @@ use super::{
|
|||||||
room::RoomId,
|
room::RoomId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type AvatarUrl = OwnedMxcUri;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RoomMember {
|
pub struct RoomMember {
|
||||||
id: UserId,
|
id: UserId,
|
||||||
|
|
||||||
|
display_name: Option<String>,
|
||||||
|
avatar_url: Option<AvatarUrl>,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
is_account_user: bool,
|
is_account_user: bool,
|
||||||
|
|
||||||
@@ -26,14 +31,18 @@ pub struct RoomMember {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RoomMember {
|
impl RoomMember {
|
||||||
fn new(
|
pub fn new(
|
||||||
id: UserId,
|
id: UserId,
|
||||||
|
display_name: Option<String>,
|
||||||
|
avatar_url: Option<AvatarUrl>,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
is_account_user: bool,
|
is_account_user: bool,
|
||||||
messaging_provider: Rc<dyn MemberMessagingProviderInterface>,
|
messaging_provider: Rc<dyn MemberMessagingProviderInterface>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
|
display_name,
|
||||||
|
avatar_url,
|
||||||
room_id,
|
room_id,
|
||||||
is_account_user,
|
is_account_user,
|
||||||
avatar: RefCell::new(None),
|
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 {
|
pub fn id(&self) -> &UserId {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn display_name(&self) -> &Option<String> {
|
||||||
|
&self.display_name
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn room_id(&self) -> &RoomId {
|
pub fn room_id(&self) -> &RoomId {
|
||||||
&self.room_id
|
&self.room_id
|
||||||
@@ -71,7 +70,11 @@ impl RoomMember {
|
|||||||
pub async fn get_avatar(&self) -> Option<Avatar> {
|
pub async fn get_avatar(&self) -> Option<Avatar> {
|
||||||
match self
|
match self
|
||||||
.messaging_provider
|
.messaging_provider
|
||||||
.get_avatar(&self.room_id, &self.id)
|
.get_avatar(
|
||||||
|
self.avatar_url.clone(),
|
||||||
|
self.room_id.clone(),
|
||||||
|
self.id.clone(),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(avatar) => avatar,
|
Ok(avatar) => avatar,
|
||||||
|
@@ -723,41 +723,39 @@ impl Client {
|
|||||||
|
|
||||||
async fn get_room_member_avatar(
|
async fn get_room_member_avatar(
|
||||||
&self,
|
&self,
|
||||||
|
avatar_url: &Option<OwnedMxcUri>,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
avatar_url: &Option<OwnedMxcUri>,
|
|
||||||
) -> anyhow::Result<Option<Vec<u8>>> {
|
) -> anyhow::Result<Option<Vec<u8>>> {
|
||||||
let client = self.client.as_ref().unwrap();
|
let client = self.client.as_ref().unwrap();
|
||||||
|
|
||||||
if let Some(room) = client.get_room(room_id) {
|
if let Some(room) = client.get_room(room_id) {
|
||||||
// TODO: Check if we can get member before fetching the data and received an error...
|
match avatar_url {
|
||||||
|
Some(avatar_url) => {
|
||||||
match room.get_member(user_id).await {
|
let thumbnail = self.get_thumbnail(avatar_url.clone()).await;
|
||||||
Ok(room_member) => {
|
return Ok(Some(thumbnail?));
|
||||||
if let Some(room_member) = room_member {
|
|
||||||
let res = match room_member
|
|
||||||
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
|
||||||
method: Method::Scale,
|
|
||||||
width: uint!(256),
|
|
||||||
height: uint!(256),
|
|
||||||
}))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(avatar) => Ok(avatar),
|
|
||||||
Err(err) => Err(err.into()),
|
|
||||||
};
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
None => match room.get_member(user_id).await {
|
||||||
warn!("Unable to get room member {user_id}: {err}");
|
Ok(room_member) => {
|
||||||
if let Some(avatar_url) = avatar_url {
|
if let Some(room_member) = room_member {
|
||||||
let thumbnail = self.get_thumbnail(avatar_url.clone()).await;
|
let res = match room_member
|
||||||
return Ok(Some(thumbnail?));
|
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
|
||||||
} else {
|
method: Method::Scale,
|
||||||
debug!("No avatar url set for the {room_id} room");
|
width: uint!(256),
|
||||||
|
height: uint!(256),
|
||||||
|
}))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(avatar) => Ok(avatar),
|
||||||
|
Err(err) => Err(err.into()),
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(err) => {
|
||||||
|
warn!("Unable to get room member {user_id}: {err}");
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -799,10 +797,10 @@ impl Client {
|
|||||||
WorkerTask::GetRoomAvatar(id, reply) => {
|
WorkerTask::GetRoomAvatar(id, reply) => {
|
||||||
reply.send(self.get_room_avatar(&id).await).await;
|
reply.send(self.get_room_avatar(&id).await).await;
|
||||||
}
|
}
|
||||||
WorkerTask::GetRoomMemberAvatar(room_id, user_id, avatar_url, reply) => {
|
WorkerTask::GetRoomMemberAvatar(avatar_url, room_id, user_id, reply) => {
|
||||||
reply
|
reply
|
||||||
.send(
|
.send(
|
||||||
self.get_room_member_avatar(&room_id, &user_id, &avatar_url)
|
self.get_room_member_avatar(&avatar_url, &room_id, &user_id)
|
||||||
.await,
|
.await,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@@ -242,7 +242,7 @@ impl AccountMessagingProviderInterface for Requester {
|
|||||||
new_room_tx,
|
new_room_tx,
|
||||||
span
|
span
|
||||||
) => {
|
) => {
|
||||||
let mut room = Room::new(id, spaces, name, topic, is_direct, Some(state));
|
let mut room = Room::new(id, name, topic, is_direct, Some(state), spaces);
|
||||||
let room_id = room.id().clone();
|
let room_id = room.id().clone();
|
||||||
|
|
||||||
room.set_messaging_provider(client.clone());
|
room.set_messaging_provider(client.clone());
|
||||||
@@ -371,16 +371,16 @@ impl SpaceMessagingProviderInterface for Requester {}
|
|||||||
impl MemberMessagingProviderInterface for Requester {
|
impl MemberMessagingProviderInterface for Requester {
|
||||||
async fn get_avatar(
|
async fn get_avatar(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
avatar_url: Option<AvatarUrl>,
|
||||||
user_id: &UserId,
|
room_id: RoomId,
|
||||||
avatar_url: &Option<AvatarUrl>,
|
user_id: UserId,
|
||||||
) -> anyhow::Result<Option<Avatar>> {
|
) -> anyhow::Result<Option<Avatar>> {
|
||||||
request_to_worker!(
|
request_to_worker!(
|
||||||
self,
|
self,
|
||||||
WorkerTask::GetRoomMemberAvatar,
|
WorkerTask::GetRoomMemberAvatar,
|
||||||
room_id.clone(),
|
avatar_url,
|
||||||
user_id.clone(),
|
room_id,
|
||||||
avatar_url.clone()
|
user_id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,9 +18,9 @@ pub enum WorkerTask {
|
|||||||
|
|
||||||
GetRoomAvatar(OwnedRoomId, Sender<anyhow::Result<Option<Vec<u8>>>>),
|
GetRoomAvatar(OwnedRoomId, Sender<anyhow::Result<Option<Vec<u8>>>>),
|
||||||
GetRoomMemberAvatar(
|
GetRoomMemberAvatar(
|
||||||
|
Option<OwnedMxcUri>,
|
||||||
OwnedRoomId,
|
OwnedRoomId,
|
||||||
OwnedUserId,
|
OwnedUserId,
|
||||||
Option<OwnedMxcUri>,
|
|
||||||
Sender<anyhow::Result<Option<Vec<u8>>>>,
|
Sender<anyhow::Result<Option<Vec<u8>>>>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -57,9 +57,9 @@ impl Debug for WorkerTask {
|
|||||||
.finish(),
|
.finish(),
|
||||||
WorkerTask::GetRoomMemberAvatar(room_id, user_id, avatar_url, _) => f
|
WorkerTask::GetRoomMemberAvatar(room_id, user_id, avatar_url, _) => f
|
||||||
.debug_tuple("WorkerTask::GetRoomMemberAvatar")
|
.debug_tuple("WorkerTask::GetRoomMemberAvatar")
|
||||||
|
.field(avatar_url)
|
||||||
.field(room_id)
|
.field(room_id)
|
||||||
.field(user_id)
|
.field(user_id)
|
||||||
.field(avatar_url)
|
|
||||||
.finish(),
|
.finish(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user