diff --git a/src/base.rs b/src/base.rs index 6f73c6f..515beca 100644 --- a/src/base.rs +++ b/src/base.rs @@ -2,22 +2,19 @@ // In order to use/run the rx.next().await statement you will need to extend the [Stream] trait // (used by [UnboundedReceiver]) by adding 'futures_util' as a dependency to your project // and adding the use futures_util::stream::StreamExt; -use futures_util::stream::StreamExt; use std::cell::RefCell; -use std::{collections::HashMap, sync::Arc}; +use dioxus::prelude::*; +use futures_util::stream::StreamExt; +use log::{debug, error, warn}; +use matrix_sdk::ruma::OwnedRoomId; +use tokio::select; + +use crate::domain::model::room::{ByIdRooms, Room}; +use crate::domain::model::session::Session; use crate::infrastructure::messaging::matrix::client::{Client, RoomEvent}; use crate::infrastructure::messaging::matrix::requester::{Receivers, Requester}; use crate::infrastructure::messaging::matrix::worker_tasks::LoginStyle; -use dioxus::prelude::*; -use matrix_sdk::{ - room::{Room as MatrixRoom, RoomMember}, - ruma::{OwnedRoomId, OwnedUserId}, -}; -use tokio::select; -use log::{debug, error, warn}; - -use crate::domain::model::session::Session; use crate::ui::components::chats_window::interface::Interface as ChatsWinInterface; // #[derive(Clone, Debug)] @@ -41,55 +38,6 @@ use crate::ui::components::chats_window::interface::Interface as ChatsWinInterfa // } // } -#[derive(Clone)] -pub struct Room { - pub matrix_room: Arc, - pub topic: Option>, - pub members: HashMap, - pub is_direct: Option, -} - -impl Room { - pub fn new( - matrix_room: Arc, - topic: Option>, - is_direct: Option, - ) -> Self { - Self { - matrix_room, - topic, - members: HashMap::new(), - is_direct, - } - } - - 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(), - ) - } - - pub fn name(&self) -> Option { - 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() - } -} - -pub type ByIdRooms = HashMap>; // pub type ByIdUserInfos = HashMap; // #[derive(Clone)] @@ -153,10 +101,7 @@ async fn on_joining_invitation( room: Room, by_id_rooms: &GlobalSignal, ) { - debug!( - "You're invited to join the \"{}\" room", - room.name().unwrap() - ); + debug!("You're invited to join the \"{}\" room", room.id()); // TODO: Update rooms by_id_rooms .write() @@ -166,7 +111,7 @@ async fn on_joining_invitation( async fn on_room_topic(room_id: OwnedRoomId, topic: String, by_id_rooms: &GlobalSignal) { if let Some(room) = by_id_rooms.read().get(&room_id) { let mut room = room.borrow_mut(); - room.topic = Some(RefCell::new(topic)); + room.set_topic(Some(topic)); } else { warn!("No room found with the \"{}\" id", room_id); } @@ -230,6 +175,7 @@ pub async fn login( } Err(err) => { error!("Error during login: {err}"); + // TODO: Handle invalid login // invalid_login.modify(|_| true); } } diff --git a/src/domain/model/mod.rs b/src/domain/model/mod.rs index bd1b488..87868cd 100644 --- a/src/domain/model/mod.rs +++ b/src/domain/model/mod.rs @@ -1 +1,2 @@ +pub(crate) mod room; pub(crate) mod session; diff --git a/src/domain/model/room.rs b/src/domain/model/room.rs new file mode 100644 index 0000000..131deeb --- /dev/null +++ b/src/domain/model/room.rs @@ -0,0 +1,145 @@ +use std::cell::RefCell; +use std::{collections::HashMap, sync::Arc}; + +use matrix_sdk::ruma::OwnedRoomId; +use matrix_sdk::{Room as MatrixRoom, RoomState as MatrixRoomState}; +use tracing::error; + +pub(crate) type RoomId = OwnedRoomId; + +#[derive(Clone, Debug)] +pub(crate) struct Room { + id: RoomId, + name: Option, + topic: Option, + is_direct: Option, + state: Option, +} + +impl Room { + fn new( + id: RoomId, + name: Option, + topic: Option, + is_direct: Option, + state: Option, + ) -> Self { + Self { + id, + name, + topic, + is_direct, + state, + } + } + + // TODO: Use a factory instead... + pub async fn from_matrix_room(matrix_room: &MatrixRoom) -> Self { + // let room_topic = matrix_room.topic().map(RefCell::new); + + let id = RoomId::from(matrix_room.room_id()); + 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 { + &self.id + } + + pub fn name(&self) -> &Option { + &self.name + } + + pub fn topic(&self) -> &Option { + &self.topic + } + pub fn set_topic(&mut self, topic: Option) { + self.topic = topic; + } + + pub fn is_direct(&self) -> &Option { + &self.is_direct + } + + pub fn state(&self) -> &Option { + &self.state + } + pub fn is_invited(&self) -> Option { + match self.state { + Some(state) => Some(state == MatrixRoomState::Invited), + None => None, + } + } +} + +pub type ByIdRooms = HashMap>; + +// pub type ByIdRooms = HashMap>; + +// #[derive(Clone)] +// pub struct Room { +// // pub matrix_room: Arc, +// pub topic: Option>, +// pub members: HashMap, +// pub is_direct: Option, +// // pub timeline: Arc, +// } + +// impl Room { +// pub async fn new( +// matrix_room: Arc, +// topic: Option>, +// is_direct: Option, +// ) -> 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 { +// 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() +// } +// } diff --git a/src/infrastructure/messaging/matrix/client.rs b/src/infrastructure/messaging/matrix/client.rs index 2b29526..5b0dc34 100644 --- a/src/infrastructure/messaging/matrix/client.rs +++ b/src/infrastructure/messaging/matrix/client.rs @@ -1,10 +1,15 @@ +use std::borrow::Borrow; use std::cell::RefCell; use std::sync::Arc; +use std::time::Duration; +use async_std::task; +use dioxus::prelude::Task; use log::{debug, error}; use tokio::sync::broadcast; use tokio::sync::broadcast::Sender; use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver}; +use tokio::sync::oneshot; use tokio::task::JoinHandle; use matrix_sdk::{ @@ -13,25 +18,11 @@ use matrix_sdk::{ room::Room as MatrixRoom, ruma::{ events::{ - key::verification::{ - done::{OriginalSyncKeyVerificationDoneEvent, ToDeviceKeyVerificationDoneEvent}, - key::{OriginalSyncKeyVerificationKeyEvent, ToDeviceKeyVerificationKeyEvent}, - request::ToDeviceKeyVerificationRequestEvent, - start::{OriginalSyncKeyVerificationStartEvent, ToDeviceKeyVerificationStartEvent}, - }, - presence::PresenceEvent, - reaction::ReactionEventContent, room::{ - member::{ - OriginalSyncRoomMemberEvent, RoomMemberEventContent, StrippedRoomMemberEvent, - }, - message::RoomMessageEventContent, - name::RoomNameEventContent, - redaction::OriginalSyncRoomRedactionEvent, + member::{RoomMemberEventContent, StrippedRoomMemberEvent}, topic::RoomTopicEventContent, }, - typing::SyncTypingEvent, - SyncMessageLikeEvent, SyncStateEvent, + SyncStateEvent, }, OwnedRoomId, }, @@ -40,7 +31,7 @@ use matrix_sdk::{ use super::requester::{Receivers, Requester}; use super::worker_tasks::{LoginStyle, WorkerTask}; -use crate::base::Room; +use crate::domain::model::room::Room; #[derive(thiserror::Error, Debug)] pub enum ClientError { @@ -57,49 +48,58 @@ pub enum RoomEvent { #[derive(Clone)] struct Senders { - room_sender: Sender, + room_events_sender: Sender, } impl Senders { - fn new(room_sender: Sender) -> Self { - Self { room_sender } + fn new(room_events_sender: Sender) -> Self { + Self { room_events_sender } } } pub struct Client { initialized: bool, client: Option>, - sync_handle: Option>, + sync_task: Option, senders: Senders, } impl Client { - pub fn new(client: Arc, room_sender: Sender) -> Self { + pub fn new(client: Arc, room_events_sender: Sender) -> Self { Self { initialized: false, client: Some(client), - sync_handle: None, - senders: Senders::new(room_sender), + sync_task: None, + senders: Senders::new(room_events_sender), } } - async fn on_sync_typing_event(_ev: SyncTypingEvent, room: MatrixRoom) { - debug!("== on_sync_typing_event =="); - let room_id = room.room_id().to_owned(); - dbg!(room_id); - } + // async fn on_sync_typing_event(_ev: SyncTypingEvent, room: MatrixRoom) { + // debug!("== on_sync_typing_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_presence_event(_ev: PresenceEvent) { + // debug!("== on_presence_event =="); + // dbg!(_ev); + // } - async fn on_sync_state_event(ev: SyncStateEvent, _room: MatrixRoom) { - error!("== on_sync_state_event =="); - if let SyncStateEvent::Original(ev) = ev { - dbg!(ev); - } - } + // async fn on_sync_state_event(ev: SyncStateEvent, _room: MatrixRoom) { + // error!("== on_sync_state_event =="); + // if let SyncStateEvent::Original(ev) = ev { + // dbg!(ev); + // } + // } + + // async fn on_original_sync_room_message_event( + // ev: OriginalSyncRoomMessageEvent, + // _matrix_room: MatrixRoom, + // _senders: Ctx, + // ) { + // error!("== on_original_sync_room_message_event =="); + // error!("ev={:?}", ev.content); + // } async fn on_stripped_room_member_event( ev: StrippedRoomMemberEvent, @@ -107,20 +107,20 @@ impl Client { matrix_room: MatrixRoom, senders: Ctx, ) { - if ev.state_key == matrix_client.user_id().unwrap() { - if matrix_room.state() == MatrixRoomState::Invited { - let room_id = matrix_room.room_id(); - let room = Room::from_matrix_room(&matrix_room).await; + if ev.state_key == matrix_client.user_id().unwrap() + && matrix_room.state() == MatrixRoomState::Invited + { + let room_id = matrix_room.room_id(); + let room = Room::from_matrix_room(&matrix_room).await; - if let Err(err) = senders - .room_sender - .send(RoomEvent::InviteEvent(room_id.to_owned(), room)) - { - error!( - "Unable to publish the new room with \"{}\" id: {}", - room_id, err - ); - } + if let Err(err) = senders + .room_events_sender + .send(RoomEvent::InviteEvent(room_id.to_owned(), room)) + { + error!( + "Unable to publish the new room with \"{}\" id: {}", + room_id, err + ); } } } @@ -134,7 +134,7 @@ impl Client { let room_id = matrix_room.room_id(); if let Err(err) = senders - .room_sender + .room_events_sender .send(RoomEvent::TopicEvent(room_id.to_owned(), ev.content.topic)) { error!("Unable to publish the \"{}\" new topic: {}", room_id, err); @@ -148,12 +148,13 @@ impl Client { senders: Ctx, ) { if let SyncStateEvent::Original(_ev) = ev { - let room_sender = &senders.room_sender; - let room_id = matrix_room.room_id(); let room = Room::from_matrix_room(&matrix_room).await; - if let Err(err) = room_sender.send(RoomEvent::MemberEvent(room_id.to_owned(), room)) { + if let Err(err) = senders + .room_events_sender + .send(RoomEvent::MemberEvent(room_id.to_owned(), room)) + { error!( "Unable to publish the new room with \"{}\" id: {}", room_id, err @@ -162,103 +163,107 @@ impl Client { } } - async fn on_sync_message_like_room_message_event( - ev: SyncMessageLikeEvent, - _room: MatrixRoom, - _client: MatrixClient, - ) { - debug!("== on_sync_message_like_room_message_event =="); - dbg!(ev); - } + // async fn on_sync_message_like_room_message_event( + // ev: SyncMessageLikeEvent, + // _room: MatrixRoom, + // _client: MatrixClient, + // ) { + // debug!("== on_sync_message_like_room_message_event =="); + // dbg!(ev); + // } - async fn on_sync_message_like_reaction_event( - ev: SyncMessageLikeEvent, - _room: MatrixRoom, - ) { - debug!("== on_sync_message_like_reaction_event =="); - dbg!(ev); - } + // async fn on_sync_message_like_reaction_event( + // ev: SyncMessageLikeEvent, + // _room: MatrixRoom, + // ) { + // debug!("== on_sync_message_like_reaction_event =="); + // dbg!(ev); + // } - async fn on_original_sync_room_redaction_event( - ev: OriginalSyncRoomRedactionEvent, - _room: MatrixRoom, - ) { - debug!("== on_original_sync_room_redaction_event =="); - dbg!(ev); - } + // async fn on_original_sync_room_redaction_event( + // ev: OriginalSyncRoomRedactionEvent, + // _room: MatrixRoom, + // ) { + // debug!("== on_original_sync_room_redaction_event =="); + // dbg!(ev); + // } - async fn on_original_sync_room_member_event( - _ev: OriginalSyncRoomMemberEvent, - _room: MatrixRoom, - _client: MatrixClient, - ) { - debug!("== on_original_sync_room_member_event =="); + // async fn on_original_sync_room_member_event( + // _ev: OriginalSyncRoomMemberEvent, + // _room: MatrixRoom, + // _client: MatrixClient, + // ) { + // debug!("== on_original_sync_room_member_event =="); - // 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); - } + // 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_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_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_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_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_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_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_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) { + // debug!("== on_room_event({}) ==", ev.) + // } pub async fn spawn(homeserver_url: String) -> Requester { let (tx, rx) = unbounded_channel::(); @@ -275,10 +280,8 @@ impl Client { let mut client = Client::new(matrix_client.clone(), room_sender); - tokio::spawn({ - async move { - client.work(rx).await; - } + dioxus::prelude::spawn(async move { + client.work(rx).await; }); Requester { @@ -291,62 +294,34 @@ impl Client { } fn init(&mut self) { - let client = self.client.clone().unwrap(); + if let Some(client) = self.client.borrow() { + 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_member_event); + let _ = client.add_event_handler(Client::on_room_topic_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_presence_event); - let _ = client.add_event_handler(Client::on_sync_state_event); - let _ = client.add_event_handler(Client::on_stripped_room_member_event); - let _ = client.add_event_handler(Client::on_sync_message_like_room_message_event); - let _ = client.add_event_handler(Client::on_sync_message_like_reaction_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_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); - let _ = client.add_event_handler(Client::on_room_topic_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_presence_event); + // let _ = client.add_event_handler(Client::on_sync_state_event); + // let _ = client.add_event_handler(Client::on_original_sync_room_message_event); - self.initialized = true; + // let _ = client.add_event_handler(Client::on_sync_message_like_room_message_event); + // let _ = client.add_event_handler(Client::on_sync_message_like_reaction_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_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; + } } - // async fn refresh_rooms(matrix_client: &MatrixClient, room_sender: &Sender) { - // let joined_matrix_rooms_ref = &matrix_client.joined_rooms(); - // let invited_matrix_rooms_ref = &matrix_client.invited_rooms(); - - // for matrix_rooms in [joined_matrix_rooms_ref, invited_matrix_rooms_ref] { - // for matrix_room in matrix_rooms.iter() { - // let topic = matrix_room.topic().map(RefCell::new); - // let room = Room::new( - // Arc::new(matrix_room.to_owned()), - // topic, - // matrix_room.is_direct().await.ok(), - // ); - - // if let Err(err) = room_sender.send(room) { - // warn!("Error: {}", err); - // } - // } - // } - // } - - // async fn refresh_rooms_forever(matrix_client: &MatrixClient, room_channel: &Sender) { - // // TODO: Add interval to config - // let mut interval = tokio::time::interval(Duration::from_secs(5)); - - // loop { - // // Self::refresh_rooms(matrix_client, room_channel).await; - - // interval.tick().await; - // } - // } - async fn login_and_sync(&mut self, style: LoginStyle) -> anyhow::Result<()> { let client = self.client.clone().unwrap(); @@ -362,62 +337,95 @@ impl Client { } } - // let (synchronized_tx, synchronized_rx) = oneshot::channel(); + let (synchronized_tx, synchronized_rx) = oneshot::channel::(); - self.sync_handle = tokio::spawn({ - async move { - // Sync once so we receive the client state and old messages - let sync_token_option = match client.sync_once(SyncSettings::default()).await { - Ok(sync_response) => Some(sync_response.next_batch), - Err(err) => { - error!("Error during sync one: {}", err); - None - } - }; - - if let Some(sync_token) = sync_token_option { - let settings = SyncSettings::default().token(sync_token); - - debug!("User connected to the homeserver, start syncing"); - - let _ = client.sync(settings).await; + let task = dioxus::prelude::spawn(async move { + // Sync once so we receive the client state and old messages + let sync_token_option = match client.sync_once(SyncSettings::default()).await { + Ok(sync_response) => Some(sync_response.next_batch), + Err(err) => { + error!("Error during sync one: {}", err); + None } + }; + + if let Some(sync_token) = sync_token_option { + let settings = SyncSettings::default().token(sync_token); + + debug!("User connected to the homeserver, start syncing"); + + if let Err(err) = synchronized_tx.send(true) { + error!("Unable to notify that the Matrix client is now synchronized ({err})"); + } + + let _ = client.sync(settings).await; } - }) - .into(); + }); + self.sync_task = Some(task); // self.start_background_tasks(synchronized_rx); Ok(()) } + // async fn register_room_events(&self, room_id: OwnedRoomId) { + // let client = self.client.unwrap(); + + // client.add_room_event_handler(&room_id, Client::on_room_event); + // } + + // async fn refresh_rooms( + // matrix_client: &Arc, + // room_events_sender: &Sender, + // ) { + // let joined_matrix_rooms_ref = &matrix_client.joined_rooms(); + // let invited_matrix_rooms_ref = &matrix_client.invited_rooms(); + + // for matrix_rooms in [joined_matrix_rooms_ref, invited_matrix_rooms_ref] { + // for matrix_room in matrix_rooms.iter() { + // let room = Room::from_matrix_room(matrix_room).await; + // let event = RoomEvent::MemberEvent(room.id().clone(), room); + + // if let Err(err) = room_events_sender.send(event) { + // error!("Error: {}", err); + // } + // } + // } + // } + + // async fn refresh_rooms_forever( + // matrix_client: Arc, + // room_events_sender: &Sender, + // ) { + // // TODO: Add interval to config + // let period_sec = Duration::from_secs(5); + + // loop { + // Self::refresh_rooms(&matrix_client, room_events_sender).await; + + // task::sleep(period_sec).await; + // } + // } + // fn start_background_tasks(&mut self, synchronized_rx: oneshot::Receiver) { // let client = self.client.clone().unwrap(); - // let room_sender_ref = &self.senders.room_sender; + // let room_events_sender = self.senders.room_events_sender.clone(); - // self.load_handle = tokio::spawn({ - // to_owned![room_sender_ref]; - - // async move { - // if let Err(err) = synchronized_rx.await { - // error!("Unable to setup the rx channel notifying that the Matrix client is now synchronized ({err})"); - // } - - // let rooms_refresh = Self::refresh_rooms_forever( - // client.as_ref(), - // &room_sender_ref - // ); - // let ((),) = tokio::join!(rooms_refresh); + // let task = dioxus::prelude::spawn(async move { + // if let Err(err) = synchronized_rx.await { + // error!("Unable to setup the rx channel notifying that the Matrix client is now synchronized ({err})"); // } - // }) - // .into(); + + // debug!("Start room refreshing forever"); + + // let _ = Self::refresh_rooms_forever(client, &room_events_sender).await; + // }); + // self.background_task = Some(task); // } async fn work(&mut self, mut rx: UnboundedReceiver) { loop { - let task = rx.recv().await; - - match task { + match rx.recv().await { Some(task) => self.run(task).await, None => { break; @@ -425,8 +433,8 @@ impl Client { } } - if let Some(handle) = self.sync_handle.take() { - handle.abort(); + if let Some(task) = self.sync_task.take() { + task.cancel() } } @@ -440,7 +448,10 @@ impl Client { WorkerTask::Login(style, reply) => { assert!(self.initialized); reply.send(self.login_and_sync(style).await).await; - } + } // WorkerTask::registerRoomEvents(room_id, reply) => { + // assert!(self.initialized); + // reply.send(self.register_room_events(room_id).await).await; + // } } } } diff --git a/src/infrastructure/messaging/matrix/requester.rs b/src/infrastructure/messaging/matrix/requester.rs index bf6c905..c984ad3 100644 --- a/src/infrastructure/messaging/matrix/requester.rs +++ b/src/infrastructure/messaging/matrix/requester.rs @@ -37,8 +37,11 @@ impl Requester { pub async fn init(&self) -> anyhow::Result<()> { let (reply, mut response) = oneshot(); - // TODO: Handle error case. - self.tx.send(WorkerTask::Init(reply)).unwrap(); + if let Err(err) = self.tx.send(WorkerTask::Init(reply)) { + let msg = format!("Unable to request the init of the Matrix client: {err}"); + return Err(anyhow::Error::msg(msg)); + } + match response.recv().await { Some(result) => Ok(result), None => Err(anyhow::Error::msg("TBD")), @@ -48,8 +51,11 @@ impl Requester { pub async fn login(&self, style: LoginStyle) -> anyhow::Result<()> { let (reply, mut response) = oneshot(); - // TODO: Handle error case. - self.tx.send(WorkerTask::Login(style, reply)).unwrap(); + if let Err(err) = self.tx.send(WorkerTask::Login(style, reply)) { + let msg = format!("Unable to request login to the Matrix client: {err}"); + return Err(anyhow::Error::msg(msg)); + } + match response.recv().await { Some(result) => result, None => Err(anyhow::Error::msg("TBD")), diff --git a/src/ui/components/chats_window/mod.rs b/src/ui/components/chats_window/mod.rs index cda94e5..fd4ee63 100644 --- a/src/ui/components/chats_window/mod.rs +++ b/src/ui/components/chats_window/mod.rs @@ -12,7 +12,8 @@ use log::{debug, error}; use matrix_sdk::ruma::OwnedRoomId; use tokio::sync::broadcast::Receiver; -use crate::base::{sync_rooms, Room, ROOMS}; +use crate::base::{sync_rooms, ROOMS}; +use crate::domain::model::room::Room; use crate::infrastructure::messaging::matrix::requester::Receivers; use conversation::Conversation; use navbar::Navbar; @@ -35,10 +36,13 @@ fn render_rooms_tabs( let displayed_room_ids = displayed_room_ids.read(); rooms_ref .values() - .filter(|room| displayed_room_ids.contains(&room.borrow().id())) + .filter(|room| displayed_room_ids.contains(room.borrow().id())) .map(|room| { let room = room.borrow(); - let room_name = room.name().unwrap_or(room.id().to_string()); + let room_name = match room.name() { + Some(room_name) => room_name.clone(), + None => room.id().to_string(), + }; rsx!( div { class: ClassName::TAB, @@ -62,10 +66,13 @@ fn render_rooms_conversations( let displayed_room_ids = displayed_room_ids.read(); rooms_ref .values() - .filter(|room| displayed_room_ids.contains(&room.borrow().id())) + .filter(|room| displayed_room_ids.contains(room.borrow().id())) .map(|room| { - let room_id = room.borrow().id(); - rsx!(Conversation { room_id: room_id },) + let room = room.borrow(); + let room_id = room.id(); + rsx!(Conversation { + room_id: room_id.clone() + },) }) .collect() } diff --git a/src/ui/components/contacts_window/contacts_section.rs b/src/ui/components/contacts_window/contacts_section.rs index c7fe09e..b1fd1f6 100644 --- a/src/ui/components/contacts_window/contacts_section.rs +++ b/src/ui/components/contacts_window/contacts_section.rs @@ -5,9 +5,9 @@ use dioxus::prelude::*; use dioxus_free_icons::icons::io_icons::IoChevronDown; use dioxus_free_icons::Icon; use log::debug; -use matrix_sdk::{ruma::OwnedRoomId, RoomState}; -use crate::base::{ByIdRooms, Room, CHATS_WIN_INTERFACE, ROOMS}; +use crate::base::{CHATS_WIN_INTERFACE, ROOMS}; +use crate::domain::model::room::{ByIdRooms, Room, RoomId}; use crate::ui::components::chats_window::interface::Interface as ChatsWindowInterface; turf::style_sheet!("src/ui/components/contacts_window/contacts_section.scss"); @@ -32,7 +32,7 @@ pub(super) fn filter_people_conversations( let mut filtered_rooms = Vec::>::with_capacity(by_id_rooms.len()); for room in by_id_rooms.values() { - let is_direct = room.borrow().is_direct.unwrap(); + let is_direct = room.borrow().is_direct().unwrap(); if !is_direct { filtered_rooms.push(room.to_owned()); } @@ -48,7 +48,7 @@ pub(super) fn filter_room_conversations( let mut filtered_rooms = Vec::>::with_capacity(by_id_rooms.len()); for room in by_id_rooms.values() { - let is_direct = room.borrow().is_direct.unwrap(); + let is_direct = room.borrow().is_direct().unwrap(); if is_direct { filtered_rooms.push(room.to_owned()); } @@ -57,10 +57,7 @@ pub(super) fn filter_room_conversations( } // TODO: Handle errors -fn on_clicked_room( - room_id: &OwnedRoomId, - chats_window_interface: &GlobalSignal, -) { +fn on_clicked_room(room_id: &RoomId, chats_window_interface: &GlobalSignal) { let _ = chats_window_interface.read().toggle_room(room_id.clone()); } @@ -89,22 +86,19 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element { ] .join(" "); - let rendered_contacts = contacts.into_iter().map(|room_ref| { - let room = room_ref.borrow(); + let rendered_contacts = contacts.into_iter().map(|room| { + let room = room.borrow(); - let room_topic = room - .topic - .as_ref() - .unwrap_or(&RefCell::new(NO_SUBJECT_REPR.to_string())) - .borrow() - .to_owned(); - let room_name = room.name().unwrap_or(NO_NAME_REPR.to_string()); - let room_id = room.id(); - - let is_invited = room.matrix_room.state() == RoomState::Invited; + let topic = room.topic().clone().unwrap_or("".to_string()); + let name = match room.name() { + Some(name) => name.clone(), + None => NO_NAME_REPR.to_string(), + }; + let id = room.id().clone(); + let is_invited = room.is_invited().unwrap_or(false); let formatted = format!( - "{room_name} - {}", + "{name} - {}", if is_invited { "Invited - ".to_string() } else { @@ -114,7 +108,7 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element { rsx! { li { - onclick: move |_| on_clicked_room(&room_id, &CHATS_WIN_INTERFACE), + onclick: move |_| on_clicked_room(&id, &CHATS_WIN_INTERFACE), img { src: "./images/status_online.png", }, @@ -123,7 +117,7 @@ pub fn ContactsSection(props: ContactsSectionProps) -> Element { }, p { style: "color: darkgrey;", - {room_topic}, + {topic}, }, } } diff --git a/src/ui/components/login.rs b/src/ui/components/login.rs index f10b6d1..fc0870b 100644 --- a/src/ui/components/login.rs +++ b/src/ui/components/login.rs @@ -654,8 +654,6 @@ pub fn Login() -> Element { let field_errors = errors.field_errors(); on_validation_errors(&field_errors, &handlers); } - - spinner_animated.set(false); } };