refactor(webapp): remove emoji web app logo option
Drop the emoji-logo feature (and its font picker) from the Web App. Only an uploaded/linked image logo and favicon remain; when no logo is set, the default project logo is shown. Existing emoji-logo overrides are ignored — the keys are gone from the manifest, so the override service skips them and the app falls back to the default logo. - Remove WEBAPP_LOGO_USE_EMOJI / WEBAPP_LOGO_EMOJI / WEBAPP_LOGO_EMOJI_FONT settings, validators, manifest entries and override/runtime plumbing. - Strip the animated-emoji fetch/cache subsystem, the /webapp-emoji route and emoji branches from logo/favicon resolution; leftover emoji cache files are now purged on appearance save. - Simplify BrandMark to an image-only component and drop the emoji UI from the admin Appearance section. - Regenerate the demo settings manifest and clean docs, locales, nginx and demo data of emoji-logo references.
This commit is contained in:
@@ -136,10 +136,6 @@ def _favicon_digest(url: str) -> Optional[str]:
|
||||
return match.group(1) if match else None
|
||||
|
||||
|
||||
def _emoji_to_codepoints(value: str) -> str:
|
||||
return "_".join(f"{ord(char):x}" for char in str(value or "").strip())
|
||||
|
||||
|
||||
def prune_unused_appearance_assets(settings: Settings) -> None:
|
||||
keep_logos = {
|
||||
filename
|
||||
@@ -156,15 +152,6 @@ def prune_unused_appearance_assets(settings: Settings) -> None:
|
||||
]
|
||||
if digest
|
||||
}
|
||||
keep_emoji_prefixes = set()
|
||||
if (
|
||||
getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False)
|
||||
and str(getattr(settings, "WEBAPP_LOGO_EMOJI_FONT", "") or "").strip()
|
||||
== "noto-color-animated"
|
||||
):
|
||||
codepoints = _emoji_to_codepoints(getattr(settings, "WEBAPP_LOGO_EMOJI", ""))
|
||||
if codepoints:
|
||||
keep_emoji_prefixes.add(f"{codepoints}.512.")
|
||||
|
||||
for path in WEBAPP_UPLOADED_LOGO_DIR.glob("logo-*"):
|
||||
if path.is_file() and path.name not in keep_logos:
|
||||
@@ -184,10 +171,9 @@ def prune_unused_appearance_assets(settings: Settings) -> None:
|
||||
except OSError:
|
||||
logger.warning("Failed to remove unused webapp favicon set %s", path, exc_info=True)
|
||||
|
||||
# Emoji logos were removed; purge any leftover animated-emoji cache files.
|
||||
for path in WEBAPP_EMOJI_CACHE_DIR.glob("*.512.*"):
|
||||
if path.is_file() and not any(
|
||||
path.name.startswith(prefix) for prefix in keep_emoji_prefixes
|
||||
):
|
||||
if path.is_file():
|
||||
try:
|
||||
path.unlink()
|
||||
except OSError:
|
||||
@@ -389,7 +375,6 @@ async def admin_appearance_logo_upload_route(request: web.Request) -> web.Respon
|
||||
request,
|
||||
{
|
||||
"WEBAPP_LOGO_URL": logo_url,
|
||||
"WEBAPP_LOGO_USE_EMOJI": False,
|
||||
**(
|
||||
{"WEBAPP_LOGO_FAVICON_URL": favicon_payload["favicon_url"]}
|
||||
if favicon_payload.get("favicon_url")
|
||||
|
||||
@@ -13,9 +13,6 @@ WEBAPP_APPEARANCE_SETTING_KEYS = frozenset(
|
||||
{
|
||||
"WEBAPP_TITLE",
|
||||
"WEBAPP_LOGO_URL",
|
||||
"WEBAPP_LOGO_USE_EMOJI",
|
||||
"WEBAPP_LOGO_EMOJI",
|
||||
"WEBAPP_LOGO_EMOJI_FONT",
|
||||
"WEBAPP_FAVICON_URL",
|
||||
"WEBAPP_FAVICON_USE_CUSTOM",
|
||||
"WEBAPP_LOGO_FAVICON_URL",
|
||||
|
||||
@@ -181,27 +181,7 @@ SETTINGS_MANIFEST: List[SettingField] = [
|
||||
SettingField(
|
||||
"WEBAPP_PRIMARY_COLOR", "color", "appearance", "Основной цвет", placeholder="#00fe7a"
|
||||
),
|
||||
SettingField("WEBAPP_LOGO_USE_EMOJI", "bool", "appearance", "Использовать эмоджи-логотип"),
|
||||
SettingField("WEBAPP_LOGO_URL", "url", "appearance", "URL логотипа"),
|
||||
SettingField("WEBAPP_LOGO_EMOJI", "string", "appearance", "Эмоджи-логотип", placeholder="🫥"),
|
||||
SettingField(
|
||||
"WEBAPP_LOGO_EMOJI_FONT",
|
||||
"string",
|
||||
"appearance",
|
||||
"Шрифт эмоджи-логотипа",
|
||||
"Выберите шрифт для отображения эмодзи-логотипа",
|
||||
choices=(
|
||||
("system", "Системный (по умолчанию)"),
|
||||
("noto-color", "Noto Color Emoji"),
|
||||
("noto-color-animated", "Noto Color Emoji Animated"),
|
||||
("noto-emoji", "Noto Emoji"),
|
||||
("twemoji", "Twitter Emoji"),
|
||||
("openmoji", "OpenMoji"),
|
||||
("apple", "Apple Color Emoji (local)"),
|
||||
("segoe", "Segoe UI Emoji (local)"),
|
||||
("noto-local", "Noto Emoji (local)"),
|
||||
),
|
||||
),
|
||||
SettingField(
|
||||
"WEBAPP_FAVICON_USE_CUSTOM",
|
||||
"bool",
|
||||
|
||||
@@ -82,7 +82,6 @@ WEBAPP_DEFAULT_LOGO_PATH = "/webapp-default-logo.webp"
|
||||
WEBAPP_DEFAULT_FAVICON_DIGEST = "19b2a242e5b7bc2d"
|
||||
WEBAPP_DEFAULT_FAVICON_DIR = WEBAPP_DEFAULT_BRAND_DIR / "favicons" / WEBAPP_DEFAULT_FAVICON_DIGEST
|
||||
WEBAPP_DEFAULT_FAVICON_URL = f"{WEBAPP_FAVICON_PATH}/{WEBAPP_DEFAULT_FAVICON_DIGEST}/icon-180.png"
|
||||
WEBAPP_EMOJI_CACHE_DIR = APP_ROOT / "data" / "webapp-emoji"
|
||||
WEBAPP_CONFIG_PLACEHOLDER = "<!-- WEBAPP_CONFIG_SCRIPT -->"
|
||||
WEBAPP_I18N_PLACEHOLDER = "<!-- WEBAPP_I18N_SCRIPT -->"
|
||||
WEBAPP_JS_PLACEHOLDER = "<!-- WEBAPP_JS_SCRIPT -->"
|
||||
@@ -92,7 +91,6 @@ DEV_MOCK_END_MARKER = "<!-- WEBAPP_DEV_MOCK_END -->"
|
||||
WEBAPP_RATE_LIMIT_WINDOW_SECONDS = 60
|
||||
WEBAPP_RATE_LIMIT_MAX_REQUESTS = 30
|
||||
WEBAPP_LOGO_MAX_BYTES = 2 * 1024 * 1024
|
||||
WEBAPP_EMOJI_MAX_BYTES = 4 * 1024 * 1024
|
||||
WEBAPP_THEME_CSS_MAX_BYTES = 512 * 1024
|
||||
WEBAPP_THEME_ASSET_MAX_BYTES = 1024 * 1024
|
||||
WEBAPP_THEME_ASSET_CONTENT_TYPES = {
|
||||
|
||||
@@ -33,7 +33,6 @@ def create_subscription_webapp_application(
|
||||
async def _startup(app_obj: web.Application) -> None:
|
||||
await _ensure_shared_http_session()
|
||||
await _warm_webapp_logo_cache(app_obj)
|
||||
await _warm_webapp_animated_emoji_cache(app_obj)
|
||||
await warm_subscription_guides_config(app_obj)
|
||||
|
||||
async def _shutdown(app_obj: web.Application) -> None:
|
||||
|
||||
@@ -206,9 +206,6 @@ async def theme_asset_route(request: web.Request) -> web.Response:
|
||||
|
||||
|
||||
def _resolve_webapp_logo_url(settings: Settings) -> str:
|
||||
if getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
return ""
|
||||
|
||||
raw_logo_url = (getattr(settings, "WEBAPP_LOGO_URL", None) or "").strip()
|
||||
if not raw_logo_url:
|
||||
return WEBAPP_DEFAULT_LOGO_PATH
|
||||
@@ -303,29 +300,8 @@ def _uploaded_webapp_logo_response(filename: str) -> web.Response:
|
||||
return response
|
||||
|
||||
|
||||
def _emoji_to_codepoints(value: str) -> str:
|
||||
return "_".join(f"{ord(char):x}" for char in str(value or "").strip())
|
||||
|
||||
|
||||
def _webapp_emoji_disk_path(codepoints: str, ext: str) -> Path:
|
||||
return WEBAPP_EMOJI_CACHE_DIR / f"{codepoints}.512.{ext}"
|
||||
|
||||
|
||||
def _webapp_animated_emoji_source_url(codepoints: str, ext: str) -> str:
|
||||
return f"https://fonts.gstatic.com/s/e/notoemoji/latest/{codepoints}/512.{ext}"
|
||||
|
||||
|
||||
def _webapp_animated_emoji_asset_path(emoji: str, ext: str = "gif") -> str:
|
||||
codepoints = _emoji_to_codepoints(emoji)
|
||||
if not codepoints or ext not in {"gif", "webp"}:
|
||||
return ""
|
||||
return f"/webapp-emoji/{codepoints}/512.{ext}"
|
||||
|
||||
|
||||
async def webapp_logo_route(request: web.Request) -> web.Response:
|
||||
settings: Settings = request.app["settings"]
|
||||
if getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
raise web.HTTPNotFound(text="webapp_logo_disabled")
|
||||
raw_logo_url = (settings.WEBAPP_LOGO_URL or "").strip()
|
||||
if not raw_logo_url:
|
||||
raise web.HTTPNotFound(text="webapp_logo_not_configured")
|
||||
@@ -521,37 +497,8 @@ def _webapp_default_brand_file_response(path: Path, content_type: str) -> web.Re
|
||||
return web.Response(body=body, content_type=content_type)
|
||||
|
||||
|
||||
async def webapp_animated_emoji_route(request: web.Request) -> web.Response:
|
||||
codepoints = str(request.match_info.get("codepoints") or "").strip().lower()
|
||||
ext = str(request.match_info.get("ext") or "").strip().lower()
|
||||
if not re.fullmatch(r"[0-9a-f]+(?:_[0-9a-f]+)*", codepoints) or ext not in {"gif", "webp"}:
|
||||
raise web.HTTPNotFound(text="webapp_emoji_not_found")
|
||||
|
||||
emoji_cache_key = f"{codepoints}:{ext}"
|
||||
emoji_caches: Dict[str, Tuple[bytes, str]] = request.app.setdefault("webapp_emoji_cache", {})
|
||||
emoji_cache = emoji_caches.get(emoji_cache_key)
|
||||
if emoji_cache is None:
|
||||
cache_lock: asyncio.Lock = request.app.setdefault("webapp_emoji_cache_lock", asyncio.Lock())
|
||||
async with cache_lock:
|
||||
emoji_cache = emoji_caches.get(emoji_cache_key)
|
||||
if emoji_cache is None:
|
||||
emoji_cache = await _load_or_fetch_webapp_animated_emoji(codepoints, ext)
|
||||
if emoji_cache:
|
||||
emoji_caches[emoji_cache_key] = emoji_cache
|
||||
|
||||
if not emoji_cache:
|
||||
raise web.HTTPNotFound(text="webapp_emoji_unavailable")
|
||||
|
||||
body, content_type = emoji_cache
|
||||
response = web.Response(body=body, content_type=content_type)
|
||||
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
|
||||
return response
|
||||
|
||||
|
||||
async def _warm_webapp_logo_cache(app: web.Application) -> None:
|
||||
settings: Settings = app["settings"]
|
||||
if getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
return
|
||||
raw_logo_url = (settings.WEBAPP_LOGO_URL or "").strip()
|
||||
if not raw_logo_url or not _is_proxyable_webapp_logo_url(raw_logo_url):
|
||||
return
|
||||
@@ -573,111 +520,6 @@ async def _warm_webapp_logo_cache(app: web.Application) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def _warm_webapp_animated_emoji_cache(app: web.Application) -> None:
|
||||
settings: Settings = app["settings"]
|
||||
if not getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
return
|
||||
if str(settings.WEBAPP_LOGO_EMOJI_FONT or "").strip() != "noto-color-animated":
|
||||
return
|
||||
|
||||
codepoints = _emoji_to_codepoints(settings.WEBAPP_LOGO_EMOJI)
|
||||
if not codepoints:
|
||||
return
|
||||
|
||||
app.setdefault("webapp_emoji_cache", {})
|
||||
app.setdefault("webapp_emoji_cache_lock", asyncio.Lock())
|
||||
emoji_caches: Dict[str, Tuple[bytes, str]] = app["webapp_emoji_cache"]
|
||||
|
||||
for ext in ("gif", "webp"):
|
||||
emoji_cache_key = f"{codepoints}:{ext}"
|
||||
if emoji_cache_key in emoji_caches:
|
||||
continue
|
||||
loaded_emoji = await _load_or_fetch_webapp_animated_emoji(codepoints, ext)
|
||||
if loaded_emoji:
|
||||
emoji_caches[emoji_cache_key] = loaded_emoji
|
||||
if ext == "gif":
|
||||
return
|
||||
|
||||
|
||||
async def _load_or_fetch_webapp_animated_emoji(
|
||||
codepoints: str, ext: str
|
||||
) -> Optional[Tuple[bytes, str]]:
|
||||
disk_emoji = await asyncio.to_thread(_read_webapp_animated_emoji_from_disk, codepoints, ext)
|
||||
if disk_emoji:
|
||||
return disk_emoji
|
||||
|
||||
fetched_emoji = await _fetch_webapp_animated_emoji(codepoints, ext)
|
||||
if fetched_emoji:
|
||||
await asyncio.to_thread(
|
||||
_write_webapp_animated_emoji_to_disk, codepoints, ext, fetched_emoji
|
||||
)
|
||||
return fetched_emoji
|
||||
|
||||
|
||||
def _read_webapp_animated_emoji_from_disk(codepoints: str, ext: str) -> Optional[Tuple[bytes, str]]:
|
||||
path = _webapp_emoji_disk_path(codepoints, ext)
|
||||
try:
|
||||
body = path.read_bytes()
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
if not body or len(body) > WEBAPP_EMOJI_MAX_BYTES:
|
||||
return None
|
||||
return body, "image/gif" if ext == "gif" else "image/webp"
|
||||
|
||||
|
||||
def _write_webapp_animated_emoji_to_disk(
|
||||
codepoints: str, ext: str, emoji: Tuple[bytes, str]
|
||||
) -> None:
|
||||
body, _content_type = emoji
|
||||
if not body or len(body) > WEBAPP_EMOJI_MAX_BYTES:
|
||||
return
|
||||
|
||||
path = _webapp_emoji_disk_path(codepoints, ext)
|
||||
try:
|
||||
WEBAPP_EMOJI_CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
path.write_bytes(body)
|
||||
except OSError as exc:
|
||||
logger.warning("Failed to write WEBAPP animated emoji cache: %s", exc)
|
||||
|
||||
|
||||
async def _fetch_webapp_animated_emoji(codepoints: str, ext: str) -> Optional[Tuple[bytes, str]]:
|
||||
try:
|
||||
session = await _get_shared_http_session()
|
||||
timeout = ClientTimeout(total=4)
|
||||
source_url = _webapp_animated_emoji_source_url(codepoints, ext)
|
||||
async with session.get(
|
||||
source_url,
|
||||
allow_redirects=False,
|
||||
headers={"Accept": "image/gif,image/webp,image/*,*/*;q=0.8"},
|
||||
timeout=timeout,
|
||||
) as response:
|
||||
if response.status != 200:
|
||||
return None
|
||||
|
||||
content_type = (
|
||||
(response.headers.get("Content-Type") or "").split(";", 1)[0].strip().lower()
|
||||
)
|
||||
expected_content_type = "image/gif" if ext == "gif" else "image/webp"
|
||||
if content_type and content_type != expected_content_type:
|
||||
return None
|
||||
|
||||
body = bytearray()
|
||||
async for chunk in response.content.iter_chunked(64 * 1024):
|
||||
body.extend(chunk)
|
||||
if len(body) > WEBAPP_EMOJI_MAX_BYTES:
|
||||
logger.warning("WEBAPP animated emoji exceeded the 4 MiB limit.")
|
||||
return None
|
||||
|
||||
if not body:
|
||||
return None
|
||||
|
||||
return bytes(body), expected_content_type
|
||||
except Exception as exc:
|
||||
logger.warning("Failed to fetch WEBAPP animated emoji: %s", exc)
|
||||
return None
|
||||
|
||||
|
||||
async def _load_or_fetch_webapp_logo(logo_url: str) -> Optional[Tuple[bytes, str]]:
|
||||
disk_logo = await asyncio.to_thread(_read_webapp_logo_from_disk, logo_url)
|
||||
if disk_logo:
|
||||
@@ -1144,9 +986,6 @@ def _build_webapp_bootstrap_payload(request: web.Request) -> Dict[str, Any]:
|
||||
"themesDir": settings.WEBAPP_THEMES_DIR,
|
||||
"themePreviewKey": preview_key,
|
||||
"logoUrl": cached["logo_url"],
|
||||
"logoUseEmoji": bool(settings.WEBAPP_LOGO_USE_EMOJI),
|
||||
"logoEmoji": settings.WEBAPP_LOGO_EMOJI,
|
||||
"logoEmojiFont": settings.WEBAPP_LOGO_EMOJI_FONT,
|
||||
"faviconUrl": cached["favicon_url"],
|
||||
"faviconUseCustom": bool(settings.WEBAPP_FAVICON_USE_CUSTOM),
|
||||
"apiBase": "/api",
|
||||
@@ -1308,12 +1147,6 @@ async def index_route(request: web.Request) -> web.Response:
|
||||
f'<script src="/{_resolve_webapp_js_asset_name()}" defer></script>',
|
||||
)
|
||||
brand_asset_url = cached["logo_url"]
|
||||
if (
|
||||
not brand_asset_url
|
||||
and settings.WEBAPP_LOGO_USE_EMOJI
|
||||
and settings.WEBAPP_LOGO_EMOJI_FONT == "noto-color-animated"
|
||||
):
|
||||
brand_asset_url = _webapp_animated_emoji_asset_path(settings.WEBAPP_LOGO_EMOJI)
|
||||
if brand_asset_url:
|
||||
html = html.replace(
|
||||
"</head>",
|
||||
|
||||
@@ -46,10 +46,6 @@ def setup_subscription_webapp_routes(app: web.Application) -> None:
|
||||
rf"{WEBAPP_FAVICON_PATH}/{{digest:[0-9a-f]{{16}}}}/{{filename:[A-Za-z0-9_.-]+}}",
|
||||
webapp_favicon_route,
|
||||
)
|
||||
app.router.add_get(
|
||||
r"/webapp-emoji/{codepoints:[0-9a-f_]+}/512.{ext:gif|webp}",
|
||||
webapp_animated_emoji_route,
|
||||
)
|
||||
app.router.add_get("/subscription_webapp.{asset_hash:[0-9a-f]{8}}.css", css_asset_route)
|
||||
app.router.add_get("/subscription_webapp.css", css_asset_route)
|
||||
app.router.add_get(
|
||||
|
||||
@@ -48,8 +48,6 @@ def _safe_color(value: Optional[str]) -> str:
|
||||
def _public_logo_url(settings: Settings) -> Optional[str]:
|
||||
"""Email recipients can't reach the in-app /webapp-logo proxy, so only a
|
||||
stored public https URL can be used directly. Anything else is dropped."""
|
||||
if getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
return None
|
||||
raw = (settings.WEBAPP_LOGO_URL or "").strip()
|
||||
if not raw:
|
||||
return None
|
||||
|
||||
@@ -28,10 +28,7 @@ from db.dal import app_settings_dal
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
APPEARANCE_OVERRIDE_KEYS = {
|
||||
"WEBAPP_LOGO_USE_EMOJI",
|
||||
"WEBAPP_LOGO_URL",
|
||||
"WEBAPP_LOGO_EMOJI",
|
||||
"WEBAPP_LOGO_EMOJI_FONT",
|
||||
"WEBAPP_FAVICON_USE_CUSTOM",
|
||||
"WEBAPP_FAVICON_URL",
|
||||
"WEBAPP_LOGO_FAVICON_URL",
|
||||
@@ -167,12 +164,6 @@ def _appearance_snapshot(settings: Settings) -> Dict[str, Any]:
|
||||
snapshot["WEBAPP_FAVICON_URL"] = favicon_url
|
||||
if getattr(settings, "WEBAPP_FAVICON_USE_CUSTOM", False):
|
||||
snapshot["WEBAPP_FAVICON_USE_CUSTOM"] = True
|
||||
if getattr(settings, "WEBAPP_LOGO_USE_EMOJI", False):
|
||||
snapshot["WEBAPP_LOGO_USE_EMOJI"] = True
|
||||
snapshot["WEBAPP_LOGO_EMOJI"] = getattr(settings, "WEBAPP_LOGO_EMOJI", "")
|
||||
emoji_font = getattr(settings, "WEBAPP_LOGO_EMOJI_FONT", "")
|
||||
if emoji_font and emoji_font != "system":
|
||||
snapshot["WEBAPP_LOGO_EMOJI_FONT"] = emoji_font
|
||||
primary_color = getattr(settings, "WEBAPP_PRIMARY_COLOR", None)
|
||||
if primary_color and primary_color != "#00fe7a":
|
||||
snapshot["WEBAPP_PRIMARY_COLOR"] = primary_color
|
||||
|
||||
@@ -59,9 +59,6 @@ class WebAppSettings(BaseModel):
|
||||
title: str
|
||||
primary_color: str
|
||||
logo_url: Optional[str]
|
||||
logo_use_emoji: bool
|
||||
logo_emoji: str
|
||||
logo_emoji_font: str
|
||||
favicon_use_custom: bool
|
||||
favicon_url: Optional[str]
|
||||
logo_favicon_url: Optional[str]
|
||||
@@ -395,15 +392,6 @@ 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",
|
||||
description=(
|
||||
"Emoji font for logo fallback: system, noto-color, noto-color-animated, "
|
||||
"noto-emoji, twemoji, openmoji, apple, segoe, noto-local"
|
||||
),
|
||||
)
|
||||
WEBAPP_FAVICON_USE_CUSTOM: bool = Field(default=False)
|
||||
WEBAPP_FAVICON_URL: Optional[str] = Field(default=None)
|
||||
WEBAPP_LOGO_FAVICON_URL: Optional[str] = Field(default=None)
|
||||
@@ -566,9 +554,6 @@ 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,
|
||||
favicon_use_custom=self.WEBAPP_FAVICON_USE_CUSTOM,
|
||||
favicon_url=self.WEBAPP_FAVICON_URL,
|
||||
logo_favicon_url=self.WEBAPP_LOGO_FAVICON_URL,
|
||||
@@ -810,21 +795,6 @@ class Settings(BaseSettings):
|
||||
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"
|
||||
|
||||
@field_validator("WEBAPP_FAVICON_USE_CUSTOM", mode="before")
|
||||
@classmethod
|
||||
def ignore_deprecated_webapp_favicon_use_custom_env(cls, _value):
|
||||
|
||||
Reference in New Issue
Block a user