From f638f4bd1e3a03bc2bdd5f9dcd57d4830fd3c553 Mon Sep 17 00:00:00 2001 From: Shav Kinderlehrer Date: Sun, 24 Mar 2024 14:18:53 -0400 Subject: [PATCH] Overhaul events system + add url_manager --- src/app.rs | 56 +++++++++++++++++++++++++++-------- src/app_action.rs | 1 - src/app_event.rs | 1 - src/component.rs | 23 +++++++------- src/components/global_keys.rs | 9 ++---- src/components/mod.rs | 1 + src/components/status.rs | 32 +++++++++++++------- src/components/url_manager.rs | 34 +++++++++++++++++++++ src/main.rs | 7 ++--- 9 files changed, 117 insertions(+), 47 deletions(-) create mode 100644 src/components/url_manager.rs diff --git a/src/app.rs b/src/app.rs index b9c3492..7d398f0 100644 --- a/src/app.rs +++ b/src/app.rs @@ -9,6 +9,7 @@ use crate::component::Component; use crate::components; use crate::keys::key_commands::KeyCommand; use crate::tui; + pub struct App { pub tui: tui::Tui, pub tick_rate: Duration, @@ -37,8 +38,16 @@ impl App { key_commands: self.key_commands.clone(), ..Default::default() }; - let status_bar = components::status::StatusBar::default(); - self.components = vec![Box::new(global_keys), Box::new(status_bar)]; + let status_bar = components::status::StatusBar { + message: "Press '?' to show the help menu".to_string(), + ..Default::default() + }; + let url_manager = components::url_manager::UrlManager::default(); + self.components = vec![ + Box::new(global_keys), + Box::new(status_bar), + Box::new(url_manager), + ]; for component in &mut self.components { component.init()?; @@ -67,16 +76,7 @@ impl App { }; if let Some(event) = event { - let mut actions: Vec = vec![]; - for component in &mut self.components { - if let Some(action) = component.handle_event(event.clone())? { - actions.push(action); - } - } - - for action in actions { - self.handle_action(action)?; - } + self.handle_event(event)?; } if self.should_quit { @@ -94,10 +94,28 @@ impl App { // status bar let _ = self.components[1].render(frame, layout[1]); + // global_keys let _ = self.components[0].render(frame, frame.size()); })?; + self.update()?; + + Ok(()) + } + + pub fn update(&mut self) -> Result<()> { + let mut events: Vec = vec![]; + for component in &mut self.components { + if let Some(event) = component.update() { + events.push(event); + } + } + + for event in events { + self.handle_event(event)?; + } + Ok(()) } @@ -119,4 +137,18 @@ impl App { } } } + + fn handle_event(&mut self, event: AppEvent) -> Result<()> { + let mut actions: Vec = vec![]; + for component in &mut self.components { + if let Some(action) = component.handle_event(event.clone()) { + actions.push(action); + } + } + + for action in actions { + self.handle_action(action)?; + } + Ok(()) + } } diff --git a/src/app_action.rs b/src/app_action.rs index 333e284..7825724 100644 --- a/src/app_action.rs +++ b/src/app_action.rs @@ -2,7 +2,6 @@ use std::fmt; #[derive(Default, Clone, Debug)] pub enum AppAction { - StatusBarGetInput(String), StatusBarSetMessage(String), StatusBarSetError(String), OpenUrl, diff --git a/src/app_event.rs b/src/app_event.rs index 8413234..94a8d0d 100644 --- a/src/app_event.rs +++ b/src/app_event.rs @@ -6,6 +6,5 @@ pub enum AppEvent { Key(KeyEvent), Mouse(MouseEvent), - StatusBarInput(String), OpenUrl(Url), } diff --git a/src/component.rs b/src/component.rs index 65d865c..3e8fd8d 100644 --- a/src/component.rs +++ b/src/component.rs @@ -14,32 +14,29 @@ pub trait Component { fn handle_action(&mut self, action: AppAction) {} #[allow(unused)] - fn handle_event(&mut self, event: AppEvent) -> Result> { + fn handle_event(&mut self, event: AppEvent) -> Option { match event { - AppEvent::Key(key_event) => Ok(self.handle_key_event(key_event)?), + AppEvent::Key(key_event) => self.handle_key_event(key_event), AppEvent::Mouse(mouse_event) => { - Ok(self.handle_mouse_event(mouse_event)?) + self.handle_mouse_event(mouse_event) } - _ => Ok(None), + _ => None, } } #[allow(unused)] - fn handle_key_event(&mut self, key: KeyEvent) -> Result> { - Ok(None) + fn handle_key_event(&mut self, key: KeyEvent) -> Option { + None } #[allow(unused)] - fn handle_mouse_event( - &mut self, - mouse: MouseEvent, - ) -> Result> { - Ok(None) + fn handle_mouse_event(&mut self, mouse: MouseEvent) -> Option { + None } #[allow(unused)] - fn update(&mut self, action: AppAction) -> Result> { - Ok(None) + fn update(&mut self) -> Option { + None } fn render(&mut self, frame: &mut Frame, rect: Rect) -> Result<()>; diff --git a/src/components/global_keys.rs b/src/components/global_keys.rs index 39ec1b7..dd903b1 100644 --- a/src/components/global_keys.rs +++ b/src/components/global_keys.rs @@ -58,20 +58,17 @@ impl Component for GlobalKeys { self.scroll_state = self.scroll_state.position(self.scroll); } - fn handle_key_event( - &mut self, - key: KeyEvent, - ) -> eyre::Result> { + fn handle_key_event(&mut self, key: KeyEvent) -> Option { if key.kind == KeyEventKind::Press { let key_event = serialize_key_event(key); for key_command in &mut self.key_commands { if key_command.key_code == key_event { - return Ok(Some(key_command.action.clone())); + return Some(key_command.action.clone()); } } } - Ok(None) + None } fn render(&mut self, frame: &mut Frame, rect: Rect) -> eyre::Result<()> { diff --git a/src/components/mod.rs b/src/components/mod.rs index a779415..07d34ab 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,2 +1,3 @@ pub mod global_keys; pub mod status; +pub mod url_manager; diff --git a/src/components/status.rs b/src/components/status.rs index d91782f..aa2b384 100644 --- a/src/components/status.rs +++ b/src/components/status.rs @@ -2,29 +2,31 @@ use ratatui::prelude::*; use ratatui::widgets::*; use crate::app_action::AppAction; +use crate::app_event::AppEvent; use crate::component::Component; use crate::keys::key_commands::serialize_key_event; #[derive(Default, Clone)] pub struct StatusBar { - message: String, - current_key: String, - error: bool, + pub message: String, + pub current_key: String, + pub error: bool, + pub url_to_open: Option, } impl Component for StatusBar { fn handle_key_event( &mut self, key: crossterm::event::KeyEvent, - ) -> eyre::Result> { + ) -> Option { let key_str = serialize_key_event(key); self.current_key = key_str; - Ok(None) + None } fn handle_action(&mut self, action: crate::app_action::AppAction) { - match action { + match action.clone() { AppAction::StatusBarSetMessage(message) => { self.error = false; self.message = message; @@ -33,14 +35,24 @@ impl Component for StatusBar { self.error = true; self.message = message; } - AppAction::StatusBarGetInput(_prompt) => todo!(), - _ => { - self.current_key += " "; - self.current_key += &action.to_string(); + AppAction::OpenUrl => { + self.url_to_open = + Some(url::Url::parse("molerat://example.com").unwrap()); } + _ => {} } } + fn update(&mut self) -> Option { + if let Some(url) = &self.url_to_open { + let event = AppEvent::OpenUrl(url.clone()); + self.url_to_open = None; + return Some(event); + } + + None + } + fn render( &mut self, frame: &mut ratatui::prelude::Frame, diff --git a/src/components/url_manager.rs b/src/components/url_manager.rs new file mode 100644 index 0000000..6067923 --- /dev/null +++ b/src/components/url_manager.rs @@ -0,0 +1,34 @@ +use url::Url; + +use crate::app_action::AppAction; +use crate::app_event::AppEvent; +use crate::component::Component; + +#[derive(Default)] +pub struct UrlManager { + url: Option, +} + +impl Component for UrlManager { + fn handle_event(&mut self, event: AppEvent) -> Option { + match event { + AppEvent::OpenUrl(url) => { + self.url = Some(url.clone()); + return Some(AppAction::StatusBarSetMessage(format!( + "Opening {}", + url.as_str() + ))); + } + _ => {} + } + None + } + + fn render( + &mut self, + _frame: &mut ratatui::prelude::Frame, + _rect: ratatui::prelude::Rect, + ) -> eyre::Result<()> { + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 33c2036..3b8bb70 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,6 @@ fn main() -> Result<()> { description: "Open new link".to_string(), action: AppAction::OpenUrl, }, - // Navigation KeyCommand { key_code: "g".to_string(), @@ -50,9 +49,9 @@ fn main() -> Result<()> { }, KeyCommand { key_code: "?".to_string(), - description: "Show help menu".to_string(), - action: AppAction::ShowHelpMenu - } + description: "Toggle help menu".to_string(), + action: AppAction::ShowHelpMenu, + }, ]; app.key_commands.append(&mut key_commands);