disk: add [ErrorState] handling for disk errors

This commit is contained in:
hinto-janaiyo 2022-11-19 21:20:28 -05:00
parent e8c41fceb3
commit 7a5fe24276
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
9 changed files with 209 additions and 217 deletions

101
Cargo.lock generated
View file

@ -1275,15 +1275,6 @@ dependencies = [
"bytemuck",
]
[[package]]
name = "encoding_rs"
version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
dependencies = [
"cfg-if",
]
[[package]]
name = "enum-ordinalize"
version = "3.1.12"
@ -1920,7 +1911,6 @@ dependencies = [
"openssl",
"rand 0.8.5",
"regex",
"reqwest",
"rfd",
"rusqlite",
"serde",
@ -1937,25 +1927,6 @@ dependencies = [
"zip",
]
[[package]]
name = "h2"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.1.0"
@ -2106,7 +2077,6 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
@ -2223,12 +2193,6 @@ dependencies = [
"web-sys",
]
[[package]]
name = "ipnet"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
[[package]]
name = "itertools"
version = "0.10.5"
@ -2438,12 +2402,6 @@ dependencies = [
"zeroize",
]
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -3339,43 +3297,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "reqwest"
version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-tls",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "retain_mut"
version = "0.1.9"
@ -3661,18 +3582,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_with"
version = "1.14.0"
@ -4275,7 +4184,6 @@ dependencies = [
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
@ -5439,15 +5347,6 @@ dependencies = [
"x11-dl",
]
[[package]]
name = "winreg"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]
[[package]]
name = "winres"
version = "0.1.12"

View file

@ -39,7 +39,7 @@ num_cpus = "1.13.1"
num-format = "0.4.0"
rand = "0.8.5"
regex = "1.6.0"
reqwest = { version = "0.11.12", features = ["blocking", "json"] }
#reqwest = { version = "0.11.12", features = ["blocking", "json"] }
rfd = "0.10.0"
rusqlite = { version = "0.28.0", features = ["bundled"] }
serde = { version = "1.0.145", features = ["rc", "derive"] }

BIN
images/ferris/happy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View file

@ -85,7 +85,7 @@ r#"Use advanced settings:
- P2Pool Main/Mini selection
- Out/In peer setting
- Log level setting"#;
pub const P2POOL_NAME: &'static str = "Add a unique name to identify this node; Only [A-Za-z0-9-_] and spaces allowed; Max length = 30 characters";
pub const P2POOL_NAME: &'static str = "Add a unique name to identify this node; Only [A-Za-z0-9-_] and spaces allowed, if the name already exists, the current settings will be saved to the already existing entry; Max length = 30 characters";
pub const P2POOL_NODE_IP: &'static str = "Specify the Monero Node IP to connect to with P2Pool; It must be a valid IPv4 address or a valid domain name; Max length = 255 characters";
pub const P2POOL_RPC_PORT: &'static str = "Specify the RPC port of the Monero node; [1-65535]";
pub const P2POOL_ZMQ_PORT: &'static str = "Specify the ZMQ port of the Monero node; [1-65535]";
@ -106,15 +106,17 @@ pub const XMRIG_PRIORITY: &'static str = "Set process priority (0 idle, 2 normal
// CLI argument messages
pub const ARG_HELP: &'static str =
r#"USAGE: ./gupax [--flags]
r#"USAGE: ./gupax [--flag]
-h | --help Print this help message
-v | --version Print version and build info
-l | --node-list Print the manual node list
-s | --state Print Gupax state
-n | --no-startup Disable all auto-startup settings for this instance
-r | --reset Reset all Gupax state and the manual node list
-f | --ferris Print an extremely cute crab
--help Print this help message
--version Print version and build info
--state Print Gupax state
--nodes Print the manual node list
--no-startup Disable all auto-startup settings for this instance
--reset-state Reset all Gupax state (your settings)
--reset-nodes Reset the manual node list in the [P2Pool] tab
--reset-all Reset both the state and the manual node list
--ferris Print an extremely cute crab
To view more detailed console debug information, start Gupax with
the environment variable [RUST_LOG] set to a log level like so:

View file

@ -179,7 +179,7 @@ impl State {
}
// Convert [String] to [State]
pub fn from_string(string: String) -> Result<Self, TomlError> {
pub fn from_string(string: &String) -> Result<Self, TomlError> {
match toml::de::from_str(&string) {
Ok(state) => {
info!("State | Parse ... OK");
@ -187,7 +187,7 @@ impl State {
Ok(state)
}
Err(err) => {
error!("State | String -> State ... FAIL ... {}", err);
warn!("State | String -> State ... FAIL ... {}", err);
Err(TomlError::Deserialize(err))
},
}
@ -207,11 +207,20 @@ impl State {
// Create
_ => {
Self::create_new()?;
read_to_string(file, &path)?
match read_to_string(file, &path) {
Ok(s) => s,
Err(e) => return Err(e),
}
},
};
// Deserialize
Self::from_string(string)
// Deserialize, attempt merge if failed
match Self::from_string(&string) {
Ok(s) => Ok(s),
Err(e) => {
warn!("State | Attempting merge...");
Self::merge(string)
},
}
}
// Completely overwrite current [state.toml]
@ -250,22 +259,17 @@ impl State {
}
}
// Take [Self] as input, merge it with whatever the current [default] is,
// Take [String] as input, merge it with whatever the current [default] is,
// leaving behind old keys+values and updating [default] with old valid ones.
// Automatically overwrite current file.
pub fn merge(old: &Self) -> Result<Self, TomlError> {
info!("Starting TOML merge...");
let old = match toml::ser::to_string(&old) {
Ok(string) => { info!("Old TOML parse ... OK"); string },
Err(err) => { error!("Couldn't parse old TOML into string"); return Err(TomlError::Serialize(err)) },
};
pub fn merge(old: String) -> Result<Self, TomlError> {
let default = match toml::ser::to_string(&Self::new()) {
Ok(string) => { info!("Default TOML parse ... OK"); string },
Err(err) => { error!("Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
Ok(string) => { info!("State | Default TOML parse ... OK"); string },
Err(err) => { error!("State | Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
};
let mut new: Self = match Figment::new().merge(Toml::string(&old)).merge(Toml::string(&default)).extract() {
Ok(new) => { info!("TOML merge ... OK"); new },
Err(err) => { error!("Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
Ok(new) => { info!("State | TOML merge ... OK"); new },
Err(err) => { error!("State | Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
};
// Attempt save
Self::save(&mut new)?;
@ -298,7 +302,7 @@ impl Node {
}
// Convert [String] to [Node] Vec
pub fn from_string(string: String) -> Result<Vec<(String, Self)>, TomlError> {
pub fn from_string_to_vec(string: &String) -> Result<Vec<(String, Self)>, TomlError> {
let nodes: toml::map::Map<String, toml::Value> = match toml::de::from_str(&string) {
Ok(map) => {
info!("Node | Parse ... OK");
@ -312,7 +316,6 @@ impl Node {
let size = nodes.keys().len();
let mut vec = Vec::with_capacity(size);
for (key, values) in nodes.iter() {
// println!("{:#?}", values.get("ip")); std::process::exit(0);
let node = Node {
ip: values.get("ip").unwrap().as_str().unwrap().to_string(),
rpc: values.get("rpc").unwrap().as_str().unwrap().to_string(),
@ -357,8 +360,8 @@ impl Node {
read_to_string(file, &path)?
},
};
// Deserialize
Self::from_string(string)
// Deserialize, attempt merge if failed
Self::from_string_to_vec(&string)
}
// Completely overwrite current [node.toml]
@ -380,26 +383,19 @@ impl Node {
let string = Self::to_string(vec);
match fs::write(path, string) {
Ok(_) => { info!("TOML save ... OK"); Ok(()) },
Err(err) => { error!("Couldn't overwrite TOML file"); return Err(TomlError::Io(err)) },
Err(err) => { error!("Couldn't overwrite TOML file"); Err(TomlError::Io(err)) },
}
}
// // Take [Self] as input, merge it with whatever the current [default] is,
// // leaving behind old keys+values and updating [default] with old valid ones.
// // Automatically overwrite current file.
// pub fn merge(old: &Self) -> Result<Self, TomlError> {
// info!("Starting TOML merge...");
// let old = match toml::ser::to_string(&old) {
// Ok(string) => { info!("Old TOML parse ... OK"); string },
// Err(err) => { error!("Couldn't parse old TOML into string"); return Err(TomlError::Serialize(err)) },
// };
// pub fn merge(old: &String) -> Result<Self, TomlError> {
// info!("Node | Starting TOML merge...");
// let default = match toml::ser::to_string(&Self::new()) {
// Ok(string) => { info!("Default TOML parse ... OK"); string },
// Err(err) => { error!("Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
// Ok(string) => { info!("Node | Default TOML parse ... OK"); string },
// Err(err) => { error!("Node | Couldn't parse default TOML into string"); return Err(TomlError::Serialize(err)) },
// };
// let mut new: Self = match Figment::new().merge(Toml::string(&old)).merge(Toml::string(&default)).extract() {
// Ok(new) => { info!("TOML merge ... OK"); new },
// Err(err) => { error!("Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
// Ok(new) => { info!("Node | TOML merge ... OK"); new },
// Err(err) => { error!("Node | Couldn't merge default + old TOML"); return Err(TomlError::Merge(err)) },
// };
// // Attempt save
// Self::save(&mut new)?;
@ -408,15 +404,24 @@ impl Node {
}
//---------------------------------------------------------------------------------------------------- Custom Error [TomlError]
#[derive(Debug)]
pub enum TomlError {
Io(std::io::Error),
Path(String),
Serialize(toml::ser::Error),
Deserialize(toml::de::Error),
Merge(figment::Error),
}
impl Display for TomlError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use TomlError::*;
match self {
Io(err) => write!(f, "{}: {} | {}", ERROR, self, err),
Path(err) => write!(f, "{}: {} | {}", ERROR, self, err),
Serialize(err) => write!(f, "{}: {} | {}", ERROR, self, err),
Deserialize(err) => write!(f, "{}: {} | {}", ERROR, self, err),
Merge(err) => write!(f, "{}: {} | {}", ERROR, self, err),
Io(err) => write!(f, "{}: IO | {}", ERROR, err),
Path(err) => write!(f, "{}: Path | {}", ERROR, err),
Serialize(err) => write!(f, "{}: Serialize | {}", ERROR, err),
Deserialize(err) => write!(f, "{}: Deserialize | {}", ERROR, err),
Merge(err) => write!(f, "{}: Merge | {}", ERROR, err),
}
}
}
@ -447,16 +452,6 @@ pub const DEFAULT_XMRIG_PATH: &'static str = r"XMRig\xmrig.exe";
#[cfg(target_family = "unix")]
pub const DEFAULT_XMRIG_PATH: &'static str = "xmrig/xmrig";
//---------------------------------------------------------------------------------------------------- Error Enum
#[derive(Debug)]
pub enum TomlError {
Io(std::io::Error),
Path(String),
Serialize(toml::ser::Error),
Deserialize(toml::de::Error),
Merge(figment::Error),
}
//---------------------------------------------------------------------------------------------------- [File] Enum (for matching which file)
#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
pub enum File {

View file

@ -17,6 +17,7 @@
// Some images of ferris in byte form for error messages, etc
pub const FERRIS_HAPPY: &[u8] = include_bytes!("../images/ferris/happy.png");
pub const FERRIS_OOPS: &[u8] = include_bytes!("../images/ferris/oops.png");
pub const FERRIS_ERROR: &[u8] = include_bytes!("../images/ferris/error.png");
pub const FERRIS_PANIC: &[u8] = include_bytes!("../images/ferris/panic.png"); // This isnt technically ferris but its ok since its spooky
@ -35,7 +36,6 @@ pub const FERRIS_PANIC: &[u8] = include_bytes!("../images/ferris/panic.png"); //
// This is the ANSI representation of Ferris in string form.
// Calling [println!] on this straight up prints a 256-bit color Ferris to the terminal.
// The ANSI codes were generated with [https://docs.rs/ansipix], but there is no reason to include the library and

View file

@ -86,7 +86,6 @@ pub struct App {
xmrig: bool, // Is xmrig online?
// State from [--flags]
no_startup: bool,
reset: bool,
// Static stuff
now: Instant, // Internal timer
exe: String, // Path for [Gupax] binary
@ -128,7 +127,6 @@ impl App {
p2pool: false,
xmrig: false,
no_startup: false,
reset: false,
now: Instant::now(),
exe: "".to_string(),
dir: "".to_string(),
@ -157,18 +155,42 @@ impl App {
Ok(dir) => dir,
Err(err) => { panic_main(err.to_string()); exit(1); },
};
// Read disk state if no [--reset] arg
if app.reset == false {
app.og = match State::get() {
Ok(toml) => Arc::new(Mutex::new(toml)),
Err(err) => { panic_main(err.to_string()); exit(1); },
};
}
let mut og = app.og.lock().unwrap(); // Lock [og]
app.state = og.clone();
// Get node list
app.og_node_vec = Node::get().unwrap();
// Read disk state
use TomlError::*;
app.state = match State::get() {
Ok(toml) => toml,
Err(err) => {
error!("State ... {}", err);
match err {
Io(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Path(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Serialize(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Deserialize(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Merge(e) => app.error_state.set(true, format!("State file: {}", e), ErrorFerris::Error, ErrorButtons::ResetState),
};
State::new()
},
};
app.og = Arc::new(Mutex::new(app.state.clone()));
// Read node list
app.og_node_vec = match Node::get() {
Ok(toml) => toml,
Err(err) => {
error!("Node ... {}", err);
match err {
Io(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Path(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Serialize(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Deserialize(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
Merge(e) => app.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Error, ErrorButtons::ResetState),
};
Node::new_vec()
},
};
app.node_vec = app.og_node_vec.clone();
let mut og = app.og.lock().unwrap(); // Lock [og]
// Handle max threads
og.xmrig.max_threads = num_cpus::get();
let current = og.xmrig.current_threads;
@ -222,7 +244,7 @@ impl Default for Tab {
//---------------------------------------------------------------------------------------------------- [ErrorState] struct
pub struct ErrorState {
error: bool, // Is there an error?
msg: &'static str, // What message to display?
msg: String, // What message to display?
ferris: ErrorFerris, // Which ferris to display?
buttons: ErrorButtons, // Which buttons to display?
}
@ -231,17 +253,17 @@ impl ErrorState {
pub fn new() -> Self {
Self {
error: false,
msg: "Unknown Error",
msg: "Unknown Error".to_string(),
ferris: ErrorFerris::Oops,
buttons: ErrorButtons::Okay,
}
}
// Convenience function to set the [App] error state
pub fn set(&mut self, error: bool, msg: &'static str, ferris: ErrorFerris, buttons: ErrorButtons) {
pub fn set(&mut self, error: bool, msg: impl Into<String>, ferris: ErrorFerris, buttons: ErrorButtons) {
*self = Self {
error,
msg,
msg: msg.into(),
ferris,
buttons,
};
@ -253,12 +275,15 @@ impl ErrorState {
pub enum ErrorButtons {
YesNo,
StayQuit,
ResetState,
ResetNode,
Okay,
Quit,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ErrorFerris {
Happy,
Oops,
Error,
Panic,
@ -267,6 +292,7 @@ pub enum ErrorFerris {
//---------------------------------------------------------------------------------------------------- [Images] struct
struct Images {
banner: RetainedImage,
happy: RetainedImage,
oops: RetainedImage,
error: RetainedImage,
panic: RetainedImage,
@ -276,6 +302,7 @@ impl Images {
fn new() -> Self {
Self {
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(),
happy: RetainedImage::from_image_bytes("happy.png", FERRIS_HAPPY).unwrap(),
oops: RetainedImage::from_image_bytes("oops.png", FERRIS_OOPS).unwrap(),
error: RetainedImage::from_image_bytes("error.png", FERRIS_ERROR).unwrap(),
panic: RetainedImage::from_image_bytes("panic.png", FERRIS_PANIC).unwrap(),
@ -388,6 +415,9 @@ fn init_auto(app: &App) {
if app.no_startup {
info!("[--no-startup] flag passed, skipping init_auto()...");
return
} else if app.error_state.error {
info!("App error detected, skipping init_auto()...");
return
} else {
info!("Starting init_auto()...");
}
@ -442,17 +472,31 @@ fn init_auto(app: &App) {
}
}
fn reset() {
let mut code = 0;
fn reset_state() -> Result<(), TomlError> {
info!("Resetting [state.toml]...");
match State::create_new() {
Ok(_) => info!("Resetting [state.toml] ... OK"),
Err(e) => { error!("Resetting [state.toml] ... FAIL ... {}", e); code = 1; },
Ok(_) => { info!("Resetting [state.toml] ... OK"); Ok(()) },
Err(e) => { error!("Resetting [state.toml] ... FAIL ... {}", e); Err(e) },
}
}
fn reset_nodes() -> Result<(), TomlError> {
info!("Resetting [node.toml]...");
match Node::create_new() {
Ok(_) => info!("Resetting [node.toml] ... OK"),
Err(e) => { error!("Resetting [node.toml] ... FAIL ... {}", e); code = 1; },
Ok(_) => { info!("Resetting [node.toml] ... OK"); Ok(()) },
Err(e) => { error!("Resetting [node.toml] ... FAIL ... {}", e); Err(e) },
}
}
fn reset() {
let mut code = 0;
match reset_state() {
Ok(_) => (),
Err(_) => code = 1,
}
match reset_nodes() {
Ok(_) => (),
Err(_) => code = 1,
}
match code {
0 => println!("\nGupax files were reset successfully."),
@ -469,23 +513,25 @@ fn parse_args(mut app: App) -> App {
// [help/version], exit early
for arg in &args {
match arg.as_str() {
"-h"|"--help" => { println!("{}", ARG_HELP); exit(0); },
"-v"|"--version" => {
"--help" => { println!("{}", ARG_HELP); exit(0); },
"--version" => {
println!("Gupax {} [OS: {}, Commit: {}]\n\n{}", GUPAX_VERSION, OS_NAME, &COMMIT[..40], ARG_COPYRIGHT);
exit(0);
},
"-f"|"--ferris" => { println!("{}", FERRIS_ANSI); exit(0); },
"--ferris" => { println!("{}", FERRIS_ANSI); exit(0); },
_ => (),
}
}
// Everything else
for arg in args {
match arg.as_str() {
"-l"|"--node-list" => { info!("Printing node list..."); print_disk_file(File::Node); }
"-s"|"--state" => { info!("Printing state..."); print_disk_file(File::State); }
"-r"|"--reset" => { reset(); }
"-n"|"--no-startup" => { app.no_startup = true; }
_ => { eprintln!("[Gupax error] Invalid option: [{}]\nFor help, use: [--help]", arg); exit(1); },
"--nodes" => { info!("Printing node list..."); print_disk_file(File::Node); }
"--state" => { info!("Printing state..."); print_disk_file(File::State); }
"--reset-state" => if let Ok(()) = reset_state() { exit(0) } else { exit(1) },
"--reset-nodes" => if let Ok(()) = reset_nodes() { exit(0) } else { exit(1) },
"--reset-all" => reset(),
"--no-startup" => app.no_startup = true,
_ => { eprintln!("[Gupax error] Invalid option: [{}]\nFor help, use: [--help]", arg); exit(1); },
}
}
app
@ -604,14 +650,6 @@ fn main() {
}
impl eframe::App for App {
// pub fn new() -> Self {
// Self {
// error: false,
// msg: String::new(),
// image: RetainedImage::from_image_bytes("banner.png", FERRIS_ERROR).unwrap(),
// buttons: ErrorButtons::Okay,
// }
// }
fn on_close_event(&mut self) -> bool {
if self.state.gupax.ask_before_quit {
self.error_state.set(true, "", ErrorFerris::Oops, ErrorButtons::StayQuit);
@ -652,8 +690,10 @@ impl eframe::App for App {
// Display ferris
use ErrorFerris::*;
use ErrorButtons::*;
let ferris = match self.error_state.ferris {
Oops => &self.img.oops,
Happy => &self.img.happy,
Oops => &self.img.oops,
Error => &self.img.error,
Panic => &self.img.panic,
};
@ -669,12 +709,23 @@ impl eframe::App for App {
ui.add_sized([width, height], Label::new("--- Are you sure you want to quit? ---"));
ui.add_sized([width, height], Label::new(text))
},
ResetState => {
ui.add_sized([width, height], Label::new(format!("--- Gupax has encountered an error! ---\n{}", &self.error_state.msg)));
ui.add_sized([width, height], Label::new("Reset Gupax state? (Your settings)"))
},
ResetNode => {
ui.add_sized([width, height], Label::new(format!("--- Gupax has encountered an error! ---\n{}", &self.error_state.msg)));
ui.add_sized([width, height], Label::new("Reset the manual node list?"))
},
_ => {
ui.add_sized([width, height], Label::new("--- Gupax has encountered an error! ---"));
ui.add_sized([width, height], Label::new(self.error_state.msg))
match self.error_state.ferris {
Panic => ui.add_sized([width, height], Label::new("--- Gupax has encountered an un-recoverable error! ---")),
Happy => ui.add_sized([width, height], Label::new("--- Success! ---")),
_ => ui.add_sized([width, height], Label::new("--- Gupax has encountered an error! ---")),
};
ui.add_sized([width, height], Label::new(&self.error_state.msg))
},
};
use ErrorButtons::*;
let height = ui.available_height();
// Capture [Esc] key
@ -693,8 +744,47 @@ impl eframe::App for App {
}
if ui.add_sized([width, height/2.0], egui::Button::new("Quit")).clicked() { exit(0); }
},
// This code handles the [state.toml/node.toml] resetting, [panic!]'ing if it errors once more
// Another error after this either means an IO error or permission error, which Gupax can't fix.
// [Yes/No] buttons
ResetState => {
if ui.add_sized([width, height/2.0], egui::Button::new("Yes")).clicked() {
match reset_state() {
Ok(_) => {
match State::get() {
Ok(s) => {
self.state = s;
self.og = Arc::new(Mutex::new(self.state.clone()));
self.error_state.set(true, "State read OK", ErrorFerris::Happy, ErrorButtons::Okay);
},
Err(e) => self.error_state.set(true, format!("State read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
}
},
Err(e) => self.error_state.set(true, format!("State reset fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
};
}
if esc || ui.add_sized([width, height/2.0], egui::Button::new("No")).clicked() { self.error_state = ErrorState::new() }
},
ResetNode => {
if ui.add_sized([width, height/2.0], egui::Button::new("Yes")).clicked() {
match reset_nodes() {
Ok(_) => {
match Node::get() {
Ok(s) => {
self.node_vec = s;
self.og_node_vec = self.node_vec.clone();
self.error_state.set(true, "Node read OK", ErrorFerris::Happy, ErrorButtons::Okay);
},
Err(e) => self.error_state.set(true, format!("Node read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
}
},
Err(e) => self.error_state.set(true, format!("Node reset fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
};
}
if esc || ui.add_sized([width, height/2.0], egui::Button::new("No")).clicked() { self.error_state = ErrorState::new() }
},
Okay => if esc || ui.add_sized([width, height], egui::Button::new("Okay")).clicked() { self.error_state = ErrorState::new(); },
Quit => if ui.add_sized([width, height], egui::Button::new("Quit")).clicked() { exit(0); },
Quit => if ui.add_sized([width, height], egui::Button::new("Quit")).clicked() { exit(1); },
}
})});
return
@ -777,13 +867,21 @@ impl eframe::App for App {
self.node_vec = self.og_node_vec.clone();
}
if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() {
let mut og = self.og.lock().unwrap();
og.gupax = self.state.gupax.clone();
og.p2pool = self.state.p2pool.clone();
og.xmrig = self.state.xmrig.clone();
self.og_node_vec = self.node_vec.clone();
self.state.save();
Node::save(&self.og_node_vec);
match self.state.save() {
Ok(_) => {
let mut og = self.og.lock().unwrap();
og.gupax = self.state.gupax.clone();
og.p2pool = self.state.p2pool.clone();
og.xmrig = self.state.xmrig.clone();
},
Err(e) => {
self.error_state.set(true, format!("State file: {}", e), ErrorFerris::Error, ErrorButtons::Okay);
},
};
match Node::save(&self.og_node_vec) {
Ok(_) => self.og_node_vec = self.node_vec.clone(),
Err(e) => self.error_state.set(true, format!("Node list: {}", e), ErrorFerris::Error, ErrorButtons::Okay),
};
}
});
@ -872,7 +970,7 @@ impl eframe::App for App {
ui.add_space(ui.available_height()/2.0);
ui.hyperlink_to("Powered by egui", "https://github.com/emilk/egui");
ui.hyperlink_to(format!("{} {}", GITHUB, "Gupax made by hinto-janaiyo"), "https://www.github.com/hinto-janaiyo/gupax");
ui.hyperlink_to(format!("{} {}", GITHUB, "Made by hinto-janaiyo"), "https://gupax.io");
ui.label("egui is licensed under MIT & Apache-2.0");
ui.label("Gupax, P2Pool, and XMRig are licensed under GPLv3");
});

View file

@ -27,8 +27,6 @@ use log::*;
// header::{HeaderValue,LOCATION},
//};
use reqwest::blocking::ClientBuilder;
//---------------------------------------------------------------------------------------------------- Node list
// Community Monerod nodes. All of these have ZMQ on 18083.
// Adding/removing nodes will need changes to pretty

View file

@ -332,7 +332,7 @@ impl P2pool {
let text = format!("{}\n Currently selected node: {}. {}\n Current amount of nodes: {}/1000", text, self.selected_index, self.selected_name, node_vec_len);
// If the node already exists, show [Save] and mutate the already existing node
if exists {
ui.set_enabled(save_diff);
ui.set_enabled(!incorrect_input && save_diff);
if ui.add_sized([width, text_edit], Button::new("Save")).on_hover_text(text).clicked() {
let node = Node {
ip: self.ip.clone(),