diff --git a/umap/static/favicon.ico b/umap/static/favicon.ico deleted file mode 100644 index 0aa459cc..00000000 Binary files a/umap/static/favicon.ico and /dev/null differ diff --git a/umap/static/umap/favicons/apple-touch-icon.png b/umap/static/umap/favicons/apple-touch-icon.png new file mode 100644 index 00000000..0f2ff064 Binary files /dev/null and b/umap/static/umap/favicons/apple-touch-icon.png differ diff --git a/umap/static/umap/favicons/favicon.ico b/umap/static/umap/favicons/favicon.ico new file mode 100644 index 00000000..39affe5c Binary files /dev/null and b/umap/static/umap/favicons/favicon.ico differ diff --git a/umap/static/umap/favicons/icon-192.png b/umap/static/umap/favicons/icon-192.png new file mode 100644 index 00000000..5a4175dd Binary files /dev/null and b/umap/static/umap/favicons/icon-192.png differ diff --git a/umap/static/umap/favicons/icon-512.png b/umap/static/umap/favicons/icon-512.png new file mode 100644 index 00000000..3103a0c2 Binary files /dev/null and b/umap/static/umap/favicons/icon-512.png differ diff --git a/umap/static/umap/favicons/icon.svg b/umap/static/umap/favicons/icon.svg new file mode 100644 index 00000000..f7fbf130 --- /dev/null +++ b/umap/static/umap/favicons/icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/umap/templates/base.html b/umap/templates/base.html index 4d93f5bd..0a57fe35 100644 --- a/umap/templates/base.html +++ b/umap/templates/base.html @@ -15,6 +15,11 @@ {% endblock extra_head %} + {# See https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs #} + + + + {% block header %} diff --git a/umap/urls.py b/umap/urls.py index 630ea45a..cd32d406 100644 --- a/umap/urls.py +++ b/umap/urls.py @@ -5,9 +5,11 @@ from django.conf.urls.static import static from django.contrib import admin from django.contrib.auth import views as auth_views from django.contrib.auth.decorators import login_required +from django.contrib.staticfiles.storage import staticfiles_storage from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.views.decorators.cache import cache_control, cache_page, never_cache from django.views.decorators.csrf import ensure_csrf_cookie +from django.views.generic.base import RedirectView from . import views from .decorators import ( @@ -183,7 +185,23 @@ urlpatterns += i18n_patterns( re_path(r"^user/(?P.+)/$", views.user_maps, name="user_maps"), re_path(r"", include(i18n_urls)), ) -urlpatterns += (path("stats/", cache_page(60 * 60)(views.stats), name="stats"),) +urlpatterns += ( + path("stats/", cache_page(60 * 60)(views.stats), name="stats"), + path( + "favicon.ico", + cache_control(max_age=60 * 60 * 24, immutable=True, public=True)( + RedirectView.as_view( + url=staticfiles_storage.url("umap/favicons/favicon.ico") + ) + ), + ), + path( + "manifest.webmanifest", + cache_control(max_age=60 * 60 * 24, immutable=True, public=True)( + views.webmanifest + ), + ), +) if settings.DEBUG and settings.MEDIA_ROOT: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/umap/views.py b/umap/views.py index 0d341585..d9f8d647 100644 --- a/umap/views.py +++ b/umap/views.py @@ -15,6 +15,7 @@ from django.contrib.auth import logout as do_logout from django.contrib.auth import get_user_model from django.contrib.gis.measure import D from django.contrib.postgres.search import SearchQuery, SearchVector +from django.contrib.staticfiles.storage import staticfiles_storage from django.core.mail import send_mail from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator from django.core.signing import BadSignature, Signer @@ -34,6 +35,8 @@ from django.utils.encoding import smart_bytes from django.utils.http import http_date from django.utils.translation import gettext as _ from django.utils.translation import to_locale +from django.views.decorators.cache import cache_control +from django.views.decorators.http import require_GET from django.views.generic import DetailView, TemplateView, View from django.views.generic.base import RedirectView from django.views.generic.detail import BaseDetailView @@ -469,9 +472,7 @@ class MapDetailMixin: else: map_statuses = AnonymousMapPermissionsForm.STATUS datalayer_statuses = AnonymousDataLayerPermissionsForm.STATUS - properties["edit_statuses"] = [ - (i, str(label)) for i, label in map_statuses - ] + properties["edit_statuses"] = [(i, str(label)) for i, label in map_statuses] properties["datalayer_edit_statuses"] = [ (i, str(label)) for i, label in datalayer_statuses ] @@ -1016,6 +1017,27 @@ def stats(request): ) +@require_GET +@cache_control(max_age=60 * 60 * 24, immutable=True, public=True) # One day. +def webmanifest(request): + return simple_json_response( + **{ + "icons": [ + { + "src": staticfiles_storage.url("umap/favicons/icon-192.png"), + "type": "image/png", + "sizes": "192x192", + }, + { + "src": staticfiles_storage.url("umap/favicons/icon-512.png"), + "type": "image/png", + "sizes": "512x512", + }, + ] + } + ) + + def logout(request): do_logout(request) if is_ajax(request):