feat: custom themes logo size tuning
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
# Remnawave Minishop
|
# Remnawave Minishop
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Remnawave Minishop - Telegram-бот и Web App (Mini App) для продажи и управления подписками Remnawave. Бот обрабатывает регистрацию, оплату, продление, пробный период, промокоды, рефералов и поддержку в чате. Web App показывает ссылку подключения, срок действия, трафик, оплату, устройства и вход по Telegram Mini Apps `initData`, Telegram OAuth / OpenID Connect и одноразовому email-коду.
|
Remnawave Minishop - Telegram-бот и Web App (Mini App) для продажи и управления подписками Remnawave. Бот обрабатывает регистрацию, оплату, продление, пробный период, промокоды, рефералов и поддержку в чате. Web App показывает ссылку подключения, срок действия, трафик, оплату, устройства и вход по Telegram Mini Apps `initData`, Telegram OAuth / OpenID Connect и одноразовому email-коду.
|
||||||
|
|
||||||
Проект является переработанным форком [kavore/remnawave-tg-shop](https://github.com/kavore/remnawave-tg-shop). Для переноса данных из прежнего стека используйте [инструкцию по миграции](docs/migration-to-minishop.md).
|
Проект является переработанным форком [kavore/remnawave-tg-shop](https://github.com/kavore/remnawave-tg-shop). Для переноса данных из прежнего стека используйте [инструкцию по миграции](docs/migration-to-minishop.md).
|
||||||
|
|||||||
@@ -134,6 +134,12 @@
|
|||||||
return `#${hex}`;
|
return `#${hex}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function homeLogoScale(theme) {
|
||||||
|
const scale = Number(theme.tokens?.home_logo_scale || 100);
|
||||||
|
if (!Number.isFinite(scale)) return 100;
|
||||||
|
return Math.min(300, Math.max(50, Math.round(scale)));
|
||||||
|
}
|
||||||
|
|
||||||
function openThemeAccentPicker(theme) {
|
function openThemeAccentPicker(theme) {
|
||||||
themesStore.setThemeAccent(theme.key, pickerHex(theme.tokens?.accent || "#00fe7a"));
|
themesStore.setThemeAccent(theme.key, pickerHex(theme.tokens?.accent || "#00fe7a"));
|
||||||
}
|
}
|
||||||
@@ -216,6 +222,10 @@
|
|||||||
themesStore.setThemeAccent(theme.key, value);
|
themesStore.setThemeAccent(theme.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setThemeHomeLogoScale(theme, value) {
|
||||||
|
themesStore.setThemeHomeLogoScale(theme.key, value);
|
||||||
|
}
|
||||||
|
|
||||||
function selectTheme(theme, event = null) {
|
function selectTheme(theme, event = null) {
|
||||||
if (event?.target?.closest?.("button,input,label")) return;
|
if (event?.target?.closest?.("button,input,label")) return;
|
||||||
if (!themesSaving) themesStore.setCurrentTheme(theme.key);
|
if (!themesSaving) themesStore.setCurrentTheme(theme.key);
|
||||||
@@ -472,6 +482,37 @@
|
|||||||
/>
|
/>
|
||||||
<span>{at("themes_use_in_admin", {}, "Использовать в админке")}</span>
|
<span>{at("themes_use_in_admin", {}, "Использовать в админке")}</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="admin-theme-card-option appearance-logo-scale-row">
|
||||||
|
<span
|
||||||
|
>{at(
|
||||||
|
"appearance_theme_home_logo_scale",
|
||||||
|
{},
|
||||||
|
"Логотип на главной и входе"
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="appearance-logo-scale-range"
|
||||||
|
type="range"
|
||||||
|
min="50"
|
||||||
|
max="300"
|
||||||
|
step="5"
|
||||||
|
value={homeLogoScale(theme)}
|
||||||
|
oninput={(event) => setThemeHomeLogoScale(theme, event.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
<span class="appearance-logo-scale-value">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="number"
|
||||||
|
min="50"
|
||||||
|
max="300"
|
||||||
|
step="5"
|
||||||
|
value={homeLogoScale(theme)}
|
||||||
|
oninput={(event) =>
|
||||||
|
setThemeHomeLogoScale(theme, event.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
%
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
<div class="appearance-theme-actions">
|
<div class="appearance-theme-actions">
|
||||||
<AdminButton
|
<AdminButton
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -703,6 +744,31 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.appearance-logo-scale-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto minmax(96px, 1fr) auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.appearance-logo-scale-range {
|
||||||
|
width: 100%;
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.appearance-logo-scale-value {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
color: var(--admin-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.appearance-logo-scale-value .input {
|
||||||
|
width: 70px;
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.admin-color.is-empty {
|
.admin-color.is-empty {
|
||||||
opacity: 0.42;
|
opacity: 0.42;
|
||||||
filter: grayscale(1);
|
filter: grayscale(1);
|
||||||
|
|||||||
@@ -183,12 +183,38 @@ export function createThemesStore({ api, onThemesSaved, flash, at }) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setThemeHomeLogoScale(key, scale) {
|
||||||
|
if (String(scale ?? "").trim() === "") scale = 100;
|
||||||
|
const numeric = Number(scale);
|
||||||
|
const nextScale = Number.isFinite(numeric)
|
||||||
|
? Math.min(300, Math.max(50, Math.round(numeric)))
|
||||||
|
: 100;
|
||||||
|
state.update((s) => ({
|
||||||
|
...s,
|
||||||
|
themesCatalog: {
|
||||||
|
...s.themesCatalog,
|
||||||
|
themes: (s.themesCatalog.themes || []).map((theme) =>
|
||||||
|
theme.key === key
|
||||||
|
? {
|
||||||
|
...theme,
|
||||||
|
tokens: {
|
||||||
|
...(theme.tokens || {}),
|
||||||
|
home_logo_scale: nextScale === 100 ? null : nextScale,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: theme
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe: state.subscribe,
|
subscribe: state.subscribe,
|
||||||
loadThemes,
|
loadThemes,
|
||||||
saveThemes,
|
saveThemes,
|
||||||
setCurrentTheme,
|
setCurrentTheme,
|
||||||
setThemeAccent,
|
setThemeAccent,
|
||||||
|
setThemeHomeLogoScale,
|
||||||
togglePrimaryAccent,
|
togglePrimaryAccent,
|
||||||
toggleAdminUse,
|
toggleAdminUse,
|
||||||
uploadLogoFile,
|
uploadLogoFile,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const TOKEN_TO_CSS_VAR = {
|
|||||||
font_sans: "--font-sans",
|
font_sans: "--font-sans",
|
||||||
font_logo: "--font-logo",
|
font_logo: "--font-logo",
|
||||||
font_mono: "--font-mono",
|
font_mono: "--font-mono",
|
||||||
|
home_logo_scale: "--home-logo-scale",
|
||||||
admin_bg: "--admin-bg",
|
admin_bg: "--admin-bg",
|
||||||
admin_surface: "--admin-surface",
|
admin_surface: "--admin-surface",
|
||||||
admin_surface_2: "--admin-surface-2",
|
admin_surface_2: "--admin-surface-2",
|
||||||
@@ -38,6 +39,12 @@ export function themeTokensToInlineStyle(tokens, primaryFallback = "#00fe7a", op
|
|||||||
if (key === "accent") continue;
|
if (key === "accent") continue;
|
||||||
const value = t[key];
|
const value = t[key];
|
||||||
if (value === undefined || value === null || value === "") continue;
|
if (value === undefined || value === null || value === "") continue;
|
||||||
|
if (key === "home_logo_scale") {
|
||||||
|
const scale = Number(value);
|
||||||
|
if (!Number.isFinite(scale) || scale <= 0) continue;
|
||||||
|
parts.push(`${cssVar}:${scale / 100}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
parts.push(`${cssVar}:${String(value)}`);
|
parts.push(`${cssVar}:${String(value)}`);
|
||||||
}
|
}
|
||||||
return parts.join(";");
|
return parts.join(";");
|
||||||
|
|||||||
@@ -30,12 +30,18 @@ a {
|
|||||||
display: grid;
|
display: grid;
|
||||||
min-height: 100dvh;
|
min-height: 100dvh;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
align-content: center;
|
align-content: safe center;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loader .brand-mark.brand-mark-lg {
|
||||||
|
width: calc(4.125rem * var(--home-logo-scale, 1));
|
||||||
|
height: calc(4.125rem * var(--home-logo-scale, 1));
|
||||||
|
font-size: calc(2.875rem * var(--home-logo-scale, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.app-header,
|
.app-header,
|
||||||
.preview-header,
|
.preview-header,
|
||||||
.screen-head {
|
.screen-head {
|
||||||
@@ -1530,17 +1536,29 @@ a {
|
|||||||
.home-layout {
|
.home-layout {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-height: calc(100dvh - 34px);
|
min-height: calc(100dvh - 34px);
|
||||||
grid-template-rows: minmax(0, 1fr) auto;
|
grid-template-rows: minmax(min-content, 1fr) auto;
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
padding-bottom: 86px;
|
padding-bottom: 86px;
|
||||||
animation: section-enter 0.24s ease-out both;
|
animation: section-enter 0.24s ease-out both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-brand {
|
.home-brand {
|
||||||
align-self: center;
|
align-self: safe center;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.home-brand .brand-mark.brand-mark-xl {
|
||||||
|
width: calc(6rem * var(--home-logo-scale, 1));
|
||||||
|
height: calc(6rem * var(--home-logo-scale, 1));
|
||||||
|
font-size: calc(4.375rem * var(--home-logo-scale, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-brand-auth .brand-mark.brand-mark-xl {
|
||||||
|
width: calc(116px * var(--home-logo-scale, 1));
|
||||||
|
height: calc(116px * var(--home-logo-scale, 1));
|
||||||
|
font-size: calc(84px * var(--home-logo-scale, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.home-bottom {
|
.home-bottom {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
@@ -1549,7 +1567,7 @@ a {
|
|||||||
|
|
||||||
.auth-screen {
|
.auth-screen {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: safe center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-card-wrap {
|
.auth-card-wrap {
|
||||||
@@ -1568,12 +1586,6 @@ a {
|
|||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-brand-auth .brand-mark.brand-mark-xl {
|
|
||||||
width: 116px;
|
|
||||||
height: 116px;
|
|
||||||
font-size: 84px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-brand h1 {
|
.login-brand h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
@@ -2129,9 +2141,9 @@ a {
|
|||||||
.home-brand .brand-mark,
|
.home-brand .brand-mark,
|
||||||
.home-brand .brand-mark-lg,
|
.home-brand .brand-mark-lg,
|
||||||
.home-brand .brand-mark-xl {
|
.home-brand .brand-mark-xl {
|
||||||
width: clamp(180px, 18vw, 260px);
|
width: calc(clamp(180px, 18vw, 260px) * var(--home-logo-scale, 1));
|
||||||
height: clamp(180px, 18vw, 260px);
|
height: calc(clamp(180px, 18vw, 260px) * var(--home-logo-scale, 1));
|
||||||
font-size: clamp(124px, 13vw, 184px);
|
font-size: calc(clamp(124px, 13vw, 184px) * var(--home-logo-scale, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.home-bottom {
|
.home-bottom {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<link id="app-favicon" rel="icon" href="data:," sizes="any">
|
<link id="app-favicon" rel="icon" href="data:," sizes="any">
|
||||||
<title>/minishop</title>
|
<title>/minishop</title>
|
||||||
<link rel="stylesheet" href="/subscription_webapp.css">
|
<link rel="stylesheet" href="/subscription_webapp.css">
|
||||||
<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">
|
<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import url("https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap&subset=cyrillic");
|
||||||
|
|
||||||
.theme-key-windows95 {
|
.theme-key-windows95 {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
@@ -15,7 +17,7 @@
|
|||||||
--blue: #000080;
|
--blue: #000080;
|
||||||
--radius: 0px;
|
--radius: 0px;
|
||||||
--font-sans: "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
|
--font-sans: "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
|
||||||
--font-logo: "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
|
--font-logo: "Press Start 2P", "Pixel Cyr", "MS Sans Serif", Tahoma, "Segoe UI", sans-serif;
|
||||||
--font-mono: Consolas, "Courier New", monospace;
|
--font-mono: Consolas, "Courier New", monospace;
|
||||||
--accent-contrast: #ffffff;
|
--accent-contrast: #ffffff;
|
||||||
--surface-sheen: transparent;
|
--surface-sheen: transparent;
|
||||||
@@ -89,6 +91,8 @@
|
|||||||
.theme-key-windows95 svg.lucide-bitcoin,
|
.theme-key-windows95 svg.lucide-bitcoin,
|
||||||
.theme-key-windows95 svg.lucide-check,
|
.theme-key-windows95 svg.lucide-check,
|
||||||
.theme-key-windows95 svg.lucide-check-circle-2,
|
.theme-key-windows95 svg.lucide-check-circle-2,
|
||||||
|
.theme-key-windows95 svg.lucide-circle-check,
|
||||||
|
.theme-key-windows95 svg.lucide-circle-check-big,
|
||||||
.theme-key-windows95 svg.lucide-chevrons-up-down,
|
.theme-key-windows95 svg.lucide-chevrons-up-down,
|
||||||
.theme-key-windows95 svg.lucide-circle-x,
|
.theme-key-windows95 svg.lucide-circle-x,
|
||||||
.theme-key-windows95 svg.lucide-coins,
|
.theme-key-windows95 svg.lucide-coins,
|
||||||
@@ -142,6 +146,7 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
|
filter: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-key-windows95 svg.lucide-arrow-left {
|
.theme-key-windows95 svg.lucide-arrow-left {
|
||||||
@@ -547,6 +552,10 @@
|
|||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-key-windows95 .traffic-top strong {
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
.theme-key-windows95 .btn-primary,
|
.theme-key-windows95 .btn-primary,
|
||||||
.theme-key-windows95 .bottom-nav button.active {
|
.theme-key-windows95 .bottom-nav button.active {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
|||||||
@@ -857,12 +857,12 @@ async def index_route(request: web.Request) -> web.Response:
|
|||||||
brand_asset_url = _webapp_animated_emoji_asset_path(settings.WEBAPP_LOGO_EMOJI)
|
brand_asset_url = _webapp_animated_emoji_asset_path(settings.WEBAPP_LOGO_EMOJI)
|
||||||
if brand_asset_url:
|
if brand_asset_url:
|
||||||
html = html.replace(
|
html = html.replace(
|
||||||
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
|
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">',
|
||||||
f'<link rel="preload" href="{brand_asset_url}" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
|
f'<link rel="preload" href="{brand_asset_url}" as="image" fetchpriority="high">',
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
html = html.replace(
|
html = html.replace(
|
||||||
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high" crossorigin="anonymous">', # noqa: E501
|
'<link rel="preload" id="logo-preload" href="" as="image" fetchpriority="high">',
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
return web.Response(text=html, content_type="text/html", charset="utf-8")
|
return web.Response(text=html, content_type="text/html", charset="utf-8")
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class ThemeTokens(BaseModel):
|
|||||||
font_sans: Optional[str] = None
|
font_sans: Optional[str] = None
|
||||||
font_logo: Optional[str] = None
|
font_logo: Optional[str] = None
|
||||||
font_mono: Optional[str] = None
|
font_mono: Optional[str] = None
|
||||||
|
home_logo_scale: Optional[int] = None
|
||||||
admin_bg: Optional[str] = None
|
admin_bg: Optional[str] = None
|
||||||
admin_surface: Optional[str] = None
|
admin_surface: Optional[str] = None
|
||||||
admin_surface_2: Optional[str] = None
|
admin_surface_2: Optional[str] = None
|
||||||
@@ -64,6 +65,16 @@ class ThemeTokens(BaseModel):
|
|||||||
hex_value = "".join(char * 2 for char in hex_value)
|
hex_value = "".join(char * 2 for char in hex_value)
|
||||||
return f"#{hex_value}"
|
return f"#{hex_value}"
|
||||||
|
|
||||||
|
@field_validator("home_logo_scale")
|
||||||
|
@classmethod
|
||||||
|
def _normalize_home_logo_scale(cls, value: Optional[int]) -> Optional[int]:
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
scale = int(value)
|
||||||
|
if scale < 50 or scale > 300:
|
||||||
|
raise ValueError("home_logo_scale must be between 50 and 300 percent")
|
||||||
|
return scale
|
||||||
|
|
||||||
|
|
||||||
class WebappTheme(BaseModel):
|
class WebappTheme(BaseModel):
|
||||||
"""Single theme descriptor loaded from WEBAPP_THEMES_DIR/<key>/theme.json."""
|
"""Single theme descriptor loaded from WEBAPP_THEMES_DIR/<key>/theme.json."""
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class WebappThemesConfigTests(unittest.TestCase):
|
|||||||
self.assertEqual(win95.tokens.style_preset, "win95")
|
self.assertEqual(win95.tokens.style_preset, "win95")
|
||||||
self.assertFalse(win95.use_primary_accent)
|
self.assertFalse(win95.use_primary_accent)
|
||||||
self.assertTrue(win95.use_in_admin)
|
self.assertTrue(win95.use_in_admin)
|
||||||
self.assertEqual(win95.assets_version, 1)
|
self.assertEqual(win95.assets_version, 3)
|
||||||
ascii_theme = cfg.theme_by_key("ascii")
|
ascii_theme = cfg.theme_by_key("ascii")
|
||||||
self.assertIsNotNone(ascii_theme)
|
self.assertIsNotNone(ascii_theme)
|
||||||
self.assertEqual(ascii_theme.css_file, "style.css")
|
self.assertEqual(ascii_theme.css_file, "style.css")
|
||||||
@@ -294,6 +294,25 @@ class WebappThemesConfigTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(cfg.theme_by_key("custom").tokens.accent, "#00ff88")
|
self.assertEqual(cfg.theme_by_key("custom").tokens.accent, "#00ff88")
|
||||||
|
|
||||||
|
def test_theme_home_logo_scale_is_public_token(self):
|
||||||
|
cfg = WebappThemesConfig(
|
||||||
|
default_theme="custom",
|
||||||
|
themes=[
|
||||||
|
{
|
||||||
|
"key": "custom",
|
||||||
|
"enabled": True,
|
||||||
|
"default": True,
|
||||||
|
"tokens": {"color_scheme": "dark", "home_logo_scale": 135},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
payload = public_themes_catalog_payload(cfg, "#abc123")
|
||||||
|
custom = payload["themes"][0]
|
||||||
|
|
||||||
|
self.assertEqual(cfg.theme_by_key("custom").tokens.home_logo_scale, 135)
|
||||||
|
self.assertEqual(custom["tokens"]["home_logo_scale"], 135)
|
||||||
|
|
||||||
def test_theme_accent_rejects_non_hex_values(self):
|
def test_theme_accent_rejects_non_hex_values(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
WebappThemesConfig(
|
WebappThemesConfig(
|
||||||
@@ -361,11 +380,14 @@ class WebappThemesConfigTests(unittest.TestCase):
|
|||||||
descriptor["assets_version"],
|
descriptor["assets_version"],
|
||||||
cfg.theme_by_key("windows95").assets_version,
|
cfg.theme_by_key("windows95").assets_version,
|
||||||
)
|
)
|
||||||
self.assertEqual(descriptor["assets_version"], 1)
|
self.assertEqual(descriptor["assets_version"], 3)
|
||||||
self.assertIn("lucide-house", css)
|
self.assertIn("lucide-house", css)
|
||||||
self.assertIn("lucide-earth", css)
|
self.assertIn("lucide-earth", css)
|
||||||
self.assertIn("lucide-circle-check", css)
|
self.assertIn("lucide-circle-check", css)
|
||||||
self.assertIn("lucide-circle-check-big", css)
|
self.assertIn("lucide-circle-check-big", css)
|
||||||
|
self.assertIn("filter: none !important", css)
|
||||||
|
self.assertIn("Press Start 2P", css)
|
||||||
|
self.assertIn(".theme-key-windows95 .traffic-top strong", css)
|
||||||
self.assertTrue((stale_theme_dir / "icons" / "dashboard.png").exists())
|
self.assertTrue((stale_theme_dir / "icons" / "dashboard.png").exists())
|
||||||
|
|
||||||
def test_resolved_refreshes_stale_builtin_light_assets(self):
|
def test_resolved_refreshes_stale_builtin_light_assets(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user