1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
use std::path::PathBuf;
use serde::Deserialize;
use tokio_stream::wrappers::ReadDirStream;
use tokio_stream::StreamExt;
use crate::theme::{theme_from_str, theme_index, Appearance, Theme};
use crate::{environment, Error, Result};
#[derive(Debug, Default)]
pub struct Config {
pub theme: Appearance,
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");
}
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");
}
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 {
#[serde(default)]
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<Appearance> {
use tokio::fs;
let read_entry = |entry: fs::DirEntry| async move {
let content = fs::read_to_string(entry.path()).await.ok()?;
let theme: Theme = toml::from_str(content.as_ref()).ok()?;
let name = entry.path().file_stem()?.to_string_lossy().to_string();
Some(theme.into_iced_theme(name))
};
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(Appearance {
selected,
all: all.into(),
})
}
}
|