From 6b8b30e6baa51a4915f81417757cc21a92e6b1ad Mon Sep 17 00:00:00 2001 From: Val Lorentz Date: Sun, 29 Oct 2023 21:25:34 +0100 Subject: [PATCH] Implement account config + login --- .config/config.json5 | 6 ++++++ Cargo.toml | 6 ++++-- src/app.rs | 31 ++++++++++++++++++++++++++++++- src/components/home.rs | 11 +++++++---- src/config.rs | 33 +++++++++------------------------ src/main.rs | 2 +- 6 files changed, 57 insertions(+), 32 deletions(-) diff --git a/.config/config.json5 b/.config/config.json5 index f880b2b..8189b8d 100644 --- a/.config/config.json5 +++ b/.config/config.json5 @@ -1,4 +1,10 @@ { + "accounts": [ + { + "user_id": "@alice:example.org", + "password": "hunter2", + }, + ], "keybindings": { "Home": { "": "/quit", // Quit the application diff --git a/Cargo.toml b/Cargo.toml index 2151569..c2be51e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,10 +39,12 @@ human-panic = "1.2.0" inventory = "0.3" lazy_static = "1.4.0" libc = "0.2.148" +log = "0.4.20" +nonempty = { version = "0.8.1", features = ["serialize"] } signal-hook = "0.3.17" -# Misc -log = "0.4.20" +# Matrix +matrix-sdk = { version = "0.6.2", features = ["eyre", "markdown"] } # UI crossterm = { version = "0.27.0", features = ["serde", "event-stream"] } diff --git a/src/app.rs b/src/app.rs index 40a7472..9af1d9b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,6 @@ use color_eyre::eyre::{Result, WrapErr}; use crossterm::event::KeyEvent; +use nonempty::NonEmpty; use ratatui::prelude::Rect; use serde::{Deserialize, Serialize}; use tokio::sync::mpsc; @@ -15,6 +16,7 @@ use crate::{ pub struct App { pub config: Config, + pub clients: NonEmpty, pub commands: RataCommands, pub tick_rate: f64, pub frame_rate: f64, @@ -26,17 +28,44 @@ pub struct App { } impl App { - pub fn new(tick_rate: f64, frame_rate: f64) -> Result { + pub async fn new(tick_rate: f64, frame_rate: f64) -> Result { let home = Home::new(); let fps = FpsCounter::default(); let config = Config::new()?; let mode = Mode::Home; + let future_clients = config.accounts.clone().map(|conf| { + tokio::spawn(async move { + let server_name = conf.user_id.server_name(); + let client = matrix_sdk::Client::builder() + .server_name(server_name) + .build() + .await + .with_context(|| format!("Could not initialize client for {}", server_name))?; + client + .login_username(&conf.user_id, &conf.password) + .send() + .await + .with_context(|| format!("Could not login as {}", conf.user_id))?; + Ok::<_, color_eyre::eyre::Report>(client) + }) + }); + let mut clients = Vec::new(); + for client in futures::future::join_all(future_clients).await { + clients.push( + client + .context("Could not join client init task")? + .context("Could not connect to all accounts")?, + ); + } + let clients = NonEmpty::collect(clients).expect("map on NonEmpty returned empty vec"); + let mut app = Self { tick_rate, frame_rate, components: vec![Box::new(home), Box::new(fps)], should_quit: false, should_suspend: false, + clients, config, commands: RataCommands::new(), mode, diff --git a/src/components/home.rs b/src/components/home.rs index bd00154..fe97222 100644 --- a/src/components/home.rs +++ b/src/components/home.rs @@ -1,10 +1,11 @@ use std::{collections::HashMap, time::Duration}; -use color_eyre::eyre::Result; +use color_eyre::eyre::{Result, WrapErr}; use crossterm::event::{KeyCode, KeyEvent}; use ratatui::{prelude::*, widgets::*}; use serde::{Deserialize, Serialize}; use tokio::sync::mpsc::UnboundedSender; +use tokio::sync::OnceCell; use super::{Component, Frame}; use crate::{ @@ -15,7 +16,7 @@ use crate::{ #[derive(Default)] pub struct Home { command_tx: Option>, - config: Config, + config: OnceCell, } impl Home { @@ -31,8 +32,10 @@ impl Component for Home { } fn register_config_handler(&mut self, config: Config) -> Result<()> { - self.config = config; - Ok(()) + self + .config + .set(config) + .context("Home config was already set") } fn update(&mut self, action: Action) -> Result> { diff --git a/src/config.rs b/src/config.rs index 215e01e..1a4f3c4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,8 +13,6 @@ use serde_json::Value as JsonValue; use crate::{action::Action, mode::Mode}; -const CONFIG: &str = include_str!("../.config/config.json5"); - #[derive(Clone, Debug, Deserialize, Default)] pub struct AppConfig { #[serde(default)] @@ -23,10 +21,17 @@ pub struct AppConfig { pub _config_dir: PathBuf, } -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Deserialize)] +pub struct AccountConfig { + pub user_id: Box, + pub password: String, +} + +#[derive(Clone, Debug, Deserialize)] pub struct Config { #[serde(default, flatten)] pub config: AppConfig, + pub accounts: nonempty::NonEmpty, #[serde(default)] pub keybindings: KeyBindings, #[serde(default)] @@ -35,7 +40,6 @@ pub struct Config { impl Config { pub fn new() -> Result { - let default_config: Config = json5::from_str(CONFIG).unwrap(); let data_dir = crate::utils::get_data_dir(); let config_dir = crate::utils::get_config_dir(); let mut builder = config::Config::builder() @@ -64,26 +68,7 @@ impl Config { log::error!("No configuration file found. Application may not behave as expected"); } - let mut cfg: Self = builder.build()?.try_deserialize()?; - - for (mode, default_bindings) in default_config.keybindings.iter() { - let user_bindings = cfg.keybindings.entry(*mode).or_default(); - for (key, cmd) in default_bindings.iter() { - user_bindings - .entry(key.clone()) - .or_insert_with(|| cmd.clone()); - } - } - for (mode, default_styles) in default_config.styles.iter() { - let user_styles = cfg.styles.entry(*mode).or_default(); - for (style_key, style) in default_styles.iter() { - user_styles - .entry(style_key.clone()) - .or_insert_with(|| style.clone()); - } - } - - Ok(cfg) + Ok(builder.build()?.try_deserialize()?) } } diff --git a/src/main.rs b/src/main.rs index 51be876..49d9bca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,7 @@ async fn tokio_main() -> Result<()> { initialize_panic_handler()?; let args = Cli::parse(); - let mut app = App::new(args.tick_rate, args.frame_rate)?; + let mut app = App::new(args.tick_rate, args.frame_rate).await?; app.run().await?; Ok(())