[FIX] mail: rendering of emails in chatter

odoo/enterprise#46143

Before this commit, messages of type email were not rendered properly in the chatter. For example, the email may display text with dark color even when in dark theme or the layout of bootstrap elements like btn might not look correct.

These style issues are caused by combining the style in content of the email (e.g. inline styles) with the style of the webclient, giving the impression that the original visual of the email is buggy.

This commit fixes the issue by showing a slightly transformed style of email messages in chatter that is readable and looks nice with the Odoo theme at hand. In particular with dark theme, the background color matches the bubble color and the text is white.

Sometimes the exact visual of the original email is desired. A button "Show Original Email" in the top-right corner of the message bubble allows seeing the visual of email in its original intention.

Task-3437069

Forward-port-of: #133545
Forward-port-of: #131202
Part-of: odoo/odoo#134234
This commit is contained in:
Rahul Prajapati
2023-09-06 11:50:55 +00:00
committed by Alexandre Kühn
parent f5307d810d
commit 2319d9d339
6 changed files with 80 additions and 2 deletions
+14
View File
@@ -3107,6 +3107,13 @@ msgstr ""
msgid "Do you really want to delete this preview?"
msgstr ""
#. module: mail
#. odoo-javascript
#: code:addons/mail/static/src/core/common/message.js:0
#, python-format
msgid "Don't show Original Email"
msgstr ""
#. module: mail
#: model_terms:ir.ui.view,arch_db:mail.mail_activity_view_form
#: model_terms:ir.ui.view,arch_db:mail.view_document_file_kanban
@@ -8573,6 +8580,13 @@ msgstr ""
msgid "Show Member List"
msgstr ""
#. module: mail
#. odoo-javascript
#: code:addons/mail/static/src/core/common/message.js:0
#, python-format
msgid "Show Original Email"
msgstr ""
#. module: mail
#. odoo-javascript
#: code:addons/mail/static/src/discuss/channel_commands.js:0
@@ -15,7 +15,7 @@
.o-mail-ChatWindow-command {
color: inherit !important;
&:hover {
background-color: rgba(0, 0, 0, 0.075);
background-color: rgba(0, 0, 0, 0.05);
}
}
}
@@ -47,6 +47,9 @@ import { useMessageActions } from "./message_actions";
* @extends {Component<Props, Env>}
*/
export class Message extends Component {
// This is the darken version of #71639e
static SHADOW_LINK_COLOR = "#66598f";
static SHADOW_LINK_HOVER_COLOR = "#564b79";
static components = {
ActionSwiper,
AttachmentList,
@@ -78,6 +81,11 @@ export class Message extends Component {
];
static template = "mail.Message";
/** @type {HTMLStyleElement} */
shadowStyle;
/** @type {ShadowRoot} */
shadowRoot;
setup() {
this.popover = usePopover(this.constructor.components.Popover, { position: "top" });
this.state = useState({
@@ -87,12 +95,15 @@ export class Message extends Component {
expandOptions: false,
lastReadMoreIndex: 0,
isReadMoreByIndex: new Map(),
originalEmail: false,
emailHeaderOpen: false,
});
this.root = useRef("root");
this.hasTouch = hasTouch;
this.messageBody = useRef("body");
this.messageActions = useMessageActions();
this.store = useState(useService("mail.store"));
this.shadowBody = useRef("shadowBody");
this.rpc = useService("rpc");
this.threadService = useState(useService("mail.thread"));
this.messageService = useState(useService("mail.message"));
@@ -112,6 +123,19 @@ export class Message extends Component {
},
() => [this.props.messageEdition?.editingMessage]
);
useEffect(
() => {
if (!this.shadowRoot) {
return;
}
if (this.state.originalEmail) {
this.shadowRoot.removeChild(this.shadowStyle);
} else {
this.shadowRoot.insertBefore(this.shadowStyle, this.shadowRoot.firstChild);
}
},
() => [this.state.originalEmail]
);
onPatched(() => {
if (this.props.highlighted && this.root.el) {
this.root.el.scrollIntoView({ behavior: "smooth", block: "center" });
@@ -122,6 +146,29 @@ export class Message extends Component {
$(this.messageBody.el).find(".o-mail-read-more-less").remove();
this.insertReadMoreLess($(this.messageBody.el));
}
if (this.shadowBody.el) {
this.shadowRoot = this.shadowBody.el.attachShadow({ mode: "open" });
const body = document.createElement("span");
body.innerHTML = this.message.body;
this.insertReadMoreLess($(body));
const color =
this.env.services.cookie?.current.color_scheme === "dark" ? "white" : "black";
this.shadowStyle = document.createElement("style");
this.shadowStyle.innerHTML = `
* {
background-color: transparent !important;
color: ${color} !important;
}
a, a * {
color: ${this.constructor.SHADOW_LINK_COLOR} !important;
}
a:hover, a *:hover {
color: ${this.constructor.SHADOW_LINK_HOVER_COLOR} !important;
}
`;
this.shadowRoot.appendChild(this.shadowStyle);
this.shadowRoot.appendChild(body);
}
});
onWillUnmount(() => {
if (this.messageBody.el) {
@@ -320,6 +367,12 @@ export class Message extends Component {
});
}
get originalEmailText() {
return this.state.originalEmail
? _t("Don't show Original Email")
: _t("Show Original Email");
}
/**
* @param {MouseEvent} ev
*/
@@ -66,6 +66,14 @@
z-index: $o-mail-NavigableList-zIndex;
}
.o-mail-Message-originalEmailText {
line-height: 1;
&:hover {
background-color: rgba(0, 0, 0, 0.075);
}
}
.o-mail-Message-starred {
color: $o-main-favorite-color;
}
@@ -93,8 +93,10 @@
}" t-ref="body">
<Composer t-if="state.isEditing" autofocus="true" composer="message.composer" messageComponent="constructor" onDiscardCallback.bind="exitEditMode" onPostCallback.bind="exitEditMode" mode="env.inChatter ? 'extended' : 'compact'" sidebar="false"/>
<t t-else="">
<button t-if="message.type === 'email'" class="o-mail-Message-originalEmailText d-block float-end p-1 mb-1 btn btn-link opacity-75 fst-italic" t-att-class="env.inChatWindow and isAlignedRight ? 'me-3' : 'ms-3'" t-esc="originalEmailText" t-on-click="() => this.state.originalEmail = !this.state.originalEmail"/>
<em t-if="message.subject and !message.isSubjectSimilarToOriginThreadName and !message.isSubjectDefault" class="mb-1 me-2">Subject: <t t-esc="message.subject"/></em>
<t t-if="message.body" t-out="message.body"/>
<div t-if="message.type === 'email'" t-ref="shadowBody"/>
<t t-elif="message.body" t-out="message.body"/>
<!-- <small t-if="message.editDate" class="o-mail-Message-edited fst-italic text-muted" t-att-class="{ 'ms-2': !message.isBodyEmpty }" t-att-title="message.editDatetimeHuge">(edited)</small> --> <!-- DISABLED because new messages sent by email are wrongly flagged as (edited) -->
<t t-if="showSubtypeDescription" t-out="message.subtypeDescription"/>
</t>
@@ -17,5 +17,6 @@ class TestLoadMessages(odoo.tests.HttpCase):
"pinned_at": odoo.fields.Datetime.now() if n == 1 else None,
"res_id": channel_id.id,
"author_id": partner_admin.id,
"message_type": "comment",
} for n in range(1, 61)])
self.start_tour("/web#action=mail.action_discuss", "mail.load_message_order", login="admin")