fjordgard

A desktop clock application
Log | Files | Refs | README | LICENSE

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 }