yozefu_app/configuration/
workspace.rs

1use std::{
2    collections::HashMap,
3    fs,
4    path::{Path, PathBuf},
5};
6
7use directories::ProjectDirs;
8use itertools::Itertools;
9use lib::Error;
10use serde_json::Value;
11
12use crate::{APPLICATION_NAME, configuration::GlobalConfig};
13
14#[derive(Debug, PartialEq, Eq, Clone)]
15#[cfg_attr(test, derive(schemars::JsonSchema))]
16/// The workspace is the directory containing yozefu configuration, logs, themes, filters...
17pub struct Workspace {
18    /// Config directory of Yozefu, the `path` is a directory
19    pub path: PathBuf,
20    /// Specific config file of Yozefu
21    pub(super) config: GlobalConfig,
22    /// Specific log file of Yozefu
23    log_file: PathBuf,
24}
25
26impl Default for Workspace {
27    fn default() -> Self {
28        Self {
29            path: Self::yozefu_directory().unwrap(),
30            config: GlobalConfig::new(
31                &Workspace::yozefu_directory()
32                    .unwrap()
33                    .join(Self::CONFIG_FILENAME),
34            ),
35            log_file: Self::yozefu_directory().unwrap().join(Self::LOGS_FILENAME),
36        }
37    }
38}
39
40impl Workspace {
41    pub const CONFIG_FILENAME: &str = "config.json";
42    pub const LOGS_FILENAME: &str = "application.log";
43    pub const THEMES_FILENAME: &str = "themes.json";
44    pub const FILTERS_DIRECTORY: &str = "filters";
45
46    pub fn new(directory: &Path, config: GlobalConfig, log_file: PathBuf) -> Self {
47        Self {
48            path: directory.to_path_buf(),
49            config,
50            log_file,
51        }
52    }
53
54    /// The default yozefu directory containing themes, filters, config...
55    fn yozefu_directory() -> Result<PathBuf, Error> {
56        ProjectDirs::from("io", "maif", APPLICATION_NAME)
57            .ok_or(Error::Error(
58                "Failed to find the yozefu configuration directory".to_string(),
59            ))
60            .map(|e| e.config_dir().to_path_buf())
61    }
62
63    /// Returns the name of config file
64    pub fn config_file(&self) -> PathBuf {
65        self.config.path.clone()
66    }
67
68    /// Returns the name of the logs file
69    pub fn log_file(&self) -> PathBuf {
70        self.log_file.clone()
71    }
72
73    pub fn config(&self) -> &GlobalConfig {
74        &self.config
75    }
76
77    /// Returns the name of the logs file
78    pub fn themes_file(&self) -> PathBuf {
79        self.path.join(Self::THEMES_FILENAME)
80    }
81
82    /// Returns the list of available theme names.
83    pub fn themes(&self) -> Vec<String> {
84        let file = self.themes_file();
85        let content = fs::read_to_string(file).unwrap_or("{}".to_string());
86        let themes: HashMap<String, Value> = serde_json::from_str(&content).unwrap_or_default();
87        themes
88            .keys()
89            .map(std::string::ToString::to_string)
90            .collect_vec()
91    }
92
93    /// Returns the name of the directory containing wasm filters
94    pub fn filters_dir(&self) -> PathBuf {
95        let dir = self.path.join(Self::FILTERS_DIRECTORY);
96        let _ = fs::create_dir_all(&dir);
97        dir
98    }
99}