new themes
This commit is contained in:
@@ -40,18 +40,72 @@ def google_fonts_css_url() -> str:
|
|||||||
return f"https://fonts.googleapis.com/css2?{families}&display=swap"
|
return f"https://fonts.googleapis.com/css2?{families}&display=swap"
|
||||||
|
|
||||||
|
|
||||||
BOOTSTRAP_THEMES = (
|
DEVEXPRESS_BOOTSTRAP_THEMES = {
|
||||||
"default",
|
"blazing-berry": "Blazing Berry",
|
||||||
"flatly",
|
"office-white": "Office White",
|
||||||
"litera",
|
"purple": "Purple",
|
||||||
"lumen",
|
}
|
||||||
"minty",
|
|
||||||
"sketchy",
|
PYTORRENT_APP_THEMES = {
|
||||||
"solar",
|
"adaptive": "pyTorrent Adaptive",
|
||||||
"spacelab",
|
"ocean": "pyTorrent Ocean",
|
||||||
"united",
|
"graphite": "pyTorrent Graphite",
|
||||||
"zephyr",
|
"forest": "pyTorrent Forest",
|
||||||
)
|
"amber": "pyTorrent Amber",
|
||||||
|
"nord": "pyTorrent Nord",
|
||||||
|
"crimson": "pyTorrent Crimson",
|
||||||
|
"sky": "pyTorrent Sky",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOTSTRAP_THEME_DEFINITIONS = {
|
||||||
|
"default": {
|
||||||
|
"label": "Default Bootstrap",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/css/bootstrap.min.css",
|
||||||
|
"cdn": f"https://cdn.jsdelivr.net/npm/bootstrap@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css",
|
||||||
|
},
|
||||||
|
# Bootswatch themes.
|
||||||
|
"flatly": {"label": "Bootswatch: Flatly", "provider": "bootswatch"},
|
||||||
|
"litera": {"label": "Bootswatch: Litera", "provider": "bootswatch"},
|
||||||
|
"lumen": {"label": "Bootswatch: Lumen", "provider": "bootswatch"},
|
||||||
|
"minty": {"label": "Bootswatch: Minty", "provider": "bootswatch"},
|
||||||
|
"sketchy": {"label": "Bootswatch: Sketchy", "provider": "bootswatch"},
|
||||||
|
"spacelab": {"label": "Bootswatch: Spacelab", "provider": "bootswatch"},
|
||||||
|
"united": {"label": "Bootswatch: United", "provider": "bootswatch"},
|
||||||
|
"zephyr": {"label": "Bootswatch: Zephyr", "provider": "bootswatch"},
|
||||||
|
# Complete DevExpress Bootstrap v5 dist.v5 set.
|
||||||
|
**{
|
||||||
|
f"dx-{theme}": {
|
||||||
|
"label": f"DevExpress: {label}",
|
||||||
|
"provider": "devexpress",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/devexpress-bootstrap-themes/dist.v5/{theme}/bootstrap.min.css",
|
||||||
|
"cdn": f"https://cdn.jsdelivr.net/gh/DevExpress/bootstrap-themes@master/dist.v5/{theme}/bootstrap.min.css",
|
||||||
|
}
|
||||||
|
for theme, label in DEVEXPRESS_BOOTSTRAP_THEMES.items()
|
||||||
|
},
|
||||||
|
# App-specific Bootstrap variable overrides. These sit on top of default Bootstrap.
|
||||||
|
**{
|
||||||
|
f"pytorrent-{theme}": {
|
||||||
|
"label": f"Custom: {label}",
|
||||||
|
"provider": "pytorrent",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/pytorrent-themes/{theme}/bootstrap.min.css",
|
||||||
|
"cdn": f"/static/{LIBS_STATIC_DIR}/pytorrent-themes/{theme}/bootstrap.min.css",
|
||||||
|
}
|
||||||
|
for theme, label in PYTORRENT_APP_THEMES.items()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _theme_definition(theme: str | None) -> dict[str, str]:
|
||||||
|
theme = theme if theme in BOOTSTRAP_THEME_DEFINITIONS else "default"
|
||||||
|
item = dict(BOOTSTRAP_THEME_DEFINITIONS[theme])
|
||||||
|
if item.get("provider") == "bootswatch":
|
||||||
|
item["local"] = f"{LIBS_STATIC_DIR}/bootswatch/{BOOTSWATCH_VERSION}/{theme}/bootstrap.min.css"
|
||||||
|
item["cdn"] = f"https://cdn.jsdelivr.net/npm/bootswatch@{BOOTSWATCH_VERSION}/dist/{theme}/bootstrap.min.css"
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
BOOTSTRAP_THEMES = tuple(BOOTSTRAP_THEME_DEFINITIONS.keys())
|
||||||
|
BOOTSTRAP_THEME_LABELS = {key: value["label"] for key, value in BOOTSTRAP_THEME_DEFINITIONS.items()}
|
||||||
|
|
||||||
STATIC_ASSETS = {
|
STATIC_ASSETS = {
|
||||||
"bootstrap_js": {
|
"bootstrap_js": {
|
||||||
@@ -86,16 +140,8 @@ STATIC_ASSETS = {
|
|||||||
|
|
||||||
|
|
||||||
def bootstrap_css_asset(theme: str | None = None) -> dict[str, str]:
|
def bootstrap_css_asset(theme: str | None = None) -> dict[str, str]:
|
||||||
theme = theme if theme in BOOTSTRAP_THEMES else "default"
|
item = _theme_definition(theme)
|
||||||
if theme == "default":
|
return {"local": item["local"], "cdn": item["cdn"]}
|
||||||
return {
|
|
||||||
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/css/bootstrap.min.css",
|
|
||||||
"cdn": f"https://cdn.jsdelivr.net/npm/bootstrap@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css",
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
"local": f"{LIBS_STATIC_DIR}/bootswatch/{BOOTSWATCH_VERSION}/{theme}/bootstrap.min.css",
|
|
||||||
"cdn": f"https://cdn.jsdelivr.net/npm/bootswatch@{BOOTSWATCH_VERSION}/dist/{theme}/bootstrap.min.css",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def asset_path(key: str) -> str:
|
def asset_path(key: str) -> str:
|
||||||
|
|||||||
@@ -4,19 +4,9 @@ import json
|
|||||||
|
|
||||||
from ..db import connect, utcnow, default_user_id
|
from ..db import connect, utcnow, default_user_id
|
||||||
from . import auth
|
from . import auth
|
||||||
|
from .frontend_assets import BOOTSTRAP_THEME_LABELS
|
||||||
|
|
||||||
BOOTSTRAP_THEMES = {
|
BOOTSTRAP_THEMES = BOOTSTRAP_THEME_LABELS
|
||||||
"default": "Default Bootstrap",
|
|
||||||
"flatly": "Flatly",
|
|
||||||
"litera": "Litera",
|
|
||||||
"lumen": "Lumen",
|
|
||||||
"minty": "Minty",
|
|
||||||
"sketchy": "Sketchy",
|
|
||||||
"solar": "Solar",
|
|
||||||
"spacelab": "Spacelab",
|
|
||||||
"united": "United",
|
|
||||||
"zephyr": "Zephyr",
|
|
||||||
}
|
|
||||||
|
|
||||||
FONT_FAMILIES = {
|
FONT_FAMILIES = {
|
||||||
"default": "Theme default",
|
"default": "Theme default",
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
--mobile-filterbar-height: 132px;
|
--mobile-filterbar-height: 132px;
|
||||||
--sidebar: calc(270px * var(--ui-scale));
|
--sidebar: calc(270px * var(--ui-scale));
|
||||||
--torrent-progress-complete: #198754;
|
--torrent-progress-complete: #198754;
|
||||||
|
--pytorrent-page-bg: var(--bs-body-bg);
|
||||||
|
--pytorrent-shell-shadow: 0 12px 45px rgba(0, 0, 0, 0.38);
|
||||||
}
|
}
|
||||||
[data-bs-theme="dark"] {
|
[data-bs-theme="dark"] {
|
||||||
--bs-body-bg: #05070a;
|
--bs-body-bg: #05070a;
|
||||||
@@ -20,6 +22,7 @@
|
|||||||
--bs-primary-bg-subtle: #0d2238;
|
--bs-primary-bg-subtle: #0d2238;
|
||||||
--bs-primary-text-emphasis: #9ecbff;
|
--bs-primary-text-emphasis: #9ecbff;
|
||||||
--torrent-progress-complete: #2f9e75;
|
--torrent-progress-complete: #2f9e75;
|
||||||
|
--pytorrent-page-bg: var(--bs-body-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
html[data-app-font="adwaita-mono"] {
|
html[data-app-font="adwaita-mono"] {
|
||||||
@@ -109,7 +112,7 @@ body {
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
min-height: 100dvh;
|
min-height: 100dvh;
|
||||||
padding: calc(8px * var(--ui-scale));
|
padding: calc(8px * var(--ui-scale));
|
||||||
background: #05070a;
|
background: var(--pytorrent-page-bg, var(--bs-body-bg));
|
||||||
font-family: var(--app-font-family);
|
font-family: var(--app-font-family);
|
||||||
}
|
}
|
||||||
.app-shell {
|
.app-shell {
|
||||||
@@ -121,7 +124,7 @@ body {
|
|||||||
border: 1px solid var(--bs-border-color);
|
border: 1px solid var(--bs-border-color);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 12px 45px rgba(0, 0, 0, 0.38);
|
box-shadow: var(--pytorrent-shell-shadow, 0 12px 45px rgba(0, 0, 0, 0.38));
|
||||||
}
|
}
|
||||||
.topbar {
|
.topbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<title>pyTorrent</title>
|
<title>pyTorrent</title>
|
||||||
<link rel="icon" href="{{ static_url('favicon.svg') }}" type="image/svg+xml">
|
<link rel="icon" href="{{ static_url('favicon.svg') }}" type="image/svg+xml">
|
||||||
<link rel="shortcut icon" href="{{ static_url('favicon.svg') }}" type="image/svg+xml">
|
<link rel="shortcut icon" href="{{ static_url('favicon.svg') }}" type="image/svg+xml">
|
||||||
|
<link id="bootstrapBaseStylesheet" href="{{ bootstrap_theme_url('default') }}" rel="stylesheet">
|
||||||
<link id="bootstrapThemeStylesheet" href="{{ bootstrap_theme_url(prefs.bootstrap_theme if prefs else 'default') }}" rel="stylesheet">
|
<link id="bootstrapThemeStylesheet" href="{{ bootstrap_theme_url(prefs.bootstrap_theme if prefs else 'default') }}" rel="stylesheet">
|
||||||
<link href="{{ frontend_asset_url('fontawesome_css') }}" rel="stylesheet">
|
<link href="{{ frontend_asset_url('fontawesome_css') }}" rel="stylesheet">
|
||||||
<link href="{{ frontend_asset_url('font_css') }}" rel="stylesheet">
|
<link href="{{ frontend_asset_url('font_css') }}" rel="stylesheet">
|
||||||
|
|||||||
@@ -41,18 +41,71 @@ def google_fonts_css_url() -> str:
|
|||||||
return f"https://fonts.googleapis.com/css2?{families}&display=swap"
|
return f"https://fonts.googleapis.com/css2?{families}&display=swap"
|
||||||
|
|
||||||
|
|
||||||
BOOTSTRAP_THEMES = (
|
DEVEXPRESS_BOOTSTRAP_THEMES = {
|
||||||
"default",
|
"blazing-berry": "Blazing Berry",
|
||||||
"flatly",
|
"office-white": "Office White",
|
||||||
"litera",
|
"purple": "Purple",
|
||||||
"lumen",
|
}
|
||||||
"minty",
|
|
||||||
"sketchy",
|
PYTORRENT_APP_THEMES = {
|
||||||
"solar",
|
"adaptive": "pyTorrent Adaptive",
|
||||||
"spacelab",
|
"ocean": "pyTorrent Ocean",
|
||||||
"united",
|
"graphite": "pyTorrent Graphite",
|
||||||
"zephyr",
|
"forest": "pyTorrent Forest",
|
||||||
)
|
"amber": "pyTorrent Amber",
|
||||||
|
"nord": "pyTorrent Nord",
|
||||||
|
"crimson": "pyTorrent Crimson",
|
||||||
|
"sky": "pyTorrent Sky",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOTSTRAP_THEME_DEFINITIONS = {
|
||||||
|
"default": {
|
||||||
|
"label": "Default Bootstrap",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/css/bootstrap.min.css",
|
||||||
|
"cdn": f"https://cdn.jsdelivr.net/npm/bootstrap@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css",
|
||||||
|
},
|
||||||
|
# Bootswatch themes.
|
||||||
|
"flatly": {"label": "Bootswatch: Flatly", "provider": "bootswatch"},
|
||||||
|
"litera": {"label": "Bootswatch: Litera", "provider": "bootswatch"},
|
||||||
|
"lumen": {"label": "Bootswatch: Lumen", "provider": "bootswatch"},
|
||||||
|
"minty": {"label": "Bootswatch: Minty", "provider": "bootswatch"},
|
||||||
|
"sketchy": {"label": "Bootswatch: Sketchy", "provider": "bootswatch"},
|
||||||
|
"spacelab": {"label": "Bootswatch: Spacelab", "provider": "bootswatch"},
|
||||||
|
"united": {"label": "Bootswatch: United", "provider": "bootswatch"},
|
||||||
|
"zephyr": {"label": "Bootswatch: Zephyr", "provider": "bootswatch"},
|
||||||
|
# Complete DevExpress Bootstrap v5 dist.v5 set.
|
||||||
|
**{
|
||||||
|
f"dx-{theme}": {
|
||||||
|
"label": f"DevExpress: {label}",
|
||||||
|
"provider": "devexpress",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/devexpress-bootstrap-themes/dist.v5/{theme}/bootstrap.min.css",
|
||||||
|
"cdn": f"https://cdn.jsdelivr.net/gh/DevExpress/bootstrap-themes@master/dist.v5/{theme}/bootstrap.min.css",
|
||||||
|
}
|
||||||
|
for theme, label in DEVEXPRESS_BOOTSTRAP_THEMES.items()
|
||||||
|
},
|
||||||
|
# App-specific Bootstrap variable overrides. These sit on top of default Bootstrap.
|
||||||
|
**{
|
||||||
|
f"pytorrent-{theme}": {
|
||||||
|
"label": f"Custom: {label}",
|
||||||
|
"provider": "pytorrent",
|
||||||
|
"local": f"{LIBS_STATIC_DIR}/pytorrent-themes/{theme}/bootstrap.min.css",
|
||||||
|
"cdn": f"/static/{LIBS_STATIC_DIR}/pytorrent-themes/{theme}/bootstrap.min.css",
|
||||||
|
}
|
||||||
|
for theme, label in PYTORRENT_APP_THEMES.items()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _theme_definition(theme: str | None) -> dict[str, str]:
|
||||||
|
theme = theme if theme in BOOTSTRAP_THEME_DEFINITIONS else "default"
|
||||||
|
item = dict(BOOTSTRAP_THEME_DEFINITIONS[theme])
|
||||||
|
if item.get("provider") == "bootswatch":
|
||||||
|
item["local"] = f"{LIBS_STATIC_DIR}/bootswatch/{BOOTSWATCH_VERSION}/{theme}/bootstrap.min.css"
|
||||||
|
item["cdn"] = f"https://cdn.jsdelivr.net/npm/bootswatch@{BOOTSWATCH_VERSION}/dist/{theme}/bootstrap.min.css"
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
BOOTSTRAP_THEMES = tuple(BOOTSTRAP_THEME_DEFINITIONS.keys())
|
||||||
STATIC_ASSETS = {
|
STATIC_ASSETS = {
|
||||||
"bootstrap_js": {
|
"bootstrap_js": {
|
||||||
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/js/bootstrap.bundle.min.js",
|
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/js/bootstrap.bundle.min.js",
|
||||||
@@ -88,15 +141,8 @@ ANY_URL_RE = re.compile(r"url\((['\"]?)(?!data:)([^)'\"]+)\1\)")
|
|||||||
|
|
||||||
|
|
||||||
def bootstrap_css_asset(theme: str) -> dict[str, str]:
|
def bootstrap_css_asset(theme: str) -> dict[str, str]:
|
||||||
if theme == "default":
|
item = _theme_definition(theme)
|
||||||
return {
|
return {"local": item["local"], "cdn": item["cdn"]}
|
||||||
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/css/bootstrap.min.css",
|
|
||||||
"cdn": f"https://cdn.jsdelivr.net/npm/bootstrap@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css",
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
"local": f"{LIBS_STATIC_DIR}/bootswatch/{BOOTSWATCH_VERSION}/{theme}/bootstrap.min.css",
|
|
||||||
"cdn": f"https://cdn.jsdelivr.net/npm/bootswatch@{BOOTSWATCH_VERSION}/dist/{theme}/bootstrap.min.css",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def download(url: str, dest: Path) -> None:
|
def download(url: str, dest: Path) -> None:
|
||||||
@@ -169,7 +215,11 @@ def main() -> None:
|
|||||||
for item in items:
|
for item in items:
|
||||||
url = item["cdn"]
|
url = item["cdn"]
|
||||||
dest = ROOT / "pytorrent" / "static" / item["local"]
|
dest = ROOT / "pytorrent" / "static" / item["local"]
|
||||||
if item.get("local") == STATIC_ASSETS["font_css"]["local"]:
|
if url.startswith("/static/"):
|
||||||
|
if not dest.is_file() or dest.stat().st_size <= 0:
|
||||||
|
raise RuntimeError(f"Bundled app theme is missing: {dest.relative_to(ROOT)}")
|
||||||
|
print(f"OK {dest.relative_to(ROOT)}")
|
||||||
|
elif item.get("local") == STATIC_ASSETS["font_css"]["local"]:
|
||||||
download_google_fonts_css(url, dest)
|
download_google_fonts_css(url, dest)
|
||||||
elif dest.suffix == ".css":
|
elif dest.suffix == ".css":
|
||||||
download_css_with_assets(url, dest)
|
download_css_with_assets(url, dest)
|
||||||
|
|||||||
Reference in New Issue
Block a user