diff --git a/src/infrastructure/services/random_svg_generators.rs b/src/infrastructure/services/random_svg_generators.rs index e0c1c7a..bd51b50 100644 --- a/src/infrastructure/services/random_svg_generators.rs +++ b/src/infrastructure/services/random_svg_generators.rs @@ -1,13 +1,18 @@ -use std::collections::HashMap; use std::fmt; -use std::io::Result as IoResult; +use std::future::Future; use std::sync::OnceLock; +use std::{collections::HashMap, future::IntoFuture}; use log::error; use rand::distributions::{Alphanumeric, DistString}; use reqwest::Result as RequestResult; + +#[cfg(feature = "desktop")] use tokio::fs::read_to_string; +#[cfg(feature = "web")] +use web_sys; + #[derive(Eq, PartialEq, Hash)] pub enum AvatarFeeling { Ok, @@ -59,9 +64,9 @@ struct DicebearConfig<'a> { lips: Vec, } -fn dicebear_variants() -> &'static HashMap> { - static HASHMAP: OnceLock> = OnceLock::new(); - HASHMAP.get_or_init(|| { +fn avatar_variants() -> &'static HashMap> { + static VARIANTS: OnceLock> = OnceLock::new(); + VARIANTS.get_or_init(|| { let mut variants = HashMap::new(); variants.insert( AvatarFeeling::Alerting, @@ -103,17 +108,16 @@ fn render_dicebear_variants(values: &[u32]) -> String { } async fn fetch_text(req: String) -> RequestResult { - reqwest::get(req).await?.text().await -} - -async fn read_file(path: &str) -> IoResult { - read_to_string(path).await + match reqwest::get(req).await?.error_for_status() { + Ok(res) => res.text().await, + Err(err) => Err(err), + } } async fn fetch_dicebear_svg( r#type: &DicebearType, req_fields: &Vec, - placeholder_path: Option<&str>, + placeholder_fetcher: Option>>>, ) -> String { // TODO: Use configuration file let url = "dicebear.tools.adrien.run"; @@ -130,19 +134,10 @@ async fn fetch_dicebear_svg( Ok(text) => Some(text), Err(err) => { error!("Error during placeholder loading: {}", err); - - match placeholder_path { - Some(placeholder_path) => match read_file(placeholder_path).await { - Ok(content) => Some(content), - Err(err) => { - error!( - "Error during to read {placeholder_path} file: {}", - err.to_string() - ); - None - } - }, - None => None, + if let Some(placeholder_fetcher) = placeholder_fetcher { + placeholder_fetcher.into_future().await + } else { + None } } }; @@ -150,9 +145,44 @@ async fn fetch_dicebear_svg( text.unwrap_or("".to_string()) } +#[cfg(feature = "desktop")] +fn gen_placeholder_fetcher<'a>(path: &'static str) -> Box>> { + let path = format!(".{}", &path); + Box::new(async move { + match read_to_string(&path).await { + Ok(content) => Some(content), + Err(err) => { + error!( + "Error during the access to the {path} file: {}", + err.to_string() + ); + None + } + } + }) +} +#[cfg(feature = "web")] +fn gen_placeholder_fetcher<'a>(path: &'static str) -> Box>> { + Box::new(async move { + let url = format!("{}{}", web_sys::window().unwrap().origin(), path); + match fetch_text(url).await { + Ok(content) => Some(content), + Err(err) => { + error!("Error during {path} fetching: {}", err.to_string()); + None + } + } + }) +} + +#[cfg(not(any(feature = "desktop", feature = "web")))] +fn gen_placeholder_fetcher<'a>(_path: &'static str) -> Box>> { + Box::new(async move { None }) +} + pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>) -> String { let (variant, feeling) = match config { - Some(config) => (dicebear_variants().get(&config.feeling), &config.feeling), + Some(config) => (avatar_variants().get(&config.feeling), &config.feeling), None => (None, &AvatarFeeling::Alerting), }; @@ -182,15 +212,15 @@ pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>> } let placeholder_path = match feeling { - AvatarFeeling::Ok => "./images/modal-default-ok-icon.svg", - AvatarFeeling::Warning => "./images/modal-default-warning-icon.svg", - AvatarFeeling::Alerting => "./images/modal-default-critical-icon.svg", + AvatarFeeling::Ok => "/images/modal-default-ok-icon.svg", + AvatarFeeling::Warning => "/images/modal-default-warning-icon.svg", + AvatarFeeling::Alerting => "/images/modal-default-critical-icon.svg", }; fetch_dicebear_svg( &DicebearType::Notionists, &req_fields, - Some(placeholder_path), + Some(gen_placeholder_fetcher(placeholder_path)), ) .await } @@ -227,5 +257,11 @@ pub async fn generate_random_svg_shape<'a>(config: Option<&'a ShapeConfig<'a>>) req_fields.push(format!("shape3Color={}", config.shape_3_color)); } - fetch_dicebear_svg(&DicebearType::Shapes, &req_fields, None).await + let placeholder_path = "/images/login-profile-placeholder.svg"; + fetch_dicebear_svg( + &DicebearType::Shapes, + &req_fields, + Some(gen_placeholder_fetcher(placeholder_path)), + ) + .await }