diff --git a/README.md b/README.md index ca8fe0c..e9c5f46 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ One of the best ways to test this application is to build both desktop and web v ### TODO (Known Issues) - [ ] Web App does not currently preserve transaction history. Reloading the page or the wallet will result in the blank transaction list (this does not affect the wallet functionality). The Web Browser transaction history storage backend is currently under development in the Rusty Kaspa wallet framework. +- [ ] When the Wen App goes off screen or in the background tab, browser will suspend it preventing it from processing updates. There is a workaround for this, but it is not yet implemented. ### License diff --git a/core/src/egui/theme/color.rs b/core/src/egui/theme/color.rs index 478fd2a..dbbd12f 100644 --- a/core/src/egui/theme/color.rs +++ b/core/src/egui/theme/color.rs @@ -19,6 +19,7 @@ pub struct ThemeColor { pub icon_color_default: Color32, pub ack_color: Color32, pub nack_color: Color32, + pub metrics_text_color: Color32, pub market_default_color: Color32, pub market_up_color: Color32, pub market_down_color: Color32, @@ -28,7 +29,8 @@ pub struct ThemeColor { pub qr_background: Color32, pub qr_foreground: Color32, - pub selection_color: Color32, + pub selection_background_color: Color32, + pub selection_text_color: Color32, pub progress_color: Color32, pub default_color: Color32, @@ -87,6 +89,7 @@ impl ThemeColor { icon_color_default: Color32::from_rgb(240, 240, 240), ack_color: Color32::from_rgb(100, 200, 100), nack_color: Color32::from_rgb(200, 100, 100), + metrics_text_color: Color32::from_rgb(230, 230, 230), market_default_color: Color32::from_rgb(240, 240, 240), market_up_color: Color32::from_rgb(136, 255, 136), market_down_color: Color32::from_rgb(255, 136, 136), @@ -96,7 +99,8 @@ impl ThemeColor { qr_background: Color32::from_rgba(0, 0, 0, 0), qr_foreground: Color32::WHITE, - selection_color: Color32::from_rgb(40, 153, 132), + selection_background_color: Color32::from_rgb(40, 153, 132), + selection_text_color: Color32::from_rgb(220,220,220), progress_color: Color32::from_rgb(71, 105, 97), transaction_incoming: Color32::from_rgb(162, 245, 187), @@ -153,6 +157,7 @@ impl ThemeColor { icon_color_default: Color32::from_rgb(32, 32, 32), ack_color: Color32::from_rgb(100, 200, 100), nack_color: Color32::from_rgb(200, 100, 100), + metrics_text_color: Color32::from_rgb(20, 20, 20), market_default_color: Color32::from_rgb(20, 20, 20), market_up_color: Color32::from_rgb(41, 77, 41), market_down_color: Color32::from_rgb(77, 41, 41), @@ -162,7 +167,8 @@ impl ThemeColor { qr_background: Color32::from_rgba(255, 255, 255, 0), qr_foreground: Color32::BLACK, - selection_color: Color32::from_rgb(165, 201, 197), + selection_background_color: Color32::from_rgb(165, 201, 197), + selection_text_color: Color32::from_rgb(20,20,20), progress_color: Color32::from_rgb(165, 201, 197), transaction_incoming: Color32::from_rgb(15, 77, 35), diff --git a/core/src/egui/theme/mod.rs b/core/src/egui/theme/mod.rs index 61f066d..28fbd48 100644 --- a/core/src/egui/theme/mod.rs +++ b/core/src/egui/theme/mod.rs @@ -53,8 +53,8 @@ impl From<&Theme> for Visuals { visuals.widgets.open.rounding = theme.style.widget_rounding; visuals.hyperlink_color = theme.color.hyperlink_color; - visuals.selection.bg_fill = theme.color.selection_color; - visuals.selection.stroke.color = theme.color.selection_color; + visuals.selection.bg_fill = theme.color.selection_background_color; + visuals.selection.stroke.color = theme.color.selection_text_color; visuals.warn_fg_color = theme.color.warning_color; visuals.error_fg_color = theme.color.error_color; diff --git a/core/src/modules/donations.rs b/core/src/modules/donations.rs index 7ee7a2b..06407e4 100644 --- a/core/src/modules/donations.rs +++ b/core/src/modules/donations.rs @@ -61,7 +61,7 @@ impl ModuleT for Donations { use egui_phosphor::light::CLIPBOARD_TEXT; ui.add_space(8.); - ui.label("This project relies on the support of the community in all areas including development, testing and funding."); + ui.label("This project relies on the support of the community."); ui.label(" "); ui.label("If you are able to contribute by donating, we would greatly appreciate your support."); ui.label(" "); diff --git a/core/src/modules/metrics.rs b/core/src/modules/metrics.rs index 59fdce0..888e4ce 100644 --- a/core/src/modules/metrics.rs +++ b/core/src/modules/metrics.rs @@ -11,6 +11,9 @@ use egui_plot::{ PlotPoints, uniform_grid_spacer, CoordinatesFormatter, Corner, }; +const METRICS_SAMPLES_START : isize = -(MAX_METRICS_SAMPLES as isize); +const MIN_RANGE : isize = 15; + pub struct Metrics { #[allow(dead_code)] runtime: Runtime, @@ -35,18 +38,30 @@ impl ModuleT for Metrics { _frame: &mut eframe::Frame, ui: &mut egui::Ui, ) { - // let theme = theme(); - let screen_rect_height = ui.ctx().screen_rect().height(); let mut store_settings = false; let mut graph_columns = core.settings.user_interface.metrics.graph_columns; let mut graph_height = core.settings.user_interface.metrics.graph_height; - #[allow(unused_mut)] let mut graph_range_from = core.settings.user_interface.metrics.graph_range_from; let mut graph_range_to = core.settings.user_interface.metrics.graph_range_to; + if graph_range_from < METRICS_SAMPLES_START { + graph_range_from = METRICS_SAMPLES_START; + } + + if graph_range_to > 0 { + graph_range_to = 0; + } + + if graph_range_to < METRICS_SAMPLES_START { + graph_range_to = METRICS_SAMPLES_START; + } + + if graph_range_to > 0 { + graph_range_to = 0; + } ui.horizontal(|ui|{ ui.heading("Node Metrics"); @@ -66,28 +81,6 @@ impl ModuleT for Metrics { .orientation(SliderOrientation::Horizontal) .suffix("px") ); - // ui.label("From:"); - // ui.add( - // Slider::new(&mut graph_range_from, 0..=MAX_METRICS_SAMPLES) - // .text("From") - // .logarithmic(true) - // .orientation(SliderOrientation::Horizontal) - // .custom_formatter(|v, _range| { - // format_duration(v as u64) - // }) - // ); - // ui.label("To:"); - // ui.label("Duration:"); - // ui.space(); - // ui.add( - // Slider::new(&mut graph_range_to, 15..=MAX_METRICS_SAMPLES) - // .text("Duration") - // .logarithmic(true) - // .orientation(SliderOrientation::Horizontal) - // .custom_formatter(|v, _range| { - // format_duration(v as u64) - // }) - // ); ui.space(); ui.separator(); @@ -145,23 +138,54 @@ impl ModuleT for Metrics { ui.separator(); ui.add( - Slider::new(&mut graph_range_to, 15..=MAX_METRICS_SAMPLES) + Slider::new(&mut graph_range_to, (METRICS_SAMPLES_START+MIN_RANGE)..=0) .logarithmic(true) .orientation(SliderOrientation::Horizontal) - .custom_formatter(|v, _range| { - format_duration(v as u64) - }) + .show_value(false) + // .custom_formatter(|v, _range| { + // format_duration(-v as u64) + // }) ); - if core.device().orientation() == Orientation::Portrait { - ui.label("Duration:"); + ui.add( + Slider::new(&mut graph_range_from, METRICS_SAMPLES_START..=-MIN_RANGE) + .logarithmic(true) + .orientation(SliderOrientation::Horizontal) + .show_value(false) + // .custom_formatter(|v, _range| { + // format_duration(-v as u64) + // }) + ); + ui.label(format!("{} ... {}", format_duration(-graph_range_from as u64), format_duration(-graph_range_to as u64))); + if core.device().orientation() != Orientation::Portrait { + ui.label("Range:"); } }); }); - if graph_range_from > graph_range_to { + if graph_range_from != core.settings.user_interface.metrics.graph_range_from { + if graph_range_from.abs_diff(graph_range_to) < 15 { + graph_range_to = graph_range_from + 15; + } + } + + if graph_range_to != core.settings.user_interface.metrics.graph_range_to { + if graph_range_to.abs_diff(graph_range_from) < 15 { + graph_range_from = graph_range_to - 15; + } + } + + if graph_range_from.abs_diff(graph_range_to) < 15 { graph_range_to = graph_range_from + 15; } + + if graph_range_to.abs_diff(graph_range_from) < 15 { + graph_range_from = graph_range_to - 15; + } + + if graph_range_from > graph_range_to { + graph_range_from = graph_range_to - 15; + } if store_settings || graph_columns != core.settings.user_interface.metrics.graph_columns @@ -169,6 +193,8 @@ impl ModuleT for Metrics { || graph_range_from != core.settings.user_interface.metrics.graph_range_from || graph_range_to != core.settings.user_interface.metrics.graph_range_to { + + println!("graph_range_from: {} graph_range_to: {}", graph_range_from, graph_range_to); core.settings.user_interface.metrics.graph_columns = graph_columns; core.settings.user_interface.metrics.graph_height = graph_height; core.settings.user_interface.metrics.graph_range_from = graph_range_from; @@ -234,7 +260,7 @@ impl Metrics { ui : &mut Ui, metric : Metric, metrics : &MetricsSnapshot, - range : std::ops::Range, + range : std::ops::Range, graph_width : f32, graph_height : f32 ) { @@ -251,7 +277,7 @@ impl Metrics { ui.add_space(8.); ui.horizontal(|ui|{ ui.with_layout(Layout::right_to_left(egui::Align::Min), |ui| { - ui.label(format!("{}: {}", i18n(metric.title().0), metric.format(metrics.get(&metric), true, false))); + ui.colored_label(theme_color().metrics_text_color, format!("{}: {}", i18n(metric.title().0), metric.format(metrics.get(&metric), true, false))); }); }); @@ -259,15 +285,15 @@ impl Metrics { let graph_data = { let metrics_data = self.runtime.metrics_service().metrics_data(); let data = metrics_data.get(&metric).unwrap(); - let mut start = range.start; - let mut end = range.end; + let mut start = range.start.clamp(METRICS_SAMPLES_START, 0).abs() as usize; + let mut end = range.end.clamp(METRICS_SAMPLES_START, 0).abs() as usize; if start > data.len() { start = data.len(); } if end > data.len() { end = data.len(); } - data[data.len()-end..data.len()-start].to_vec() + data[data.len()-start..data.len()-end].to_vec() }; let mut plot = Plot::new(metric.as_str()) diff --git a/core/src/modules/settings/mod.rs b/core/src/modules/settings/mod.rs index 5cd949c..e08ea54 100644 --- a/core/src/modules/settings/mod.rs +++ b/core/src/modules/settings/mod.rs @@ -367,45 +367,53 @@ impl Settings { .default_open(false) .show(ui, |ui| { - ui.vertical(|ui|{ - ui.checkbox(&mut self.settings.developer.enable, i18n("Developer Mode")); - ui.label("Developer mode enables advanced and experimental features"); + ui.horizontal(|ui| { + ui.add_space(2.); + ui.vertical(|ui|{ + ui.checkbox(&mut self.settings.developer.enable, i18n("Developer Mode")); + if !self.settings.developer.enable { + ui.label("Developer mode enables advanced and experimental features"); + } + }); }); - ui.vertical(|ui|{ - if self.settings.developer.enable { - #[cfg(not(target_arch = "wasm32"))] - ui.checkbox( - &mut self.settings.developer.enable_experimental_features, - i18n("Enable experimental features") - ).on_hover_text_at_pointer( - i18n("Enables features currently in development") - ); - - #[cfg(not(target_arch = "wasm32"))] - ui.checkbox( - &mut self.settings.developer.enable_custom_daemon_args, - i18n("Enable custom daemon arguments") - ).on_hover_text_at_pointer( - i18n("Allow custom arguments for the Rusty Kaspa daemon") - ); - - ui.checkbox( - &mut self.settings.developer.disable_password_restrictions, - i18n("Disable password score restrictions") - ).on_hover_text_at_pointer( - i18n("Removes security restrictions, allows for single-letter passwords") - ); - - #[cfg(not(target_arch = "wasm32"))] - ui.checkbox( - &mut self.settings.developer.enable_screen_capture, - i18n("Enable screen capture") - ).on_hover_text_at_pointer( - i18n("Allows you to take screenshots from within the application") - ); - } - }); + if self.settings.developer.enable { + ui.indent("developer_mode_settings", |ui | { + + // ui.vertical(|ui|{ + #[cfg(not(target_arch = "wasm32"))] + ui.checkbox( + &mut self.settings.developer.enable_experimental_features, + i18n("Enable experimental features") + ).on_hover_text_at_pointer( + i18n("Enables features currently in development") + ); + + #[cfg(not(target_arch = "wasm32"))] + ui.checkbox( + &mut self.settings.developer.enable_custom_daemon_args, + i18n("Enable custom daemon arguments") + ).on_hover_text_at_pointer( + i18n("Allow custom arguments for the Rusty Kaspa daemon") + ); + + ui.checkbox( + &mut self.settings.developer.disable_password_restrictions, + i18n("Disable password score restrictions") + ).on_hover_text_at_pointer( + i18n("Removes security restrictions, allows for single-letter passwords") + ); + + #[cfg(not(target_arch = "wasm32"))] + ui.checkbox( + &mut self.settings.developer.enable_screen_capture, + i18n("Enable screen capture") + ).on_hover_text_at_pointer( + i18n("Allows you to take screenshots from within the application") + ); + // }); + }); + } if self.settings.developer != core.settings.developer { ui.add_space(16.); diff --git a/core/src/modules/welcome.rs b/core/src/modules/welcome.rs index d631554..05afa90 100644 --- a/core/src/modules/welcome.rs +++ b/core/src/modules/welcome.rs @@ -150,6 +150,8 @@ impl ModuleT for Welcome { }); ui.vertical_centered(|ui| { + ui.add_space(32.0); + ui.colored_label(theme_color().alert_color, "Please note - this is an alpha release - Kaspa NG is still in early development and is not yet ready for production use."); ui.add_space(32.0); ui.label(format!("Kaspa NG v{} • Rusty Kaspa v{}", env!("CARGO_PKG_VERSION"), kaspa_wallet_core::version())); ui.hyperlink_to( diff --git a/core/src/settings.rs b/core/src/settings.rs index ae6c2ee..67015be 100644 --- a/core/src/settings.rs +++ b/core/src/settings.rs @@ -171,9 +171,20 @@ impl std::fmt::Display for NetworkInterfaceConfig { } } + + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum NodeConnectionConfigKind { + Custom, + Existing, +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct NodeSettings { + // pub connection_config_kind: NodeConnectionConfigKind, + // pub existing_server: Server, pub rpc_kind: RpcKind, pub wrpc_url: String, pub wrpc_encoding: WrpcEncoding, @@ -296,8 +307,8 @@ impl From<&NodeSettings> for RpcConfig { pub struct MetricsSettings { pub graph_columns: usize, pub graph_height: usize, - pub graph_range_from: usize, - pub graph_range_to: usize, + pub graph_range_from: isize, + pub graph_range_to: isize, pub disabled: AHashSet, } @@ -306,8 +317,8 @@ impl Default for MetricsSettings { Self { graph_columns: 3, graph_height: 90, - graph_range_from: 0, - graph_range_to: 15 * 60, + graph_range_from: -15 * 60, + graph_range_to: 0, disabled: AHashSet::default(), } } diff --git a/core/src/utils/arglist.rs b/core/src/utils/arglist.rs index 164716b..0a6d6a5 100644 --- a/core/src/utils/arglist.rs +++ b/core/src/utils/arglist.rs @@ -1,3 +1,5 @@ +use ahash::AHashSet; + #[derive(Default)] pub struct Arglist { pub args: Vec, @@ -11,6 +13,13 @@ impl Arglist { impl From for Vec { fn from(arglist: Arglist) -> Self { - arglist.args + let mut unique_elements = AHashSet::new(); + let mut list = vec![]; + for arg in arglist.args.into_iter() { + if unique_elements.insert(arg.clone()) { + list.push(arg); + } + } + list } }