"""Web app manifest and service worker (installable app, Android share target).""" from django.contrib.auth.decorators import login_not_required from django.http import HttpResponse, JsonResponse from django.templatetags.static import static from django.urls import reverse from django.views.decorators.cache import cache_control from django.views.decorators.http import require_GET # No caching of pages or API responses: private recipes must never sit in a shared cache, # and the app is online-only. The worker exists so browsers offer installation. SERVICE_WORKER = """self.addEventListener("install", () => self.skipWaiting()); self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim())); """ @login_not_required @require_GET @cache_control(max_age=3600) def manifest(request): data = { "name": "Kochbuch", "short_name": "Kochbuch", "lang": "de", "start_url": reverse("recipes:list"), "scope": "/", "display": "standalone", "background_color": "#faf7f2", "theme_color": "#b4532a", "icons": [ {"src": static("icons/icon-192.png"), "sizes": "192x192", "type": "image/png"}, {"src": static("icons/icon-512.png"), "sizes": "512x512", "type": "image/png"}, {"src": static("icons/icon-maskable-512.png"), "sizes": "512x512", "type": "image/png", "purpose": "maskable"}, ], "share_target": { "action": reverse("recipes:share"), "method": "GET", "params": {"title": "title", "text": "text", "url": "url"}, }, } return JsonResponse(data, content_type="application/manifest+json", json_dumps_params={"ensure_ascii": False}) @login_not_required @require_GET @cache_control(max_age=0, no_cache=True) def service_worker(request): return HttpResponse(SERVICE_WORKER, content_type="application/javascript")