pwa: add possibility to set application icon (#29457)

This commit is contained in:
Frédéric Péters 2019-01-04 20:56:08 +01:00
parent 2d4ca51241
commit 2e58ce9b02
9 changed files with 97 additions and 13 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2019-01-04 19:36
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pwa', '0003_pwanavigationentry'),
]
operations = [
migrations.AddField(
model_name='pwasettings',
name='application_icon',
field=models.FileField(blank=True, help_text='Should be a square of at least 512\xd7512 pixels.', null=True, upload_to=b'pwa', verbose_name='Application Icon'),
),
]

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*
#
# combo - content management system
# Copyright (C) 2015-2018 Entr'ouvert
#
@ -33,6 +35,13 @@ from combo import utils
class PwaSettings(models.Model):
APPLICATION_ICON_SIZES = ['%sx%s' % (x, x) for x in (48, 96, 192, 256, 512)]
application_icon = models.FileField(
verbose_name=_('Application Icon'),
help_text=_(u'Should be a square of at least 512×512 pixels.'),
upload_to='pwa',
blank=True,
null=True)
offline_text = RichTextField(
verbose_name=_('Offline Information Text'),
default=_('You are currently offline.'),

View File

@ -1,4 +1,4 @@
{% load static %}{
{% load static thumbnail %}{
"name": "{% firstof global_title "Compte Citoyen" %}",
"short_name": "{% firstof global_title "Compte Citoyen" %}",
"start_url": "{% firstof pwa_start_url "/" %}",
@ -8,6 +8,17 @@
{% endif %}
{% block icons %}
"icons": [
{% if pwa_settings.application_icon %}
{% for icon_size in pwa_settings.APPLICATION_ICON_SIZES %}
{
"sizes": "{{ icon_size }}",
{% thumbnail pwa_settings.application_icon icon_size crop='center' format='PNG' as im %}
"src": "{{ site_base }}{{ im.url }}",
{% endthumbnail %}
"type": "image/png"
}{% if not forloop.last %},{% endif %}
{% endfor %}
{% else %}
{% for icon_size in icon_sizes %}
{
"sizes": "{{ icon_size }}x{{ icon_size }}",
@ -15,6 +26,7 @@
"type": "image/png"
}{% if not forloop.last %},{% endif %}
{% endfor %}
{% endif %}
],
{% endblock %}
{% block extra %}

View File

@ -1,5 +1,5 @@
{% extends "combo/pwa/manager_base.html" %}
{% load i18n static %}
{% load i18n thumbnail %}
{% block content %}
<div class="manager-mobile-home-layout">
@ -9,7 +9,11 @@
<div class="mobile-app-content">
<div class="splash">
<div class="appicon">
<img src="{% static "" %}{{ css_variant }}/{{ icon_prefix }}{{icon_sizes|last}}px.png" alt="">
{% if pwa_settings.application_icon %}
{% thumbnail pwa_settings.application_icon '512x512' crop='center' format='PNG' as im %}
<img src="{{ im.url }}" alt="">
{% endthumbnail %}
{% endif %}
</div>
<div class="applabel">{% firstof global_title "Compte Citoyen" %}</div>
</div>

View File

@ -1,4 +1,4 @@
{% load i18n static %}<!DOCTYPE html>
{% load i18n thumbnail %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
@ -42,7 +42,12 @@ p.retry a {
</head>
<body>
<div class="info-text">
<img src="{% static "" %}{{ css_variant }}/{{ icon_prefix }}{{icon_sizes|last}}px.png" alt="">
{% if pwa_settings.application_icon %}
{% thumbnail pwa_settings.application_icon '512x512' crop='center' format='PNG' as im %}
<img src="{{ im.url }}" alt="">
{% endthumbnail %}
{% endif %}
{{ pwa_settings.offline_text|safe }}
{% if pwa_settings.offline_retry_button %}

View File

@ -1,4 +1,4 @@
{% load combo gadjo static %}
{% load combo gadjo static thumbnail %}
/* global self, caches, fetch, URL, Response */
'use strict';
@ -26,7 +26,11 @@ var config = {
version: 'v{{ version }}',
staticCacheItems: [
'/__pwa__/offline/',
'{% static "" %}{{ css_variant }}/{{ icon_prefix }}{{icon_sizes|last}}px.png'
{% if pwa_settings.application_icon %}
{% thumbnail pwa_settings.application_icon '512x512' crop='center' format='PNG' as im %}
'{{ im.url }}'
{% endthumbnail %}
{% endif %}
],
cachePathPattern: /^\/static\/.*/,
handleFetchPathPattern: /.*/,

View File

@ -32,7 +32,10 @@ def manifest_json(request, *args, **kwargs):
template = get_template('combo/manifest.json')
except TemplateDoesNotExist:
raise Http404()
return HttpResponse(template.render({}, request), content_type='application/json')
context = {
'site_base': request.build_absolute_uri('/')[:-1],
}
return HttpResponse(template.render(context, request), content_type='application/json')
def js_response(request, template_name, **kwargs):
@ -81,9 +84,4 @@ def subscribe_push(request, *args, **kwargs):
class OfflinePage(TemplateView):
template_name = 'combo/pwa/offline.html'
def get_context_data(self, **kwargs):
context = super(OfflinePage, self).get_context_data(**kwargs)
context['pwa_settings'] = PwaSettings.singleton()
return context
offline_page = OfflinePage.as_view()

View File

@ -17,8 +17,12 @@
from django.conf import settings
from combo.utils.cache import cache_during_request
from combo.apps.pwa.models import PwaSettings
def template_vars(request):
context_extras = {}
context_extras['debug'] = settings.DEBUG
context_extras['pwa_settings'] = cache_during_request(PwaSettings.singleton)
context_extras.update(settings.TEMPLATE_VARS)
return context_extras

View File

@ -1,7 +1,9 @@
import base64
import os
import mock
import pytest
from webtest import Upload
try:
import pywebpush
@ -137,6 +139,14 @@ def test_pwa_manager(app, admin_user):
resp = resp.form.submit()
assert 'An URL cannot be specified' in resp.text
# add an icon
resp = app.get('/manage/pwa/')
resp.form['application_icon'] = Upload('test.png',
base64.decodestring(b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
assert PwaSettings.singleton().application_icon.name == 'pwa/test.png'
def test_pwa_offline_page(app):
PwaSettings.objects.all().delete()
@ -175,3 +185,21 @@ def test_pwa_navigation_templatetag(app):
nav = t.render(Context({'request': request, 'render_skeleton': True}))
assert 'data-pwa-user-name="{% block placeholder-user-name %}' in nav
def test_pwa_application_icon(app, admin_user):
app = login(app)
with override_settings(TEMPLATE_VARS={'pwa_display': 'standalone'}):
PwaSettings.objects.all().delete()
resp = app.get('/manage/pwa/')
resp.form['application_icon'] = Upload('test.png',
base64.decodestring(b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAACklEQVQI12NoAAAAggCB3UNq9AAAAABJRU5ErkJggg=='),
'image/png')
resp = resp.form.submit().follow()
resp = app.get('/manifest.json', status=200)
assert len(resp.json['icons']) == 5
# make sure largest icon is referenced in service worker
resp2 = app.get('/service-worker.js', status=200)
assert resp.json['icons'][-1]['src'].split('/')[-1] in resp.text