From 35225a14dbce0e69129e309881b58b178030ab72 Mon Sep 17 00:00:00 2001 From: Soispha Date: Sun, 9 Jul 2023 07:58:18 +0200 Subject: [PATCH 1/3] Style(treewide): Format all files with rustfmt --- src/accounts/mod.rs | 78 +++++++---- src/app/event.rs | 333 ++++++++++++++++++++++++++------------------ src/app/mod.rs | 91 ++++++------ src/app/status.rs | 67 +++++---- src/main.rs | 4 +- src/ui/mod.rs | 333 ++++++++++++++++++++++++++++---------------- 6 files changed, 556 insertions(+), 350 deletions(-) diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs index 2e2fc08..f273104 100644 --- a/src/accounts/mod.rs +++ b/src/accounts/mod.rs @@ -1,13 +1,13 @@ use std::fs; -use matrix_sdk::{Client, - config::SyncSettings, - ruma::{user_id, - events::room::message::SyncRoomMessageEvent, - exports::serde_json}, - Session}; + use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + ruma::{events::room::message::SyncRoomMessageEvent, exports::serde_json, user_id}, + Client, Session, +}; use serde::{Deserialize, Serialize}; -use cli_log::{error, warn, info}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Account { @@ -33,7 +33,7 @@ pub struct AccountsManager { } impl Account { - pub fn name (&self) -> &String { + pub fn name(&self) -> &String { &self.name } @@ -43,11 +43,12 @@ impl Account { } impl AccountsManager { - pub fn new(config:Option) -> Self { + pub fn new(config: Option) -> Self { return match config { Some(s) => { info!("Loading serialized AccountsManager"); - let accounts_data:AccountsData = serde_json::from_str(&s).expect("failed to deserialize json"); + let accounts_data: AccountsData = + serde_json::from_str(&s).expect("failed to deserialize json"); let mut clients = Vec::new(); clients.resize(accounts_data.accounts.len(), None); Self { @@ -56,7 +57,7 @@ impl AccountsManager { accounts: accounts_data.accounts, clients, } - }, + } None => { info!("Creating empty AccountsManager"); Self { @@ -66,7 +67,7 @@ impl AccountsManager { clients: Vec::new(), } } - } + }; } pub async fn restore(&mut self) -> Result<()> { @@ -74,7 +75,12 @@ impl AccountsManager { Ok(()) } - pub async fn add(&mut self, homeserver: &String, username: &String, password: &String) -> Result { + pub async fn add( + &mut self, + homeserver: &String, + username: &String, + password: &String, + ) -> Result { let id = self.num_accounts; self.num_accounts += 1; @@ -84,7 +90,8 @@ impl AccountsManager { .build() .await?; - client.login_username(username, password) + client + .login_username(username, password) .initial_device_display_name("Trinitrix") .send() .await?; @@ -94,9 +101,13 @@ impl AccountsManager { let account = Account { homeserver: homeserver.to_string(), id, - name: client.account().get_display_name().await?.expect("failed to fetch display name"), + name: client + .account() + .get_display_name() + .await? + .expect("failed to fetch display name"), session: session.clone(), - sync_token: None + sync_token: None, }; self.logout().await?; @@ -105,12 +116,16 @@ impl AccountsManager { self.clients.push(Some(client)); self.save()?; - info!("Logged in as '{}' device ID: {}", session.user_id.to_string(), session.device_id.to_string()); + info!( + "Logged in as '{}' device ID: {}", + session.user_id.to_string(), + session.device_id.to_string() + ); Ok(id) } - pub async fn login(&mut self, account_id:u32) -> Result<()> { + pub async fn login(&mut self, account_id: u32) -> Result<()> { self.logout().await?; // log out the current account let account = if account_id >= self.num_accounts { @@ -120,17 +135,28 @@ impl AccountsManager { self.get(account_id).expect("Account lookup failed") }; - if self.clients.get(account_id as usize).expect("client lookup failed").is_none() { - info!("No client cached for account: '{}' -> requesting a new one", &account.session.user_id); + if self + .clients + .get(account_id as usize) + .expect("client lookup failed") + .is_none() + { + info!( + "No client cached for account: '{}' -> requesting a new one", + &account.session.user_id + ); let client = Client::builder() .homeserver_url(&account.homeserver) - .sled_store(format!("userdata/{account_id}"), Some("supersecure")) ? + .sled_store(format!("userdata/{account_id}"), Some("supersecure"))? .build() .await?; client.restore_login(account.session.clone()).await?; self.clients.insert(account_id as usize, Some(client)); } else { - info!("Using cached client for account: '{}'", &account.session.user_id); + info!( + "Using cached client for account: '{}'", + &account.session.user_id + ); }; info!("Restored account"); @@ -156,7 +182,7 @@ impl AccountsManager { Ok(()) } - pub fn save(&self) -> Result<()>{ + pub fn save(&self) -> Result<()> { let accounts_data = AccountsData { current_account: self.current_account, accounts: self.accounts.clone(), @@ -188,5 +214,7 @@ impl AccountsManager { } } - pub fn num_accounts(&self) -> u32 { self.num_accounts } -} \ No newline at end of file + pub fn num_accounts(&self) -> u32 { + self.num_accounts + } +} diff --git a/src/app/event.rs b/src/app/event.rs index 02226f1..9d0c8bc 100644 --- a/src/app/event.rs +++ b/src/app/event.rs @@ -1,14 +1,27 @@ -use crate::app::{App, status::{Status, State}}; -use crate::ui; -use tokio::time::Duration; -use tokio::sync::{mpsc, broadcast}; +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + room::Room, + ruma::events::room::{ + member::StrippedRoomMemberEvent, + message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, + }, + Client, LoopCtrl, +}; +use tokio::{ + sync::{broadcast, mpsc}, + time::Duration, +}; use tokio_util::sync::CancellationToken; -use anyhow::{Result, Error}; -use matrix_sdk::{Client, room::{Room}, config::SyncSettings, ruma::events::room::{ - member::StrippedRoomMemberEvent, - message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, -}, LoopCtrl}; -use cli_log::{error, warn, info}; + +use crate::{ + app::{ + status::{State, Status}, + App, + }, + ui, +}; #[derive(Debug)] pub enum EventStatus { @@ -20,7 +33,7 @@ pub enum EventStatus { #[derive(Debug)] pub struct Event { input_event: Option, - matrix_event: Option + matrix_event: Option, } pub struct EventBuilder { @@ -42,7 +55,6 @@ impl Default for EventBuilder { event: Event::default(), } } - } impl EventBuilder { @@ -51,7 +63,10 @@ impl EventBuilder { self } - fn matrix_event(&mut self, matrix_event: matrix_sdk::deserialized_responses::SyncResponse) -> &Self { + fn matrix_event( + &mut self, + matrix_event: matrix_sdk::deserialized_responses::SyncResponse, + ) -> &Self { self.event.matrix_event = Some(matrix_event); self } @@ -66,7 +81,6 @@ impl EventBuilder { impl Event { pub async fn handle(&self, app: &mut App<'_>) -> Result { - if self.matrix_event.is_some() { return self.handle_matrix(app).await; } @@ -88,7 +102,11 @@ impl Event { None => continue, }; for m_event in m_room.timeline.events.clone() { - let event = m_event.event.deserialize().unwrap().into_full_event(m_room_id.clone()); + let event = m_event + .event + .deserialize() + .unwrap() + .into_full_event(m_room_id.clone()); room.timeline_add(event); } } @@ -99,99 +117,125 @@ impl Event { async fn handle_main(&self, app: &mut App<'_>) -> Result { if self.input_event.is_some() { match tui_textarea::Input::from(self.input_event.clone().unwrap()) { - tui_textarea::Input { key: tui_textarea::Key::Esc, .. } => return Ok(EventStatus::Terminate), + tui_textarea::Input { + key: tui_textarea::Key::Esc, + .. + } => return Ok(EventStatus::Terminate), tui_textarea::Input { key: tui_textarea::Key::Tab, .. } => { app.ui.cycle_main_input_position(); } - input => { - match app.ui.input_position() { - ui::MainInputPosition::MessageCompose => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Enter, alt: true, ..} => { - match app.status.room_mut() { - Some(room) => { - room.send(app.ui.message_compose.lines().join("\n")).await?; - app.ui.message_compose_clear(); - }, - None => () - }; - } - _ => { app.ui.message_compose.input(input); } - }; - }, - ui::MainInputPosition::Rooms => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Up, ..} => { - let i = match app.ui.rooms_state.selected() { - Some(i) => { - if i > 0 { i - 1 } - else { i } - }, - None => 0, - }; - app.ui.rooms_state.select(Some(i)); - app.status.set_room_by_index(i)?; - }, - tui_textarea::Input {key: tui_textarea::Key::Down, ..} => { - let i = match app.ui.rooms_state.selected() { - Some(i) => { - if i < app.status.rooms().len() { i + 1 } - else { i } - }, - None => 0, - }; - app.ui.rooms_state.select(Some(i)); - app.status.set_room_by_index(i)?; - }, - _ => () - }; - }, - ui::MainInputPosition::Messages => { - match input { - tui_textarea::Input {key: tui_textarea::Key::Up, ..} => { - match app.status.room_mut(){ - Some(room) => { - let len = room.timeline().len(); - let i = match room.view_scroll() { - Some(i) => i+1, - None => 0, - }; - if i < len { - room.set_view_scroll(Some(i)) - } - if i <= len - 5 { - room.poll_old_timeline().await?; - } - }, - None => (), - }; - }, - tui_textarea::Input {key: tui_textarea::Key::Down, ..} => { - match app.status.room_mut(){ - Some(room) => { - match room.view_scroll() { - Some(i) => { - if i == 0 { - room.set_view_scroll(None); - } else { - room.set_view_scroll(Some(i - 1)); - } - } - None => (), - }; - }, - None => (), - }; - }, - _ => () - }; - }, - _ => (), + input => match app.ui.input_position() { + ui::MainInputPosition::MessageCompose => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Enter, + alt: true, + .. + } => { + match app.status.room_mut() { + Some(room) => { + room.send(app.ui.message_compose.lines().join("\n")) + .await?; + app.ui.message_compose_clear(); + } + None => (), + }; + } + _ => { + app.ui.message_compose.input(input); + } + }; } - } + ui::MainInputPosition::Rooms => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Up, + .. + } => { + let i = match app.ui.rooms_state.selected() { + Some(i) => { + if i > 0 { + i - 1 + } else { + i + } + } + None => 0, + }; + app.ui.rooms_state.select(Some(i)); + app.status.set_room_by_index(i)?; + } + tui_textarea::Input { + key: tui_textarea::Key::Down, + .. + } => { + let i = match app.ui.rooms_state.selected() { + Some(i) => { + if i < app.status.rooms().len() { + i + 1 + } else { + i + } + } + None => 0, + }; + app.ui.rooms_state.select(Some(i)); + app.status.set_room_by_index(i)?; + } + _ => (), + }; + } + ui::MainInputPosition::Messages => { + match input { + tui_textarea::Input { + key: tui_textarea::Key::Up, + .. + } => { + match app.status.room_mut() { + Some(room) => { + let len = room.timeline().len(); + let i = match room.view_scroll() { + Some(i) => i + 1, + None => 0, + }; + if i < len { + room.set_view_scroll(Some(i)) + } + if i <= len - 5 { + room.poll_old_timeline().await?; + } + } + None => (), + }; + } + tui_textarea::Input { + key: tui_textarea::Key::Down, + .. + } => { + match app.status.room_mut() { + Some(room) => { + match room.view_scroll() { + Some(i) => { + if i == 0 { + room.set_view_scroll(None); + } else { + room.set_view_scroll(Some(i - 1)); + } + } + None => (), + }; + } + None => (), + }; + } + _ => (), + }; + } + _ => (), + }, }; } Ok(EventStatus::Ok) @@ -200,18 +244,21 @@ impl Event { async fn handle_setup(&self, app: &mut App<'_>) -> Result { let ui = match &mut app.ui.setup_ui { Some(ui) => ui, - None => return Err(Error::msg("SetupUI instance not found")) + None => return Err(Error::msg("SetupUI instance not found")), }; if self.input_event.is_some() { match tui_textarea::Input::from(self.input_event.clone().unwrap()) { - tui_textarea::Input { key: tui_textarea::Key::Esc, .. } => return Ok(EventStatus::Terminate), + tui_textarea::Input { + key: tui_textarea::Key::Esc, + .. + } => return Ok(EventStatus::Terminate), tui_textarea::Input { key: tui_textarea::Key::Tab, .. } => { ui.cycle_input_position(); - }, + } tui_textarea::Input { key: tui_textarea::Key::Enter, .. @@ -225,33 +272,40 @@ impl Event { if login.is_ok() { return Ok(EventStatus::Finished); } - }, + } _ => ui.cycle_input_position(), }; - }, - input => { - match ui.input_position() { - ui::SetupInputPosition::Homeserver => { ui.homeserver.input(input); }, - ui::SetupInputPosition::Username => { ui.username.input(input); }, - ui::SetupInputPosition::Password => { - ui.password_data.input(input.clone()); - match input.key { - tui_textarea::Key::Char(_) => { - ui.password.input(tui_textarea::Input { key: tui_textarea::Key::Char('*'), ctrl: false, alt: false }); - }, - _ => { ui.password.input(input); }, - } - }, - _ => (), - } } + input => match ui.input_position() { + ui::SetupInputPosition::Homeserver => { + ui.homeserver.input(input); + } + ui::SetupInputPosition::Username => { + ui.username.input(input); + } + ui::SetupInputPosition::Password => { + ui.password_data.input(input.clone()); + match input.key { + tui_textarea::Key::Char(_) => { + ui.password.input(tui_textarea::Input { + key: tui_textarea::Key::Char('*'), + ctrl: false, + alt: false, + }); + } + _ => { + ui.password.input(input); + } + } + } + _ => (), + }, }; } Ok(EventStatus::Ok) } } - async fn poll_input_events_stage_2(channel: mpsc::Sender) -> Result<()> { loop { if crossterm::event::poll(Duration::from_millis(100))? { @@ -266,7 +320,10 @@ async fn poll_input_events_stage_2(channel: mpsc::Sender) -> Result<()> { } } -pub async fn poll_input_events(channel: mpsc::Sender, kill: CancellationToken) -> Result<()> { +pub async fn poll_input_events( + channel: mpsc::Sender, + kill: CancellationToken, +) -> Result<()> { tokio::select! { output = poll_input_events_stage_2(channel) => output, _ = kill.cancelled() => Err(Error::msg("received kill signal")) @@ -275,28 +332,32 @@ pub async fn poll_input_events(channel: mpsc::Sender, kill: CancellationT async fn poll_matrix_events_stage_2(channel: mpsc::Sender, client: Client) -> Result<()> { let sync_settings = SyncSettings::default(); - // .token(sync_token) - // .timeout(Duration::from_secs(30)); + // .token(sync_token) + // .timeout(Duration::from_secs(30)); let tx = &channel; - client.sync_with_callback(sync_settings, |response| async move { - let event = EventBuilder::default() - .matrix_event(response) - .build(); + client + .sync_with_callback(sync_settings, |response| async move { + let event = EventBuilder::default().matrix_event(response).build(); - match tx.send(event).await { - Ok(_) => LoopCtrl::Continue, - Err(_) => LoopCtrl::Break, - } - }).await?; + match tx.send(event).await { + Ok(_) => LoopCtrl::Continue, + Err(_) => LoopCtrl::Break, + } + }) + .await?; Ok(()) } -pub async fn poll_matrix_events(channel: mpsc::Sender, kill: CancellationToken, client: Client) -> Result<()> { +pub async fn poll_matrix_events( + channel: mpsc::Sender, + kill: CancellationToken, + client: Client, +) -> Result<()> { tokio::select! { output = poll_matrix_events_stage_2(channel, client) => output, _ = kill.cancelled() => Err(Error::msg("received kill signal")), } -} \ No newline at end of file +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 09931fd..6b14863 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,27 +1,29 @@ pub mod event; pub mod status; -use crate::accounts; -use crate::ui; - use std::path::Path; -use matrix_sdk::{Client, - room::{Room}, - config::SyncSettings, - ruma::events::room::{ - member::StrippedRoomMemberEvent, - message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, - }, - event_handler::Ctx -}; -use accounts::Account; -use accounts::AccountsManager; -use anyhow::{Result, Error}; -use cli_log::{error, warn, info}; -use tokio::{time::{sleep, Duration}, sync::{mpsc, broadcast}}; -use tokio_util::sync::CancellationToken; -use status::{Status, State}; +use accounts::{Account, AccountsManager}; +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; +use matrix_sdk::{ + config::SyncSettings, + event_handler::Ctx, + room::Room, + ruma::events::room::{ + member::StrippedRoomMemberEvent, + message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent}, + }, + Client, +}; +use status::{State, Status}; +use tokio::{ + sync::{broadcast, mpsc}, + time::{sleep, Duration}, +}; +use tokio_util::sync::CancellationToken; + +use crate::{accounts, ui}; pub struct App<'a> { ui: ui::UI<'a>, @@ -35,14 +37,12 @@ pub struct App<'a> { } impl Drop for App<'_> { - fn drop(&mut self) { - - } + fn drop(&mut self) {} } impl App<'_> { pub fn new() -> Self { - let path:&std::path::Path = Path::new("userdata/accounts.json"); + let path: &std::path::Path = Path::new("userdata/accounts.json"); let config = if path.exists() { info!("Reading account config (userdata/accounts.json)"); Some(std::fs::read_to_string(path).expect("failed to read accounts config")) @@ -65,9 +65,11 @@ impl App<'_> { } pub async fn run(&mut self) -> Result<()> { - // Spawn input event listener - tokio::task::spawn(event::poll_input_events(self.channel_tx.clone(), self.input_listener_killer.clone())); + tokio::task::spawn(event::poll_input_events( + self.channel_tx.clone(), + self.input_listener_killer.clone(), + )); if self.account().is_err() { info!("No saved sessions found -> jumping into setup"); @@ -77,14 +79,13 @@ impl App<'_> { self.init_account().await?; } - loop { self.status.set_state(State::Main); self.ui.update(&self.status).await?; let event: event::Event = match self.channel_rx.recv().await { Some(e) => e, - None => return Err(Error::msg("Event channel has no senders")) + None => return Err(Error::msg("Event channel has no senders")), }; match event.handle(self).await? { @@ -107,7 +108,7 @@ impl App<'_> { let event: event::Event = match self.channel_rx.recv().await { Some(e) => e, - None => return Err(Error::msg("Event channel has no senders")) + None => return Err(Error::msg("Event channel has no senders")), }; match event.handle(self).await? { @@ -121,14 +122,19 @@ impl App<'_> { pub async fn init_account(&mut self) -> Result<()> { let client = match self.client() { Some(c) => c, - None => return Err(Error::msg("failed to get current client")) - }.clone(); + None => return Err(Error::msg("failed to get current client")), + } + .clone(); self.matrix_listener_killer.cancel(); self.matrix_listener_killer = CancellationToken::new(); // Spawn Matrix Event Listener - tokio::task::spawn(event::poll_matrix_events(self.channel_tx.clone(), self.matrix_listener_killer.clone(), client.clone())); + tokio::task::spawn(event::poll_matrix_events( + self.channel_tx.clone(), + self.matrix_listener_killer.clone(), + client.clone(), + )); // Reset Status self.status = Status::new(Some(client)); @@ -139,10 +145,11 @@ impl App<'_> { self.status.set_account_name(name); self.status.set_account_user_id(user_id); - for (_, room) in self.status.rooms_mut() { room.update_name().await?; - for _ in 0..3 { room.poll_old_timeline().await?; } + for _ in 0..3 { + room.poll_old_timeline().await?; + } } info!("Initializing client for the current account"); @@ -151,12 +158,18 @@ impl App<'_> { } pub async fn switch_account(&mut self, account_id: u32) -> Result<()> { - Ok(()) } - pub async fn login(&mut self, homeserver: &String, username: &String, password: &String) -> Result<()> { - self.accounts_manager.add(homeserver, username, password).await?; + pub async fn login( + &mut self, + homeserver: &String, + username: &String, + password: &String, + ) -> Result<()> { + self.accounts_manager + .add(homeserver, username, password) + .await?; self.init_account().await?; Ok(()) } @@ -165,11 +178,11 @@ impl App<'_> { let account = self.accounts_manager.current(); match account { None => Err(Error::msg("failed to resolve current account")), - Some(a) => Ok(a) + Some(a) => Ok(a), } } - + pub fn client(&self) -> Option<&Client> { self.accounts_manager.client() } -} \ No newline at end of file +} diff --git a/src/app/status.rs b/src/app/status.rs index 6110cfd..6b2d3fc 100644 --- a/src/app/status.rs +++ b/src/app/status.rs @@ -1,14 +1,16 @@ use std::any::Any; + +use anyhow::{Error, Result}; +use cli_log::{error, info, warn}; use indexmap::IndexMap; -use matrix_sdk::{Client, - ruma::{events::{AnyTimelineEvent, - room::message::RoomMessageEventContent, - StateEventType}, - RoomId, - TransactionId}, - room::MessagesOptions}; -use anyhow::{Result, Error}; -use cli_log::{error, warn, info}; +use matrix_sdk::{ + room::MessagesOptions, + ruma::{ + events::{room::message::RoomMessageEventContent, AnyTimelineEvent, StateEventType}, + RoomId, TransactionId, + }, + Client, +}; pub enum State { None, @@ -36,7 +38,7 @@ pub struct Status { } impl Room { - pub fn new (matrix_room: matrix_sdk::room::Joined) -> Self { + pub fn new(matrix_room: matrix_sdk::room::Joined) -> Self { Self { matrix_room, name: "".to_string(), @@ -50,26 +52,29 @@ impl Room { pub async fn poll_old_timeline(&mut self) -> Result<()> { if let Some(AnyTimelineEvent::State(event)) = &self.timeline.get(0) { if event.event_type() == StateEventType::RoomCreate { - return Ok(()) + return Ok(()); } } let mut messages_options = MessagesOptions::backward(); messages_options = match &self.timeline_end { Some(end) => messages_options.from(end.as_str()), - None => messages_options + None => messages_options, }; let events = self.matrix_room.messages(messages_options).await?; self.timeline_end = events.end; for event in events.chunk.iter() { - self.timeline.insert(0, match event.event.deserialize() { - Ok(ev) => ev, - Err(err) => { - warn!("Failed to deserialize timeline event - {err}"); - continue; - } - }); + self.timeline.insert( + 0, + match event.event.deserialize() { + Ok(ev) => ev, + Err(err) => { + warn!("Failed to deserialize timeline event - {err}"); + continue; + } + }, + ); } Ok(()) } @@ -87,7 +92,9 @@ impl Room { self.timeline.push(event); } - pub fn timeline(&self) -> &Vec { &self.timeline } + pub fn timeline(&self) -> &Vec { + &self.timeline + } pub async fn send(&mut self, message: String) -> Result<()> { let content = RoomMessageEventContent::text_plain(message); @@ -114,9 +121,7 @@ impl Status { let mut rooms = IndexMap::new(); if let Some(c) = &client { for r in c.joined_rooms() { - rooms.insert( - r.room_id().to_string(), - Room::new(r.clone())); + rooms.insert(r.room_id().to_string(), Room::new(r.clone())); } }; @@ -167,7 +172,10 @@ impl Status { self.current_room_id = room_id.to_string(); Ok(()) } else { - Err(Error::msg(format!("failed to set room -> invalid room id {}", room_id.to_string()))) + Err(Error::msg(format!( + "failed to set room -> invalid room id {}", + room_id.to_string() + ))) } } @@ -176,7 +184,10 @@ impl Status { self.current_room_id = room_id.clone(); Ok(()) } else { - Err(Error::msg(format!("failed to set room -> invalid room index {}", room_index))) + Err(Error::msg(format!( + "failed to set room -> invalid room index {}", + room_index + ))) } } @@ -187,12 +198,12 @@ impl Status { pub fn get_room_mut(&mut self, room_id: &RoomId) -> Option<&mut Room> { self.rooms.get_mut(room_id.as_str()) } - + pub fn state(&self) -> &State { &self.state } - + pub fn set_state(&mut self, state: State) { self.state = state; } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 24ccbfc..aa926e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ -mod ui; mod accounts; mod app; +mod ui; -use cli_log::{error, warn, info}; +use cli_log::{error, info, warn}; #[tokio::main] async fn main() -> anyhow::Result<()> { diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 18280f6..f5b8a2a 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,30 +1,35 @@ -use crate::app::status::Status; +use std::{cmp, io, io::Stdout}; -use std::cmp; -use crossterm::{ - event::{self, DisableMouseCapture, EnableMouseCapture, Event, read}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, - style::{style}, -}; use anyhow::{Error, Result}; -use std::io::Stdout; -use std::io; -use tui::{backend::CrosstermBackend, layout::{Constraint, Direction, Layout}, widgets::{Block, Borders, Widget}, Terminal, Frame}; -use tui::layout::{Alignment, Corner}; -use tui::style::{Color, Modifier, Style}; -use tui::text::{Spans, Span, Text}; -use tui::widgets::{List, ListItem, ListState, Paragraph, Wrap}; +use cli_log::{error, info, warn}; +use crossterm::{ + event::{self, read, DisableMouseCapture, EnableMouseCapture, Event}, + execute, + style::style, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, +}; +use matrix_sdk::{ + room::MessagesOptions, + ruma::events::{AnyMessageLikeEvent, AnyTimelineEvent}, +}; +use tui::{ + backend::CrosstermBackend, + layout::{Alignment, Constraint, Corner, Direction, Layout}, + style::{Color, Modifier, Style}, + text::{Span, Spans, Text}, + widgets::{Block, Borders, List, ListItem, ListState, Paragraph, Widget, Wrap}, + Frame, Terminal, +}; use tui_textarea::{Input, Key, TextArea}; -use cli_log::{error, warn, info}; -use matrix_sdk::{room::MessagesOptions, ruma::events::{AnyTimelineEvent, AnyMessageLikeEvent}}; + +use crate::app::status::Status; #[derive(Clone, Copy)] pub enum SetupInputPosition { Homeserver, Username, Password, - Ok + Ok, } #[derive(Clone, Copy)] @@ -33,7 +38,7 @@ pub enum MainInputPosition { Rooms, Messages, MessageCompose, - RoomInfo + RoomInfo, } pub struct SetupUI<'a> { @@ -54,7 +59,6 @@ pub struct UI<'a> { pub setup_ui: Option>, } - fn terminal_prepare() -> Result { enable_raw_mode()?; let mut stdout = io::stdout(); @@ -80,9 +84,7 @@ pub fn textarea_inactivate(textarea: &mut TextArea) { .block() .cloned() .unwrap_or_else(|| Block::default().borders(Borders::ALL)); - textarea.set_block( - b.style(Style::default().fg(Color::DarkGray)) - ); + textarea.set_block(b.style(Style::default().fg(Color::DarkGray))); } impl Drop for UI<'_> { @@ -94,7 +96,9 @@ impl Drop for UI<'_> { LeaveAlternateScreen, DisableMouseCapture ).expect("While destructing UI -> Failed execute backend commands (LeaveAlternateScreen and DisableMouseCapture)"); - self.terminal.show_cursor().expect("While destructing UI -> Failed to re-enable cursor"); + self.terminal + .show_cursor() + .expect("While destructing UI -> Failed to re-enable cursor"); } } @@ -105,18 +109,9 @@ impl SetupUI<'_> { let mut password = TextArea::default(); let mut password_data = TextArea::default(); - homeserver.set_block( - Block::default() - .title("Homeserver") - .borders(Borders::ALL)); - username.set_block( - Block::default() - .title("Username") - .borders(Borders::ALL)); - password.set_block( - Block::default() - .title("Password") - .borders(Borders::ALL)); + homeserver.set_block(Block::default().title("Homeserver").borders(Borders::ALL)); + username.set_block(Block::default().title("Username").borders(Borders::ALL)); + password.set_block(Block::default().title("Password").borders(Borders::ALL)); textarea_activate(&mut homeserver); textarea_inactivate(&mut username); @@ -138,68 +133,74 @@ impl SetupUI<'_> { textarea_activate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Username - }, + } SetupInputPosition::Username => { textarea_inactivate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_activate(&mut self.password); SetupInputPosition::Password - }, + } SetupInputPosition::Password => { textarea_inactivate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Ok - }, + } SetupInputPosition::Ok => { textarea_activate(&mut self.homeserver); textarea_inactivate(&mut self.username); textarea_inactivate(&mut self.password); SetupInputPosition::Homeserver - }, + } }; } - pub fn input_position(&self) -> &SetupInputPosition { &self.input_position } + pub fn input_position(&self) -> &SetupInputPosition { + &self.input_position + } - pub async fn update(&'_ mut self, terminal: &mut Terminal>) -> Result<()> { + pub async fn update( + &'_ mut self, + terminal: &mut Terminal>, + ) -> Result<()> { let mut strings: Vec = Vec::new(); strings.resize(3, "".to_string()); - let content_ok = match self.input_position { - SetupInputPosition:: Ok => Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED)), + let content_ok = match self.input_position { + SetupInputPosition::Ok => { + Span::styled("OK", Style::default().add_modifier(Modifier::UNDERLINED)) + } _ => Span::styled("OK", Style::default().fg(Color::DarkGray)), }; - let block = Block::default() - .title("Login") - .borders(Borders::ALL); - - let mut ok = Paragraph::new(content_ok) - .alignment(Alignment::Center); + let block = Block::default().title("Login").borders(Borders::ALL); + let mut ok = Paragraph::new(content_ok).alignment(Alignment::Center); // define a 32 * 6 chunk in the middle of the screen let mut chunk = terminal.size()?; - chunk.x = (chunk.width / 2) - 16; - chunk.y = (chunk.height / 2) - 5; + chunk.x = (chunk.width / 2) - 16; + chunk.y = (chunk.height / 2) - 5; chunk.height = 12; - chunk.width = 32; + chunk.width = 32; let mut split_chunk = chunk.clone(); - split_chunk.x += 1; - split_chunk.y += 1; + split_chunk.x += 1; + split_chunk.y += 1; split_chunk.height -= 1; - split_chunk.width -= 2; + split_chunk.width -= 2; let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([ - Constraint::Length(3), // 0. Homserver: - Constraint::Length(3), // 1. Username: - Constraint::Length(3), // 2. Password: - Constraint::Length(1) // 3. OK - ].as_ref()) + .constraints( + [ + Constraint::Length(3), // 0. Homserver: + Constraint::Length(3), // 1. Username: + Constraint::Length(3), // 2. Password: + Constraint::Length(1), // 3. OK + ] + .as_ref(), + ) .split(split_chunk); terminal.draw(|frame| { @@ -226,7 +227,8 @@ impl UI<'_> { message_compose.set_block( Block::default() .title("Message Compose (send: +)") - .borders(Borders::ALL)); + .borders(Borders::ALL), + ); info!("Initialized UI"); @@ -235,7 +237,7 @@ impl UI<'_> { input_position: MainInputPosition::Rooms, rooms_state: ListState::default(), message_compose, - setup_ui: None + setup_ui: None, } } @@ -249,14 +251,17 @@ impl UI<'_> { }; } - pub fn input_position(&self) -> &MainInputPosition { &self.input_position } + pub fn input_position(&self) -> &MainInputPosition { + &self.input_position + } pub fn message_compose_clear(&mut self) { self.message_compose = TextArea::default(); self.message_compose.set_block( Block::default() .title("Message Compose (send: +)") - .borders(Borders::ALL)); + .borders(Borders::ALL), + ); } pub async fn update(&mut self, status: &Status) -> Result<()> { @@ -264,7 +269,14 @@ impl UI<'_> { let main_chunks = Layout::default() .direction(Direction::Horizontal) - .constraints([Constraint::Length(32), Constraint::Min(16), Constraint::Length(32)].as_ref()) + .constraints( + [ + Constraint::Length(32), + Constraint::Min(16), + Constraint::Length(32), + ] + .as_ref(), + ) .split(chunk); let left_chunks = Layout::default() @@ -274,7 +286,13 @@ impl UI<'_> { let middle_chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Min(4), Constraint::Length(cmp::min(2 + self.message_compose.lines().len() as u16, 8))].as_ref()) + .constraints( + [ + Constraint::Min(4), + Constraint::Length(cmp::min(2 + self.message_compose.lines().len() as u16, 8)), + ] + .as_ref(), + ) .split(main_chunks[1]); let right_chunks = Layout::default() @@ -282,15 +300,22 @@ impl UI<'_> { .constraints([Constraint::Min(4)].as_ref()) .split(main_chunks[2]); - let mut status_content = Text::styled(status.account_name(), Style::default().add_modifier(Modifier::BOLD)); + let mut status_content = Text::styled( + status.account_name(), + Style::default().add_modifier(Modifier::BOLD), + ); status_content.extend(Text::styled(status.account_user_id(), Style::default())); - status_content.extend(Text::styled("settings", Style::default().fg(Color::LightMagenta).add_modifier(Modifier::ITALIC | Modifier::UNDERLINED))); + status_content.extend(Text::styled( + "settings", + Style::default() + .fg(Color::LightMagenta) + .add_modifier(Modifier::ITALIC | Modifier::UNDERLINED), + )); - let rooms_content = status.rooms() + let rooms_content = status + .rooms() .iter() - .map(|(_, room)| { - ListItem::new(Span::styled(room.name(), Style::default())) - }) + .map(|(_, room)| ListItem::new(Span::styled(room.name(), Style::default()))) .collect::>(); let messages_content = match status.room() { @@ -300,7 +325,6 @@ impl UI<'_> { .rev() .map(|event| { match event { - // Message Like Events AnyTimelineEvent::MessageLike(message_like_event) => { let (content, color) = match &message_like_event { @@ -312,30 +336,48 @@ impl UI<'_> { .body(); (message_content.to_string(), Color::White) - }, - _ => ("~~~ not supported message like event ~~~".to_string(), Color::Red) + } + _ => ( + "~~~ not supported message like event ~~~".to_string(), + Color::Red, + ), }; - let mut text = Text::styled(message_like_event.sender().to_string(), - Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)); - text.extend(Text::styled(content.to_string(), - Style::default().fg(color))); + let mut text = Text::styled( + message_like_event.sender().to_string(), + Style::default() + .fg(Color::Cyan) + .add_modifier(Modifier::BOLD), + ); + text.extend(Text::styled( + content.to_string(), + Style::default().fg(color), + )); ListItem::new(text) - }, + } // State Events AnyTimelineEvent::State(state) => { ListItem::new(vec![Spans::from(vec![ - Span::styled(state.sender().to_string(), Style::default().fg(Color::DarkGray)), + Span::styled( + state.sender().to_string(), + Style::default().fg(Color::DarkGray), + ), Span::styled(": ", Style::default().fg(Color::DarkGray)), - Span::styled(state.event_type().to_string(), Style::default().fg(Color::DarkGray)) + Span::styled( + state.event_type().to_string(), + Style::default().fg(Color::DarkGray), + ), ])]) } } }) .collect::>() - }, + } None => { - vec![ListItem::new(Text::styled("No room selected!", Style::default().fg(Color::Red)))] + vec![ListItem::new(Text::styled( + "No room selected!", + Style::default().fg(Color::Red), + ))] } }; @@ -347,78 +389,129 @@ impl UI<'_> { room_info_content.extend(Text::styled(room.name(), Style::default().fg(Color::Cyan))); if room.encrypted() { - room_info_content.extend(Text::styled("Encrypted", Style::default().fg(Color::Green))); + room_info_content + .extend(Text::styled("Encrypted", Style::default().fg(Color::Green))); } else { - room_info_content.extend(Text::styled("Not Encrypted!", Style::default().fg(Color::Red))); + room_info_content.extend(Text::styled( + "Not Encrypted!", + Style::default().fg(Color::Red), + )); } } else { - room_info_content.extend(Text::styled("No room selected!", Style::default().fg(Color::Red))); + room_info_content.extend(Text::styled( + "No room selected!", + Style::default().fg(Color::Red), + )); } - // calculate to widgets colors, based of which widget is currently selected let colors = match self.input_position { MainInputPosition::Status => { textarea_inactivate(&mut self.message_compose); - vec![Color::White, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::White, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::Rooms => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::White, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::White, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::Messages => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::White, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::White, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::MessageCompose => { textarea_activate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + ] + } MainInputPosition::RoomInfo => { textarea_inactivate(&mut self.message_compose); - vec![Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::DarkGray, Color::White] - }, + vec![ + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::DarkGray, + Color::White, + ] + } }; // initiate the widgets let status_panel = Paragraph::new(status_content) - .block(Block::default() - .title("Status") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Status as usize]))) + .block( + Block::default() + .title("Status") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Status as usize])), + ) .alignment(Alignment::Left); let rooms_panel = List::new(rooms_content) - .block(Block::default() - .title("Rooms (navigate: arrow keys)") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Rooms as usize]))) + .block( + Block::default() + .title("Rooms (navigate: arrow keys)") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Rooms as usize])), + ) .style(Style::default().fg(Color::DarkGray)) - .highlight_style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)) + .highlight_style( + Style::default() + .fg(Color::Cyan) + .add_modifier(Modifier::BOLD), + ) .highlight_symbol(">"); let messages_panel = List::new(messages_content) - .block(Block::default() - .title("Messages") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::Messages as usize]))) + .block( + Block::default() + .title("Messages") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::Messages as usize])), + ) .start_corner(Corner::BottomLeft) .highlight_symbol(">") - .highlight_style(Style::default().fg(Color::LightMagenta).add_modifier(Modifier::BOLD)); + .highlight_style( + Style::default() + .fg(Color::LightMagenta) + .add_modifier(Modifier::BOLD), + ); let room_info_panel = Paragraph::new(room_info_content) - .block(Block::default() - .title("Room Info") - .borders(Borders::ALL) - .style(Style::default().fg(colors[MainInputPosition::RoomInfo as usize]))) + .block( + Block::default() + .title("Room Info") + .borders(Borders::ALL) + .style(Style::default().fg(colors[MainInputPosition::RoomInfo as usize])), + ) .alignment(Alignment::Center); - // render the widgets self.terminal.draw(|frame| { frame.render_widget(status_panel, left_chunks[0]); frame.render_stateful_widget(rooms_panel, left_chunks[1], &mut self.rooms_state); - frame.render_stateful_widget(messages_panel, middle_chunks[0], & mut messages_state); + frame.render_stateful_widget(messages_panel, middle_chunks[0], &mut messages_state); frame.render_widget(self.message_compose.widget(), middle_chunks[1]); frame.render_widget(room_info_panel, right_chunks[0]); })?; From a9f72e34e64e1fd8a350f794b1385c49f65ad715 Mon Sep 17 00:00:00 2001 From: Soispha Date: Sun, 9 Jul 2023 08:09:14 +0200 Subject: [PATCH 2/3] Build(cargo): Remove wildcard version specification in `Cargo.toml` Wildcard version is comparable to selecting a version depending on the result of a dice roll. What I mean with this is, that the version will be selected based on what the specific user already has in their cargo registry. This means that the same codebase will compile wonderfully on one machine but will fail with weird errors like: `the trait 'From' is not implemented for 'Input'` on an other one. Additionally crates.io does not accept crates with a bare wildcard version requirement for aforementioned reasons. Lastly using direct versions requirement allows to use `cargo upgrade` to automatically update these requirements to their highest possible value, as determined by SemVer. This works especially well, when adding new dependencies with `cargo add`, as this also adds a direct version requirement. --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5f63dd..4c97bff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ license = "MIT" [dependencies] tui = "0.19" -tui-textarea = { version = "*" } -crossterm = "*" +tui-textarea = { version = "0.2", features = ["crossterm"] } +crossterm = "0.25" matrix-sdk = "0.6" anyhow = "1.0" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } tokio-util = "0.7" serde = "1.0" cli-log = "2.0" -indexmap = "*" \ No newline at end of file +indexmap = "2.0.0" From 1c43626fad1250a27c3b84fcf9cc70a2c82e29eb Mon Sep 17 00:00:00 2001 From: Soispha Date: Sun, 9 Jul 2023 08:41:25 +0200 Subject: [PATCH 3/3] Build(Cargo): Update `Cargo.lock` and upgrade `Cargo.toml` --- Cargo.lock | 306 ++++++++++++++++++++++------------------------------- Cargo.toml | 2 +- 2 files changed, 127 insertions(+), 181 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a2e53a..775b5e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -138,20 +138,20 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -230,9 +230,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" +checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" dependencies = [ "arrayref", "arrayvec", @@ -402,9 +402,9 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "constant_time_eq" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" @@ -424,9 +424,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -538,7 +538,7 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "strsim", "syn 1.0.109", @@ -593,7 +593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" dependencies = [ "darling", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "syn 1.0.109", ] @@ -640,9 +640,9 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -699,7 +699,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -839,9 +839,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -987,18 +987,9 @@ checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hkdf" @@ -1191,9 +1182,9 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1213,9 +1204,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "js-sys" @@ -1495,9 +1486,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1511,7 +1502,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1543,19 +1534,19 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "object" -version = "0.30.4" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -1593,9 +1584,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -1695,29 +1686,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -1779,9 +1770,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] @@ -1813,7 +1804,7 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "syn 1.0.109", ] @@ -1833,7 +1824,7 @@ version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", ] [[package]] @@ -2042,9 +2033,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" dependencies = [ "aho-corasick", "memchr", @@ -2053,9 +2056,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" [[package]] name = "reqwest" @@ -2185,7 +2188,7 @@ checksum = "0f82e91eb61cd86d9287303133ee55b54618eccb75a522cc22a42c15f5bda340" dependencies = [ "once_cell", "proc-macro-crate", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "ruma-identifiers-validation", "serde", @@ -2201,31 +2204,31 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.37.20" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2259,38 +2262,38 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "bd51c3db8f9500d531e6c12dd0fd4ad13d133e9117f5aebac3cdbb8b6d9824b0" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" +checksum = "5a16be4fe5320ade08736447e3198294a5ea9a6d44dde6f35f0a5e06859c427a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "27738cfea0d944ab72c3ed01f3d5f23ec4322af8a1431e40ce630e4c01ea74fd" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" dependencies = [ "itoa", "ryu", @@ -2396,9 +2399,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -2448,18 +2451,18 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.22" +version = "2.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "36ccaf716a23c35ff908f91c971a86a9a71af5998c1d8f10e828d9f55f68ac00" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", "unicode-ident", ] @@ -2475,27 +2478,27 @@ dependencies = [ "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2526,9 +2529,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374442f06ee49c3a28a8fc9f01a2596fed7559c6b99b31279c3261778e77d84f" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg 1.1.0", "backtrace", @@ -2539,7 +2542,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2548,9 +2551,9 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2594,9 +2597,9 @@ checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", "toml_datetime", @@ -2627,9 +2630,9 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] [[package]] @@ -2648,7 +2651,7 @@ dependencies = [ "anyhow", "cli-log", "crossterm", - "indexmap 1.9.3", + "indexmap 2.0.0", "matrix-sdk", "serde", "tokio", @@ -2700,9 +2703,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "unicode-normalization" @@ -2865,9 +2868,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", "wasm-bindgen-shared", ] @@ -2899,9 +2902,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2974,21 +2977,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -3004,93 +2992,51 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -3099,9 +3045,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] @@ -3142,7 +3088,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.63", + "proc-macro2 1.0.64", "quote 1.0.29", - "syn 2.0.22", + "syn 2.0.24", ] diff --git a/Cargo.toml b/Cargo.toml index 4c97bff..92db0f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ tui-textarea = { version = "0.2", features = ["crossterm"] } crossterm = "0.25" matrix-sdk = "0.6" anyhow = "1.0" -tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.29", features = ["macros", "rt-multi-thread"] } tokio-util = "0.7" serde = "1.0" cli-log = "2.0"