diff --git a/addons/im_livechat/static/src/embed/core/disabled_features.js b/addons/im_livechat/static/src/embed/core/disabled_features.js index 6a4c3cacffd..84fa35c94d8 100644 --- a/addons/im_livechat/static/src/embed/core/disabled_features.js +++ b/addons/im_livechat/static/src/embed/core/disabled_features.js @@ -41,6 +41,9 @@ patch(ThreadService.prototype, "im_livechat/disabled", { async fetchNewMessages(thread) { return; }, + async loadAround() { + return; + }, }); patch(Store.prototype, "im_livechat/disabled", { diff --git a/addons/mail/static/src/core/common/chat_window.js b/addons/mail/static/src/core/common/chat_window.js index 88c0e68bd5f..6cd295d8a92 100644 --- a/addons/mail/static/src/core/common/chat_window.js +++ b/addons/mail/static/src/core/common/chat_window.js @@ -48,7 +48,7 @@ export class ChatWindow extends Component { this.messageEdition = useMessageEdition(); this.messageHighlight = useMessageHighlight(); this.messageToReplyTo = useMessageToReplyTo(); - this.state = useState({ moreActionsExpanded: false }); + this.state = useState({ moreActionsExpanded: false, jumpThreadPresent: 0 }); this.ui = useState(useService("ui")); this.contentRef = useRef("content"); this.threadActions = useThreadActions(); diff --git a/addons/mail/static/src/core/common/chat_window.xml b/addons/mail/static/src/core/common/chat_window.xml index 290cfce2186..3239e3e3130 100644 --- a/addons/mail/static/src/core/common/chat_window.xml +++ b/addons/mail/static/src/core/common/chat_window.xml @@ -60,8 +60,8 @@ - - + + diff --git a/addons/mail/static/src/core/common/composer.js b/addons/mail/static/src/core/common/composer.js index 23569eeed7e..9b47dd20a96 100644 --- a/addons/mail/static/src/core/common/composer.js +++ b/addons/mail/static/src/core/common/composer.js @@ -16,13 +16,26 @@ import { markEventHandled, } from "@mail/utils/common/misc"; -import { Component, onMounted, useChildSubEnv, useEffect, useRef, useState } from "@odoo/owl"; +import { + Component, + markup, + onMounted, + useChildSubEnv, + useEffect, + useRef, + useState, +} from "@odoo/owl"; import { _t } from "@web/core/l10n/translation"; import { useService } from "@web/core/utils/hooks"; import { sprintf } from "@web/core/utils/strings"; import { FileUploader } from "@web/views/fields/file_handler"; +const EDIT_CLICK_TYPE = { + CANCEL: "cancel", + SAVE: "save", +}; + /** * @typedef {Object} Props * @property {import("@mail/core/common/composer_model").Composer} composer @@ -47,6 +60,7 @@ export class Composer extends Component { static defaultProps = { mode: "normal", className: "", + sidebar: true, }; static props = [ "composer", @@ -60,10 +74,16 @@ export class Composer extends Component { "messageEdition?", "messageComponent?", "className?", + "sidebar?", ]; static template = "mail.Composer"; setup() { + this.SEND_KEYBIND_TO_SEND = markup( + sprintf(_t("%(send_keybind)s to send"), { + send_keybind: this.sendKeybind, + }) + ); this.messaging = useMessaging(); this.store = useStore(); if (this.allowUpload) { @@ -180,6 +200,39 @@ export class Composer extends Component { return ""; } + onClickCancelOrSaveEditText(ev) { + if (this.props.composer.message && ev.target.dataset?.type === EDIT_CLICK_TYPE.CANCEL) { + this.props.onDiscardCallback(ev); + } + if (this.props.composer.message && ev.target.dataset?.type === EDIT_CLICK_TYPE.SAVE) { + this.editMessage(ev); + } + } + + get CANCEL_OR_SAVE_EDIT_TEXT() { + return markup( + sprintf( + _t( + "%(cancel_keybind)s to cancel, %(save_keybind)s to save" + ), + { + cancel_keybind: _t("Escape"), + cancel_type: EDIT_CLICK_TYPE.CANCEL, + save_keybind: this.sendKeybind, + save_type: EDIT_CLICK_TYPE.SAVE, + } + ) + ); + } + + get SEND_TEXT() { + return this.props.composer.type === "note" ? _t("Log") : _t("Send"); + } + + get sendKeybind() { + return this.props.mode === "extended" ? _t("CTRL-Enter") : _t("Enter"); + } + get thread() { return this.props.composer.thread ?? null; } diff --git a/addons/mail/static/src/core/common/composer.scss b/addons/mail/static/src/core/common/composer.scss index 4283d5b5a90..1c04322c361 100644 --- a/addons/mail/static/src/core/common/composer.scss +++ b/addons/mail/static/src/core/common/composer.scss @@ -46,10 +46,14 @@ max-height: 100px; resize: none; - .o-extended & { + .o-extended:not(.o-isUiSmall) & { max-height: 400px; } + .o-extended.o-isUiSmall & { + max-height: Min(400px, 30vh); + } + &::placeholder { @include text-truncate(); } diff --git a/addons/mail/static/src/core/common/composer.xml b/addons/mail/static/src/core/common/composer.xml index c9c0ff95a45..4119cd02a4e 100644 --- a/addons/mail/static/src/core/common/composer.xml +++ b/addons/mail/static/src/core/common/composer.xml @@ -8,11 +8,15 @@
-
+
Avatar of user
@@ -81,7 +85,10 @@
- +
+ + +
- escape to cancel, enter to save +
diff --git a/addons/mail/static/src/core/common/discuss.js b/addons/mail/static/src/core/common/discuss.js index 200f38225ac..7c611fcd6a0 100644 --- a/addons/mail/static/src/core/common/discuss.js +++ b/addons/mail/static/src/core/common/discuss.js @@ -51,6 +51,7 @@ export class Discuss extends Component { this.messageToReplyTo = useMessageToReplyTo(); this.contentRef = useRef("content"); this.root = useRef("root"); + this.state = useState({ jumpThreadPresent: 0 }); this.orm = useService("orm"); this.effect = useService("effect"); this.ui = useState(useService("ui")); diff --git a/addons/mail/static/src/core/common/discuss.xml b/addons/mail/static/src/core/common/discuss.xml index acffddc9519..5de23cb70f8 100644 --- a/addons/mail/static/src/core/common/discuss.xml +++ b/addons/mail/static/src/core/common/discuss.xml @@ -62,8 +62,8 @@
- - + +
diff --git a/addons/mail/static/src/core/common/message.js b/addons/mail/static/src/core/common/message.js index 9f7c346a6f4..fe1aa6a12d3 100644 --- a/addons/mail/static/src/core/common/message.js +++ b/addons/mail/static/src/core/common/message.js @@ -238,8 +238,10 @@ export class Message extends Component { return Boolean(!this.message.isTransient && this.message.resId); } - get canUnfollow() { - return Boolean(this.message.originThread?.followerOfSelf); + get showUnfollow() { + return Boolean( + this.message.originThread?.followerOfSelf && this.props.thread?.model === "mail.box" + ); } get isActive() { diff --git a/addons/mail/static/src/core/common/message.scss b/addons/mail/static/src/core/common/message.scss index 4f60775c365..b3322222861 100644 --- a/addons/mail/static/src/core/common/message.scss +++ b/addons/mail/static/src/core/common/message.scss @@ -51,10 +51,10 @@ } .o-mail-Message-actions { - z-index: $o-mail-NavigableList-zIndex - 2; + z-index: $o-mail-NavigableList-zIndex - 3; &.o-expanded { - z-index: $o-mail-NavigableList-zIndex - 1; + z-index: $o-mail-NavigableList-zIndex - 2; } button:hover, .focus { diff --git a/addons/mail/static/src/core/common/message.xml b/addons/mail/static/src/core/common/message.xml index 1d351fd0856..c0d51294878 100644 --- a/addons/mail/static/src/core/common/message.xml +++ b/addons/mail/static/src/core/common/message.xml @@ -79,7 +79,7 @@
- + Subject: @@ -131,7 +131,7 @@ View Reactions Mark as Read - Unfollow + Unfollow Mark as Unread Edit Delete diff --git a/addons/mail/static/src/core/common/messaging_service.js b/addons/mail/static/src/core/common/messaging_service.js index 9edb6ddfc08..b1957d23f5f 100644 --- a/addons/mail/static/src/core/common/messaging_service.js +++ b/addons/mail/static/src/core/common/messaging_service.js @@ -237,6 +237,7 @@ export class Messaging { Object.assign(notif.payload, { body: markup(notif.payload.body) }) ); channel.messages.push(message); + channel.transientMessages.push(message); break; } case "mail.link.preview/delete": diff --git a/addons/mail/static/src/core/common/thread.js b/addons/mail/static/src/core/common/thread.js index c2d942e7d88..8597889378c 100644 --- a/addons/mail/static/src/core/common/thread.js +++ b/addons/mail/static/src/core/common/thread.js @@ -28,6 +28,7 @@ export const PRESENT_THRESHOLD = 2500; /** * @typedef {Object} Props * @property {boolean} [isInChatWindow=false] + * @property {number} [jumpPresent=0] * @property {import("@mail/utils/common/hooks").MessageEdition} [messageEdition] * @property {import("@mail/utils/common/hooks").MessageToReplyTo} [messageToReplyTo] * @property {"asc"|"desc"} [order="asc"] @@ -39,6 +40,7 @@ export class Thread extends Component { static props = [ "isInChatWindow?", "hasScrollAdjust?", + "jumpPresent?", "thread", "messageEdition?", "messageToReplyTo?", @@ -47,6 +49,7 @@ export class Thread extends Component { static defaultProps = { isInChatWindow: false, hasScrollAdjust: true, + jumpPresent: 0, order: "asc", // 'asc' or 'desc' }; static template = "mail.Thread"; @@ -127,6 +130,15 @@ export class Thread extends Component { () => this.updateShowJumpPresent(), () => [this.props.thread.loadNewer] ); + useEffect( + () => { + if (this.props.jumpPresent !== this.lastJumpPresent) { + this.jumpToPresent("instant"); + this.lastJumpPresent = this.props.jumpPresent; + } + }, + () => [this.props.jumpPresent] + ); onMounted(() => { this.oldestPersistentMessage = this.props.thread.oldestPersistentMessage?.id; if (!this.env.inChatter || !this.props.hasScrollAdjust) { @@ -135,9 +147,13 @@ export class Thread extends Component { } }); onWillStart(() => { + this.lastJumpPresent = this.props.jumpPresent; this.threadService.fetchNewMessages(this.props.thread); }); onWillUpdateProps((nextProps) => { + if (nextProps.thread !== this.props.thread) { + this.lastJumpPresent = nextProps.jumpPresent; + } this.threadService.fetchNewMessages(nextProps.thread); }); } @@ -155,12 +171,12 @@ export class Thread extends Component { this.threadService.fetchMoreMessages(this.props.thread); } - async onClickJumpPresent() { + async jumpToPresent(behavior) { this.isJumpingRecent = true; await this.threadService.loadAround(this.props.thread); this.props.thread.loadNewer = false; - this.present.el.scrollIntoView({ - behavior: this.props.order === "asc" ? "smooth" : "instant", // FIXME somehow smooth not working in desc mode + this.present.el?.scrollIntoView({ + behavior: behavior ?? (this.props.order === "asc" ? "smooth" : "instant"), // FIXME somehow smooth not working in desc mode block: "center", }); // Let smooth scroll a bit so load more is not visible diff --git a/addons/mail/static/src/core/common/thread.scss b/addons/mail/static/src/core/common/thread.scss index e43d0e6ff78..a1de9a0c285 100644 --- a/addons/mail/static/src/core/common/thread.scss +++ b/addons/mail/static/src/core/common/thread.scss @@ -27,7 +27,7 @@ .o-mail-Thread-jumpPresent { background-color: mix(map-get($theme-colors, 'info'), $o-webclient-background-color, 5%); - z-index: $o-mail-NavigableList-zIndex - 2; + z-index: $o-mail-NavigableList-zIndex - 1; } .o-mail-NotificationMessage p { diff --git a/addons/mail/static/src/core/common/thread.xml b/addons/mail/static/src/core/common/thread.xml index 24e9c03d5d7..73659a60c02 100644 --- a/addons/mail/static/src/core/common/thread.xml +++ b/addons/mail/static/src/core/common/thread.xml @@ -3,7 +3,7 @@ -
+