feat: init
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::AppError;
|
||||
use crate::models::common::{ColorScheme, Density, FontSize, Theme};
|
||||
use crate::models::users::UserAppearance;
|
||||
use crate::service::UserService;
|
||||
use crate::session::Session;
|
||||
|
||||
use super::util::{merge_optional_text, parse_enum};
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
|
||||
pub struct UpdateUserAppearanceParams {
|
||||
pub theme: Option<String>,
|
||||
pub color_scheme: Option<String>,
|
||||
pub density: Option<String>,
|
||||
pub font_size: Option<String>,
|
||||
pub editor_theme: Option<String>,
|
||||
pub markdown_preview: Option<bool>,
|
||||
pub reduced_motion: Option<bool>,
|
||||
}
|
||||
|
||||
impl UserService {
|
||||
pub async fn user_appearance(&self, ctx: &Session) -> Result<UserAppearance, AppError> {
|
||||
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
|
||||
self.ensure_user_appearance(user_uid).await
|
||||
}
|
||||
|
||||
pub async fn user_update_appearance(
|
||||
&self,
|
||||
ctx: &Session,
|
||||
params: UpdateUserAppearanceParams,
|
||||
) -> Result<UserAppearance, AppError> {
|
||||
let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
|
||||
let current = self.ensure_user_appearance(user_uid).await?;
|
||||
let theme = parse_enum(params.theme, current.theme, Theme::Unknown, "theme")?;
|
||||
let color_scheme = parse_enum(
|
||||
params.color_scheme,
|
||||
current.color_scheme,
|
||||
ColorScheme::Unknown,
|
||||
"color_scheme",
|
||||
)?;
|
||||
let density = parse_enum(params.density, current.density, Density::Unknown, "density")?;
|
||||
let font_size = parse_enum(
|
||||
params.font_size,
|
||||
current.font_size,
|
||||
FontSize::Unknown,
|
||||
"font_size",
|
||||
)?;
|
||||
|
||||
sqlx::query_as::<_, UserAppearance>(
|
||||
"UPDATE user_appearance SET theme = $1, color_scheme = $2, density = $3, font_size = $4, \
|
||||
editor_theme = $5, markdown_preview = $6, reduced_motion = $7, updated_at = $8 \
|
||||
WHERE user_id = $9 RETURNING user_id, theme, color_scheme, density, font_size, \
|
||||
editor_theme, markdown_preview, reduced_motion, created_at, updated_at",
|
||||
)
|
||||
.bind(theme)
|
||||
.bind(color_scheme)
|
||||
.bind(density)
|
||||
.bind(font_size)
|
||||
.bind(merge_optional_text(params.editor_theme, current.editor_theme))
|
||||
.bind(params.markdown_preview.unwrap_or(current.markdown_preview))
|
||||
.bind(params.reduced_motion.unwrap_or(current.reduced_motion))
|
||||
.bind(chrono::Utc::now())
|
||||
.bind(user_uid)
|
||||
.fetch_one(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)
|
||||
}
|
||||
|
||||
async fn ensure_user_appearance(
|
||||
&self,
|
||||
user_uid: uuid::Uuid,
|
||||
) -> Result<UserAppearance, AppError> {
|
||||
if let Some(appearance) = self.find_user_appearance(user_uid).await? {
|
||||
return Ok(appearance);
|
||||
}
|
||||
let now = chrono::Utc::now();
|
||||
sqlx::query(
|
||||
"INSERT INTO user_appearance (user_id, theme, color_scheme, density, font_size, \
|
||||
markdown_preview, reduced_motion, created_at, updated_at) \
|
||||
VALUES ($1, 'system', 'system', 'comfortable', 'medium', true, false, $2, $2) ON CONFLICT (user_id) DO NOTHING",
|
||||
)
|
||||
.bind(user_uid)
|
||||
.bind(now)
|
||||
.execute(self.ctx.db.writer())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
self.find_user_appearance(user_uid)
|
||||
.await?
|
||||
.ok_or(AppError::UserNotFound)
|
||||
}
|
||||
|
||||
async fn find_user_appearance(
|
||||
&self,
|
||||
user_uid: uuid::Uuid,
|
||||
) -> Result<Option<UserAppearance>, AppError> {
|
||||
sqlx::query_as::<_, UserAppearance>(
|
||||
"SELECT user_id, theme, color_scheme, density, font_size, editor_theme, \
|
||||
markdown_preview, reduced_motion, created_at, updated_at \
|
||||
FROM user_appearance WHERE user_id = $1",
|
||||
)
|
||||
.bind(user_uid)
|
||||
.fetch_optional(self.ctx.db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user