offline libs
This commit is contained in:
111
pytorrent/services/frontend_assets.py
Normal file
111
pytorrent/services/frontend_assets.py
Normal file
@@ -0,0 +1,111 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from ..config import BASE_DIR, USE_OFFLINE_LIBS
|
||||
|
||||
# Notatka: jeden manifest utrzymuje spójne adresy CDN i ścieżki lokalne dla trybu offline.
|
||||
LIBS_STATIC_DIR = "libs"
|
||||
LIBS_DIR = BASE_DIR / "pytorrent" / "static" / LIBS_STATIC_DIR
|
||||
BOOTSTRAP_VERSION = "5.3.3"
|
||||
BOOTSWATCH_VERSION = "5.3.3"
|
||||
FONTAWESOME_VERSION = "6.5.2"
|
||||
FLAG_ICONS_VERSION = "7.2.3"
|
||||
SWAGGER_UI_VERSION = "5"
|
||||
SOCKET_IO_VERSION = "4.7.5"
|
||||
|
||||
BOOTSTRAP_THEMES = (
|
||||
"default",
|
||||
"flatly",
|
||||
"litera",
|
||||
"lumen",
|
||||
"minty",
|
||||
"sketchy",
|
||||
"solar",
|
||||
"spacelab",
|
||||
"united",
|
||||
"zephyr",
|
||||
)
|
||||
|
||||
STATIC_ASSETS = {
|
||||
"bootstrap_js": {
|
||||
"local": f"{LIBS_STATIC_DIR}/bootstrap/{BOOTSTRAP_VERSION}/js/bootstrap.bundle.min.js",
|
||||
"cdn": f"https://cdn.jsdelivr.net/npm/bootstrap@{BOOTSTRAP_VERSION}/dist/js/bootstrap.bundle.min.js",
|
||||
},
|
||||
"fontawesome_css": {
|
||||
"local": f"{LIBS_STATIC_DIR}/fontawesome/{FONTAWESOME_VERSION}/css/all.min.css",
|
||||
"cdn": f"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/{FONTAWESOME_VERSION}/css/all.min.css",
|
||||
},
|
||||
"flag_icons_css": {
|
||||
"local": f"{LIBS_STATIC_DIR}/flag-icons/{FLAG_ICONS_VERSION}/css/flag-icons.min.css",
|
||||
"cdn": f"https://cdn.jsdelivr.net/gh/lipis/flag-icons@{FLAG_ICONS_VERSION}/css/flag-icons.min.css",
|
||||
},
|
||||
"socket_io_js": {
|
||||
"local": f"{LIBS_STATIC_DIR}/socket.io/{SOCKET_IO_VERSION}/socket.io.min.js",
|
||||
"cdn": f"https://cdn.socket.io/{SOCKET_IO_VERSION}/socket.io.min.js",
|
||||
},
|
||||
"swagger_css": {
|
||||
"local": f"{LIBS_STATIC_DIR}/swagger-ui/{SWAGGER_UI_VERSION}/swagger-ui.css",
|
||||
"cdn": f"https://cdn.jsdelivr.net/npm/swagger-ui-dist@{SWAGGER_UI_VERSION}/swagger-ui.css",
|
||||
},
|
||||
"swagger_js": {
|
||||
"local": f"{LIBS_STATIC_DIR}/swagger-ui/{SWAGGER_UI_VERSION}/swagger-ui-bundle.js",
|
||||
"cdn": f"https://cdn.jsdelivr.net/npm/swagger-ui-dist@{SWAGGER_UI_VERSION}/swagger-ui-bundle.js",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def bootstrap_css_asset(theme: str | None = None) -> dict[str, str]:
|
||||
theme = theme if theme in BOOTSTRAP_THEMES else "default"
|
||||
if theme == "default":
|
||||
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:
|
||||
return STATIC_ASSETS[key]["local" if USE_OFFLINE_LIBS else "cdn"]
|
||||
|
||||
|
||||
def bootstrap_css_path(theme: str | None = None) -> str:
|
||||
return bootstrap_css_asset(theme)["local" if USE_OFFLINE_LIBS else "cdn"]
|
||||
|
||||
|
||||
def required_offline_paths() -> list[Path]:
|
||||
paths = [LIBS_DIR.parent / item["local"] for item in STATIC_ASSETS.values()]
|
||||
paths.extend(LIBS_DIR.parent / bootstrap_css_asset(theme)["local"] for theme in BOOTSTRAP_THEMES)
|
||||
return paths
|
||||
|
||||
|
||||
def missing_offline_paths() -> list[Path]:
|
||||
missing = [path for path in required_offline_paths() if not path.is_file() or path.stat().st_size <= 0]
|
||||
# Notatka: sprawdzane są też zasoby referencjonowane przez CSS, np. fonty ikon i pliki flag.
|
||||
required_dirs = [
|
||||
LIBS_DIR / f"fontawesome/{FONTAWESOME_VERSION}/webfonts",
|
||||
LIBS_DIR / f"flag-icons/{FLAG_ICONS_VERSION}/flags/4x3",
|
||||
LIBS_DIR / f"flag-icons/{FLAG_ICONS_VERSION}/flags/1x1",
|
||||
]
|
||||
for directory in required_dirs:
|
||||
if not directory.is_dir() or not any(directory.iterdir()):
|
||||
missing.append(directory)
|
||||
return missing
|
||||
|
||||
|
||||
def validate_offline_assets() -> None:
|
||||
# Notatka: aplikacja zatrzymuje start, gdy tryb offline jest aktywny, a pliki nie są zainstalowane.
|
||||
if not USE_OFFLINE_LIBS:
|
||||
return
|
||||
missing = missing_offline_paths()
|
||||
if missing:
|
||||
preview = "\n".join(f"- {path.relative_to(BASE_DIR)}" for path in missing[:20])
|
||||
extra = "" if len(missing) <= 20 else f"\n- ... and {len(missing) - 20} more"
|
||||
raise RuntimeError(
|
||||
"PYTORRENT_USE_OFFLINE_LIBS=true, but frontend libraries are missing. "
|
||||
"Run: ./scripts/download_frontend_libs.py or ./install.sh\n"
|
||||
f"Missing files:\n{preview}{extra}"
|
||||
)
|
||||
@@ -28,11 +28,10 @@ FONT_FAMILIES = {
|
||||
}
|
||||
|
||||
def bootstrap_css_url(theme: str | None) -> str:
|
||||
theme = theme if theme in BOOTSTRAP_THEMES else "default"
|
||||
if theme == "default":
|
||||
return "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
return f"https://cdn.jsdelivr.net/npm/bootswatch@5.3.3/dist/{theme}/bootstrap.min.css"
|
||||
# Notatka: zachowana funkcja zwraca aktualny adres motywu, ale źródło wybiera konfiguracja offline.
|
||||
from .frontend_assets import bootstrap_css_path
|
||||
|
||||
return bootstrap_css_path(theme)
|
||||
|
||||
def list_profiles(user_id: int | None = None):
|
||||
user_id = user_id or auth.current_user_id() or default_user_id()
|
||||
|
||||
Reference in New Issue
Block a user