tracing package doesn't support web platform when dioxus-logger `will eventually support every target that Dioxus does. Currently only web and desktop platforms are supported.`
278 lines
8.3 KiB
Rust
278 lines
8.3 KiB
Rust
// 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 futures_util::stream::StreamExt;
|
|
use std::cell::RefCell;
|
|
use std::{collections::HashMap, sync::Arc};
|
|
|
|
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::ui::components::chats_window::interface::Interface as ChatsWinInterface;
|
|
|
|
// #[derive(Clone, Debug)]
|
|
// pub struct UserInfo {
|
|
// pub avatar_url: Option<OwnedMxcUri>,
|
|
// pub display_name: Option<String>,
|
|
// pub blurhash: Option<String>,
|
|
// }
|
|
|
|
// impl UserInfo {
|
|
// pub fn new(
|
|
// avatar_url: Option<OwnedMxcUri>,
|
|
// display_name: Option<String>,
|
|
// blurhash: Option<String>,
|
|
// ) -> Self {
|
|
// Self {
|
|
// avatar_url,
|
|
// display_name,
|
|
// blurhash,
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
#[derive(Clone)]
|
|
pub struct Room {
|
|
pub matrix_room: Arc<MatrixRoom>,
|
|
pub topic: Option<RefCell<String>>,
|
|
pub members: HashMap<OwnedUserId, RoomMember>,
|
|
pub is_direct: Option<bool>,
|
|
}
|
|
|
|
impl Room {
|
|
pub fn new(
|
|
matrix_room: Arc<MatrixRoom>,
|
|
topic: Option<RefCell<String>>,
|
|
is_direct: Option<bool>,
|
|
) -> 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<String> {
|
|
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<OwnedRoomId, RefCell<Room>>;
|
|
// pub type ByIdUserInfos = HashMap<OwnedUserId, UserInfo>;
|
|
|
|
// #[derive(Clone)]
|
|
// pub struct Store {
|
|
// pub is_logged: bool,
|
|
// pub rooms: ByIdRooms,
|
|
// pub user_infos: ByIdUserInfos,
|
|
// pub user_id: Option<OwnedUserId>,
|
|
// }
|
|
|
|
// 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<RefCell<Requester>>,
|
|
}
|
|
|
|
impl AppSettings {
|
|
pub fn new() -> Self {
|
|
Self { requester: None }
|
|
}
|
|
|
|
pub fn set_requester(&mut self, requester: RefCell<Requester>) {
|
|
self.requester = Some(requester);
|
|
}
|
|
}
|
|
|
|
async fn on_room(room_id: OwnedRoomId, room: Room, by_id_rooms: &GlobalSignal<ByIdRooms>) {
|
|
// TODO: Update rooms
|
|
by_id_rooms
|
|
.write()
|
|
.insert(room_id, RefCell::<Room>::new(room));
|
|
}
|
|
|
|
async fn on_joining_invitation(
|
|
room_id: OwnedRoomId,
|
|
room: Room,
|
|
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
|
) {
|
|
debug!(
|
|
"You're invited to join the \"{}\" room",
|
|
room.name().unwrap()
|
|
);
|
|
// TODO: Update rooms
|
|
by_id_rooms
|
|
.write()
|
|
.insert(room_id, RefCell::<Room>::new(room));
|
|
}
|
|
|
|
async fn on_room_topic(room_id: OwnedRoomId, topic: String, by_id_rooms: &GlobalSignal<ByIdRooms>) {
|
|
if let Some(room) = by_id_rooms.read().get(&room_id) {
|
|
let mut room = room.borrow_mut();
|
|
room.topic = Some(RefCell::new(topic));
|
|
} else {
|
|
warn!("No room found with the \"{}\" id", room_id);
|
|
}
|
|
}
|
|
|
|
pub async fn sync_messages(by_id_rooms: &GlobalSignal<ByIdRooms>, room_id: OwnedRoomId) {
|
|
error!("== sync_messages ==");
|
|
|
|
}
|
|
|
|
pub async fn sync_rooms(
|
|
mut rx: UnboundedReceiver<bool>,
|
|
receivers: Receivers,
|
|
by_id_rooms: &GlobalSignal<ByIdRooms>,
|
|
) {
|
|
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<bool>,
|
|
app_settings: &GlobalSignal<AppSettings>,
|
|
session: &GlobalSignal<Session>,
|
|
) {
|
|
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}");
|
|
// 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 struct Session {
|
|
pub homeserver_url: Option<String>,
|
|
pub username: Option<String>,
|
|
pub password: Option<String>,
|
|
pub is_logged: bool,
|
|
}
|
|
impl Session {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
homeserver_url: None,
|
|
username: None,
|
|
password: None,
|
|
is_logged: false,
|
|
}
|
|
}
|
|
pub fn update(
|
|
&mut self,
|
|
homeserver_url: Option<String>,
|
|
username: Option<String>,
|
|
password: Option<String>,
|
|
) {
|
|
self.homeserver_url = homeserver_url;
|
|
self.username = username;
|
|
self.password = password;
|
|
}
|
|
}
|
|
|
|
pub static APP_SETTINGS: GlobalSignal<AppSettings> = Signal::global(AppSettings::new);
|
|
pub static ROOMS: GlobalSignal<ByIdRooms> = Signal::global(ByIdRooms::new);
|
|
pub static SESSION: GlobalSignal<Session> = Signal::global(Session::new);
|
|
pub static CHATS_WIN_INTERFACE: GlobalSignal<ChatsWinInterface> =
|
|
Signal::global(ChatsWinInterface::new);
|