diff --git a/web_pwa_customize/README.rst b/web_pwa_customize/README.rst index 26cb2c30d698..bd4d7dc2cf1c 100644 --- a/web_pwa_customize/README.rst +++ b/web_pwa_customize/README.rst @@ -35,6 +35,11 @@ Web Pwa Customize This module allows to configure data for Progressive Web App: Short name, Background color, Theme color and Icon. +It also covers iOS Safari's "Add to Home Screen", which reads the +``apple-touch-icon`` link tag rather than the manifest - without this, +an icon configured here would only ever show up on Chrome, Edge and +Android. + **Table of contents** .. contents:: @@ -46,6 +51,13 @@ Use Cases / Context The existing definitions in the old web_pwa_oca of 16.0 (not existing or customizable in core) are maintained. +The settings this module adds live in the same "Progressive Web App" +block as core's own ``web.web_app_name`` field, which core hides behind +developer mode (``base.group_no_one``). That restriction is dropped here +so the settings are actually reachable - General Settings itself already +requires admin access, so this doesn't expose anything that wasn't +already admin-only. + Configuration ============= @@ -78,6 +90,9 @@ Contributors - Víctor Martínez - Pedro M. Baeza +- `LadyHwesta `__ (apple-touch-icon + support, settings visibility) + Maintainers ----------- diff --git a/web_pwa_customize/__manifest__.py b/web_pwa_customize/__manifest__.py index 9cd7d3a7dfca..c2ca1a67f143 100644 --- a/web_pwa_customize/__manifest__.py +++ b/web_pwa_customize/__manifest__.py @@ -4,11 +4,14 @@ "name": "Web Pwa Customize", "author": "Tecnativa, Odoo Community Association (OCA)", "website": "https://github.com/OCA/web", - "version": "19.0.1.0.0", + "version": "19.0.1.1.0", "depends": ["web"], "license": "AGPL-3", "category": "Website", "installable": True, "maintainers": ["victoralmau"], - "data": ["views/res_config_settings_views.xml"], + "data": [ + "views/res_config_settings_views.xml", + "views/webclient_templates.xml", + ], } diff --git a/web_pwa_customize/controllers/webmanifest.py b/web_pwa_customize/controllers/webmanifest.py index 13f2600b80b8..994dee31e8ef 100644 --- a/web_pwa_customize/controllers/webmanifest.py +++ b/web_pwa_customize/controllers/webmanifest.py @@ -8,6 +8,20 @@ from odoo.addons.web.controllers import webmanifest +# iOS Safari's "Add to Home Screen" reads a single apple-touch-icon link +# tag, not the PWA manifest's icons array, so it needs one fixed image +# rather than a list of sizes. None of the sizes this module generates +# (128 up to 512) is the platform's own recommended 180x180, so 192x192 - +# the closest larger one - is tried first, then whatever else exists. +APPLE_TOUCH_ICON_SIZES = [ + "192x192", + "256x256", + "152x152", + "144x144", + "128x128", + "512x512", +] + class WebManifest(webmanifest.WebManifest): def _get_pwa_manifest_icons(self, pwa_icon): @@ -42,6 +56,51 @@ def _get_pwa_manifest_icons(self, pwa_icon): ] return icons + def _get_apple_touch_icon_attachment(self): + """The best-fitting configured icon for iOS's apple-touch-icon, or + None if no custom icon has been uploaded at all.""" + pwa_icon = ( + request.env["ir.attachment"] + .sudo() + .search([("url", "like", "/web_pwa_customize/icon.")]) + ) + if not pwa_icon: + return None + if pwa_icon.mimetype.startswith("image/svg"): + return pwa_icon + sized_icons = ( + request.env["ir.attachment"] + .sudo() + .search( + [ + ("url", "like", "/web_pwa_customize/icon"), + ("url", "not like", "/web_pwa_customize/icon."), + ] + ) + ) + by_url = {icon.url: icon for icon in sized_icons} + for size in APPLE_TOUCH_ICON_SIZES: + icon = by_url.get(f"/web_pwa_customize/icon{size}.png") + if icon: + return icon + return pwa_icon + + @http.route( + "/web_pwa_customize/apple_touch_icon", + type="http", + auth="public", + readonly=True, + ) + def apple_touch_icon(self): + """iOS Safari's "Add to Home Screen" reads the apple-touch-icon + link tag, not the PWA manifest - redirect it to whichever + configured icon fits best, falling back to Odoo's own artwork if + nothing has been configured.""" + icon = self._get_apple_touch_icon_attachment() + if not icon: + return request.redirect("/web/static/img/odoo-icon-ios.png") + return request.redirect(icon.url) + @http.route( "/web/manifest.webmanifest", type="http", diff --git a/web_pwa_customize/readme/CONTEXT.md b/web_pwa_customize/readme/CONTEXT.md index 6f4089074ca3..594e35d173cc 100644 --- a/web_pwa_customize/readme/CONTEXT.md +++ b/web_pwa_customize/readme/CONTEXT.md @@ -1,2 +1,4 @@ The existing definitions in the old web_pwa_oca of 16.0 (not existing or customizable in core) are maintained. + +The settings this module adds live in the same "Progressive Web App" block as core's own `web.web_app_name` field, which core hides behind developer mode (`base.group_no_one`). That restriction is dropped here so the settings are actually reachable - General Settings itself already requires admin access, so this doesn't expose anything that wasn't already admin-only. diff --git a/web_pwa_customize/readme/CONTRIBUTORS.md b/web_pwa_customize/readme/CONTRIBUTORS.md index 5fee3904270d..3e87ded9c1fd 100644 --- a/web_pwa_customize/readme/CONTRIBUTORS.md +++ b/web_pwa_customize/readme/CONTRIBUTORS.md @@ -1,3 +1,4 @@ - [Tecnativa](https://www.tecnativa.com): - Víctor Martínez - Pedro M. Baeza +- [LadyHwesta](https://github.com/LadyHwesta) (apple-touch-icon support, settings visibility) diff --git a/web_pwa_customize/readme/DESCRIPTION.md b/web_pwa_customize/readme/DESCRIPTION.md index d780ed50121a..892030810cb7 100644 --- a/web_pwa_customize/readme/DESCRIPTION.md +++ b/web_pwa_customize/readme/DESCRIPTION.md @@ -1 +1,3 @@ This module allows to configure data for Progressive Web App: Short name, Background color, Theme color and Icon. + +It also covers iOS Safari's "Add to Home Screen", which reads the `apple-touch-icon` link tag rather than the manifest - without this, an icon configured here would only ever show up on Chrome, Edge and Android. diff --git a/web_pwa_customize/static/description/index.html b/web_pwa_customize/static/description/index.html index b47d09e202ae..1ec2418f538b 100644 --- a/web_pwa_customize/static/description/index.html +++ b/web_pwa_customize/static/description/index.html @@ -377,6 +377,10 @@

Web Pwa Customize

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

This module allows to configure data for Progressive Web App: Short name, Background color, Theme color and Icon.

+

It also covers iOS Safari’s “Add to Home Screen”, which reads the +apple-touch-icon link tag rather than the manifest - without this, +an icon configured here would only ever show up on Chrome, Edge and +Android.

Table of contents

Configuration

@@ -425,6 +435,8 @@

Contributors

  • Pedro M. Baeza
  • +
  • LadyHwesta (apple-touch-icon +support, settings visibility)
  • diff --git a/web_pwa_customize/tests/test_web_pwa_customize.py b/web_pwa_customize/tests/test_web_pwa_customize.py index e91e995ed836..2e44e6eed686 100644 --- a/web_pwa_customize/tests/test_web_pwa_customize.py +++ b/web_pwa_customize/tests/test_web_pwa_customize.py @@ -106,3 +106,73 @@ def test_default_get_colors(self): ) self.assertEqual(res.get("pwa_background_color"), "#714B67") self.assertEqual(res.get("pwa_theme_color"), "#714B67") + + def test_apple_touch_icon_falls_back_without_custom_icon(self): + """iOS Safari reads apple-touch-icon, not the manifest - with no + icon configured it should fall back to Odoo's own artwork.""" + self.env["res.config.settings"].create({"pwa_icon": False}).execute() + response = self.url_open( + "/web_pwa_customize/apple_touch_icon", allow_redirects=False + ) + self.assertEqual(response.status_code, 303) + # Werkzeug renders this Location either as a bare path or as an + # absolute URL depending on the environment (both are valid per + # RFC 7231) - assert on the path, not on which form it took. + self.assertTrue( + response.headers["Location"].endswith("/web/static/img/odoo-icon-ios.png") + ) + + def test_apple_touch_icon_redirects_to_configured_png(self): + img = Image.new("RGB", (512, 512), color="red") + img_byte_arr = io.BytesIO() + img.save(img_byte_arr, format="PNG") + icon_base64 = base64.b64encode(img_byte_arr.getvalue()) + self.env["res.config.settings"].create({"pwa_icon": icon_base64}).execute() + response = self.url_open( + "/web_pwa_customize/apple_touch_icon", allow_redirects=False + ) + self.assertEqual(response.status_code, 303) + self.assertTrue( + response.headers["Location"].endswith("/web_pwa_customize/icon192x192.png") + ) + + def test_apple_touch_icon_redirects_to_configured_svg(self): + svg_content = ( + '' + '' + "" + ) + svg_base64 = base64.b64encode(svg_content.encode("utf-8")) + self.env["res.config.settings"].create({"pwa_icon": svg_base64}).execute() + response = self.url_open( + "/web_pwa_customize/apple_touch_icon", allow_redirects=False + ) + self.assertEqual(response.status_code, 303) + self.assertTrue( + response.headers["Location"].endswith("/web_pwa_customize/icon.svg") + ) + + def test_apple_touch_icon_link_uses_our_route(self): + self.authenticate("admin", "admin") + page = self.url_open("/odoo") + self.assertIn( + '', + page.text, + ) + + def test_pwa_settings_visible_without_developer_mode(self): + """The whole block - short name, colors, icon, and core's own + web_app_name - should be visible to a plain admin, not just one + with developer mode's base.group_no_one enabled.""" + admin = self.env.ref("base.user_admin") + self.assertNotIn( + self.env.ref("base.group_no_one"), + admin.group_ids, + "test assumption broken: admin already has group_no_one", + ) + arch = self.env["res.config.settings"].with_user(admin).get_view()["arch"] + self.assertIn('id="pwa_settings"', arch) + self.assertIn('name="web_app_name"', arch) + self.assertIn('name="pwa_short_name"', arch) + self.assertIn('name="pwa_icon"', arch) diff --git a/web_pwa_customize/views/res_config_settings_views.xml b/web_pwa_customize/views/res_config_settings_views.xml index 44e0f27e1e3c..90a9c5ca9d86 100644 --- a/web_pwa_customize/views/res_config_settings_views.xml +++ b/web_pwa_customize/views/res_config_settings_views.xml @@ -5,34 +5,46 @@ res.config.settings - - - - - -
    - Background Color - -
    -
    - Theme Color - -
    -
    - -
    - -
    -
    -
    + + + + + + + + + + +
    + Background Color + +
    +
    + Theme Color + +
    +
    + +
    + +
    +
    +
    +
    diff --git a/web_pwa_customize/views/webclient_templates.xml b/web_pwa_customize/views/webclient_templates.xml new file mode 100644 index 000000000000..97fdaeaf0e8b --- /dev/null +++ b/web_pwa_customize/views/webclient_templates.xml @@ -0,0 +1,13 @@ + + + + +