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},
Trinitrix::Api,
},
events::event_types::Event,
events::Event,
};
use super::command_transfer_value::support_types::Function;

View File

@ -4,7 +4,7 @@ use anyhow::Result;
use cli_log::info;
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<()> {
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},
Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui,
},
events::event_types::EventStatus,
events::EventStatus,
keymappings::{
key::{Key, Keys},
trie::Node,

View File

@ -1,6 +1,8 @@
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
// 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::{
command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api},
events::event_types::{Event, EventStatus},
events::{Event, EventStatus},
keymappings::key::{Key, Keys},
status::State,
App,

View File

@ -1,7 +1,7 @@
use anyhow::Result;
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.
// TODO(@Soispha): Move the lua executor thread code from app to this module

View File

@ -1,7 +1,7 @@
use anyhow::Result;
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> {
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 crate::{
app::{events::event_types::EventStatus, App},
app::{events::EventStatus, App},
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 matrix_sdk::{config::SyncSettings, Client, LoopCtrl};
use tokio::{sync::mpsc, time::Duration};
use tokio_util::sync::CancellationToken;
use anyhow::{Context, Result};
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(
channel: mpsc::Sender<Event>,
kill: CancellationToken,
) -> Result<()> {
async fn poll_input_events_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;
#[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!("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(
channel: mpsc::Sender<Event>,
kill: CancellationToken,
client: Client,
) -> Result<()> {
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"),
}
#[derive(Debug)]
pub enum EventStatus {
Ok,
Finished,
Terminate,
}

View File

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