#![allow(non_snake_case)] #[macro_use] extern crate cfg_if; mod domain; mod infrastructure; mod ui; mod utils; use std::rc::Rc; use dioxus::document::{Link, Style}; use dioxus::prelude::*; use futures_util::stream::StreamExt; use tracing::{debug, error, warn}; use tracing_subscriber::{prelude::*, EnvFilter}; use crate::{ domain::model::{messaging_interface::AccountMessagingProviderInterface, session::Session}, infrastructure::messaging::matrix::{client::Client, worker_tasks::LoginStyle}, ui::{ layouts::{conversations::Conversations, login::Login}, ACCOUNT, SESSION, }, }; cfg_if! { if #[cfg(target_family = "wasm")] { use tracing_web::MakeWebConsoleWriter; } else { use std::fs::File; use dioxus::desktop::Config; use time::format_description::well_known::Iso8601; use tracing_subscriber::fmt::time::UtcTime; use tracing_forest::ForestLayer; } } async fn login(mut rx: UnboundedReceiver, 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 (requester, account_events_receiver) = Client::spawn(homeserver_url.unwrap()).await; if let Err(err) = requester.init().await { warn!("Unable to login: {}", err); } match requester .login(LoginStyle::Password(username.unwrap(), password.unwrap())) .await { Ok(_) => { debug!("successfully logged"); session.write().is_logged = true; let requester = Rc::new(requester); dioxus::prelude::spawn(async move { ACCOUNT.write().set_messaging_provider(requester.clone()); let _ = requester .run_forever(&*ACCOUNT.read(), account_events_receiver) .await; }); } Err(err) => { error!("Error during login: {err}"); // TODO: Handle invalid login // invalid_login.modify(|_| true); return; } } } else { warn!("At least one of the following values is/are invalid: homeserver, username or password"); } } else { warn!("already logged... skip login"); } } } fn app() -> Element { let login_coro = use_coroutine(|rx| login(rx, &SESSION)); let is_logged = SESSION.read().is_logged; if !is_logged { login_coro.send(false); } rsx! { Link { href: asset!("public/fonts/Geist/Geist-Medium.woff2"), as: "font", type: "font/woff2" } Style { id: "style-head", "body {{ font-family: 'Geist'; font-weight: normal; }}" } if !is_logged { Login {} } else { Conversations {} } } } fn main() { let mut builder = LaunchBuilder::new(); let mut layers = Vec::new(); cfg_if! { if #[cfg(target_family = "wasm")] { let console_layer = tracing_subscriber::fmt::layer() .with_ansi(false) // Only partially supported across browsers .without_time() // std::time is not available in browsers, see note below .with_writer(MakeWebConsoleWriter::new()) // write events to the console .boxed(); layers.push(console_layer); } else { let config = Config::new().with_menu(None); builder = builder.with_cfg(config); let log_file = File::create("/tmp/bg92.log").unwrap(); let file_layer = tracing_subscriber::fmt::layer() .with_ansi(false) .with_writer(log_file) .with_timer(UtcTime::new(Iso8601::DATE_TIME)) .boxed(); layers.push(file_layer); let console_layer = ForestLayer::default().boxed(); layers.push(console_layer); } } tracing_subscriber::registry() .with(layers) .with(EnvFilter::from_default_env()) .init(); builder.launch(app); }