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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::path::Path;
use std::fs::File;
use std::{env, fs};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
pub struct AppSettings {
    pub name: String,
    pub favicons: Vec<Favicon>,
}

#[derive(Deserialize, Serialize)]
pub struct Favicon {
    pub rel: String,
    pub href: String
}

#[derive(Deserialize, Serialize)]
pub struct Features {
    #[serde(rename = "rich-text-editor")]
    pub rich_text_editor: bool,
    #[serde(rename = "sortable-stack")]
    pub sortable_stack: bool,
}

#[derive(Deserialize, Serialize)]
pub struct Colors {
    pub accent: Color,
    #[serde(rename = "on-accent")]
    pub on_accent: Color,
    pub background: Color,
    #[serde(rename = "on-background")]
    pub on_background: Color,
    pub surface: Color,
    #[serde(rename = "on-surface")]
    pub on_surface: Color,
    pub destructive: Color,
    #[serde(rename = "on-destructive")]
    pub on_destructive: Color,
}

#[derive(Deserialize, Serialize)]
pub struct Color {
    pub dark: String,
    pub light: String,
}

#[derive(Deserialize, Serialize)]
pub struct Shapes {
    #[serde(rename = "border-radius")]
    pub border_radius: i32,
    #[serde(rename = "spacing-factor")]
    pub spacing_factor: i32,
}

#[derive(Deserialize, Serialize)]
pub struct Config {
    pub app: AppSettings,
    pub features: Features,
    pub colors: Colors,
    pub shapes: Shapes,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            app: AppSettings {
                name: "".to_string(),
                favicons: vec![]
            },
            features: Features {
                rich_text_editor: false,
                sortable_stack: false
            },
            colors: Colors {
                accent: Color {
                    dark: "#1d5dea".to_string(),
                    light: "#1d5dea".to_string(),
                },
                on_accent: Color {
                    dark: "#ffffff".to_string(),
                    light: "#ffffff".to_string()
                },
                background: Color {
                    dark: "#121212".to_string(),
                    light: "#ffffff".to_string()
                },
                on_background: Color {
                    dark: "#ffffff".to_string(),
                    light: "#000000".to_string()
                },
                surface: Color {
                    dark: "#181818".to_string(),
                    light: "#efefef".to_string()
                },
                on_surface: Color {
                    dark: "#ffffff".to_string(),
                    light: "#000000".to_string()
                },
                destructive: Color {
                    dark: "#f14a61".to_string(),
                    light: "#f14a61".to_string()
                },
                on_destructive: Color {
                    dark: "#ffffff".to_string(),
                    light: "#ffffff".to_string()
                },
            },
            shapes: Shapes {
                border_radius: 8,
                spacing_factor: 4
            }
        }
    }
}

pub struct ConfigLoader;

impl ConfigLoader {
    pub fn load_from_config_folder() -> Config {
        let theme_path = Path::new("./viewy.toml");
        let mut theme = if theme_path.exists() {
            fs::read_to_string(theme_path)
                .map(|theme_config| -> Config {
                    toml::from_str(&theme_config).expect("Can't parse theme config file")
                })
                .expect("Can't open config file")
        } else {
            Config::default()
        };

        theme.colors.accent.light = env::var("VIEWY_COLOR_ACCENT_LIGHT")
            .unwrap_or(theme.colors.accent.light);
        theme.colors.accent.dark = env::var("VIEWY_COLOR_ACCENT_DARK")
            .unwrap_or(theme.colors.accent.dark);

        theme
    }
}