From e81e958bf3f83be0425a10d010dad7cff55d2ac6 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Fri, 23 Oct 2026 17:19:19 +0200 Subject: [PATCH] [IMP] web_company_color: match browser theme color Odoo hard-codes the theme-color meta tag to its default navbar color, so mobile browsers kept painting their address bar with it after the navbar was recolored. Use the active company's navbar color instead, compiled as SCSS so expressions like desaturate() also work. The active company is now taken only from the user's allowed companies, falling back to the current company. --- web_company_color/README.rst | 4 ++ web_company_color/models/__init__.py | 1 + web_company_color/models/assetsbundle.py | 12 +--- web_company_color/models/ir_http.py | 12 ++++ web_company_color/models/res_company.py | 38 +++++++++++- web_company_color/readme/DESCRIPTION.md | 3 + .../static/description/index.html | 5 +- web_company_color/tests/__init__.py | 1 + web_company_color/tests/test_theme_color.py | 58 +++++++++++++++++++ web_company_color/view/assets.xml | 6 ++ 10 files changed, 126 insertions(+), 14 deletions(-) create mode 100644 web_company_color/models/ir_http.py create mode 100644 web_company_color/tests/test_theme_color.py diff --git a/web_company_color/README.rst b/web_company_color/README.rst index e3f14499b0b8..8c7f3b88bace 100644 --- a/web_company_color/README.rst +++ b/web_company_color/README.rst @@ -34,6 +34,10 @@ Web Company Color This module change navbar colors based in the company logo colors. +The navbar background color is also used as the browser theme color, so +mobile browsers paint their address bar with the same color as the +navbar. + **Table of contents** .. contents:: diff --git a/web_company_color/models/__init__.py b/web_company_color/models/__init__.py index 8677b09f5075..0e3633b4e713 100644 --- a/web_company_color/models/__init__.py +++ b/web_company_color/models/__init__.py @@ -3,3 +3,4 @@ from . import assetsbundle from . import res_company from . import ir_qweb +from . import ir_http diff --git a/web_company_color/models/assetsbundle.py b/web_company_color/models/assetsbundle.py index e416e20a28cd..a9277e60382d 100644 --- a/web_company_color/models/assetsbundle.py +++ b/web_company_color/models/assetsbundle.py @@ -1,20 +1,10 @@ # Copyright 2020 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.http import request - from odoo.addons.base.models.assetsbundle import AssetsBundle class AssetsBundleCompanyColor(AssetsBundle): def get_company_color_asset_node(self): """Process the user active company scss and returns the node to inject""" - try: - active_company_id = int( - request.httprequest.cookies.get("cids", "").split("-")[0] - ) - except Exception: - active_company_id = False - company_id = ( - self.env["res.company"].browse(active_company_id) or self.env.company - ) + company_id = self.env["res.company"]._get_web_company_color_active_company() return company_id.scss_get_url() diff --git a/web_company_color/models/ir_http.py b/web_company_color/models/ir_http.py new file mode 100644 index 000000000000..e0606581696b --- /dev/null +++ b/web_company_color/models/ir_http.py @@ -0,0 +1,12 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import models + + +class IrHttp(models.AbstractModel): + _inherit = "ir.http" + + def webclient_rendering_context(self): + res = super().webclient_rendering_context() + company = self.env["res.company"]._get_web_company_color_active_company() + res["web_company_color_theme_color"] = company._get_theme_color() + return res diff --git a/web_company_color/models/res_company.py b/web_company_color/models/res_company.py index 3d40723bc5e4..7e7691deb734 100644 --- a/web_company_color/models/res_company.py +++ b/web_company_color/models/res_company.py @@ -1,11 +1,13 @@ # Copyright 2019 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import base64 +import re from colorsys import hls_to_rgb, rgb_to_hls -from odoo import api, fields, models +from odoo import api, fields, models, tools +from odoo.http import request -from odoo.addons.base.models.assetsbundle import ScssStylesheetAsset +from odoo.addons.base.models.assetsbundle import CompileError, ScssStylesheetAsset from ..utils import convert_to_image, image_to_rgb, n_rgb_to_hex @@ -209,6 +211,38 @@ def button_compute_color(self): ) self.update(values) + @api.model + def _get_web_company_color_active_company(self): + try: + active_company_id = int( + request.httprequest.cookies.get("cids", "").split("-")[0] + ) + except Exception: + active_company_id = False + return ( + self.env.user.company_ids.filtered(lambda c: c.id == active_company_id) + or self.env.company + ) + + def _get_theme_color(self): + self.ensure_one() + if not self.color_navbar_bg: + return False + return self._compile_theme_color(self.color_navbar_bg) + + @api.model + @tools.ormcache("color") + def _compile_theme_color(self, color): + scss_asset = ScssStylesheetAsset( + "web_company_color.company_color_assets", url=URL_BASE + ) + try: + css = scss_asset.compile(f".o_theme_color {{ color: {color}; }}") + except CompileError: + return False + match = re.search(r"color:\s*([^;]+);", css) + return match and match.group(1).strip() + def _scss_get_sanitized_values(self): self.ensure_one() # Clone company_color as dictionary to avoid ORM operations diff --git a/web_company_color/readme/DESCRIPTION.md b/web_company_color/readme/DESCRIPTION.md index b164fc0f50b5..2c4cbe884952 100644 --- a/web_company_color/readme/DESCRIPTION.md +++ b/web_company_color/readme/DESCRIPTION.md @@ -1 +1,4 @@ This module change navbar colors based in the company logo colors. + +The navbar background color is also used as the browser theme color, so mobile +browsers paint their address bar with the same color as the navbar. diff --git a/web_company_color/static/description/index.html b/web_company_color/static/description/index.html index f0150e75f03e..609a6dbccb12 100644 --- a/web_company_color/static/description/index.html +++ b/web_company_color/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Web Company Color