♻️ Make random_svg_generators able to get placeholder according to the target
This commit is contained in:
@@ -1,13 +1,18 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Result as IoResult;
|
use std::future::Future;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
use std::{collections::HashMap, future::IntoFuture};
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
use rand::distributions::{Alphanumeric, DistString};
|
||||||
use reqwest::Result as RequestResult;
|
use reqwest::Result as RequestResult;
|
||||||
|
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
use tokio::fs::read_to_string;
|
use tokio::fs::read_to_string;
|
||||||
|
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
use web_sys;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash)]
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
pub enum AvatarFeeling {
|
pub enum AvatarFeeling {
|
||||||
Ok,
|
Ok,
|
||||||
@@ -59,9 +64,9 @@ struct DicebearConfig<'a> {
|
|||||||
lips: Vec<u32>,
|
lips: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dicebear_variants() -> &'static HashMap<AvatarFeeling, DicebearConfig<'static>> {
|
fn avatar_variants() -> &'static HashMap<AvatarFeeling, DicebearConfig<'static>> {
|
||||||
static HASHMAP: OnceLock<HashMap<AvatarFeeling, DicebearConfig>> = OnceLock::new();
|
static VARIANTS: OnceLock<HashMap<AvatarFeeling, DicebearConfig>> = OnceLock::new();
|
||||||
HASHMAP.get_or_init(|| {
|
VARIANTS.get_or_init(|| {
|
||||||
let mut variants = HashMap::new();
|
let mut variants = HashMap::new();
|
||||||
variants.insert(
|
variants.insert(
|
||||||
AvatarFeeling::Alerting,
|
AvatarFeeling::Alerting,
|
||||||
@@ -103,17 +108,16 @@ fn render_dicebear_variants(values: &[u32]) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_text(req: String) -> RequestResult<String> {
|
async fn fetch_text(req: String) -> RequestResult<String> {
|
||||||
reqwest::get(req).await?.text().await
|
match reqwest::get(req).await?.error_for_status() {
|
||||||
}
|
Ok(res) => res.text().await,
|
||||||
|
Err(err) => Err(err),
|
||||||
async fn read_file(path: &str) -> IoResult<String> {
|
}
|
||||||
read_to_string(path).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_dicebear_svg(
|
async fn fetch_dicebear_svg(
|
||||||
r#type: &DicebearType,
|
r#type: &DicebearType,
|
||||||
req_fields: &Vec<String>,
|
req_fields: &Vec<String>,
|
||||||
placeholder_path: Option<&str>,
|
placeholder_fetcher: Option<Box<impl Future<Output = Option<String>>>>,
|
||||||
) -> String {
|
) -> String {
|
||||||
// TODO: Use configuration file
|
// TODO: Use configuration file
|
||||||
let url = "dicebear.tools.adrien.run";
|
let url = "dicebear.tools.adrien.run";
|
||||||
@@ -130,19 +134,10 @@ async fn fetch_dicebear_svg(
|
|||||||
Ok(text) => Some(text),
|
Ok(text) => Some(text),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Error during placeholder loading: {}", err);
|
error!("Error during placeholder loading: {}", err);
|
||||||
|
if let Some(placeholder_fetcher) = placeholder_fetcher {
|
||||||
match placeholder_path {
|
placeholder_fetcher.into_future().await
|
||||||
Some(placeholder_path) => match read_file(placeholder_path).await {
|
} else {
|
||||||
Ok(content) => Some(content),
|
None
|
||||||
Err(err) => {
|
|
||||||
error!(
|
|
||||||
"Error during to read {placeholder_path} file: {}",
|
|
||||||
err.to_string()
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -150,9 +145,44 @@ async fn fetch_dicebear_svg(
|
|||||||
text.unwrap_or("".to_string())
|
text.unwrap_or("".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
|
fn gen_placeholder_fetcher<'a>(path: &'static str) -> Box<impl Future<Output = Option<String>>> {
|
||||||
|
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<impl Future<Output = Option<String>>> {
|
||||||
|
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<impl Future<Output = Option<String>>> {
|
||||||
|
Box::new(async move { None })
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>) -> String {
|
pub async fn generate_random_svg_avatar<'a>(config: Option<&'a AvatarConfig<'a>>) -> String {
|
||||||
let (variant, feeling) = match config {
|
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),
|
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 {
|
let placeholder_path = match feeling {
|
||||||
AvatarFeeling::Ok => "./images/modal-default-ok-icon.svg",
|
AvatarFeeling::Ok => "/images/modal-default-ok-icon.svg",
|
||||||
AvatarFeeling::Warning => "./images/modal-default-warning-icon.svg",
|
AvatarFeeling::Warning => "/images/modal-default-warning-icon.svg",
|
||||||
AvatarFeeling::Alerting => "./images/modal-default-critical-icon.svg",
|
AvatarFeeling::Alerting => "/images/modal-default-critical-icon.svg",
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch_dicebear_svg(
|
fetch_dicebear_svg(
|
||||||
&DicebearType::Notionists,
|
&DicebearType::Notionists,
|
||||||
&req_fields,
|
&req_fields,
|
||||||
Some(placeholder_path),
|
Some(gen_placeholder_fetcher(placeholder_path)),
|
||||||
)
|
)
|
||||||
.await
|
.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));
|
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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user