Refactor(app): Add a transmitter

This commit is contained in:
Benedikt Peetz 2023-07-16 14:18:17 +02:00
parent ba225e29df
commit 49818e0bfe
Signed by: bpeetz
GPG Key ID: A5E94010C3A642AD
3 changed files with 89 additions and 36 deletions

View File

@ -2,7 +2,11 @@ use anyhow::Result;
use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent, KeyModifiers}; use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent, KeyModifiers};
use crate::{ use crate::{
app::{command, command::Command, events::event_types::EventStatus, App}, app::{
command_interface::Command,
events::event_types::{Event, EventStatus},
App,
},
ui::central, ui::central,
}; };
@ -11,25 +15,33 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
CrosstermEvent::Key(KeyEvent { CrosstermEvent::Key(KeyEvent {
code: KeyCode::Esc, .. code: KeyCode::Esc, ..
}) => { }) => {
command::execute(app.channel_tx(), Command::Exit).await?; app.transmitter
.send(Event::CommandEvent(Command::Exit))
.await?;
} }
CrosstermEvent::Key(KeyEvent { CrosstermEvent::Key(KeyEvent {
code: KeyCode::Tab, .. code: KeyCode::Tab, ..
}) => { }) => {
command::execute(app.channel_tx(), Command::CyclePlanes).await?; app.transmitter
.send(Event::CommandEvent(Command::CyclePlanes))
.await?;
} }
CrosstermEvent::Key(KeyEvent { CrosstermEvent::Key(KeyEvent {
code: KeyCode::BackTab, code: KeyCode::BackTab,
.. ..
}) => { }) => {
command::execute(app.channel_tx(), Command::CyclePlanesRev).await?; app.transmitter
.send(Event::CommandEvent(Command::CyclePlanesRev))
.await?;
} }
CrosstermEvent::Key(KeyEvent { CrosstermEvent::Key(KeyEvent {
code: KeyCode::Char('c'), code: KeyCode::Char('c'),
modifiers: KeyModifiers::CONTROL, modifiers: KeyModifiers::CONTROL,
.. ..
}) => { }) => {
command::execute(app.channel_tx(), Command::CommandLineShow).await?; app.transmitter
.send(Event::CommandEvent(Command::CommandLineShow))
.await?;
} }
input => match app.ui.input_position() { input => match app.ui.input_position() {
central::InputPosition::MessageCompose => { central::InputPosition::MessageCompose => {
@ -39,10 +51,10 @@ pub async fn handle(app: &mut App<'_>, input_event: &CrosstermEvent) -> Result<E
modifiers: KeyModifiers::ALT, modifiers: KeyModifiers::ALT,
.. ..
}) => { }) => {
command::execute( app.transmitter
app.channel_tx(), .send(Event::CommandEvent(Command::RoomMessageSend(
Command::RoomMessageSend(app.ui.message_compose.lines().join("\n")), app.ui.message_compose.lines().join("\n"),
) )))
.await?; .await?;
app.ui.message_compose_clear(); app.ui.message_compose_clear();
} }

View File

@ -1,29 +1,31 @@
pub mod command_interface; pub mod command_interface;
pub mod events; pub mod events;
pub mod status; pub mod status;
pub mod transmitter;
use std::{path::Path, sync::mpsc::Sender as StdSender}; use std::{path::Path, sync::mpsc::Sender as StdSender};
use accounts::{Account, AccountsManager};
use anyhow::{Context, Error, Result}; use anyhow::{Context, Error, Result};
use cli_log::info; use cli_log::info;
use matrix_sdk::Client; use matrix_sdk::Client;
use rlua::Lua; use rlua::Lua;
use status::{State, Status}; use status::{State, Status};
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
use crate::{accounts, app::command_interface::generate_ci_functions, ui::{central, setup}}; use crate::{
accounts::{Account, AccountsManager},
app::{command_interface::generate_ci_functions, events::event_types::Event},
ui::{central, setup},
};
use self::events::event_types::{self, Event}; use self::{events::event_types, transmitter::Transmitter};
pub struct App<'ui> { pub struct App<'ui> {
ui: central::UI<'ui>, ui: central::UI<'ui>,
accounts_manager: accounts::AccountsManager, accounts_manager: AccountsManager,
status: Status, status: Status,
channel_tx: mpsc::Sender<event_types::Event>, transmitter: Transmitter,
channel_rx: mpsc::Receiver<event_types::Event>,
input_listener_killer: CancellationToken, input_listener_killer: CancellationToken,
matrix_listener_killer: CancellationToken, matrix_listener_killer: CancellationToken,
@ -49,19 +51,17 @@ impl App<'_> {
None None
}; };
let (channel_tx, channel_rx) = mpsc::channel(256); let transmitter = Transmitter::new();
Ok(Self { Ok(Self {
ui: central::UI::new()?, ui: central::UI::new()?,
accounts_manager: AccountsManager::new(config)?, accounts_manager: AccountsManager::new(config)?,
status: Status::new(None), status: Status::new(None),
channel_tx, transmitter,
channel_rx,
input_listener_killer: CancellationToken::new(), input_listener_killer: CancellationToken::new(),
matrix_listener_killer: CancellationToken::new(), matrix_listener_killer: CancellationToken::new(),
lua: set_up_lua(channel_tx), lua: set_up_lua(transmitter.std_tx()),
}) })
} }
@ -83,7 +83,7 @@ impl App<'_> {
pub async fn run(&mut self) -> Result<()> { pub async fn run(&mut self) -> Result<()> {
// Spawn input event listener // Spawn input event listener
tokio::task::spawn(events::poll_input_events( tokio::task::spawn(events::poll_input_events(
self.channel_tx.clone(), self.transmitter.tx(),
self.input_listener_killer.clone(), self.input_listener_killer.clone(),
)); ));
@ -99,10 +99,11 @@ impl App<'_> {
self.status.set_state(State::Main); self.status.set_state(State::Main);
self.ui.update(&self.status).await?; self.ui.update(&self.status).await?;
let event: event_types::Event = match self.channel_rx.recv().await { let event = self
Some(e) => e, .transmitter
None => return Err(Error::msg("Event channel has no senders")), .recv()
}; .await
.context("Failed to get next event")?;
match event.handle(self).await? { match event.handle(self).await? {
event_types::EventStatus::Ok => (), event_types::EventStatus::Ok => (),
@ -122,10 +123,11 @@ impl App<'_> {
self.status.set_state(State::Setup); self.status.set_state(State::Setup);
self.ui.update_setup().await?; self.ui.update_setup().await?;
let event: event_types::Event = match self.channel_rx.recv().await { let event = self
Some(e) => e, .transmitter
None => return Err(Error::msg("Event channel has no senders")), .recv()
}; .await
.context("Failed to get next event")?;
match event.handle(self).await? { match event.handle(self).await? {
event_types::EventStatus::Ok => (), event_types::EventStatus::Ok => (),
@ -149,7 +151,7 @@ impl App<'_> {
// Spawn Matrix Event Listener // Spawn Matrix Event Listener
tokio::task::spawn(events::poll_matrix_events( tokio::task::spawn(events::poll_matrix_events(
self.channel_tx.clone(), self.transmitter.tx(),
self.matrix_listener_killer.clone(), self.matrix_listener_killer.clone(),
client.clone(), client.clone(),
)); ));
@ -203,8 +205,4 @@ impl App<'_> {
pub fn client(&self) -> Option<&Client> { pub fn client(&self) -> Option<&Client> {
self.accounts_manager.client() self.accounts_manager.client()
} }
pub fn channel_tx(&self) -> &mpsc::Sender<Event> {
&self.channel_tx
}
} }

43
src/app/transmitter.rs Normal file
View File

@ -0,0 +1,43 @@
use std::sync::mpsc as StdMpsc;
use anyhow::{bail, Context, Result};
use tokio::sync::mpsc;
use super::events::event_types::Event;
pub struct Transmitter {
tx: mpsc::Sender<Event>,
rx: mpsc::Receiver<Event>,
std_tx: StdMpsc::Sender<Event>,
std_rx: StdMpsc::Receiver<Event>,
}
impl Transmitter {
pub fn new() -> Transmitter {
let (std_tx, std_rx) = StdMpsc::channel();
let (tx, rx) = mpsc::channel(256);
Transmitter {
tx,
rx,
std_tx,
std_rx,
}
}
pub fn tx(&self) -> mpsc::Sender<Event> {
self.tx.to_owned()
}
pub fn std_tx(&self) -> StdMpsc::Sender<Event> {
self.std_tx.to_owned()
}
pub async fn recv(&mut self) -> Result<Event> {
match self.rx.recv().await {
Some(event) => Ok(event),
None => bail!("Event channel has no senders"),
}
}
pub async fn send(&mut self, event: Event) -> Result<()> {
self.tx.send(event).await.context("Failed to send event")
}
}