diff --git a/src/runner.rs b/src/app.rs similarity index 72% rename from src/runner.rs rename to src/app.rs index 32954e4..345f4f3 100644 --- a/src/runner.rs +++ b/src/app.rs @@ -1,27 +1,38 @@ use color_eyre::eyre::Result; +use serde_derive::{Deserialize, Serialize}; use tokio::sync::mpsc; use crate::{ command::Command, - components::{app::App, Component}, + components::{task_report::TaskReport, Component}, config::Config, tui, }; -pub struct Runner { +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Mode { + #[default] + TaskReport, + TaskContext, + Calendar, + Error, +} + +pub struct App { pub config: Config, pub tick_rate: f64, pub frame_rate: f64, pub components: Vec>, pub should_quit: bool, pub should_suspend: bool, + pub mode: Mode, } -impl Runner { +impl App { pub fn new(tick_rate: f64, frame_rate: f64) -> Result { - let app = App::new(); + let app = TaskReport::new(); let config = Config::new()?; - let app = app.keybindings(config.keybindings.clone()); + let mode = Mode::TaskReport; Ok(Self { tick_rate, frame_rate, @@ -29,6 +40,7 @@ impl Runner { should_quit: false, should_suspend: false, config, + mode, }) } @@ -44,6 +56,10 @@ impl Runner { component.register_command_handler(command_tx.clone())?; } + for component in self.components.iter_mut() { + component.register_config_handler(self.config.clone())?; + } + for component in self.components.iter_mut() { component.init()?; } @@ -55,13 +71,19 @@ impl Runner { tui::Event::Tick => command_tx.send(Command::Tick)?, tui::Event::Render => command_tx.send(Command::Render)?, tui::Event::Resize(x, y) => command_tx.send(Command::Resize(x, y))?, - e => { - for component in self.components.iter_mut() { - if let Some(command) = component.handle_events(Some(e.clone()))? { - command_tx.send(command)?; - } - } + tui::Event::Key(key) => { + let command = if let Some(keymap) = self.config.keybindings.get(&self.mode) { + if let Some(command) = keymap.get(&vec![key]) { + command_tx.send(command.clone())?; + }; + }; }, + _ => {}, + } + for component in self.components.iter_mut() { + if let Some(command) = component.handle_events(Some(e.clone()))? { + command_tx.send(command)?; + } } } diff --git a/src/components.rs b/src/components.rs index d1651dd..8eb7459 100644 --- a/src/components.rs +++ b/src/components.rs @@ -5,16 +5,21 @@ use tokio::sync::mpsc::UnboundedSender; use crate::{ command::Command, + config::Config, tui::{Event, Frame}, }; -pub mod app; +pub mod task_report; pub trait Component { #[allow(unused_variables)] fn register_command_handler(&mut self, tx: UnboundedSender) -> Result<()> { Ok(()) } + #[allow(unused_variables)] + fn register_config_handler(&mut self, config: Config) -> Result<()> { + Ok(()) + } fn init(&mut self) -> Result<()> { Ok(()) } diff --git a/src/components/app.rs b/src/components/task_report.rs similarity index 66% rename from src/components/app.rs rename to src/components/task_report.rs index a03b8e5..001ccb4 100644 --- a/src/components/app.rs +++ b/src/components/task_report.rs @@ -10,22 +10,15 @@ use tui_input::backend::crossterm::EventHandler; use uuid::Uuid; use super::{Component, Frame}; -use crate::{command::Command, config::KeyBindings}; - -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Mode { - #[default] - TaskReport, - TaskContext, - Calendar, - Error, -} +use crate::{ + command::Command, + config::{Config, KeyBindings}, +}; #[derive(Default)] -pub struct App { - pub mode: Mode, +pub struct TaskReport { + pub config: Config, pub command_tx: Option>, - pub keybindings: KeyBindings, pub last_export: Option, pub report: String, pub filter: String, @@ -33,16 +26,11 @@ pub struct App { pub tasks: Vec, } -impl App { +impl TaskReport { pub fn new() -> Self { Self::default() } - pub fn keybindings(mut self, keybindings: KeyBindings) -> Self { - self.keybindings = keybindings; - self - } - pub fn refresh(&mut self) -> Result<()> { self.last_export = Some(std::time::SystemTime::now()); Ok(()) @@ -93,39 +81,25 @@ impl App { if let Ok(imported) = import(data.as_bytes()) { self.tasks = imported; log::info!("Imported {} tasks", self.tasks.len()); - if self.mode == Mode::Error { - self.send_command(Command::ShowTaskReport)?; - }; - // } else { - // self.error = Some(format!("Unable to parse output of `{:?}`:\n`{:?}`", task, data)); - // self.mode = Mode::Tasks(Action::Error); - // debug!("Unable to parse output: {:?}", data); + self.send_command(Command::ShowTaskReport)?; } } else { - // self.error = Some(format!("Cannot run `{:?}` - ({}) error:\n{}", &task, output.status, error)); + self.send_command(Command::Error(format!("Unable to parse output of `{:?}`:\n`{:?}`", task, data)))?; } Ok(()) } } -impl Component for App { +impl Component for TaskReport { fn register_command_handler(&mut self, tx: UnboundedSender) -> Result<()> { self.command_tx = Some(tx); Ok(()) } - fn handle_key_events(&mut self, key: KeyEvent) -> Result> { - let command = if let Some(keymap) = self.keybindings.get(&self.mode) { - if let Some(command) = keymap.get(&vec![key]) { - command - } else { - return Ok(None); - } - } else { - return Ok(None); - }; - Ok(Some(command.clone())) + fn register_config_handler(&mut self, config: Config) -> Result<()> { + self.config = config; + Ok(()) } fn update(&mut self, command: Command) -> Result> { diff --git a/src/config.rs b/src/config.rs index 42fcd8d..01d86b1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use ratatui::style::{Color, Modifier, Style}; use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; use serde_derive::Deserialize; -use crate::{command::Command, components::app::Mode}; +use crate::{app::Mode, command::Command}; const CONFIG: &'static str = include_str!("../.config/config.json5"); diff --git a/src/main.rs b/src/main.rs index e03cdaf..054f7a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,11 +2,11 @@ #![allow(unused_imports)] #![allow(unused_variables)] +pub mod app; pub mod cli; pub mod command; pub mod components; pub mod config; -pub mod runner; pub mod tui; pub mod utils; @@ -15,7 +15,7 @@ use cli::Cli; use color_eyre::eyre::Result; use crate::{ - runner::Runner, + app::App, utils::{initialize_logging, initialize_panic_handler, version}, }; @@ -25,7 +25,7 @@ async fn tokio_main() -> Result<()> { initialize_panic_handler()?; let args = Cli::parse(); - let mut runner = Runner::new(args.tick_rate, args.frame_rate)?; + let mut runner = App::new(args.tick_rate, args.frame_rate)?; runner.run().await?; Ok(())