From 5f11cbc0a2026415da5f1f3d962d3df88145f5bd Mon Sep 17 00:00:00 2001 From: Anton Yemelyanov Date: Wed, 20 Dec 2023 21:28:07 +0200 Subject: [PATCH] handling for enable/disable of market and update monitors --- core/src/modules/account_manager/balance.rs | 28 +-- core/src/modules/overview.rs | 92 ++++---- core/src/modules/settings/mod.rs | 19 +- .../runtime/services/market_monitor/mod.rs | 31 ++- core/src/runtime/services/plugin_manager.rs | 213 ------------------ core/src/runtime/services/update_monitor.rs | 19 +- 6 files changed, 110 insertions(+), 292 deletions(-) delete mode 100644 core/src/runtime/services/plugin_manager.rs diff --git a/core/src/modules/account_manager/balance.rs b/core/src/modules/account_manager/balance.rs index b14bf8a..02d9bfc 100644 --- a/core/src/modules/account_manager/balance.rs +++ b/core/src/modules/account_manager/balance.rs @@ -33,21 +33,23 @@ impl<'context> BalancePane<'context> { ); } - if let Some(market) = core.market.as_ref() { - if let Some(price_list) = market.price.as_ref() { - let mut symbols = price_list.keys().collect::>(); - symbols.sort(); - symbols.into_iter().for_each(|symbol| { - if let Some(data) = price_list.get(symbol) { - let symbol = symbol.to_uppercase(); - let MarketData { price, change : _, .. } = data; - let text = format!("{:.8} {}", sompi_to_kaspa(balance.mature) * (*price), symbol.as_str()); - ui.label(RichText::new(text).font(FontId::proportional(16.))); - } - }); + if core.settings.market_monitor { + if let Some(market) = core.market.as_ref() { + if let Some(price_list) = market.price.as_ref() { + let mut symbols = price_list.keys().collect::>(); + symbols.sort(); + symbols.into_iter().for_each(|symbol| { + if let Some(data) = price_list.get(symbol) { + let symbol = symbol.to_uppercase(); + let MarketData { price, change : _, .. } = data; + let text = format!("{:.8} {}", sompi_to_kaspa(balance.mature) * (*price), symbol.as_str()); + ui.label(RichText::new(text).font(FontId::proportional(16.))); + } + }); + } } } - + if balance.pending != 0 { ui.label(format!( "Pending: {}", diff --git a/core/src/modules/overview.rs b/core/src/modules/overview.rs index 22ebf6b..95ef1c0 100644 --- a/core/src/modules/overview.rs +++ b/core/src/modules/overview.rs @@ -106,54 +106,56 @@ impl Overview { .auto_shrink([false; 2]) .show(ui, |ui| { - CollapsingHeader::new(i18n("Market")) - .default_open(true) - .show(ui, |ui| { + if core.settings.market_monitor { + CollapsingHeader::new(i18n("Market")) + .default_open(true) + .show(ui, |ui| { - if let Some(market) = core.market.as_ref() { - if let Some(price_list) = market.price.as_ref() { - let mut symbols = price_list.keys().collect::>(); - symbols.sort(); - symbols.into_iter().for_each(|symbol| { - if let Some(data) = price_list.get(symbol) { - let symbol = symbol.to_uppercase(); - CollapsingHeader::new(symbol.as_str()) - .default_open(true) - .show(ui, |ui| { - Grid::new("market_price_info_grid") - .num_columns(2) - .spacing([16.0,4.0]) - .show(ui, |ui| { - let MarketData { price, volume, change, market_cap , precision } = *data; - ui.label(i18n("Price")); - // ui.colored_label(theme_color().market_default_color, RichText::new(format_price_with_symbol(price, precision, symbol.as_str())).font(FontId::monospace(14.))); // - ui.colored_label(theme_color().market_default_color, RichText::new(format_price_with_symbol(price, precision, symbol.as_str()))); // - ui.end_row(); - - ui.label(i18n("Change")); - if change > 0. { - ui.colored_label(theme_color().market_up_color, RichText::new(format!("+{:.2}% ",change))); - } else { - ui.colored_label(theme_color().market_down_color, RichText::new(format!("{:.2}% ",change))); - }; - ui.end_row(); - - ui.label(i18n("Volume")); - ui.colored_label(theme_color().market_default_color, RichText::new(format!("{} {}",volume.trunc().separated_string(),symbol.to_uppercase()))); - ui.end_row(); - - ui.label(i18n("Market Cap")); - ui.colored_label(theme_color().market_default_color, RichText::new(format!("{} {}",market_cap.trunc().separated_string(),symbol.to_uppercase()))); - ui.end_row(); - }); - - }); - } - }) + if let Some(market) = core.market.as_ref() { + if let Some(price_list) = market.price.as_ref() { + let mut symbols = price_list.keys().collect::>(); + symbols.sort(); + symbols.into_iter().for_each(|symbol| { + if let Some(data) = price_list.get(symbol) { + let symbol = symbol.to_uppercase(); + CollapsingHeader::new(symbol.as_str()) + .default_open(true) + .show(ui, |ui| { + Grid::new("market_price_info_grid") + .num_columns(2) + .spacing([16.0,4.0]) + .show(ui, |ui| { + let MarketData { price, volume, change, market_cap , precision } = *data; + ui.label(i18n("Price")); + // ui.colored_label(theme_color().market_default_color, RichText::new(format_price_with_symbol(price, precision, symbol.as_str())).font(FontId::monospace(14.))); // + ui.colored_label(theme_color().market_default_color, RichText::new(format_price_with_symbol(price, precision, symbol.as_str()))); // + ui.end_row(); + + ui.label(i18n("Change")); + if change > 0. { + ui.colored_label(theme_color().market_up_color, RichText::new(format!("+{:.2}% ",change))); + } else { + ui.colored_label(theme_color().market_down_color, RichText::new(format!("{:.2}% ",change))); + }; + ui.end_row(); + + ui.label(i18n("Volume")); + ui.colored_label(theme_color().market_default_color, RichText::new(format!("{} {}",volume.trunc().separated_string(),symbol.to_uppercase()))); + ui.end_row(); + + ui.label(i18n("Market Cap")); + ui.colored_label(theme_color().market_default_color, RichText::new(format!("{} {}",market_cap.trunc().separated_string(),symbol.to_uppercase()))); + ui.end_row(); + }); + + }); + } + }) + } } - } - }); + }); + } CollapsingHeader::new(i18n("Resources")) .default_open(true) diff --git a/core/src/modules/settings/mod.rs b/core/src/modules/settings/mod.rs index 41dadbe..5cd949c 100644 --- a/core/src/modules/settings/mod.rs +++ b/core/src/modules/settings/mod.rs @@ -158,7 +158,7 @@ impl Settings { use crate::runtime::services::kaspa::Config; ui.add_space(4.); - ui.checkbox(&mut self.settings.node.kaspad_daemon_args_enable, i18n("Enable custom daemon arguments")); + ui.checkbox(&mut self.settings.node.kaspad_daemon_args_enable, i18n("Activate custom daemon arguments")); ui.add_space(4.); if self.settings.node.kaspad_daemon_args_enable { @@ -344,8 +344,10 @@ impl Settings { CollapsingHeader::new("Market Monitor") .default_open(true) .show(ui, |ui| { - let mut v = false; - if ui.checkbox(&mut v, i18n("Enable Market Monitor")).changed() { + if ui.checkbox(&mut self.settings.market_monitor, i18n("Enable Market Monitor")).changed() { + core.settings.market_monitor = self.settings.market_monitor; + self.runtime.market_monitor_service().enable(core.settings.market_monitor); + core.store_settings(); } }); @@ -353,10 +355,11 @@ impl Settings { CollapsingHeader::new("Check for Updates") .default_open(true) .show(ui, |ui| { - let mut v = false; - if ui.checkbox(&mut v, i18n("Check for Software Updates via GitHub")).changed() { + if ui.checkbox(&mut self.settings.update_monitor, i18n("Check for Software Updates via GitHub")).changed() { + core.settings.update_monitor = self.settings.update_monitor; + self.runtime.update_monitor_service().enable(core.settings.update_monitor); + core.store_settings(); } - }); }); @@ -382,7 +385,7 @@ impl Settings { #[cfg(not(target_arch = "wasm32"))] ui.checkbox( &mut self.settings.developer.enable_custom_daemon_args, - i18n("Allow custom daemon arguments") + i18n("Enable custom daemon arguments") ).on_hover_text_at_pointer( i18n("Allow custom arguments for the Rusty Kaspa daemon") ); @@ -397,7 +400,7 @@ impl Settings { #[cfg(not(target_arch = "wasm32"))] ui.checkbox( &mut self.settings.developer.enable_screen_capture, - i18n("Screen capture") + i18n("Enable screen capture") ).on_hover_text_at_pointer( i18n("Allows you to take screenshots from within the application") ); diff --git a/core/src/runtime/services/market_monitor/mod.rs b/core/src/runtime/services/market_monitor/mod.rs index 09a0d4c..94cc013 100644 --- a/core/src/runtime/services/market_monitor/mod.rs +++ b/core/src/runtime/services/market_monitor/mod.rs @@ -70,12 +70,14 @@ pub type CurrencyDescriptorList = Vec; // pub struct MarketData {} pub enum MarketMonitorEvents { + Enable, + Disable, Exit, } pub struct MarketMonitorService { pub application_events: ApplicationEventsChannel, - pub plugin_events: Channel, + pub service_events: Channel, pub task_ctl: Channel<()>, pub is_enabled: AtomicBool, pub currencies: Mutex>>, @@ -85,7 +87,7 @@ pub struct MarketMonitorService { } impl MarketMonitorService { - pub fn new(application_events: ApplicationEventsChannel, _settings: &Settings) -> Self { + pub fn new(application_events: ApplicationEventsChannel, settings: &Settings) -> Self { let currencies = ["usd", "btc"] .into_iter() .map(String::from) @@ -93,9 +95,9 @@ impl MarketMonitorService { Self { application_events, - plugin_events: Channel::unbounded(), + service_events: Channel::unbounded(), task_ctl: Channel::oneshot(), - is_enabled: AtomicBool::new(false), + is_enabled: AtomicBool::new(settings.market_monitor), provider: Mutex::new(MarketDataProvider::default()), // ------ // currencies: Mutex::new(Some(vec!["usd".to_string()])), @@ -115,6 +117,14 @@ impl MarketMonitorService { self.provider.lock().unwrap().clone() } + pub fn enable(&self, enable : bool) { + if enable { + self.service_events.try_send(MarketMonitorEvents::Enable).unwrap(); + } else { + self.service_events.try_send(MarketMonitorEvents::Disable).unwrap(); + } + } + #[allow(dead_code)] async fn update_available_currencies(&self) -> Result<()> { let available_currencies = self.provider().fetch_available_currencies().await?; @@ -195,9 +205,18 @@ impl Service for MarketMonitorService { this.update_market_price_list().await?; }, - msg = this.as_ref().plugin_events.receiver.recv().fuse() => { + msg = this.as_ref().service_events.receiver.recv().fuse() => { if let Ok(event) = msg { match event { + MarketMonitorEvents::Enable => { + if !this.is_enabled.load(Ordering::SeqCst) { + this.is_enabled.store(true, Ordering::SeqCst); + this.update_market_price_list().await?; + } + } + MarketMonitorEvents::Disable => { + this.is_enabled.store(false, Ordering::SeqCst); + } MarketMonitorEvents::Exit => { break; } @@ -215,7 +234,7 @@ impl Service for MarketMonitorService { } fn terminate(self: Arc) { - self.plugin_events + self.service_events .sender .try_send(MarketMonitorEvents::Exit) .unwrap(); diff --git a/core/src/runtime/services/plugin_manager.rs b/core/src/runtime/services/plugin_manager.rs deleted file mode 100644 index d7176e5..0000000 --- a/core/src/runtime/services/plugin_manager.rs +++ /dev/null @@ -1,213 +0,0 @@ -use crate::imports::*; -use crate::runtime::plugins::*; - -pub enum PluginManagerEvents { - Start(Arc), - Stop(Arc), - Exit, -} - -pub struct PluginManagerService { - pub application_events: ApplicationEventsChannel, - pub service_events: Channel, - pub task_ctl: Channel<()>, - pub plugins: Arc>>, - pub plugin_settings: Mutex, - pub running_plugins: HashMap, -} - -impl PluginManagerService { - pub fn new(application_events: ApplicationEventsChannel, settings: &Settings) -> Self { - let plugins: Vec> = vec![Arc::new(MarketMonitorPlugin::new( - application_events.clone(), - ))]; - - let running_plugins = plugins - .iter() - .map(|plugin| (plugin.ident().to_string(), AtomicBool::new(false))) - .collect::>(); - - // let plugins: Vec = plugins - // .into_iter() - // .map(|plugin| PluginContainer::new(plugin)) - // .collect(); - - Self { - application_events, - service_events: Channel::unbounded(), - task_ctl: Channel::oneshot(), - plugins: Arc::new(plugins), - plugin_settings: Mutex::new(settings.plugins.clone().unwrap_or_default()), - running_plugins, - // is_enabled_map: HashMap::new(), - } - } - - pub fn is_running(&self, plugin: &Arc) -> bool { - self.running_plugins - .get(plugin.ident()) - .map(|is_running| is_running.load(Ordering::Relaxed)) - .expect("is_running(): no such plugin") - } - - pub fn is_enabled(&self, plugin: &Arc) -> bool { - self.plugin_settings - .lock() - .unwrap() - .get(plugin.ident()) - .map(|settings| settings.enabled) - .unwrap_or(false) - } - - pub fn enable(&self, plugin: &Arc, enabled: bool) { - if let Some(plugin_settings) = self.plugin_settings.lock().unwrap().get_mut(plugin.ident()) - { - plugin_settings.enabled = enabled; - } - - // - TODO - START PLUGIN IF NOT RUNNING - // - TODO - START PLUGIN IF NOT RUNNING - // - TODO - START PLUGIN IF NOT RUNNING - // - TODO - START PLUGIN IF NOT RUNNING - // - TODO - START PLUGIN IF NOT RUNNING - } - - pub fn plugins(&self) -> &Arc>> { - &self.plugins - } - - pub fn running_plugins(&self) -> Vec> { - self.plugins() - .iter() - .filter(|plugin| self.is_running(plugin)) - .cloned() - .collect::>() - } - - pub fn store(&self) -> Result { - let mut plugin_settings_map = PluginSettingsMap::default(); - for plugin in self.plugins().iter() { - let enabled = self.is_enabled(plugin); - if let Ok(Some(settings)) = plugin.store() { - let plugin_settings = PluginSettings { enabled, settings }; - plugin_settings_map.insert(plugin.ident().to_string(), plugin_settings); - } - } - Ok(plugin_settings_map) - } - - pub async fn start_plugins(&self, settings: &Settings) -> Result<()> { - // do nothing if plugins are disabled - if !settings.enable_plugins { - return Ok(()); - } - - *self.plugin_settings.lock().unwrap() = settings.plugins.clone().unwrap_or_default(); - - let running_plugins = self.running_plugins(); - for plugin in running_plugins.into_iter() { - let ident = plugin.ident(); - if let Some(plugin_settings) = self.plugin_settings.lock().unwrap().get(ident).cloned() - { - plugin.load(plugin_settings.settings)?; - } - if let Err(err) = plugin.clone().start().await { - log_error!("Failed to start plugin {}: {}", plugin.name(), err); - } - } - Ok(()) - } - - pub fn terminate_plugins(&self) { - let running_plugins = self.running_plugins(); - running_plugins - .into_iter() - .for_each(|plugin| plugin.terminate()); - } - - pub async fn join_plugins(&self) -> Result<()> { - let running_plugins = self.running_plugins(); - for plugin in running_plugins.into_iter() { - if let Err(err) = plugin.clone().join().await { - log_error!("Failed to join plugin {}: {}", plugin.name(), err); - } - } - Ok(()) - } -} - -#[async_trait] -impl Service for PluginManagerService { - fn name(&self) -> &'static str { - "plugin-manager" - } - - async fn attach_rpc(self: Arc, rpc_api: &Arc) -> Result<()> { - let running_plugins = self.running_plugins(); - for plugin in running_plugins.into_iter() { - if let Err(err) = plugin.clone().attach_rpc(rpc_api).await { - log_error!("Failed to attach RPC to plugin {}: {}", plugin.name(), err); - } - } - Ok(()) - } - - async fn detach_rpc(self: Arc) -> Result<()> { - let running_plugins = self.running_plugins(); - for plugin in running_plugins.into_iter() { - if let Err(err) = plugin.clone().detach_rpc().await { - log_error!( - "Failed to detach RPC from plugin {}: {}", - plugin.name(), - err - ); - } - } - - Ok(()) - } - - async fn spawn(self: Arc) -> Result<()> { - let this = self.clone(); - let _application_events_sender = self.application_events.sender.clone(); - - loop { - select! { - - msg = this.service_events.recv().fuse() => { - if let Ok(event) = msg { - match event { - PluginManagerEvents::Start(_plugin) => { - } - PluginManagerEvents::Stop(_plugin) => { - } - PluginManagerEvents::Exit => { - break; - } - } - } else { - break; - } - } - } - } - - this.task_ctl.send(()).await.unwrap(); - - Ok(()) - } - - fn terminate(self: Arc) { - self.terminate_plugins(); - - self.service_events - .sender - .try_send(PluginManagerEvents::Exit) - .unwrap(); - } - - async fn join(self: Arc) -> Result<()> { - self.join_plugins().await?; - Ok(()) - } -} diff --git a/core/src/runtime/services/update_monitor.rs b/core/src/runtime/services/update_monitor.rs index d701a6e..88af211 100644 --- a/core/src/runtime/services/update_monitor.rs +++ b/core/src/runtime/services/update_monitor.rs @@ -32,12 +32,13 @@ impl UpdateMonitorService { // self.rpc_api.lock().unwrap().clone() // } - // pub fn enable(&self) { - // self.service_events - // .sender - // .try_send(UpdateMonitorEvents::Enable) - // .unwrap(); - // } + pub fn enable(&self, enable : bool) { + if enable { + self.service_events.try_send(UpdateMonitorEvents::Enable).unwrap(); + } else { + self.service_events.try_send(UpdateMonitorEvents::Disable).unwrap(); + } + } // pub fn disable(&self) { // self.service_events @@ -85,7 +86,11 @@ impl Service for UpdateMonitorService { if let Ok(event) = msg { match event { UpdateMonitorEvents::Enable => { - self.is_enabled.store(true, Ordering::Relaxed); + if !self.is_enabled.load(Ordering::Relaxed) { + self.is_enabled.store(true, Ordering::Relaxed); + #[cfg(not(target_arch = "wasm32"))] + let _ = check_version().await; + } } UpdateMonitorEvents::Disable => { self.is_enabled.store(false, Ordering::Relaxed);