From c5517ce86e9e5f28f8352f3f077b0cde33b4660a Mon Sep 17 00:00:00 2001 From: tsm-odoo Date: Fri, 20 Oct 2023 09:34:28 +0200 Subject: [PATCH] [FIX] im_livechat: remove non-required dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit reduces the size and avoid conflicts caused by the embed live chat bundle: jquery, legacy libs... At the same time, this commit fixes the emoji picker that was wrongly positionned and scrolled up the page when opening. Finally, this commit ensures the chat window is always at the bottom of the screen. opw-3539362 closes odoo/odoo#139261 X-original-commit: 1b29419e50343bfd723b41368ba38ce63b063d92 Signed-off-by: Alexandre Kühn (aku) --- addons/im_livechat/__manifest__.py | 4 +- .../static/src/embed/external/boot.js | 5 +- .../static/src/embed/external/overrides.scss | 3 + addons/mail/__manifest__.py | 1 + .../static/src/core/common/chat_window.xml | 2 +- addons/mail/static/src/core/common/message.js | 103 ++-------------- .../src/core/web_portal/message_patch.js | 111 ++++++++++++++++++ addons/mail/static/src/utils/common/format.js | 10 +- 8 files changed, 132 insertions(+), 107 deletions(-) create mode 100644 addons/im_livechat/static/src/embed/external/overrides.scss create mode 100644 addons/mail/static/src/core/web_portal/message_patch.js diff --git a/addons/im_livechat/__manifest__.py b/addons/im_livechat/__manifest__.py index 8e4bc5d390a..8966d6788bb 100644 --- a/addons/im_livechat/__manifest__.py +++ b/addons/im_livechat/__manifest__.py @@ -102,7 +102,6 @@ Help your customers with this chat, and analyse their feedback. 'im_livechat/static/src/embed/common/**/*', ], 'im_livechat.assets_embed_external': [ - 'web/static/lib/jquery/jquery.js', 'web/static/src/libs/fontawesome/css/font-awesome.css', 'im_livechat/static/src/embed/common/scss/bootstrap_overridden.scss', ('include', 'web._assets_helpers'), @@ -121,7 +120,8 @@ Help your customers with this chat, and analyse their feedback. 'bus/static/src/services/**/*.js', 'bus/static/src/workers/websocket_worker.js', 'bus/static/src/workers/websocket_worker_utils.js', - + ('remove', 'bus/static/src/services/assets_watchdog_service.js'), + ('remove', 'bus/static/src/simple_notification_service.js'), ('include', 'im_livechat.assets_embed_core'), 'im_livechat/static/src/embed/external/**/*', ], diff --git a/addons/im_livechat/static/src/embed/external/boot.js b/addons/im_livechat/static/src/embed/external/boot.js index c287f7bae39..f28a0727a8e 100644 --- a/addons/im_livechat/static/src/embed/external/boot.js +++ b/addons/im_livechat/static/src/embed/external/boot.js @@ -1,11 +1,9 @@ /* @odoo-module */ -import { makeRoot, makeShadow } from "@im_livechat/embed/common/boot_helpers"; import { LivechatButton } from "@im_livechat/embed/common/livechat_button"; +import { makeShadow, makeRoot } from "@im_livechat/embed/common/boot_helpers"; import { serverUrl } from "@im_livechat/embed/common/livechat_data"; -import { ChatWindowContainer } from "@mail/core/common/chat_window_container"; - import { mount, whenReady } from "@odoo/owl"; import { templates } from "@web/core/assets"; @@ -19,7 +17,6 @@ import { session } from "@web/session"; await whenReady(); const mainComponentsRegistry = registry.category("main_components"); mainComponentsRegistry.add("LivechatRoot", { Component: LivechatButton }); - mainComponentsRegistry.add("ChatWindowContainer", { Component: ChatWindowContainer }); const env = makeEnv(); await startServices(env); odoo.isReady = true; diff --git a/addons/im_livechat/static/src/embed/external/overrides.scss b/addons/im_livechat/static/src/embed/external/overrides.scss new file mode 100644 index 00000000000..414d81c412e --- /dev/null +++ b/addons/im_livechat/static/src/embed/external/overrides.scss @@ -0,0 +1,3 @@ +.o-main-components-container, .o_notification_manager { + position: fixed !important; +} diff --git a/addons/mail/__manifest__.py b/addons/mail/__manifest__.py index 374b37d8d6d..288c21018cc 100644 --- a/addons/mail/__manifest__.py +++ b/addons/mail/__manifest__.py @@ -134,6 +134,7 @@ For more specific needs, you may also assign custom-defined actions ('remove', 'mail/static/lib/lame/lame.js'), 'mail/static/src/js/**/*', 'mail/static/src/core/common/**/*', + 'mail/static/src/core/web_portal/**/*', 'mail/static/src/core/web/**/*', 'mail/static/src/**/common/**/*', 'mail/static/src/**/web/**/*', diff --git a/addons/mail/static/src/core/common/chat_window.xml b/addons/mail/static/src/core/common/chat_window.xml index 8bc58375020..6ac41b4a922 100644 --- a/addons/mail/static/src/core/common/chat_window.xml +++ b/addons/mail/static/src/core/common/chat_window.xml @@ -7,7 +7,7 @@ t-att-class="{ 'w-100 h-100 o-mobile': ui.isSmall, 'o-folded': props.chatWindow.folded, - 'position-absolute bottom-0 overflow-hidden d-flex flex-column': !props.chatWindow.hidden, + 'position-fixed bottom-0 overflow-hidden d-flex flex-column': !props.chatWindow.hidden, 'rounded-top-3': !props.chatWindow.hidden and !ui.isSmall, }" t-on-keydown="onKeydown" diff --git a/addons/mail/static/src/core/common/message.js b/addons/mail/static/src/core/common/message.js index efa8b278451..7ff72a9fcdb 100644 --- a/addons/mail/static/src/core/common/message.js +++ b/addons/mail/static/src/core/common/message.js @@ -18,7 +18,6 @@ import { Component, onMounted, onPatched, - onWillUnmount, useChildSubEnv, useEffect, useRef, @@ -99,8 +98,6 @@ export class Message extends Component { isHovered: false, isClicked: false, expandOptions: false, - lastReadMoreIndex: 0, - isReadMoreByIndex: new Map(), originalEmail: false, emailHeaderOpen: false, }); @@ -150,15 +147,14 @@ export class Message extends Component { }); onMounted(() => { if (this.messageBody.el) { - $(this.messageBody.el).find(".o-mail-read-more-less").remove(); - this.insertReadMoreLess($(this.messageBody.el)); + this.prepareMessageBody(this.messageBody.el); } if (this.shadowBody.el) { this.shadowRoot = this.shadowBody.el.attachShadow({ mode: "open" }); const body = document.createElement("span"); body.innerHTML = this.props.messageSearch?.highlight(this.message.body) ?? this.message.body; - this.insertReadMoreLess($(body)); + this.prepareMessageBody(body); const color = cookie.get("color_scheme") === "dark" ? "white" : "black"; this.shadowStyle = document.createElement("style"); this.shadowStyle.innerHTML = ` @@ -180,11 +176,6 @@ export class Message extends Component { this.shadowRoot.appendChild(body); } }); - onWillUnmount(() => { - if (this.messageBody.el) { - $(this.messageBody.el).find(".o-mail-read-more-less").remove(); - } - }); } get attClass() { @@ -436,6 +427,11 @@ export class Message extends Component { this.enterEditMode(); } + /** + * @param {HTMLElement} element + */ + prepareMessageBody(element) {} + enterEditMode() { const messageContent = convertBrToLineBreak(this.props.message.body); this.props.message.composer = { @@ -473,91 +469,6 @@ export class Message extends Component { }); } - /** - * Modifies the message to add the 'read more/read less' functionality - * All element nodes with 'data-o-mail-quote' attribute are concerned. - * All text nodes after a ``#stopSpelling`` element are concerned. - * Those text nodes need to be wrapped in a span (toggle functionality). - * All consecutive elements are joined in one 'read more/read less'. - * - * FIXME This method should be rewritten (task-2308951) - * - * @param {jQuery} $element - */ - insertReadMoreLess($element) { - const groups = []; - let readMoreNodes; - - // nodeType 1: element_node - // nodeType 3: text_node - const $children = $element - .contents() - .filter( - (index, content) => - content.nodeType === 1 || (content.nodeType === 3 && content.nodeValue.trim()) - ); - - for (const child of $children) { - let $child = $(child); - - // Hide Text nodes if "stopSpelling" - if (child.nodeType === 3 && $child.prevAll('[id*="stopSpelling"]').length > 0) { - // Convert Text nodes to Element nodes - $child = $("", { - text: child.textContent, - "data-o-mail-quote": "1", - }); - child.parentNode.replaceChild($child[0], child); - } - - // Create array for each 'read more' with nodes to toggle - if ( - $child.attr("data-o-mail-quote") || - ($child.get(0).nodeName === "BR" && - $child.prev('[data-o-mail-quote="1"]').length > 0) - ) { - if (!readMoreNodes) { - readMoreNodes = []; - groups.push(readMoreNodes); - } - $child.hide(); - readMoreNodes.push($child); - } else { - readMoreNodes = undefined; - this.insertReadMoreLess($child); - } - } - - for (const group of groups) { - const index = this.state.lastReadMoreIndex++; - // Insert link just before the first node - const $readMoreLess = $("", { - class: "o-mail-read-more-less d-block", - href: "#", - text: "Read More", - }).insertBefore(group[0]); - - // Toggle All next nodes - if (!this.state.isReadMoreByIndex.has(index)) { - this.state.isReadMoreByIndex.set(index, true); - } - const updateFromState = () => { - const isReadMore = this.state.isReadMoreByIndex.get(index); - for (const $child of group) { - $child.hide(); - $child.toggle(!isReadMore); - } - $readMoreLess.text(isReadMore ? "Read More" : "Read Less"); - }; - $readMoreLess.click((e) => { - e.preventDefault(); - this.state.isReadMoreByIndex.set(index, !this.state.isReadMoreByIndex.get(index)); - updateFromState(); - }); - updateFromState(); - } - } - openReactionMenu() { this.dialog.add(MessageReactionMenu, { message: this.props.message, diff --git a/addons/mail/static/src/core/web_portal/message_patch.js b/addons/mail/static/src/core/web_portal/message_patch.js new file mode 100644 index 00000000000..659fd2285a7 --- /dev/null +++ b/addons/mail/static/src/core/web_portal/message_patch.js @@ -0,0 +1,111 @@ +/* @odoo-module */ + +import { patch } from "@web/core/utils/patch"; +import { Message } from "@mail/core/common/message"; +import { onWillUnmount } from "@odoo/owl"; + +patch(Message.prototype, { + setup() { + super.setup(...arguments); + this.state.lastReadMoreIndex = 0; + this.state.isReadMoreByIndex = new Map(); + onWillUnmount(() => { + this.messageBody.el?.querySelector(".o-mail-read-more-less")?.remove(); + }); + }, + + /** + * @override + * @param {HTMLElement} element + */ + prepareMessageBody(element) { + const $el = $(element); + $el.find(".o-mail-read-more-less").remove(); + this.insertReadMoreLess($el); + }, + + /** + * Modifies the message to add the 'read more/read less' functionality + * All element nodes with 'data-o-mail-quote' attribute are concerned. + * All text nodes after a ``#stopSpelling`` element are concerned. + * Those text nodes need to be wrapped in a span (toggle functionality). + * All consecutive elements are joined in one 'read more/read less'. + * + * FIXME This method should be rewritten (task-2308951) + * + * @param {jQuery} $element + */ + insertReadMoreLess($element) { + const groups = []; + let readMoreNodes; + + // nodeType 1: element_node + // nodeType 3: text_node + const $children = $element + .contents() + .filter( + (index, content) => + content.nodeType === 1 || (content.nodeType === 3 && content.nodeValue.trim()) + ); + + for (const child of $children) { + let $child = $(child); + + // Hide Text nodes if "stopSpelling" + if (child.nodeType === 3 && $child.prevAll('[id*="stopSpelling"]').length > 0) { + // Convert Text nodes to Element nodes + $child = $("", { + text: child.textContent, + "data-o-mail-quote": "1", + }); + child.parentNode.replaceChild($child[0], child); + } + + // Create array for each 'read more' with nodes to toggle + if ( + $child.attr("data-o-mail-quote") || + ($child.get(0).nodeName === "BR" && + $child.prev('[data-o-mail-quote="1"]').length > 0) + ) { + if (!readMoreNodes) { + readMoreNodes = []; + groups.push(readMoreNodes); + } + $child.hide(); + readMoreNodes.push($child); + } else { + readMoreNodes = undefined; + this.insertReadMoreLess($child); + } + } + + for (const group of groups) { + const index = this.state.lastReadMoreIndex++; + // Insert link just before the first node + const $readMoreLess = $("", { + class: "o-mail-read-more-less d-block", + href: "#", + text: "Read More", + }).insertBefore(group[0]); + + // Toggle All next nodes + if (!this.state.isReadMoreByIndex.has(index)) { + this.state.isReadMoreByIndex.set(index, true); + } + const updateFromState = () => { + const isReadMore = this.state.isReadMoreByIndex.get(index); + for (const $child of group) { + $child.hide(); + $child.toggle(!isReadMore); + } + $readMoreLess.text(isReadMore ? "Read More" : "Read Less"); + }; + $readMoreLess.click((e) => { + e.preventDefault(); + this.state.isReadMoreByIndex.set(index, !this.state.isReadMoreByIndex.get(index)); + updateFromState(); + }); + updateFromState(); + } + }, +}); diff --git a/addons/mail/static/src/utils/common/format.js b/addons/mail/static/src/utils/common/format.js index 6a3134211b7..5928c0f5a88 100644 --- a/addons/mail/static/src/utils/common/format.js +++ b/addons/mail/static/src/utils/common/format.js @@ -64,11 +64,13 @@ export function parseAndTransform(htmlString, transformFunction) { const string = htmlString.replace(/</g, openToken); let children; try { - children = $("
").html(string).contents(); + const div = document.createElement("div"); + div.innerHTML = string; + children = Array.from(div.childNodes); } catch { - children = $("
") - .html("
" + string + "
") - .contents(); + const div = document.createElement("div"); + div.innerHTML = `
${string}
`; + children = Array.from(div.childNodes); } return _parseAndTransform(children, transformFunction).replace( new RegExp(openToken, "g"),