Le navigateur servait un CSS périmé après mise à jour (aucun invalidateur sur /static). Les liens CSS/JS portent désormais ?v=<mtime des fichiers statiques> : toute modification du design est visible immédiatement chez tous les clients, sans hard-refresh ni bump manuel de version.
68 lines
2.5 KiB
Python
68 lines
2.5 KiB
Python
"""Pages HTML (Jinja2 + htmx). Toutes protégées sauf /login."""
|
|
|
|
from fastapi import APIRouter, Depends, Request
|
|
from fastapi.responses import HTMLResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
from app.config import BASE_DIR
|
|
from app.routers.auth import current_user
|
|
|
|
router = APIRouter(tags=["pages"], include_in_schema=False)
|
|
protected = APIRouter(tags=["pages"], include_in_schema=False, dependencies=[Depends(current_user)])
|
|
|
|
templates = Jinja2Templates(directory=BASE_DIR / "app" / "templates")
|
|
|
|
# Cache-busting des assets : version dérivée de la date des fichiers statiques —
|
|
# tout changement de CSS/JS invalide le cache navigateur sans intervention.
|
|
_static_root = BASE_DIR / "app" / "static"
|
|
templates.env.globals["asset_v"] = str(
|
|
max(int(p.stat().st_mtime) for p in _static_root.rglob("*") if p.is_file())
|
|
)
|
|
|
|
|
|
@router.get("/login", response_class=HTMLResponse)
|
|
async def login_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "login.html")
|
|
|
|
|
|
@protected.get("/", response_class=HTMLResponse)
|
|
async def index(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "index.html")
|
|
|
|
|
|
@protected.get("/discover", response_class=HTMLResponse)
|
|
async def discover_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "discover.html")
|
|
|
|
|
|
@protected.get("/title/{source}/{source_id:path}", response_class=HTMLResponse)
|
|
async def title_page(request: Request, source: str, source_id: str) -> HTMLResponse:
|
|
return templates.TemplateResponse(
|
|
request, "title.html", {"source": source, "source_id": source_id}
|
|
)
|
|
|
|
|
|
@protected.get("/downloads", response_class=HTMLResponse)
|
|
async def downloads_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "downloads.html")
|
|
|
|
|
|
@protected.get("/library", response_class=HTMLResponse)
|
|
async def library_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "library.html")
|
|
|
|
|
|
@protected.get("/watch/{download_id}", response_class=HTMLResponse)
|
|
async def watch_page(request: Request, download_id: int) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "watch.html", {"download_id": download_id})
|
|
|
|
|
|
@protected.get("/favorites", response_class=HTMLResponse)
|
|
async def favorites_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "favorites.html")
|
|
|
|
|
|
@protected.get("/admin", response_class=HTMLResponse)
|
|
async def admin_page(request: Request) -> HTMLResponse:
|
|
return templates.TemplateResponse(request, "admin.html")
|