feat: custom themes polishing
This commit is contained in:
@@ -92,6 +92,7 @@ class WebAppSettings(BaseModel):
|
||||
title: str
|
||||
primary_color: str
|
||||
logo_url: Optional[str]
|
||||
logo_use_emoji: bool
|
||||
logo_emoji: str
|
||||
logo_emoji_font: str
|
||||
session_ttl_seconds: int
|
||||
@@ -369,6 +370,7 @@ class Settings(BaseSettings):
|
||||
),
|
||||
)
|
||||
WEBAPP_LOGO_URL: Optional[str] = Field(default=None)
|
||||
WEBAPP_LOGO_USE_EMOJI: bool = Field(default=False)
|
||||
WEBAPP_LOGO_EMOJI: str = Field(default="🫥")
|
||||
WEBAPP_LOGO_EMOJI_FONT: str = Field(
|
||||
default="system",
|
||||
@@ -545,6 +547,7 @@ class Settings(BaseSettings):
|
||||
title=self.WEBAPP_TITLE,
|
||||
primary_color=self.WEBAPP_PRIMARY_COLOR,
|
||||
logo_url=self.WEBAPP_LOGO_URL,
|
||||
logo_use_emoji=self.WEBAPP_LOGO_USE_EMOJI,
|
||||
logo_emoji=self.WEBAPP_LOGO_EMOJI,
|
||||
logo_emoji_font=self.WEBAPP_LOGO_EMOJI_FONT,
|
||||
session_ttl_seconds=self.WEBAPP_SESSION_TTL_SECONDS,
|
||||
@@ -836,6 +839,31 @@ class Settings(BaseSettings):
|
||||
theme_dir=self.WEBAPP_THEMES_DIR,
|
||||
)
|
||||
|
||||
@field_validator("WEBAPP_PRIMARY_COLOR", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_primary_color_env(cls, _value):
|
||||
return "#00fe7a"
|
||||
|
||||
@field_validator("WEBAPP_LOGO_URL", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_logo_url_env(cls, _value):
|
||||
return None
|
||||
|
||||
@field_validator("WEBAPP_LOGO_USE_EMOJI", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_logo_use_emoji_env(cls, _value):
|
||||
return False
|
||||
|
||||
@field_validator("WEBAPP_LOGO_EMOJI", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_logo_emoji_env(cls, _value):
|
||||
return "🫥"
|
||||
|
||||
@field_validator("WEBAPP_LOGO_EMOJI_FONT", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_logo_emoji_font_env(cls, _value):
|
||||
return "system"
|
||||
|
||||
@computed_field
|
||||
@property
|
||||
def referral_bonus_inviter(self) -> Dict[int, int]:
|
||||
|
||||
@@ -8,7 +8,7 @@ import re
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
from pydantic import BaseModel, Field, field_validator, model_validator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -48,6 +48,22 @@ class ThemeTokens(BaseModel):
|
||||
admin_muted: Optional[str] = None
|
||||
admin_dim: Optional[str] = None
|
||||
|
||||
@field_validator("accent")
|
||||
@classmethod
|
||||
def _normalize_accent_hex(cls, value: Optional[str]) -> Optional[str]:
|
||||
if value is None:
|
||||
return None
|
||||
raw = str(value).strip()
|
||||
if not raw:
|
||||
return None
|
||||
match = re.fullmatch(r"#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})", raw)
|
||||
if not match:
|
||||
raise ValueError("accent must be a hex color (#RGB or #RRGGBB)")
|
||||
hex_value = match.group(1).lower()
|
||||
if len(hex_value) == 3:
|
||||
hex_value = "".join(char * 2 for char in hex_value)
|
||||
return f"#{hex_value}"
|
||||
|
||||
|
||||
class WebappTheme(BaseModel):
|
||||
"""Single theme descriptor loaded from WEBAPP_THEMES_DIR/<key>/theme.json."""
|
||||
@@ -256,10 +272,13 @@ def _theme_sort_key(theme: WebappTheme, index: int) -> tuple[int, int]:
|
||||
|
||||
|
||||
def _sorted_themes(themes: List[WebappTheme]) -> List[WebappTheme]:
|
||||
return [theme for _, theme in sorted(
|
||||
((_theme_sort_key(t, i), t) for i, t in enumerate(themes)),
|
||||
key=lambda pair: pair[0],
|
||||
)]
|
||||
return [
|
||||
theme
|
||||
for _, theme in sorted(
|
||||
((_theme_sort_key(t, i), t) for i, t in enumerate(themes)),
|
||||
key=lambda pair: pair[0],
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def _themes_config_from_list(
|
||||
|
||||
Reference in New Issue
Block a user