ui + stratum: fix spaces, workers list, decrease delay for server status update
This commit is contained in:
parent
94a598a923
commit
c17990d0c5
8 changed files with 283 additions and 134 deletions
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue