diff --git a/src/gui/views/content.rs b/src/gui/views/content.rs index 0a1d4ae..55ffbba 100644 --- a/src/gui/views/content.rs +++ b/src/gui/views/content.rs @@ -138,7 +138,7 @@ impl Content { if self.first_draw { // Show crash report if needed. - if AppConfig::show_crash() { + if Settings::crash_report_path().exists() { Modal::new(Self::CRASH_REPORT_MODAL) .closeable(false) .position(ModalPosition::Center) @@ -415,10 +415,10 @@ impl Content { let text = format!("{} {}", FILE_X, t!("share")); View::colored_text_button(ui, text, Colors::blue(), Colors::white_or_black(false), || { if let Ok(data) = fs::read_to_string(Settings::crash_report_path()) { - cb.share_data(Settings::CRASH_REPORT_FILE_NAME.to_string(), - data.as_bytes().to_vec()).unwrap_or_default() + let name = Settings::CRASH_REPORT_FILE_NAME.to_string(); + let _ = cb.share_data(name, data.as_bytes().to_vec()); } - AppConfig::set_show_crash(false); + Settings::delete_crash_report(); modal.close(); }); }); @@ -427,7 +427,7 @@ impl Content { ui.add_space(8.0); ui.vertical_centered_justified(|ui| { View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || { - AppConfig::set_show_crash(false); + Settings::delete_crash_report(); modal.close(); }); }); diff --git a/src/main.rs b/src/main.rs index 49c0eb5..9315e4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,25 +43,39 @@ fn real_main() { // Setup callback on panic crash. std::panic::set_hook(Box::new(|info| { - let backtrace = backtrace::Backtrace::new(); // Format error. + let backtrace = backtrace::Backtrace::new(); let time = grim::gui::views::View::format_time(chrono::Utc::now().timestamp()); - let target = egui::os::OperatingSystem::from_target_os(); + let os = egui::os::OperatingSystem::from_target_os(); let ver = grim::VERSION; let msg = panic_info_message(info); - let err = format!("{} - {:?} - v{}\n\n{}\n\n{:?}", time, target, ver, msg, backtrace); + let loc = if let Some(location) = info.location() { + format!("{}:{}:{}", location.file(), location.line(), location.column()) + } else { + "no location found.".parse().unwrap() + }; + let err = format!("{} - {:?} - v{}\n{}\n{}\n\n{:?}", time, os, ver, msg, loc, backtrace); // Save backtrace to file. let log = grim::Settings::crash_report_path(); if log.exists() { - let _ = std::fs::remove_file(log.clone()); + use std::io::{Seek, SeekFrom, Write}; + let mut file = std::fs::OpenOptions::new() + .write(true) + .append(true) + .open(log) + .unwrap(); + if file.seek(SeekFrom::End(0)).is_ok() { + file.write(err.as_bytes()).unwrap_or_default(); + } + } else { + std::fs::write(log, err.as_bytes()).unwrap_or_default(); } - std::fs::write(log, err.as_bytes()).unwrap(); - // Setup flag to show crash after app restart. - grim::AppConfig::set_show_crash(true); + // Print message error. + println!("{}\n{}", msg, loc); })); // Start GUI. - match std::panic::catch_unwind(|| { + let _ = std::panic::catch_unwind(|| { if is_app_running(&data) { return; } else if let Some(data) = data { @@ -70,16 +84,13 @@ fn real_main() { let platform = grim::gui::platform::Desktop::new(); start_app_socket(platform.clone()); start_desktop_gui(platform); - }) { - Ok(_) => {} - Err(e) => println!("{:?}", e) - } + }); } /// Get panic message from crash payload. #[allow(dead_code)] #[cfg(not(target_os = "android"))] -fn panic_info_message<'pi>(panic_info: &'pi std::panic::PanicInfo<'_>) -> &'pi str { +fn panic_info_message<'pi>(panic_info: &'pi std::panic::PanicHookInfo<'_>) -> &'pi str { let payload = panic_info.payload(); // taken from: https://github.com/rust-lang/rust/blob/4b9f4b221b92193c7e95b1beb502c6eb32c3b613/library/std/src/panicking.rs#L194-L200 match payload.downcast_ref::<&'static str>() { @@ -114,7 +125,7 @@ fn start_desktop_gui(platform: grim::gui::platform::Desktop) { .with_min_inner_size([AppConfig::MIN_WIDTH, AppConfig::MIN_HEIGHT]) .with_inner_size([width, height]); - // Setup an icon. + // Setup icon. if let Ok(icon) = eframe::icon_data::from_png_bytes(include_bytes!("../img/icon.png")) { viewport = viewport.with_icon(std::sync::Arc::new(icon)); } @@ -176,19 +187,15 @@ fn is_app_running(data: &Option) -> bool { let res: Result<(), Box> = runtime .block_on(async { use interprocess::local_socket::{ - tokio::{prelude::*, Stream}, - GenericFilePath, GenericNamespaced + tokio::{prelude::*, Stream} }; use tokio::{ io::AsyncWriteExt, }; let socket_path = grim::Settings::socket_path(); - let name = if GenericNamespaced::is_supported() { - grim::Settings::SOCKET_NAME.to_ns_name::()? - } else { - socket_path.clone().to_fs_name::()? - }; + let name = grim::Settings::socket_name(&socket_path)?; + // Connect to running application socket. let conn = Stream::connect(name).await?; let data = data.clone().unwrap_or("".to_string()); @@ -203,7 +210,7 @@ fn is_app_running(data: &Option) -> bool { drop((rec, sen)); Ok(()) }); - return match res { + match res { Ok(_) => true, Err(_) => false } @@ -220,7 +227,7 @@ fn start_app_socket(platform: grim::gui::platform::Desktop) { .block_on(async { use interprocess::local_socket::{ tokio::{prelude::*, Stream}, - GenericFilePath, GenericNamespaced, Listener, ListenerOptions, + Listener, ListenerOptions, }; use std::io; use tokio::{ @@ -238,15 +245,12 @@ fn start_app_socket(platform: grim::gui::platform::Desktop) { Ok(buffer) } + // Setup socket name. let socket_path = grim::Settings::socket_path(); - let name = if GenericNamespaced::is_supported() { - grim::Settings::SOCKET_NAME.to_ns_name::()? - } else { - socket_path.clone().to_fs_name::()? - }; if socket_path.exists() { - let _ = std::fs::remove_file(socket_path); + let _ = std::fs::remove_file(&socket_path); } + let name = grim::Settings::socket_name(&socket_path)?; // Create listener. let opts = ListenerOptions::new().name(name); diff --git a/src/settings/config.rs b/src/settings/config.rs index e764ab3..e4db640 100644 --- a/src/settings/config.rs +++ b/src/settings/config.rs @@ -49,9 +49,6 @@ pub struct AppConfig { /// Flag to check if dark theme should be used, use system settings if not set. use_dark_theme: Option, - - /// Flag to show crash report when happened. - show_crash: Option } impl Default for AppConfig { @@ -68,7 +65,6 @@ impl Default for AppConfig { y: None, lang: None, use_dark_theme: None, - show_crash: None, } } } @@ -241,17 +237,4 @@ impl AppConfig { w_config.use_dark_theme = Some(use_dark); w_config.save(); } - - /// Check if crash report should be shown on application start. - pub fn show_crash() -> bool { - let r_config = Settings::app_config_to_read(); - r_config.show_crash.unwrap_or(false) - } - - /// Setup flag to show crash report on application start. - pub fn set_show_crash(show: bool) { - let mut w_config = Settings::app_config_to_update(); - w_config.show_crash = Some(show); - w_config.save(); - } } \ No newline at end of file diff --git a/src/settings/settings.rs b/src/settings/settings.rs index c065f59..a1a95f7 100644 --- a/src/settings/settings.rs +++ b/src/settings/settings.rs @@ -13,15 +13,17 @@ // limitations under the License. use std::fs::{self, File}; +use std::io; use std::io::Write; use std::path::PathBuf; use std::sync::Arc; +use egui::os::OperatingSystem; use lazy_static::lazy_static; use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use serde::de::DeserializeOwned; use serde::Serialize; - use grin_config::ConfigError; +use interprocess::local_socket::{GenericFilePath, GenericNamespaced, Name, NameType, ToFsName, ToNsName}; use crate::node::NodeConfig; use crate::settings::AppConfig; @@ -127,10 +129,7 @@ impl Settings { /// Get base directory path for configuration. pub fn base_path(sub_dir: Option) -> PathBuf { // Check if dir exists. - let mut path = match dirs::home_dir() { - Some(p) => p, - None => PathBuf::new(), - }; + let mut path = dirs::home_dir().unwrap_or_else(|| PathBuf::new()); path.push(Self::MAIN_DIR_NAME); if sub_dir.is_some() { path.push(sub_dir.unwrap()); @@ -149,20 +148,39 @@ impl Settings { socket_path } - /// Get configuration file path from provided name and sub-directory if needed. + /// Get desktop application socket name from provided path. + pub fn socket_name(path: &PathBuf) -> io::Result { + let name = if OperatingSystem::Mac != OperatingSystem::from_target_os() && + GenericNamespaced::is_supported() { + Self::SOCKET_NAME.to_ns_name::()? + } else { + path.clone().to_fs_name::()? + }; + Ok(name) + } + + /// Get configuration file path from provided name and subdirectory if needed. pub fn config_path(config_name: &str, sub_dir: Option) -> PathBuf { let mut path = Self::base_path(sub_dir); path.push(config_name); path } - /// Get configuration file path from provided name and sub-directory if needed. + /// Get configuration file path from provided name and subdirectory if needed. pub fn crash_report_path() -> PathBuf { let mut path = Self::base_path(None); path.push(Self::CRASH_REPORT_FILE_NAME); path } + /// Delete crash report file. + pub fn delete_crash_report() { + let log = Self::crash_report_path(); + if log.exists() { + let _ = fs::remove_file(log.clone()); + } + } + /// Read configuration from the file. pub fn read_from_file(config_path: PathBuf) -> Result { let file_content = fs::read_to_string(config_path.clone())?;