🚧 Add Avatar management and refresh the Matrix client part

This commit is contained in:
2024-05-17 22:41:35 +02:00
parent 0b898dce52
commit fdae149c4a
5 changed files with 399 additions and 311 deletions

View File

@@ -5,8 +5,8 @@ use tokio::sync::broadcast::Receiver;
use super::{ use super::{
common::{Avatar, UserId}, common::{Avatar, UserId},
room_member::RoomMember,
room::{Invitation, Room, RoomId}, room::{Invitation, Room, RoomId},
room_member::{AvatarUrl, RoomMember},
space::Space, space::Space,
}; };
use crate::infrastructure::messaging::matrix::account_event::AccountEvent; use crate::infrastructure::messaging::matrix::account_event::AccountEvent;
@@ -35,6 +35,7 @@ pub trait RoomMessagingConsumerInterface {
async fn on_new_topic(&self, _topic: Option<String>) {} async fn on_new_topic(&self, _topic: Option<String>) {}
async fn on_new_name(&self, _name: Option<String>) {} async fn on_new_name(&self, _name: Option<String>) {}
async fn on_new_avatar(&self, _url: Option<Avatar>) {}
#[allow(dead_code)] #[allow(dead_code)]
async fn on_membership(&self, _member: RoomMember) {} async fn on_membership(&self, _member: RoomMember) {}
@@ -63,5 +64,6 @@ pub trait MemberMessagingProviderInterface {
&self, &self,
room_id: &RoomId, room_id: &RoomId,
user_id: &UserId, user_id: &UserId,
avatar_url: &Option<AvatarUrl>,
) -> anyhow::Result<Option<Avatar>>; ) -> anyhow::Result<Option<Avatar>>;
} }

View File

@@ -9,20 +9,22 @@ use dioxus::prelude::Task;
use matrix_sdk::{ use matrix_sdk::{
config::SyncSettings, config::SyncSettings,
event_handler::Ctx, event_handler::Ctx,
media::{MediaFormat, MediaThumbnailSize}, media::{MediaFormat, MediaRequest, MediaThumbnailSize},
room::{Room, RoomMember}, room::{ParentSpace, Room, RoomMember},
ruma::{ ruma::{
api::client::media::get_content_thumbnail::v3::Method, api::client::media::get_content_thumbnail::v3::Method,
events::{ events::{
room::{ room::{
member::{ avatar::{RoomAvatarEventContent, StrippedRoomAvatarEvent},
OriginalSyncRoomMemberEvent, RoomMemberEventContent, StrippedRoomMemberEvent, create::{RoomCreateEventContent, StrippedRoomCreateEvent},
}, member::{MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent},
topic::RoomTopicEventContent, name::{RoomNameEventContent, StrippedRoomNameEvent},
topic::{RoomTopicEventContent, StrippedRoomTopicEvent},
MediaSource,
}, },
SyncStateEvent, SyncStateEvent,
}, },
uint, OwnedRoomId, RoomId, UserId, uint, OwnedMxcUri, OwnedRoomId, OwnedUserId, RoomId, UserId,
}, },
Client as MatrixClient, RoomMemberships, RoomState, Client as MatrixClient, RoomMemberships, RoomState,
}; };
@@ -68,21 +70,29 @@ impl Senders {
room_senders.contains_key(room_id) room_senders.contains_key(room_id)
} }
fn send(&self, room_id: &RoomId, event: RoomEvent) -> Result<usize, SendError<RoomEvent>> { fn send(&self, room_id: &RoomId, event: RoomEvent) -> Result<(), SendError<RoomEvent>> {
let room_senders = self.room_events_senders.lock().unwrap(); let room_senders = self.room_events_senders.lock().unwrap();
if let Some(room_sender) = room_senders.get(room_id) { if let Some(room_sender) = room_senders.get(room_id) {
room_sender.send(event) if let Err(err) = room_sender.send(event) {
} else { error!("Unable to send event to the {room_id} room: {err}");
error!("No sender found for \"{}\" room id", room_id); return Err(err);
Ok(0)
} }
} else {
warn!("No sender found for {room_id} room");
// TODO: Return error
}
Ok(())
} }
fn add_room(&self, room_id: &OwnedRoomId) -> Option<RoomEventsReceiver> { fn add_room(&self, room_id: &OwnedRoomId) -> Option<RoomEventsReceiver> {
let mut senders = self.room_events_senders.lock().unwrap(); let mut senders = self.room_events_senders.lock().unwrap();
if !senders.contains_key(room_id) { if !senders.contains_key(room_id) {
let (room_sender, room_receiver) = broadcast::channel(32); let (room_sender, room_receiver) = broadcast::channel(32);
senders.insert(room_id.clone(), room_sender); senders.insert(room_id.clone(), room_sender);
debug!("Create sender for {room_id} room");
Some(RoomEventsReceiver::new(room_receiver)) Some(RoomEventsReceiver::new(room_receiver))
} else { } else {
None None
@@ -109,45 +119,43 @@ impl Client {
async fn create_space( async fn create_space(
senders: &Ctx<Senders>, senders: &Ctx<Senders>,
room_id: OwnedRoomId, room_id: &OwnedRoomId,
room: Option<&Room>, room: Option<&Room>,
) -> anyhow::Result<(), SendError<AccountEvent>> { ) -> anyhow::Result<(), SendError<AccountEvent>> {
if let Some(receiver) = senders.add_room(&room_id) {
let mut name = None; let mut name = None;
let mut topic = None; let mut topic = None;
if let Some(room) = room { if let Some(room) = room {
name = room.name(); name = room.name();
topic = room.topic(); topic = room.topic();
} }
if let Some(receiver) = senders.add_room(&room_id) {
let (reply, mut response) = oneshot::<bool>(); let (reply, mut response) = oneshot::<bool>();
let event = AccountEvent::NewSpace(room_id.clone(), name, topic, receiver, reply); let event = AccountEvent::NewSpace(
room_id.clone(),
name.clone(),
topic.clone(),
receiver,
reply,
);
if let Err(err) = senders.account_events_sender.send(event) { if let Err(err) = senders.account_events_sender.send(event) {
error!(
"Unable to publish the new room with \"{}\" id: {}",
room_id, err
);
return Err(err); return Err(err);
} }
// We're expecting a response indicating that the client is able to compute the next RoomEvent // We're expecting a response indicating that the client is able to compute the next RoomEvent
response.recv().await; response.recv().await;
} else {
let events = vec![RoomEvent::NewTopic(topic), RoomEvent::NewName(name)]; let events = vec![RoomEvent::NewTopic(topic), RoomEvent::NewName(name)];
for event in events { for event in events {
if let Err(err) = senders.send(&room_id, event.clone()) { if let Err(_err) = senders.send(&room_id, event.clone()) {
error!( // TODO: Return an error
"Unable to publish the {:?} event to the \"{}\" room: {}",
event, room_id, err
);
// return Err(err);
} }
} }
} }
Ok(()) Ok(())
} }
@@ -163,24 +171,25 @@ impl Client {
let is_direct = match room.is_direct().await { let is_direct = match room.is_direct().await {
Ok(is_direct) => Some(is_direct), Ok(is_direct) => Some(is_direct),
Err(err) => { Err(err) => {
error!("Unable to know if the room \"{room_id}\" is direct: {err}"); error!("Unable to know if the {room_id} room is direct: {err}");
None None
} }
}; };
let mut parents = vec![]; let mut parents = vec![];
// TODO: Remove unwrap
let mut spaces = room.parent_spaces().await.unwrap(); if let Ok(mut spaces) = room.parent_spaces().await {
while let Some(parent) = spaces.next().await { while let Some(parent) = spaces.next().await {
match parent { match parent {
Ok(parent) => match parent { Ok(parent) => match parent {
matrix_sdk::room::ParentSpace::Reciprocal(parent) => { ParentSpace::Reciprocal(parent) => {
parents.push(parent.room_id().to_owned()); parents.push(parent.room_id().to_owned());
} }
_ => todo!(), _ => todo!(),
}, },
Err(err) => { Err(err) => {
error!("{}", err); error!("{err}");
}
} }
} }
} }
@@ -197,11 +206,6 @@ impl Client {
); );
if let Err(err) = senders.account_events_sender.send(event) { if let Err(err) = senders.account_events_sender.send(event) {
error!(
"Unable to publish the new room with \"{}\" id: {}",
room.room_id(),
err
);
return Err(err); return Err(err);
} }
@@ -218,17 +222,15 @@ impl Client {
let room_id = room.room_id().to_owned(); let room_id = room.room_id().to_owned();
if room.is_space() { if room.is_space() {
Self::create_space(senders, room_id, Some(room)).await Self::create_space(senders, &room_id, Some(room)).await
} else { } else {
let ret = Self::create_room(senders, room).await;
let mut parents = vec![]; let mut parents = vec![];
// TODO: Remove unwrap
let mut spaces = room.parent_spaces().await.unwrap(); if let Ok(mut spaces) = room.parent_spaces().await {
while let Some(parent) = spaces.next().await { while let Some(parent) = spaces.next().await {
match parent { match parent {
Ok(parent) => match parent { Ok(parent) => match parent {
matrix_sdk::room::ParentSpace::Reciprocal(parent) => { ParentSpace::Reciprocal(parent) => {
parents.push(parent.room_id().to_owned()); parents.push(parent.room_id().to_owned());
} }
_ => { _ => {
@@ -239,233 +241,263 @@ impl Client {
} }
}, },
Err(err) => { Err(err) => {
error!("{}", err); error!("{err}");
}
} }
} }
} }
error!("parents={:?}", &parents);
for parent in parents { for parent in parents {
// Create a minimal space to make the relation consistent... its content will be sync later. // Create a minimal space to make the relation consistent... its content will be sync later.
if !senders.contains(&parent) { if !senders.contains(&parent) {
let _ = Self::create_space(senders, parent.clone(), None).await; let _ = Self::create_space(senders, &parent, None).await;
} }
let event = RoomEvent::NewChild(room_id.clone()); let event = RoomEvent::NewChild(room_id.clone());
if let Err(err) = senders.send(parent.as_ref(), event.clone()) { if let Err(_err) = senders.send(&parent, event) {
error!( // TODO: Return an error
"Unable to send the {:?} event to the \"{}\": {:?}", }
event, parent, err }
Self::create_room(senders, room).await
}
}
async fn on_stripped_room_create_event(
_ev: StrippedRoomCreateEvent,
room: Room,
senders: Ctx<Senders>,
) {
let _ = Self::add_room(&senders, &room).await;
}
// SyncStateEvent: A possibly-redacted state event without a room_id.
async fn on_sync_room_create_event(
_ev: SyncStateEvent<RoomCreateEventContent>,
room: Room,
senders: Ctx<Senders>,
) {
let _ = Self::add_room(&senders, &room).await;
}
fn on_invite_room_member_event(
user_id: OwnedUserId,
inviter_id: OwnedUserId,
room: &Room,
matrix_client: &MatrixClient,
senders: &Ctx<Senders>,
) {
if let Some(client_user_id) = matrix_client.user_id() {
let is_account_user = user_id == client_user_id;
let room_id = room.room_id();
debug!(
"{} (account user: {is_account_user}) invited by {} to join the {} room",
&user_id, &inviter_id, &room_id
); );
let event = RoomEvent::Invitation(user_id, inviter_id, is_account_user);
if let Err(_err) = senders.send(room_id, event) {
// TODO: Return an error
}
} }
} }
ret fn on_join_room_member_event(
user_id: OwnedUserId,
displayname: Option<String>,
avatar_url: Option<OwnedMxcUri>,
room: &Room,
matrix_client: &MatrixClient,
senders: &Ctx<Senders>,
) {
if let Some(client_user_id) = matrix_client.user_id() {
let is_account_user = user_id == client_user_id;
let room_id = room.room_id();
error!("{} has joined the {} room", &user_id, &room_id);
let event = RoomEvent::Join(user_id, displayname, avatar_url, is_account_user);
if let Err(_err) = senders.send(room_id, event) {
// TODO: Return an error
}
} }
} }
// async fn on_sync_typing_event(_ev: SyncTypingEvent, room: Room) { // This function is called on each m.room.member event for an invited room preview (room not already joined).
// debug!("== on_sync_typing_event =="); // async fn on_stripped_room_member_event(
// let room_id = room.room_id().to_owned();
// dbg!(room_id);
// }
// async fn on_presence_event(_ev: PresenceEvent) {
// debug!("== on_presence_event ==");
// dbg!(_ev);
// }
// async fn on_sync_state_event(ev: SyncStateEvent<RoomNameEventContent>, _room: Room) {
// error!("== on_sync_state_event ==");
// if let SyncStateEvent::Original(ev) = ev {
// dbg!(ev);
// }
// }
// async fn on_original_sync_room_message_event(
// ev: OriginalSyncRoomMessageEvent,
// _room: Room,
// _senders: Ctx<Senders>,
// ) {
// error!("== on_original_sync_room_message_event ==");
// error!("ev={:?}", ev.content);
async fn on_stripped_room_member_event( async fn on_stripped_room_member_event(
ev: StrippedRoomMemberEvent, ev: StrippedRoomMemberEvent,
matrix_client: MatrixClient, matrix_client: MatrixClient,
room: Room, room: Room,
senders: Ctx<Senders>, senders: Ctx<Senders>,
) { ) {
error!("*** on_stripped_room_member_event ***"); match room.state() {
// error!("ev={:?}", ev); RoomState::Invited => {
let user_id = &ev.state_key;
if ev.state_key == matrix_client.user_id().unwrap() match ev.content.membership {
&& room.state() == RoomState::Invited MembershipState::Invite => Self::on_invite_room_member_event(
&& Self::add_room(&senders, &room).await.is_ok() user_id.clone(),
{ ev.sender,
&room,
&matrix_client,
&senders,
),
MembershipState::Join => Self::on_join_room_member_event(
ev.sender,
ev.content.displayname,
ev.content.avatar_url,
&room,
&matrix_client,
&senders,
),
_ => {
error!("TODO: {:?}", ev);
}
}
}
_ => {
error!("TODO: {:?}", ev);
}
}
}
// SyncStateEvent: A possibly-redacted state event without a room_id.
// RoomMemberEventContent: The content of an m.room.member event.
async fn on_sync_room_member_event(
ev: SyncStateEvent<RoomMemberEventContent>,
matrix_client: MatrixClient,
room: Room,
senders: Ctx<Senders>,
) {
if let SyncStateEvent::Original(ev) = ev {
match ev.content.membership {
MembershipState::Invite => {
let invitee_id = ev.state_key;
Self::on_invite_room_member_event(
invitee_id,
ev.sender,
&room,
&matrix_client,
&senders,
)
// .await
}
MembershipState::Join => {
Self::on_join_room_member_event(
ev.sender,
ev.content.displayname,
ev.content.avatar_url,
&room,
&matrix_client,
&senders,
)
// .await
}
_ => error!("TODO"),
}
}
}
async fn on_room_avatar_event(room: &Room, senders: &Ctx<Senders>) {
let room_id = room.room_id(); let room_id = room.room_id();
let avatar = match room
let event = RoomEvent::Invitation(); .avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
if let Err(err) = senders.send(room_id, event) { method: Method::Scale,
error!( width: uint!(256),
"Unable to publish the room \"{}\" invitation: {}", height: uint!(256),
room.room_id(), }))
err .await
); {
Ok(avatar) => avatar,
Err(err) => {
error!("Unable to fetch avatar for {}: {err}", &room_id);
None
} }
};
let event = RoomEvent::NewAvatar(avatar);
if let Err(_err) = senders.send(room_id, event) {
// TODO: Return an error
} }
} }
async fn on_room_topic_event( async fn on_stripped_room_avatar_event(
_ev: StrippedRoomAvatarEvent,
room: Room,
senders: Ctx<Senders>,
) {
Self::on_room_avatar_event(&room, &senders).await;
}
async fn on_sync_room_avatar_event(
ev: SyncStateEvent<RoomAvatarEventContent>,
room: Room,
senders: Ctx<Senders>,
) {
if let SyncStateEvent::Original(_ev) = ev {
dioxus::prelude::spawn(async move {
Self::on_room_avatar_event(&room, &senders).await;
});
}
}
fn on_room_name_event(name: Option<String>, room: &Room, senders: &Ctx<Senders>) {
let event = RoomEvent::NewName(name);
if let Err(_err) = senders.send(room.room_id(), event) {
// TODO: Return an error
}
}
async fn on_stripped_room_name_event(
ev: StrippedRoomNameEvent,
room: Room,
senders: Ctx<Senders>,
) {
Self::on_room_name_event(ev.content.name, &room, &senders);
}
async fn on_sync_room_name_event(
ev: SyncStateEvent<RoomNameEventContent>,
room: Room,
senders: Ctx<Senders>,
) {
if let SyncStateEvent::Original(ev) = ev {
Self::on_room_name_event(Some(ev.content.name), &room, &senders);
}
}
fn on_room_topic_event(topic: Option<String>, room: &Room, senders: &Ctx<Senders>) {
let event = RoomEvent::NewTopic(topic);
if let Err(_err) = senders.send(room.room_id(), event) {
// TODO: Return an error
}
}
async fn on_stripped_room_topic_event(
ev: StrippedRoomTopicEvent,
room: Room,
senders: Ctx<Senders>,
) {
Self::on_room_topic_event(ev.content.topic, &room, &senders);
}
async fn on_sync_room_topic_event(
ev: SyncStateEvent<RoomTopicEventContent>, ev: SyncStateEvent<RoomTopicEventContent>,
room: Room, room: Room,
senders: Ctx<Senders>, senders: Ctx<Senders>,
) { ) {
error!("*** on_room_topic_event ***");
// error!("ev={:?}", ev);
if let SyncStateEvent::Original(ev) = ev { if let SyncStateEvent::Original(ev) = ev {
let _ = Self::add_room(&senders, &room).await; Self::on_room_topic_event(Some(ev.content.topic), &room, &senders);
let room_id = room.room_id();
let event = RoomEvent::NewTopic(Some(ev.content.topic));
if let Err(err) = senders.send(room_id, event) {
error!(
"Unable to publish the room \"{}\" topic: {}",
room.room_id(),
err
);
} }
} }
}
async fn on_room_member_event(
ev: SyncStateEvent<RoomMemberEventContent>,
room: Room,
senders: Ctx<Senders>,
) {
error!("*** on_room_member_event ***");
// error!("ev={:?}", ev);
if let SyncStateEvent::Original(_ev) = ev {
if Self::add_room(&senders, &room).await.is_ok() {
// let room_id = room.room_id();
// // TODO: Client shall only manage Matrix object... not BG92 ones.
// let event = RoomEvent::Membership(RoomMember::new(ev.sender, room_id));
// if let Some(result) = senders.send(room_id, event) {
// if let Err(err) = result {
// error!(
// "Unable to publish the room \"{}\" membership: {}",
// room.room_id(),
// err
// );
// }
// }
}
}
}
// async fn on_sync_message_like_room_message_event(
// ev: SyncMessageLikeEvent<RoomMessageEventContent>,
// _room: Room,
// _client: MatrixClient,
// ) {
// debug!("== on_sync_message_like_room_message_event ==");
// dbg!(ev);
// }
// async fn on_sync_message_like_reaction_event(
// ev: SyncMessageLikeEvent<ReactionEventContent>,
// _room: Room,
// ) {
// debug!("== on_sync_message_like_reaction_event ==");
// dbg!(ev);
// }
// async fn on_original_sync_room_redaction_event(
// ev: OriginalSyncRoomRedactionEvent,
// _room: Room,
// ) {
// debug!("== on_original_sync_room_redaction_event ==");
// dbg!(ev);
// }
async fn on_original_sync_room_member_event(
_ev: OriginalSyncRoomMemberEvent,
_room: Room,
_client: MatrixClient,
) {
// debug!("== on_original_sync_room_member_event ==");
// error!("room={:?}", room);
// let mut store = store_ctx.read().unwrap().to_owned();
// dbg!(store.rooms.keys());
// let is_direct = room.is_direct().await.ok();
// store.rooms.insert(
// OwnedRoomId::from(room_id),
// Arc::new(RwLock::new(Room::new(Arc::new(room), None, is_direct))),
// );
// let _ = store_ctx.write(store);
}
// async fn on_original_sync_key_verif_start_event(
// ev: OriginalSyncKeyVerificationStartEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_original_sync_key_verif_start_event ==");
// dbg!(ev);
// }
// async fn on_original_sync_key_verif_key_event(
// ev: OriginalSyncKeyVerificationKeyEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_original_sync_key_verif_key_event ==");
// dbg!(ev);
// }
// async fn on_original_sync_key_verif_done_event(
// ev: OriginalSyncKeyVerificationDoneEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_original_sync_key_verif_done_event ==");
// dbg!(ev);
// }
// async fn on_device_key_verif_req_event(
// ev: ToDeviceKeyVerificationRequestEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_device_key_verif_req_event ==");
// dbg!(ev);
// }
// async fn on_device_key_verif_start_event(
// ev: ToDeviceKeyVerificationStartEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_device_key_verif_start_event ==");
// dbg!(ev);
// }
// async fn on_device_key_verif_key_event(
// ev: ToDeviceKeyVerificationKeyEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_device_key_verif_key_event ==");
// dbg!(ev);
// }
// async fn on_device_key_verif_done_event(
// ev: ToDeviceKeyVerificationDoneEvent,
// _client: MatrixClient,
// ) {
// debug!("== on_device_key_verif_done_event ==");
// dbg!(ev);
// }
// async fn on_room_event(ev: SomeEvent, _senders: Ctx<Senders>) {
// debug!("== on_room_event({}) ==", ev.)
// }
pub async fn spawn(homeserver_url: String) -> (Requester, Receiver<AccountEvent>) { pub async fn spawn(homeserver_url: String) -> (Requester, Receiver<AccountEvent>) {
let matrix_client = Arc::new( let matrix_client = Arc::new(
@@ -494,28 +526,20 @@ impl Client {
// TODO: Remove clone? // TODO: Remove clone?
client.add_event_handler_context(self.senders.clone()); client.add_event_handler_context(self.senders.clone());
let _ = client.add_event_handler(Client::on_stripped_room_create_event);
let _ = client.add_event_handler(Client::on_sync_room_create_event);
let _ = client.add_event_handler(Client::on_stripped_room_member_event); let _ = client.add_event_handler(Client::on_stripped_room_member_event);
let _ = client.add_event_handler(Client::on_room_topic_event); let _ = client.add_event_handler(Client::on_sync_room_member_event);
let _ = client.add_event_handler(Client::on_room_member_event);
// let _ = client.add_event_handler(Client::on_sync_typing_event); let _ = client.add_event_handler(Client::on_stripped_room_avatar_event);
// let _ = client.add_event_handler(Client::on_presence_event); let _ = client.add_event_handler(Client::on_sync_room_avatar_event);
// let _ = client.add_event_handler(Client::on_sync_state_event);
// let _ = client.add_event_handler(Client::on_original_sync_room_message_event);
// let _ = client.add_event_handler(Client::on_sync_message_like_room_message_event); let _ = client.add_event_handler(Client::on_stripped_room_name_event);
// let _ = client.add_event_handler(Client::on_sync_message_like_reaction_event); let _ = client.add_event_handler(Client::on_sync_room_name_event);
// let _ = client.add_event_handler(Client::on_original_sync_room_redaction_event);
let _ = client.add_event_handler(Client::on_original_sync_room_member_event); let _ = client.add_event_handler(Client::on_stripped_room_topic_event);
let _ = client.add_event_handler(Client::on_sync_room_topic_event);
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_start_event);
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_key_event);
// let _ = client.add_event_handler(Client::on_original_sync_key_verif_done_event);
// let _ = client.add_event_handler(Client::on_device_key_verif_req_event);
// let _ = client.add_event_handler(Client::on_device_key_verif_start_event);
// let _ = client.add_event_handler(Client::on_device_key_verif_key_event);
// let _ = client.add_event_handler(Client::on_device_key_verif_done_event);
self.initialized = true; self.initialized = true;
} }
@@ -625,15 +649,39 @@ impl Client {
} }
} }
// TODO: Share MediaRequest with other media requests
async fn get_thumbnail(&self, media_url: OwnedMxcUri) -> anyhow::Result<Vec<u8>> {
let client = self.client.as_ref().unwrap();
let media = client.media();
let request = MediaRequest {
source: MediaSource::Plain(media_url),
format: MediaFormat::Thumbnail(MediaThumbnailSize {
method: Method::Scale,
width: uint!(256),
height: uint!(256),
}),
};
let res = media.get_media_content(&request, true).await;
Ok(res?)
}
async fn get_room_member_avatar( async fn get_room_member_avatar(
&self, &self,
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) {
if let Ok(Some(room_member)) = room.get_member(user_id).await { // TODO: Check if we can get member before fetching the data and received an error...
match room.get_member(user_id).await {
Ok(room_member) => match room_member {
Some(room_member) => {
let res = match room_member let res = match room_member
.avatar(MediaFormat::Thumbnail(MediaThumbnailSize { .avatar(MediaFormat::Thumbnail(MediaThumbnailSize {
method: Method::Scale, method: Method::Scale,
@@ -647,6 +695,19 @@ impl Client {
}; };
return res; return res;
} }
// TODO: Error msg
None => (),
},
Err(err) => {
error!("Unable to get room member {user_id}: {err}");
if let Some(avatar_url) = avatar_url {
let thumbnail = self.get_thumbnail(avatar_url.clone()).await;
return Ok(Some(thumbnail?));
} else {
error!("No avatar url set for the {room_id} room");
}
}
}
} }
Ok(None) Ok(None)
} }
@@ -691,9 +752,12 @@ impl Client {
reply.send(self.get_room_members(&id).await).await; reply.send(self.get_room_members(&id).await).await;
} }
WorkerTask::GetRoomMemberAvatar(room_id, user_id, reply) => { WorkerTask::GetRoomMemberAvatar(room_id, user_id, avatar_url, reply) => {
reply reply
.send(self.get_room_member_avatar(&room_id, &user_id).await) .send(
self.get_room_member_avatar(&room_id, &user_id, &avatar_url)
.await,
)
.await; .await;
} }
} }

View File

@@ -1,7 +1,6 @@
use std::{collections::HashMap, rc::Rc}; use std::{collections::HashMap, rc::Rc};
use async_trait::async_trait; use async_trait::async_trait;
use futures::future::join_all;
use tokio::{ use tokio::{
select, select,
sync::{broadcast::Receiver, mpsc::UnboundedSender}, sync::{broadcast::Receiver, mpsc::UnboundedSender},
@@ -23,8 +22,8 @@ use crate::{
RoomMessagingProviderInterface, SpaceMessagingConsumerInterface, RoomMessagingProviderInterface, SpaceMessagingConsumerInterface,
SpaceMessagingProviderInterface, SpaceMessagingProviderInterface,
}, },
room::{Room, RoomId}, room::{Invitation, Room, RoomId},
room_member::RoomMember, room_member::{AvatarUrl, RoomMember},
space::Space, space::Space,
}, },
utils::oneshot, utils::oneshot,
@@ -182,19 +181,29 @@ impl AccountMessagingProviderInterface for Requester {
if let Ok(room_event) = room_event { if let Ok(room_event) = room_event {
if let Some(consumer) = room_events_consumers.get(&room_id) { if let Some(consumer) = room_events_consumers.get(&room_id) {
match room_event { match room_event {
RoomEvent::Invitation() => { RoomEvent::Invitation(user_id, sender_id, is_account_user) => {
consumer.on_invitation().await; let invitation = Invitation::new(user_id, sender_id, is_account_user);
consumer.on_invitation(invitation).await;
},
RoomEvent::Join(user_id, user_name, avatar_url, is_account_user) => {
let member = RoomMember::new(
UserId::from(user_id),
user_name,
avatar_url,
room_id,
is_account_user,
client.clone());
consumer.on_membership(member).await;
}, },
// RoomEvent::Membership(user_id, is_account_user) => {
// let member = RoomMember::new(UserId::from(user_id), room_id, is_account_user);
// consumer.on_membership(member).await;
// },
RoomEvent::NewTopic(topic) => { RoomEvent::NewTopic(topic) => {
consumer.on_new_topic(topic).await; consumer.on_new_topic(topic).await;
}, },
RoomEvent::NewName(name) => { RoomEvent::NewName(name) => {
consumer.on_new_name(name).await; consumer.on_new_name(name).await;
}, },
RoomEvent::NewAvatar(avatar) => {
consumer.on_new_avatar(avatar).await;
}
_ => {} _ => {}
} }
} else { } else {
@@ -256,12 +265,14 @@ impl MemberMessagingProviderInterface for Requester {
&self, &self,
room_id: &RoomId, room_id: &RoomId,
user_id: &UserId, user_id: &UserId,
avatar_url: &Option<AvatarUrl>,
) -> anyhow::Result<Option<Avatar>> { ) -> anyhow::Result<Option<Avatar>> {
request_to_worker!( request_to_worker!(
self, self,
WorkerTask::GetRoomMemberAvatar, WorkerTask::GetRoomMemberAvatar,
room_id.clone(), room_id.clone(),
user_id.clone() user_id.clone(),
avatar_url.clone()
) )
} }
} }

View File

@@ -1,34 +1,43 @@
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use matrix_sdk::ruma::{OwnedRoomId, OwnedUserId}; use matrix_sdk::ruma::{OwnedMxcUri, OwnedRoomId, OwnedUserId};
use tokio::sync::broadcast::Receiver; use tokio::sync::broadcast::Receiver;
use crate::domain::model::common::Avatar;
#[derive(Clone)] #[derive(Clone)]
pub enum RoomEvent { pub enum RoomEvent {
Invitation(), Invitation(OwnedUserId, OwnedUserId, bool),
Join(OwnedUserId, Option<String>, Option<OwnedMxcUri>, bool),
#[allow(dead_code)]
Membership(OwnedUserId, bool),
NewTopic(Option<String>), NewTopic(Option<String>),
NewName(Option<String>), NewName(Option<String>),
NewAvatar(Option<Avatar>),
NewChild(OwnedRoomId), NewChild(OwnedRoomId),
} }
impl Debug for RoomEvent { impl Debug for RoomEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
match self { match self {
Self::Invitation() => f Self::Invitation(invitee_id, sender_id, is_account_user) => f
.debug_tuple("RoomEvent::Invitation") .debug_tuple("RoomEvent::Invitation")
.field(&format_args!("_")) .field(invitee_id)
.field(sender_id)
.field(is_account_user)
.finish(), .finish(),
Self::Membership(user_id, is_account_user) => f Self::Join(user_id, user_name, avatar_url, is_account_user) => f
.debug_tuple("RoomEvent::Membership") .debug_tuple("RoomEvent::Join")
.field(user_id) .field(user_id)
.field(user_name)
.field(avatar_url)
.field(is_account_user) .field(is_account_user)
.finish(), .finish(),
Self::NewTopic(topic) => f.debug_tuple("RoomEvent::NewTopic").field(topic).finish(), Self::NewTopic(topic) => f.debug_tuple("RoomEvent::NewTopic").field(topic).finish(),
Self::NewName(name) => f.debug_tuple("RoomEvent::NewName").field(name).finish(), Self::NewName(name) => f.debug_tuple("RoomEvent::NewName").field(name).finish(),
Self::NewAvatar(avatar) => f
.debug_tuple("RoomEvent::NewAvatar")
.field(&format!("is_some: {}", &avatar.is_some()))
.finish(),
Self::NewChild(room_id) => f Self::NewChild(room_id) => f
.debug_tuple("SpaceEvent::NewChild") .debug_tuple("SpaceEvent::NewChild")
.field(room_id) .field(room_id)

View File

@@ -2,7 +2,7 @@ use std::fmt::{Debug, Formatter};
use matrix_sdk::{ use matrix_sdk::{
room::RoomMember, room::RoomMember,
ruma::{OwnedRoomId, OwnedUserId}, ruma::{OwnedMxcUri, OwnedRoomId, OwnedUserId},
}; };
use crate::utils::Sender; use crate::utils::Sender;
@@ -25,6 +25,7 @@ pub enum WorkerTask {
GetRoomMemberAvatar( GetRoomMemberAvatar(
OwnedRoomId, OwnedRoomId,
OwnedUserId, OwnedUserId,
Option<OwnedMxcUri>,
Sender<anyhow::Result<Option<Vec<u8>>>>, Sender<anyhow::Result<Option<Vec<u8>>>>,
), ),
} }
@@ -64,10 +65,11 @@ impl Debug for WorkerTask {
.field(id) .field(id)
.finish(), .finish(),
WorkerTask::GetRoomMemberAvatar(room_id, user_id, _) => f WorkerTask::GetRoomMemberAvatar(room_id, user_id, avatar_url, _) => f
.debug_tuple("WorkerTask::GetRoomMemberAvatar") .debug_tuple("WorkerTask::GetRoomMemberAvatar")
.field(room_id) .field(room_id)
.field(user_id) .field(user_id)
.field(avatar_url)
.finish(), .finish(),
} }
} }