gitdataai/lib/service/user/accessibility.rs

111 lines
4.1 KiB
Rust

use db::sqlx;
use model::users::UserAccessibilityModel;
use serde::{Deserialize, Serialize};
use session::Session;
use crate::{AppService, error::AppError, session_user};
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct UserAccessibilityConfig {
pub reduce_motion: bool,
pub high_contrast: bool,
pub screen_reader_optimized: bool,
pub font_scale_percent: i32,
pub color_blind_mode: Option<String>,
}
#[derive(Debug, Clone, Deserialize, utoipa::ToSchema)]
pub struct UpdateUserAccessibilityConfig {
pub reduce_motion: Option<bool>,
pub high_contrast: Option<bool>,
pub screen_reader_optimized: Option<bool>,
pub font_scale_percent: Option<i32>,
pub color_blind_mode: Option<Option<String>>,
}
impl AppService {
pub async fn user_update_accessibility_config(
&self,
ctx: &Session,
params: UpdateUserAccessibilityConfig,
) -> Result<UserAccessibilityConfig, AppError> {
let user_uid = session_user(ctx)?;
let mut config = self.user_accessibility_config(user_uid).await?;
if let Some(reduce_motion) = params.reduce_motion {
config.reduce_motion = reduce_motion;
}
if let Some(high_contrast) = params.high_contrast {
config.high_contrast = high_contrast;
}
if let Some(screen_reader_optimized) = params.screen_reader_optimized {
config.screen_reader_optimized = screen_reader_optimized;
}
if let Some(font_scale_percent) = params.font_scale_percent {
config.font_scale_percent = font_scale_percent.clamp(50, 200);
}
if let Some(color_blind_mode) = params.color_blind_mode {
config.color_blind_mode = color_blind_mode;
}
let now = chrono::Utc::now();
sqlx::query(
"INSERT INTO user_accessibility \
(\"user\", reduce_motion, high_contrast, screen_reader_optimized, font_scale_percent, color_blind_mode, created_at, updated_at) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $7) \
ON CONFLICT (\"user\") DO UPDATE SET \
reduce_motion = EXCLUDED.reduce_motion, high_contrast = EXCLUDED.high_contrast, \
screen_reader_optimized = EXCLUDED.screen_reader_optimized, font_scale_percent = EXCLUDED.font_scale_percent, \
color_blind_mode = EXCLUDED.color_blind_mode, updated_at = EXCLUDED.updated_at",
)
.bind(user_uid)
.bind(config.reduce_motion)
.bind(config.high_contrast)
.bind(config.screen_reader_optimized)
.bind(config.font_scale_percent)
.bind(&config.color_blind_mode)
.bind(now)
.execute(self.db.writer())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(config)
}
pub async fn user_accessibility_config(
&self,
user_uid: uuid::Uuid,
) -> Result<UserAccessibilityConfig, AppError> {
let row = sqlx::query_as::<_, UserAccessibilityModel>(
"SELECT \"user\", reduce_motion, high_contrast, screen_reader_optimized, font_scale_percent, color_blind_mode, created_at, updated_at \
FROM user_accessibility WHERE \"user\" = $1",
)
.bind(user_uid)
.fetch_optional(self.db.reader())
.await
.map_err(|e| AppError::DatabaseError(e.to_string()))?;
Ok(row.map(Into::into).unwrap_or_default())
}
}
impl Default for UserAccessibilityConfig {
fn default() -> Self {
Self {
reduce_motion: false,
high_contrast: false,
screen_reader_optimized: false,
font_scale_percent: 100,
color_blind_mode: None,
}
}
}
impl From<UserAccessibilityModel> for UserAccessibilityConfig {
fn from(value: UserAccessibilityModel) -> Self {
Self {
reduce_motion: value.reduce_motion,
high_contrast: value.high_contrast,
screen_reader_optimized: value.screen_reader_optimized,
font_scale_percent: value.font_scale_percent,
color_blind_mode: value.color_blind_mode,
}
}
}