From a499263dd35508e44a2ec831b1cf30cde564a1d6 Mon Sep 17 00:00:00 2001 From: "Hubert Van de Walle (huvw)" Date: Thu, 12 May 2022 12:53:12 +0000 Subject: [PATCH] [FIX] web: mail.MessagingMenu isn't always added in the systray Steps to follow - Use chrome - Connect to a runbot with the demo account - After a couple refreshes, the mail.MessagingMenu isn't displayed Cause of the issue The navbar should be updated when there is a new item added to the systray registry. For that, the navbar listen to the update event with the `useBus` function. `useBus` itself uses `useEffect` which only starts listening after a component has been mounted/patched. -> The update callback is never called in this case because new items are added before the callback is registered. opw-2801467 closes odoo/odoo#92768 X-original-commit: c2fd26881ceae95417e2a0afc71fdf8567e3b8c0 Signed-off-by: Samuel Degueldre Signed-off-by: Hubert Van De Walle --- .../web/static/src/webclient/navbar/navbar.js | 14 ++++++--- .../static/tests/webclient/navbar_tests.js | 29 ++++++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/addons/web/static/src/webclient/navbar/navbar.js b/addons/web/static/src/webclient/navbar/navbar.js index e86eda5aa86..44cdcf522e7 100644 --- a/addons/web/static/src/webclient/navbar/navbar.js +++ b/addons/web/static/src/webclient/navbar/navbar.js @@ -2,12 +2,12 @@ import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; -import { useService, useBus } from "@web/core/utils/hooks"; +import { useService } from "@web/core/utils/hooks"; import { registry } from "@web/core/registry"; import { debounce } from "@web/core/utils/timing"; import { ErrorHandler } from "@web/core/utils/components"; -const { Component, onWillDestroy, useExternalListener, useEffect, useRef } = owl; +const { Component, onWillDestroy, onWillUnmount, useExternalListener, useEffect, useRef } = owl; const systrayRegistry = registry.category("systray"); const getBoundingClientRect = Element.prototype.getBoundingClientRect; @@ -47,8 +47,14 @@ export class NavBar extends Component { this.render(); }; - useBus(systrayRegistry, "UPDATE", renderAndAdapt); - useBus(this.env.bus, "MENUS:APP-CHANGED", renderAndAdapt); + systrayRegistry.on("UPDATE", this, renderAndAdapt); + this.env.bus.on("MENUS:APP-CHANGED", this, renderAndAdapt); + + onWillUnmount(() => { + systrayRegistry.off("UPDATE", this); + this.env.bus.off("MENUS:APP-CHANGED", this); + }); + // We don't want to adapt every time we are patched // rather, we adapt only when menus or systrays have changed. useEffect( diff --git a/addons/web/static/tests/webclient/navbar_tests.js b/addons/web/static/tests/webclient/navbar_tests.js index 3a1cdf38f28..db49cd67871 100644 --- a/addons/web/static/tests/webclient/navbar_tests.js +++ b/addons/web/static/tests/webclient/navbar_tests.js @@ -19,7 +19,7 @@ import { mockTimeout, } from "../helpers/utils"; -const { Component, xml } = owl; +const { Component, xml, onRendered } = owl; const systrayRegistry = registry.category("systray"); const serviceRegistry = registry.category("services"); @@ -174,6 +174,33 @@ QUnit.test("navbar can display systray items ordered based on their sequence", a assert.strictEqual(menuSystray.innerText, "my item 3\nmy item 4\nmy item 2\nmy item 1"); }); +QUnit.test("navbar updates after adding a systray item", async (assert) => { + class MyItem1 extends Component {} + MyItem1.template = xml`
  • my item 1
  • `; + + clearRegistryWithCleanup(systrayRegistry); + systrayRegistry.add('addon.myitem1', { Component: MyItem1 }); + + const env = await makeTestEnv(baseConfig); + + patchWithCleanup(NavBar.prototype, { + setup() { + onRendered(() => { + if (!systrayRegistry.contains('addon.myitem2')) { + class MyItem2 extends Component {} + MyItem2.template = xml`
  • my item 2
  • `; + systrayRegistry.add('addon.myitem2', {Component: MyItem2}); + } + }); + this._super(); + } + }); + + await mount(NavBar, target, { env }); + const menuSystray = target.getElementsByClassName("o_menu_systray")[0]; + assert.containsN(menuSystray, "li", 2, "2 systray items should be displayed"); +}); + QUnit.test("can adapt with 'more' menu sections behavior", async (assert) => { class MyNavbar extends NavBar { async adapt() {