mirror of
https://github.com/jwinterm/grim.git
synced 2026-10-22 07:58:31 +02:00
config + ui + node: all server config values, stratum config ui refactoring, global modal position fix, modal id refactoring, remove chain data on node launch error
This commit is contained in:
+5
-4
@@ -64,7 +64,6 @@ impl App {
|
||||
|
||||
/// Setup application styles.
|
||||
pub fn setup_visuals(ctx: &Context) {
|
||||
// Setup style
|
||||
let mut style = (*ctx.style()).clone();
|
||||
// Setup spacing for buttons.
|
||||
style.spacing.button_padding = egui::vec2(12.0, 8.0);
|
||||
@@ -76,14 +75,16 @@ impl App {
|
||||
style.spacing.icon_width = 24.0;
|
||||
style.spacing.icon_width_inner = 14.0;
|
||||
style.spacing.icon_spacing = 10.0;
|
||||
|
||||
// Setup style
|
||||
ctx.set_style(style);
|
||||
|
||||
// Setup visuals
|
||||
let mut visuals = egui::Visuals::light();
|
||||
|
||||
// Setup selection color.
|
||||
visuals.selection.stroke = Stroke { width: 1.0, color: Colors::TEXT };
|
||||
visuals.selection.bg_fill = Colors::GOLD;
|
||||
// Disable stroke around panels by default
|
||||
visuals.widgets.noninteractive.bg_stroke = Stroke::NONE;
|
||||
// Setup visuals
|
||||
ctx.set_visuals(visuals);
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -25,10 +25,12 @@ impl Colors {
|
||||
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
|
||||
pub const GREEN: Color32 = Color32::from_rgb(0, 0x64, 0);
|
||||
pub const RED: Color32 = Color32::from_rgb(0x8B, 0, 0);
|
||||
pub const FILL: Color32 = Color32::from_gray(240);
|
||||
pub const FILL: Color32 = Color32::from_gray(244);
|
||||
pub const FILL_DARK: Color32 = Color32::from_gray(232);
|
||||
pub const TITLE: Color32 = Color32::from_gray(60);
|
||||
pub const TEXT: Color32 = Color32::from_gray(80);
|
||||
pub const BUTTON: Color32 = Color32::from_gray(70);
|
||||
pub const TEXT_BUTTON: Color32 = Color32::from_gray(70);
|
||||
pub const BUTTON: Color32 = Color32::from_gray(249);
|
||||
pub const GRAY: Color32 = Color32::from_gray(120);
|
||||
pub const STROKE: Color32 = Color32::from_gray(190);
|
||||
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::gui::screens::ScreenId;
|
||||
use crate::gui::views::{Modal, ModalId, ModalLocation};
|
||||
use crate::gui::views::{Modal, ModalLocation};
|
||||
|
||||
lazy_static! {
|
||||
/// Static [`Navigator`] state to be accessible from anywhere.
|
||||
@@ -53,6 +53,9 @@ impl Default for Navigator {
|
||||
}
|
||||
|
||||
impl Navigator {
|
||||
/// Identifier for exit [`Modal`].
|
||||
pub const EXIT_MODAL: &'static str = "exit";
|
||||
|
||||
/// Initialize navigation from provided [`ScreenId`].
|
||||
pub fn init(from: ScreenId) {
|
||||
let mut w_nav = NAVIGATOR_STATE.write().unwrap();
|
||||
@@ -118,7 +121,7 @@ impl Navigator {
|
||||
|
||||
/// Open exit confirmation [`Modal`] with provided [NAVIGATOR_STATE] lock.
|
||||
fn open_exit_modal_nav(mut w_nav: RwLockWriteGuard<Navigator>) {
|
||||
let m = Modal::new(ModalId::Exit, ModalLocation::Global).title(t!("modal_exit.exit"));
|
||||
let m = Modal::new(Self::EXIT_MODAL, ModalLocation::Global).title(t!("modal_exit.exit"));
|
||||
w_nav.global_modal = Some(m);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
use egui::Frame;
|
||||
|
||||
use crate::gui::icons::{ARROW_CIRCLE_LEFT, GLOBE, PLUS};
|
||||
use crate::gui::Navigator;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::screens::{Screen, ScreenId};
|
||||
use crate::gui::views::{TitlePanel, TitlePanelAction, View};
|
||||
@@ -43,6 +43,7 @@ impl Screen for Accounts {
|
||||
egui::CentralPanel::default()
|
||||
.frame(Frame {
|
||||
stroke: View::DEFAULT_STROKE,
|
||||
fill: Colors::FILL_DARK,
|
||||
..Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
|
||||
+27
-22
@@ -17,7 +17,7 @@ use std::cmp::min;
|
||||
use crate::gui::{App, Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::screens::{Account, Accounts, Screen, ScreenId};
|
||||
use crate::gui::views::{ModalId, ModalLocation, Network, View};
|
||||
use crate::gui::views::{ModalLocation, Network, View};
|
||||
use crate::node::Node;
|
||||
|
||||
pub struct Root {
|
||||
@@ -67,10 +67,9 @@ impl Root {
|
||||
ui: &mut egui::Ui,
|
||||
frame: &mut eframe::Frame,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
let location = ModalLocation::Global;
|
||||
Navigator::modal_ui(ui, location, |ui, modal| {
|
||||
Navigator::modal_ui(ui, ModalLocation::Global, |ui, modal| {
|
||||
match modal.id {
|
||||
ModalId::Exit => {
|
||||
Navigator::EXIT_MODAL => {
|
||||
if self.show_exit_progress {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
@@ -89,30 +88,36 @@ impl Root {
|
||||
ui.label(t!("modal_exit.description"));
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
// Setup spacing between buttons
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || {
|
||||
if !Node::is_running() {
|
||||
App::exit(frame, cb);
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop(true);
|
||||
modal.disable_closing();
|
||||
self.show_exit_progress = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop(true);
|
||||
modal.disable_closing();
|
||||
self.show_exit_progress = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,4 +27,6 @@ pub use network::*;
|
||||
mod network_node;
|
||||
mod network_settings;
|
||||
mod network_metrics;
|
||||
mod network_mining;
|
||||
mod network_mining;
|
||||
mod settings_stratum;
|
||||
mod settings_node_server;
|
||||
+19
-17
@@ -21,11 +21,6 @@ use egui::epaint::RectShape;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::views::View;
|
||||
|
||||
/// Identifier for [`Modal`] content to draw at [`Modal::ui`].
|
||||
pub enum ModalId {
|
||||
Exit
|
||||
}
|
||||
|
||||
/// Location for [`Modal`] at application UI.
|
||||
pub enum ModalLocation {
|
||||
/// To draw globally above side panel and screen.
|
||||
@@ -46,8 +41,8 @@ pub enum ModalPosition {
|
||||
|
||||
/// Stores data to draw dialog box/popup at UI, powered by [`egui::Window`].
|
||||
pub struct Modal {
|
||||
/// Identifier for content.
|
||||
pub(crate) id: ModalId,
|
||||
/// Identifier for modal.
|
||||
pub(crate) id: &'static str,
|
||||
/// Location at UI.
|
||||
pub(crate) location: ModalLocation,
|
||||
/// Position on the screen.
|
||||
@@ -65,7 +60,7 @@ impl Modal {
|
||||
const DEFAULT_WIDTH: i64 = 380;
|
||||
|
||||
/// Create open and closeable Modal with center position.
|
||||
pub fn new(id: ModalId, location: ModalLocation) -> Self {
|
||||
pub fn new(id: &'static str, location: ModalLocation) -> Self {
|
||||
Self {
|
||||
id,
|
||||
location,
|
||||
@@ -116,9 +111,7 @@ impl Modal {
|
||||
|
||||
/// Show Modal with provided content.
|
||||
pub fn ui(&self, ui: &mut egui::Ui, add_content: impl FnOnce(&mut egui::Ui, &Modal)) {
|
||||
let width = min(ui.available_width() as i64 - 20, Self::DEFAULT_WIDTH) as f32;
|
||||
|
||||
// Show background Window at full available size
|
||||
// Show background Window at full available size.
|
||||
egui::Window::new(self.window_id(true))
|
||||
.title_bar(false)
|
||||
.resizable(false)
|
||||
@@ -133,13 +126,17 @@ impl Modal {
|
||||
ui.set_min_size(ui.available_size());
|
||||
});
|
||||
|
||||
// Show main content Window at given position
|
||||
// Choose width of modal content.
|
||||
let width = min(ui.available_width() as i64 - 20, Self::DEFAULT_WIDTH) as f32;
|
||||
|
||||
// Show main content Window at given position.
|
||||
let (content_align, content_offset) = self.modal_position();
|
||||
let layer_id = egui::Window::new(self.window_id(false))
|
||||
.title_bar(false)
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.default_width(width)
|
||||
.anchor(self.modal_position(), Vec2::default())
|
||||
.anchor(content_align, content_offset)
|
||||
.frame(egui::Frame {
|
||||
rounding: Rounding::same(8.0),
|
||||
fill: Colors::YELLOW,
|
||||
@@ -152,7 +149,7 @@ impl Modal {
|
||||
self.draw_content(ui, add_content);
|
||||
}).unwrap().response.layer_id;
|
||||
|
||||
// Always show main content Window above background Window
|
||||
// Always show main content Window above background Window.
|
||||
ui.ctx().move_to_top(layer_id);
|
||||
|
||||
}
|
||||
@@ -173,11 +170,16 @@ impl Modal {
|
||||
}
|
||||
|
||||
/// Get [`egui::Window`] position based on [`ModalPosition`].
|
||||
fn modal_position(&self) -> Align2 {
|
||||
match self.position {
|
||||
fn modal_position(&self) -> (Align2, Vec2) {
|
||||
let align = match self.position {
|
||||
ModalPosition::CenterTop => { Align2::CENTER_TOP }
|
||||
ModalPosition::Center => { Align2::CENTER_CENTER }
|
||||
}
|
||||
};
|
||||
let offset = match self.position {
|
||||
ModalPosition::CenterTop => { Vec2::new(0.0, 20.0) }
|
||||
ModalPosition::Center => { Vec2::new(0.0, 0.0) }
|
||||
};
|
||||
(align, offset)
|
||||
}
|
||||
|
||||
/// Draw provided content.
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpListener};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use egui::{Color32, lerp, Rgba, RichText, Stroke};
|
||||
@@ -22,17 +24,18 @@ use grin_chain::SyncStatus;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalLocation, View};
|
||||
use crate::gui::views::network_metrics::NetworkMetrics;
|
||||
use crate::gui::views::network_mining::NetworkMining;
|
||||
use crate::gui::views::network_node::NetworkNode;
|
||||
use crate::gui::views::network_settings::NetworkSettings;
|
||||
use crate::gui::views::View;
|
||||
use crate::node::Node;
|
||||
use crate::Settings;
|
||||
|
||||
pub trait NetworkTab {
|
||||
fn get_type(&self) -> NetworkTabType;
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks);
|
||||
fn on_modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks);
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
@@ -68,13 +71,19 @@ impl Default for Network {
|
||||
|
||||
impl Network {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
||||
// Show modal if it's opened.
|
||||
if Navigator::is_modal_open(ModalLocation::SidePanel) {
|
||||
Navigator::modal_ui(ui, ModalLocation::SidePanel, |ui, modal| {
|
||||
self.current_tab.as_mut().on_modal_ui(ui, modal, cb);
|
||||
});
|
||||
}
|
||||
|
||||
egui::TopBottomPanel::top("network_title")
|
||||
.resizable(false)
|
||||
.frame(egui::Frame {
|
||||
fill: Colors::YELLOW,
|
||||
inner_margin: Margin::same(0.0),
|
||||
outer_margin: Margin::same(0.0),
|
||||
stroke: Stroke::NONE,
|
||||
..Default::default()
|
||||
})
|
||||
.show_inside(ui, |ui| {
|
||||
@@ -217,7 +226,8 @@ impl Network {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn disabled_server_content(ui: &mut egui::Ui) {
|
||||
/// Content to draw when node is disabled.
|
||||
pub fn disabled_node_ui(ui: &mut egui::Ui) {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
let text = t!("network.disabled_server", "dots" => DOTS_THREE_OUTLINE_VERTICAL);
|
||||
ui.label(RichText::new(text)
|
||||
@@ -241,5 +251,25 @@ impl Network {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// List of available IP addresses.
|
||||
pub fn get_ip_list() -> Vec<IpAddr> {
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
addresses
|
||||
}
|
||||
|
||||
/// Check whether a port is available on the provided host.
|
||||
pub fn is_port_available(host: &str, port: u16) -> bool {
|
||||
let ip_addr = Ipv4Addr::from_str(host).unwrap();
|
||||
let ipv4 = SocketAddrV4::new(ip_addr, port);
|
||||
TcpListener::bind(ipv4).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke, Ui};
|
||||
use grin_servers::DiffBlock;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -39,7 +39,7 @@ impl NetworkTab for NetworkMetrics {
|
||||
// Show message when node is not running or loading spinner when metrics are not available.
|
||||
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
@@ -113,9 +113,9 @@ impl NetworkTab for NetworkMetrics {
|
||||
// Show difficulty adjustment window blocks
|
||||
let blocks_size = stats.diff_stats.last_blocks.len();
|
||||
ScrollArea::vertical()
|
||||
.id_source("difficulty_scroll")
|
||||
.auto_shrink([false; 2])
|
||||
.stick_to_bottom(true)
|
||||
.id_source("difficulty_scroll")
|
||||
.show_rows(
|
||||
ui,
|
||||
DIFF_BLOCK_UI_HEIGHT,
|
||||
@@ -137,6 +137,8 @@ impl NetworkTab for NetworkMetrics {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {}
|
||||
}
|
||||
|
||||
const DIFF_BLOCK_UI_HEIGHT: f32 = 76.60;
|
||||
|
||||
+37
-135
@@ -12,24 +12,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fmt::format;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||
use egui::{Response, RichText, Rounding, ScrollArea, Stroke, TextStyle, Widget};
|
||||
use grin_chain::SyncStatus;
|
||||
use grin_servers::WorkerStats;
|
||||
use pnet::ipnetwork::IpNetwork;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON, WRENCH};
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::settings_stratum::StratumServerSetup;
|
||||
use crate::node::{Node, NodeConfig};
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NetworkMining;
|
||||
pub struct NetworkMining {
|
||||
stratum_server_setup: StratumServerSetup
|
||||
}
|
||||
|
||||
impl NetworkTab for NetworkMining {
|
||||
fn get_type(&self) -> NetworkTabType {
|
||||
@@ -42,7 +41,7 @@ impl NetworkTab for NetworkMining {
|
||||
// Show message when node is not running or loading spinner when mining are not available.
|
||||
if !server_stats.is_some() || Node::get_sync_status().unwrap() != SyncStatus::NoSync {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
@@ -58,137 +57,31 @@ impl NetworkTab for NetworkMining {
|
||||
|
||||
let stratum_stats = &server_stats.as_ref().unwrap().stratum_stats;
|
||||
|
||||
// Stratum server address + port from config.
|
||||
let saved_stratum_addr = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.stratum_server_addr.unwrap();
|
||||
let (stratum_addr, stratum_port) = saved_stratum_addr.split_once(":").unwrap();
|
||||
|
||||
// List of available ip addresses.
|
||||
let mut addresses = Vec::new();
|
||||
for net_if in pnet::datalink::interfaces() {
|
||||
for ip in net_if.ips {
|
||||
if ip.is_ipv4() {
|
||||
addresses.push(ip.ip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show error message when IP addresses are not available on the system.
|
||||
if addresses.is_empty() {
|
||||
View::center_content(ui, 52.0, |ui| {
|
||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show stratum server setup when mining server is not enabled.
|
||||
// Show stratum server setup when mining server is not running.
|
||||
if !stratum_stats.is_running && !Node::is_stratum_server_starting() {
|
||||
ScrollArea::vertical()
|
||||
.id_source("stratum_server_setup")
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
ui.add_space(6.0);
|
||||
View::sub_title(ui,
|
||||
format!("{} {}", WRENCH, t!("network_mining.server_setup")));
|
||||
|
||||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
self.stratum_server_setup.ui(ui, cb);
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_mining.choose_ip_address"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(10.0);
|
||||
|
||||
if addresses.len() != 0 {
|
||||
let saved_ip_addr = &IpAddr::from_str(stratum_addr).unwrap();
|
||||
let mut selected_addr = saved_ip_addr;
|
||||
|
||||
// Set first IP address as current if saved is not present at system.
|
||||
if !addresses.contains(selected_addr) {
|
||||
selected_addr = addresses.get(0).unwrap();
|
||||
}
|
||||
|
||||
// Show available IP addresses on the system.
|
||||
let _ = addresses.chunks(2).map(|x| {
|
||||
if x.len() == 2 {
|
||||
ui.columns(2, |columns| {
|
||||
let addr0 = x.get(0).unwrap();
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr0,
|
||||
addr0.to_string());
|
||||
});
|
||||
let addr1 = x.get(1).unwrap();
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr1,
|
||||
addr1.to_string());
|
||||
})
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
} else {
|
||||
let addr = x.get(0).unwrap();
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr,
|
||||
addr.to_string());
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Save stratum server address at config if it was changed.
|
||||
if saved_ip_addr != selected_addr {
|
||||
let addr_to_save = format!("{}:{}", selected_addr, stratum_port);
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.stratum_server_addr = Some(addr_to_save);
|
||||
w_node_config.save();
|
||||
}
|
||||
}
|
||||
|
||||
ui.label(RichText::new(t!("network_mining.change_port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
|
||||
// Show button to choose server port.
|
||||
ui.add_space(6.0);
|
||||
View::button(ui, stratum_port.to_string(), Colors::WHITE, || {
|
||||
//TODO: Open modal to change value
|
||||
cb.show_keyboard();
|
||||
});
|
||||
|
||||
ui.add_space(14.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show message about stratum server config.
|
||||
let text = t!(
|
||||
"network_mining.server_setting",
|
||||
"address" => saved_stratum_addr,
|
||||
"settings" => FADERS
|
||||
);
|
||||
let text = t!("network_mining.server_setting", "settings" => FADERS);
|
||||
ui.label(RichText::new(text)
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(8.0);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show button to enable server.
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
// Show button to enable stratum server if port is available.
|
||||
if self.stratum_server_setup.stratum_port_available {
|
||||
ui.add_space(6.0);
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
|
||||
let stratum_enabled = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
@@ -218,9 +111,10 @@ impl NetworkTab for NetworkMining {
|
||||
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
let (stratum_addr, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
View::rounded_box(ui,
|
||||
saved_stratum_addr,
|
||||
t!("network_mining.ip_address"),
|
||||
format!("{}:{}", stratum_addr, stratum_port),
|
||||
t!("network_mining.address"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
columns[1].vertical_centered(|ui| {
|
||||
@@ -302,7 +196,6 @@ impl NetworkTab for NetworkMining {
|
||||
ui.add_space(4.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
ScrollArea::vertical()
|
||||
.auto_shrink([false; 2])
|
||||
.id_source("stratum_workers_scroll")
|
||||
@@ -322,7 +215,7 @@ impl NetworkTab for NetworkMining {
|
||||
} else {
|
||||
[false, false]
|
||||
};
|
||||
draw_worker_stats(ui, worker, rounding)
|
||||
draw_workers_stats(ui, worker, rounding)
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -335,11 +228,20 @@ impl NetworkTab for NetworkMining {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
match modal.id {
|
||||
StratumServerSetup::STRATUM_PORT_MODAL => {
|
||||
self.stratum_server_setup.stratum_port_modal_ui(ui, modal, cb);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const WORKER_UI_HEIGHT: f32 = 77.0;
|
||||
|
||||
fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
||||
fn draw_workers_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
|
||||
// Add space before the first item.
|
||||
if rounding[0] {
|
||||
ui.add_space(4.0);
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
use eframe::epaint::Stroke;
|
||||
use egui::{RichText, Rounding, ScrollArea};
|
||||
use egui::{RichText, Rounding, ScrollArea, Ui};
|
||||
use grin_servers::PeerStats;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS_CONNECTED, SHARE_NETWORK};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::gui::views::{Modal, Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -35,7 +35,7 @@ impl NetworkTab for NetworkNode {
|
||||
// Show message when node is not running or loading spinner when stats are not available.
|
||||
if !server_stats.is_some() {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
Network::disabled_node_ui(ui);
|
||||
} else {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
@@ -47,6 +47,7 @@ impl NetworkTab for NetworkNode {
|
||||
let stats = server_stats.as_ref().unwrap();
|
||||
|
||||
ScrollArea::vertical()
|
||||
.id_source("integrated_node")
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
// Show header info.
|
||||
@@ -180,6 +181,8 @@ impl NetworkTab for NetworkNode {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {}
|
||||
}
|
||||
|
||||
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||
|
||||
@@ -12,9 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::Ui;
|
||||
use grin_core::global::ChainTypes;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::COMPUTER_TOWER;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{NetworkTab, NetworkTabType};
|
||||
use crate::gui::views::{Modal, NetworkTab, NetworkTabType, View};
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -26,5 +29,13 @@ impl NetworkTab for NetworkSettings {
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_settings.server")));
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
}
|
||||
|
||||
fn on_modal_ui(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// /// Integrated node server setup ui section.
|
||||
// struct
|
||||
@@ -0,0 +1,247 @@
|
||||
// Copyright 2023 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use egui::{RichText, TextStyle, Widget};
|
||||
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::WRENCH;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalLocation, ModalPosition, Network, View};
|
||||
use crate::node::NodeConfig;
|
||||
|
||||
/// Stratum server setup ui section.
|
||||
pub struct StratumServerSetup {
|
||||
/// Stratum address to be used inside edit modal.
|
||||
stratum_address_edit: String,
|
||||
/// Stratum port to be used inside edit modal.
|
||||
stratum_port_edit: String,
|
||||
/// Flag to check if stratum port is available inside edit modal.
|
||||
port_available_edit: bool,
|
||||
|
||||
/// Flag to check if stratum port is available from saved config value.
|
||||
pub(crate) stratum_port_available: bool
|
||||
}
|
||||
|
||||
impl Default for StratumServerSetup {
|
||||
fn default() -> Self {
|
||||
let (stratum_address, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
let is_port_available = Network::is_port_available(stratum_address.as_str(), stratum_port);
|
||||
Self {
|
||||
stratum_address_edit: stratum_address,
|
||||
stratum_port_edit: stratum_port.to_string(),
|
||||
port_available_edit: is_port_available,
|
||||
stratum_port_available: is_port_available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StratumServerSetup {
|
||||
/// Identifier for stratum port [`Modal`].
|
||||
pub const STRATUM_PORT_MODAL: &'static str = "stratum_port";
|
||||
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", WRENCH, t!("network_mining.server_setup")));
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show error message when IP addresses are not available on the system.
|
||||
let mut addresses = Network::get_ip_list();
|
||||
if addresses.is_empty() {
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_mining.no_ip_addresses"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.ip_address"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show stratum IP address setup.
|
||||
Self::ip_address_setup_ui(ui, addresses);
|
||||
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
|
||||
// Show button to choose stratum server port.
|
||||
ui.add_space(6.0);
|
||||
let (stratum_address, stratum_port) = NodeConfig::get_stratum_address_port();
|
||||
View::button(ui, stratum_port.to_string(), Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.stratum_address_edit = stratum_address.clone();
|
||||
self.stratum_port_edit = stratum_port.to_string();
|
||||
self.port_available_edit = Network::is_port_available(
|
||||
stratum_address.as_str(),
|
||||
stratum_port
|
||||
);
|
||||
|
||||
// Show stratum port modal.
|
||||
let port_modal = Modal::new(Self::STRATUM_PORT_MODAL,
|
||||
ModalLocation::SidePanel)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_port"));
|
||||
Navigator::open_modal(port_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show error when stratum server port is unavailable.
|
||||
if !self.stratum_port_available {
|
||||
ui.label(RichText::new(t!("network_mining.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw stratum port [`Modal`] content.
|
||||
pub fn stratum_port_modal_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.enter_value"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw stratum port text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
||||
.font(TextStyle::Button)
|
||||
.desired_width(48.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified port is unavailable.
|
||||
if !self.port_available_edit {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_mining.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
}
|
||||
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.save"), Colors::WHITE, || {
|
||||
// Check if port is available.
|
||||
let port_parse = self.stratum_port_edit.parse::<u16>();
|
||||
let is_available = port_parse.is_ok() && Network::is_port_available(
|
||||
self.stratum_address_edit.as_str(),
|
||||
port_parse.unwrap()
|
||||
);
|
||||
self.port_available_edit = is_available;
|
||||
|
||||
// Save port at config if it's available.
|
||||
if self.port_available_edit {
|
||||
NodeConfig::save_stratum_address_port(
|
||||
self.stratum_address_edit.clone(),
|
||||
self.stratum_port_edit.clone()
|
||||
);
|
||||
|
||||
self.stratum_port_available = true;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Show stratum IP address setup.
|
||||
fn ip_address_setup_ui(ui: &mut egui::Ui, addresses: Vec<IpAddr>) {
|
||||
let (addr, port) = NodeConfig::get_stratum_address_port();
|
||||
let saved_ip_addr = &IpAddr::from_str(addr.as_str()).unwrap();
|
||||
let mut selected_addr = saved_ip_addr;
|
||||
|
||||
// Set first IP address as current if saved is not present at system.
|
||||
if !addresses.contains(selected_addr) {
|
||||
selected_addr = addresses.get(0).unwrap();
|
||||
}
|
||||
|
||||
// Show available IP addresses on the system.
|
||||
let _ = addresses.chunks(2).map(|x| {
|
||||
if x.len() == 2 {
|
||||
ui.columns(2, |columns| {
|
||||
let addr0 = x.get(0).unwrap();
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr0,
|
||||
addr0.to_string());
|
||||
});
|
||||
let addr1 = x.get(1).unwrap();
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr1,
|
||||
addr1.to_string());
|
||||
})
|
||||
});
|
||||
} else {
|
||||
let addr = x.get(0).unwrap();
|
||||
View::radio_value(ui,
|
||||
&mut selected_addr,
|
||||
addr,
|
||||
addr.to_string());
|
||||
}
|
||||
ui.add_space(10.0);
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
// Save stratum server address at config if it was changed.
|
||||
if saved_ip_addr != selected_addr {
|
||||
NodeConfig::save_stratum_address_port(selected_addr.to_string(), port.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ impl View {
|
||||
|
||||
/// Draw [`Button`] with specified background fill color.
|
||||
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) {
|
||||
let br = Button::new(RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON))
|
||||
let br = Button::new(RichText::new(text.to_uppercase()).size(18.0).color(Colors::TEXT_BUTTON))
|
||||
.stroke(Self::DEFAULT_STROKE)
|
||||
.fill(fill_color)
|
||||
.ui(ui);
|
||||
@@ -207,7 +207,7 @@ impl View {
|
||||
/// Draw the button that looks like checkbox with callback on check.
|
||||
pub fn checkbox(ui: &mut egui::Ui, checked: bool, text: String, callback: impl FnOnce()) {
|
||||
let (text_value, color) = match checked {
|
||||
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::BUTTON) }
|
||||
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::TEXT_BUTTON) }
|
||||
false => { (format!("{} {}", SQUARE, text), Colors::TEXT) }
|
||||
};
|
||||
let br = Button::new(RichText::new(text_value).size(18.0).color(color))
|
||||
|
||||
Reference in New Issue
Block a user