🏗️ Rearchitecting the interface with the MatrixClient
- Replace RwStore with channels. - Use of fermi to handle application data. - Use of tracing.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use dioxus::prelude::*;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::components::avatar_selector::AvatarSelector;
|
||||
use crate::components::chats_window::edit_section::EditSection;
|
||||
@@ -7,6 +8,8 @@ use crate::components::icons::DownArrowIcon;
|
||||
turf::style_sheet!("src/components/chats_window/chats_window.scss");
|
||||
|
||||
pub fn ChatsWindow(cx: Scope) -> Element {
|
||||
debug!("ChatsWindow rendering");
|
||||
|
||||
let room_names = vec![
|
||||
"MON POTE",
|
||||
"Second room",
|
||||
|
@@ -1,37 +1,47 @@
|
||||
use std::cell::RefCell;
|
||||
use std::time::Duration;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_std::utils::rw::UseRw;
|
||||
use fermi::*;
|
||||
use tokio::time::sleep;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::base::Room;
|
||||
use crate::base::Store;
|
||||
use crate::components::contacts_window::contacts_section::ContactsSection;
|
||||
use crate::base::AppSettings;
|
||||
use crate::base::{ByIdRooms, Room, APP_SETTINGS, ROOMS};
|
||||
use crate::components::contacts_window::contacts_section::{
|
||||
filter_people_conversations, filter_room_conversations, ContactsSection,
|
||||
};
|
||||
|
||||
turf::style_sheet!("src/components/contacts_window/contacts.scss");
|
||||
|
||||
#[inline_props]
|
||||
pub fn Contacts<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
println!("Contacts rendering");
|
||||
pub fn Contacts(cx: Scope) -> Element {
|
||||
debug!("Contacts rendering");
|
||||
|
||||
let store = rw_store.read().unwrap();
|
||||
let app_settings_atom = use_atom_ref(cx, &APP_SETTINGS);
|
||||
let rooms_atom = use_atom_ref(cx, &ROOMS);
|
||||
|
||||
let rooms = &store.rooms;
|
||||
async fn sync_rooms(app_settings: UseAtomRef<AppSettings>, rooms_atom: UseAtomRef<ByIdRooms>) {
|
||||
loop {
|
||||
let requester = &app_settings.read().requester;
|
||||
|
||||
let rooms_len = rooms.len();
|
||||
let mut groups = Vec::<Room>::with_capacity(rooms_len);
|
||||
let mut directs = Vec::<Room>::with_capacity(rooms_len);
|
||||
|
||||
for arc_room in rooms.values() {
|
||||
let room = arc_room.read().unwrap().to_owned();
|
||||
|
||||
let is_direct = room.is_direct.unwrap();
|
||||
if is_direct {
|
||||
directs.push(room);
|
||||
} else {
|
||||
groups.push(room);
|
||||
if requester.is_some() {
|
||||
let rooms_receiver = &requester.as_ref().unwrap().rooms_receiver;
|
||||
let room = rooms_receiver.recv_async().await.unwrap();
|
||||
let room_id = room.id();
|
||||
dbg!(&room_id);
|
||||
rooms_atom
|
||||
.write()
|
||||
.insert(room_id, RefCell::<Room>::new(room));
|
||||
} else {
|
||||
sleep(Duration::from_millis(1000)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use_coroutine(cx, |_: UnboundedReceiver<()>| {
|
||||
sync_rooms(app_settings_atom.clone(), rooms_atom.clone())
|
||||
});
|
||||
|
||||
// TODO: Test overflow
|
||||
// TODO: Add offline users ?
|
||||
cx.render(rsx! {
|
||||
@@ -40,8 +50,8 @@ pub fn Contacts<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
div {
|
||||
class: ClassName::CONTACTS,
|
||||
|
||||
ContactsSection {name: "Groups", contacts: RefCell::new(groups)},
|
||||
ContactsSection {name: "Available", contacts: RefCell::new(directs)},
|
||||
ContactsSection {name: "Groups", filter: &filter_room_conversations},
|
||||
ContactsSection {name: "Available", filter: &filter_people_conversations},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -3,9 +3,11 @@ use std::cell::RefCell;
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_free_icons::icons::io_icons::IoChevronDown;
|
||||
use dioxus_free_icons::Icon;
|
||||
use fermi::prelude::*;
|
||||
use matrix_sdk::RoomState;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::base::Room;
|
||||
use crate::base::{ByIdRooms, Room, ROOMS};
|
||||
|
||||
turf::style_sheet!("src/components/contacts_window/contacts_section.scss");
|
||||
|
||||
@@ -19,11 +21,46 @@ fn ContactsArrow(cx: Scope) -> Element {
|
||||
})
|
||||
}
|
||||
|
||||
static NO_NAME_REPR: &str = "No name";
|
||||
static NO_SUBJECT_REPR: &str = "No subject";
|
||||
|
||||
#[inline_props]
|
||||
pub fn ContactsSection<'a>(cx: Scope, name: &'a str, contacts: RefCell<Vec<Room>>) -> Element {
|
||||
println!("ContactsSection rendering");
|
||||
pub fn filter_people_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
let rooms = rooms_atom.read();
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
||||
|
||||
for room in rooms.values() {
|
||||
let is_direct = room.borrow().is_direct.unwrap();
|
||||
if !is_direct {
|
||||
filtered_rooms.push(room.to_owned());
|
||||
}
|
||||
}
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
pub fn filter_room_conversations(rooms_atom: UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>> {
|
||||
let rooms = rooms_atom.read();
|
||||
let mut filtered_rooms = Vec::<RefCell<Room>>::with_capacity(rooms.len());
|
||||
|
||||
for room in rooms.values() {
|
||||
let is_direct = room.borrow().is_direct.unwrap();
|
||||
if is_direct {
|
||||
filtered_rooms.push(room.to_owned());
|
||||
}
|
||||
}
|
||||
filtered_rooms
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ContactsSection<'a>(
|
||||
cx: Scope,
|
||||
name: &'a str,
|
||||
filter: &'a dyn Fn(UseAtomRef<ByIdRooms>) -> Vec<RefCell<Room>>,
|
||||
) -> Element {
|
||||
debug!("ContactsSection rendering");
|
||||
|
||||
let rooms_atom = use_atom_ref(cx, &ROOMS);
|
||||
let contacts = filter(rooms_atom.clone());
|
||||
let contacts_len = contacts.len();
|
||||
|
||||
let show = use_state(cx, || false);
|
||||
|
||||
@@ -33,11 +70,19 @@ pub fn ContactsSection<'a>(cx: Scope, name: &'a str, contacts: RefCell<Vec<Room>
|
||||
]
|
||||
.join(" ");
|
||||
|
||||
let contacts_len = contacts.borrow().len();
|
||||
let rendered_contacts = contacts.into_iter().map(|room_ref| {
|
||||
let room = room_ref.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 rendered_contacts = contacts.borrow_mut().clone().into_iter().map(|room| {
|
||||
let room_name = room.name().unwrap();
|
||||
let is_invited = room.matrix_room.state() == RoomState::Invited;
|
||||
|
||||
let formatted = format!(
|
||||
"{room_name} - {}",
|
||||
if is_invited {
|
||||
@@ -47,8 +92,6 @@ pub fn ContactsSection<'a>(cx: Scope, name: &'a str, contacts: RefCell<Vec<Room>
|
||||
}
|
||||
);
|
||||
|
||||
let room_topic = room.topic.unwrap_or(NO_SUBJECT_REPR.to_string()).to_owned();
|
||||
|
||||
rsx!(li {
|
||||
img {
|
||||
src: "./images/status_online.png",
|
||||
@@ -60,8 +103,7 @@ pub fn ContactsSection<'a>(cx: Scope, name: &'a str, contacts: RefCell<Vec<Room>
|
||||
style: "color: darkgrey;",
|
||||
room_topic,
|
||||
},
|
||||
},
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
cx.render(rsx! {
|
||||
|
@@ -1,14 +1,14 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_std::utils::rw::UseRw;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::base::Store;
|
||||
use crate::components::contacts_window::contacts::Contacts;
|
||||
use crate::components::contacts_window::user_infos::UserInfos;
|
||||
|
||||
turf::style_sheet!("src/components/contacts_window/contacts_window.scss");
|
||||
|
||||
#[inline_props]
|
||||
pub fn ContactsWindow<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
pub fn ContactsWindow(cx: Scope) -> Element {
|
||||
debug!("ContactsWindow rendering");
|
||||
|
||||
cx.render(rsx! {
|
||||
style { STYLE_SHEET },
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn ContactsWindow<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
class: ClassName::USER_INFO,
|
||||
},
|
||||
|
||||
UserInfos {rw_store: rw_store},
|
||||
UserInfos {},
|
||||
},
|
||||
|
||||
div {
|
||||
@@ -84,7 +84,7 @@ pub fn ContactsWindow<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
},
|
||||
},
|
||||
|
||||
Contacts {rw_store: rw_store},
|
||||
Contacts {},
|
||||
|
||||
div {
|
||||
class: ClassName::FOOTER,
|
||||
|
@@ -1,7 +1,8 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_std::utils::rw::UseRw;
|
||||
use fermi::*;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::base::Store;
|
||||
use crate::base::APP_SETTINGS;
|
||||
use crate::components::avatar_selector::AvatarSelector;
|
||||
use crate::components::icons::DownArrowIcon;
|
||||
|
||||
@@ -9,15 +10,31 @@ turf::style_sheet!("src/components/contacts_window/user_infos.scss");
|
||||
|
||||
static MESSAGE_PLACEHOLDER: &str = "<Enter a personal message>";
|
||||
|
||||
#[inline_props]
|
||||
pub fn UserInfos<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
pub fn UserInfos(cx: Scope) -> Element {
|
||||
debug!("UserInfos rendering");
|
||||
|
||||
let app_settings = use_atom_ref(cx, &APP_SETTINGS);
|
||||
let store = &app_settings.read().store;
|
||||
|
||||
println!("----------------------------------");
|
||||
println!("UserInfos rendering");
|
||||
// println!("store={:?}", &store);
|
||||
dbg!(&store.user_id);
|
||||
println!("----------------------------------");
|
||||
|
||||
let store = rw_store.read().unwrap().clone();
|
||||
// let user_id = store.user_id..as_ref().unwrap();
|
||||
|
||||
let user_id = store.user_id.unwrap();
|
||||
let user_info = store.user_infos.get(&user_id).unwrap();
|
||||
let user_display_name = user_info.display_name.as_ref().unwrap();
|
||||
// let mut user_info_option = None;
|
||||
let mut user_display_name_option = None;
|
||||
|
||||
let user_id_option = &store.user_id;
|
||||
if user_id_option.is_some() {
|
||||
let user_id = user_id_option.as_ref().unwrap();
|
||||
let user_info_option = store.user_infos.get(user_id);
|
||||
if user_info_option.is_some() {
|
||||
user_display_name_option = user_info_option.unwrap().display_name.as_ref();
|
||||
}
|
||||
}
|
||||
|
||||
cx.render(rsx! {
|
||||
style { STYLE_SHEET },
|
||||
@@ -37,7 +54,7 @@ pub fn UserInfos<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
class: ClassName::USER_ID,
|
||||
p {
|
||||
class: ClassName::USER_NAME,
|
||||
"{user_display_name}",
|
||||
if user_display_name_option.is_some() { "{user_display_name}" } else { "AIE" },
|
||||
},
|
||||
p {
|
||||
class: ClassName::USER_STATUS,
|
||||
|
@@ -1,10 +1,10 @@
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_std::utils::rw::UseRw;
|
||||
use fermi::*;
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::base::{AppSettings, Store};
|
||||
use crate::base::APP_SETTINGS;
|
||||
use crate::components::avatar_selector::AvatarSelector;
|
||||
use crate::components::header::Header;
|
||||
use crate::matrix_client::{LoginStyle, MatrixClient};
|
||||
@@ -13,14 +13,14 @@ turf::style_sheet!("src/components/login.scss");
|
||||
|
||||
static EMPTY_PLACEHOLDER: &str = "Tmp placeholder";
|
||||
|
||||
#[inline_props]
|
||||
pub fn Login<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
let app_context = use_shared_state::<AppSettings>(cx).unwrap();
|
||||
pub fn Login(cx: Scope) -> Element {
|
||||
debug!("Login rendering");
|
||||
|
||||
let app_settings = use_atom_ref(cx, &APP_SETTINGS);
|
||||
|
||||
let invalid_login = use_state(cx, || false);
|
||||
let login = use_ref(cx, || Login::new());
|
||||
|
||||
let arc_store = Arc::new(rw_store.to_owned().clone());
|
||||
|
||||
let password_class = if **invalid_login {
|
||||
ClassName::INVALID_INPUT
|
||||
} else {
|
||||
@@ -29,7 +29,7 @@ pub fn Login<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
|
||||
let run_matrix_client = move |_| {
|
||||
cx.spawn({
|
||||
to_owned![app_context, invalid_login, login, arc_store];
|
||||
to_owned![invalid_login, login, app_settings];
|
||||
|
||||
let login_ref = login.read();
|
||||
let homeserver_url = login_ref.homeserver_url.clone().unwrap();
|
||||
@@ -37,20 +37,22 @@ pub fn Login<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
let password = login_ref.password.clone().unwrap();
|
||||
|
||||
async move {
|
||||
let requester = MatrixClient::spawn(homeserver_url, arc_store.clone()).await;
|
||||
requester.init();
|
||||
let new_matrix_client = MatrixClient::spawn(homeserver_url).await;
|
||||
|
||||
match requester.login(LoginStyle::Password(username, password)) {
|
||||
new_matrix_client.init();
|
||||
|
||||
match new_matrix_client.login(LoginStyle::Password(username, password)) {
|
||||
Ok(_) => {
|
||||
println!("successfully logged");
|
||||
debug!("successfully logged");
|
||||
app_settings.write().store.is_logged = true;
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error during login: {err}");
|
||||
error!("Error during login: {err}");
|
||||
invalid_login.modify(|_| true);
|
||||
}
|
||||
}
|
||||
|
||||
app_context.write().requester = Some(Arc::new(requester));
|
||||
app_settings.write().requester = Some(new_matrix_client);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@@ -1,20 +1,23 @@
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_std::utils::rw::UseRw;
|
||||
use fermi::*;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::base::Store;
|
||||
use crate::base::APP_SETTINGS;
|
||||
use crate::components::contacts_window::contacts_window::ContactsWindow;
|
||||
use crate::components::login::Login;
|
||||
|
||||
#[inline_props]
|
||||
pub fn MainWindow<'a>(cx: Scope, rw_store: &'a UseRw<Store>) -> Element {
|
||||
let is_logged = rw_store.read().unwrap().is_logged;
|
||||
pub fn MainWindow(cx: Scope) -> Element {
|
||||
debug!("MainWindow rendering");
|
||||
|
||||
let app_settings = use_atom_ref(cx, &APP_SETTINGS);
|
||||
let is_logged = app_settings.read().store.is_logged;
|
||||
|
||||
cx.render(rsx! {
|
||||
if is_logged {
|
||||
rsx!(ContactsWindow {rw_store: rw_store})
|
||||
rsx!(ContactsWindow {})
|
||||
}
|
||||
else {
|
||||
rsx!(Login {rw_store: rw_store})
|
||||
rsx!(Login {})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user