feat: manage XvB like a new process

feat: maj TODO
fix: use Vec2 instead of separating height and witdh as args in functions
feat: status of XvB process
feat: button to autostart XvB process into Gupax Tab
feat: autostart XvB if button is checked
feat: buttons to start/stop/restart XvB process in XvB Tab
feat: check token and address inputs before allowing to start XvB
feat: add description to buttons when hovering
fix: adjust test
feat: function to verify if token exist on XvB API
clippy auto and manual fix
This commit is contained in:
Louis-Marie Baer 2024-03-12 12:25:34 +01:00
parent bbb61d8268
commit 74355605e9
22 changed files with 934 additions and 616 deletions

View file

@ -12,19 +12,20 @@
- [x] link to website - [x] link to website
- [ ] message overing explaining registration and needs to read the rules. - [ ] message overing explaining registration and needs to read the rules.
- [ ] token input - [ ] token input
- [ ] information - [ ] hero checkbox
- [ ] status of h/s received by the raffle, authenfication by token. - [ ] log section
- [ ] status of h/s received by the raffle, authentication by token.
- [ ] status of 1h and 24h average h/s sent to raffle from this instance - [ ] status of 1h and 24h average h/s sent to raffle from this instance
- [ ] number of failures - [ ] number of failures
- [ ] log section - [ ] round type in
- [ ] winner of round - [ ] win or loose
- [ ] round in - [ ] new process for XvB
- [ ] hero checkbox - [x] status process XvB
- [x] status process XvB
- [x] public information from [API](https://xmrvsbeast.com/p2pool/stats) - [x] public information from [API](https://xmrvsbeast.com/p2pool/stats)
- [ ] if not enough hashrate for min round and share acquirement OR no share acquired, node destination for xmrig is only p2pool. - [x] stop, start, restart buttons
- [ ] if share acquired and enough hashrate to keep up round min hashrate and share acquirement, switch node destination for xmrig between p2pool and raffle giving raffle minimum round requirement + buffer. - [x] button to autostart
- [ ] if hero checked, give maximum hasrate to raffle while keeping enough for p2pool. - [ ] distribute hashrate conforming to the algorithm.
- [ ] output log to console in XvB tab
- [ ] edit metadata of project - [ ] edit metadata of project
- [ ] cargo package metadata - [ ] cargo package metadata
- [ ] pgp signatures - [ ] pgp signatures

View file

@ -35,19 +35,25 @@ impl eframe::App for App {
let xmrig_is_waiting = xmrig.is_waiting(); let xmrig_is_waiting = xmrig.is_waiting();
let xmrig_state = xmrig.state; let xmrig_state = xmrig.state;
drop(xmrig); drop(xmrig);
debug!("App | Locking and collecting XvB state...");
let xvb = lock!(self.xvb);
let xvb_is_alive = xvb.is_alive();
let xvb_is_waiting = xvb.is_waiting();
let xvb_state = xvb.state;
drop(xvb);
// This sets the top level Ui dimensions. // This sets the top level Ui dimensions.
// Used as a reference for other uis. // Used as a reference for other uis.
debug!("App | Setting width/height"); debug!("App | Setting width/height");
CentralPanel::default().show(ctx, |ui| { CentralPanel::default().show(ctx, |ui| {
let available_width = ui.available_width(); let available_width = ui.available_width();
if self.width != available_width { if self.size.x != available_width {
self.width = available_width; self.size.x = available_width;
if self.now.elapsed().as_secs() > 5 { if self.now.elapsed().as_secs() > 5 {
self.must_resize = true; self.must_resize = true;
} }
}; };
self.height = ui.available_height(); self.size.y = ui.available_height();
}); });
self.resize(ctx); self.resize(ctx);
@ -77,12 +83,15 @@ impl eframe::App for App {
ctx, ctx,
p2pool_state, p2pool_state,
xmrig_state, xmrig_state,
xvb_state,
&key, &key,
wants_input, wants_input,
p2pool_is_waiting, p2pool_is_waiting,
xmrig_is_waiting, xmrig_is_waiting,
xvb_is_waiting,
p2pool_is_alive, p2pool_is_alive,
xmrig_is_alive, xmrig_is_alive,
xvb_is_alive,
); );
self.middle_panel(ctx, frame, key, p2pool_is_alive, xmrig_is_alive); self.middle_panel(ctx, frame, key, p2pool_is_alive, xmrig_is_alive);
} }

View file

@ -37,6 +37,7 @@ use crate::APP_DEFAULT_WIDTH;
use crate::GUPAX_VERSION; use crate::GUPAX_VERSION;
use crate::OS; use crate::OS;
use eframe::CreationContext; use eframe::CreationContext;
use egui::vec2;
use egui::Vec2; use egui::Vec2;
use log::debug; use log::debug;
use log::error; use log::error;
@ -62,8 +63,7 @@ pub mod resize;
pub struct App { pub struct App {
// Misc state // Misc state
pub tab: Tab, // What tab are we on? pub tab: Tab, // What tab are we on?
pub width: f32, // Top-level width pub size: Vec2, // Top-level width and Top-level height
pub height: f32, // Top-level height
// Alpha (transparency) // Alpha (transparency)
// This value is used to incrementally increase/decrease // This value is used to incrementally increase/decrease
// the transparency when resizing. Basically, it fades // the transparency when resizing. Basically, it fades
@ -102,6 +102,7 @@ pub struct App {
pub pub_sys: Arc<Mutex<Sys>>, // [Sys] state, read by [Status], mutated by [Helper] pub pub_sys: Arc<Mutex<Sys>>, // [Sys] state, read by [Status], mutated by [Helper]
pub p2pool: Arc<Mutex<Process>>, // [P2Pool] process state pub p2pool: Arc<Mutex<Process>>, // [P2Pool] process state
pub xmrig: Arc<Mutex<Process>>, // [XMRig] process state pub xmrig: Arc<Mutex<Process>>, // [XMRig] process state
pub xvb: Arc<Mutex<Process>>, // [Xvb] process state
pub p2pool_api: Arc<Mutex<PubP2poolApi>>, // Public ready-to-print P2Pool API made by the "helper" thread pub p2pool_api: Arc<Mutex<PubP2poolApi>>, // Public ready-to-print P2Pool API made by the "helper" thread
pub xmrig_api: Arc<Mutex<PubXmrigApi>>, // Public ready-to-print XMRig API made by the "helper" thread pub xmrig_api: Arc<Mutex<PubXmrigApi>>, // Public ready-to-print XMRig API made by the "helper" thread
pub xvb_api: Arc<Mutex<PubXvbApi>>, // Public XvB API pub xvb_api: Arc<Mutex<PubXvbApi>>, // Public XvB API
@ -181,6 +182,11 @@ impl App {
String::new(), String::new(),
PathBuf::new() PathBuf::new()
)); ));
let xvb = arc_mut!(Process::new(
ProcessName::Xvb,
String::new(),
PathBuf::new()
));
let p2pool_api = arc_mut!(PubP2poolApi::new()); let p2pool_api = arc_mut!(PubP2poolApi::new());
let xmrig_api = arc_mut!(PubXmrigApi::new()); let xmrig_api = arc_mut!(PubXmrigApi::new());
let xvb_api = arc_mut!(PubXvbApi::new()); let xvb_api = arc_mut!(PubXvbApi::new());
@ -220,8 +226,7 @@ impl App {
let mut app = Self { let mut app = Self {
tab: Tab::default(), tab: Tab::default(),
ping: arc_mut!(Ping::new()), ping: arc_mut!(Ping::new()),
width: APP_DEFAULT_WIDTH, size: vec2(APP_DEFAULT_WIDTH, APP_DEFAULT_HEIGHT),
height: APP_DEFAULT_HEIGHT,
must_resize: false, must_resize: false,
og: arc_mut!(State::new()), og: arc_mut!(State::new()),
state: State::new(), state: State::new(),
@ -244,6 +249,7 @@ impl App {
pub_sys.clone(), pub_sys.clone(),
p2pool.clone(), p2pool.clone(),
xmrig.clone(), xmrig.clone(),
xvb.clone(),
p2pool_api.clone(), p2pool_api.clone(),
xmrig_api.clone(), xmrig_api.clone(),
xvb_api.clone(), xvb_api.clone(),
@ -253,6 +259,7 @@ impl App {
)), )),
p2pool, p2pool,
xmrig, xmrig,
xvb,
p2pool_api, p2pool_api,
xvb_api, xvb_api,
xmrig_api, xmrig_api,

View file

@ -14,38 +14,45 @@ use egui::TextStyle::Name;
use egui::*; use egui::*;
use log::debug; use log::debug;
use crate::helper::ProcessState::*;
use crate::{app::Tab, utils::constants::SPACE}; use crate::{app::Tab, utils::constants::SPACE};
impl crate::app::App { impl crate::app::App {
#[allow(clippy::too_many_arguments)]
pub fn bottom_panel( pub fn bottom_panel(
&mut self, &mut self,
ctx: &egui::Context, ctx: &egui::Context,
p2pool_state: ProcessState, p2pool_state: ProcessState,
xmrig_state: ProcessState, xmrig_state: ProcessState,
xvb_state: ProcessState,
key: &KeyPressed, key: &KeyPressed,
wants_input: bool, wants_input: bool,
p2pool_is_waiting: bool, p2pool_is_waiting: bool,
xmrig_is_waiting: bool, xmrig_is_waiting: bool,
xvb_is_waiting: bool,
p2pool_is_alive: bool, p2pool_is_alive: bool,
xmrig_is_alive: bool, xmrig_is_alive: bool,
xvb_is_alive: bool,
) { ) {
// Bottom: app info + state/process buttons // Bottom: app info + state/process buttons
debug!("App | Rendering BOTTOM bar"); debug!("App | Rendering BOTTOM bar");
TopBottomPanel::bottom("bottom").show(ctx, |ui| { TopBottomPanel::bottom("bottom").show(ctx, |ui| {
let height = self.height / 22.0; let height = self.size.y / 22.0;
// let width = self.size.x;
ui.style_mut().override_text_style = Some(Name("Bottom".into())); ui.style_mut().override_text_style = Some(Name("Bottom".into()));
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.group(|ui| { ui.group(|ui| {
let width = ((self.width / 2.0) / 4.0) - (SPACE * 2.0); let width = ((self.size.x / 2.0) / 4.0) - (SPACE * 2.0);
let size = vec2(width, height);
// [Gupax Version] // [Gupax Version]
// Is yellow if the user updated and should (but isn't required to) restart. // Is yellow if the user updated and should (but isn't required to) restart.
match *lock!(self.restart) { match *lock!(self.restart) {
Restart::Yes => ui Restart::Yes => ui
.add_sized( .add_sized(
[width, height], size,
Label::new(RichText::new(&self.name_version).color(YELLOW)), Label::new(RichText::new(&self.name_version).color(YELLOW)),
) )
.on_hover_text(GUPAX_SHOULD_RESTART), .on_hover_text(GUPAX_SHOULD_RESTART),
_ => ui.add_sized([width, height], Label::new(&self.name_version)), _ => ui.add_sized(size, Label::new(&self.name_version)),
}; };
ui.separator(); ui.separator();
// [OS] // [OS]
@ -54,95 +61,79 @@ impl crate::app::App {
// [App] is initialized, so no reason to check here. // [App] is initialized, so no reason to check here.
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
if self.admin { if self.admin {
ui.add_sized([width, height], Label::new(self.os)); ui.add_sized(size, Label::new(self.os));
} else { } else {
ui.add_sized( ui.add_sized(size, Label::new(RichText::new(self.os).color(RED)))
[width, height],
Label::new(RichText::new(self.os).color(RED)),
)
.on_hover_text(WINDOWS_NOT_ADMIN); .on_hover_text(WINDOWS_NOT_ADMIN);
} }
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
ui.add_sized([width, height], Label::new(self.os)); // [P2Pool/XMRig/XvB] Status
ui.add_sized(size, Label::new(self.os));
ui.separator(); ui.separator();
// [P2Pool/XMRig] Status status_p2pool(p2pool_state, ui, size);
use crate::helper::ProcessState::*;
match p2pool_state {
Alive => ui
.add_sized(
[width, height],
Label::new(RichText::new("P2Pool ⏺").color(GREEN)),
)
.on_hover_text(P2POOL_ALIVE),
Dead => ui
.add_sized(
[width, height],
Label::new(RichText::new("P2Pool ⏺").color(GRAY)),
)
.on_hover_text(P2POOL_DEAD),
Failed => ui
.add_sized(
[width, height],
Label::new(RichText::new("P2Pool ⏺").color(RED)),
)
.on_hover_text(P2POOL_FAILED),
Syncing => ui
.add_sized(
[width, height],
Label::new(RichText::new("P2Pool ⏺").color(ORANGE)),
)
.on_hover_text(P2POOL_SYNCING),
Middle | Waiting | NotMining => ui
.add_sized(
[width, height],
Label::new(RichText::new("P2Pool ⏺").color(YELLOW)),
)
.on_hover_text(P2POOL_MIDDLE),
};
ui.separator(); ui.separator();
match xmrig_state { status_xmrig(xmrig_state, ui, size);
Alive => ui ui.separator();
.add_sized( status_xvb(xvb_state, ui, size);
[width, height],
Label::new(RichText::new("XMRig ⏺").color(GREEN)),
)
.on_hover_text(XMRIG_ALIVE),
Dead => ui
.add_sized(
[width, height],
Label::new(RichText::new("XMRig ⏺").color(GRAY)),
)
.on_hover_text(XMRIG_DEAD),
Failed => ui
.add_sized(
[width, height],
Label::new(RichText::new("XMRig ⏺").color(RED)),
)
.on_hover_text(XMRIG_FAILED),
NotMining => ui
.add_sized(
[width, height],
Label::new(RichText::new("XMRig ⏺").color(ORANGE)),
)
.on_hover_text(XMRIG_NOT_MINING),
Middle | Waiting | Syncing => ui
.add_sized(
[width, height],
Label::new(RichText::new("XMRig ⏺").color(YELLOW)),
)
.on_hover_text(XMRIG_MIDDLE),
};
}); });
// [Save/Reset]
ui.with_layout(Layout::right_to_left(Align::RIGHT), |ui| { ui.with_layout(Layout::right_to_left(Align::RIGHT), |ui| {
let width = (ui.available_width() / 3.0) - (SPACE * 3.0); let width = (ui.available_width() / 3.0) - (SPACE * 3.0);
let size = vec2(width, height);
// [Save/Reset]
self.save_reset_ui(ui, size, key, wants_input);
// [Simple/Advanced] + [Start/Stop/Restart]
match self.tab {
Tab::Status => {
self.status_submenu(ui, height);
}
Tab::Gupax => {
self.gupax_submenu(ui, height);
}
Tab::P2pool => {
self.p2pool_submenu(ui, size);
self.p2pool_run_actions(
ui,
height,
p2pool_is_waiting,
p2pool_is_alive,
wants_input,
key,
);
}
Tab::Xmrig => {
self.xmrig_submenu(ui, size);
self.xmrig_run_actions(
ui,
height,
xmrig_is_waiting,
xmrig_is_alive,
key,
wants_input,
);
}
Tab::Xvb => self.xvb_run_actions(
ui,
height,
xvb_is_waiting,
xvb_is_alive,
key,
wants_input,
),
Tab::About => {}
}
});
});
});
}
fn save_reset_ui(&mut self, ui: &mut Ui, size: Vec2, key: &KeyPressed, wants_input: bool) {
ui.group(|ui| { ui.group(|ui| {
ui.set_enabled(self.diff); ui.set_enabled(self.diff);
let width = width / 2.0; let width = size.x / 2.0;
let size = vec2(width, size.y);
if key.is_r() && !wants_input && self.diff if key.is_r() && !wants_input && self.diff
|| ui || ui
.add_sized([width, height], Button::new("Reset")) .add_sized(size, Button::new("Reset"))
.on_hover_text("Reset changes") .on_hover_text("Reset changes")
.clicked() .clicked()
{ {
@ -151,12 +142,13 @@ impl crate::app::App {
self.state.gupax = og.gupax; self.state.gupax = og.gupax;
self.state.p2pool = og.p2pool; self.state.p2pool = og.p2pool;
self.state.xmrig = og.xmrig; self.state.xmrig = og.xmrig;
self.state.xvb = og.xvb;
self.node_vec = self.og_node_vec.clone(); self.node_vec = self.og_node_vec.clone();
self.pool_vec = self.og_pool_vec.clone(); self.pool_vec = self.og_pool_vec.clone();
} }
if key.is_s() && !wants_input && self.diff if key.is_s() && !wants_input && self.diff
|| ui || ui
.add_sized([width, height], Button::new("Save")) .add_sized(size, Button::new("Save"))
.on_hover_text("Save changes") .on_hover_text("Save changes")
.clicked() .clicked()
{ {
@ -167,6 +159,7 @@ impl crate::app::App {
og.gupax = self.state.gupax.clone(); og.gupax = self.state.gupax.clone();
og.p2pool = self.state.p2pool.clone(); og.p2pool = self.state.p2pool.clone();
og.xmrig = self.state.xmrig.clone(); og.xmrig = self.state.xmrig.clone();
og.xvb = self.state.xvb.clone();
} }
Err(e) => { Err(e) => {
self.error_state.set( self.error_state.set(
@ -194,15 +187,14 @@ impl crate::app::App {
}; };
} }
}); });
}
// [Simple/Advanced] + [Start/Stop/Restart] fn status_submenu(&mut self, ui: &mut Ui, height: f32) {
match self.tab {
Tab::Status => {
ui.group(|ui| { ui.group(|ui| {
let width = (ui.available_width() / 3.0) - 14.0; let width = (ui.available_width() / 3.0) - 14.0;
let size = vec2(width, height);
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new( SelectableLabel::new(
self.state.status.submenu == Submenu::Benchmarks, self.state.status.submenu == Submenu::Benchmarks,
"Benchmarks", "Benchmarks",
@ -216,11 +208,8 @@ impl crate::app::App {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new( SelectableLabel::new(self.state.status.submenu == Submenu::P2pool, "P2Pool"),
self.state.status.submenu == Submenu::P2pool,
"P2Pool",
),
) )
.on_hover_text(STATUS_SUBMENU_P2POOL) .on_hover_text(STATUS_SUBMENU_P2POOL)
.clicked() .clicked()
@ -230,7 +219,7 @@ impl crate::app::App {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new( SelectableLabel::new(
self.state.status.submenu == Submenu::Processes, self.state.status.submenu == Submenu::Processes,
"Processes", "Processes",
@ -243,12 +232,13 @@ impl crate::app::App {
} }
}); });
} }
Tab::Gupax => { fn gupax_submenu(&mut self, ui: &mut Ui, height: f32) {
ui.group(|ui| { ui.group(|ui| {
let width = (ui.available_width() / 2.0) - 10.5; let width = (ui.available_width() / 2.0) - 10.5;
let size = vec2(width, height);
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(!self.state.gupax.simple, "Advanced"), SelectableLabel::new(!self.state.gupax.simple, "Advanced"),
) )
.on_hover_text(GUPAX_ADVANCED) .on_hover_text(GUPAX_ADVANCED)
@ -259,7 +249,7 @@ impl crate::app::App {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.state.gupax.simple, "Simple"), SelectableLabel::new(self.state.gupax.simple, "Simple"),
) )
.on_hover_text(GUPAX_SIMPLE) .on_hover_text(GUPAX_SIMPLE)
@ -269,12 +259,13 @@ impl crate::app::App {
} }
}); });
} }
Tab::P2pool => { fn p2pool_submenu(&mut self, ui: &mut Ui, size: Vec2) {
ui.group(|ui| { ui.group(|ui| {
let width = width / 1.5; let width = size.x / 1.5;
let size = vec2(width, size.y);
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(!self.state.p2pool.simple, "Advanced"), SelectableLabel::new(!self.state.p2pool.simple, "Advanced"),
) )
.on_hover_text(P2POOL_ADVANCED) .on_hover_text(P2POOL_ADVANCED)
@ -285,7 +276,7 @@ impl crate::app::App {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.state.p2pool.simple, "Simple"), SelectableLabel::new(self.state.p2pool.simple, "Simple"),
) )
.on_hover_text(P2POOL_SIMPLE) .on_hover_text(P2POOL_SIMPLE)
@ -294,21 +285,32 @@ impl crate::app::App {
self.state.p2pool.simple = true; self.state.p2pool.simple = true;
} }
}); });
}
fn p2pool_run_actions(
&mut self,
ui: &mut Ui,
height: f32,
p2pool_is_waiting: bool,
p2pool_is_alive: bool,
wants_input: bool,
key: &KeyPressed,
) {
ui.group(|ui| { ui.group(|ui| {
let width = (ui.available_width() / 3.0) - 5.0; let width = (ui.available_width() / 3.0) - 5.0;
let size = vec2(width, height);
if p2pool_is_waiting { if p2pool_is_waiting {
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(P2POOL_MIDDLE); .on_disabled_hover_text(P2POOL_MIDDLE);
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(P2POOL_MIDDLE); .on_disabled_hover_text(P2POOL_MIDDLE);
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(P2POOL_MIDDLE); .on_disabled_hover_text(P2POOL_MIDDLE);
}); });
} else if p2pool_is_alive { } else if p2pool_is_alive {
if key.is_up() && !wants_input if key.is_up() && !wants_input
|| ui || ui
.add_sized([width, height], Button::new("")) .add_sized(size, Button::new(""))
.on_hover_text("Restart P2Pool") .on_hover_text("Restart P2Pool")
.clicked() .clicked()
{ {
@ -323,21 +325,21 @@ impl crate::app::App {
} }
if key.is_down() && !wants_input if key.is_down() && !wants_input
|| ui || ui
.add_sized([width, height], Button::new("")) .add_sized(size, Button::new(""))
.on_hover_text("Stop P2Pool") .on_hover_text("Stop P2Pool")
.clicked() .clicked()
{ {
Helper::stop_p2pool(&self.helper); Helper::stop_p2pool(&self.helper);
} }
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Start P2Pool"); .on_disabled_hover_text("Start P2Pool");
}); });
} else { } else {
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Restart P2Pool"); .on_disabled_hover_text("Restart P2Pool");
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Stop P2Pool"); .on_disabled_hover_text("Stop P2Pool");
}); });
// Check if address is okay before allowing to start. // Check if address is okay before allowing to start.
@ -359,10 +361,7 @@ impl crate::app::App {
let color = if ui_enabled { GREEN } else { RED }; let color = if ui_enabled { GREEN } else { RED };
if (ui_enabled && key.is_up() && !wants_input) if (ui_enabled && key.is_up() && !wants_input)
|| ui || ui
.add_sized( .add_sized(size, Button::new(RichText::new("").color(color)))
[width, height],
Button::new(RichText::new("").color(color)),
)
.on_hover_text("Start P2Pool") .on_hover_text("Start P2Pool")
.on_disabled_hover_text(text) .on_disabled_hover_text(text)
.clicked() .clicked()
@ -379,12 +378,13 @@ impl crate::app::App {
} }
}); });
} }
Tab::Xmrig => { fn xmrig_submenu(&mut self, ui: &mut Ui, size: Vec2) {
ui.group(|ui| { ui.group(|ui| {
let width = width / 1.5; let width = size.x / 1.5;
let size = vec2(width, size.y);
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(!self.state.xmrig.simple, "Advanced"), SelectableLabel::new(!self.state.xmrig.simple, "Advanced"),
) )
.on_hover_text(XMRIG_ADVANCED) .on_hover_text(XMRIG_ADVANCED)
@ -395,7 +395,7 @@ impl crate::app::App {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.state.xmrig.simple, "Simple"), SelectableLabel::new(self.state.xmrig.simple, "Simple"),
) )
.on_hover_text(XMRIG_SIMPLE) .on_hover_text(XMRIG_SIMPLE)
@ -404,21 +404,32 @@ impl crate::app::App {
self.state.xmrig.simple = true; self.state.xmrig.simple = true;
} }
}); });
}
fn xmrig_run_actions(
&mut self,
ui: &mut Ui,
height: f32,
xmrig_is_waiting: bool,
xmrig_is_alive: bool,
key: &KeyPressed,
wants_input: bool,
) {
ui.group(|ui| { ui.group(|ui| {
let width = (ui.available_width() / 3.0) - 5.0; let width = (ui.available_width() / 3.0) - 5.0;
let size = vec2(width, height);
if xmrig_is_waiting { if xmrig_is_waiting {
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XMRIG_MIDDLE); .on_disabled_hover_text(XMRIG_MIDDLE);
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XMRIG_MIDDLE); .on_disabled_hover_text(XMRIG_MIDDLE);
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XMRIG_MIDDLE); .on_disabled_hover_text(XMRIG_MIDDLE);
}); });
} else if xmrig_is_alive { } else if xmrig_is_alive {
if key.is_up() && !wants_input if key.is_up() && !wants_input
|| ui || ui
.add_sized([width, height], Button::new("")) .add_sized(size, Button::new(""))
.on_hover_text("Restart XMRig") .on_hover_text("Restart XMRig")
.clicked() .clicked()
{ {
@ -438,7 +449,7 @@ impl crate::app::App {
} }
if key.is_down() && !wants_input if key.is_down() && !wants_input
|| ui || ui
.add_sized([width, height], Button::new("")) .add_sized(size, Button::new(""))
.on_hover_text("Stop XMRig") .on_hover_text("Stop XMRig")
.clicked() .clicked()
{ {
@ -450,14 +461,14 @@ impl crate::app::App {
} }
} }
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Start XMRig"); .on_disabled_hover_text("Start XMRig");
}); });
} else { } else {
ui.add_enabled_ui(false, |ui| { ui.add_enabled_ui(false, |ui| {
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Restart XMRig"); .on_disabled_hover_text("Restart XMRig");
ui.add_sized([width, height], Button::new("")) ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Stop XMRig"); .on_disabled_hover_text("Stop XMRig");
}); });
let mut text = String::new(); let mut text = String::new();
@ -465,9 +476,8 @@ impl crate::app::App {
if !Gupax::path_is_file(&self.state.gupax.xmrig_path) { if !Gupax::path_is_file(&self.state.gupax.xmrig_path) {
ui_enabled = false; ui_enabled = false;
text = format!("Error: {}", XMRIG_PATH_NOT_FILE); text = format!("Error: {}", XMRIG_PATH_NOT_FILE);
} else if !crate::components::update::check_xmrig_path( } else if !crate::components::update::check_xmrig_path(&self.state.gupax.xmrig_path)
&self.state.gupax.xmrig_path, {
) {
ui_enabled = false; ui_enabled = false;
text = format!("Error: {}", XMRIG_PATH_NOT_VALID); text = format!("Error: {}", XMRIG_PATH_NOT_VALID);
} }
@ -475,10 +485,7 @@ impl crate::app::App {
let color = if ui_enabled { GREEN } else { RED }; let color = if ui_enabled { GREEN } else { RED };
if (ui_enabled && key.is_up() && !wants_input) if (ui_enabled && key.is_up() && !wants_input)
|| ui || ui
.add_sized( .add_sized(size, Button::new(RichText::new("").color(color)))
[width, height],
Button::new(RichText::new("").color(color)),
)
.on_hover_text("Start XMRig") .on_hover_text("Start XMRig")
.on_disabled_hover_text(text) .on_disabled_hover_text(text)
.clicked() .clicked()
@ -500,10 +507,125 @@ impl crate::app::App {
} }
}); });
} }
_ => (), fn xvb_run_actions(
&mut self,
ui: &mut Ui,
height: f32,
xvb_is_waiting: bool,
xvb_is_alive: bool,
key: &KeyPressed,
wants_input: bool,
) {
ui.group(|ui| {
let width = (ui.available_width() / 3.0) - 5.0;
let size = vec2(width, height);
if xvb_is_waiting {
ui.add_enabled_ui(false, |ui| {
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XVB_MIDDLE);
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XVB_MIDDLE);
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text(XVB_MIDDLE);
});
} else if xvb_is_alive {
if key.is_up() && !wants_input
|| ui
.add_sized(size, Button::new(""))
.on_hover_text("Restart Xvb")
.clicked()
{
Helper::restart_xvb(&self.helper, &self.state.xvb, &self.state.p2pool);
} }
if key.is_down() && !wants_input
|| ui
.add_sized(size, Button::new(""))
.on_hover_text("Stop Xvb")
.clicked()
{
Helper::stop_xvb(&self.helper);
}
ui.add_enabled_ui(false, |ui| {
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Start Xvb");
}); });
} else {
ui.add_enabled_ui(false, |ui| {
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Restart Xvb");
ui.add_sized(size, Button::new(""))
.on_disabled_hover_text("Stop Xvb");
}); });
let ui_enabled =
!self.state.p2pool.address.is_empty() && !self.state.xvb.token.is_empty();
ui.set_enabled(ui_enabled);
let color = if ui_enabled { GREEN } else { RED };
if (ui_enabled && key.is_up() && !wants_input)
|| ui
.add_sized(size, Button::new(RichText::new("").color(color)))
.on_hover_text("Start Xvb")
.on_disabled_hover_text(XVB_NOT_CONFIGURED)
.clicked()
{
Helper::start_xvb(&self.helper, &self.state.xvb, &self.state.p2pool);
}
}
}); });
} }
} }
fn status_p2pool(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(GREEN)))
.on_hover_text(P2POOL_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(GRAY)))
.on_hover_text(P2POOL_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(RED)))
.on_hover_text(P2POOL_FAILED),
Syncing => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(ORANGE)))
.on_hover_text(P2POOL_SYNCING),
Middle | Waiting | NotMining => ui
.add_sized(size, Label::new(RichText::new("P2Pool ⏺").color(YELLOW)))
.on_hover_text(P2POOL_MIDDLE),
};
}
fn status_xmrig(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(GREEN)))
.on_hover_text(XMRIG_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(GRAY)))
.on_hover_text(XMRIG_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(RED)))
.on_hover_text(XMRIG_FAILED),
NotMining => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(ORANGE)))
.on_hover_text(XMRIG_NOT_MINING),
Middle | Waiting | Syncing => ui
.add_sized(size, Label::new(RichText::new("XMRig ⏺").color(YELLOW)))
.on_hover_text(XMRIG_MIDDLE),
};
}
fn status_xvb(state: ProcessState, ui: &mut Ui, size: Vec2) {
match state {
Alive => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(GREEN)))
.on_hover_text(XVB_ALIVE),
Dead => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(GRAY)))
.on_hover_text(XVB_DEAD),
Failed => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(RED)))
.on_hover_text(XVB_FAILED),
Middle | Waiting | NotMining | Syncing => ui
.add_sized(size, Label::new(RichText::new("XvB ⏺").color(YELLOW)))
.on_hover_text(XVB_MIDDLE),
};
}

View file

@ -22,8 +22,7 @@ impl Gupax {
file_window: &Arc<Mutex<FileWindow>>, file_window: &Arc<Mutex<FileWindow>>,
error_state: &mut ErrorState, error_state: &mut ErrorState,
restart: &Arc<Mutex<Restart>>, restart: &Arc<Mutex<Restart>>,
width: f32, size: Vec2,
height: f32,
_frame: &mut eframe::Frame, _frame: &mut eframe::Frame,
_ctx: &egui::Context, _ctx: &egui::Context,
ui: &mut egui::Ui, ui: &mut egui::Ui,
@ -32,16 +31,16 @@ impl Gupax {
debug!("Gupax Tab | Rendering [Update] button + progress bar"); debug!("Gupax Tab | Rendering [Update] button + progress bar");
ui.group(|ui| { ui.group(|ui| {
let button = if self.simple { let button = if self.simple {
height / 5.0 size.y / 5.0
} else { } else {
height / 15.0 size.y / 15.0
}; };
let height = if self.simple { let height = if self.simple {
height / 5.0 size.y / 5.0
} else { } else {
height / 10.0 size.y / 10.0
}; };
let width = width - SPACE; let width = size.x - SPACE;
let updating = *lock2!(update, updating); let updating = *lock2!(update, updating);
ui.vertical(|ui| { ui.vertical(|ui| {
// If [Gupax] is being built for a Linux distro, // If [Gupax] is being built for a Linux distro,
@ -68,60 +67,53 @@ impl Gupax {
let msg = format!("{}\n{}{}", *lock2!(update, msg), prog, "%"); let msg = format!("{}\n{}{}", *lock2!(update, msg), prog, "%");
ui.add_sized([width, height * 1.4], Label::new(RichText::new(msg))); ui.add_sized([width, height * 1.4], Label::new(RichText::new(msg)));
let height = height / 2.0; let height = height / 2.0;
let size = vec2(width, height);
if updating { if updating {
ui.add_sized([width, height], Spinner::new().size(height)); ui.add_sized(size, Spinner::new().size(height));
} else { } else {
ui.add_sized([width, height], Label::new("...")); ui.add_sized(size, Label::new("..."));
} }
ui.add_sized( ui.add_sized(size, ProgressBar::new(lock2!(update, prog).round() / 100.0));
[width, height],
ProgressBar::new(lock2!(update, prog).round() / 100.0),
);
}); });
}); });
debug!("Gupax Tab | Rendering bool buttons"); debug!("Gupax Tab | Rendering bool buttons");
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.group(|ui| { ui.group(|ui| {
let width = (width - SPACE * 12.0) / 6.0; let width = (size.x - SPACE * 12.0) / 6.0;
let height = if self.simple { let height = if self.simple {
height / 10.0 size.y / 10.0
} else { } else {
height / 15.0 size.y / 15.0
}; };
let size = vec2(width, height);
ui.style_mut().override_text_style = Some(egui::TextStyle::Small); ui.style_mut().override_text_style = Some(egui::TextStyle::Small);
ui.add_sized( ui.add_sized(
[width, height], size,
Checkbox::new(&mut self.update_via_tor, "Update via Tor"), Checkbox::new(&mut self.update_via_tor, "Update via Tor"),
) )
.on_hover_text(GUPAX_UPDATE_VIA_TOR); .on_hover_text(GUPAX_UPDATE_VIA_TOR);
ui.separator(); ui.separator();
ui.add_sized( ui.add_sized(size, Checkbox::new(&mut self.auto_update, "Auto-Update"))
[width, height],
Checkbox::new(&mut self.auto_update, "Auto-Update"),
)
.on_hover_text(GUPAX_AUTO_UPDATE); .on_hover_text(GUPAX_AUTO_UPDATE);
ui.separator(); ui.separator();
ui.add_sized( ui.add_sized(size, Checkbox::new(&mut self.auto_p2pool, "Auto-P2Pool"))
[width, height],
Checkbox::new(&mut self.auto_p2pool, "Auto-P2Pool"),
)
.on_hover_text(GUPAX_AUTO_P2POOL); .on_hover_text(GUPAX_AUTO_P2POOL);
ui.separator(); ui.separator();
ui.add_sized( ui.add_sized(size, Checkbox::new(&mut self.auto_xmrig, "Auto-XMRig"))
[width, height],
Checkbox::new(&mut self.auto_xmrig, "Auto-XMRig"),
)
.on_hover_text(GUPAX_AUTO_XMRIG); .on_hover_text(GUPAX_AUTO_XMRIG);
ui.separator(); ui.separator();
ui.add_sized(size, Checkbox::new(&mut self.auto_xvb, "Auto-XvB"))
.on_hover_text(GUPAX_AUTO_XVB);
ui.separator();
ui.add_sized( ui.add_sized(
[width, height], size,
Checkbox::new(&mut self.ask_before_quit, "Ask before quit"), Checkbox::new(&mut self.ask_before_quit, "Ask before quit"),
) )
.on_hover_text(GUPAX_ASK_BEFORE_QUIT); .on_hover_text(GUPAX_ASK_BEFORE_QUIT);
ui.separator(); ui.separator();
ui.add_sized( ui.add_sized(
[width, height], size,
Checkbox::new(&mut self.save_before_quit, "Save before quit"), Checkbox::new(&mut self.save_before_quit, "Save before quit"),
) )
.on_hover_text(GUPAX_SAVE_BEFORE_QUIT); .on_hover_text(GUPAX_SAVE_BEFORE_QUIT);
@ -134,7 +126,7 @@ impl Gupax {
debug!("Gupax Tab | Rendering P2Pool/XMRig path selection"); debug!("Gupax Tab | Rendering P2Pool/XMRig path selection");
// P2Pool/XMRig binary path selection // P2Pool/XMRig binary path selection
let height = height / 28.0; let height = size.y / 28.0;
let text_edit = (ui.available_width() / 10.0) - SPACE; let text_edit = (ui.available_width() / 10.0) - SPACE;
ui.group(|ui| { ui.group(|ui| {
ui.add_sized( ui.add_sized(
@ -238,7 +230,8 @@ impl Gupax {
// Saved [Tab] // Saved [Tab]
debug!("Gupax Tab | Rendering [Tab] selector"); debug!("Gupax Tab | Rendering [Tab] selector");
ui.group(|ui| { ui.group(|ui| {
let width = (width / 5.0) - (SPACE * 1.93); let width = (size.x / 5.0) - (SPACE * 1.93);
let size = vec2(width, height);
ui.add_sized( ui.add_sized(
[ui.available_width(), height / 2.0], [ui.available_width(), height / 2.0],
Label::new(RichText::new("Default Tab").underline().color(LIGHT_GRAY)), Label::new(RichText::new("Default Tab").underline().color(LIGHT_GRAY)),
@ -247,10 +240,7 @@ impl Gupax {
ui.separator(); ui.separator();
ui.horizontal(|ui| { ui.horizontal(|ui| {
if ui if ui
.add_sized( .add_sized(size, SelectableLabel::new(self.tab == Tab::About, "About"))
[width, height],
SelectableLabel::new(self.tab == Tab::About, "About"),
)
.on_hover_text(GUPAX_TAB_ABOUT) .on_hover_text(GUPAX_TAB_ABOUT)
.clicked() .clicked()
{ {
@ -259,7 +249,7 @@ impl Gupax {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.tab == Tab::Status, "Status"), SelectableLabel::new(self.tab == Tab::Status, "Status"),
) )
.on_hover_text(GUPAX_TAB_STATUS) .on_hover_text(GUPAX_TAB_STATUS)
@ -269,10 +259,7 @@ impl Gupax {
} }
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(size, SelectableLabel::new(self.tab == Tab::Gupax, "Gupax"))
[width, height],
SelectableLabel::new(self.tab == Tab::Gupax, "Gupax"),
)
.on_hover_text(GUPAX_TAB_GUPAX) .on_hover_text(GUPAX_TAB_GUPAX)
.clicked() .clicked()
{ {
@ -281,7 +268,7 @@ impl Gupax {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.tab == Tab::P2pool, "P2Pool"), SelectableLabel::new(self.tab == Tab::P2pool, "P2Pool"),
) )
.on_hover_text(GUPAX_TAB_P2POOL) .on_hover_text(GUPAX_TAB_P2POOL)
@ -291,10 +278,7 @@ impl Gupax {
} }
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(size, SelectableLabel::new(self.tab == Tab::Xmrig, "XMRig"))
[width, height],
SelectableLabel::new(self.tab == Tab::Xmrig, "XMRig"),
)
.on_hover_text(GUPAX_TAB_XMRIG) .on_hover_text(GUPAX_TAB_XMRIG)
.clicked() .clicked()
{ {
@ -317,7 +301,7 @@ impl Gupax {
.on_hover_text(GUPAX_ADJUST); .on_hover_text(GUPAX_ADJUST);
ui.separator(); ui.separator();
ui.vertical(|ui| { ui.vertical(|ui| {
let width = width / 10.0; let width = size.x / 10.0;
ui.spacing_mut().icon_width = width / 25.0; ui.spacing_mut().icon_width = width / 25.0;
ui.spacing_mut().slider_width = width * 7.6; ui.spacing_mut().slider_width = width * 7.6;
match self.ratio { match self.ratio {
@ -334,17 +318,18 @@ impl Gupax {
} }
} }
let height = height / 3.5; let height = height / 3.5;
let size = vec2(width, height);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.set_enabled(self.ratio != Ratio::Height); ui.set_enabled(self.ratio != Ratio::Height);
ui.add_sized( ui.add_sized(
[width, height], size,
Label::new(format!( Label::new(format!(
" Width [{}-{}]:", " Width [{}-{}]:",
APP_MIN_WIDTH as u16, APP_MAX_WIDTH as u16 APP_MIN_WIDTH as u16, APP_MAX_WIDTH as u16
)), )),
); );
ui.add_sized( ui.add_sized(
[width, height], size,
Slider::new( Slider::new(
&mut self.selected_width, &mut self.selected_width,
APP_MIN_WIDTH as u16..=APP_MAX_WIDTH as u16, APP_MIN_WIDTH as u16..=APP_MAX_WIDTH as u16,
@ -355,14 +340,14 @@ impl Gupax {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.set_enabled(self.ratio != Ratio::Width); ui.set_enabled(self.ratio != Ratio::Width);
ui.add_sized( ui.add_sized(
[width, height], size,
Label::new(format!( Label::new(format!(
"Height [{}-{}]:", "Height [{}-{}]:",
APP_MIN_HEIGHT as u16, APP_MAX_HEIGHT as u16 APP_MIN_HEIGHT as u16, APP_MAX_HEIGHT as u16
)), )),
); );
ui.add_sized( ui.add_sized(
[width, height], size,
Slider::new( Slider::new(
&mut self.selected_height, &mut self.selected_height,
APP_MIN_HEIGHT as u16..=APP_MAX_HEIGHT as u16, APP_MIN_HEIGHT as u16..=APP_MAX_HEIGHT as u16,
@ -372,11 +357,11 @@ impl Gupax {
}); });
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add_sized( ui.add_sized(
[width, height], size,
Label::new(format!("Scaling [{APP_MIN_SCALE}..{APP_MAX_SCALE}]:")), Label::new(format!("Scaling [{APP_MIN_SCALE}..{APP_MAX_SCALE}]:")),
); );
ui.add_sized( ui.add_sized(
[width, height], size,
Slider::new(&mut self.selected_scale, APP_MIN_SCALE..=APP_MAX_SCALE) Slider::new(&mut self.selected_scale, APP_MIN_SCALE..=APP_MAX_SCALE)
.step_by(0.1), .step_by(0.1),
) )
@ -388,10 +373,11 @@ impl Gupax {
// Width/Height locks // Width/Height locks
ui.horizontal(|ui| { ui.horizontal(|ui| {
use Ratio::*; use Ratio::*;
let width = (width / 4.0) - (SPACE * 1.5); let width = (size.x / 4.0) - (SPACE * 1.5);
let size = vec2(width, height);
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.ratio == Width, "Lock to width"), SelectableLabel::new(self.ratio == Width, "Lock to width"),
) )
.on_hover_text(GUPAX_LOCK_WIDTH) .on_hover_text(GUPAX_LOCK_WIDTH)
@ -402,7 +388,7 @@ impl Gupax {
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(
[width, height], size,
SelectableLabel::new(self.ratio == Height, "Lock to height"), SelectableLabel::new(self.ratio == Height, "Lock to height"),
) )
.on_hover_text(GUPAX_LOCK_HEIGHT) .on_hover_text(GUPAX_LOCK_HEIGHT)
@ -412,17 +398,14 @@ impl Gupax {
} }
ui.separator(); ui.separator();
if ui if ui
.add_sized( .add_sized(size, SelectableLabel::new(self.ratio == None, "No lock"))
[width, height],
SelectableLabel::new(self.ratio == None, "No lock"),
)
.on_hover_text(GUPAX_NO_LOCK) .on_hover_text(GUPAX_NO_LOCK)
.clicked() .clicked()
{ {
self.ratio = None; self.ratio = None;
} }
if ui if ui
.add_sized([width, height], Button::new("Set")) .add_sized(size, Button::new("Set"))
.on_hover_text(GUPAX_SET) .on_hover_text(GUPAX_SET)
.clicked() .clicked()
{ {

View file

@ -24,8 +24,8 @@ impl crate::app::App {
debug!("App | Rendering CENTRAL_PANEL (tab contents)"); debug!("App | Rendering CENTRAL_PANEL (tab contents)");
CentralPanel::default().show(ctx, |ui| { CentralPanel::default().show(ctx, |ui| {
// This sets the Ui dimensions after Top/Bottom are filled // This sets the Ui dimensions after Top/Bottom are filled
self.width = ui.available_width(); self.size.x = ui.available_width();
self.height = ui.available_height(); self.size.y = ui.available_height();
ui.style_mut().override_text_style = Some(TextStyle::Body); ui.style_mut().override_text_style = Some(TextStyle::Body);
match self.tab { match self.tab {
Tab::About => { Tab::About => {
@ -85,8 +85,8 @@ path_xmr: {:#?}\n
self.now.elapsed().as_secs_f32(), self.now.elapsed().as_secs_f32(),
self.state.gupax.selected_width, self.state.gupax.selected_width,
self.state.gupax.selected_height, self.state.gupax.selected_height,
self.width, self.size.x,
self.height, self.size.y,
OS_NAME, OS_NAME,
self.max_threads, self.max_threads,
self.pid, self.pid,
@ -117,24 +117,25 @@ path_xmr: {:#?}\n
); );
self.error_state.set(debug_info, ErrorFerris::Cute, ErrorButtons::Debug); self.error_state.set(debug_info, ErrorFerris::Cute, ErrorButtons::Debug);
} }
let width = self.width; let width = self.size.x;
let height = self.height/30.0; let height = self.size.y/30.0;
let max_height = self.height; let max_height = self.size.y;
let size = vec2(width, height);
ui.add_space(10.0); ui.add_space(10.0);
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
ui.set_max_height(max_height); ui.set_max_height(max_height);
// Display [Gupax] banner // Display [Gupax] banner
let link_width = width/14.0; let link_width = width/14.0;
ui.add_sized(Vec2::new(width, height*3.0), Image::from_bytes("bytes://banner.png", BYTES_BANNER)); ui.add_sized(Vec2::new(width, height*3.0), Image::from_bytes("bytes://banner.png", BYTES_BANNER));
ui.add_sized([width, height], Label::new("is a GUI for mining")); ui.add_sized(size, Label::new("is a GUI for mining"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[Monero]", "https://www.github.com/monero-project/monero")); ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[Monero]", "https://www.github.com/monero-project/monero"));
ui.add_sized([width, height], Label::new("on")); ui.add_sized(size, Label::new("on"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[P2Pool]", "https://www.github.com/SChernykh/p2pool")); ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[P2Pool]", "https://www.github.com/SChernykh/p2pool"));
ui.add_sized([width, height], Label::new("using")); ui.add_sized(size, Label::new("using"));
ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[XMRig]", "https://www.github.com/xmrig/xmrig")); ui.add_sized([link_width, height], Hyperlink::from_label_and_url("[XMRig]", "https://www.github.com/xmrig/xmrig"));
ui.add_space(SPACE*2.0); ui.add_space(SPACE*2.0);
ui.add_sized([width, height], Label::new(KEYBOARD_SHORTCUTS)); ui.add_sized(size, Label::new(KEYBOARD_SHORTCUTS));
ui.add_space(SPACE*2.0); ui.add_space(SPACE*2.0);
if cfg!(debug_assertions) { ui.label(format!("Gupax is running in debug mode - {}", self.now.elapsed().as_secs_f64())); } if cfg!(debug_assertions) { ui.label(format!("Gupax is running in debug mode - {}", self.now.elapsed().as_secs_f64())); }
@ -143,23 +144,23 @@ path_xmr: {:#?}\n
} }
Tab::Status => { Tab::Status => {
debug!("App | Entering [Status] Tab"); debug!("App | Entering [Status] Tab");
crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.xvb_api,&self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.width, self.height, ctx, ui); crate::disk::state::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.xvb_api,&self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.size, ctx, ui);
} }
Tab::Gupax => { Tab::Gupax => {
debug!("App | Entering [Gupax] Tab"); debug!("App | Entering [Gupax] Tab");
crate::disk::state::Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.width, self.height, frame, ctx, ui); crate::disk::state::Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.size, frame, ctx, ui);
} }
Tab::P2pool => { Tab::P2pool => {
debug!("App | Entering [P2Pool] Tab"); debug!("App | Entering [P2Pool] Tab");
crate::disk::state::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui); crate::disk::state::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.size, ctx, ui);
} }
Tab::Xmrig => { Tab::Xmrig => {
debug!("App | Entering [XMRig] Tab"); debug!("App | Entering [XMRig] Tab");
crate::disk::state::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui); crate::disk::state::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.size, ctx, ui);
} }
Tab::Xvb => { Tab::Xvb => {
debug!("App | Entering [XvB] Tab"); debug!("App | Entering [XvB] Tab");
crate::disk::state::Xvb::show(self.width, self.height, ctx, ui); crate::disk::state::Xvb::show(self.size, ctx, ui);
} }
} }
}); });

View file

@ -18,7 +18,7 @@ use crate::helper::p2pool::PubP2poolApi;
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::{components::node::*, constants::*, helper::*, macros::*, utils::regex::Regexes}; use crate::{components::node::*, constants::*, helper::*, macros::*, utils::regex::Regexes};
use egui::{Color32, Label, RichText, TextEdit, TextStyle::*}; use egui::{Color32, Label, RichText, TextEdit, TextStyle::*, Vec2};
use log::*; use log::*;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -37,18 +37,19 @@ impl P2pool {
process: &Arc<Mutex<Process>>, process: &Arc<Mutex<Process>>,
api: &Arc<Mutex<PubP2poolApi>>, api: &Arc<Mutex<PubP2poolApi>>,
buffer: &mut String, buffer: &mut String,
width: f32, size: Vec2,
height: f32,
_ctx: &egui::Context, _ctx: &egui::Context,
ui: &mut egui::Ui, ui: &mut egui::Ui,
) { ) {
let text_edit = height / 25.0; let height = size.y;
let width = size.x;
let text_edit = size.y / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console //---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("P2Pool Tab | Rendering [Console]"); debug!("P2Pool Tab | Rendering [Console]");
ui.group(|ui| { ui.group(|ui| {
if self.simple { if self.simple {
let height = height / 2.8; let height = size.y / 2.8;
let width = width - SPACE; let width = size.x - SPACE;
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical() egui::ScrollArea::vertical()

View file

@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use crate::{ use crate::{
app::Benchmark, disk::state::Status, helper::xmrig::PubXmrigApi, utils::human::HumanNumber, app::Benchmark, disk::state::Status, helper::xmrig::PubXmrigApi, utils::human::HumanNumber,
}; };
use egui::{Hyperlink, ProgressBar, Spinner}; use egui::{Hyperlink, ProgressBar, Spinner, Vec2};
use crate::utils::macros::lock; use crate::utils::macros::lock;
@ -13,22 +13,23 @@ use log::*;
impl Status { impl Status {
pub(super) fn benchmarks( pub(super) fn benchmarks(
&mut self, &mut self,
width: f32, size: Vec2,
height: f32,
ui: &mut egui::Ui, ui: &mut egui::Ui,
benchmarks: &[Benchmark], benchmarks: &[Benchmark],
xmrig_alive: bool, xmrig_alive: bool,
xmrig_api: &Arc<Mutex<PubXmrigApi>>, xmrig_api: &Arc<Mutex<PubXmrigApi>>,
) { ) {
debug!("Status Tab | Rendering [Benchmarks]"); debug!("Status Tab | Rendering [Benchmarks]");
let text = height / 20.0; let text = size.x / 20.0;
let double = text * 2.0; let double = text * 2.0;
let log = height / 3.0; let log = size.y / 3.0;
let width = size.x;
let height = size.y;
// [0], The user's CPU (most likely). // [0], The user's CPU (most likely).
let cpu = &benchmarks[0]; let cpu = &benchmarks[0];
ui.horizontal(|ui| { ui.horizontal(|ui| {
let width = (width / 2.0) - (SPACE * 1.666); let width = (size.x / 2.0) - (SPACE * 1.666);
let min_height = log; let min_height = log;
ui.group(|ui| { ui.group(|ui| {
ui.vertical(|ui| { ui.vertical(|ui| {

View file

@ -15,6 +15,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use egui::Vec2;
use crate::{ use crate::{
app::Benchmark, app::Benchmark,
disk::{gupax_p2pool_api::GupaxP2poolApi, state::Status, status::*}, disk::{gupax_p2pool_api::GupaxP2poolApi, state::Status, status::*},
@ -47,8 +49,7 @@ impl Status {
max_threads: usize, max_threads: usize,
gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>, gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>,
benchmarks: &[Benchmark], benchmarks: &[Benchmark],
width: f32, size: Vec2,
height: f32,
_ctx: &egui::Context, _ctx: &egui::Context,
ui: &mut egui::Ui, ui: &mut egui::Ui,
) { ) {
@ -56,8 +57,7 @@ impl Status {
if self.submenu == Submenu::Processes { if self.submenu == Submenu::Processes {
self.processes( self.processes(
sys, sys,
width, size,
height,
ui, ui,
p2pool_alive, p2pool_alive,
p2pool_api, p2pool_api,
@ -70,17 +70,10 @@ impl Status {
); );
//---------------------------------------------------------------------------------------------------- [P2Pool] //---------------------------------------------------------------------------------------------------- [P2Pool]
} else if self.submenu == Submenu::P2pool { } else if self.submenu == Submenu::P2pool {
self.p2pool( self.p2pool(size, ui, gupax_p2pool_api, p2pool_alive, p2pool_api);
width,
height,
ui,
gupax_p2pool_api,
p2pool_alive,
p2pool_api,
);
//---------------------------------------------------------------------------------------------------- [Benchmarks] //---------------------------------------------------------------------------------------------------- [Benchmarks]
} else if self.submenu == Submenu::Benchmarks { } else if self.submenu == Submenu::Benchmarks {
self.benchmarks(width, height, ui, benchmarks, xmrig_alive, xmrig_api) self.benchmarks(size, ui, benchmarks, xmrig_alive, xmrig_api)
} }
} }
} }

View file

@ -1,6 +1,6 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use egui::{Label, RichText, SelectableLabel, Slider, TextEdit}; use egui::{Label, RichText, SelectableLabel, Slider, TextEdit, Vec2};
use crate::{ use crate::{
disk::{ disk::{
@ -15,14 +15,15 @@ use crate::{
impl Status { impl Status {
pub fn p2pool( pub fn p2pool(
&mut self, &mut self,
width: f32, size: Vec2,
height: f32,
ui: &mut egui::Ui, ui: &mut egui::Ui,
gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>, gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>,
p2pool_alive: bool, p2pool_alive: bool,
p2pool_api: &Arc<Mutex<PubP2poolApi>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>,
) { ) {
let api = lock!(gupax_p2pool_api); let api = lock!(gupax_p2pool_api);
let height = size.y;
let width = size.x;
let text = height / 25.0; let text = height / 25.0;
let log = height / 2.8; let log = height / 2.8;
// Payout Text + PayoutView buttons // Payout Text + PayoutView buttons

View file

@ -1,4 +1,4 @@
use egui::{ScrollArea, Ui}; use egui::{ScrollArea, Ui, Vec2};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::disk::state::Status; use crate::disk::state::Status;
@ -17,8 +17,7 @@ impl Status {
pub(super) fn processes( pub(super) fn processes(
&mut self, &mut self,
sys: &Arc<Mutex<Sys>>, sys: &Arc<Mutex<Sys>>,
width: f32, size: Vec2,
height: f32,
ui: &mut egui::Ui, ui: &mut egui::Ui,
p2pool_alive: bool, p2pool_alive: bool,
p2pool_api: &Arc<Mutex<PubP2poolApi>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>,
@ -29,9 +28,9 @@ impl Status {
xvb_api: &Arc<Mutex<PubXvbApi>>, xvb_api: &Arc<Mutex<PubXvbApi>>,
max_threads: usize, max_threads: usize,
) { ) {
let width = (width / 4.0) - (SPACE * 1.7500); let width = (size.x / 4.0) - (SPACE * 1.7500);
let min_height = height - SPACE; let min_height = size.y - SPACE;
let height = height / 25.0; let height = size.y / 25.0;
ui.horizontal(|ui| { ui.horizontal(|ui| {
// [Gupax] // [Gupax]
gupax(ui, min_height, width, height, sys); gupax(ui, min_height, width, height, sys);
@ -261,6 +260,7 @@ fn p2pool(
}) })
}); });
} }
#[allow(clippy::too_many_arguments)]
fn xmrig( fn xmrig(
ui: &mut Ui, ui: &mut Ui,
min_height: f32, min_height: f32,
@ -432,14 +432,14 @@ fn xvb(ui: &mut Ui, min_height: f32, width: f32, height: f32, xvb_api: &Arc<Mute
Label::new(RichText::new("Share Effort").underline().color(BONE)), Label::new(RichText::new("Share Effort").underline().color(BONE)),
) )
.on_hover_text(STATUS_XVB_SHARE); .on_hover_text(STATUS_XVB_SHARE);
ui.add_sized([width, height], Label::new(format!("{}", api.share_effort))); ui.add_sized([width, height], Label::new(api.share_effort.to_string()));
// Block reward // Block reward
ui.add_sized( ui.add_sized(
[width, height], [width, height],
Label::new(RichText::new("Block Reward").underline().color(BONE)), Label::new(RichText::new("Block Reward").underline().color(BONE)),
) )
.on_hover_text(STATUS_XVB_BLOCK_REWARD); .on_hover_text(STATUS_XVB_BLOCK_REWARD);
ui.add_sized([width, height], Label::new(format!("{}", api.block_reward))); ui.add_sized([width, height], Label::new(api.block_reward.to_string()));
// reward yearly // reward yearly
ui.add_sized( ui.add_sized(
[width, height], [width, height],

View file

@ -23,7 +23,8 @@ use crate::regex::REGEXES;
use crate::utils::regex::Regexes; use crate::utils::regex::Regexes;
use crate::{constants::*, macros::*}; use crate::{constants::*, macros::*};
use egui::{ use egui::{
Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit, TextStyle::*, vec2, Button, Checkbox, ComboBox, Label, RichText, SelectableLabel, Slider, TextEdit,
TextStyle::*, Vec2,
}; };
use log::*; use log::*;
@ -38,18 +39,18 @@ impl Xmrig {
process: &Arc<Mutex<Process>>, process: &Arc<Mutex<Process>>,
api: &Arc<Mutex<PubXmrigApi>>, api: &Arc<Mutex<PubXmrigApi>>,
buffer: &mut String, buffer: &mut String,
width: f32, size: Vec2,
height: f32,
_ctx: &egui::Context, _ctx: &egui::Context,
ui: &mut egui::Ui, ui: &mut egui::Ui,
) { ) {
let text_edit = height / 25.0; let text_edit = size.y / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console //---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("XMRig Tab | Rendering [Console]"); debug!("XMRig Tab | Rendering [Console]");
ui.group(|ui| { ui.group(|ui| {
if self.simple { if self.simple {
let height = height / 1.5; let height = size.y / 1.5;
let width = width - SPACE; let width = size.x - SPACE;
let size = vec2(width, height);
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical() egui::ScrollArea::vertical()
@ -59,15 +60,16 @@ impl Xmrig {
.auto_shrink([false; 2]) .auto_shrink([false; 2])
.show_viewport(ui, |ui, _| { .show_viewport(ui, |ui, _| {
ui.add_sized( ui.add_sized(
[width, height], size,
TextEdit::multiline(&mut lock!(api).output.as_str()), TextEdit::multiline(&mut lock!(api).output.as_str()),
); );
}); });
}); });
//---------------------------------------------------------------------------------------------------- [Advanced] Console //---------------------------------------------------------------------------------------------------- [Advanced] Console
} else { } else {
let height = height / 2.8; let height = size.y / 2.8;
let width = width - SPACE; let width = size.x - SPACE;
let size = vec2(width, height);
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical() egui::ScrollArea::vertical()
@ -77,7 +79,7 @@ impl Xmrig {
.auto_shrink([false; 2]) .auto_shrink([false; 2])
.show_viewport(ui, |ui, _| { .show_viewport(ui, |ui, _| {
ui.add_sized( ui.add_sized(
[width, height], size,
TextEdit::multiline(&mut lock!(api).output.as_str()), TextEdit::multiline(&mut lock!(api).output.as_str()),
); );
}); });
@ -109,7 +111,7 @@ impl Xmrig {
debug!("XMRig Tab | Rendering [Arguments]"); debug!("XMRig Tab | Rendering [Arguments]");
ui.group(|ui| { ui.group(|ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
let width = (width / 10.0) - SPACE; let width = (size.x / 10.0) - SPACE;
ui.add_sized([width, text_edit], Label::new("Command arguments:")); ui.add_sized([width, text_edit], Label::new("Command arguments:"));
ui.add_sized( ui.add_sized(
[ui.available_width(), text_edit], [ui.available_width(), text_edit],
@ -126,7 +128,7 @@ impl Xmrig {
//---------------------------------------------------------------------------------------------------- Address //---------------------------------------------------------------------------------------------------- Address
debug!("XMRig Tab | Rendering [Address]"); debug!("XMRig Tab | Rendering [Address]");
ui.group(|ui| { ui.group(|ui| {
let width = width - SPACE; let width = size.x - SPACE;
ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0); ui.spacing_mut().text_edit_width = (width) - (SPACE * 3.0);
let text; let text;
let color; let color;
@ -160,7 +162,7 @@ impl Xmrig {
} }
debug!("XMRig Tab | Rendering [Threads]"); debug!("XMRig Tab | Rendering [Threads]");
ui.vertical(|ui| { ui.vertical(|ui| {
let width = width / 10.0; let width = size.x / 10.0;
let text_width = width * 2.4; let text_width = width * 2.4;
ui.spacing_mut().slider_width = width * 6.5; ui.spacing_mut().slider_width = width * 6.5;
ui.spacing_mut().icon_width = width / 25.0; ui.spacing_mut().icon_width = width / 25.0;
@ -471,21 +473,16 @@ impl Xmrig {
ui.horizontal(|ui| { ui.horizontal(|ui| {
let width = (ui.available_width() / 2.0) - 11.0; let width = (ui.available_width() / 2.0) - 11.0;
let height = text_edit * 2.0; let height = text_edit * 2.0;
let size = vec2(width, height);
// let mut style = (*ctx.style()).clone(); // let mut style = (*ctx.style()).clone();
// style.spacing.icon_width_inner = width / 8.0; // style.spacing.icon_width_inner = width / 8.0;
// style.spacing.icon_width = width / 6.0; // style.spacing.icon_width = width / 6.0;
// style.spacing.icon_spacing = 20.0; // style.spacing.icon_spacing = 20.0;
// ctx.set_style(style); // ctx.set_style(style);
ui.add_sized( ui.add_sized(size, Checkbox::new(&mut self.tls, "TLS Connection"))
[width, height],
Checkbox::new(&mut self.tls, "TLS Connection"),
)
.on_hover_text(XMRIG_TLS); .on_hover_text(XMRIG_TLS);
ui.separator(); ui.separator();
ui.add_sized( ui.add_sized(size, Checkbox::new(&mut self.keepalive, "Keepalive"))
[width, height],
Checkbox::new(&mut self.keepalive, "Keepalive"),
)
.on_hover_text(XMRIG_KEEPALIVE); .on_hover_text(XMRIG_KEEPALIVE);
}); });
}); });

View file

@ -1,12 +1,12 @@
use egui::{Hyperlink, Image}; use egui::{Hyperlink, Image, Vec2};
use crate::constants::{BYTES_XVB, SPACE}; use crate::constants::{BYTES_XVB, SPACE};
impl crate::disk::state::Xvb { impl crate::disk::state::Xvb {
#[inline(always)] // called once #[inline(always)] // called once
pub fn show(width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) { pub fn show(size: Vec2, _ctx: &egui::Context, ui: &mut egui::Ui) {
let website_height = height / 10.0; let website_height = size.y / 10.0;
let width = width - SPACE; let width = size.x - SPACE;
// ui.add_sized( // ui.add_sized(
// [width, website_height], // [width, website_height],
// Hyperlink::from_label_and_url("XMRvsBeast", "https://xmrvsbeast.com"), // Hyperlink::from_label_and_url("XMRvsBeast", "https://xmrvsbeast.com"),

View file

@ -23,8 +23,8 @@ impl crate::app::App {
CentralPanel::default().show(ctx, |ui| { CentralPanel::default().show(ctx, |ui| {
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
// Set width/height/font // Set width/height/font
let width = self.width; let width = self.size.x;
let height = self.height / 4.0; let height = self.size.y / 4.0;
ui.style_mut().override_text_style = Some(Name("MonospaceLarge".into())); ui.style_mut().override_text_style = Some(Name("MonospaceLarge".into()));
// Display ferris // Display ferris

View file

@ -8,8 +8,8 @@ impl crate::app::App {
pub fn top_panel(&mut self, ctx: &egui::Context) { pub fn top_panel(&mut self, ctx: &egui::Context) {
debug!("App | Rendering TOP tabs"); debug!("App | Rendering TOP tabs");
TopBottomPanel::top("top").show(ctx, |ui| { TopBottomPanel::top("top").show(ctx, |ui| {
let width = (self.width - (SPACE * 11.0)) / 6.0; let width = (self.size.x - (SPACE * 11.0)) / 6.0;
let height = self.height / 15.0; let height = self.size.y / 15.0;
ui.add_space(4.0); ui.add_space(4.0);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.style_mut().override_text_style = Some(Name("Tab".into())); ui.style_mut().override_text_style = Some(Name("Tab".into()));

View file

@ -50,9 +50,9 @@ impl App {
ctx.request_repaint(); ctx.request_repaint();
info!( info!(
"App | Resizing frame to match new internal resolution: [{}x{}]", "App | Resizing frame to match new internal resolution: [{}x{}]",
self.width, self.height self.size.x, self.size.y
); );
init_text_styles(ctx, self.width, self.state.gupax.selected_scale); init_text_styles(ctx, self.size.x, self.state.gupax.selected_scale);
self.resizing = false; self.resizing = false;
} }
}); });

View file

@ -1,3 +1,6 @@
use anyhow::{bail, Result};
use hyper::StatusCode;
use super::*; use super::*;
use crate::{components::node::RemoteNode, disk::status::*}; use crate::{components::node::RemoteNode, disk::status::*};
//---------------------------------------------------------------------------------------------------- [State] Impl //---------------------------------------------------------------------------------------------------- [State] Impl
@ -175,6 +178,7 @@ pub struct Gupax {
pub auto_update: bool, pub auto_update: bool,
pub auto_p2pool: bool, pub auto_p2pool: bool,
pub auto_xmrig: bool, pub auto_xmrig: bool,
pub auto_xvb: bool,
// pub auto_monero: bool, // pub auto_monero: bool,
pub ask_before_quit: bool, pub ask_before_quit: bool,
pub save_before_quit: bool, pub save_before_quit: bool,
@ -240,8 +244,15 @@ pub struct Xmrig {
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)] #[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub struct Xvb { pub struct Xvb {
pub token_confirmed: String, pub token: String,
pub token_inserted: String, pub node: XvbNode,
}
#[derive(Clone, Eq, PartialEq, Debug, Deserialize, Serialize, Default)]
pub enum XvbNode {
NorthAmerica,
#[default]
Europe,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
@ -272,6 +283,7 @@ impl Default for Gupax {
auto_update: true, auto_update: true,
auto_p2pool: false, auto_p2pool: false,
auto_xmrig: false, auto_xmrig: false,
auto_xvb: true,
ask_before_quit: true, ask_before_quit: true,
save_before_quit: true, save_before_quit: true,
update_via_tor: true, update_via_tor: true,
@ -314,6 +326,36 @@ impl Default for P2pool {
} }
} }
} }
impl Xvb {
pub async fn is_token_exist(address: String, token: String) -> Result<()> {
let client: hyper::Client<hyper::client::HttpConnector> =
hyper::Client::builder().build(hyper::client::HttpConnector::new());
if let Ok(request) = hyper::Request::builder()
.method("GET")
.uri(format!(
"{}/cgi-bin/p2pool_bonus_history_api.cgi?address={}&token={}",
XVB_URL, address, token
))
.body(hyper::Body::empty())
{
if let Ok(resp) = client.request(request).await {
match resp.status() {
StatusCode::OK => Ok(()),
StatusCode::UNPROCESSABLE_ENTITY => {
bail!("the token is invalid for this xmr address.")
}
_ => bail!("The status of the response is not expected"),
}
} else {
bail!("error from response")
}
} else {
bail!("request could not be build")
}
}
}
impl Xmrig { impl Xmrig {
fn with_threads(max_threads: usize, current_threads: usize) -> Self { fn with_threads(max_threads: usize, current_threads: usize) -> Self {
let xmrig = Self::default(); let xmrig = Self::default();

View file

@ -31,6 +31,7 @@ mod test {
auto_update = true auto_update = true
auto_p2pool = false auto_p2pool = false
auto_xmrig = false auto_xmrig = false
auto_xvb = false
ask_before_quit = true ask_before_quit = true
save_before_quit = true save_before_quit = true
update_via_tor = true update_via_tor = true
@ -97,8 +98,8 @@ mod test {
selected_port = "3333" selected_port = "3333"
[xvb] [xvb]
token_confirmed = "" token = ""
token_inserted = "" node = "Europe"
[version] [version]
gupax = "v1.3.0" gupax = "v1.3.0"
p2pool = "v2.5" p2pool = "v2.5"

View file

@ -72,6 +72,7 @@ pub struct Helper {
pub pub_sys: Arc<Mutex<Sys>>, // The public API for [sysinfo] that the [Status] tab reads from pub pub_sys: Arc<Mutex<Sys>>, // The public API for [sysinfo] that the [Status] tab reads from
pub p2pool: Arc<Mutex<Process>>, // P2Pool process state pub p2pool: Arc<Mutex<Process>>, // P2Pool process state
pub xmrig: Arc<Mutex<Process>>, // XMRig process state pub xmrig: Arc<Mutex<Process>>, // XMRig process state
pub xvb: Arc<Mutex<Process>>, // XvB process state
pub gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for GUI thread) pub gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, // P2Pool API state (for GUI thread)
pub gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for GUI thread) pub gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, // XMRig API state (for GUI thread)
pub gui_api_xvb: Arc<Mutex<PubXvbApi>>, // XMRig API state (for GUI thread) pub gui_api_xvb: Arc<Mutex<PubXvbApi>>, // XMRig API state (for GUI thread)
@ -246,6 +247,7 @@ impl Default for ProcessSignal {
pub enum ProcessName { pub enum ProcessName {
P2pool, P2pool,
Xmrig, Xmrig,
Xvb,
} }
impl std::fmt::Display for ProcessState { impl std::fmt::Display for ProcessState {
@ -263,6 +265,7 @@ impl std::fmt::Display for ProcessName {
match *self { match *self {
ProcessName::P2pool => write!(f, "P2Pool"), ProcessName::P2pool => write!(f, "P2Pool"),
ProcessName::Xmrig => write!(f, "XMRig"), ProcessName::Xmrig => write!(f, "XMRig"),
ProcessName::Xvb => write!(f, "XvB"),
} }
} }
} }
@ -276,6 +279,7 @@ impl Helper {
pub_sys: Arc<Mutex<Sys>>, pub_sys: Arc<Mutex<Sys>>,
p2pool: Arc<Mutex<Process>>, p2pool: Arc<Mutex<Process>>,
xmrig: Arc<Mutex<Process>>, xmrig: Arc<Mutex<Process>>,
xvb: Arc<Mutex<Process>>,
gui_api_p2pool: Arc<Mutex<PubP2poolApi>>, gui_api_p2pool: Arc<Mutex<PubP2poolApi>>,
gui_api_xmrig: Arc<Mutex<PubXmrigApi>>, gui_api_xmrig: Arc<Mutex<PubXmrigApi>>,
gui_api_xvb: Arc<Mutex<PubXvbApi>>, gui_api_xvb: Arc<Mutex<PubXvbApi>>,
@ -293,6 +297,7 @@ impl Helper {
// These are created when initializing [App], since it needs a handle to it as well // These are created when initializing [App], since it needs a handle to it as well
p2pool, p2pool,
xmrig, xmrig,
xvb,
gui_api_p2pool, gui_api_p2pool,
gui_api_xmrig, gui_api_xmrig,
gui_api_xvb, gui_api_xvb,

View file

@ -1,26 +1,98 @@
use derive_more::Display; use derive_more::Display;
use hyper::client::HttpConnector; use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector; use hyper_tls::HttpsConnector;
use log::{debug, info, warn}; use log::{debug, error, info, warn};
use serde::Deserialize; use serde::Deserialize;
use std::fmt::Write;
use std::{ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
thread, thread,
time::Instant, time::Instant,
}; };
use crate::utils::{constants::XVB_URL_PUBLIC_API, macros::lock}; use crate::{
disk::state::Xvb,
helper::{ProcessSignal, ProcessState},
utils::{
constants::{HORI_CONSOLE, XVB_URL_PUBLIC_API},
human::HumanTime,
macros::{lock, lock2, sleep},
},
};
use super::Helper; use super::{Helper, Process};
impl Helper { impl Helper {
pub fn start_xvb(helper: &Arc<Mutex<Self>>) { // Just sets some signals for the watchdog thread to pick up on.
pub fn stop_xvb(helper: &Arc<Mutex<Self>>) {
info!("XvB | Attempting to stop...");
lock2!(helper, p2pool).signal = ProcessSignal::Stop;
lock2!(helper, p2pool).state = ProcessState::Middle;
}
pub fn restart_xvb(
helper: &Arc<Mutex<Self>>,
state_xvb: &crate::disk::state::Xvb,
state_p2pool: &crate::disk::state::P2pool,
) {
info!("XvB | Attempting to restart...");
lock2!(helper, p2pool).signal = ProcessSignal::Restart;
lock2!(helper, p2pool).state = ProcessState::Middle;
let helper = helper.clone();
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
// This thread lives to wait, start xmrig then die.
thread::spawn(move || {
while lock2!(helper, xvb).state != ProcessState::Waiting {
warn!("XvB | Want to restart but process is still alive, waiting...");
sleep!(1000);
}
// Ok, process is not alive, start the new one!
info!("XvB | Old process seems dead, starting new one!");
Self::start_xvb(&helper, &state_xvb, &state_p2pool);
});
info!("XMRig | Restart ... OK");
}
pub fn start_xvb(
helper: &Arc<Mutex<Self>>,
state_xvb: &crate::disk::state::Xvb,
state_p2pool: &crate::disk::state::P2pool,
) {
lock2!(helper, xvb).state = ProcessState::Middle;
let https = HttpsConnector::new(); let https = HttpsConnector::new();
let client = hyper::Client::builder().build(https); let client = hyper::Client::builder().build(https);
let gui_api = Arc::clone(&lock!(helper).gui_api_xvb); let gui_api = Arc::clone(&lock!(helper).gui_api_xvb);
let pub_api = Arc::clone(&lock!(helper).pub_api_xvb); let pub_api = Arc::clone(&lock!(helper).pub_api_xvb);
let process = Arc::clone(&lock!(helper).xvb);
let state_xvb = state_xvb.clone();
let state_p2pool = state_p2pool.clone();
// two first verifications should be done before starting the process and giving the possibility to start it.
// verify if address is inserted
// if state_p2pool.address.is_empty() {
// warn!("Xvb | Start ... Failed because payout address is not inserted in P2pool tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// verify if token exist
// if state_xvb.token.is_empty() {
// warn!("Xvb | Start ... Failed because valid token is not inserted in XvB tab");
// lock2!(helper, xvb).state = ProcessState::Failed;
// return;
// }
// verify if token and address are existent on XvB server
let rt = tokio::runtime::Runtime::new().unwrap();
if !rt.block_on(async move {
Xvb::is_token_exist(state_p2pool.address, state_xvb.token)
.await
.is_ok()
}) {
warn!("Xvb | Start ... Failed because token and associated address are not existent on XvB server");
lock2!(helper, xvb).state = ProcessState::Failed;
return;
}
thread::spawn(move || { thread::spawn(move || {
Self::spawn_xvb_watchdog(client, gui_api, pub_api); Self::spawn_xvb_watchdog(client, gui_api, pub_api, process);
}); });
} }
#[tokio::main] #[tokio::main]
@ -28,16 +100,31 @@ impl Helper {
client: hyper::Client<HttpsConnector<HttpConnector>>, client: hyper::Client<HttpsConnector<HttpConnector>>,
gui_api: Arc<Mutex<PubXvbApi>>, gui_api: Arc<Mutex<PubXvbApi>>,
pub_api: Arc<Mutex<PubXvbApi>>, pub_api: Arc<Mutex<PubXvbApi>>,
process: Arc<Mutex<Process>>,
) { ) {
info!("XvB started"); info!("XvB started");
// 2. Set process state
debug!("XvB | Setting process state...");
{
let mut lock = lock!(process);
lock.state = ProcessState::Middle;
lock.signal = ProcessSignal::None;
lock.start = Instant::now();
}
// Reset stats before loop // Reset stats before loop
*lock!(pub_api) = PubXvbApi::new(); *lock!(pub_api) = PubXvbApi::new();
*lock!(gui_api) = PubXvbApi::new(); *lock!(gui_api) = PubXvbApi::new();
let start = lock!(process).start;
info!("XvB | Entering watchdog mode... woof!"); info!("XvB | Entering watchdog mode... woof!");
loop { loop {
// Set timer // Set timer
let now = Instant::now(); let now = Instant::now();
// check signal
if signal_interrupt(process.clone(), start, gui_api.clone()) {
break;
}
debug!("XvB Watchdog | ----------- Start of loop -----------"); debug!("XvB Watchdog | ----------- Start of loop -----------");
// Send an HTTP API request // Send an HTTP API request
debug!("XvB Watchdog | Attempting HTTP API request..."); debug!("XvB Watchdog | Attempting HTTP API request...");
@ -57,7 +144,7 @@ impl Helper {
// XvB Status do not need to be refreshed like others because combine_with_gui do not refresh if no data is changed. // XvB Status do not need to be refreshed like others because combine_with_gui do not refresh if no data is changed.
let elapsed = now.elapsed().as_secs(); let elapsed = now.elapsed().as_secs();
if elapsed < 59 { if elapsed < 59 {
let sleep = (60 - elapsed) as u64; let sleep = 60 - elapsed;
debug!("XvB Watchdog | END OF LOOP - Sleeping for [{}]s...", sleep); debug!("XvB Watchdog | END OF LOOP - Sleeping for [{}]s...", sleep);
std::thread::sleep(std::time::Duration::from_secs(sleep)) std::thread::sleep(std::time::Duration::from_secs(sleep))
} else { } else {
@ -70,6 +157,10 @@ impl Helper {
use serde_this_or_that::as_u64; use serde_this_or_that::as_u64;
#[derive(Debug, Clone, Default, Deserialize)] #[derive(Debug, Clone, Default, Deserialize)]
pub struct PubXvbApi { pub struct PubXvbApi {
#[serde(skip)]
pub output: String,
#[serde(skip)]
pub uptime: HumanTime,
pub time_remain: u32, // remaining time of round in minutes pub time_remain: u32, // remaining time of round in minutes
pub bonus_hr: f64, pub bonus_hr: f64,
pub donate_hr: f64, // donated hr from all donors pub donate_hr: f64, // donated hr from all donors
@ -139,6 +230,57 @@ impl PubXvbApi {
Ok(serde_json::from_slice::<Self>(&body)?) Ok(serde_json::from_slice::<Self>(&body)?)
} }
} }
fn signal_interrupt(
process: Arc<Mutex<Process>>,
start: Instant,
gui_api: Arc<Mutex<PubXvbApi>>,
) -> bool {
// Check SIGNAL
// check if STOP or RESTART Signal is given.
// if STOP, will put Signal to None, if Restart to Wait
// in either case, will break from loop.
if lock!(process).signal == ProcessSignal::Stop {
debug!("P2Pool Watchdog | Stop SIGNAL caught");
// Wait to get the exit status
let uptime = HumanTime::into_human(start.elapsed());
info!("Xvb Watchdog | Stopped ... Uptime was: [{}]", uptime);
// insert the signal into output of XvB
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb stopped | Uptime: [{}] | \n{}\n\n\n\n",
HORI_CONSOLE,
uptime,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI Uptime/Exit status write failed: {}", e);
}
debug!("XvB Watchdog | Stop SIGNAL done, breaking");
lock!(process).signal = ProcessSignal::None;
return true;
// Check RESTART
} else if lock!(process).signal == ProcessSignal::Restart {
debug!("XvB Watchdog | Restart SIGNAL caught");
let uptime = HumanTime::into_human(start.elapsed());
info!("XvB Watchdog | Stopped ... Uptime was: [{}]", uptime);
// insert the signal into output of XvB
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!(
lock!(gui_api).output,
"{}\nXvb stopped | Uptime: [{}] | \n{}\n\n\n\n",
HORI_CONSOLE,
uptime,
HORI_CONSOLE
) {
error!("XvB Watchdog | GUI Uptime/Exit status write failed: {}", e);
}
debug!("XvB Watchdog | Restart SIGNAL done, breaking");
lock!(process).state = ProcessState::Waiting;
return true;
}
false
}
//---------------------------------------------------------------------------------------------------- TEST //---------------------------------------------------------------------------------------------------- TEST
#[cfg(test)] #[cfg(test)]
mod test { mod test {

View file

@ -206,7 +206,11 @@ pub fn init_auto(app: &mut App) {
} else { } else {
info!("Skipping auto-xmrig..."); info!("Skipping auto-xmrig...");
} }
// [XvB] // [Auto-XvB]
// For now, the XvB client of the API for receiving public information is always enabled. if app.state.gupax.auto_xvb {
Helper::start_xvb(&app.helper); Helper::start_xvb(&app.helper, &app.state.xvb, &app.state.p2pool);
} else {
info!("Skipping auto-xvb...");
}
} }

View file

@ -101,6 +101,13 @@ pub const XMRIG_FAILED: &str = "XMRig is offline and failed when exiting";
pub const XMRIG_MIDDLE: &str = "XMRig is in the middle of (re)starting/stopping"; pub const XMRIG_MIDDLE: &str = "XMRig is in the middle of (re)starting/stopping";
pub const XMRIG_NOT_MINING: &str = "XMRig is online, but not mining to any pool"; pub const XMRIG_NOT_MINING: &str = "XMRig is online, but not mining to any pool";
pub const XVB_ALIVE: &str =
"XvB process is configured and distributing hashrate, XvB node is online";
pub const XVB_DEAD: &str = "XvB process is offline";
pub const XVB_FAILED: &str = "XvB process is misconfigured or the XvB node is offline";
pub const XVB_MIDDLE: &str = "XvB is in the middle of (re)starting/stopping";
pub const XVB_NOT_CONFIGURED: &str = "You need to insert an existent token before starting XvB";
// This is the typical space added when using // This is the typical space added when using
// [ui.separator()] or [ui.group()] // [ui.separator()] or [ui.group()]
// Used for subtracting the width/height so // Used for subtracting the width/height so
@ -266,6 +273,7 @@ pub const GUPAX_ASK_BEFORE_QUIT: &str = "Ask before quitting Gupax";
pub const GUPAX_SAVE_BEFORE_QUIT: &str = "Automatically save any changed settings before quitting"; pub const GUPAX_SAVE_BEFORE_QUIT: &str = "Automatically save any changed settings before quitting";
pub const GUPAX_AUTO_P2POOL: &str = "Automatically start P2Pool on Gupax startup. If you are using [P2Pool Simple], this will NOT wait for your [Auto-Ping] to finish, it will start P2Pool on the pool you already have selected. This option will fail if your P2Pool settings aren't valid!"; pub const GUPAX_AUTO_P2POOL: &str = "Automatically start P2Pool on Gupax startup. If you are using [P2Pool Simple], this will NOT wait for your [Auto-Ping] to finish, it will start P2Pool on the pool you already have selected. This option will fail if your P2Pool settings aren't valid!";
pub const GUPAX_AUTO_XMRIG: &str = "Automatically start XMRig on Gupax startup. This option will fail if your XMRig settings aren't valid!"; pub const GUPAX_AUTO_XMRIG: &str = "Automatically start XMRig on Gupax startup. This option will fail if your XMRig settings aren't valid!";
pub const GUPAX_AUTO_XVB: &str = "Automatically start XvB on Gupax startup. This option will fail if your XvB settings aren't valid!";
pub const GUPAX_ADJUST: &str = "Adjust and set the width/height of the Gupax window"; pub const GUPAX_ADJUST: &str = "Adjust and set the width/height of the Gupax window";
pub const GUPAX_WIDTH: &str = "Set the width of the Gupax window"; pub const GUPAX_WIDTH: &str = "Set the width of the Gupax window";
pub const GUPAX_HEIGHT: &str = "Set the height of the Gupax window"; pub const GUPAX_HEIGHT: &str = "Set the height of the Gupax window";