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:
|
network:
|
||||||
self: Network
|
self: Network
|
||||||
node: Integrated node
|
node: Integrated node
|
||||||
metrics: Network metrics
|
metrics: Chain metrics
|
||||||
mining: Mining
|
mining: Mining
|
||||||
settings: Node settings
|
settings: Node settings
|
||||||
enable_node: Enable node
|
enable_node: Enable node
|
||||||
|
@ -46,7 +46,7 @@ network_node:
|
||||||
size: Size (GB)
|
size: Size (GB)
|
||||||
peers: Peers
|
peers: Peers
|
||||||
network_metrics:
|
network_metrics:
|
||||||
loading: Metrics will be available after the synchronization
|
loading: Chain metrics will be available after the synchronization
|
||||||
emission: Emission
|
emission: Emission
|
||||||
inflation: Inflation
|
inflation: Inflation
|
||||||
supply: Supply
|
supply: Supply
|
||||||
|
@ -57,7 +57,6 @@ network_mining:
|
||||||
loading: Mining will be available after the synchronization
|
loading: Mining will be available after the synchronization
|
||||||
enable_server: Enable server
|
enable_server: Enable server
|
||||||
disabled_server: 'Enable stratum server at %{address} or change settings by selecting %{settings} at the bottom of the screen.'
|
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.'
|
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
|
address: IP Address
|
||||||
wallet: Wallet Address
|
wallet: Wallet Address
|
||||||
|
@ -65,9 +64,11 @@ network_mining:
|
||||||
miners: Miners
|
miners: Miners
|
||||||
devices: Devices
|
devices: Devices
|
||||||
blocks_found: Blocks found
|
blocks_found: Blocks found
|
||||||
hashrate: Hashrate
|
hashrate: 'Hashrate (C%{bits})'
|
||||||
|
connected: Connected
|
||||||
|
disconnected: Disconnected
|
||||||
modal:
|
modal:
|
||||||
cancel: Cancel
|
cancel: Cancel
|
||||||
modal_exit:
|
modal_exit:
|
||||||
description: Are you sure you want to quit the app?
|
description: Are you sure you want to quit the application?
|
||||||
exit: Exit
|
exit: Exit
|
|
@ -3,7 +3,7 @@ screen_accounts:
|
||||||
network:
|
network:
|
||||||
self: Сеть
|
self: Сеть
|
||||||
node: Встроенный узел
|
node: Встроенный узел
|
||||||
metrics: Показатели сети
|
metrics: Показатели цепи
|
||||||
mining: Майнинг
|
mining: Майнинг
|
||||||
settings: Настройки узла
|
settings: Настройки узла
|
||||||
enable_node: Включить узел
|
enable_node: Включить узел
|
||||||
|
@ -46,7 +46,7 @@ network_node:
|
||||||
size: Размер (ГБ)
|
size: Размер (ГБ)
|
||||||
peers: Пиры
|
peers: Пиры
|
||||||
network_metrics:
|
network_metrics:
|
||||||
loading: Метрики будут доступны после синхронизации
|
loading: Показатели цепи будут доступны после синхронизации
|
||||||
emission: Эмиссия
|
emission: Эмиссия
|
||||||
inflation: Инфляция
|
inflation: Инфляция
|
||||||
supply: Предложение
|
supply: Предложение
|
||||||
|
@ -57,7 +57,6 @@ network_mining:
|
||||||
loading: Майнинг будет доступен после синхронизации
|
loading: Майнинг будет доступен после синхронизации
|
||||||
enable_server: Включить сервер
|
enable_server: Включить сервер
|
||||||
disabled_server: 'Включите stratum-сервер по адресу %{address} или измените настройки, выбрав %{settings} внизу экрана.'
|
disabled_server: 'Включите stratum-сервер по адресу %{address} или измените настройки, выбрав %{settings} внизу экрана.'
|
||||||
starting: Stratum-сервер запускается
|
|
||||||
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
||||||
address: IP Адрес
|
address: IP Адрес
|
||||||
wallet: Адрес кошелька
|
wallet: Адрес кошелька
|
||||||
|
@ -65,7 +64,9 @@ network_mining:
|
||||||
miners: Майнеры
|
miners: Майнеры
|
||||||
devices: Устройства
|
devices: Устройства
|
||||||
found: Найдено
|
found: Найдено
|
||||||
hashrate: Хешрэйт
|
hashrate: 'Хешрэйт (C%{bits})'
|
||||||
|
connected: Подключен
|
||||||
|
disconnected: Отключен
|
||||||
modal:
|
modal:
|
||||||
cancel: Отмена
|
cancel: Отмена
|
||||||
modal_exit:
|
modal_exit:
|
||||||
|
|
|
@ -23,6 +23,8 @@ impl Colors {
|
||||||
pub const SEMI_TRANSPARENT: Color32 = Color32::from_black_alpha(100);
|
pub const SEMI_TRANSPARENT: Color32 = Color32::from_black_alpha(100);
|
||||||
pub const YELLOW: Color32 = Color32::from_rgb(254, 241, 2);
|
pub const YELLOW: Color32 = Color32::from_rgb(254, 241, 2);
|
||||||
pub const GOLD: Color32 = Color32::from_rgb(255, 215, 0);
|
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 FILL: Color32 = Color32::from_gray(240);
|
||||||
pub const TITLE: Color32 = Color32::from_gray(60);
|
pub const TITLE: Color32 = Color32::from_gray(60);
|
||||||
pub const TEXT: Color32 = Color32::from_gray(80);
|
pub const TEXT: Color32 = Color32::from_gray(80);
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
use eframe::epaint::{Color32, Rounding, Stroke};
|
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||||
use egui::{RichText, ScrollArea};
|
|
||||||
use grin_servers::DiffBlock;
|
use grin_servers::DiffBlock;
|
||||||
|
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
|
@ -56,15 +55,11 @@ impl NetworkTab for NetworkMetrics {
|
||||||
let stats = server_stats.as_ref().unwrap();
|
let stats = server_stats.as_ref().unwrap();
|
||||||
|
|
||||||
// Show emission info.
|
// Show emission info.
|
||||||
ui.vertical_centered_justified(|ui| {
|
View::sub_title(ui, format!("{} {}", COINS, t!("network_metrics.emission")));
|
||||||
View::sub_header(ui, format!("{} {}", COINS, t!("network_metrics.emission")));
|
ui.columns(3, |columns| {
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
|
|
||||||
let supply = stats.header_stats.height as f64 * BLOCK_REWARD;
|
let supply = stats.header_stats.height as f64 * BLOCK_REWARD;
|
||||||
let rate = (YEARLY_SUPPLY * 100.0) / supply;
|
let rate = (YEARLY_SUPPLY * 100.0) / supply;
|
||||||
|
|
||||||
ui.columns(3, |columns| {
|
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
format!("{}ツ", BLOCK_REWARD),
|
format!("{}ツ", BLOCK_REWARD),
|
||||||
|
@ -87,14 +82,11 @@ impl NetworkTab for NetworkMetrics {
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show difficulty adjustment window info
|
// Show difficulty adjustment window info
|
||||||
ui.vertical_centered_justified(|ui| {
|
let difficulty_title = t!(
|
||||||
let title = t!(
|
|
||||||
"network_metrics.difficulty_window",
|
"network_metrics.difficulty_window",
|
||||||
"size" => stats.diff_stats.window_size
|
"size" => stats.diff_stats.window_size
|
||||||
);
|
);
|
||||||
View::sub_header(ui, format!("{} {}", HOURGLASS_MEDIUM, title));
|
View::sub_title(ui, format!("{} {}", HOURGLASS_MEDIUM, difficulty_title));
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
ui.columns(3, |columns| {
|
ui.columns(3, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(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]) {
|
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] {
|
if rounding[0] {
|
||||||
ui.add_space(4.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 },
|
sw: if rounding[1] { 8.0 } else { 0.0 },
|
||||||
se: 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 }
|
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));
|
.size(18.0));
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
|
|
||||||
// Draw block hash
|
// Draw block hash.
|
||||||
ui.heading(RichText::new(db.block_hash.to_string())
|
ui.heading(RichText::new(db.block_hash.to_string())
|
||||||
.color(Colors::BLACK)
|
.color(Colors::BLACK)
|
||||||
.size(18.0));
|
.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)
|
ui.heading(RichText::new(CUBE_TRANSPARENT)
|
||||||
.color(Colors::TITLE)
|
.color(Colors::TITLE)
|
||||||
.size(16.0));
|
.size(16.0));
|
||||||
ui.add_space(4.0);
|
ui.add_space(3.0);
|
||||||
|
// Draw block difficulty and height.
|
||||||
// Draw block difficulty and height
|
|
||||||
ui.heading(RichText::new(db.difficulty.to_string())
|
ui.heading(RichText::new(db.difficulty.to_string())
|
||||||
.color(Colors::TITLE)
|
.color(Colors::TITLE)
|
||||||
.size(16.0));
|
.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)
|
ui.heading(RichText::new(TIMER)
|
||||||
.color(Colors::GRAY)
|
.color(Colors::GRAY)
|
||||||
.size(16.0));
|
.size(16.0));
|
||||||
ui.add_space(4.0);
|
ui.add_space(3.0);
|
||||||
|
// Draw block date.
|
||||||
// Draw block time
|
|
||||||
ui.heading(RichText::new(format!("{}s", db.duration))
|
ui.heading(RichText::new(format!("{}s", db.duration))
|
||||||
.color(Colors::GRAY)
|
.color(Colors::GRAY)
|
||||||
.size(16.0));
|
.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.heading(RichText::new(HOURGLASS_LOW).color(Colors::GRAY).size(16.0));
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
|
// Draw block time.
|
||||||
let naive_datetime = NaiveDateTime::from_timestamp_opt(db.time as i64, 0);
|
let block_time = NaiveDateTime::from_timestamp_opt(db.time as i64, 0).unwrap();
|
||||||
if naive_datetime.is_some() {
|
let block_datetime: DateTime<Utc> = DateTime::from_utc(block_time, Utc);
|
||||||
let datetime: DateTime<Utc> = DateTime::from_utc(naive_datetime.unwrap(), Utc);
|
ui.heading(RichText::new(block_datetime.to_string())
|
||||||
ui.heading(RichText::new(datetime.to_string())
|
|
||||||
.color(Colors::GRAY)
|
.color(Colors::GRAY)
|
||||||
.size(16.0));
|
.size(16.0));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,11 +12,13 @@
|
||||||
// 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::RichText;
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
|
use egui::{RichText, Rounding, ScrollArea, Stroke};
|
||||||
use grin_chain::SyncStatus;
|
use grin_chain::SyncStatus;
|
||||||
|
use grin_servers::WorkerStats;
|
||||||
|
|
||||||
use crate::gui::Colors;
|
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::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
|
@ -68,6 +70,18 @@ impl NetworkTab for NetworkMining {
|
||||||
.color(Colors::INACTIVE_TEXT)
|
.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);
|
ui.add_space(10.0);
|
||||||
|
|
||||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||||
|
@ -76,7 +90,7 @@ impl NetworkTab for NetworkMining {
|
||||||
|
|
||||||
ui.add_space(2.0);
|
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()
|
let stratum_enabled = Settings::node_config_to_read()
|
||||||
.members.clone()
|
.members.clone()
|
||||||
.server.stratum_mining_config.unwrap()
|
.server.stratum_mining_config.unwrap()
|
||||||
|
@ -93,23 +107,14 @@ impl NetworkTab for NetworkMining {
|
||||||
return;
|
return;
|
||||||
} else if Node::is_stratum_server_starting() {
|
} else if Node::is_stratum_server_starting() {
|
||||||
// Show loading spinner when mining server is 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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show stratum mining server info.
|
// Show stratum mining server info.
|
||||||
ui.vertical_centered_justified(|ui| {
|
View::sub_title(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
|
||||||
View::sub_header(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
|
@ -118,11 +123,12 @@ impl NetworkTab for NetworkMining {
|
||||||
[true, false, true, false]);
|
[true, false, true, false]);
|
||||||
});
|
});
|
||||||
columns[1].vertical_centered(|ui| {
|
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()
|
let wallet_address = Settings::node_config_to_read()
|
||||||
.members.clone()
|
.members.clone()
|
||||||
.server.stratum_mining_config.unwrap()
|
.server.stratum_mining_config.unwrap()
|
||||||
.wallet_listener_url;
|
.wallet_listener_url
|
||||||
|
.replace("http://", "");
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
wallet_address,
|
wallet_address,
|
||||||
t!("network_mining.wallet"),
|
t!("network_mining.wallet"),
|
||||||
|
@ -132,11 +138,7 @@ impl NetworkTab for NetworkMining {
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show network info.
|
// Show network info.
|
||||||
ui.vertical_centered_justified(|ui| {
|
View::sub_title(ui, format!("{} {}", POLYGON, t!("network.self")));
|
||||||
View::sub_header(ui, format!("{} {}", POLYGON, t!("network.self")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
|
|
||||||
ui.columns(3, |columns| {
|
ui.columns(3, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
let difficulty = if stratum_stats.network_difficulty > 0 {
|
let difficulty = if stratum_stats.network_difficulty > 0 {
|
||||||
|
@ -162,24 +164,20 @@ impl NetworkTab for NetworkMining {
|
||||||
});
|
});
|
||||||
columns[2].vertical_centered(|ui| {
|
columns[2].vertical_centered(|ui| {
|
||||||
let hashrate = if stratum_stats.network_hashrate > 0.0 {
|
let hashrate = if stratum_stats.network_hashrate > 0.0 {
|
||||||
stratum_stats.network_hashrate.to_string()
|
format!("{:.*}", 2, stratum_stats.network_hashrate)
|
||||||
} else {
|
} else {
|
||||||
"-".into()
|
"-".into()
|
||||||
};
|
};
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
hashrate,
|
hashrate,
|
||||||
t!("network_mining.hashrate"),
|
t!("network_mining.hashrate", "bits" => stratum_stats.edge_bits),
|
||||||
[false, true, false, true]);
|
[false, true, false, true]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show mining info.
|
// Show mining info.
|
||||||
ui.vertical_centered_justified(|ui| {
|
View::sub_title(ui, format!("{} {}", CPU, t!("network_mining.miners")));
|
||||||
View::sub_header(ui, format!("{} {}", CPU, t!("network_mining.miners")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
|
@ -197,9 +195,32 @@ impl NetworkTab for NetworkMining {
|
||||||
});
|
});
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show miners info.
|
// Show workers stats or info text when possible.
|
||||||
if !stratum_stats.worker_stats.is_empty() {
|
let workers_size = stratum_stats.worker_stats.len();
|
||||||
//TODO: miners workers
|
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 {
|
} else if ui.available_height() > 142.0 {
|
||||||
View::center_content(ui, 142.0, |ui| {
|
View::center_content(ui, 142.0, |ui| {
|
||||||
ui.label(RichText::new(t!("network_mining.info", "settings" => FADERS))
|
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.
|
// limitations under the License.
|
||||||
|
|
||||||
use eframe::epaint::Stroke;
|
use eframe::epaint::Stroke;
|
||||||
use egui::{Color32, RichText, Rounding, ScrollArea};
|
use egui::{RichText, Rounding, ScrollArea};
|
||||||
use grin_servers::PeerStats;
|
use grin_servers::PeerStats;
|
||||||
|
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
|
@ -48,11 +48,8 @@ impl NetworkTab for NetworkNode {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
.auto_shrink([false; 2])
|
.auto_shrink([false; 2])
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
// Show header stats
|
// Show header info.
|
||||||
ui.vertical_centered_justified(|ui| {
|
View::sub_title(ui, format!("{} {}", FLOW_ARROW, t!("network_node.header")));
|
||||||
View::sub_header(ui, format!("{} {}", FLOW_ARROW, t!("network_node.header")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
|
@ -82,13 +79,10 @@ impl NetworkTab for NetworkNode {
|
||||||
[false, false, false, true]);
|
[false, false, false, true]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show block stats
|
// Show block info.
|
||||||
ui.add_space(4.0);
|
View::sub_title(ui, format!("{} {}", CUBE, t!("network_node.block")));
|
||||||
ui.vertical_centered_justified(|ui| {
|
|
||||||
View::sub_header(ui, format!("{} {}", CUBE, t!("network_node.block")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
View::rounded_box(ui,
|
View::rounded_box(ui,
|
||||||
|
@ -118,13 +112,10 @@ impl NetworkTab for NetworkNode {
|
||||||
[false, false, false, true]);
|
[false, false, false, true]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show data stats
|
// Show data info.
|
||||||
ui.add_space(4.0);
|
View::sub_title(ui, format!("{} {}", SHARE_NETWORK, t!("network_node.data")));
|
||||||
ui.vertical_centered_justified(|ui| {
|
|
||||||
View::sub_header(ui, format!("{} {}", SHARE_NETWORK, t!("network_node.data")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered(|ui| {
|
columns[0].vertical_centered(|ui| {
|
||||||
let tx_stat = match &stats.tx_stats {
|
let tx_stat = match &stats.tx_stats {
|
||||||
|
@ -165,15 +156,11 @@ impl NetworkTab for NetworkNode {
|
||||||
[false, false, false, true]);
|
[false, false, false, true]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
ui.add_space(4.0);
|
||||||
|
|
||||||
// Show peers stats when available
|
// Show peer stats when available.
|
||||||
if stats.peer_count > 0 {
|
if stats.peer_count > 0 {
|
||||||
ui.add_space(4.0);
|
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
|
||||||
ui.vertical_centered_justified(|ui| {
|
|
||||||
View::sub_header(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
|
|
||||||
});
|
|
||||||
ui.add_space(4.0);
|
|
||||||
|
|
||||||
for index in 0..stats.peer_stats.len() {
|
for index in 0..stats.peer_stats.len() {
|
||||||
let ps = stats.peer_stats.get(index).unwrap();
|
let ps = stats.peer_stats.get(index).unwrap();
|
||||||
let rounding = if stats.peer_count == 1 {
|
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]) {
|
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let mut rect = ui.available_rect_before_wrap();
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
rect.set_height(77.0);
|
rect.set_height(78.0);
|
||||||
|
|
||||||
ui.painter().rect(
|
ui.painter().rect(
|
||||||
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 },
|
sw: if rounding[1] { 8.0 } else { 0.0 },
|
||||||
se: 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 }
|
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)
|
.color(Colors::GRAY)
|
||||||
.size(16.0));
|
.size(16.0));
|
||||||
});
|
});
|
||||||
ui.add_space(2.0);
|
ui.add_space(3.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add space after last item
|
// Add space after last item
|
||||||
|
|
|
@ -18,7 +18,7 @@ use egui::epaint::text::TextWrapping;
|
||||||
use egui::text::{LayoutJob, TextFormat};
|
use egui::text::{LayoutJob, TextFormat};
|
||||||
|
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
use crate::gui::icons::{CHECK_SQUARE, SQUARE};
|
use crate::gui::icons::{CHECK_SQUARE, CIRCLE, RADIO_BUTTON, SQUARE};
|
||||||
|
|
||||||
pub struct View;
|
pub struct View;
|
||||||
|
|
||||||
|
@ -54,19 +54,23 @@ impl View {
|
||||||
ui.label(job);
|
ui.label(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sub-header with uppercase characters and more lighter color.
|
/// Draw horizontally centered sub-title with space below.
|
||||||
pub fn sub_header(ui: &mut egui::Ui, text: String) {
|
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.label(RichText::new(text.to_uppercase()).size(16.0).color(Colors::TEXT));
|
||||||
|
});
|
||||||
|
ui.add_space(4.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporary button click optimization for touch screens.
|
/// Temporary button click optimization for touch screens.
|
||||||
fn on_button_click(ui: &mut egui::Ui, resp: Response, action: impl FnOnce()) {
|
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
|
// 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();
|
ui.input_mut().pointer = PointerState::default();
|
||||||
}
|
}
|
||||||
// Call click action if button is clicked or drag released
|
// 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)();
|
(action)();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -80,7 +84,7 @@ impl View {
|
||||||
let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE);
|
let wt = RichText::new(icon.to_string()).size(24.0).color(Colors::TITLE);
|
||||||
let br = Button::new(wt)
|
let br = Button::new(wt)
|
||||||
.fill(Colors::TRANSPARENT)
|
.fill(Colors::TRANSPARENT)
|
||||||
.ui(ui).interact(Sense::click_and_drag());
|
.ui(ui);
|
||||||
|
|
||||||
Self::on_button_click(ui, br, action);
|
Self::on_button_click(ui, br, action);
|
||||||
});
|
});
|
||||||
|
@ -106,7 +110,7 @@ impl View {
|
||||||
let br = Button::new(wt)
|
let br = Button::new(wt)
|
||||||
.stroke(stroke)
|
.stroke(stroke)
|
||||||
.fill(color)
|
.fill(color)
|
||||||
.ui(ui).interact(Sense::click_and_drag());
|
.ui(ui);
|
||||||
|
|
||||||
Self::on_button_click(ui, br, action);
|
Self::on_button_click(ui, br, action);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +121,7 @@ impl View {
|
||||||
let br = Button::new(wt)
|
let br = Button::new(wt)
|
||||||
.stroke(Self::DEFAULT_STROKE)
|
.stroke(Self::DEFAULT_STROKE)
|
||||||
.fill(fill_color)
|
.fill(fill_color)
|
||||||
.ui(ui).interact(Sense::click_and_drag());
|
.ui(ui);
|
||||||
|
|
||||||
Self::on_button_click(ui, br, action);
|
Self::on_button_click(ui, br, action);
|
||||||
}
|
}
|
||||||
|
@ -146,8 +150,11 @@ impl View {
|
||||||
// Draw box content.
|
// Draw box content.
|
||||||
let content_resp = ui.allocate_ui_at_rect(rect, |ui| {
|
let content_resp = ui.allocate_ui_at_rect(rect, |ui| {
|
||||||
ui.vertical_centered_justified(|ui| {
|
ui.vertical_centered_justified(|ui| {
|
||||||
|
ui.add_space(2.0);
|
||||||
|
|
||||||
|
ui.scope(|ui| {
|
||||||
// Correct vertical spacing between items.
|
// 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.
|
// Draw box value.
|
||||||
let mut job = LayoutJob::single_section(value, TextFormat {
|
let mut job = LayoutJob::single_section(value, TextFormat {
|
||||||
|
@ -166,6 +173,9 @@ impl View {
|
||||||
// Draw box label.
|
// Draw box label.
|
||||||
ui.label(RichText::new(label).color(Colors::GRAY).size(15.0));
|
ui.label(RichText::new(label).color(Colors::GRAY).size(15.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui.add_space(2.0);
|
||||||
|
});
|
||||||
}).response;
|
}).response;
|
||||||
|
|
||||||
// Setup background shape to be painted behind box content.
|
// 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);
|
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()) {
|
pub fn checkbox(ui: &mut egui::Ui, checked: bool, text: String, callback: impl FnOnce()) {
|
||||||
let text_value = match checked {
|
let (text_value, color) = match checked {
|
||||||
true => { format!("{} {}", CHECK_SQUARE, text)}
|
true => { (format!("{} {}", CHECK_SQUARE, text), Colors::BUTTON) }
|
||||||
false => { format!("{} {}", SQUARE, text)}
|
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)
|
let br = Button::new(wt)
|
||||||
.frame(false)
|
.frame(false)
|
||||||
.stroke(Stroke::NONE)
|
.stroke(Stroke::NONE)
|
||||||
.fill(Colors::TRANSPARENT)
|
.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);
|
Self::on_button_click(ui, br, callback);
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ impl Node {
|
||||||
server.start_stratum_server(stratum_config);
|
server.start_stratum_server(stratum_config);
|
||||||
|
|
||||||
// Wait for mining server to start and update status.
|
// 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);
|
NODE_STATE.start_stratum_server.store(false, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue