feat: crash report
This commit is contained in:
parent
92eb5f59ad
commit
f3db1005b5
15 changed files with 182 additions and 68 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -3803,6 +3803,7 @@ dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"arti-client",
|
"arti-client",
|
||||||
"arti-hyper",
|
"arti-hyper",
|
||||||
|
"backtrace",
|
||||||
"chrono",
|
"chrono",
|
||||||
"curve25519-dalek 4.1.3",
|
"curve25519-dalek 4.1.3",
|
||||||
"dark-light",
|
"dark-light",
|
||||||
|
@ -3839,6 +3840,7 @@ dependencies = [
|
||||||
"nokhwa",
|
"nokhwa",
|
||||||
"openpnp_capture_sys",
|
"openpnp_capture_sys",
|
||||||
"openssl-sys",
|
"openssl-sys",
|
||||||
|
"panic-message",
|
||||||
"parking_lot 0.12.3",
|
"parking_lot 0.12.3",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"qrcodegen",
|
"qrcodegen",
|
||||||
|
@ -6563,6 +6565,12 @@ dependencies = [
|
||||||
"sha2 0.10.8",
|
"sha2 0.10.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "panic-message"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "384e52fd8fbd4cbe3c317e8216260c21a0f9134de108cea8a4dd4e7e152c472d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
|
|
@ -16,6 +16,9 @@ path = "src/main.rs"
|
||||||
name="grim"
|
name="grim"
|
||||||
crate-type = ["rlib"]
|
crate-type = ["rlib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = 1
|
||||||
|
|
||||||
[profile.release-apk]
|
[profile.release-apk]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
strip = true
|
strip = true
|
||||||
|
@ -51,6 +54,8 @@ egui_extras = { version = "0.28.1", features = ["image", "svg"] }
|
||||||
rust-i18n = "2.3.1"
|
rust-i18n = "2.3.1"
|
||||||
|
|
||||||
## other
|
## other
|
||||||
|
backtrace = "0.3"
|
||||||
|
panic-message = "0.3.0"
|
||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
|
|
|
@ -26,6 +26,8 @@ theme: 'Theme:'
|
||||||
dark: Dunkel
|
dark: Dunkel
|
||||||
light: Hell
|
light: Hell
|
||||||
choose_file: Datei auswählen
|
choose_file: Datei auswählen
|
||||||
|
crash_report: Absturzbericht
|
||||||
|
crash_report_warning: Anwendung wurde beim letzten Mal unerwartet geschlossen, Sie können den Absturzbericht mit Entwicklern teilen.
|
||||||
wallets:
|
wallets:
|
||||||
await_conf_amount: Erwarte Bestätigung
|
await_conf_amount: Erwarte Bestätigung
|
||||||
await_fin_amount: Warten auf die Fertigstellung
|
await_fin_amount: Warten auf die Fertigstellung
|
||||||
|
|
|
@ -26,6 +26,8 @@ theme: 'Theme:'
|
||||||
dark: Dark
|
dark: Dark
|
||||||
light: Light
|
light: Light
|
||||||
choose_file: Choose file
|
choose_file: Choose file
|
||||||
|
crash_report: Crash report
|
||||||
|
crash_report_warning: Application closed unexpectedly last time, you can share crash report with developers.
|
||||||
wallets:
|
wallets:
|
||||||
await_conf_amount: Awaiting confirmation
|
await_conf_amount: Awaiting confirmation
|
||||||
await_fin_amount: Awaiting finalization
|
await_fin_amount: Awaiting finalization
|
||||||
|
|
|
@ -26,6 +26,8 @@ theme: 'Thème:'
|
||||||
dark: Sombre
|
dark: Sombre
|
||||||
light: Clair
|
light: Clair
|
||||||
choose_file: Choisir un fichier
|
choose_file: Choisir un fichier
|
||||||
|
crash_report: Rapport d'échec
|
||||||
|
crash_report_warning: L'application s'est fermée de manière inattendue la dernière fois, vous pouvez partager un rapport d'incident avec les développeurs.
|
||||||
wallets:
|
wallets:
|
||||||
await_conf_amount: En attente de confirmation
|
await_conf_amount: En attente de confirmation
|
||||||
await_fin_amount: En attente de finalisation
|
await_fin_amount: En attente de finalisation
|
||||||
|
|
|
@ -26,6 +26,8 @@ theme: 'Тема:'
|
||||||
dark: Тёмная
|
dark: Тёмная
|
||||||
light: Светлая
|
light: Светлая
|
||||||
choose_file: Выбрать файл
|
choose_file: Выбрать файл
|
||||||
|
crash_report: Отчёт о сбое
|
||||||
|
crash_report_warning: В прошлый раз приложение неожиданно закрылось, вы можете поделиться отчетом о сбое с разработчиками.
|
||||||
wallets:
|
wallets:
|
||||||
await_conf_amount: Ожидает подтверждения
|
await_conf_amount: Ожидает подтверждения
|
||||||
await_fin_amount: Ожидает завершения
|
await_fin_amount: Ожидает завершения
|
||||||
|
|
|
@ -26,6 +26,8 @@ theme: 'Tema:'
|
||||||
dark: Karanlik
|
dark: Karanlik
|
||||||
light: Isik
|
light: Isik
|
||||||
choose_file: Dosya seçin
|
choose_file: Dosya seçin
|
||||||
|
crash_report: Ariza Raporu
|
||||||
|
crash_report_warning: Uygulama beklenmedik bir sekilde kapandi son kez, kilitlenme raporunu gelistiricilerle paylasabilirsiniz.
|
||||||
wallets:
|
wallets:
|
||||||
await_conf_amount: Onay bekleniyor
|
await_conf_amount: Onay bekleniyor
|
||||||
await_fin_amount: Tamamlanma bekleniyor
|
await_fin_amount: Tamamlanma bekleniyor
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::fs;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use egui::os::OperatingSystem;
|
use egui::os::OperatingSystem;
|
||||||
use egui::{Align, Layout, RichText};
|
use egui::{Align, Layout, RichText};
|
||||||
|
@ -20,10 +21,10 @@ use lazy_static::lazy_static;
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, View};
|
use crate::gui::views::{Modal, View};
|
||||||
use crate::gui::views::types::ModalContainer;
|
use crate::gui::views::types::{ModalContainer, ModalPosition};
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use crate::AppConfig;
|
use crate::{AppConfig, Settings};
|
||||||
use crate::gui::icons::{CHECK, CHECK_FAT};
|
use crate::gui::icons::{CHECK, CHECK_FAT, FILE_X};
|
||||||
use crate::gui::views::network::{NetworkContent, NodeSetup};
|
use crate::gui::views::network::{NetworkContent, NodeSetup};
|
||||||
use crate::gui::views::wallets::WalletsContent;
|
use crate::gui::views::wallets::WalletsContent;
|
||||||
|
|
||||||
|
@ -63,9 +64,10 @@ impl Default for Content {
|
||||||
show_exit_progress: false,
|
show_exit_progress: false,
|
||||||
first_draw: true,
|
first_draw: true,
|
||||||
allowed_modal_ids: vec![
|
allowed_modal_ids: vec![
|
||||||
Self::EXIT_MODAL_ID,
|
Self::EXIT_CONFIRMATION_MODAL,
|
||||||
Self::SETTINGS_MODAL,
|
Self::SETTINGS_MODAL,
|
||||||
Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL,
|
Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL,
|
||||||
|
Self::CRASH_REPORT_MODAL
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,11 +81,12 @@ impl ModalContainer for Content {
|
||||||
fn modal_ui(&mut self,
|
fn modal_ui(&mut self,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
modal: &Modal,
|
modal: &Modal,
|
||||||
_: &dyn PlatformCallbacks) {
|
cb: &dyn PlatformCallbacks) {
|
||||||
match modal.id {
|
match modal.id {
|
||||||
Self::EXIT_MODAL_ID => self.exit_modal_content(ui, modal),
|
Self::EXIT_CONFIRMATION_MODAL => self.exit_modal_content(ui, modal),
|
||||||
Self::SETTINGS_MODAL => self.settings_modal_ui(ui, modal),
|
Self::SETTINGS_MODAL => self.settings_modal_ui(ui, modal),
|
||||||
Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL => self.android_warning_modal_ui(ui, modal),
|
Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL => self.android_warning_modal_ui(ui, modal),
|
||||||
|
Self::CRASH_REPORT_MODAL => self.crash_report_modal_ui(ui, modal, cb),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,12 +94,13 @@ impl ModalContainer for Content {
|
||||||
|
|
||||||
impl Content {
|
impl Content {
|
||||||
/// Identifier for exit confirmation [`Modal`].
|
/// Identifier for exit confirmation [`Modal`].
|
||||||
pub const EXIT_MODAL_ID: &'static str = "exit_confirmation_modal";
|
pub const EXIT_CONFIRMATION_MODAL: &'static str = "exit_confirmation_modal";
|
||||||
/// Identifier for wallet opening [`Modal`].
|
/// Identifier for wallet opening [`Modal`].
|
||||||
pub const SETTINGS_MODAL: &'static str = "settings_modal";
|
pub const SETTINGS_MODAL: &'static str = "settings_modal";
|
||||||
|
|
||||||
/// Identifier for integrated node warning [`Modal`] on Android.
|
/// Identifier for integrated node warning [`Modal`] on Android.
|
||||||
const ANDROID_INTEGRATED_NODE_WARNING_MODAL: &'static str = "android_node_warning_modal";
|
const ANDROID_INTEGRATED_NODE_WARNING_MODAL: &'static str = "android_node_warning_modal";
|
||||||
|
/// Identifier for crash report [`Modal`].
|
||||||
|
const CRASH_REPORT_MODAL: &'static str = "crash_report_modal";
|
||||||
|
|
||||||
/// Default width of side panel at application UI.
|
/// Default width of side panel at application UI.
|
||||||
pub const SIDE_PANEL_WIDTH: f32 = 400.0;
|
pub const SIDE_PANEL_WIDTH: f32 = 400.0;
|
||||||
|
@ -132,16 +136,23 @@ impl Content {
|
||||||
self.wallets.ui(ui, cb);
|
self.wallets.ui(ui, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if self.first_draw {
|
||||||
|
// Show crash report if needed.
|
||||||
|
if AppConfig::show_crash() {
|
||||||
|
Modal::new(Self::CRASH_REPORT_MODAL)
|
||||||
|
.closeable(false)
|
||||||
|
.position(ModalPosition::Center)
|
||||||
|
.title(t!("crash_report"))
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
// Show integrated node warning on Android if needed.
|
// Show integrated node warning on Android if needed.
|
||||||
if self.first_draw && OperatingSystem::from_target_os() == OperatingSystem::Android &&
|
if OperatingSystem::from_target_os() == OperatingSystem::Android &&
|
||||||
AppConfig::android_integrated_node_warning_needed() {
|
AppConfig::android_integrated_node_warning_needed() {
|
||||||
Modal::new(Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL)
|
Modal::new(Self::ANDROID_INTEGRATED_NODE_WARNING_MODAL)
|
||||||
.title(t!("network.node"))
|
.title(t!("network.node"))
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Setup first draw flag.
|
|
||||||
if self.first_draw {
|
|
||||||
self.first_draw = false;
|
self.first_draw = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,9 +198,9 @@ impl Content {
|
||||||
NETWORK_PANEL_OPEN.load(Ordering::Relaxed)
|
NETWORK_PANEL_OPEN.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show exit confirmation modal.
|
/// Show exit confirmation [`Modal`].
|
||||||
pub fn show_exit_modal() {
|
pub fn show_exit_modal() {
|
||||||
Modal::new(Self::EXIT_MODAL_ID)
|
Modal::new(Self::EXIT_CONFIRMATION_MODAL)
|
||||||
.title(t!("modal.confirmation"))
|
.title(t!("modal.confirmation"))
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
@ -383,7 +394,7 @@ impl Content {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
ui.label(RichText::new(t!("network.android_warning"))
|
ui.label(RichText::new(t!("network.android_warning"))
|
||||||
.size(15.0)
|
.size(16.0)
|
||||||
.color(Colors::text(false)));
|
.color(Colors::text(false)));
|
||||||
});
|
});
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
@ -395,4 +406,38 @@ impl Content {
|
||||||
});
|
});
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw content for integrated node warning [`Modal`] on Android.
|
||||||
|
fn crash_report_modal_ui(&mut self,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
modal: &Modal,
|
||||||
|
cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("crash_report_warning"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::text(false)));
|
||||||
|
ui.add_space(6.0);
|
||||||
|
// Draw button to share crash report.
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
AppConfig::set_show_crash(false);
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(8.0);
|
||||||
|
View::horizontal_line(ui, Colors::item_stroke());
|
||||||
|
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);
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
}
|
||||||
}
|
}
|
65
src/main.rs
65
src/main.rs
|
@ -29,19 +29,41 @@ fn real_main() {
|
||||||
.parse_default_env()
|
.parse_default_env()
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
use grim::gui::platform::Desktop;
|
// Setup callback on panic crash.
|
||||||
use grim::gui::App;
|
std::panic::set_hook(Box::new(|info| {
|
||||||
|
let backtrace = backtrace::Backtrace::new();
|
||||||
|
// Format error.
|
||||||
|
let time = grim::gui::views::View::format_time(chrono::Utc::now().timestamp());
|
||||||
|
let target = egui::os::OperatingSystem::from_target_os();
|
||||||
|
let ver = grim::VERSION;
|
||||||
|
let msg = panic_message::panic_info_message(info);
|
||||||
|
let err = format!("{} - {:?} - v{}\n\n{}\n\n{:?}", time, target, ver, msg, backtrace);
|
||||||
|
// Save backtrace to file.
|
||||||
|
let log = grim::Settings::crash_report_path();
|
||||||
|
if log.exists() {
|
||||||
|
std::fs::remove_file(log.clone()).unwrap();
|
||||||
|
}
|
||||||
|
std::fs::write(log, err.as_bytes()).unwrap();
|
||||||
|
// Setup flag to show crash after app restart.
|
||||||
|
grim::AppConfig::set_show_crash(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Start GUI.
|
||||||
|
let _ = std::panic::catch_unwind(|| {
|
||||||
|
start_desktop_gui();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start GUI with Desktop related setup.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
|
fn start_desktop_gui() {
|
||||||
use grim::AppConfig;
|
use grim::AppConfig;
|
||||||
|
use dark_light::Mode;
|
||||||
|
|
||||||
use std::sync::Arc;
|
let platform = grim::gui::platform::Desktop::default();
|
||||||
use egui::pos2;
|
|
||||||
use egui::os::OperatingSystem;
|
|
||||||
use eframe::icon_data::from_png_bytes;
|
|
||||||
|
|
||||||
let platform = Desktop::default();
|
|
||||||
|
|
||||||
// Setup system theme if not set.
|
// Setup system theme if not set.
|
||||||
use dark_light::Mode;
|
|
||||||
if let None = AppConfig::dark_theme() {
|
if let None = AppConfig::dark_theme() {
|
||||||
let dark = match dark_light::detect() {
|
let dark = match dark_light::detect() {
|
||||||
Mode::Dark => true,
|
Mode::Dark => true,
|
||||||
|
@ -57,49 +79,46 @@ fn real_main() {
|
||||||
let mut viewport = egui::ViewportBuilder::default()
|
let mut viewport = egui::ViewportBuilder::default()
|
||||||
.with_min_inner_size([AppConfig::MIN_WIDTH, AppConfig::MIN_HEIGHT])
|
.with_min_inner_size([AppConfig::MIN_WIDTH, AppConfig::MIN_HEIGHT])
|
||||||
.with_inner_size([width, height]);
|
.with_inner_size([width, height]);
|
||||||
|
|
||||||
// Setup an icon.
|
// Setup an icon.
|
||||||
if let Ok(icon) = from_png_bytes(include_bytes!("../img/icon.png")) {
|
if let Ok(icon) = eframe::icon_data::from_png_bytes(include_bytes!("../img/icon.png")) {
|
||||||
viewport = viewport.with_icon(Arc::new(icon));
|
viewport = viewport.with_icon(std::sync::Arc::new(icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup window position.
|
// Setup window position.
|
||||||
if let Some((x, y)) = AppConfig::window_pos() {
|
if let Some((x, y)) = AppConfig::window_pos() {
|
||||||
viewport = viewport.with_position(pos2(x, y));
|
viewport = viewport.with_position(egui::pos2(x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup window decorations.
|
// Setup window decorations.
|
||||||
let is_mac_os = OperatingSystem::from_target_os() == OperatingSystem::Mac;
|
let is_mac = egui::os::OperatingSystem::from_target_os() == egui::os::OperatingSystem::Mac;
|
||||||
viewport = viewport
|
viewport = viewport
|
||||||
.with_fullsize_content_view(true)
|
.with_fullsize_content_view(true)
|
||||||
.with_title_shown(false)
|
.with_title_shown(false)
|
||||||
.with_titlebar_buttons_shown(false)
|
.with_titlebar_buttons_shown(false)
|
||||||
.with_titlebar_shown(false)
|
.with_titlebar_shown(false)
|
||||||
.with_transparent(true)
|
.with_transparent(true)
|
||||||
.with_decorations(is_mac_os);
|
.with_decorations(is_mac);
|
||||||
|
|
||||||
let mut options = eframe::NativeOptions {
|
let mut options = eframe::NativeOptions {
|
||||||
viewport,
|
viewport,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use Glow renderer for Windows.
|
// Use Glow renderer for Windows.
|
||||||
let is_windows = OperatingSystem::from_target_os() == OperatingSystem::Windows;
|
let win = egui::os::OperatingSystem::from_target_os() == egui::os::OperatingSystem::Windows;
|
||||||
options.renderer = if is_windows {
|
options.renderer = if win {
|
||||||
eframe::Renderer::Glow
|
eframe::Renderer::Glow
|
||||||
} else {
|
} else {
|
||||||
eframe::Renderer::Wgpu
|
eframe::Renderer::Wgpu
|
||||||
};
|
};
|
||||||
|
|
||||||
match grim::start(options.clone(), grim::app_creator(App::new(platform.clone()))) {
|
// Start GUI.
|
||||||
|
match grim::start(options.clone(), grim::app_creator(grim::gui::App::new(platform.clone()))) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if is_windows {
|
if win {
|
||||||
panic!("{}", e);
|
panic!("{}", e);
|
||||||
}
|
}
|
||||||
// Start with another renderer on error.
|
// Start with another renderer on error.
|
||||||
options.renderer = eframe::Renderer::Glow;
|
options.renderer = eframe::Renderer::Glow;
|
||||||
match grim::start(options, grim::app_creator(App::new(platform))) {
|
match grim::start(options, grim::app_creator(grim::gui::App::new(platform))) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
panic!("{}", e);
|
panic!("{}", e);
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl PeersConfig {
|
||||||
/// Save peers config to the file.
|
/// Save peers config to the file.
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
let chain_type = AppConfig::chain_type();
|
let chain_type = AppConfig::chain_type();
|
||||||
let config_path = Settings::get_config_path(Self::FILE_NAME, Some(chain_type.shortname()));
|
let config_path = Settings::config_path(Self::FILE_NAME, Some(chain_type.shortname()));
|
||||||
Settings::write_to_file(self, config_path);
|
Settings::write_to_file(self, config_path);
|
||||||
// Load changes to node server config.
|
// Load changes to node server config.
|
||||||
Self::load_to_server_config();
|
Self::load_to_server_config();
|
||||||
|
@ -149,7 +149,7 @@ impl NodeConfig {
|
||||||
// Initialize peers config.
|
// Initialize peers config.
|
||||||
let peers_config = {
|
let peers_config = {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let path = Settings::get_config_path(PeersConfig::FILE_NAME, sub_dir);
|
let path = Settings::config_path(PeersConfig::FILE_NAME, sub_dir);
|
||||||
let config = Settings::read_from_file::<PeersConfig>(path.clone());
|
let config = Settings::read_from_file::<PeersConfig>(path.clone());
|
||||||
if !path.exists() || config.is_err() {
|
if !path.exists() || config.is_err() {
|
||||||
Self::save_default_peers_config(chain_type)
|
Self::save_default_peers_config(chain_type)
|
||||||
|
@ -161,7 +161,7 @@ impl NodeConfig {
|
||||||
// Initialize node config.
|
// Initialize node config.
|
||||||
let node_config = {
|
let node_config = {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, sub_dir);
|
let path = Settings::config_path(SERVER_CONFIG_FILE_NAME, sub_dir);
|
||||||
let config = Settings::read_from_file::<ConfigMembers>(path.clone());
|
let config = Settings::read_from_file::<ConfigMembers>(path.clone());
|
||||||
if !path.exists() || config.is_err() {
|
if !path.exists() || config.is_err() {
|
||||||
Self::save_default_node_server_config(chain_type)
|
Self::save_default_node_server_config(chain_type)
|
||||||
|
@ -176,10 +176,10 @@ impl NodeConfig {
|
||||||
/// Save default node config for specified [`ChainTypes`].
|
/// Save default node config for specified [`ChainTypes`].
|
||||||
fn save_default_node_server_config(chain_type: &ChainTypes) -> ConfigMembers {
|
fn save_default_node_server_config(chain_type: &ChainTypes) -> ConfigMembers {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, sub_dir.clone());
|
let path = Settings::config_path(SERVER_CONFIG_FILE_NAME, sub_dir.clone());
|
||||||
|
|
||||||
let mut default_config = GlobalConfig::for_chain(chain_type);
|
let mut default_config = GlobalConfig::for_chain(chain_type);
|
||||||
default_config.update_paths(&Settings::get_base_path(sub_dir));
|
default_config.update_paths(&Settings::base_path(sub_dir));
|
||||||
let mut config = default_config.members.unwrap();
|
let mut config = default_config.members.unwrap();
|
||||||
|
|
||||||
// Generate random p2p and api ports.
|
// Generate random p2p and api ports.
|
||||||
|
@ -214,7 +214,7 @@ impl NodeConfig {
|
||||||
/// Save default peers config for specified [`ChainTypes`].
|
/// Save default peers config for specified [`ChainTypes`].
|
||||||
fn save_default_peers_config(chain_type: &ChainTypes) -> PeersConfig {
|
fn save_default_peers_config(chain_type: &ChainTypes) -> PeersConfig {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let path = Settings::get_config_path(PeersConfig::FILE_NAME, sub_dir);
|
let path = Settings::config_path(PeersConfig::FILE_NAME, sub_dir);
|
||||||
let config = PeersConfig::default();
|
let config = PeersConfig::default();
|
||||||
Settings::write_to_file(&config, path);
|
Settings::write_to_file(&config, path);
|
||||||
config
|
config
|
||||||
|
@ -223,7 +223,7 @@ impl NodeConfig {
|
||||||
/// Save node config to the file.
|
/// Save node config to the file.
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
let sub_dir = Some(self.node.server.chain_type.shortname());
|
let sub_dir = Some(self.node.server.chain_type.shortname());
|
||||||
let config_path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, sub_dir);
|
let config_path = Settings::config_path(SERVER_CONFIG_FILE_NAME, sub_dir);
|
||||||
Settings::write_to_file(&self.node, config_path);
|
Settings::write_to_file(&self.node, config_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ impl NodeConfig {
|
||||||
/// Get path for secret file.
|
/// Get path for secret file.
|
||||||
fn get_secret_path(chain_type: &ChainTypes, secret_file_name: &str) -> PathBuf {
|
fn get_secret_path(chain_type: &ChainTypes, secret_file_name: &str) -> PathBuf {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let grin_path = Settings::get_base_path(sub_dir);
|
let grin_path = Settings::base_path(sub_dir);
|
||||||
let mut api_secret_path = grin_path;
|
let mut api_secret_path = grin_path;
|
||||||
api_secret_path.push(secret_file_name);
|
api_secret_path.push(secret_file_name);
|
||||||
api_secret_path
|
api_secret_path
|
||||||
|
|
|
@ -49,6 +49,9 @@ pub struct AppConfig {
|
||||||
|
|
||||||
/// Flag to check if dark theme should be used, use system settings if not set.
|
/// Flag to check if dark theme should be used, use system settings if not set.
|
||||||
use_dark_theme: Option<bool>,
|
use_dark_theme: Option<bool>,
|
||||||
|
|
||||||
|
/// Flag to show crash report when happened.
|
||||||
|
show_crash: Option<bool>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AppConfig {
|
impl Default for AppConfig {
|
||||||
|
@ -65,6 +68,7 @@ impl Default for AppConfig {
|
||||||
y: None,
|
y: None,
|
||||||
lang: None,
|
lang: None,
|
||||||
use_dark_theme: None,
|
use_dark_theme: None,
|
||||||
|
show_crash: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +93,7 @@ impl AppConfig {
|
||||||
|
|
||||||
/// Save application configuration to the file.
|
/// Save application configuration to the file.
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
Settings::write_to_file(self, Settings::get_config_path(Self::FILE_NAME, None));
|
Settings::write_to_file(self, Settings::config_path(Self::FILE_NAME, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change global [`ChainTypes`] and load new [`NodeConfig`].
|
/// Change global [`ChainTypes`] and load new [`NodeConfig`].
|
||||||
|
@ -241,4 +245,17 @@ impl AppConfig {
|
||||||
w_config.use_dark_theme = Some(use_dark);
|
w_config.use_dark_theme = Some(use_dark);
|
||||||
w_config.save();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -33,9 +33,6 @@ lazy_static! {
|
||||||
static ref SETTINGS_STATE: Arc<Settings> = Arc::new(Settings::init());
|
static ref SETTINGS_STATE: Arc<Settings> = Arc::new(Settings::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Main application directory name.
|
|
||||||
const MAIN_DIR_NAME: &'static str = ".grim";
|
|
||||||
|
|
||||||
/// Contains initialized configurations.
|
/// Contains initialized configurations.
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
/// Application configuration.
|
/// Application configuration.
|
||||||
|
@ -49,14 +46,20 @@ pub struct Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
|
/// Main application directory name.
|
||||||
|
pub const MAIN_DIR_NAME: &'static str = ".grim";
|
||||||
|
|
||||||
|
/// Crash report file name.
|
||||||
|
pub const CRASH_REPORT_FILE_NAME: &'static str = "crash.log";
|
||||||
|
|
||||||
/// Initialize settings with app and node configs.
|
/// Initialize settings with app and node configs.
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
// Initialize app config.
|
// Initialize app config.
|
||||||
let app_config_path = Settings::get_config_path(AppConfig::FILE_NAME, None);
|
let app_config_path = Settings::config_path(AppConfig::FILE_NAME, None);
|
||||||
let app_config = Self::init_config::<AppConfig>(app_config_path);
|
let app_config = Self::init_config::<AppConfig>(app_config_path);
|
||||||
|
|
||||||
// Initialize tor config.
|
// Initialize tor config.
|
||||||
let tor_config_path = Settings::get_config_path(TorConfig::FILE_NAME, None);
|
let tor_config_path = Settings::config_path(TorConfig::FILE_NAME, None);
|
||||||
let tor_config = Self::init_config::<TorConfig>(tor_config_path);
|
let tor_config = Self::init_config::<TorConfig>(tor_config_path);
|
||||||
|
|
||||||
let chain_type = &app_config.chain_type;
|
let chain_type = &app_config.chain_type;
|
||||||
|
@ -121,13 +124,13 @@ impl Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get base directory path for configuration.
|
/// Get base directory path for configuration.
|
||||||
pub fn get_base_path(sub_dir: Option<String>) -> PathBuf {
|
pub fn base_path(sub_dir: Option<String>) -> PathBuf {
|
||||||
// Check if dir exists.
|
// Check if dir exists.
|
||||||
let mut path = match dirs::home_dir() {
|
let mut path = match dirs::home_dir() {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => PathBuf::new(),
|
None => PathBuf::new(),
|
||||||
};
|
};
|
||||||
path.push(MAIN_DIR_NAME);
|
path.push(Self::MAIN_DIR_NAME);
|
||||||
if sub_dir.is_some() {
|
if sub_dir.is_some() {
|
||||||
path.push(sub_dir.unwrap());
|
path.push(sub_dir.unwrap());
|
||||||
}
|
}
|
||||||
|
@ -139,10 +142,17 @@ impl Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get configuration file path from provided name and sub-directory if needed.
|
/// Get configuration file path from provided name and sub-directory if needed.
|
||||||
pub fn get_config_path(config_name: &str, sub_dir: Option<String>) -> PathBuf {
|
pub fn config_path(config_name: &str, sub_dir: Option<String>) -> PathBuf {
|
||||||
let mut settings_path = Self::get_base_path(sub_dir);
|
let mut path = Self::base_path(sub_dir);
|
||||||
settings_path.push(config_name);
|
path.push(config_name);
|
||||||
settings_path
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get configuration file path from provided name and sub-directory if needed.
|
||||||
|
pub fn crash_report_path() -> PathBuf {
|
||||||
|
let mut path = Self::base_path(None);
|
||||||
|
path.push(Self::CRASH_REPORT_FILE_NAME);
|
||||||
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read configuration from the file.
|
/// Read configuration from the file.
|
||||||
|
|
|
@ -61,12 +61,12 @@ impl TorConfig {
|
||||||
|
|
||||||
/// Save application configuration to the file.
|
/// Save application configuration to the file.
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
Settings::write_to_file(self, Settings::get_config_path(Self::FILE_NAME, None));
|
Settings::write_to_file(self, Settings::config_path(Self::FILE_NAME, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get path from subdirectory name.
|
/// Get path from subdirectory name.
|
||||||
fn sub_dir_path(name: &str) -> String {
|
fn sub_dir_path(name: &str) -> String {
|
||||||
let mut base = Settings::get_base_path(Some(Self::DIR_NAME.to_string()));
|
let mut base = Settings::base_path(Some(Self::DIR_NAME.to_string()));
|
||||||
base.push(name);
|
base.push(name);
|
||||||
base.to_str().unwrap().to_string()
|
base.to_str().unwrap().to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ impl WalletConfig {
|
||||||
/// Get wallets base directory path for provided [`ChainTypes`].
|
/// Get wallets base directory path for provided [`ChainTypes`].
|
||||||
pub fn get_base_path(chain_type: ChainTypes) -> PathBuf {
|
pub fn get_base_path(chain_type: ChainTypes) -> PathBuf {
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
let mut wallets_path = Settings::get_base_path(sub_dir);
|
let mut wallets_path = Settings::base_path(sub_dir);
|
||||||
wallets_path.push(BASE_DIR_NAME);
|
wallets_path.push(BASE_DIR_NAME);
|
||||||
// Create wallets base directory if it doesn't exist.
|
// Create wallets base directory if it doesn't exist.
|
||||||
if !wallets_path.exists() {
|
if !wallets_path.exists() {
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl ConnectionsConfig {
|
||||||
|
|
||||||
/// Initialize configuration for provided [`ChainTypes`].
|
/// Initialize configuration for provided [`ChainTypes`].
|
||||||
pub fn for_chain_type(chain_type: &ChainTypes) -> Self {
|
pub fn for_chain_type(chain_type: &ChainTypes) -> Self {
|
||||||
let path = Settings::get_config_path(Self::FILE_NAME, Some(chain_type.shortname()));
|
let path = Settings::config_path(Self::FILE_NAME, Some(chain_type.shortname()));
|
||||||
let parsed = Settings::read_from_file::<ConnectionsConfig>(path.clone());
|
let parsed = Settings::read_from_file::<ConnectionsConfig>(path.clone());
|
||||||
if !path.exists() || parsed.is_err() {
|
if !path.exists() || parsed.is_err() {
|
||||||
let default_config = ConnectionsConfig {
|
let default_config = ConnectionsConfig {
|
||||||
|
@ -57,7 +57,7 @@ impl ConnectionsConfig {
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
let chain_type = AppConfig::chain_type();
|
let chain_type = AppConfig::chain_type();
|
||||||
let sub_dir = Some(chain_type.shortname());
|
let sub_dir = Some(chain_type.shortname());
|
||||||
Settings::write_to_file(self, Settings::get_config_path(Self::FILE_NAME, sub_dir));
|
Settings::write_to_file(self, Settings::config_path(Self::FILE_NAME, sub_dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get [`ExternalConnection`] list.
|
/// Get [`ExternalConnection`] list.
|
||||||
|
|
Loading…
Reference in a new issue