diff options
| author | pml68 <contact@pml68.dev> | 2024-12-30 02:15:10 +0100 |
|---|---|---|
| committer | pml68 <contact@pml68.dev> | 2024-12-30 02:15:10 +0100 |
| commit | 0dad6dd5b8395d3089bed022a4b8830f7cae7d9f (patch) | |
| tree | e28ccc225c07f9b49a1c233fb81c8eddd75a01c0 /iced_builder/src/config.rs | |
| parent | refactor!: switch to `uuid` for uuid generation (diff) | |
| download | iced-builder-0dad6dd5b8395d3089bed022a4b8830f7cae7d9f.tar.gz | |
feat: add config loading, with theming support, limited to Palette for now
Diffstat (limited to '')
| -rw-r--r-- | iced_builder/src/config.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/iced_builder/src/config.rs b/iced_builder/src/config.rs new file mode 100644 index 0000000..75aee1d --- /dev/null +++ b/iced_builder/src/config.rs @@ -0,0 +1,123 @@ +use std::path::PathBuf; + +use serde::Deserialize; +use tokio_stream::wrappers::ReadDirStream; +use tokio_stream::StreamExt; + +use crate::theme::{theme_from_str, theme_index, Theme, ThemePalette}; +use crate::{environment, Error, Result}; + +#[derive(Debug, Default)] +pub struct Config { + pub theme: Theme, + pub last_project: Option<PathBuf>, +} + +impl Config { + pub fn selected_theme(&self) -> iced::Theme { + self.theme.selected.clone() + } + + pub fn config_dir() -> PathBuf { + let dir = environment::config_dir(); + + if !dir.exists() { + std::fs::create_dir_all(dir.as_path()) + .expect("expected permissions to create config folder"); + } + println!("{}", dir.to_string_lossy()); + dir + } + + pub fn themes_dir() -> PathBuf { + let dir = Self::config_dir().join("themes"); + + if !dir.exists() { + std::fs::create_dir_all(dir.as_path()) + .expect("expected permissions to create themes folder"); + } + println!("{}", dir.to_string_lossy()); + dir + } + + pub fn config_file_path() -> PathBuf { + Self::config_dir().join(environment::CONFIG_FILE_NAME) + } + + pub async fn load() -> Result<Self> { + use tokio::fs; + + #[derive(Deserialize)] + pub struct Configuration { + pub theme: String, + pub last_project: Option<PathBuf>, + } + + let path = Self::config_file_path(); + if !path.try_exists()? { + return Err(Error::ConfigMissing); + } + + let content = fs::read_to_string(path).await?; + + let Configuration { + theme, + last_project, + } = toml::from_str(content.as_ref())?; + + let theme = Self::load_theme(theme).await.unwrap_or_default(); + + Ok(Self { + theme, + last_project, + }) + } + + pub async fn load_theme(theme_name: String) -> Result<Theme> { + use tokio::fs; + + let read_entry = |entry: fs::DirEntry| async move { + let content = fs::read_to_string(entry.path()).await.ok()?; + + let palette: ThemePalette = + toml::from_str(content.as_ref()).ok()?; + let name = entry.path().file_stem()?.to_string_lossy().to_string(); + + Some(iced::Theme::custom(name, palette.into())) + }; + + let mut all = iced::Theme::ALL.to_owned(); + let mut selected = iced::Theme::default(); + + if theme_index(theme_name.clone(), iced::Theme::ALL).is_some() { + selected = theme_from_str(None, &theme_name); + } + + let mut stream = + ReadDirStream::new(fs::read_dir(Self::themes_dir()).await?); + while let Some(entry) = stream.next().await { + let Ok(entry) = entry else { + continue; + }; + + let Some(file_name) = entry.file_name().to_str().map(String::from) + else { + continue; + }; + + if let Some(file_name) = file_name.strip_suffix(".toml") { + if let Some(theme) = read_entry(entry).await { + if file_name == theme_name { + selected = theme.clone(); + } + all.push(theme); + } + } + } + + Ok(Theme { + selected, + all: all.into(), + }) + } +} |
