diff options
Diffstat (limited to 'ui/src/usecase')
-rw-r--r-- | ui/src/usecase/mod.rs | 9 | ||||
-rw-r--r-- | ui/src/usecase/presenter.rs | 59 | ||||
-rw-r--r-- | ui/src/usecase/service.rs | 24 | ||||
-rw-r--r-- | ui/src/usecase/view.rs | 22 | ||||
-rw-r--r-- | ui/src/usecase/watcher.rs | 46 |
5 files changed, 160 insertions, 0 deletions
diff --git a/ui/src/usecase/mod.rs b/ui/src/usecase/mod.rs new file mode 100644 index 0000000..7ca5fcb --- /dev/null +++ b/ui/src/usecase/mod.rs @@ -0,0 +1,9 @@ +pub mod presenter; +pub mod service; +pub mod view; +pub mod watcher; + +pub use presenter::*; +pub use service::*; +pub use view::*; +pub use watcher::*; diff --git a/ui/src/usecase/presenter.rs b/ui/src/usecase/presenter.rs new file mode 100644 index 0000000..335d16d --- /dev/null +++ b/ui/src/usecase/presenter.rs @@ -0,0 +1,59 @@ +use std::time::{Duration, Instant}; + +use super::{service, DesktopServiceState, Event}; +use crate::BUFFER; +use async_std::task::sleep; +use crossbeam_channel::{Receiver, Sender}; + +pub async fn create(sender: Sender<Event>, receiver: Receiver<Event>) { + let mut now = Instant::now(); + let buffer = BUFFER.get().unwrap().to_owned(); + let send = |event| sender.send(event).unwrap_or_default(); + if let Some(mut service) = service::create() { + let mut service_state = DesktopServiceState::Unknown; + let mut file = "hbbs.out".to_owned(); + send(Event::ViewRenderServiceState(service_state.to_owned())); + loop { + for _ in 1..buffer { + match receiver.recv_timeout(Duration::from_nanos(1)) { + Ok(event) => match event { + Event::BroswerInit => { + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + Event::BrowserAction(action) => match action.as_str() { + "restart" => service.restart(), + _ => (), + }, + Event::FileChange(path) => { + if path == file { + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + } + Event::ViewAction(action) => match action.as_str() { + "start" => service.start(), + "stop" => service.stop(), + "restart" => service.restart(), + "pause" => service.pause(), + "exit" => send(Event::ViewRenderAppExit), + _ => { + file = action; + send(Event::BrowserUpdate(("file".to_owned(), file.to_owned()))); + } + }, + _ => (), + }, + Err(_) => break, + } + } + sleep(Duration::from_micros(999)).await; + if now.elapsed().as_millis() > 999 { + let state = service.check(); + if state != service_state { + service_state = state.to_owned(); + send(Event::ViewRenderServiceState(state)); + } + now = Instant::now(); + } + } + } +} diff --git a/ui/src/usecase/service.rs b/ui/src/usecase/service.rs new file mode 100644 index 0000000..4d992c1 --- /dev/null +++ b/ui/src/usecase/service.rs @@ -0,0 +1,24 @@ +use crate::adapter; + +pub fn create() -> Option<Box<dyn IDesktopService + Send>> { + if cfg!(target_os = "windows") { + return Some(Box::new(adapter::WindowsDesktopService::new())); + } + None +} + +#[derive(Debug, Clone, PartialEq)] +pub enum DesktopServiceState { + Paused, + Started, + Stopped, + Unknown, +} + +pub trait IDesktopService { + fn start(&mut self); + fn stop(&mut self); + fn restart(&mut self); + fn pause(&mut self); + fn check(&mut self) -> DesktopServiceState; +} diff --git a/ui/src/usecase/view.rs b/ui/src/usecase/view.rs new file mode 100644 index 0000000..882769b --- /dev/null +++ b/ui/src/usecase/view.rs @@ -0,0 +1,22 @@ +use super::DesktopServiceState; +use crate::adapter::desktop; +use crossbeam_channel::{Receiver, Sender}; + +pub async fn create(sender: Sender<Event>, receiver: Receiver<Event>) { + desktop::run(sender, receiver).await; +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Event { + BrowserAction(String), + BroswerInit, + BrowserUpdate((String, String)), + BrowserRender(String), + FileChange(String), + ViewAction(String), + ViewInit, + ViewUpdate(String), + ViewRender(String), + ViewRenderAppExit, + ViewRenderServiceState(DesktopServiceState), +} diff --git a/ui/src/usecase/watcher.rs b/ui/src/usecase/watcher.rs new file mode 100644 index 0000000..883ba68 --- /dev/null +++ b/ui/src/usecase/watcher.rs @@ -0,0 +1,46 @@ +use std::{path::Path, time::Duration}; + +use super::Event; +use crate::path; +use async_std::task::{sleep, spawn_blocking}; +use crossbeam_channel::{bounded, Sender}; +use notify::{Config, RecommendedWatcher, RecursiveMode, Result, Watcher}; + +pub async fn create(sender: Sender<Event>) { + loop { + let watch_sender = sender.clone(); + match spawn_blocking(|| { + watch( + format!("{}/logs/", path().to_str().unwrap_or_default()), + watch_sender, + ) + }) + .await + { + Ok(_) => (), + Err(e) => println!("error: {e}"), + } + sleep(Duration::from_secs(1)).await; + } +} + +fn watch<P: AsRef<Path>>(path: P, sender: Sender<Event>) -> Result<()> { + let (tx, rx) = bounded(10); + let mut watcher = RecommendedWatcher::new(tx, Config::default())?; + watcher.watch(path.as_ref(), RecursiveMode::Recursive)?; + for res in rx { + let event = res?; + for p in event.paths { + let path = p + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + .to_owned(); + if path.len() > 0 { + sender.send(Event::FileChange(path)).unwrap_or_default(); + } + } + } + Ok(()) +} |