diff --git a/src/gupax.rs b/src/gupax.rs index a040a37..b1a6914 100644 --- a/src/gupax.rs +++ b/src/gupax.rs @@ -28,6 +28,7 @@ use crate::{ disk::Gupax, update::*, ErrorState, + Restart, }; use std::{ thread, @@ -78,7 +79,7 @@ pub enum Ratio { //---------------------------------------------------------------------------------------------------- Gupax impl Gupax { - pub fn show(&mut self, og: &Arc>, state_path: &Path, update: &Arc>, file_window: &Arc>, error_state: &mut ErrorState, width: f32, height: f32, frame: &mut eframe::Frame, ctx: &egui::Context, ui: &mut egui::Ui) { + pub fn show(&mut self, og: &Arc>, state_path: &Path, update: &Arc>, file_window: &Arc>, error_state: &mut ErrorState, restart: &Arc>, width: f32, height: f32, frame: &mut eframe::Frame, ctx: &egui::Context, ui: &mut egui::Ui) { // Update button + Progress bar ui.group(|ui| { // These are in unnecessary [ui.vertical()]'s @@ -91,7 +92,7 @@ impl Gupax { ui.vertical(|ui| { ui.set_enabled(!updating); if ui.add_sized([width, height], Button::new("Check for updates")).on_hover_text(GUPAX_UPDATE).clicked() { - Update::spawn_thread(og, &self, state_path, update, error_state); + Update::spawn_thread(og, &self, state_path, update, error_state, restart); } }); ui.vertical(|ui| { diff --git a/src/main.rs b/src/main.rs index 2aa4523..7892084 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,6 +88,10 @@ pub struct App { og_pool_vec: Vec<(String, Pool)>, // Manual Pool database pool_vec: Vec<(String, Pool)>, // Manual Pool database diff: bool, // This bool indicates state changes + // Restart state: + // If Gupax updated itself, this represents that the + // user should (but isn't required to) restart Gupax. + restart: Arc>, // Error State // These values are essentially global variables that // indicate if an error message needs to be displayed @@ -143,6 +147,7 @@ impl App { node_vec: Node::new_vec(), og_pool_vec: Pool::new_vec(), pool_vec: Pool::new_vec(), + restart: Arc::new(Mutex::new(Restart::No)), diff: false, error_state: ErrorState::new(), p2pool: false, @@ -313,6 +318,13 @@ impl Default for Tab { } } +//---------------------------------------------------------------------------------------------------- [Restart] Enum +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Restart { + No, // We don't need to restart + Yes, // We updated, user should probably (but isn't required to) restart +} + //---------------------------------------------------------------------------------------------------- [ErrorState] struct #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ErrorButtons { @@ -492,7 +504,7 @@ fn init_auto(app: &mut App) { // [Auto-Update] if app.state.gupax.auto_update { - Update::spawn_thread(&app.og, &app.state.gupax, &app.state_path, &app.update, &mut app.error_state); + Update::spawn_thread(&app.og, &app.state.gupax, &app.state_path, &app.update, &mut app.error_state, &app.restart); } else { info!("Skipping auto-update..."); } @@ -860,22 +872,28 @@ impl eframe::App for App { ui.style_mut().override_text_style = Some(Name("Bottom".into())); ui.horizontal(|ui| { ui.group(|ui| { - // [Gupax Version] + [OS] + [P2Pool on/off] + [XMRig on/off] let width = ((self.width/2.0)/4.0)-(SPACE*2.0); - ui.add_sized([width, height], Label::new(&*self.name_version)); + // [Gupax Version] + // Is yellow if the user updated and should (but isn't required to) restart. + match *self.restart.lock().unwrap() { + Restart::Yes => ui.add_sized([width, height], Label::new(RichText::new(&self.name_version).color(YELLOW))).on_hover_text("Gupax was updated. A restart is recommended but not required."), + _ => ui.add_sized([width, height], Label::new(&self.name_version)).on_hover_text("Gupax is up-to-date"), + }; ui.separator(); + // [OS] ui.add_sized([width, height], Label::new(self.os)); ui.separator(); + // [P2Pool/XMRig] Status if self.p2pool { - ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GREEN))); + ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(GREEN))).on_hover_text("P2Pool is online"); } else { - ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(RED))); + ui.add_sized([width, height], Label::new(RichText::new("P2Pool ⏺").color(RED))).on_hover_text("P2Pool is offline"); } ui.separator(); if self.xmrig { - ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GREEN))); + ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(GREEN))).on_hover_text("XMRig is online"); } else { - ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(RED))); + ui.add_sized([width, height], Label::new(RichText::new("XMRig ⏺").color(RED))).on_hover_text("XMRig is offline"); } }); @@ -1026,7 +1044,7 @@ impl eframe::App for App { Status::show(self, self.width, self.height, ctx, ui); } Tab::Gupax => { - Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, self.width, self.height, frame, ctx, ui); + 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); } Tab::P2pool => { P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, self.p2pool, &self.ping, &self.regex, self.width, self.height, ctx, ui); diff --git a/src/update.rs b/src/update.rs index 8018c04..0495e06 100644 --- a/src/update.rs +++ b/src/update.rs @@ -32,6 +32,7 @@ use crate::{ disk::*, update::Name::*, ErrorState,ErrorFerris,ErrorButtons, + Restart, }; use hyper::{ Client,Body,Request, @@ -265,7 +266,7 @@ impl Update { // actually contains the code. This is so that everytime // an update needs to happen (Gupax tab, auto-update), the // code only needs to be edited once, here. - pub fn spawn_thread(og: &Arc>, gupax: &crate::disk::Gupax, state_path: &Path, update: &Arc>, error_state: &mut ErrorState) { + pub fn spawn_thread(og: &Arc>, gupax: &crate::disk::Gupax, state_path: &Path, update: &Arc>, error_state: &mut ErrorState, restart: &Arc>) { // Check P2Pool path for safety // Attempt relative to absolute path let p2pool_path = match into_absolute_path(gupax.p2pool_path.clone()) { @@ -329,9 +330,10 @@ impl Update { let state_ver = Arc::clone(&og.lock().unwrap().version); let state_path = state_path.to_path_buf(); let update = Arc::clone(update); + let restart = Arc::clone(restart); std::thread::spawn(move|| { info!("Spawning update thread..."); - match Update::start(update.clone(), og.clone(), state_ver.clone()) { + match Update::start(update.clone(), og.clone(), state_ver.clone(), restart) { Ok(_) => { info!("Update | Saving state..."); let original_version = og.lock().unwrap().version.clone(); @@ -362,7 +364,7 @@ impl Update { // 4. loop over vec, download links // 5. extract, upgrade #[tokio::main] - pub async fn start(update: Arc>, _og: Arc>, state_ver: Arc>) -> Result<(), anyhow::Error> { + pub async fn start(update: Arc>, _og: Arc>, state_ver: Arc>, restart: Arc>) -> Result<(), anyhow::Error> { //---------------------------------------------------------------------------------------------------- Init *update.lock().unwrap().updating.lock().unwrap() = true; // Set timer @@ -658,7 +660,11 @@ impl Update { } std::fs::rename(entry.path(), path)?; match name { - Gupax => state_ver.lock().unwrap().gupax = Pkg::get_new_pkg_version(Gupax, &vec4)?, + Gupax => { + state_ver.lock().unwrap().gupax = Pkg::get_new_pkg_version(Gupax, &vec4)?; + // If we're updating Gupax, set the [Restart] state so that the user knows to restart + *restart.lock().unwrap() = Restart::Yes; + }, P2pool => state_ver.lock().unwrap().p2pool = Pkg::get_new_pkg_version(P2pool, &vec4)?, Xmrig => state_ver.lock().unwrap().xmrig = Pkg::get_new_pkg_version(Xmrig, &vec4)?, };