♻️ Replace flume with tokio and share Matrix client infos to chats

- Remove of the flume dependency.
- Add the capability to share data provided by the Matrix client to the ChatsWindow. Indeed, until the 0.6 Dioxus
  release, each window runs in a separate virtual DOM so the context and Fermi states are completely seperate
  (cf. https://discord.com/channels/899851952891002890/1188206938215948378).
This commit is contained in:
2023-12-25 23:14:43 +01:00
parent d7ba8130d3
commit ddeb94e887
8 changed files with 223 additions and 192 deletions

View File

@@ -1,5 +1,3 @@
use futures::select;
// 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
@@ -12,34 +10,36 @@ use fermi::*;
use matrix_sdk::room::Room as MatrixRoom;
use matrix_sdk::{
room::RoomMember,
ruma::{OwnedMxcUri, OwnedRoomId, OwnedUserId},
ruma::{OwnedRoomId, OwnedUserId},
};
use tokio::select;
use tracing::{debug, error, warn};
use crate::matrix_interface::client::{Client, RoomTopicEvent};
use crate::matrix_interface::requester::Receivers;
use crate::matrix_interface::requester::Requester;
use crate::matrix_interface::worker_tasks::LoginStyle;
#[derive(Clone, Debug)]
pub struct UserInfo {
pub avatar_url: Option<OwnedMxcUri>,
pub display_name: Option<String>,
pub blurhash: Option<String>,
}
// #[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,
}
}
}
// 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, Debug)]
pub struct Room {
@@ -80,106 +80,101 @@ impl PartialEq for Room {
}
pub type ByIdRooms = HashMap<OwnedRoomId, RefCell<Room>>;
pub type ByIdUserInfos = HashMap<OwnedUserId, UserInfo>;
// 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>,
}
// #[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 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 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 {}
// impl Eq for Store {}
pub struct AppSettings {
requester: Option<Box<Requester>>,
pub store: Store,
pub requester: Option<RefCell<Requester>>,
}
impl AppSettings {
pub fn new() -> Self {
Self {
requester: None,
store: Store::new(),
}
Self { requester: None }
}
pub fn set_requester(&mut self, requester: Box<Requester>) {
pub fn set_requester(&mut self, requester: RefCell<Requester>) {
self.requester = Some(requester);
}
}
pub static APP_SETTINGS: AtomRef<AppSettings> = AtomRef(|_| AppSettings::new());
async fn on_room(room_option: Option<Room>, rooms_ref: &UseAtomRef<ByIdRooms>) {
if let Some(room) = room_option {
let room_id = room.id();
async fn on_room(room: Room, rooms_ref: &UseAtomRef<ByIdRooms>) {
let room_id = room.id();
// TODO: Update rooms
rooms_ref
.write()
.insert(room_id, RefCell::<Room>::new(room));
}
// TODO: Update rooms
rooms_ref
.write()
.insert(room_id, RefCell::<Room>::new(room));
}
async fn on_room_topic(
room_topic_event_option: Option<RoomTopicEvent>,
rooms_ref: &UseAtomRef<ByIdRooms>,
) {
if let Some(room_topic_event) = room_topic_event_option {
let room_id = room_topic_event.0;
pub async fn on_room_topic(room_topic_event: RoomTopicEvent, rooms_ref: &UseAtomRef<ByIdRooms>) {
let room_id = room_topic_event.0;
if let Some(room_ref) = rooms_ref.read().get(&room_id) {
let topic = room_topic_event.1;
if let Some(room_ref) = rooms_ref.read().get(&room_id) {
let topic = room_topic_event.1;
let mut room = room_ref.borrow_mut();
room.topic = Some(RefCell::new(topic));
} else {
warn!("No room found with the \"{}\" id", room_id);
}
let mut room = room_ref.borrow_mut();
room.topic = Some(RefCell::new(topic));
} else {
warn!("No room found with the \"{}\" id", room_id);
}
}
pub async fn sync_rooms(
mut rx: UnboundedReceiver<bool>,
app_settings_ref: UseAtomRef<AppSettings>,
receivers: Receivers,
rooms_ref: UseAtomRef<ByIdRooms>,
) {
while let Some(_is_logged) = rx.next().await {
if let Some(requester) = &app_settings_ref.read().requester {
let mut room_stream = requester.rooms_receiver.stream();
let mut room_topic_stream = requester.room_topic_receiver.stream();
let mut rooms_receiver = receivers.rooms_receiver.borrow_mut();
let mut room_topic_receiver = receivers.room_topic_receiver.borrow_mut();
loop {
select! {
room = room_stream.next() => on_room(room, &rooms_ref).await,
room_topic_event = room_topic_stream.next() => on_room_topic(room_topic_event, &rooms_ref).await,
loop {
select! {
res = rooms_receiver.recv() => {
if let Ok(room) = res {
on_room(room, &rooms_ref).await;
}
},
res = room_topic_receiver.recv() => {
if let Ok(room_topic_event) = res {
on_room_topic(room_topic_event, &rooms_ref).await;
}
}
}
}
@@ -215,7 +210,7 @@ pub async fn login(
// invalid_login.modify(|_| true);
}
}
app_settings_ref.write().set_requester(Box::new(client));
app_settings_ref.write().set_requester(RefCell::new(client));
} else {
warn!("At least one of the following values is/are invalid: homeserver, username or password");
}