use std::fs::OpenOptions;
use std::path::{Path, PathBuf};
use std::string::ToString;
use crate::config::serialization::{SerializerError, SerializerErrorKind, deserialize, serialize};
use crate::config::themes::Theme;
pub struct ThemeProvider {
theme: Theme, theme_path: PathBuf, degraded: bool, }
impl ThemeProvider {
pub fn new(theme_path: &Path) -> Result<Self, SerializerError> {
let default_theme: Theme = Theme::default();
info!(
"Setting up theme provider with theme path {}",
theme_path.display(),
);
let mut provider: ThemeProvider = ThemeProvider {
theme: default_theme,
theme_path: theme_path.to_path_buf(),
degraded: false,
};
if !theme_path.exists() {
if let Err(err) = provider.save() {
error!("Couldn't write theme file: {}", err);
return Err(err);
}
debug!("Theme file didn't exist; created file");
} else {
if let Err(err) = provider.load() {
error!("Couldn't read theme file: {}", err);
return Err(err);
}
debug!("Read theme file");
}
Ok(provider)
}
pub fn degraded() -> Self {
Self {
theme: Theme::default(),
theme_path: PathBuf::default(),
degraded: true,
}
}
pub fn theme(&self) -> &Theme {
&self.theme
}
pub fn theme_mut(&mut self) -> &mut Theme {
&mut self.theme
}
pub fn load(&mut self) -> Result<(), SerializerError> {
if self.degraded {
warn!("Configuration won't be loaded, since degraded; reloading default...");
self.theme = Theme::default();
return Err(SerializerError::new_ex(
SerializerErrorKind::Generic,
String::from("Can't access theme file"),
));
}
debug!("Loading theme from file...");
match OpenOptions::new()
.read(true)
.open(self.theme_path.as_path())
{
Ok(reader) => {
match deserialize(Box::new(reader)) {
Ok(theme) => {
self.theme = theme;
Ok(())
}
Err(err) => Err(err),
}
}
Err(err) => {
error!("Failed to read theme: {}", err);
Err(SerializerError::new_ex(
SerializerErrorKind::Io,
err.to_string(),
))
}
}
}
pub fn save(&self) -> Result<(), SerializerError> {
if self.degraded {
warn!("Configuration won't be saved, since in degraded mode");
return Err(SerializerError::new_ex(
SerializerErrorKind::Generic,
String::from("Can't access theme file"),
));
}
debug!("Writing theme");
match OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(self.theme_path.as_path())
{
Ok(writer) => serialize(self.theme(), Box::new(writer)),
Err(err) => {
error!("Failed to write theme: {}", err);
Err(SerializerError::new_ex(
SerializerErrorKind::Io,
err.to_string(),
))
}
}
}
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use tempfile::TempDir;
use tuirealm::ratatui::style::Color;
use super::*;
#[test]
fn test_system_theme_provider_new() {
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
let theme_path: PathBuf = get_theme_path(tmp_dir.path());
let mut provider: ThemeProvider = ThemeProvider::new(theme_path.as_path()).unwrap();
assert_eq!(provider.theme().auth_address, Color::Yellow);
assert_eq!(provider.theme_path, theme_path);
assert_eq!(provider.degraded, false);
provider.theme_mut().auth_address = Color::Green;
assert_eq!(provider.theme().auth_address, Color::Green);
}
#[test]
fn test_system_theme_provider_load_and_save() {
let tmp_dir: tempfile::TempDir = TempDir::new().ok().unwrap();
let theme_path: PathBuf = get_theme_path(tmp_dir.path());
let mut provider: ThemeProvider = ThemeProvider::new(theme_path.as_path()).unwrap();
provider.theme_mut().auth_address = Color::Green;
assert!(provider.save().is_ok());
provider.theme_mut().auth_address = Color::Blue;
assert!(provider.load().is_ok());
assert_eq!(provider.theme().auth_address, Color::Green);
let provider: ThemeProvider = ThemeProvider::new(theme_path.as_path()).unwrap();
assert_eq!(provider.theme().auth_address, Color::Green); }
#[test]
fn test_system_theme_provider_degraded() {
let mut provider: ThemeProvider = ThemeProvider::degraded();
assert_eq!(provider.theme().auth_address, Color::Yellow);
assert_eq!(provider.degraded, true);
provider.theme_mut().auth_address = Color::Green;
assert!(provider.load().is_err());
assert_eq!(provider.theme().auth_address, Color::Yellow);
assert!(provider.save().is_err());
}
#[test]
fn test_system_theme_provider_err() {
assert!(ThemeProvider::new(Path::new("/tmp/oifoif/omar")).is_err());
}
fn get_theme_path(dir: &Path) -> PathBuf {
let mut p: PathBuf = PathBuf::from(dir);
p.push("theme.toml");
p
}
}