diff --git a/web/core/context_processors.py b/web/core/context_processors.py index 0884840..77a7ab9 100644 --- a/web/core/context_processors.py +++ b/web/core/context_processors.py @@ -1,8 +1,13 @@ +# core/context_processors.py from pathlib import Path -from .models_ann import Announcement, AnnouncementDismissal -from django.contrib.staticfiles import finders import os +from django.contrib.staticfiles import finders +from django.contrib.staticfiles.storage import staticfiles_storage + +from .models_ann import Announcement, AnnouncementDismissal + + def app_version(request): version_file = Path(__file__).resolve().parent.parent / "version.txt" try: @@ -12,19 +17,40 @@ def app_version(request): version = "v0.0.0" return {"APP_VERSION": version} + def available_themes(request): - """Returns ['midnight','dawn','forest','sandstone', ...] by scanning /static/themes/*.css""" - names = [] - # Find the absolute path for the 'themes' directory via staticfiles finders - # We look for any 'themes' folder that exists and aggregate CSS files. - for finder in finders.get_finders(): - for path, storage in finder.list(['themes']): - if path.startswith('themes/') and path.endswith('.css'): - base = os.path.basename(path)[:-4] # strip .css - names.append(base) - # stable order - names = sorted(set(names)) - return {'available_themes': names} + """ + Return a list of theme names by scanning /static/themes/*.css. + Works in development (finders) and production (staticfiles_storage). + Never returns an empty list. + """ + names = set() + + # A) Dev/app static: scan all registered static finders + try: + for finder in finders.get_finders(): + for path, storage in finder.list(['themes']): + # e.g. "themes/midnight.css" + if path.startswith('themes/') and path.endswith('.css'): + names.add(os.path.basename(path)[:-4]) # strip ".css" + except Exception: + pass + + # B) Prod/collected: scan STATIC_ROOT via staticfiles_storage + try: + dirs, files = staticfiles_storage.listdir('themes') + for f in files: + if f.endswith('.css'): + names.add(f[:-4]) + except Exception: + pass + + # C) Safety net: default themes so the selector is never empty + if not names: + names.update({'midnight', 'dawn', 'forest', 'sandstone'}) + + return {'available_themes': sorted(names)} + def pending_announcement(request): """