mirror of
https://code.gri.mw/GUI/grim.git
synced 2026-07-14 02:38:55 +00:00
config + ui: add p2p config and ui, fix input fields size, update translations
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
use egui::{Id, RichText, TextStyle, Ui, Widget};
|
||||
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{CLOCK_COUNTDOWN, LINE_SEGMENTS, TIMER, WATCH};
|
||||
use crate::gui::icons::{CLOCK_COUNTDOWN, GRAPH, TIMER, WATCH};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalPosition, View};
|
||||
use crate::gui::views::network::settings::NetworkSettings;
|
||||
@@ -58,7 +58,7 @@ impl DandelionSetup {
|
||||
pub const STEM_PROBABILITY_MODAL: &'static str = "stem_probability";
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", LINE_SEGMENTS, "Dandelion"));
|
||||
View::sub_title(ui, format!("{} {}", GRAPH, "Dandelion"));
|
||||
View::horizontal_line(ui, Colors::STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
@@ -135,7 +135,7 @@ impl DandelionSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.epoch_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(46.0)
|
||||
.desired_width(52.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -220,7 +220,7 @@ impl DandelionSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.embargo_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(46.0)
|
||||
.desired_width(52.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -305,7 +305,7 @@ impl DandelionSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.aggregation_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(36.0)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -390,7 +390,7 @@ impl DandelionSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stem_prob_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(36.0)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
|
||||
@@ -35,13 +35,10 @@ pub struct NodeSetup {
|
||||
api_port_available_edit: bool,
|
||||
|
||||
/// Flag to check if API port from saved config value is available.
|
||||
pub(crate) is_api_port_available: bool,
|
||||
is_api_port_available: bool,
|
||||
|
||||
/// Rest API and v2 Owner API secret value.
|
||||
api_secret_edit: String,
|
||||
|
||||
/// Foreign API secret value.
|
||||
foreign_api_secret_edit: String,
|
||||
/// Secret edit value for modal.
|
||||
secret_edit: String,
|
||||
|
||||
/// Future Time Limit value.
|
||||
ftl_edit: String,
|
||||
@@ -56,8 +53,7 @@ impl Default for NodeSetup {
|
||||
api_port_edit: api_port,
|
||||
api_port_available_edit: is_api_port_available,
|
||||
is_api_port_available,
|
||||
api_secret_edit: "".to_string(),
|
||||
foreign_api_secret_edit: "".to_string(),
|
||||
secret_edit: "".to_string(),
|
||||
ftl_edit: NodeConfig::get_ftl(),
|
||||
}
|
||||
}
|
||||
@@ -253,7 +249,7 @@ impl NodeSetup {
|
||||
// Draw API port text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.api_port_edit)
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.0)
|
||||
.desired_width(64.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -335,14 +331,7 @@ impl NodeSetup {
|
||||
|
||||
View::button(ui, secret_text, Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
match modal_id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
self.api_secret_edit = secret_value.unwrap_or("".to_string());
|
||||
},
|
||||
_ => {
|
||||
self.foreign_api_secret_edit = secret_value.unwrap_or("".to_string());
|
||||
}
|
||||
}
|
||||
self.secret_edit = secret_value.unwrap_or("".to_string());
|
||||
// Show secret edit modal.
|
||||
let port_modal = Modal::new(modal_id)
|
||||
.position(ModalPosition::CenterTop)
|
||||
@@ -367,11 +356,7 @@ impl NodeSetup {
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw API port text edit.
|
||||
let edit_text = match modal.id {
|
||||
Self::API_SECRET_MODAL => &mut self.api_secret_edit,
|
||||
_ => &mut self.foreign_api_secret_edit
|
||||
};
|
||||
let text_edit_resp = egui::TextEdit::singleline(edit_text)
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.secret_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.cursor_at_end(true)
|
||||
@@ -396,25 +381,15 @@ impl NodeSetup {
|
||||
columns[0].with_layout(Layout::right_to_left(Align::Center), |ui| {
|
||||
let copy_title = format!("{} {}", COPY, t!("network_settings.copy"));
|
||||
View::button(ui, copy_title, Colors::WHITE, || {
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
cb.copy_string_to_buffer(self.api_secret_edit.clone());
|
||||
},
|
||||
_ => {
|
||||
cb.copy_string_to_buffer(self.foreign_api_secret_edit.clone());
|
||||
}
|
||||
};
|
||||
|
||||
cb.copy_string_to_buffer(self.secret_edit.clone());
|
||||
});
|
||||
});
|
||||
columns[1].with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
let paste_title = format!("{} {}", CLIPBOARD_TEXT, t!("network_settings.paste"));
|
||||
let paste_title = format!("{} {}",
|
||||
CLIPBOARD_TEXT,
|
||||
t!("network_settings.paste"));
|
||||
View::button(ui, paste_title, Colors::WHITE, || {
|
||||
let text = cb.get_string_from_buffer();
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => self.api_secret_edit = text,
|
||||
_ => self.foreign_api_secret_edit = text
|
||||
};
|
||||
self.secret_edit = cb.get_string_from_buffer();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -435,14 +410,13 @@ impl NodeSetup {
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
let secret = self.secret_edit.clone();
|
||||
match modal.id {
|
||||
Self::API_SECRET_MODAL => {
|
||||
let api_secret = &self.api_secret_edit.clone();
|
||||
NodeConfig::save_api_secret(api_secret);
|
||||
NodeConfig::save_api_secret(&secret);
|
||||
}
|
||||
_ => {
|
||||
let foreign_api_secret = &self.foreign_api_secret_edit.clone();
|
||||
NodeConfig::save_foreign_api_secret(foreign_api_secret);
|
||||
NodeConfig::save_foreign_api_secret(&secret);
|
||||
}
|
||||
};
|
||||
cb.hide_keyboard();
|
||||
@@ -504,7 +478,7 @@ impl NodeSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(46.0)
|
||||
.desired_width(52.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
|
||||
@@ -10,4 +10,892 @@
|
||||
// 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.
|
||||
// limitations under the License.
|
||||
|
||||
use std::fmt::format;
|
||||
use egui::{Direction, Id, Layout, RichText, Rounding, Stroke, TextStyle, Ui, Widget};
|
||||
use egui_extras::{Size, StripBuilder};
|
||||
use grin_core::global::ChainTypes;
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{HANDSHAKE, PLUG, TRASH, GLOBE_SIMPLE, PLUS_CIRCLE, ARROW_FAT_LINES_UP, ARROW_FAT_LINES_DOWN, ARROW_FAT_LINE_UP, PROHIBIT_INSET};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalPosition, View};
|
||||
use crate::gui::views::network::settings::NetworkSettings;
|
||||
use crate::node::{NodeConfig, PeersConfig};
|
||||
|
||||
/// Type of peer.
|
||||
#[derive(Eq, PartialEq)]
|
||||
enum PeerType {
|
||||
DefaultSeed,
|
||||
CustomSeed,
|
||||
Allowed,
|
||||
Denied,
|
||||
Preferred
|
||||
}
|
||||
|
||||
/// P2P server setup ui section.
|
||||
pub struct P2PSetup {
|
||||
/// P2P port value.
|
||||
port_edit: String,
|
||||
/// Flag to check if p2p port is available.
|
||||
port_available_edit: bool,
|
||||
|
||||
/// Flag to check if p2p port from saved config value is available.
|
||||
is_port_available: bool,
|
||||
|
||||
/// Flag to check if entered peer address is correct and/or available.
|
||||
is_correct_address_edit: bool,
|
||||
|
||||
/// Peer edit value for modal.
|
||||
peer_edit: String,
|
||||
/// Default main network seeds.
|
||||
default_main_seeds: Vec<String>,
|
||||
/// Default test network seeds.
|
||||
default_test_seeds: Vec<String>,
|
||||
|
||||
/// How long banned peer should stay banned.
|
||||
ban_window_edit: String,
|
||||
|
||||
/// Maximum number of inbound peer connections.
|
||||
max_inbound_count: String,
|
||||
|
||||
/// Maximum number of outbound peer connections.
|
||||
max_outbound_count: String,
|
||||
|
||||
/// Preferred minimum number of outbound peers.
|
||||
min_outbound_count: String
|
||||
}
|
||||
|
||||
impl Default for P2PSetup {
|
||||
fn default() -> Self {
|
||||
let port = NodeConfig::get_p2p_port();
|
||||
let is_port_available = NodeConfig::is_p2p_port_available(&port);
|
||||
let default_main_seeds = grin_servers::MAINNET_DNS_SEEDS
|
||||
.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
let default_test_seeds = grin_servers::TESTNET_DNS_SEEDS
|
||||
.into_iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
Self {
|
||||
port_edit: port,
|
||||
port_available_edit: is_port_available,
|
||||
is_correct_address_edit: true,
|
||||
is_port_available,
|
||||
peer_edit: "".to_string(),
|
||||
default_main_seeds,
|
||||
default_test_seeds,
|
||||
ban_window_edit: NodeConfig::get_p2p_ban_window(),
|
||||
max_inbound_count: NodeConfig::get_max_inbound_peers(),
|
||||
max_outbound_count: NodeConfig::get_max_outbound_peers(),
|
||||
min_outbound_count: NodeConfig::get_min_outbound_peers(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl P2PSetup {
|
||||
/// Identifier for port value [`Modal`].
|
||||
pub const PORT_MODAL: &'static str = "p2p_port";
|
||||
/// Identifier for custom seed [`Modal`].
|
||||
pub const CUSTOM_SEED_MODAL: &'static str = "p2p_custom_seed";
|
||||
/// Identifier for allowed peer [`Modal`].
|
||||
pub const ALLOW_PEER_MODAL: &'static str = "p2p_allow_peer";
|
||||
/// Identifier for denied peer [`Modal`].
|
||||
pub const DENY_PEER_MODAL: &'static str = "p2p_deny_peer";
|
||||
/// Identifier for preferred peer [`Modal`].
|
||||
pub const PREFER_PEER_MODAL: &'static str = "p2p_prefer_peer";
|
||||
/// Identifier for ban window [`Modal`].
|
||||
pub const BAN_WINDOW_MODAL: &'static str = "p2p_ban_window";
|
||||
/// Identifier for maximum number of inbound peers [`Modal`].
|
||||
pub const MAX_INBOUND_MODAL: &'static str = "p2p_max_inbound";
|
||||
/// Identifier for maximum number of outbound peers [`Modal`].
|
||||
pub const MAX_OUTBOUND_MODAL: &'static str = "p2p_max_outbound";
|
||||
/// Identifier for minimum number of outbound peers [`Modal`].
|
||||
pub const MIN_OUTBOUND_MODAL: &'static str = "p2p_min_outbound";
|
||||
|
||||
/// Title for custom DNS Seeds setup section.
|
||||
const DNS_SEEDS_TITLE: &'static str = "DNS Seeds";
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_settings.p2p_server")));
|
||||
View::horizontal_line(ui, Colors::STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.vertical_centered(|ui| {
|
||||
// Show p2p port setup.
|
||||
self.port_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show seeding type setup.
|
||||
self.seeding_type_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.allow_list"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(6.0);
|
||||
// Show allowed peers setup.
|
||||
self.peer_list_ui(ui, &PeerType::Allowed, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.deny_list"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(6.0);
|
||||
// Show denied peers setup.
|
||||
self.peer_list_ui(ui, &PeerType::Denied, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
ui.label(RichText::new(t!("network_settings.favourites"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(6.0);
|
||||
// Show preferred peers setup.
|
||||
self.peer_list_ui(ui, &PeerType::Preferred, cb);
|
||||
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show ban window setup.
|
||||
self.ban_window_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show maximum inbound peers value setup.
|
||||
self.max_inbound_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show maximum outbound peers value setup.
|
||||
self.max_outbound_ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show minimum outbound peers value setup.
|
||||
self.min_outbound_ui(ui, cb);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw p2p port setup content.
|
||||
fn port_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
ui.label(RichText::new(t!("network_settings.p2p_port"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
let port = NodeConfig::get_p2p_port();
|
||||
View::button(ui, format!("{} {}", PLUG, port.clone()), Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.port_edit = port;
|
||||
self.port_available_edit = self.is_port_available;
|
||||
// Show p2p port modal.
|
||||
let port_modal = Modal::new(Self::PORT_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_value"));
|
||||
Navigator::show_modal(port_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show error when stratum server port is unavailable.
|
||||
if !self.is_port_available {
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(t!("network_settings.port_unavailable"))
|
||||
.size(16.0)
|
||||
.color(Colors::RED));
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw p2p port [`Modal`] content.
|
||||
pub fn port_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.p2p_port"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw p2p port text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.port_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.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_settings.port_unavailable"))
|
||||
.size(18.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(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
// Check if port is available.
|
||||
let available = NodeConfig::is_p2p_port_available(&self.port_edit);
|
||||
self.port_available_edit = available;
|
||||
|
||||
// Save port at config if it's available.
|
||||
if available {
|
||||
NodeConfig::save_p2p_port(self.port_edit.parse::<u16>().unwrap());
|
||||
|
||||
self.is_port_available = true;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw peer list content based on provided [`PeerType`].
|
||||
fn peer_list_ui(&mut self, ui: &mut Ui, peer_type: &PeerType, cb: &dyn PlatformCallbacks) {
|
||||
let peer_list = match peer_type {
|
||||
PeerType::DefaultSeed => {
|
||||
if AppConfig::chain_type() == ChainTypes::Testnet {
|
||||
self.default_test_seeds.clone()
|
||||
} else {
|
||||
self.default_main_seeds.clone()
|
||||
}
|
||||
}
|
||||
PeerType::CustomSeed => NodeConfig::get_custom_seeds(),
|
||||
PeerType::Allowed => NodeConfig::get_allowed_peers(),
|
||||
PeerType::Denied => NodeConfig::get_denied_peers(),
|
||||
PeerType::Preferred => NodeConfig::get_preferred_peers()
|
||||
};
|
||||
for (index, peer) in peer_list.iter().enumerate() {
|
||||
let rounding = if peer_list.len() == 1 {
|
||||
[true, true]
|
||||
} else if index == 0 {
|
||||
[true, false]
|
||||
} else if index == peer_list.len() - 1 {
|
||||
[false, true]
|
||||
} else {
|
||||
[false, false]
|
||||
};
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
// Draw peer list item.
|
||||
Self::peer_item_ui(ui, peer, peer_type, rounding);
|
||||
});
|
||||
}
|
||||
|
||||
if peer_type != &PeerType::DefaultSeed {
|
||||
// Draw description.
|
||||
if peer_type != &PeerType::CustomSeed {
|
||||
if !peer_list.is_empty() {
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
let desc = match peer_type {
|
||||
PeerType::Allowed => t!("network_settings.allow_list_desc"),
|
||||
PeerType::Denied => t!("network_settings.deny_list_desc"),
|
||||
&_ => t!("network_settings.favourites_desc"),
|
||||
};
|
||||
ui.label(RichText::new(desc)
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT));
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
|
||||
let add_text = if peer_type == &PeerType::CustomSeed {
|
||||
format!("{} {}", PLUS_CIRCLE, t!("network_settings.add_seed"))
|
||||
} else {
|
||||
format!("{} {}", PLUS_CIRCLE, t!("network_settings.add_peer"))
|
||||
|
||||
};
|
||||
View::button(ui, add_text, Colors::GOLD, || {
|
||||
// Setup values for modal.
|
||||
self.peer_edit = "".to_string();
|
||||
// Select modal id.
|
||||
let modal_id = match peer_type {
|
||||
PeerType::Allowed => Self::ALLOW_PEER_MODAL,
|
||||
PeerType::Denied => Self::DENY_PEER_MODAL,
|
||||
PeerType::Preferred => Self::PREFER_PEER_MODAL,
|
||||
_ => Self::CUSTOM_SEED_MODAL
|
||||
};
|
||||
// Select modal title.
|
||||
let modal_title = match peer_type {
|
||||
PeerType::Allowed => t!("network_settings.allow_list"),
|
||||
PeerType::Denied => t!("network_settings.deny_list"),
|
||||
PeerType::Preferred => t!("network_settings.favourites"),
|
||||
_ => Self::DNS_SEEDS_TITLE.to_string()
|
||||
};
|
||||
// Show modal to add peer.
|
||||
let peer_modal = Modal::new(modal_id)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(modal_title);
|
||||
Navigator::show_modal(peer_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
|
||||
/// Draw peer creation [`Modal`] content.
|
||||
pub fn peer_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
let label_text = match modal.id {
|
||||
Self::CUSTOM_SEED_MODAL => t!("network_settings.add_seed"),
|
||||
&_ => t!("network_settings.add_peer")
|
||||
};
|
||||
ui.label(RichText::new(label_text).size(18.0).color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw peer address text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.peer_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(ui.available_width())
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified address is incorrect.
|
||||
if !self.is_correct_address_edit {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.peer_address_error"))
|
||||
.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(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
// Check if peer is correct and/or available.
|
||||
let peer = self.peer_edit.clone();
|
||||
let is_correct_address = PeersConfig::peer_to_addr(peer.clone()).is_some();
|
||||
self.is_correct_address_edit = is_correct_address;
|
||||
|
||||
// Save peer at config.
|
||||
if is_correct_address {
|
||||
match modal.id {
|
||||
Self::CUSTOM_SEED_MODAL => NodeConfig::save_custom_seed(peer),
|
||||
Self::ALLOW_PEER_MODAL => NodeConfig::allow_peer(peer),
|
||||
Self::DENY_PEER_MODAL => NodeConfig::deny_peer(peer),
|
||||
Self::PREFER_PEER_MODAL => NodeConfig::prefer_peer(peer),
|
||||
&_ => {}
|
||||
}
|
||||
|
||||
self.is_port_available = true;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw peer list item.
|
||||
fn peer_item_ui(ui: &mut Ui, peer_addr: &String, peer_type: &PeerType, rounding: [bool; 2]) {
|
||||
// Draw round background.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.min += egui::emath::vec2(6.0, 0.0);
|
||||
rect.set_height(42.0);
|
||||
ui.painter().rect(
|
||||
rect,
|
||||
Rounding {
|
||||
nw: if rounding[0] { 6.0 } else { 0.0 },
|
||||
ne: if rounding[0] { 6.0 } else { 0.0 },
|
||||
sw: if rounding[1] { 6.0 } else { 0.0 },
|
||||
se: if rounding[1] { 6.0 } else { 0.0 },
|
||||
},
|
||||
Colors::WHITE,
|
||||
Stroke { width: 1.0, color: Colors::ITEM_STROKE }
|
||||
);
|
||||
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(42.0))
|
||||
.vertical(|mut strip| {
|
||||
strip.strip(|builder| {
|
||||
builder
|
||||
.size(Size::exact(13.0))
|
||||
.size(Size::remainder())
|
||||
.size(Size::exact(46.0))
|
||||
.horizontal(|mut strip| {
|
||||
strip.empty();
|
||||
strip.cell(|ui| {
|
||||
ui.horizontal_centered(|ui| {
|
||||
// Draw peer address.
|
||||
let peer_text = format!("{} {}", GLOBE_SIMPLE, &peer_addr);
|
||||
ui.label(RichText::new(peer_text)
|
||||
.color(Colors::TEXT_BUTTON)
|
||||
.size(17.0));
|
||||
});
|
||||
});
|
||||
if peer_type != &PeerType::DefaultSeed {
|
||||
strip.cell(|ui| {
|
||||
// Draw delete button for non-default seed peers.
|
||||
View::button(ui, TRASH.to_string(), Colors::BUTTON, || {
|
||||
match peer_type {
|
||||
PeerType::CustomSeed => {
|
||||
NodeConfig::remove_custom_seed(peer_addr);
|
||||
}
|
||||
PeerType::Allowed => {
|
||||
NodeConfig::remove_allowed_peer(peer_addr);
|
||||
}
|
||||
PeerType::Denied => {
|
||||
NodeConfig::remove_denied_peer(peer_addr);
|
||||
}
|
||||
PeerType::Preferred => {
|
||||
NodeConfig::remove_preferred_peer(peer_addr);
|
||||
}
|
||||
PeerType::DefaultSeed => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
strip.empty();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw seeding type setup content.
|
||||
fn seeding_type_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
let title = Self::DNS_SEEDS_TITLE;
|
||||
ui.label(RichText::new(title).size(16.0).color(Colors::GRAY));
|
||||
ui.add_space(2.0);
|
||||
|
||||
let default_seeding = NodeConfig::is_default_seeding_type();
|
||||
View::checkbox(ui, default_seeding, t!("network_settings.default"), || {
|
||||
NodeConfig::toggle_seeding_type();
|
||||
});
|
||||
ui.add_space(8.0);
|
||||
|
||||
let peers_type = if default_seeding {
|
||||
PeerType::DefaultSeed
|
||||
} else {
|
||||
PeerType::CustomSeed
|
||||
};
|
||||
self.peer_list_ui(ui, &peers_type, cb);
|
||||
}
|
||||
|
||||
/// Draw ban window setup content.
|
||||
fn ban_window_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
ui.label(RichText::new(t!("network_settings.ban_window"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
let ban_window = NodeConfig::get_p2p_ban_window();
|
||||
View::button(ui, format!("{} {}", PROHIBIT_INSET, ban_window.clone()), Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.ban_window_edit = ban_window;
|
||||
// Show ban window period setup modal.
|
||||
let ban_modal = Modal::new(Self::BAN_WINDOW_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_value"));
|
||||
Navigator::show_modal(ban_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(t!("network_settings.ban_window_desc"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
|
||||
/// Draw ban window [`Modal`] content.
|
||||
pub fn ban_window_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.ban_window"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw ban window text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ban_window_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(84.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||
if self.ban_window_edit.parse::<i64>().is_err() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||
.size(18.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
if let Ok(ban_window) = self.ban_window_edit.parse::<i64>() {
|
||||
NodeConfig::save_p2p_ban_window(ban_window);
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw maximum number of inbound peers setup content.
|
||||
fn max_inbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
ui.label(RichText::new(t!("network_settings.max_inbound_count"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
let max_inbound = NodeConfig::get_max_inbound_peers();
|
||||
let button_text = format!("{} {}", ARROW_FAT_LINES_DOWN, max_inbound.clone());
|
||||
View::button(ui, button_text, Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.max_inbound_count = max_inbound;
|
||||
// Show maximum number of inbound peers setup modal.
|
||||
let max_inbound_modal = Modal::new(Self::MAX_INBOUND_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_value"));
|
||||
Navigator::show_modal(max_inbound_modal);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
|
||||
/// Draw maximum number of inbound peers [`Modal`] content.
|
||||
pub fn max_inbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.max_inbound_count"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw maximum number of inbound peers text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_inbound_count)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||
if self.max_inbound_count.parse::<u32>().is_err() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||
.size(18.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
if let Ok(max_inbound) = self.max_inbound_count.parse::<u32>() {
|
||||
NodeConfig::save_max_inbound_peers(max_inbound);
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw maximum number of outbound peers setup content.
|
||||
fn max_outbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
ui.label(RichText::new(t!("network_settings.max_outbound_count"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
let max_outbound = NodeConfig::get_max_outbound_peers();
|
||||
let button_text = format!("{} {}", ARROW_FAT_LINES_UP, max_outbound.clone());
|
||||
View::button(ui, button_text, Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.max_outbound_count = max_outbound;
|
||||
// Show maximum number of outbound peers setup modal.
|
||||
let max_outbound = Modal::new(Self::MAX_OUTBOUND_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_value"));
|
||||
Navigator::show_modal(max_outbound);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
|
||||
/// Draw maximum number of outbound peers [`Modal`] content.
|
||||
pub fn max_outbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.max_outbound_count"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw maximum number of outbound peers text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_outbound_count)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||
if self.max_outbound_count.parse::<u32>().is_err() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||
.size(18.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
if let Ok(max_outbound) = self.max_outbound_count.parse::<u32>() {
|
||||
NodeConfig::save_max_outbound_peers(max_outbound);
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
|
||||
/// Draw minimum number of outbound peers setup content.
|
||||
fn min_outbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||
ui.label(RichText::new(t!("network_settings.min_outbound_count"))
|
||||
.size(16.0)
|
||||
.color(Colors::GRAY)
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
|
||||
let min_outbound = NodeConfig::get_min_outbound_peers();
|
||||
let button_text = format!("{} {}", ARROW_FAT_LINE_UP, min_outbound.clone());
|
||||
View::button(ui, button_text, Colors::BUTTON, || {
|
||||
// Setup values for modal.
|
||||
self.min_outbound_count = min_outbound;
|
||||
// Show maximum number of outbound peers setup modal.
|
||||
let min_outbound = Modal::new(Self::MIN_OUTBOUND_MODAL)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("network_settings.change_value"));
|
||||
Navigator::show_modal(min_outbound);
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.label(RichText::new(t!("network_settings.min_outbound_desc"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(2.0);
|
||||
}
|
||||
|
||||
/// Draw minimum number of outbound peers [`Modal`] content.
|
||||
pub fn min_outbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("network_settings.min_outbound_count"))
|
||||
.size(18.0)
|
||||
.color(Colors::GRAY));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw maximum number of outbound peers text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_outbound_count)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||
if self.min_outbound_count.parse::<u32>().is_err() {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||
.size(18.0)
|
||||
.color(Colors::RED));
|
||||
} else {
|
||||
NetworkSettings::node_restart_required_ui(ui);
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
// Save button callback.
|
||||
let on_save = || {
|
||||
if let Ok(max_outbound) = self.min_outbound_count.parse::<u32>() {
|
||||
NodeConfig::save_min_outbound_peers(max_outbound);
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
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, on_save);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ impl PoolSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.fee_base_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(70.0)
|
||||
.desired_width(76.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -222,7 +222,7 @@ impl PoolSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.reorg_period_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(36.0)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -307,7 +307,7 @@ impl PoolSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.pool_size_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.0)
|
||||
.desired_width(64.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -392,7 +392,7 @@ impl PoolSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stempool_size_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.0)
|
||||
.desired_width(64.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -477,7 +477,7 @@ impl PoolSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_weight_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.0)
|
||||
.desired_width(64.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
|
||||
@@ -32,7 +32,7 @@ pub struct StratumSetup {
|
||||
stratum_port_available_edit: bool,
|
||||
|
||||
/// Flag to check if stratum port from saved config value is available.
|
||||
pub(crate) is_port_available: bool,
|
||||
is_port_available: bool,
|
||||
|
||||
/// Attempt time value in seconds to mine on a particular header.
|
||||
attempt_time_edit: String,
|
||||
@@ -192,7 +192,7 @@ impl StratumSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(58.0)
|
||||
.desired_width(64.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -288,7 +288,7 @@ impl StratumSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(36.0)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
@@ -374,7 +374,7 @@ impl StratumSetup {
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit)
|
||||
.id(Id::from(modal.id))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(36.0)
|
||||
.desired_width(42.0)
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
|
||||
@@ -21,11 +21,12 @@ use grin_chain::SyncStatus;
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, ModalContainer, TitlePanel, View};
|
||||
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
||||
use crate::gui::views::network::configs::node::NodeSetup;
|
||||
use crate::gui::views::network::configs::p2p::P2PSetup;
|
||||
use crate::gui::views::network::configs::pool::PoolSetup;
|
||||
use crate::gui::views::network::configs::stratum::StratumSetup;
|
||||
use crate::gui::views::network::metrics::NetworkMetrics;
|
||||
@@ -77,6 +78,16 @@ impl Default for NetworkContainer {
|
||||
NodeSetup::API_SECRET_MODAL,
|
||||
NodeSetup::FOREIGN_API_SECRET_MODAL,
|
||||
NodeSetup::FTL_MODAL,
|
||||
// P2P setup modals.
|
||||
P2PSetup::PORT_MODAL,
|
||||
P2PSetup::CUSTOM_SEED_MODAL,
|
||||
P2PSetup::ALLOW_PEER_MODAL,
|
||||
P2PSetup::DENY_PEER_MODAL,
|
||||
P2PSetup::PREFER_PEER_MODAL,
|
||||
P2PSetup::BAN_WINDOW_MODAL,
|
||||
P2PSetup::MAX_INBOUND_MODAL,
|
||||
P2PSetup::MAX_OUTBOUND_MODAL,
|
||||
P2PSetup::MIN_OUTBOUND_MODAL,
|
||||
// Stratum setup modals.
|
||||
StratumSetup::STRATUM_PORT_MODAL,
|
||||
StratumSetup::ATTEMPT_TIME_MODAL,
|
||||
@@ -114,6 +125,7 @@ impl NetworkContainer {
|
||||
}
|
||||
|
||||
egui::TopBottomPanel::top("network_title")
|
||||
.exact_height(TitlePanel::DEFAULT_HEIGHT)
|
||||
.resizable(false)
|
||||
.frame(egui::Frame {
|
||||
fill: Colors::YELLOW,
|
||||
@@ -187,34 +199,28 @@ impl NetworkContainer {
|
||||
/// Draw title content.
|
||||
fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(TitlePanel::DEFAULT_HEIGHT))
|
||||
.vertical(|mut strip| {
|
||||
.size(Size::exact(52.0))
|
||||
.size(Size::remainder())
|
||||
.size(Size::exact(52.0))
|
||||
.horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::title_button(ui, DOTS_THREE_OUTLINE_VERTICAL, || {
|
||||
//TODO: Show connections
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.strip(|builder| {
|
||||
builder
|
||||
.size(Size::exact(52.0))
|
||||
.size(Size::remainder())
|
||||
.size(Size::exact(52.0))
|
||||
.horizontal(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::title_button(ui, DOTS_THREE_OUTLINE_VERTICAL, || {
|
||||
//TODO: Actions for node
|
||||
});
|
||||
});
|
||||
});
|
||||
strip.strip(|builder| {
|
||||
self.title_text_ui(builder);
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
if !View::is_dual_panel_mode(frame) {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::title_button(ui, CARDHOLDER, || {
|
||||
Navigator::toggle_side_panel();
|
||||
});
|
||||
});
|
||||
}
|
||||
self.title_text_ui(builder);
|
||||
});
|
||||
strip.cell(|ui| {
|
||||
if !View::is_dual_panel_mode(frame) {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::title_button(ui, CARDHOLDER, || {
|
||||
Navigator::toggle_side_panel();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -249,14 +255,14 @@ impl NetworkContainer {
|
||||
bright as f32
|
||||
};
|
||||
|
||||
// Draw sync text
|
||||
// Draw sync status text.
|
||||
let status_color_rgba = Rgba::from(Colors::TEXT) * color_factor;
|
||||
let status_color = Color32::from(status_color_rgba);
|
||||
View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color);
|
||||
|
||||
// Repaint based on sync status
|
||||
// Repaint delay based on sync status.
|
||||
if idle {
|
||||
ui.ctx().request_repaint_after(Duration::from_millis(250));
|
||||
ui.ctx().request_repaint_after(Node::STATS_UPDATE_DELAY);
|
||||
} else {
|
||||
ui.ctx().request_repaint();
|
||||
}
|
||||
@@ -274,7 +280,7 @@ impl NetworkContainer {
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
ui.add_space(10.0);
|
||||
View::button(ui, t!("network.enable_node"), Colors::GOLD, || {
|
||||
View::button(ui, format!("{} {}", POWER, t!("network.enable_node")), Colors::GOLD, || {
|
||||
Node::start();
|
||||
});
|
||||
ui.add_space(2.0);
|
||||
|
||||
@@ -164,8 +164,7 @@ impl NetworkTab for NetworkNode {
|
||||
// Show peer stats when available.
|
||||
if stats.peer_count > 0 {
|
||||
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
|
||||
for index in 0..stats.peer_stats.len() {
|
||||
let ps = stats.peer_stats.get(index).unwrap();
|
||||
for (index, ps) in stats.peer_stats.iter().enumerate() {
|
||||
let rounding = if stats.peer_count == 1 {
|
||||
[true, true]
|
||||
} else if index == 0 {
|
||||
@@ -188,9 +187,9 @@ impl NetworkTab for NetworkNode {
|
||||
|
||||
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||
ui.vertical(|ui| {
|
||||
// Draw round background.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(78.3);
|
||||
|
||||
ui.painter().rect(
|
||||
rect,
|
||||
Rounding {
|
||||
@@ -204,39 +203,29 @@ fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||
);
|
||||
|
||||
ui.add_space(2.0);
|
||||
|
||||
// Draw peer address
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(5.0);
|
||||
// Draw peer address
|
||||
ui.heading(RichText::new(format!("{} {}", PLUGS_CONNECTED, &peer.addr))
|
||||
.color(Colors::BLACK)
|
||||
.size(18.0));
|
||||
let addr_text = format!("{} {}", PLUGS_CONNECTED, &peer.addr);
|
||||
ui.label(RichText::new(addr_text).color(Colors::BLACK).size(18.0));
|
||||
});
|
||||
// Draw peer difficulty and height
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(6.0);
|
||||
// Draw peer difficulty and height
|
||||
ui.heading(RichText::new(format!("{} {}", PACKAGE, peer.total_difficulty))
|
||||
.color(Colors::TITLE)
|
||||
.size(16.0));
|
||||
let diff_text = format!("{} {}", PACKAGE, peer.total_difficulty);
|
||||
ui.label(RichText::new(diff_text).color(Colors::TITLE).size(16.0));
|
||||
ui.add_space(2.0);
|
||||
ui.heading(RichText::new(AT).color(Colors::TITLE).size(16.0));
|
||||
ui.label(RichText::new(AT).color(Colors::TITLE).size(16.0));
|
||||
ui.add_space(2.0);
|
||||
ui.heading(RichText::new(peer.height.to_string())
|
||||
.color(Colors::TITLE)
|
||||
.size(16.0));
|
||||
ui.label(RichText::new(peer.height.to_string()).color(Colors::TITLE).size(16.0));
|
||||
});
|
||||
|
||||
// Draw peer user-agent
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(6.0);
|
||||
// Draw peer user-agent
|
||||
ui.heading(RichText::new(format!("{} {}", DEVICES, &peer.user_agent))
|
||||
.color(Colors::GRAY)
|
||||
.size(16.0));
|
||||
let agent_text = format!("{} {}", DEVICES, &peer.user_agent);
|
||||
ui.label(RichText::new(agent_text).color(Colors::GRAY).size(16.0));
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
});
|
||||
|
||||
// Add space after last item
|
||||
// if rounding[1] {
|
||||
// ui.add_space(2.0);
|
||||
// }
|
||||
}
|
||||
@@ -21,13 +21,16 @@ use crate::gui::views::{Modal, ModalPosition, View};
|
||||
use crate::gui::views::network::{NetworkTab, NetworkTabType};
|
||||
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
||||
use crate::gui::views::network::configs::node::NodeSetup;
|
||||
use crate::gui::views::network::configs::p2p::P2PSetup;
|
||||
use crate::gui::views::network::configs::pool::PoolSetup;
|
||||
use crate::gui::views::network::configs::stratum::StratumSetup;
|
||||
use crate::node::{Node, NodeConfig};
|
||||
|
||||
/// Integrated node settings tab content.
|
||||
#[derive(Default)]
|
||||
pub struct NetworkSettings {
|
||||
node: NodeSetup,
|
||||
p2p: P2PSetup,
|
||||
stratum: StratumSetup,
|
||||
pool: PoolSetup,
|
||||
dandelion: DandelionSetup
|
||||
@@ -49,6 +52,12 @@ impl NetworkTab for NetworkSettings {
|
||||
View::horizontal_line(ui, Colors::STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
self.p2p.ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
View::horizontal_line(ui, Colors::STROKE);
|
||||
ui.add_space(4.0);
|
||||
|
||||
self.stratum.ui(ui, cb);
|
||||
|
||||
ui.add_space(6.0);
|
||||
@@ -81,6 +90,16 @@ impl NetworkTab for NetworkSettings {
|
||||
NodeSetup::API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
||||
NodeSetup::FOREIGN_API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
||||
NodeSetup::FTL_MODAL => self.node.ftl_modal(ui, modal, cb),
|
||||
// P2P setup modals.
|
||||
P2PSetup::PORT_MODAL => self.p2p.port_modal(ui, modal, cb),
|
||||
P2PSetup::CUSTOM_SEED_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||
P2PSetup::ALLOW_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||
P2PSetup::DENY_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||
P2PSetup::PREFER_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||
P2PSetup::BAN_WINDOW_MODAL => self.p2p.ban_window_modal(ui, modal, cb),
|
||||
P2PSetup::MAX_INBOUND_MODAL => self.p2p.max_inbound_modal(ui, modal, cb),
|
||||
P2PSetup::MAX_OUTBOUND_MODAL => self.p2p.max_outbound_modal(ui, modal, cb),
|
||||
P2PSetup::MIN_OUTBOUND_MODAL => self.p2p.min_outbound_modal(ui, modal, cb),
|
||||
// Stratum server setup modals.
|
||||
StratumSetup::STRATUM_PORT_MODAL => self.stratum.port_modal(ui, modal, cb),
|
||||
StratumSetup::ATTEMPT_TIME_MODAL => self.stratum.attempt_modal(ui, modal, cb),
|
||||
|
||||
Reference in New Issue
Block a user