config.rs (3718B)
1 #[cfg(not(target_arch = "wasm32"))] 2 use directories::ProjectDirs; 3 use serde::{Deserialize, Serialize}; 4 5 #[derive( 6 Serialize, Deserialize, Debug, Clone, Copy, PartialEq, strum::Display, strum::VariantArray, 7 )] 8 pub enum BackgroundMode { 9 Unsplash, 10 Solid, 11 #[cfg(not(target_arch = "wasm32"))] 12 Local, 13 } 14 15 impl BackgroundMode { 16 pub fn default_background(&self) -> &'static str { 17 match self { 18 // https://unsplash.com/collections/1053828/tabliss-official 19 Self::Unsplash => "1053828", 20 Self::Solid => "#000000", 21 #[cfg(not(target_arch = "wasm32"))] 22 Self::Local => "", 23 } 24 } 25 26 pub fn edit_text(&self) -> &'static str { 27 match self { 28 Self::Unsplash => "Unsplash collection", 29 Self::Solid => "Color (#rrggbb)", 30 #[cfg(not(target_arch = "wasm32"))] 31 Self::Local => "File path", 32 } 33 } 34 } 35 36 #[derive(Serialize, Deserialize, Clone)] 37 pub struct Location { 38 pub longitude: f64, 39 pub latitude: f64, 40 pub name: Option<String>, 41 } 42 43 #[derive(Serialize, Deserialize, Clone)] 44 pub struct Config { 45 pub time_format: String, 46 pub background_mode: BackgroundMode, 47 pub background: String, 48 pub unsplash_key: Option<String>, 49 pub location: Option<Location>, 50 } 51 52 impl Config { 53 #[cfg(not(target_arch = "wasm32"))] 54 pub fn load() -> anyhow::Result<Config> { 55 if let Some(dir) = ProjectDirs::from("net.sivory", "", "fjordgard") { 56 let config_file = dir.config_dir().join("config.json"); 57 58 if !config_file.exists() { 59 return Ok(Config::default()); 60 } 61 62 let data = std::fs::read_to_string(config_file)?; 63 64 Ok(serde_json::from_str(&data)?) 65 } else { 66 Ok(Config::default()) 67 } 68 } 69 70 #[cfg(not(target_arch = "wasm32"))] 71 pub async fn save(&self) -> anyhow::Result<()> { 72 if let Some(dir) = ProjectDirs::from("net.sivory", "", "fjordgard") { 73 let config_dir = dir.config_dir(); 74 tokio::fs::create_dir_all(config_dir).await?; 75 76 let contents = serde_json::to_string(self)?; 77 78 tokio::fs::write(config_dir.join("config.json"), contents).await?; 79 80 Ok(()) 81 } else { 82 anyhow::bail!("no config directory found") 83 } 84 } 85 86 #[cfg(target_arch = "wasm32")] 87 fn get_storage() -> anyhow::Result<web_sys::Storage> { 88 let window = web_sys::window().ok_or_else(|| anyhow::anyhow!("expected window"))?; 89 90 window 91 .local_storage() 92 .map_err(|_| anyhow::anyhow!("expected local_storage"))? 93 .ok_or_else(|| anyhow::anyhow!("expected local_storage")) 94 } 95 96 #[cfg(target_arch = "wasm32")] 97 pub fn load() -> anyhow::Result<Config> { 98 let storage = Self::get_storage()?; 99 100 if let Some(config) = storage.get_item("config").ok().flatten() { 101 Ok(serde_json::from_str(&config)?) 102 } else { 103 Ok(Config::default()) 104 } 105 } 106 107 #[cfg(target_arch = "wasm32")] 108 pub async fn save(&self) -> anyhow::Result<()> { 109 let storage = Self::get_storage()?; 110 let config = serde_json::to_string(self)?; 111 112 storage 113 .set_item("config", &config) 114 .map_err(|_| anyhow::anyhow!("failed to save config"))?; 115 116 Ok(()) 117 } 118 } 119 120 impl Default for Config { 121 fn default() -> Self { 122 Self { 123 time_format: String::from("%-I:%M:%S"), 124 background_mode: BackgroundMode::Solid, 125 background: BackgroundMode::Solid.default_background().to_string(), 126 unsplash_key: None, 127 location: None, 128 } 129 } 130 }