mirror of
https://github.com/jwinterm/grim.git
synced 2026-10-22 15:58:32 +02:00
settings: move to separate module
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
// Copyright 2023 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use grin_core::global::ChainTypes;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use crate::node::NodeConfig;
|
||||
use crate::Settings;
|
||||
use crate::wallet::ConnectionsConfig;
|
||||
|
||||
/// Application configuration, stored at toml file.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AppConfig {
|
||||
/// Run node server on startup.
|
||||
pub(crate) auto_start_node: bool,
|
||||
/// Chain type for node and wallets.
|
||||
pub(crate) chain_type: ChainTypes,
|
||||
|
||||
/// Flag to show wallet list at dual panel wallets mode.
|
||||
show_wallets_at_dual_panel: bool,
|
||||
/// Flag to show all connections at network panel or integrated node info.
|
||||
show_connections_network_panel: bool,
|
||||
|
||||
/// Width of the desktop window.
|
||||
width: f32,
|
||||
/// Height of the desktop window.
|
||||
height: f32,
|
||||
|
||||
/// Position of the desktop window.
|
||||
x: Option<f32>, y: Option<f32>,
|
||||
|
||||
/// Locale code for i18n.
|
||||
lang: Option<String>
|
||||
}
|
||||
|
||||
const DEFAULT_WIDTH: f32 = 1200.0;
|
||||
const DEFAULT_HEIGHT: f32 = 720.0;
|
||||
|
||||
impl Default for AppConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
auto_start_node: false,
|
||||
chain_type: ChainTypes::default(),
|
||||
show_wallets_at_dual_panel: false,
|
||||
show_connections_network_panel: false,
|
||||
width: DEFAULT_WIDTH,
|
||||
height: DEFAULT_HEIGHT,
|
||||
x: None,
|
||||
y: None,
|
||||
lang: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
/// Application configuration file name.
|
||||
pub const FILE_NAME: &'static str = "app.toml";
|
||||
|
||||
/// Default i18n locale.
|
||||
pub const DEFAULT_LOCALE: &'static str = "en";
|
||||
|
||||
/// Save application configuration to the file.
|
||||
pub fn save(&self) {
|
||||
Settings::write_to_file(self, Settings::get_config_path(Self::FILE_NAME, None));
|
||||
}
|
||||
|
||||
/// Change global [`ChainTypes`] and load new [`NodeConfig`].
|
||||
pub fn change_chain_type(chain_type: &ChainTypes) {
|
||||
let current_chain_type = Self::chain_type();
|
||||
if current_chain_type != *chain_type {
|
||||
// Save chain type at app config.
|
||||
{
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.chain_type = *chain_type;
|
||||
w_app_config.save();
|
||||
}
|
||||
// Load node configuration for selected chain type.
|
||||
{
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
let node_config = NodeConfig::for_chain_type(chain_type);
|
||||
w_node_config.node = node_config.node;
|
||||
w_node_config.peers = node_config.peers;
|
||||
}
|
||||
// Load connections configuration
|
||||
{
|
||||
let mut w_node_config = Settings::conn_config_to_update();
|
||||
*w_node_config = ConnectionsConfig::for_chain_type(chain_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get current [`ChainTypes`] for node and wallets.
|
||||
pub fn chain_type() -> ChainTypes {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
r_config.chain_type
|
||||
}
|
||||
|
||||
/// Check if integrated node is starting with application.
|
||||
pub fn autostart_node() -> bool {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
r_config.auto_start_node
|
||||
}
|
||||
|
||||
/// Toggle integrated node autostart.
|
||||
pub fn toggle_node_autostart() {
|
||||
let autostart = Self::autostart_node();
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.auto_start_node = !autostart;
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Check if it's needed to show wallet list at dual panel wallets mode.
|
||||
pub fn show_wallets_at_dual_panel() -> bool {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
r_config.show_wallets_at_dual_panel
|
||||
}
|
||||
|
||||
/// Toggle flag to show wallet list at dual panel wallets mode.
|
||||
pub fn toggle_show_wallets_at_dual_panel() {
|
||||
let show = Self::show_wallets_at_dual_panel();
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.show_wallets_at_dual_panel = !show;
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Check if it's needed to show all connections or integrated node info at network panel.
|
||||
pub fn show_connections_network_panel() -> bool {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
r_config.show_connections_network_panel
|
||||
}
|
||||
|
||||
/// Toggle flag to show all connections or integrated node info at network panel.
|
||||
pub fn toggle_show_connections_network_panel() {
|
||||
let show = Self::show_connections_network_panel();
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.show_connections_network_panel = !show;
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Save desktop window width and height.
|
||||
pub fn save_window_size(w: f32, h: f32) {
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.width = w;
|
||||
w_app_config.height = h;
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Get desktop window width and height.
|
||||
pub fn window_size() -> (f32, f32) {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
(r_config.width, r_config.height)
|
||||
}
|
||||
|
||||
/// Save desktop window position.
|
||||
pub fn save_window_pos(x: f32, y: f32) {
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.x = Some(x);
|
||||
w_app_config.y = Some(y);
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Get desktop window position.
|
||||
pub fn window_pos() -> Option<(f32, f32)> {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
if r_config.x.is_some() && r_config.y.is_some() {
|
||||
return Some((r_config.x.unwrap(), r_config.y.unwrap()))
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Save locale code.
|
||||
pub fn save_locale(lang: &str) {
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.lang = Some(lang.to_string());
|
||||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Get current saved locale code.
|
||||
pub fn locale() -> Option<String> {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
if r_config.lang.is_some() {
|
||||
return Some(r_config.lang.clone().unwrap())
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod settings;
|
||||
pub use settings::Settings;
|
||||
|
||||
mod config;
|
||||
pub use config::AppConfig;
|
||||
@@ -0,0 +1,148 @@
|
||||
// Copyright 2023 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use grin_config::ConfigError;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::node::NodeConfig;
|
||||
use crate::settings::AppConfig;
|
||||
use crate::wallet::ConnectionsConfig;
|
||||
|
||||
lazy_static! {
|
||||
/// Static settings state to be accessible globally.
|
||||
static ref SETTINGS_STATE: Arc<Settings> = Arc::new(Settings::init());
|
||||
}
|
||||
|
||||
/// Main application directory name.
|
||||
const MAIN_DIR_NAME: &'static str = ".grim";
|
||||
|
||||
/// Contains initialized configurations.
|
||||
pub struct Settings {
|
||||
/// Application configuration.
|
||||
app_config: Arc<RwLock<AppConfig>>,
|
||||
/// Integrated node configuration.
|
||||
node_config: Arc<RwLock<NodeConfig>>,
|
||||
/// Wallet connections configuration.
|
||||
conn_config: Arc<RwLock<ConnectionsConfig>>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Initialize settings with app and node configs.
|
||||
fn init() -> Self {
|
||||
let app_config_path = Settings::get_config_path(AppConfig::FILE_NAME, None);
|
||||
let app_config = Self::init_config::<AppConfig>(app_config_path);
|
||||
let chain_type = &app_config.chain_type;
|
||||
Self {
|
||||
node_config: Arc::new(RwLock::new(NodeConfig::for_chain_type(chain_type))),
|
||||
conn_config: Arc::new(RwLock::new(ConnectionsConfig::for_chain_type(chain_type))),
|
||||
app_config: Arc::new(RwLock::new(app_config)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize configuration from provided file path or set [`Default`] if file not exists.
|
||||
pub fn init_config<T: Default + Serialize + DeserializeOwned>(path: PathBuf) -> T {
|
||||
let parsed = Self::read_from_file::<T>(path.clone());
|
||||
if !path.exists() || parsed.is_err() {
|
||||
let default_config = T::default();
|
||||
Settings::write_to_file(&default_config, path);
|
||||
default_config
|
||||
} else {
|
||||
parsed.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get node configuration to read values.
|
||||
pub fn node_config_to_read() -> RwLockReadGuard<'static, NodeConfig> {
|
||||
SETTINGS_STATE.node_config.read().unwrap()
|
||||
}
|
||||
|
||||
/// Get node configuration to update values.
|
||||
pub fn node_config_to_update() -> RwLockWriteGuard<'static, NodeConfig> {
|
||||
SETTINGS_STATE.node_config.write().unwrap()
|
||||
}
|
||||
|
||||
/// Get app configuration to read values.
|
||||
pub fn app_config_to_read() -> RwLockReadGuard<'static, AppConfig> {
|
||||
SETTINGS_STATE.app_config.read().unwrap()
|
||||
}
|
||||
|
||||
/// Get app configuration to update values.
|
||||
pub fn app_config_to_update() -> RwLockWriteGuard<'static, AppConfig> {
|
||||
SETTINGS_STATE.app_config.write().unwrap()
|
||||
}
|
||||
|
||||
/// Get connections configuration to read values.
|
||||
pub fn conn_config_to_read() -> RwLockReadGuard<'static, ConnectionsConfig> {
|
||||
SETTINGS_STATE.conn_config.read().unwrap()
|
||||
}
|
||||
|
||||
/// Get connections configuration to update values.
|
||||
pub fn conn_config_to_update() -> RwLockWriteGuard<'static, ConnectionsConfig> {
|
||||
SETTINGS_STATE.conn_config.write().unwrap()
|
||||
}
|
||||
|
||||
/// Get base directory path for configuration.
|
||||
pub fn get_base_path(sub_dir: Option<String>) -> PathBuf {
|
||||
// Check if dir exists.
|
||||
let mut path = match dirs::home_dir() {
|
||||
Some(p) => p,
|
||||
None => PathBuf::new(),
|
||||
};
|
||||
path.push(MAIN_DIR_NAME);
|
||||
if sub_dir.is_some() {
|
||||
path.push(sub_dir.unwrap());
|
||||
}
|
||||
// Create if the default path doesn't exist.
|
||||
if !path.exists() {
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let mut settings_path = Self::get_base_path(sub_dir);
|
||||
settings_path.push(config_name);
|
||||
settings_path
|
||||
}
|
||||
|
||||
/// Read configuration from the file.
|
||||
pub fn read_from_file<T: DeserializeOwned>(config_path: PathBuf) -> Result<T, ConfigError> {
|
||||
let file_content = fs::read_to_string(config_path.clone())?;
|
||||
let parsed = toml::from_str::<T>(file_content.as_str());
|
||||
match parsed {
|
||||
Ok(cfg) => Ok(cfg),
|
||||
Err(e) => {
|
||||
return Err(ConfigError::ParseError(
|
||||
config_path.to_str().unwrap().to_string(),
|
||||
format!("{}", e),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Write configuration to the file.
|
||||
pub fn write_to_file<T: Serialize>(config: &T, path: PathBuf) {
|
||||
let conf_out = toml::to_string(config).unwrap();
|
||||
let mut file = File::create(path.to_str().unwrap()).unwrap();
|
||||
file.write_all(conf_out.as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user