148 lines
4.5 KiB
Rust
148 lines
4.5 KiB
Rust
use std::{
|
|
env::current_dir,
|
|
fs::{self, File},
|
|
io::Read,
|
|
path::PathBuf,
|
|
sync::Arc,
|
|
};
|
|
|
|
use once_cell::sync::OnceCell;
|
|
use paris::info;
|
|
use serde::{Deserialize, Serialize};
|
|
use tauri::{api::path::config_dir, async_runtime::Mutex};
|
|
|
|
use super::DisplayConfig;
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
pub struct Configuration {
|
|
pub config_version: u8,
|
|
pub display_configs: Vec<DisplayConfig>,
|
|
}
|
|
|
|
impl Configuration {
|
|
pub fn default() -> Self {
|
|
Self {
|
|
config_version: 1,
|
|
display_configs: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct Manager {
|
|
config: Arc<Mutex<Configuration>>,
|
|
}
|
|
|
|
impl Manager {
|
|
pub fn global() -> &'static Manager {
|
|
static DISPLAY_CONFIG_MANAGE: OnceCell<Manager> = OnceCell::new();
|
|
|
|
DISPLAY_CONFIG_MANAGE.get_or_init(|| Self::init_from_disk())
|
|
}
|
|
|
|
pub fn default() -> Self {
|
|
Self::new(Configuration::default())
|
|
}
|
|
|
|
pub fn new(config: Configuration) -> Self {
|
|
Self {
|
|
config: Arc::new(Mutex::new(config)),
|
|
}
|
|
}
|
|
|
|
pub fn get_config_file_path() -> PathBuf {
|
|
config_dir()
|
|
.unwrap_or(current_dir().unwrap())
|
|
.join("display_config.json")
|
|
}
|
|
|
|
pub fn init_from_disk() -> Self {
|
|
let config_file_path = Self::get_config_file_path();
|
|
match Self::read_config_from_disk(config_file_path) {
|
|
Ok(config) => Self::new(config),
|
|
Err(_) => Self::default(),
|
|
}
|
|
}
|
|
|
|
pub fn read_config_from_disk(config_file_path: PathBuf) -> anyhow::Result<Configuration> {
|
|
let mut file = File::open(config_file_path)
|
|
.map_err(|error| anyhow::anyhow!("config file is not existed. {}", error))?;
|
|
let mut contents = String::new();
|
|
file.read_to_string(&mut contents)
|
|
.map_err(|error| anyhow::anyhow!("can not read config file. {}", error))?;
|
|
serde_json::from_str(&contents)
|
|
.map_err(|error| anyhow::anyhow!("can not parse config file contents. {}", error))
|
|
}
|
|
|
|
pub fn write_config_to_disk(
|
|
config_file_path: PathBuf,
|
|
config: &Configuration,
|
|
) -> anyhow::Result<()> {
|
|
let contents = serde_json::to_string(config)
|
|
.map_err(|error| anyhow::anyhow!("can not serialize config. {}", error))?;
|
|
info!("contents: {}", contents);
|
|
fs::write(config_file_path, contents.as_bytes())
|
|
.map_err(|error| anyhow::anyhow!("can not write config file. {}", error))?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn get_config(&self) -> Configuration {
|
|
self.config.lock().await.clone()
|
|
}
|
|
pub async fn set_config(&self, new_config: &Configuration) {
|
|
let mut config = self.config.lock().await;
|
|
*config = new_config.clone();
|
|
}
|
|
pub async fn reload_config(&self) -> anyhow::Result<Configuration> {
|
|
let mut config = self.config.lock().await;
|
|
let new_config = Self::read_config_from_disk(Self::get_config_file_path())
|
|
.map_err(|err| anyhow::anyhow!("can not reload config. {:?}", err))?;
|
|
*config = new_config.clone();
|
|
return anyhow::Ok(new_config);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use std::fs;
|
|
|
|
use serde_json::json;
|
|
use test_dir::{DirBuilder, TestDir};
|
|
|
|
use crate::picker::config::Configuration;
|
|
|
|
#[tokio::test]
|
|
async fn write_config_to_disk_should_be_successful() {
|
|
let temp = TestDir::temp().create("config_dir", test_dir::FileType::Dir);
|
|
let config_file_path = temp.path("config_dir").join("picker.config.json");
|
|
let manager = crate::picker::config::manger::Manager::default();
|
|
crate::picker::config::manger::Manager::write_config_to_disk(
|
|
config_file_path.clone(),
|
|
&Configuration::default(),
|
|
)
|
|
.unwrap();
|
|
|
|
let contents = fs::read_to_string(config_file_path.clone()).unwrap();
|
|
let _config: Configuration = serde_json::from_str(contents.as_str()).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn read_config_to_disk_should_be_successful() {
|
|
let temp = TestDir::temp().create("config_dir", test_dir::FileType::Dir);
|
|
let config_file_path = temp.path("config_dir").join("picker.config.json");
|
|
fs::write(
|
|
config_file_path.clone(),
|
|
json!({
|
|
"config_version": 1,
|
|
"display_configs": []
|
|
})
|
|
.to_string()
|
|
.as_bytes(),
|
|
)
|
|
.unwrap();
|
|
let _manager =
|
|
crate::picker::config::manger::Manager::read_config_from_disk(config_file_path.clone())
|
|
.unwrap();
|
|
}
|
|
}
|