refactor: restructured event sources

This commit is contained in:
antifallobst 2023-10-19 18:14:59 +02:00
parent 4e839d4e2c
commit a538877b5b
Signed by: antifallobst
GPG Key ID: 2B4F402172791BAF
18 changed files with 140 additions and 137 deletions

View File

@ -19,7 +19,7 @@ use crate::app::{
Raw::{DisplayOutput, RaiseError}, Raw::{DisplayOutput, RaiseError},
Trinitrix::Api, Trinitrix::Api,
}, },
events::event_types::Event, events::Event,
}; };
use super::command_transfer_value::support_types::Function; use super::command_transfer_value::support_types::Function;

View File

@ -4,7 +4,7 @@ use anyhow::Result;
use cli_log::info; use cli_log::info;
use tokio::{fs, sync::mpsc::Sender}; use tokio::{fs, sync::mpsc::Sender};
use crate::app::events::event_types::Event; use crate::app::events::Event;
pub async fn load(tx: Sender<Event>, path: PathBuf) -> Result<()> { pub async fn load(tx: Sender<Event>, path: PathBuf) -> Result<()> {
let lua_config_code = fs::read_to_string(&path).await?; let lua_config_code = fs::read_to_string(&path).await?;

View File

@ -1,53 +0,0 @@
mod handlers;
use anyhow::{Context, Result};
use cli_log::trace;
use crossterm::event::Event as CrosstermEvent;
use tokio::sync::oneshot;
use super::EventStatus;
use crate::app::{
command_interface::{command_transfer_value::{CommandTransferValue, support_types::Function}, Command},
status::State,
App, events::event_types::event::handlers::{input, matrix, command, lua_command, setup, function},
};
#[derive(Debug)]
pub enum Event {
InputEvent(CrosstermEvent),
MatrixEvent(matrix_sdk::deserialized_responses::SyncResponse),
CommandEvent(Command, Option<oneshot::Sender<CommandTransferValue>>),
LuaCommand(String),
Function(Function),
}
impl Event {
pub async fn handle(self, app: &mut App<'_>) -> Result<EventStatus> {
trace!("Recieved event to handle: `{:#?}`", &self);
match self {
Event::MatrixEvent(event) => matrix::handle(app, &event)
.await
.with_context(|| format!("Failed to handle matrix event: `{:#?}`", event)),
Event::CommandEvent(event, callback_tx) => command::handle(app, &event, callback_tx)
.await
.with_context(|| format!("Failed to handle command event: `{:#?}`", event)),
Event::LuaCommand(lua_code) => lua_command::handle(app, lua_code.to_owned())
.await
.with_context(|| format!("Failed to handle lua code: `{}`", lua_code)),
Event::Function(function) => function::handle(app, function.to_owned())
.await
.with_context(|| format!("Failed to handle function: `{}`", function)),
Event::InputEvent(event) => match app.status.state() {
State::Setup => setup::handle(app, &event).await.with_context(|| {
format!("Failed to handle input (setup) event: `{:#?}`", event)
}),
_ => input::handle(app, &event).await.with_context(|| {
format!("Failed to handle input (non-setup) event: `{:#?}`", event)
}),
},
}
}
}

View File

@ -1,6 +0,0 @@
#[derive(Debug)]
pub enum EventStatus {
Ok,
Finished,
Terminate,
}

View File

@ -1,4 +0,0 @@
pub mod event;
pub mod event_status;
pub use self::{event::*, event_status::*};

View File

@ -11,7 +11,7 @@ use crate::{
command_transfer_value::{CommandTransferValue, Table}, command_transfer_value::{CommandTransferValue, Table},
Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui, Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui,
}, },
events::event_types::EventStatus, events::EventStatus,
keymappings::{ keymappings::{
key::{Key, Keys}, key::{Key, Keys},
trie::Node, trie::Node,

View File

@ -1,6 +1,8 @@
use anyhow::Result; use anyhow::Result;
use crate::app::{events::event_types::EventStatus, App, command_interface::command_transfer_value::support_types::Function}; use crate::app::{
command_interface::command_transfer_value::support_types::Function, events::EventStatus, App,
};
// TODO(@soispha): We just assume for now that all functions originate in lua. This module will in // TODO(@soispha): We just assume for now that all functions originate in lua. This module will in
// future versions house check for the language the function came from <2023-10-15> // future versions house check for the language the function came from <2023-10-15>

View File

@ -4,7 +4,7 @@ use crossterm::event::Event as CrosstermEvent;
use crate::app::{ use crate::app::{
command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api}, command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api},
events::event_types::{Event, EventStatus}, events::{Event, EventStatus},
keymappings::key::{Key, Keys}, keymappings::key::{Key, Keys},
status::State, status::State,
App, App,

View File

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use cli_log::trace; use cli_log::trace;
use crate::app::{events::event_types::EventStatus, App}; use crate::app::{events::EventStatus, App};
// This function is here mainly to reserve this spot for further processing of the lua command. // This function is here mainly to reserve this spot for further processing of the lua command.
// TODO(@Soispha): Move the lua executor thread code from app to this module // TODO(@Soispha): Move the lua executor thread code from app to this module

View File

@ -1,7 +1,7 @@
use anyhow::Result; use anyhow::Result;
use matrix_sdk::deserialized_responses::SyncResponse; use matrix_sdk::deserialized_responses::SyncResponse;
use crate::app::{events::event_types::EventStatus, App}; use crate::app::{events::EventStatus, App};
pub async fn handle(app: &mut App<'_>, sync: &SyncResponse) -> Result<EventStatus> { pub async fn handle(app: &mut App<'_>, sync: &SyncResponse) -> Result<EventStatus> {
for (m_room_id, m_room) in sync.rooms.join.iter() { for (m_room_id, m_room) in sync.rooms.join.iter() {

View File

@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent}; use crossterm::event::{Event as CrosstermEvent, KeyCode, KeyEvent};
use crate::{ use crate::{
app::{events::event_types::EventStatus, App}, app::{events::EventStatus, App},
ui::setup, ui::setup,
}; };

View File

@ -0,0 +1,21 @@
use crate::app::events::Event;
use anyhow::{bail, Result};
use tokio::{sync::mpsc, time::Duration};
use tokio_util::sync::CancellationToken;
pub async fn poll(channel: mpsc::Sender<Event>, kill: CancellationToken) -> Result<()> {
async fn stage_2(channel: mpsc::Sender<Event>) -> Result<()> {
loop {
if crossterm::event::poll(Duration::from_millis(100))? {
let event = Event::InputEvent(crossterm::event::read()?);
channel.send(event).await?;
} else {
tokio::task::yield_now().await;
}
}
}
tokio::select! {
output = stage_2(channel) => output,
_ = kill.cancelled() => bail!("received kill signal")
}
}

View File

@ -0,0 +1,41 @@
/* WARNING(@antifallobst):
* This file is going to be removed while implementing Chat Backend Servers!
* <19-10-2023>
*/
use crate::app::events::Event;
use anyhow::{bail, Result};
use matrix_sdk::{config::SyncSettings, Client, LoopCtrl};
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
pub async fn poll(
channel: mpsc::Sender<Event>,
kill: CancellationToken,
client: Client,
) -> Result<()> {
async fn stage_2(channel: mpsc::Sender<Event>, client: Client) -> Result<()> {
let sync_settings = SyncSettings::default();
// .token(sync_token)
// .timeout(Duration::from_secs(30));
let tx = &channel;
client
.sync_with_callback(sync_settings, |response| async move {
let event = Event::MatrixEvent(response);
match tx.send(event).await {
Ok(_) => LoopCtrl::Continue,
Err(_) => LoopCtrl::Break,
}
})
.await?;
Ok(())
}
tokio::select! {
output = stage_2(channel, client) => output,
_ = kill.cancelled() => bail!("received kill signal"),
}
}

View File

@ -0,0 +1,2 @@
pub mod input;
pub mod matrix;

View File

@ -1,62 +1,64 @@
pub mod event_types; mod handlers;
pub mod listeners;
use anyhow::{bail, Result}; use anyhow::{Context, Result};
use matrix_sdk::{config::SyncSettings, Client, LoopCtrl};
use tokio::{sync::mpsc, time::Duration};
use tokio_util::sync::CancellationToken;
use self::event_types::Event; use crate::app::{
command_interface::{
command_transfer_value::{support_types::Function, CommandTransferValue},
Command,
},
status::State,
App,
};
use cli_log::trace;
use crossterm::event::Event as CrosstermEvent;
use handlers::{command, function, input, lua_command, matrix, setup};
use tokio::sync::oneshot;
pub async fn poll_input_events( #[derive(Debug)]
channel: mpsc::Sender<Event>, pub enum Event {
kill: CancellationToken, InputEvent(CrosstermEvent),
) -> Result<()> { MatrixEvent(matrix_sdk::deserialized_responses::SyncResponse),
async fn poll_input_events_stage_2(channel: mpsc::Sender<Event>) -> Result<()> { CommandEvent(Command, Option<oneshot::Sender<CommandTransferValue>>),
loop { LuaCommand(String),
if crossterm::event::poll(Duration::from_millis(100))? { Function(Function),
let event = Event::InputEvent(crossterm::event::read()?); }
channel.send(event).await?;
} else { impl Event {
tokio::task::yield_now().await; pub async fn handle(self, app: &mut App<'_>) -> Result<EventStatus> {
trace!("Received event to handle: `{:#?}`", &self);
match self {
Event::MatrixEvent(event) => matrix::handle(app, &event)
.await
.with_context(|| format!("Failed to handle matrix event: `{:#?}`", event)),
Event::CommandEvent(event, callback_tx) => command::handle(app, &event, callback_tx)
.await
.with_context(|| format!("Failed to handle command event: `{:#?}`", event)),
Event::LuaCommand(lua_code) => lua_command::handle(app, lua_code.to_owned())
.await
.with_context(|| format!("Failed to handle lua code: `{}`", lua_code)),
Event::Function(function) => function::handle(app, function.to_owned())
.await
.with_context(|| format!("Failed to handle function: `{}`", function)),
Event::InputEvent(event) => match app.status.state() {
State::Setup => setup::handle(app, &event).await.with_context(|| {
format!("Failed to handle input (setup) event: `{:#?}`", event)
}),
_ => input::handle(app, &event).await.with_context(|| {
format!("Failed to handle input (non-setup) event: `{:#?}`", event)
}),
},
} }
} }
}
tokio::select! {
output = poll_input_events_stage_2(channel) => output,
_ = kill.cancelled() => bail!("received kill signal")
}
} }
pub async fn poll_matrix_events( #[derive(Debug)]
channel: mpsc::Sender<Event>, pub enum EventStatus {
kill: CancellationToken, Ok,
client: Client, Finished,
) -> Result<()> { Terminate,
async fn poll_matrix_events_stage_2(
channel: mpsc::Sender<Event>,
client: Client,
) -> Result<()> {
let sync_settings = SyncSettings::default();
// .token(sync_token)
// .timeout(Duration::from_secs(30));
let tx = &channel;
client
.sync_with_callback(sync_settings, |response| async move {
let event = Event::MatrixEvent(response);
match tx.send(event).await {
Ok(_) => LoopCtrl::Continue,
Err(_) => LoopCtrl::Break,
}
})
.await?;
Ok(())
}
tokio::select! {
output = poll_matrix_events_stage_2(channel, client) => output,
_ = kill.cancelled() => bail!("received kill signal"),
}
} }

View File

@ -1,7 +1,7 @@
pub mod command_interface; pub mod command_interface;
pub mod keymappings;
pub mod config; pub mod config;
pub mod events; pub mod events;
pub mod keymappings;
pub mod status; pub mod status;
use std::{ use std::{
@ -20,12 +20,12 @@ use self::{
command_interface::{ command_interface::{
command_transfer_value::support_types::Function, lua_command_manager::LuaCommandManager, command_transfer_value::support_types::Function, lua_command_manager::LuaCommandManager,
}, },
events::event_types, keymappings::trie::Node, keymappings::trie::Node,
}; };
use crate::{ use crate::{
accounts::{Account, AccountsManager}, accounts::{Account, AccountsManager},
app::{ app::{
events::event_types::Event, events::{Event, EventStatus},
status::{State, Status}, status::{State, Status},
}, },
ui::{central, setup}, ui::{central, setup},
@ -83,7 +83,7 @@ impl App<'_> {
pub async fn run(&mut self, cli_lua_config_file: Option<PathBuf>) -> Result<()> { pub async fn run(&mut self, cli_lua_config_file: Option<PathBuf>) -> Result<()> {
// Spawn input event listener // Spawn input event listener
tokio::task::spawn(events::poll_input_events( tokio::task::spawn(events::listeners::input::poll(
self.tx.clone(), self.tx.clone(),
self.input_listener_killer.clone(), self.input_listener_killer.clone(),
)); ));
@ -131,8 +131,8 @@ impl App<'_> {
let event = self.rx.recv().await.context("Failed to get next event")?; let event = self.rx.recv().await.context("Failed to get next event")?;
match event.handle(self).await? { match event.handle(self).await? {
event_types::EventStatus::Ok => (), EventStatus::Ok => (),
event_types::EventStatus::Terminate => break, EventStatus::Terminate => break,
_ => todo!(), _ => todo!(),
}; };
} }
@ -152,11 +152,9 @@ impl App<'_> {
let event = self.rx.recv().await.context("Failed to get next event")?; let event = self.rx.recv().await.context("Failed to get next event")?;
match event.handle(self).await? { match event.handle(self).await? {
event_types::EventStatus::Ok => (), EventStatus::Ok => (),
event_types::EventStatus::Finished => return Ok(()), EventStatus::Finished => return Ok(()),
event_types::EventStatus::Terminate => { EventStatus::Terminate => return Err(Error::msg("Terminated by user")),
return Err(Error::msg("Terminated by user"))
}
} }
} }
} }
@ -172,7 +170,7 @@ impl App<'_> {
self.matrix_listener_killer = CancellationToken::new(); self.matrix_listener_killer = CancellationToken::new();
// Spawn Matrix Event Listener // Spawn Matrix Event Listener
tokio::task::spawn(events::poll_matrix_events( tokio::task::spawn(events::listeners::matrix::poll(
self.tx.clone(), self.tx.clone(),
self.matrix_listener_killer.clone(), self.matrix_listener_killer.clone(),
client.clone(), client.clone(),