// Cf. https://dioxuslabs.com/learn/0.4/reference/use_coroutine // 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 std::cell::RefCell; 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 crate::ui::components::chats_window::interface::Interface as ChatsWinInterface; // #[derive(Clone, Debug)] // pub struct UserInfo { // pub avatar_url: Option, // pub display_name: Option, // pub blurhash: Option, // } // impl UserInfo { // pub fn new( // avatar_url: Option, // display_name: Option, // blurhash: Option, // ) -> Self { // Self { // avatar_url, // display_name, // blurhash, // } // } // } // pub type ByIdUserInfos = HashMap; // #[derive(Clone)] // pub struct Store { // pub is_logged: bool, // pub rooms: ByIdRooms, // pub user_infos: ByIdUserInfos, // pub user_id: Option, // } // impl Store { // pub fn new() -> Self { // Self { // is_logged: false, // rooms: HashMap::new(), // user_infos: HashMap::new(), // user_id: None, // } // } // } // impl PartialEq for Store { // fn eq(&self, other: &Self) -> bool { // self.is_logged == other.is_logged // && self.user_id == other.user_id // && self.user_infos.len() == other.user_infos.len() // && self // .user_infos // .keys() // .all(|k| other.user_infos.contains_key(k)) // && self.rooms.len() == other.rooms.len() // && self.rooms.keys().all(|k| other.rooms.contains_key(k)) // } // } // impl Eq for Store {} pub struct AppSettings { pub requester: Option>, } impl AppSettings { pub fn new() -> Self { Self { requester: None } } pub fn set_requester(&mut self, requester: RefCell) { self.requester = Some(requester); } } async fn on_room(room_id: OwnedRoomId, room: Room, by_id_rooms: &GlobalSignal) { // TODO: Update rooms by_id_rooms .write() .insert(room_id, RefCell::::new(room)); } async fn on_joining_invitation( room_id: OwnedRoomId, room: Room, by_id_rooms: &GlobalSignal, ) { debug!("You're invited to join the \"{}\" room", room.id()); // TODO: Update rooms by_id_rooms .write() .insert(room_id, RefCell::::new(room)); } 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.set_topic(Some(topic)); } else { warn!("No room found with the \"{}\" id", room_id); } } pub async fn sync_messages(by_id_rooms: &GlobalSignal, room_id: OwnedRoomId) { error!("== sync_messages =="); } pub async fn sync_rooms( mut rx: UnboundedReceiver, receivers: Receivers, by_id_rooms: &GlobalSignal, ) { if let Some(_is_logged) = rx.next().await { let mut rooms_receiver = receivers.room_receiver.borrow_mut(); loop { // TODO: Remove select if no more receivers will be used. select! { res = rooms_receiver.recv() => { if let Ok(room_event) = res { match room_event { RoomEvent::MemberEvent(room_id, room) => on_room(room_id, room, &by_id_rooms).await, RoomEvent::InviteEvent(room_id, room) => on_joining_invitation(room_id, room, &by_id_rooms).await, RoomEvent::TopicEvent(room_id, topic) => on_room_topic(room_id, topic, &by_id_rooms).await, }; } }, } } } } pub async fn login( mut rx: UnboundedReceiver, app_settings: &GlobalSignal, session: &GlobalSignal, ) { while let Some(is_logged) = rx.next().await { if !is_logged { let homeserver_url = session.read().homeserver_url.clone(); let username = session.read().username.clone(); let password = session.read().password.clone(); if homeserver_url.is_some() && username.is_some() && password.is_some() { let client = Client::spawn(homeserver_url.unwrap()).await; if let Err(err) = client.init().await { error!("Following error occureds during client init: {}", err); } match client .login(LoginStyle::Password(username.unwrap(), password.unwrap())) .await { Ok(_) => { debug!("successfully logged"); session.write().is_logged = true; } Err(err) => { error!("Error during login: {err}"); // TODO: Handle invalid login // invalid_login.modify(|_| true); } } app_settings.write().set_requester(RefCell::new(client)); } else { warn!("At least one of the following values is/are invalid: homeserver, username or password"); } } else { warn!("already logged... skip login"); } } error!("=== LOGIN END ==="); } pub static APP_SETTINGS: GlobalSignal = Signal::global(AppSettings::new); pub static ROOMS: GlobalSignal = Signal::global(ByIdRooms::new); pub static SESSION: GlobalSignal = Signal::global(Session::new); pub static CHATS_WIN_INTERFACE: GlobalSignal = Signal::global(ChatsWinInterface::new);