ui + stratum: fix spaces, workers list, decrease delay for server status update

This commit is contained in:
ardocrat 2023-06-20 00:38:25 +03:00
parent 94a598a923
commit c17990d0c5
8 changed files with 283 additions and 134 deletions

View file

@ -3,7 +3,7 @@ screen_accounts:
network:
self: Network
node: Integrated node
metrics: Network metrics
metrics: Chain metrics
mining: Mining
settings: Node settings
enable_node: Enable node
@ -46,7 +46,7 @@ network_node:
size: Size (GB)
peers: Peers
network_metrics:
loading: Metrics will be available after the synchronization
loading: Chain metrics will be available after the synchronization
emission: Emission
inflation: Inflation
supply: Supply
@ -57,7 +57,6 @@ network_mining:
loading: Mining will be available after the synchronization
enable_server: Enable server
disabled_server: 'Enable stratum server at %{address} or change settings by selecting %{settings} at the bottom of the screen.'
starting: Stratum server is starting
info: 'Mining server is enabled, you can change settings by selecting %{settings} at the bottom of the screen. Data is updating when devices are connected.'
address: IP Address
wallet: Wallet Address
@ -65,9 +64,11 @@ network_mining:
miners: Miners
devices: Devices
blocks_found: Blocks found
hashrate: Hashrate
hashrate: 'Hashrate (C%{bits})'
connected: Connected
disconnected: Disconnected
modal:
cancel: Cancel
modal_exit:
description: Are you sure you want to quit the app?
description: Are you sure you want to quit the application?
exit: Exit

View file

@ -3,7 +3,7 @@ screen_accounts:
network:
self: Сеть
node: Встроенный узел
metrics: Показатели сети
metrics: Показатели цепи
mining: Майнинг
settings: Настройки узла
enable_node: Включить узел
@ -46,7 +46,7 @@ network_node:
size: Размер (ГБ)
peers: Пиры
network_metrics:
loading: Метрики будут доступны после синхронизации
loading: Показатели цепи будут доступны после синхронизации
emission: Эмиссия
inflation: Инфляция
supply: Предложение
@ -57,7 +57,6 @@ network_mining:
loading: Майнинг будет доступен после синхронизации
enable_server: Включить сервер
disabled_server: 'Включите stratum-сервер по адресу %{address} или измените настройки, выбрав %{settings} внизу экрана.'
starting: Stratum-сервер запускается
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
address: IP Адрес
wallet: Адрес кошелька
@ -65,7 +64,9 @@ network_mining:
miners: Майнеры
devices: Устройства
found: Найдено
hashrate: Хешрэйт
hashrate: 'Хешрэйт (C%{bits})'
connected: Подключен
disconnected: Отключен
modal:
cancel: Отмена
modal_exit:

View file

@ -23,6 +23,8 @@ impl Colors {
pub const SEMI_TRANSPARENT: Color32 = Color32::from_black_alpha(100);
pub const YELLOW: Color32 = Color32::from_rgb(254, 241, 2);
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
pub const GREEN: Color32 = Color32::from_rgb(0, 0x64, 0);
pub const RED: Color32 = Color32::from_rgb(0x8B, 0, 0);
pub const FILL: Color32 = Color32::from_gray(240);
pub const TITLE: Color32 = Color32::from_gray(60);
pub const TEXT: Color32 = Color32::from_gray(80);

View file

@ -13,8 +13,7 @@
// limitations under the License.
use chrono::{DateTime, NaiveDateTime, Utc};
use eframe::epaint::{Color32, Rounding, Stroke};
use egui::{RichText, ScrollArea};
use egui::{RichText, Rounding, ScrollArea, Stroke};
use grin_servers::DiffBlock;
use crate::gui::Colors;
@ -56,15 +55,11 @@ impl NetworkTab for NetworkMetrics {
let stats = server_stats.as_ref().unwrap();
// Show emission info.
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", COINS, t!("network_metrics.emission")));
});
ui.add_space(4.0);
View::sub_title(ui, format!("{} {}", COINS, t!("network_metrics.emission")));
ui.columns(3, |columns| {
let supply = stats.header_stats.height as f64 * BLOCK_REWARD;
let rate = (YEARLY_SUPPLY * 100.0) / supply;
ui.columns(3, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
format!("{}", BLOCK_REWARD),
@ -87,14 +82,11 @@ impl NetworkTab for NetworkMetrics {
ui.add_space(4.0);
// Show difficulty adjustment window info
ui.vertical_centered_justified(|ui| {
let title = t!(
let difficulty_title = t!(
"network_metrics.difficulty_window",
"size" => stats.diff_stats.window_size
);
View::sub_header(ui, format!("{} {}", HOURGLASS_MEDIUM, title));
});
ui.add_space(4.0);
View::sub_title(ui, format!("{} {}", HOURGLASS_MEDIUM, difficulty_title));
ui.columns(3, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
@ -146,10 +138,10 @@ impl NetworkTab for NetworkMetrics {
}
}
const DIFF_BLOCK_UI_HEIGHT: f32 = 77.0;
const DIFF_BLOCK_UI_HEIGHT: f32 = 76.60;
fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
// Add space before first item
// Add space before the first item.
if rounding[0] {
ui.add_space(4.0);
}
@ -167,7 +159,7 @@ fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
sw: if rounding[1] { 8.0 } else { 0.0 },
se: if rounding[1] { 8.0 } else { 0.0 },
},
Color32::WHITE,
Colors::WHITE,
Stroke { width: 1.0, color: Colors::ITEM_STROKE }
);
@ -179,7 +171,7 @@ fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
.size(18.0));
ui.add_space(2.0);
// Draw block hash
// Draw block hash.
ui.heading(RichText::new(db.block_hash.to_string())
.color(Colors::BLACK)
.size(18.0));
@ -189,9 +181,8 @@ fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
ui.heading(RichText::new(CUBE_TRANSPARENT)
.color(Colors::TITLE)
.size(16.0));
ui.add_space(4.0);
// Draw block difficulty and height
ui.add_space(3.0);
// Draw block difficulty and height.
ui.heading(RichText::new(db.difficulty.to_string())
.color(Colors::TITLE)
.size(16.0));
@ -207,23 +198,21 @@ fn draw_diff_block(ui: &mut egui::Ui, db: &DiffBlock, rounding: [bool; 2]) {
ui.heading(RichText::new(TIMER)
.color(Colors::GRAY)
.size(16.0));
ui.add_space(4.0);
// Draw block time
ui.add_space(3.0);
// Draw block date.
ui.heading(RichText::new(format!("{}s", db.duration))
.color(Colors::GRAY)
.size(16.0));
ui.add_space(2.0);
ui.add_space(4.0);
ui.heading(RichText::new(HOURGLASS_LOW).color(Colors::GRAY).size(16.0));
ui.add_space(2.0);
let naive_datetime = NaiveDateTime::from_timestamp_opt(db.time as i64, 0);
if naive_datetime.is_some() {
let datetime: DateTime<Utc> = DateTime::from_utc(naive_datetime.unwrap(), Utc);
ui.heading(RichText::new(datetime.to_string())
// Draw block time.
let block_time = NaiveDateTime::from_timestamp_opt(db.time as i64, 0).unwrap();
let block_datetime: DateTime<Utc> = DateTime::from_utc(block_time, Utc);
ui.heading(RichText::new(block_datetime.to_string())
.color(Colors::GRAY)
.size(16.0));
}
});
ui.add_space(2.0);
});

View file

@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::RichText;
use chrono::{DateTime, NaiveDateTime, Utc};
use egui::{RichText, Rounding, ScrollArea, Stroke};
use grin_chain::SyncStatus;
use grin_servers::WorkerStats;
use crate::gui::Colors;
use crate::gui::icons::{COMPUTER_TOWER, CPU, FADERS, POLYGON};
use crate::gui::icons::{BARBELL, CLOCK_AFTERNOON, COMPUTER_TOWER, CPU, CUBE, FADERS, FOLDER_DASHED, FOLDER_NOTCH_MINUS, FOLDER_NOTCH_PLUS, PLUGS, PLUGS_CONNECTED, POLYGON};
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
use crate::node::Node;
use crate::Settings;
@ -68,6 +70,18 @@ impl NetworkTab for NetworkMining {
.color(Colors::INACTIVE_TEXT)
);
let mut addresses = Vec::new();
for net_if in pnet::datalink::interfaces() {
for ip in net_if.ips {
if ip.is_ipv4() {
addresses.push(ip);
}
}
}
if addresses.len() != 0 {
}
ui.add_space(10.0);
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
@ -76,7 +90,7 @@ impl NetworkTab for NetworkMining {
ui.add_space(2.0);
// Check if stratum server is enabled at config
// Check if stratum server is enabled at config.
let stratum_enabled = Settings::node_config_to_read()
.members.clone()
.server.stratum_mining_config.unwrap()
@ -93,23 +107,14 @@ impl NetworkTab for NetworkMining {
return;
} else if Node::is_stratum_server_starting() {
// Show loading spinner when mining server is starting.
View::center_content(ui, 162.0, |ui| {
ui.centered_and_justified(|ui| {
View::big_loading_spinner(ui);
ui.add_space(18.0);
ui.label(RichText::new(t!("network_mining.starting"))
.size(16.0)
.color(Colors::INACTIVE_TEXT)
);
});
return;
}
// Show stratum mining server info.
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
});
ui.add_space(4.0);
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
ui.columns(2, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
@ -118,11 +123,12 @@ impl NetworkTab for NetworkMining {
[true, false, true, false]);
});
columns[1].vertical_centered(|ui| {
// Stratum mining wallet address.
//TODO: Stratum mining wallet listening address. Replace with local wallet name.
let wallet_address = Settings::node_config_to_read()
.members.clone()
.server.stratum_mining_config.unwrap()
.wallet_listener_url;
.wallet_listener_url
.replace("http://", "");
View::rounded_box(ui,
wallet_address,
t!("network_mining.wallet"),
@ -132,11 +138,7 @@ impl NetworkTab for NetworkMining {
ui.add_space(4.0);
// Show network info.
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", POLYGON, t!("network.self")));
});
ui.add_space(4.0);
View::sub_title(ui, format!("{} {}", POLYGON, t!("network.self")));
ui.columns(3, |columns| {
columns[0].vertical_centered(|ui| {
let difficulty = if stratum_stats.network_difficulty > 0 {
@ -162,24 +164,20 @@ impl NetworkTab for NetworkMining {
});
columns[2].vertical_centered(|ui| {
let hashrate = if stratum_stats.network_hashrate > 0.0 {
stratum_stats.network_hashrate.to_string()
format!("{:.*}", 2, stratum_stats.network_hashrate)
} else {
"-".into()
};
View::rounded_box(ui,
hashrate,
t!("network_mining.hashrate"),
t!("network_mining.hashrate", "bits" => stratum_stats.edge_bits),
[false, true, false, true]);
});
});
ui.add_space(4.0);
// Show mining info.
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", CPU, t!("network_mining.miners")));
});
ui.add_space(4.0);
View::sub_title(ui, format!("{} {}", CPU, t!("network_mining.miners")));
ui.columns(2, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
@ -197,9 +195,32 @@ impl NetworkTab for NetworkMining {
});
ui.add_space(4.0);
// Show miners info.
if !stratum_stats.worker_stats.is_empty() {
//TODO: miners workers
// Show workers stats or info text when possible.
let workers_size = stratum_stats.worker_stats.len();
if workers_size != 0 && stratum_stats.num_workers > 0 {
ScrollArea::vertical()
.auto_shrink([false; 2])
.id_source("stratum_workers_scroll")
.show_rows(
ui,
WORKER_UI_HEIGHT,
workers_size,
|ui, row_range| {
for index in row_range {
let worker = stratum_stats.worker_stats.get(index).unwrap();
let rounding = if workers_size == 1 {
[true, true]
} else if index == 0 {
[true, false]
} else if index == workers_size - 1 {
[false, true]
} else {
[false, false]
};
draw_worker_stats(ui, worker, rounding)
}
},
);
} else if ui.available_height() > 142.0 {
View::center_content(ui, 142.0, |ui| {
ui.label(RichText::new(t!("network_mining.info", "settings" => FADERS))
@ -210,3 +231,123 @@ impl NetworkTab for NetworkMining {
}
}
}
const WORKER_UI_HEIGHT: f32 = 77.0;
fn draw_worker_stats(ui: &mut egui::Ui, ws: &WorkerStats, rounding: [bool; 2]) {
// Add space before the first item.
if rounding[0] {
ui.add_space(4.0);
}
ui.horizontal(|ui| {
ui.add_space(6.0);
ui.vertical(|ui| {
let mut rect = ui.available_rect_before_wrap();
rect.set_height(WORKER_UI_HEIGHT);
ui.painter().rect(
rect,
Rounding {
nw: if rounding[0] { 8.0 } else { 0.0 },
ne: if rounding[0] { 8.0 } else { 0.0 },
sw: if rounding[1] { 8.0 } else { 0.0 },
se: if rounding[1] { 8.0 } else { 0.0 },
},
Colors::WHITE,
Stroke { width: 1.0, color: Colors::ITEM_STROKE }
);
ui.add_space(2.0);
ui.horizontal_top(|ui| {
let (status_text, status_icon) = match ws.is_connected {
true => { (t!("network_mining.connected"), PLUGS_CONNECTED) }
false => { (t!("network_mining.disconnected"), PLUGS) }
};
ui.add_space(5.0);
ui.heading(RichText::new(status_icon)
.color(Colors::BLACK)
.size(18.0));
ui.add_space(2.0);
// Draw worker ID.
ui.heading(RichText::new(&ws.id)
.color(Colors::BLACK)
.size(18.0));
ui.add_space(3.0);
// Draw worker status.
ui.heading(RichText::new(status_text)
.color(Colors::BLACK)
.size(18.0));
});
ui.horizontal_top(|ui| {
ui.add_space(6.0);
ui.heading(RichText::new(BARBELL)
.color(Colors::TITLE)
.size(16.0));
ui.add_space(4.0);
// Draw difficulty.
ui.heading(RichText::new(ws.pow_difficulty.to_string())
.color(Colors::TITLE)
.size(16.0));
ui.add_space(6.0);
ui.heading(RichText::new(FOLDER_NOTCH_PLUS)
.color(Colors::GREEN)
.size(16.0));
ui.add_space(3.0);
// Draw accepted shares.
ui.heading(RichText::new(ws.num_accepted.to_string())
.color(Colors::GREEN)
.size(16.0));
ui.add_space(6.0);
ui.heading(RichText::new(FOLDER_NOTCH_MINUS)
.color(Colors::RED)
.size(16.0));
ui.add_space(3.0);
// Draw rejected shares.
ui.heading(RichText::new(ws.num_rejected.to_string())
.color(Colors::RED)
.size(16.0));
ui.add_space(6.0);
ui.heading(RichText::new(FOLDER_DASHED)
.color(Colors::GRAY)
.size(16.0));
ui.add_space(3.0);
// Draw stale shares.
ui.heading(RichText::new(ws.num_stale.to_string())
.color(Colors::GRAY)
.size(16.0));
ui.add_space(6.0);
ui.heading(RichText::new(CUBE)
.color(Colors::TITLE)
.size(16.0));
ui.add_space(3.0);
// Draw blocks found.
ui.heading(RichText::new(ws.num_blocks_found.to_string())
.color(Colors::TITLE)
.size(16.0));
});
ui.horizontal_top(|ui| {
ui.add_space(6.0);
ui.heading(RichText::new(CLOCK_AFTERNOON)
.color(Colors::TITLE)
.size(16.0));
ui.add_space(4.0);
// Draw block time
let seen = ws.last_seen.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
let naive_datetime = NaiveDateTime::from_timestamp_opt(seen as i64, 0).unwrap();
let datetime: DateTime<Utc> = DateTime::from_utc(naive_datetime, Utc);
ui.heading(RichText::new(datetime.to_string())
.color(Colors::GRAY)
.size(16.0));
});
ui.add_space(2.0);
});
});
}

View file

@ -13,7 +13,7 @@
// limitations under the License.
use eframe::epaint::Stroke;
use egui::{Color32, RichText, Rounding, ScrollArea};
use egui::{RichText, Rounding, ScrollArea};
use grin_servers::PeerStats;
use crate::gui::Colors;
@ -48,11 +48,8 @@ impl NetworkTab for NetworkNode {
ScrollArea::vertical()
.auto_shrink([false; 2])
.show(ui, |ui| {
// Show header stats
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", FLOW_ARROW, t!("network_node.header")));
});
ui.add_space(4.0);
// Show header info.
View::sub_title(ui, format!("{} {}", FLOW_ARROW, t!("network_node.header")));
ui.columns(2, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
@ -82,13 +79,10 @@ impl NetworkTab for NetworkNode {
[false, false, false, true]);
});
});
ui.add_space(4.0);
// Show block stats
ui.add_space(4.0);
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", CUBE, t!("network_node.block")));
});
ui.add_space(4.0);
// Show block info.
View::sub_title(ui, format!("{} {}", CUBE, t!("network_node.block")));
ui.columns(2, |columns| {
columns[0].vertical_centered(|ui| {
View::rounded_box(ui,
@ -118,13 +112,10 @@ impl NetworkTab for NetworkNode {
[false, false, false, true]);
});
});
ui.add_space(4.0);
// Show data stats
ui.add_space(4.0);
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", SHARE_NETWORK, t!("network_node.data")));
});
ui.add_space(4.0);
// Show data info.
View::sub_title(ui, format!("{} {}", SHARE_NETWORK, t!("network_node.data")));
ui.columns(2, |columns| {
columns[0].vertical_centered(|ui| {
let tx_stat = match &stats.tx_stats {
@ -165,15 +156,11 @@ impl NetworkTab for NetworkNode {
[false, false, false, true]);
});
});
ui.add_space(4.0);
// Show peers stats when available
// Show peer stats when available.
if stats.peer_count > 0 {
ui.add_space(4.0);
ui.vertical_centered_justified(|ui| {
View::sub_header(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
});
ui.add_space(4.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();
let rounding = if stats.peer_count == 1 {
@ -197,7 +184,7 @@ impl NetworkTab for NetworkNode {
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
ui.vertical(|ui| {
let mut rect = ui.available_rect_before_wrap();
rect.set_height(77.0);
rect.set_height(78.0);
ui.painter().rect(
rect,
@ -207,7 +194,7 @@ fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
sw: if rounding[1] { 8.0 } else { 0.0 },
se: if rounding[1] { 8.0 } else { 0.0 },
},
Color32::WHITE,
Colors::WHITE,
Stroke { width: 1.0, color: Colors::ITEM_STROKE }
);
@ -255,7 +242,7 @@ fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
.color(Colors::GRAY)
.size(16.0));
});
ui.add_space(2.0);
ui.add_space(3.0);
});
// Add space after last item

View file

@ -18,7 +18,7 @@ use egui::epaint::text::TextWrapping;
use egui::text::{LayoutJob, TextFormat};
use crate::gui::Colors;
use crate::gui::icons::{CHECK_SQUARE, SQUARE};
use crate::gui::icons::{CHECK_SQUARE, CIRCLE, RADIO_BUTTON, SQUARE};
pub struct View;
@ -54,19 +54,23 @@ impl View {
ui.label(job);
}
/// Sub-header with uppercase characters and more lighter color.
pub fn sub_header(ui: &mut egui::Ui, text: String) {
/// Draw horizontally centered sub-title with space below.
pub fn sub_title(ui: &mut egui::Ui, text: String) {
ui.vertical_centered_justified(|ui| {
ui.label(RichText::new(text.to_uppercase()).size(16.0).color(Colors::TEXT));
});
ui.add_space(4.0);
}
/// Temporary button click optimization for touch screens.
fn on_button_click(ui: &mut egui::Ui, resp: Response, action: impl FnOnce()) {
let drag_resp = resp.interact(Sense::click_and_drag());
// Clear pointer event if dragging is out of button area
if resp.dragged() && !ui.rect_contains_pointer(resp.rect) {
if drag_resp.dragged() && !ui.rect_contains_pointer(drag_resp.rect) {
ui.input_mut().pointer = PointerState::default();
}
// Call click action if button is clicked or drag released
if resp.drag_released() || resp.clicked() {
if drag_resp.drag_released() || drag_resp.clicked() {
(action)();
};
}
@ -80,7 +84,7 @@ impl View {
let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE);
let br = Button::new(wt)
.fill(Colors::TRANSPARENT)
.ui(ui).interact(Sense::click_and_drag());
.ui(ui);
Self::on_button_click(ui, br, action);
});
@ -106,7 +110,7 @@ impl View {
let br = Button::new(wt)
.stroke(stroke)
.fill(color)
.ui(ui).interact(Sense::click_and_drag());
.ui(ui);
Self::on_button_click(ui, br, action);
}
@ -117,7 +121,7 @@ impl View {
let br = Button::new(wt)
.stroke(Self::DEFAULT_STROKE)
.fill(fill_color)
.ui(ui).interact(Sense::click_and_drag());
.ui(ui);
Self::on_button_click(ui, br, action);
}
@ -146,8 +150,11 @@ impl View {
// Draw box content.
let content_resp = ui.allocate_ui_at_rect(rect, |ui| {
ui.vertical_centered_justified(|ui| {
ui.add_space(2.0);
ui.scope(|ui| {
// Correct vertical spacing between items.
ui.style_mut().spacing.item_spacing.y = -4.0;
ui.style_mut().spacing.item_spacing.y = -3.0;
// Draw box value.
let mut job = LayoutJob::single_section(value, TextFormat {
@ -166,6 +173,9 @@ impl View {
// Draw box label.
ui.label(RichText::new(label).color(Colors::GRAY).size(15.0));
});
ui.add_space(2.0);
});
}).response;
// Setup background shape to be painted behind box content.
@ -196,18 +206,36 @@ impl View {
Spinner::new().size(48.0).color(Colors::GOLD).ui(ui);
}
/// Draw the button that looks like checkbox with callback after change.
/// Draw the button that looks like checkbox with callback on check.
pub fn checkbox(ui: &mut egui::Ui, checked: bool, text: String, callback: impl FnOnce()) {
let text_value = match checked {
true => { format!("{} {}", CHECK_SQUARE, text)}
false => { format!("{} {}", SQUARE, text)}
let (text_value, color) = match checked {
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::BUTTON) }
false => { (format!("{} {}", SQUARE, text), Colors::TEXT) }
};
let wt = RichText::new(text_value).size(19.0).color(Colors::BUTTON);
let wt = RichText::new(text_value).size(18.0).color(color);
let br = Button::new(wt)
.frame(false)
.stroke(Stroke::NONE)
.fill(Colors::TRANSPARENT)
.ui(ui).interact(Sense::click_and_drag());
.ui(ui);
Self::on_button_click(ui, br, callback);
}
/// Draw the radio button with callback on select.
pub fn radio_button(ui: &mut egui::Ui, selected: bool, text: String, callback: impl FnOnce()) {
let (text_value, color) = match selected {
true => { (format!("{} {}", RADIO_BUTTON, text), Colors::BUTTON) }
false => { (format!("{} {}", CIRCLE, text), Colors::TEXT) }
};
let wt = RichText::new(text_value).size(18.0).color(color);
let br = Button::new(wt)
.frame(false)
.stroke(Stroke::NONE)
.fill(Colors::TRANSPARENT)
.ui(ui);
Self::on_button_click(ui, br, callback);
}

View file

@ -186,7 +186,7 @@ impl Node {
server.start_stratum_server(stratum_config);
// Wait for mining server to start and update status.
thread::sleep(Duration::from_millis(1000));
thread::sleep(Duration::from_millis(100));
NODE_STATE.start_stratum_server.store(false, Ordering::Relaxed);
}