add: display warning in profile settings if your text contrast is horrible

This commit is contained in:
trisua 2025-04-22 19:46:08 -04:00
parent 434f2ba00d
commit f867abcb34
5 changed files with 172 additions and 16 deletions

View file

@ -313,6 +313,25 @@
<div class="w-full hidden flex flex-col gap-2" data-tab="theme">
<div class="card tertiary flex flex-col gap-2" id="theme_settings">
{% if failing_color_keys|length > 0 %}
<div
class="card flex flex-col gap-2"
style="background: white; color: black"
ui_ident="awful_contrast"
>
<div class="flex gap-2 items-center">
{{ icon "contrast" }}
<b>Some of your custom colors fail contrast checks:</b>
</div>
<ul>
{% for key in failing_color_keys %}
<li>{{ key[0] }} <b>{{ key[1] }} &lt; 4.5</b></li>
{% endfor %}
</ul>
</div>
{% endif %}
<div
class="card w-full flex flex-wrap gap-2"
ui_ident="import_export"
@ -725,6 +744,7 @@
"change_banner",
]);
ui.refresh_container(theme_settings, [
"awful_contrast",
"import_export",
"theme_preference",
"profile_theme",

View file

@ -10,6 +10,7 @@ use serde::Deserialize;
use tera::Context;
use tetratto_core::model::{Error, auth::User, communities::Community, permissions::FinePermission};
use tetratto_shared::hash::hash;
use contrasted::{Color, MINIMUM_CONTRAST_THRESHOLD};
#[derive(Deserialize)]
pub struct SettingsProps {
@ -59,6 +60,63 @@ pub async fn settings_request(
.replace("\"", "\\\""),
);
// check color contrasts
let mut failing_color_keys: Vec<(&str, f64)> = Vec::new();
let settings_map = serde_json::from_str::<serde_json::Map<String, serde_json::Value>>(
&serde_json::to_string(&profile.settings).unwrap(),
)
.unwrap();
let light = serde_json::Value::from("Light");
let mut profile_theme = settings_map
.get("profile_theme")
.unwrap_or(&light)
.as_str()
.unwrap();
if profile_theme.is_empty() | (profile_theme == "Auto") {
profile_theme = "Light";
}
let default_surface = serde_json::Value::from(if profile_theme == "Light" {
"#f3f2f1"
} else {
"#19171c"
});
let mut color_surface = settings_map
.get("theme_color_surface")
.unwrap_or(&default_surface)
.as_str()
.unwrap();
if color_surface.is_empty() {
color_surface = default_surface.as_str().unwrap();
}
for setting in &settings_map {
if !setting.0.starts_with("theme_color_text") {
continue;
}
let value = setting.1.as_str().unwrap();
if !value.starts_with("#") {
// we can only parse hex right now
continue;
}
let c1 = Color::from_hex(&color_surface);
let c2 = Color::from_hex(&value);
let contrast = c1.contrast(&c2);
if contrast < MINIMUM_CONTRAST_THRESHOLD {
failing_color_keys.push((setting.0, contrast));
}
}
context.insert("failing_color_keys", &failing_color_keys);
// return
Ok(Html(
data.1.render("profile/settings.html", &context).unwrap(),