2023-07-03 21:17:49 +03:00
|
|
|
// 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.
|
|
|
|
|
2023-08-11 01:02:08 +03:00
|
|
|
use egui::{RichText, ScrollArea, Stroke};
|
2023-07-03 21:17:49 +03:00
|
|
|
use egui::style::Margin;
|
|
|
|
|
|
|
|
use crate::AppConfig;
|
2023-07-13 03:54:27 +03:00
|
|
|
use crate::gui::Colors;
|
2023-08-05 22:39:42 +03:00
|
|
|
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, PLUS_CIRCLE, POWER};
|
2023-07-03 21:17:49 +03:00
|
|
|
use crate::gui::platform::PlatformCallbacks;
|
2023-08-05 22:39:42 +03:00
|
|
|
use crate::gui::views::{ConnectionsContent, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitlePanel, View};
|
2023-08-03 04:11:25 +03:00
|
|
|
use crate::gui::views::network::types::{NetworkTab, NetworkTabType};
|
|
|
|
use crate::gui::views::types::TitleType;
|
2023-07-03 21:17:49 +03:00
|
|
|
use crate::node::Node;
|
2023-08-09 02:22:16 +03:00
|
|
|
use crate::wallet::ExternalConnection;
|
2023-07-03 21:17:49 +03:00
|
|
|
|
2023-07-14 00:55:31 +03:00
|
|
|
/// Network content.
|
2023-07-31 16:23:15 +03:00
|
|
|
pub struct NetworkContent {
|
2023-08-11 01:02:08 +03:00
|
|
|
/// Current integrated node tab content.
|
|
|
|
node_tab_content: Box<dyn NetworkTab>,
|
2023-08-05 22:39:42 +03:00
|
|
|
/// Connections content.
|
|
|
|
connections: ConnectionsContent
|
2023-07-03 21:17:49 +03:00
|
|
|
}
|
|
|
|
|
2023-07-31 16:23:15 +03:00
|
|
|
impl Default for NetworkContent {
|
2023-07-03 21:17:49 +03:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2023-08-11 01:02:08 +03:00
|
|
|
node_tab_content: Box::new(NetworkNode::default()),
|
2023-08-05 22:39:42 +03:00
|
|
|
connections: ConnectionsContent::default(),
|
2023-07-03 21:17:49 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-31 16:23:15 +03:00
|
|
|
impl NetworkContent {
|
2023-07-03 21:17:49 +03:00
|
|
|
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
|
2023-08-05 22:39:42 +03:00
|
|
|
// Flag to show connections or integrated node content.
|
|
|
|
let show_connections = AppConfig::show_connections_network_panel();
|
|
|
|
|
2023-07-21 04:17:57 +03:00
|
|
|
// Show title panel.
|
2023-08-05 22:39:42 +03:00
|
|
|
self.title_ui(ui, frame, show_connections, cb);
|
2023-07-03 21:17:49 +03:00
|
|
|
|
2023-08-11 01:02:08 +03:00
|
|
|
// Show integrated node tabs content.
|
|
|
|
egui::TopBottomPanel::bottom("node_tabs_panel")
|
|
|
|
.resizable(false)
|
2023-07-03 21:17:49 +03:00
|
|
|
.frame(egui::Frame {
|
2023-08-11 01:02:08 +03:00
|
|
|
fill: Colors::FILL,
|
2023-08-03 10:47:16 +03:00
|
|
|
inner_margin: Margin {
|
|
|
|
left: View::get_left_inset() + 4.0,
|
|
|
|
right: View::far_right_inset_margin(ui, frame) + 4.0,
|
2023-08-11 01:02:08 +03:00
|
|
|
top: 4.0,
|
|
|
|
bottom: View::get_bottom_inset() + 4.0,
|
2023-08-05 22:39:42 +03:00
|
|
|
},
|
2023-08-11 01:02:08 +03:00
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.show_animated_inside(ui, !show_connections, |ui| {
|
|
|
|
self.tabs_ui(ui);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Show current node tab content.
|
|
|
|
egui::SidePanel::right("node_tab_content_panel")
|
|
|
|
.resizable(false)
|
|
|
|
.exact_width(ui.available_width())
|
|
|
|
.frame(egui::Frame {
|
|
|
|
stroke: View::DEFAULT_STROKE,
|
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.show_animated_inside(ui, !show_connections, |ui| {
|
|
|
|
egui::CentralPanel::default()
|
|
|
|
.frame(egui::Frame {
|
|
|
|
fill: Colors::WHITE,
|
|
|
|
stroke: View::DEFAULT_STROKE,
|
|
|
|
inner_margin: Margin {
|
|
|
|
left: View::get_left_inset() + 4.0,
|
|
|
|
right: View::far_right_inset_margin(ui, frame) + 4.0,
|
|
|
|
top: 3.0,
|
|
|
|
bottom: 4.0,
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.show_inside(ui, |ui| {
|
|
|
|
self.node_tab_content.ui(ui, frame, cb);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
let content_width = ui.available_width();
|
|
|
|
|
|
|
|
// Show connections content.
|
|
|
|
egui::CentralPanel::default()
|
|
|
|
.frame(egui::Frame {
|
|
|
|
stroke: if show_connections{
|
|
|
|
View::DEFAULT_STROKE
|
2023-08-05 22:39:42 +03:00
|
|
|
} else {
|
2023-08-11 01:02:08 +03:00
|
|
|
Stroke::NONE
|
2023-08-03 10:47:16 +03:00
|
|
|
},
|
2023-08-11 01:02:08 +03:00
|
|
|
inner_margin: Margin {
|
|
|
|
left: if show_connections {
|
|
|
|
View::get_left_inset() + 4.0
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
},
|
|
|
|
right: if show_connections {
|
|
|
|
View::far_right_inset_margin(ui, frame) + 4.0
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
},
|
|
|
|
top: 3.0,
|
|
|
|
bottom: View::get_bottom_inset() + 4.0,
|
|
|
|
},
|
|
|
|
fill: Colors::BUTTON,
|
2023-07-03 21:17:49 +03:00
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.show_inside(ui, |ui| {
|
2023-08-11 01:02:08 +03:00
|
|
|
if !show_connections {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ScrollArea::vertical()
|
|
|
|
.id_source("connections_content")
|
|
|
|
.auto_shrink([false; 2])
|
|
|
|
.show(ui, |ui| {
|
|
|
|
ui.add_space(1.0);
|
|
|
|
ui.vertical_centered(|ui| {
|
|
|
|
// Setup wallet list width.
|
|
|
|
let mut rect = ui.available_rect_before_wrap();
|
|
|
|
let mut width = ui.available_width();
|
|
|
|
if !Root::is_dual_panel_mode(frame) {
|
|
|
|
width = f32::min(width, Root::SIDE_PANEL_WIDTH * 1.3)
|
|
|
|
}
|
|
|
|
rect.set_width(width);
|
|
|
|
|
|
|
|
ui.allocate_ui(rect.size(), |ui| {
|
|
|
|
self.connections.ui(ui, frame, cb);
|
2023-08-05 22:39:42 +03:00
|
|
|
});
|
|
|
|
});
|
2023-08-11 01:02:08 +03:00
|
|
|
});
|
2023-07-03 21:17:49 +03:00
|
|
|
});
|
2023-07-14 03:51:06 +03:00
|
|
|
|
2023-08-05 22:39:42 +03:00
|
|
|
// Redraw after delay if node is not syncing to update stats.
|
2023-07-14 03:51:06 +03:00
|
|
|
if Node::not_syncing() {
|
|
|
|
ui.ctx().request_repaint_after(Node::STATS_UPDATE_DELAY);
|
|
|
|
}
|
2023-07-03 21:17:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Draw tab buttons in the bottom of the screen.
|
|
|
|
fn tabs_ui(&mut self, ui: &mut egui::Ui) {
|
|
|
|
ui.scope(|ui| {
|
|
|
|
// Setup spacing between tabs.
|
2023-07-07 03:50:08 +03:00
|
|
|
ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 0.0);
|
2023-07-03 21:17:49 +03:00
|
|
|
// Setup vertical padding inside tab button.
|
2023-07-07 03:50:08 +03:00
|
|
|
ui.style_mut().spacing.button_padding = egui::vec2(0.0, 8.0);
|
2023-07-03 21:17:49 +03:00
|
|
|
|
2023-07-13 03:54:27 +03:00
|
|
|
// Draw tab buttons.
|
2023-08-11 01:02:08 +03:00
|
|
|
let current_type = self.node_tab_content.get_type();
|
2023-07-03 21:17:49 +03:00
|
|
|
ui.columns(4, |columns| {
|
|
|
|
columns[0].vertical_centered_justified(|ui| {
|
2023-07-13 03:54:27 +03:00
|
|
|
View::tab_button(ui, DATABASE, current_type == NetworkTabType::Node, || {
|
2023-08-11 01:02:08 +03:00
|
|
|
self.node_tab_content = Box::new(NetworkNode::default());
|
|
|
|
});
|
2023-07-03 21:17:49 +03:00
|
|
|
});
|
|
|
|
columns[1].vertical_centered_justified(|ui| {
|
2023-07-13 03:54:27 +03:00
|
|
|
View::tab_button(ui, GAUGE, current_type == NetworkTabType::Metrics, || {
|
2023-08-11 01:02:08 +03:00
|
|
|
self.node_tab_content = Box::new(NetworkMetrics::default());
|
|
|
|
});
|
2023-07-03 21:17:49 +03:00
|
|
|
});
|
|
|
|
columns[2].vertical_centered_justified(|ui| {
|
2023-07-13 03:54:27 +03:00
|
|
|
View::tab_button(ui, FACTORY, current_type == NetworkTabType::Mining, || {
|
2023-08-11 01:02:08 +03:00
|
|
|
self.node_tab_content = Box::new(NetworkMining::default());
|
|
|
|
});
|
2023-07-03 21:17:49 +03:00
|
|
|
});
|
|
|
|
columns[3].vertical_centered_justified(|ui| {
|
2023-07-13 03:54:27 +03:00
|
|
|
View::tab_button(ui, FADERS, current_type == NetworkTabType::Settings, || {
|
2023-08-11 01:02:08 +03:00
|
|
|
self.node_tab_content = Box::new(NetworkSettings::default());
|
|
|
|
});
|
2023-07-03 21:17:49 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Draw title content.
|
2023-08-05 22:39:42 +03:00
|
|
|
fn title_ui(&mut self,
|
|
|
|
ui: &mut egui::Ui,
|
|
|
|
frame: &mut eframe::Frame,
|
|
|
|
show_connections: bool,
|
|
|
|
cb: &dyn PlatformCallbacks) {
|
2023-07-14 03:51:06 +03:00
|
|
|
// Setup values for title panel.
|
2023-08-11 01:02:08 +03:00
|
|
|
let title_text = self.node_tab_content.get_type().title().to_uppercase();
|
2023-07-14 03:51:06 +03:00
|
|
|
let subtitle_text = Node::get_sync_status_text();
|
|
|
|
let not_syncing = Node::not_syncing();
|
2023-08-05 22:39:42 +03:00
|
|
|
let title_content = if !show_connections {
|
|
|
|
TitleType::WithSubTitle(title_text, subtitle_text, !not_syncing)
|
|
|
|
} else {
|
|
|
|
TitleType::Single(t!("network.connections").to_uppercase())
|
|
|
|
};
|
2023-07-21 04:17:57 +03:00
|
|
|
|
2023-07-14 03:51:06 +03:00
|
|
|
// Draw title panel.
|
2023-08-03 04:11:25 +03:00
|
|
|
TitlePanel::ui(title_content, |ui, _| {
|
2023-08-05 22:39:42 +03:00
|
|
|
if !show_connections {
|
|
|
|
View::title_button(ui, DOTS_THREE_OUTLINE_VERTICAL, || {
|
|
|
|
AppConfig::toggle_show_connections_network_panel();
|
2023-08-09 02:22:16 +03:00
|
|
|
if AppConfig::show_connections_network_panel() {
|
|
|
|
ExternalConnection::start_ext_conn_availability_check();
|
|
|
|
}
|
2023-08-05 22:39:42 +03:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
View::title_button(ui, PLUS_CIRCLE, || {
|
|
|
|
self.connections.show_add_ext_conn_modal(cb);
|
|
|
|
});
|
|
|
|
}
|
2023-07-21 04:17:57 +03:00
|
|
|
}, |ui, frame| {
|
|
|
|
if !Root::is_dual_panel_mode(frame) {
|
|
|
|
View::title_button(ui, CARDHOLDER, || {
|
|
|
|
Root::toggle_network_panel();
|
|
|
|
});
|
|
|
|
}
|
2023-07-16 11:23:56 +03:00
|
|
|
}, ui, frame);
|
2023-07-03 21:17:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Content to draw when node is disabled.
|
|
|
|
pub fn disabled_node_ui(ui: &mut egui::Ui) {
|
2023-07-21 04:17:57 +03:00
|
|
|
View::center_content(ui, 156.0, |ui| {
|
2023-07-03 21:17:49 +03:00
|
|
|
let text = t!("network.disabled_server", "dots" => DOTS_THREE_OUTLINE_VERTICAL);
|
|
|
|
ui.label(RichText::new(text)
|
|
|
|
.size(16.0)
|
|
|
|
.color(Colors::INACTIVE_TEXT)
|
|
|
|
);
|
2023-07-21 04:17:57 +03:00
|
|
|
ui.add_space(8.0);
|
2023-07-11 03:02:44 +03:00
|
|
|
View::button(ui, format!("{} {}", POWER, t!("network.enable_node")), Colors::GOLD, || {
|
2023-07-03 21:17:49 +03:00
|
|
|
Node::start();
|
|
|
|
});
|
|
|
|
ui.add_space(2.0);
|
|
|
|
Self::autorun_node_ui(ui);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-08-03 17:38:10 +03:00
|
|
|
/// Content to draw on loading.
|
|
|
|
pub fn loading_ui(ui: &mut egui::Ui, text: Option<String>) {
|
|
|
|
match text {
|
|
|
|
None => {
|
|
|
|
ui.centered_and_justified(|ui| {
|
|
|
|
View::big_loading_spinner(ui);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
Some(t) => {
|
|
|
|
View::center_content(ui, 162.0, |ui| {
|
|
|
|
View::big_loading_spinner(ui);
|
|
|
|
ui.add_space(18.0);
|
|
|
|
ui.label(RichText::new(t)
|
|
|
|
.size(16.0)
|
|
|
|
.color(Colors::INACTIVE_TEXT)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-13 03:54:27 +03:00
|
|
|
/// Draw checkbox to run integrated node on application launch.
|
2023-07-03 21:17:49 +03:00
|
|
|
pub fn autorun_node_ui(ui: &mut egui::Ui) {
|
|
|
|
let autostart = AppConfig::autostart_node();
|
|
|
|
View::checkbox(ui, autostart, t!("network.autorun"), || {
|
|
|
|
AppConfig::toggle_node_autostart();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|