ui + build: title panel refactoring, check node idle state for network title animation, optimize font sizes, run build on several devices for Android

This commit is contained in:
ardocrat 2023-07-14 03:51:06 +03:00
parent dbe178f792
commit c20ee3e629
23 changed files with 185 additions and 228 deletions

View file

@ -37,8 +37,11 @@ then
yes | cp -f target/${platform_path}/${type}/libgrim.so app/src/main/jniLibs/${platform_param} yes | cp -f target/${platform_path}/${type}/libgrim.so app/src/main/jniLibs/${platform_param}
./gradlew clean ./gradlew clean
./gradlew build ./gradlew build
#./gradlew installDebug # Install on several devices
adb install app/build/outputs/apk/debug/app-debug.apk for SERIAL in $(adb devices | grep -v List | cut -f 1);
do
adb -s $SERIAL install app/build/outputs/apk/debug/app-debug.apk
sleep 1s sleep 1s
adb shell am start -n mw.gri.android/.MainActivity adb -s $SERIAL shell am start -n mw.gri.android/.MainActivity;
done
fi fi

View file

@ -9,8 +9,6 @@ network:
mining: Mining mining: Mining
settings: Node settings settings: Node settings
enable_node: Enable node enable_node: Enable node
disable: Disable
restart: Restart
autorun: Autorun autorun: Autorun
disabled_server: 'Enable integrated node or add another connection method by pressing %{dots} in the top-left corner of the screen.' disabled_server: 'Enable integrated node or add another connection method by pressing %{dots} in the top-left corner of the screen.'
no_ips: There are no available IP addresses on your system, server cannot be started, check your network connectivity. no_ips: There are no available IP addresses on your system, server cannot be started, check your network connectivity.

View file

@ -9,8 +9,6 @@ network:
mining: Майнинг mining: Майнинг
settings: Настройки узла settings: Настройки узла
enable_node: Включить узел enable_node: Включить узел
disable: Выключить
restart: Перезапустить
autorun: Автозапуск autorun: Автозапуск
disabled_server: 'Включите встроенный узел или добавьте другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.' disabled_server: 'Включите встроенный узел или добавьте другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.'
no_ips: В вашей системе отсутствуют доступные IP адреса, запуск сервера невозможен, проверьте ваше подключение к сети. no_ips: В вашей системе отсутствуют доступные IP адреса, запуск сервера невозможен, проверьте ваше подключение к сети.
@ -79,7 +77,7 @@ network_settings:
restart_node_required: Для применения изменений требуется перезапуск узла. restart_node_required: Для применения изменений требуется перезапуск узла.
enable: Включить enable: Включить
disable: Выключить disable: Выключить
restart: Перезапустить restart: Перезапуск
server: Сервер server: Сервер
api_ip: API IP Адрес api_ip: API IP Адрес
api_port: API Порт api_port: API Порт

View file

@ -43,7 +43,7 @@ impl<Platform: PlatformCallbacks> eframe::App for PlatformApp<Platform> {
// Show main content. // Show main content.
egui::CentralPanel::default() egui::CentralPanel::default()
.frame(egui::Frame { .frame(egui::Frame {
fill: Colors::FILL, fill: Colors::YELLOW,
..Default::default() ..Default::default()
}) })
.show(ctx, |ui| { .show(ctx, |ui| {

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::gui::{App, PlatformApp}; use crate::gui::PlatformApp;
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
#[derive(Default)] #[derive(Default)]

View file

@ -15,7 +15,7 @@
use crate::gui::Colors; use crate::gui::Colors;
use crate::gui::icons::{GLOBE, PLUS}; use crate::gui::icons::{GLOBE, PLUS};
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, TitleAction, TitlePanel, View}; use crate::gui::views::{Root, TitleAction, TitleType, TitlePanel, View};
/// Accounts content. /// Accounts content.
pub struct Accounts { pub struct Accounts {
@ -33,7 +33,8 @@ impl Default for Accounts {
impl Accounts { impl Accounts {
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) { pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
TitlePanel::ui(t!("accounts.title"), if !Root::is_dual_panel_mode(frame) { let title_content = TitleType::Single(t!("accounts.title").to_uppercase());
TitlePanel::ui(title_content, if !Root::is_dual_panel_mode(frame) {
TitleAction::new(GLOBE, || { TitleAction::new(GLOBE, || {
Root::toggle_side_panel(); Root::toggle_side_panel();
}) })

View file

@ -291,7 +291,7 @@ impl Modal {
ui.vertical_centered_justified(|ui| { ui.vertical_centered_justified(|ui| {
ui.add_space(8.0); ui.add_space(8.0);
ui.label(RichText::new(self.title.as_ref().unwrap()) ui.label(RichText::new(self.title.as_ref().unwrap())
.size(20.0) .size(19.0)
.color(Colors::TITLE) .color(Colors::TITLE)
); );
ui.add_space(8.0); ui.add_space(8.0);

View file

@ -187,7 +187,7 @@ fn block_item_ui(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
// Draw block hash. // Draw block hash.
ui.heading(RichText::new(format!("{} {}", HASH, db.block_hash)) ui.heading(RichText::new(format!("{} {}", HASH, db.block_hash))
.color(Colors::BLACK) .color(Colors::BLACK)
.size(18.0)); .size(17.0));
}); });
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add_space(6.0); ui.add_space(6.0);

View file

@ -246,7 +246,7 @@ fn worker_item_ui(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
let status_line_text = format!("{} {} {}", status_icon, ws.id, status_text); let status_line_text = format!("{} {} {}", status_icon, ws.id, status_text);
ui.heading(RichText::new(status_line_text) ui.heading(RichText::new(status_line_text)
.color(status_color) .color(status_color)
.size(18.0)); .size(17.0));
ui.add_space(2.0); ui.add_space(2.0);
}); });
ui.horizontal(|ui| { ui.horizontal(|ui| {

View file

@ -21,7 +21,7 @@ use crate::AppConfig;
use crate::gui::Colors; use crate::gui::Colors;
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER}; use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, ModalContainer, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitleAction, TitleContent, TitlePanel, View}; use crate::gui::views::{Modal, ModalContainer, NetworkMetrics, NetworkMining, NetworkNode, NetworkSettings, Root, TitleAction, TitleType, TitlePanel, View};
use crate::gui::views::network::setup::{DandelionSetup, NodeSetup, P2PSetup, PoolSetup, StratumSetup}; use crate::gui::views::network::setup::{DandelionSetup, NodeSetup, P2PSetup, PoolSetup, StratumSetup};
use crate::node::Node; use crate::node::Node;
@ -155,6 +155,11 @@ impl Network {
.show_inside(ui, |ui| { .show_inside(ui, |ui| {
self.current_tab.ui(ui, cb); self.current_tab.ui(ui, cb);
}); });
// Redraw content after delay if node is not syncing to update stats.
if Node::not_syncing() {
ui.ctx().request_repaint_after(Node::STATS_UPDATE_DELAY);
}
} }
/// Draw tab buttons in the bottom of the screen. /// Draw tab buttons in the bottom of the screen.
@ -194,9 +199,13 @@ impl Network {
/// Draw title content. /// Draw title content.
fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
let title_content = TitleContent::Custom("network_title".to_string(), Box::new(|ui| { // Setup values for title panel.
})); let title_text = self.current_tab.get_type().title().to_uppercase();
TitlePanel::test_ui(title_content, TitleAction::new(DOTS_THREE_OUTLINE_VERTICAL, || { let subtitle_text = Node::get_sync_status_text();
let not_syncing = Node::not_syncing();
let title_content = TitleType::WithSubTitle(title_text, subtitle_text, !not_syncing);
// Draw title panel.
TitlePanel::ui(title_content, TitleAction::new(DOTS_THREE_OUTLINE_VERTICAL, || {
//TODO: Show connections //TODO: Show connections
}), if !Root::is_dual_panel_mode(frame) { }), if !Root::is_dual_panel_mode(frame) {
TitleAction::new(CARDHOLDER, || { TitleAction::new(CARDHOLDER, || {
@ -205,78 +214,6 @@ impl Network {
} else { } else {
None None
}, ui); }, ui);
// StripBuilder::new(ui)
// .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| {
// self.title_text_ui(builder);
// });
// strip.cell(|ui| {
// if !Root::is_dual_panel_mode(frame) {
// ui.centered_and_justified(|ui| {
// View::title_button(ui, CARDHOLDER, || {
// Root::toggle_side_panel();
// });
// });
// }
// });
// });
}
/// Draw title text.
fn title_text_ui(&self, builder: StripBuilder) {
builder
.size(Size::remainder())
.size(Size::exact(28.0))
.vertical(|mut strip| {
strip.cell(|ui| {
ui.add_space(4.0);
ui.vertical_centered(|ui| {
ui.label(RichText::new(self.current_tab.get_type().title().to_uppercase())
.size(19.0)
.color(Colors::TITLE));
});
});
strip.cell(|ui| {
ui.centered_and_justified(|ui| {
let sync_status = Node::get_sync_status();
// Setup text color animation based on sync status
let idle = match sync_status {
None => !Node::is_starting(),
Some(ss) => ss == SyncStatus::NoSync
};
let (dark, bright) = (0.3, 1.0);
let color_factor = if !idle {
lerp(dark..=bright, ui.input(|i| i.time).cos().abs()) as f32
} else {
bright as f32
};
// 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 delay based on sync status.
if idle {
ui.ctx().request_repaint_after(Node::STATS_UPDATE_DELAY);
} else {
ui.ctx().request_repaint();
}
});
});
});
} }
/// Content to draw when node is disabled. /// Content to draw when node is disabled.

View file

@ -210,7 +210,7 @@ fn peer_item_ui(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add_space(5.0); ui.add_space(5.0);
let addr_text = format!("{} {}", PLUGS_CONNECTED, &peer.addr); let addr_text = format!("{} {}", PLUGS_CONNECTED, &peer.addr);
ui.label(RichText::new(addr_text).color(Colors::BLACK).size(18.0)); ui.label(RichText::new(addr_text).color(Colors::BLACK).size(17.0));
}); });
// Draw peer difficulty and height // Draw peer difficulty and height
ui.horizontal(|ui| { ui.horizontal(|ui| {

View file

@ -158,7 +158,7 @@ impl NetworkSettings {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.reset_settings_desc")) ui.label(RichText::new(t!("network_settings.reset_settings_desc"))
.size(18.0) .size(17.0)
.color(Colors::TEXT)); .color(Colors::TEXT));
ui.add_space(8.0); ui.add_space(8.0);
}); });
@ -212,7 +212,7 @@ impl NetworkSettings {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.restart_node_required")) ui.label(RichText::new(t!("network_settings.restart_node_required"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
}); });

View file

@ -127,7 +127,7 @@ impl DandelionSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.epoch_duration")) ui.label(RichText::new(t!("network_settings.epoch_duration"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -147,7 +147,7 @@ impl DandelionSetup {
if self.epoch_edit.parse::<u16>().is_err() { if self.epoch_edit.parse::<u16>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -212,7 +212,7 @@ impl DandelionSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.embargo_timer")) ui.label(RichText::new(t!("network_settings.embargo_timer"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -232,7 +232,7 @@ impl DandelionSetup {
if self.embargo_edit.parse::<u16>().is_err() { if self.embargo_edit.parse::<u16>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -297,7 +297,7 @@ impl DandelionSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.aggregation_period")) ui.label(RichText::new(t!("network_settings.aggregation_period"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -317,7 +317,7 @@ impl DandelionSetup {
if self.aggregation_edit.parse::<u16>().is_err() { if self.aggregation_edit.parse::<u16>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -382,7 +382,7 @@ impl DandelionSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.stem_probability")) ui.label(RichText::new(t!("network_settings.stem_probability"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -402,7 +402,7 @@ impl DandelionSetup {
if self.stem_prob_edit.parse::<u8>().is_err() { if self.stem_prob_edit.parse::<u8>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);

View file

@ -245,7 +245,7 @@ impl NodeSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.api_port")) ui.label(RichText::new(t!("network_settings.api_port"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(6.0); ui.add_space(6.0);
@ -353,7 +353,7 @@ impl NodeSetup {
_ => t!("network_settings.foreign_api_secret") _ => t!("network_settings.foreign_api_secret")
}; };
ui.label(RichText::new(description) ui.label(RichText::new(description)
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(6.0); ui.add_space(6.0);
@ -376,19 +376,17 @@ impl NodeSetup {
ui.spacing_mut().item_spacing = egui::Vec2::new(12.0, 0.0); ui.spacing_mut().item_spacing = egui::Vec2::new(12.0, 0.0);
let mut buttons_rect = ui.available_rect_before_wrap(); let mut buttons_rect = ui.available_rect_before_wrap();
buttons_rect.set_height(46.0); buttons_rect.set_height(42.0);
ui.allocate_ui_at_rect(buttons_rect, |ui| { ui.allocate_ui_at_rect(buttons_rect, |ui| {
ui.columns(2, |columns| { ui.columns(2, |columns| {
columns[0].with_layout(Layout::right_to_left(Align::Center), |ui| { columns[0].with_layout(Layout::right_to_left(Align::Center), |ui| {
let copy_title = format!("{} {}", COPY, t!("copy")); View::button(ui, COPY.to_string(), Colors::WHITE, || {
View::button(ui, copy_title, Colors::WHITE, || {
cb.copy_string_to_buffer(self.secret_edit.clone()); cb.copy_string_to_buffer(self.secret_edit.clone());
}); });
}); });
columns[1].with_layout(Layout::left_to_right(Align::Center), |ui| { columns[1].with_layout(Layout::left_to_right(Align::Center), |ui| {
let paste_title = format!("{} {}", CLIPBOARD_TEXT, t!("paste")); View::button(ui, CLIPBOARD_TEXT.to_string(), Colors::WHITE, || {
View::button(ui, paste_title, Colors::WHITE, || {
self.secret_edit = cb.get_string_from_buffer(); self.secret_edit = cb.get_string_from_buffer();
}); });
}); });
@ -469,7 +467,7 @@ impl NodeSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.ftl")) ui.label(RichText::new(t!("network_settings.ftl"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -489,7 +487,7 @@ impl NodeSetup {
if self.ftl_edit.parse::<u64>().is_err() { if self.ftl_edit.parse::<u64>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);

View file

@ -235,7 +235,7 @@ impl P2PSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.p2p_port")) ui.label(RichText::new(t!("network_settings.p2p_port"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -255,7 +255,7 @@ impl P2PSetup {
if !self.port_available_edit { if !self.port_available_edit {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.port_unavailable")) ui.label(RichText::new(t!("network_settings.port_unavailable"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} }
@ -389,7 +389,7 @@ impl P2PSetup {
Self::CUSTOM_SEED_MODAL => t!("network_settings.add_seed"), Self::CUSTOM_SEED_MODAL => t!("network_settings.add_seed"),
&_ => t!("network_settings.add_peer") &_ => t!("network_settings.add_peer")
}; };
ui.label(RichText::new(label_text).size(18.0).color(Colors::GRAY)); ui.label(RichText::new(label_text).size(17.0).color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
// Draw peer address text edit. // Draw peer address text edit.
@ -577,7 +577,7 @@ impl P2PSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.ban_window")) ui.label(RichText::new(t!("network_settings.ban_window"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -597,7 +597,7 @@ impl P2PSetup {
if self.ban_window_edit.parse::<i64>().is_err() { if self.ban_window_edit.parse::<i64>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -663,7 +663,7 @@ impl P2PSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.max_inbound_count")) ui.label(RichText::new(t!("network_settings.max_inbound_count"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -683,7 +683,7 @@ impl P2PSetup {
if self.max_inbound_count.parse::<u32>().is_err() { if self.max_inbound_count.parse::<u32>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -749,7 +749,7 @@ impl P2PSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.max_outbound_count")) ui.label(RichText::new(t!("network_settings.max_outbound_count"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -769,7 +769,7 @@ impl P2PSetup {
if self.max_outbound_count.parse::<u32>().is_err() { if self.max_outbound_count.parse::<u32>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -840,7 +840,7 @@ impl P2PSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.min_outbound_count")) ui.label(RichText::new(t!("network_settings.min_outbound_count"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -860,7 +860,7 @@ impl P2PSetup {
if self.min_outbound_count.parse::<u32>().is_err() { if self.min_outbound_count.parse::<u32>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);

View file

@ -129,7 +129,7 @@ impl PoolSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.pool_fee")) ui.label(RichText::new(t!("network_settings.pool_fee"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -149,7 +149,7 @@ impl PoolSetup {
if self.fee_base_edit.parse::<u64>().is_err() { if self.fee_base_edit.parse::<u64>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -214,7 +214,7 @@ impl PoolSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.reorg_period")) ui.label(RichText::new(t!("network_settings.reorg_period"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -233,8 +233,8 @@ impl PoolSetup {
// Show error when specified value is not valid or reminder to restart enabled node. // Show error when specified value is not valid or reminder to restart enabled node.
if self.reorg_period_edit.parse::<u32>().is_err() { if self.reorg_period_edit.parse::<u32>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.reorg_period")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -299,7 +299,7 @@ impl PoolSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.max_tx_pool")) ui.label(RichText::new(t!("network_settings.max_tx_pool"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -319,7 +319,7 @@ impl PoolSetup {
if self.pool_size_edit.parse::<usize>().is_err() { if self.pool_size_edit.parse::<usize>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -384,7 +384,7 @@ impl PoolSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.max_tx_stempool")) ui.label(RichText::new(t!("network_settings.max_tx_stempool"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -404,7 +404,7 @@ impl PoolSetup {
if self.stempool_size_edit.parse::<usize>().is_err() { if self.stempool_size_edit.parse::<usize>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);
@ -469,7 +469,7 @@ impl PoolSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.max_tx_weight")) ui.label(RichText::new(t!("network_settings.max_tx_weight"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -489,7 +489,7 @@ impl PoolSetup {
if self.max_weight_edit.parse::<u64>().is_err() { if self.max_weight_edit.parse::<u64>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
NetworkSettings::node_restart_required_ui(ui); NetworkSettings::node_restart_required_ui(ui);

View file

@ -186,7 +186,7 @@ impl StratumSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.stratum_port")) ui.label(RichText::new(t!("network_settings.stratum_port"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -206,7 +206,7 @@ impl StratumSetup {
if !self.stratum_port_available_edit { if !self.stratum_port_available_edit {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.port_unavailable")) ui.label(RichText::new(t!("network_settings.port_unavailable"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
server_restart_required_ui(ui); server_restart_required_ui(ui);
@ -284,7 +284,7 @@ impl StratumSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.attempt_time")) ui.label(RichText::new(t!("network_settings.attempt_time"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -304,7 +304,7 @@ impl StratumSetup {
if self.attempt_time_edit.parse::<u32>().is_err() { if self.attempt_time_edit.parse::<u32>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
server_restart_required_ui(ui); server_restart_required_ui(ui);
@ -370,7 +370,7 @@ impl StratumSetup {
ui.add_space(6.0); ui.add_space(6.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("network_settings.min_share_diff")) ui.label(RichText::new(t!("network_settings.min_share_diff"))
.size(18.0) .size(17.0)
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
@ -390,7 +390,7 @@ impl StratumSetup {
if self.min_share_diff_edit.parse::<u64>().is_err() { if self.min_share_diff_edit.parse::<u64>().is_err() {
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("network_settings.not_valid_value")) ui.label(RichText::new(t!("network_settings.not_valid_value"))
.size(18.0) .size(17.0)
.color(Colors::RED)); .color(Colors::RED));
} else { } else {
server_restart_required_ui(ui); server_restart_required_ui(ui);

View file

@ -140,7 +140,7 @@ impl Root {
/// Show exit confirmation modal. /// Show exit confirmation modal.
pub fn show_exit_modal() { pub fn show_exit_modal() {
let exit_modal = Modal::new(Self::EXIT_MODAL_ID).title(t!("modal_exit.exit")); let exit_modal = Modal::new(Self::EXIT_MODAL_ID).title(t!("modal.confirmation"));
Modal::show(exit_modal); Modal::show(exit_modal);
} }
@ -160,7 +160,7 @@ impl Root {
View::small_loading_spinner(ui); View::small_loading_spinner(ui);
ui.add_space(12.0); ui.add_space(12.0);
ui.label(RichText::new(t!("sync_status.shutdown")) ui.label(RichText::new(t!("sync_status.shutdown"))
.size(18.0) .size(17.0)
.color(Colors::TEXT)); .color(Colors::TEXT));
}); });
ui.add_space(10.0); ui.add_space(10.0);
@ -168,7 +168,7 @@ impl Root {
ui.add_space(8.0); ui.add_space(8.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("modal_exit.description")) ui.label(RichText::new(t!("modal_exit.description"))
.size(18.0) .size(17.0)
.color(Colors::TEXT)); .color(Colors::TEXT));
}); });
ui.add_space(10.0); ui.add_space(10.0);

View file

@ -12,13 +12,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use egui::Id; use egui::{Color32, Id, lerp, Rgba, RichText};
use egui::style::Margin; use egui::style::Margin;
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use crate::gui::Colors; use crate::gui::Colors;
use crate::gui::views::View; use crate::gui::views::View;
/// Title action button.
pub struct TitleAction { pub struct TitleAction {
pub(crate) icon: Box<&'static str>, pub(crate) icon: Box<&'static str>,
pub(crate) on_click: Box<dyn Fn()>, pub(crate) on_click: Box<dyn Fn()>,
@ -30,22 +31,22 @@ impl TitleAction {
} }
} }
/// Represents title content, can be text or callback to draw custom title. /// Represents title content, can be single title or with animated sub-title.
pub enum TitleContent { pub enum TitleType {
Text(String), Single(String),
/// First argument is identifier for panel. WithSubTitle(String, String, bool)
Custom(String, Box<dyn Fn(&mut egui::Ui)>)
} }
/// Title panel with left/right action buttons and text in the middle.
pub struct TitlePanel; pub struct TitlePanel;
impl TitlePanel { impl TitlePanel {
pub const DEFAULT_HEIGHT: f32 = 52.0; pub const DEFAULT_HEIGHT: f32 = 52.0;
pub fn test_ui(title: TitleContent, l: Option<TitleAction>, r: Option<TitleAction>, ui: &mut egui::Ui) { pub fn ui(title: TitleType, l: Option<TitleAction>, r: Option<TitleAction>, ui: &mut egui::Ui) {
let id = match &title { let id = match &title {
TitleContent::Text(text) => Id::from(text.clone()), TitleType::Single(text) => Id::from(text.clone()),
TitleContent::Custom(text, _) => Id::from(text.clone()) TitleType::WithSubTitle(text, _, _) => Id::from(text.clone())
}; };
egui::TopBottomPanel::top(id) egui::TopBottomPanel::top(id)
.resizable(false) .resizable(false)
@ -64,44 +65,21 @@ impl TitlePanel {
strip.cell(|ui| { strip.cell(|ui| {
Self::draw_action(ui, l); Self::draw_action(ui, l);
}); });
strip.cell(|ui| {
match title { match title {
TitleContent::Text(text) => { TitleType::Single(text) => {
Self::draw_title(ui, text); strip.cell(|ui| {
} ui.add_space(2.0);
TitleContent::Custom(_, cb) => { ui.centered_and_justified(|ui| {
(cb)(ui); View::ellipsize_text(ui, text, 19.0, Colors::TITLE);
}
}
});
strip.cell(|ui| {
Self::draw_action(ui, r);
});
});
});
}
pub fn ui(title: String, l: Option<TitleAction>, r: Option<TitleAction>, ui: &mut egui::Ui) {
egui::TopBottomPanel::top(Id::from(title.clone()))
.resizable(false)
.exact_height(Self::DEFAULT_HEIGHT)
.frame(egui::Frame {
outer_margin: Margin::same(-1.0),
fill: Colors::YELLOW,
..Default::default()
})
.show_inside(ui, |ui| {
StripBuilder::new(ui)
.size(Size::exact(Self::DEFAULT_HEIGHT))
.size(Size::remainder())
.size(Size::exact(Self::DEFAULT_HEIGHT))
.horizontal(|mut strip| {
strip.cell(|ui| {
Self::draw_action(ui, l);
});
strip.cell(|ui| {
Self::draw_title(ui, title);
}); });
});
}
TitleType::WithSubTitle(text, subtitle_text, animate_sub) => {
strip.strip(|builder| {
Self::with_sub_title(builder, text, subtitle_text, animate_sub);
});
}
}
strip.cell(|ui| { strip.cell(|ui| {
Self::draw_action(ui, r); Self::draw_action(ui, r);
}); });
@ -109,6 +87,7 @@ impl TitlePanel {
}); });
} }
/// Draw panel [`TitleAction`].
fn draw_action(ui: &mut egui::Ui, action: Option<TitleAction>) { fn draw_action(ui: &mut egui::Ui, action: Option<TitleAction>) {
if action.is_some() { if action.is_some() {
let action = action.unwrap(); let action = action.unwrap();
@ -120,10 +99,45 @@ impl TitlePanel {
} }
} }
fn draw_title(ui: &mut egui::Ui, title: String) { /// Draw title text for [`TitleType::Single`] type.
ui.add_space(2.0); fn single(ui: &mut egui::Ui, title: String) {
}
/// Draw title text for [`TitleType::WithSubTitle`] type.
fn with_sub_title(builder: StripBuilder, title: String, subtitle: String, animate_sub: bool) {
builder
.size(Size::remainder())
.size(Size::exact(30.0))
.vertical(|mut strip| {
strip.cell(|ui| {
ui.add_space(4.0);
ui.centered_and_justified(|ui| { ui.centered_and_justified(|ui| {
View::ellipsize_text(ui, title.to_uppercase(), 20.0, Colors::TITLE); View::ellipsize_text(ui, title, 18.0, Colors::TITLE);
});
});
strip.cell(|ui| {
ui.centered_and_justified(|ui| {
// Setup text color animation if needed.
let (dark, bright) = (0.3, 1.0);
let color_factor = if animate_sub {
lerp(dark..=bright, ui.input(|i| i.time).cos().abs()) as f32
} else {
bright as f32
};
// Draw subtitle text.
let sub_color_rgba = Rgba::from(Colors::TEXT) * color_factor;
let sub_color = Color32::from(sub_color_rgba);
View::ellipsize_text(ui, subtitle, 15.0, sub_color);
// Repaint delay based on animation status.
if animate_sub {
ui.ctx().request_repaint();
}
});
ui.add_space(2.0);
});
}); });
} }
} }

View file

@ -76,7 +76,7 @@ impl View {
// Disable stroke color on hover. // Disable stroke color on hover.
ui.style_mut().visuals.widgets.hovered.bg_stroke = Self::DEFAULT_STROKE; ui.style_mut().visuals.widgets.hovered.bg_stroke = Self::DEFAULT_STROKE;
// Setup text. // Setup text.
let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE); let wt = RichText::new(icon.to_string()).size(22.0).color(Colors::TITLE);
// Draw button. // Draw button.
let br = Button::new(wt) let br = Button::new(wt)
.fill(Colors::TRANSPARENT) .fill(Colors::TRANSPARENT)
@ -101,7 +101,7 @@ impl View {
true => Colors::FILL, true => Colors::FILL,
false => Colors::WHITE false => Colors::WHITE
}; };
let br = Button::new(RichText::new(icon.to_string()).size(24.0).color(text_color)) let br = Button::new(RichText::new(icon.to_string()).size(22.0).color(text_color))
.stroke(stroke) .stroke(stroke)
.fill(color) .fill(color)
.ui(ui); .ui(ui);
@ -112,7 +112,7 @@ impl View {
/// Draw [`Button`] with specified background fill color. /// Draw [`Button`] with specified background fill color.
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) { pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) {
let button_text = Self::ellipsize(text.to_uppercase(), 18.0, Colors::TEXT_BUTTON); let button_text = Self::ellipsize(text.to_uppercase(), 17.0, Colors::TEXT_BUTTON);
let br = Button::new(button_text) let br = Button::new(button_text)
.stroke(Self::DEFAULT_STROKE) .stroke(Self::DEFAULT_STROKE)
.fill(fill_color) .fill(fill_color)
@ -154,7 +154,7 @@ impl View {
// Draw box value. // Draw box value.
let mut job = LayoutJob::single_section(value, TextFormat { let mut job = LayoutJob::single_section(value, TextFormat {
font_id: FontId::proportional(18.0), font_id: FontId::proportional(17.0),
color: Colors::BLACK, color: Colors::BLACK,
..Default::default() ..Default::default()
}); });
@ -209,7 +209,7 @@ impl View {
false => (format!("{} {}", SQUARE, text), Colors::CHECKBOX) false => (format!("{} {}", SQUARE, text), Colors::CHECKBOX)
}; };
let br = Button::new(RichText::new(text_value).size(18.0).color(color)) let br = Button::new(RichText::new(text_value).size(17.0).color(color))
.frame(false) .frame(false)
.stroke(Stroke::NONE) .stroke(Stroke::NONE)
.fill(Colors::TRANSPARENT) .fill(Colors::TRANSPARENT)

View file

@ -173,10 +173,10 @@ pub fn setup_fonts(ctx: &Context) {
let mut style = (*ctx.style()).clone(); let mut style = (*ctx.style()).clone();
style.text_styles = [ style.text_styles = [
(Heading, FontId::new(20.0, Proportional)), (Heading, FontId::new(19.0, Proportional)),
(Body, FontId::new(16.0, Proportional)), (Body, FontId::new(16.0, Proportional)),
(Button, FontId::new(18.0, Proportional)), (Button, FontId::new(17.0, Proportional)),
(Small, FontId::new(12.0, Proportional)), (Small, FontId::new(15.0, Proportional)),
(Monospace, FontId::new(16.0, Proportional)), (Monospace, FontId::new(16.0, Proportional)),
].into(); ].into();

View file

@ -29,31 +29,31 @@ use crate::node::NodeConfig;
use crate::node::stratum::{StratumStopState, StratumServer}; use crate::node::stratum::{StratumStopState, StratumServer};
lazy_static! { lazy_static! {
/// Static thread-aware state of [`Node`] to be updated from another thread. /// Static thread-aware state of [`Node`] to be updated from separate thread.
static ref NODE_STATE: Arc<Node> = Arc::new(Node::default()); static ref NODE_STATE: Arc<Node> = Arc::new(Node::default());
} }
/// Provides [`Server`] control, holds current status and statistics. /// Provides [`Server`] control, holds current status and statistics.
pub struct Node { pub struct Node {
/// The node [`Server`] statistics for UI. /// Node [`Server`] statistics for UI.
stats: Arc<RwLock<Option<ServerStats>>>, stats: Arc<RwLock<Option<ServerStats>>>,
/// Stratum server statistics. /// [`StratumServer`] statistics.
stratum_stats: Arc<grin_util::RwLock<StratumStats>>, stratum_stats: Arc<grin_util::RwLock<StratumStats>>,
/// Stratum server statistics. /// State to stop [`StratumServer`] from outside.
stratum_stop_state: Arc<StratumStopState>, stratum_stop_state: Arc<StratumStopState>,
/// Running API server address. /// Running API [`Server`] address.
api_addr: Arc<RwLock<Option<String>>>, api_addr: Arc<RwLock<Option<String>>>,
/// Running P2P server port. /// Running P2P [`grin_p2p::Server`] port.
p2p_port: Arc<RwLock<Option<u16>>>, p2p_port: Arc<RwLock<Option<u16>>>,
/// Indicator if server is starting. /// Indicator if node [`Server`] is starting.
starting: AtomicBool, starting: AtomicBool,
/// Thread flag to stop the server and start it again. /// Thread flag to stop the [`Server`] and start it again.
restart_needed: AtomicBool, restart_needed: AtomicBool,
/// Thread flag to stop the server. /// Thread flag to stop the [`Server`].
stop_needed: AtomicBool, stop_needed: AtomicBool,
/// Flag to check if app exit is needed after server stop. /// Flag to check if app exit is needed after [`Server`] stop.
exit_after_stop: AtomicBool, exit_after_stop: AtomicBool,
/// Thread flag to start stratum server. /// Thread flag to start [`StratumServer`].
start_stratum_needed: AtomicBool, start_stratum_needed: AtomicBool,
/// Error on [`Server`] start. /// Error on [`Server`] start.
init_error: Option<Error> init_error: Option<Error>
@ -78,7 +78,7 @@ impl Default for Node {
} }
impl Node { impl Node {
/// Delay for server thread to update the stats. /// Delay for thread to update the stats.
pub const STATS_UPDATE_DELAY: Duration = Duration::from_millis(250); pub const STATS_UPDATE_DELAY: Duration = Duration::from_millis(250);
/// Stop the [`Server`] and setup exit flag after if needed. /// Stop the [`Server`] and setup exit flag after if needed.
@ -87,14 +87,14 @@ impl Node {
NODE_STATE.exit_after_stop.store(exit_after_stop, Ordering::Relaxed); NODE_STATE.exit_after_stop.store(exit_after_stop, Ordering::Relaxed);
} }
/// Start the node. /// Request to start the [`Node`].
pub fn start() { pub fn start() {
if !Self::is_running() { if !Self::is_running() {
Self::start_server_thread(); Self::start_server_thread();
} }
} }
/// Restart the node. /// Request to restart the [`Node`].
pub fn restart() { pub fn restart() {
if Self::is_running() { if Self::is_running() {
NODE_STATE.restart_needed.store(true, Ordering::Relaxed); NODE_STATE.restart_needed.store(true, Ordering::Relaxed);
@ -103,7 +103,7 @@ impl Node {
} }
} }
/// Get API server address if node is running. /// Get API [`Server`] address if [`Node`] is running.
pub fn get_api_addr() -> Option<String> { pub fn get_api_addr() -> Option<String> {
let r_api_addr = NODE_STATE.api_addr.read().unwrap(); let r_api_addr = NODE_STATE.api_addr.read().unwrap();
if r_api_addr.is_some() { if r_api_addr.is_some() {
@ -113,7 +113,7 @@ impl Node {
} }
} }
/// Get P2P server port if node is running. /// Get P2P [`grin_p2p::Server`] port if node is running.
pub fn get_p2p_port() -> Option<u16> { pub fn get_p2p_port() -> Option<u16> {
let r_p2p_port = NODE_STATE.p2p_port.read().unwrap(); let r_p2p_port = NODE_STATE.p2p_port.read().unwrap();
if r_p2p_port.is_some() { if r_p2p_port.is_some() {
@ -123,47 +123,47 @@ impl Node {
} }
} }
/// Request to start stratum server. /// Request to start [`StratumServer`].
pub fn start_stratum() { pub fn start_stratum() {
NODE_STATE.start_stratum_needed.store(true, Ordering::Relaxed); NODE_STATE.start_stratum_needed.store(true, Ordering::Relaxed);
} }
/// Check if stratum server is starting. /// Check if [`StratumServer`] is starting.
pub fn is_stratum_starting() -> bool { pub fn is_stratum_starting() -> bool {
NODE_STATE.start_stratum_needed.load(Ordering::Relaxed) NODE_STATE.start_stratum_needed.load(Ordering::Relaxed)
} }
/// Get stratum server statistics. /// Get [`StratumServer`] statistics.
pub fn get_stratum_stats() -> grin_util::RwLockReadGuard<'static, StratumStats> { pub fn get_stratum_stats() -> grin_util::RwLockReadGuard<'static, StratumStats> {
NODE_STATE.stratum_stats.read() NODE_STATE.stratum_stats.read()
} }
/// Stop stratum server. /// Stop [`StratumServer`].
pub fn stop_stratum() { pub fn stop_stratum() {
NODE_STATE.stratum_stop_state.stop() NODE_STATE.stratum_stop_state.stop()
} }
/// Check if stratum server is stopping. /// Check if [`StratumServer`] is stopping.
pub fn is_stratum_stopping() -> bool { pub fn is_stratum_stopping() -> bool {
NODE_STATE.stratum_stop_state.is_stopped() NODE_STATE.stratum_stop_state.is_stopped()
} }
/// Check if node is starting. /// Check if [`Node`] is starting.
pub fn is_starting() -> bool { pub fn is_starting() -> bool {
NODE_STATE.starting.load(Ordering::Relaxed) NODE_STATE.starting.load(Ordering::Relaxed)
} }
/// Check if node is running. /// Check if [`Node`] is running.
pub fn is_running() -> bool { pub fn is_running() -> bool {
Self::get_sync_status().is_some() Self::get_sync_status().is_some()
} }
/// Check if node is stopping. /// Check if [`Node`] is stopping.
pub fn is_stopping() -> bool { pub fn is_stopping() -> bool {
NODE_STATE.stop_needed.load(Ordering::Relaxed) NODE_STATE.stop_needed.load(Ordering::Relaxed)
} }
/// Check if node is restarting. /// Check if [`Node`] is restarting.
pub fn is_restarting() -> bool { pub fn is_restarting() -> bool {
NODE_STATE.restart_needed.load(Ordering::Relaxed) NODE_STATE.restart_needed.load(Ordering::Relaxed)
} }
@ -173,6 +173,14 @@ impl Node {
NODE_STATE.stats.read().unwrap() NODE_STATE.stats.read().unwrap()
} }
/// Check if [`Server`] is not syncing (disabled or just running after synchronization).
pub fn not_syncing() -> bool {
return match Node::get_sync_status() {
None => true,
Some(ss) => ss == SyncStatus::NoSync
};
}
/// Get synchronization status, empty when [`Server`] is not running. /// Get synchronization status, empty when [`Server`] is not running.
pub fn get_sync_status() -> Option<SyncStatus> { pub fn get_sync_status() -> Option<SyncStatus> {
// Return Shutdown status when node is stopping. // Return Shutdown status when node is stopping.

View file

@ -205,7 +205,7 @@ impl State {
} }
} }
/// Stratum server stop state shared between to stop stratum from node thread. /// Stratum server stop state to stop it from node thread.
pub struct StratumStopState { pub struct StratumStopState {
stopping: AtomicBool, stopping: AtomicBool,
} }