summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorPriyanka Kakadiya <pka@odoo.com>2021-01-29 11:55:19 +0000
committerPriyanka Kakadiya <pka@odoo.com>2021-03-10 13:30:18 +0000
commit2542f731c5b06c3b451ecde7992d3bb45adb2c60 (patch)
treed590eab9af3504ca9c4932cca13d36070ac3489a /addons
parenta8b43d02066b2299ac2f4b88056c37725e9ce6cd (diff)
[FIX] mail: fix keyboard shortcut issue for small screen
Current behavior before PR: When having a small screen, the composer in a chat window has no actual shortcut to send the message. Desired behavior after PR is merged: 'CTRL-Enter' keyboard shortcut will work for small screen size. LINKS: PR https://github.com//pull/65241 Task-2446076 closes odoo/odoo#65241 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js36
-rw-r--r--addons/mail/static/src/components/composer_text_input/composer_text_input.js3
-rw-r--r--addons/mail/static/src/components/thread_view/thread_view.js7
-rw-r--r--addons/mail/static/src/components/thread_view/thread_view.xml2
-rw-r--r--addons/mail/static/src/models/thread_view/thread_view.js71
5 files changed, 115 insertions, 4 deletions
diff --git a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
index 4e032e93dfb..979280465c3 100644
--- a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
+++ b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
@@ -1892,6 +1892,42 @@ QUnit.test('chat window should scroll to the newly posted message just after pos
);
});
+QUnit.test('chat window: post message on non-mailing channel with "CTRL-Enter" keyboard shortcut for small screen size', async function (assert) {
+ assert.expect(1);
+
+ this.data['mail.channel'].records.push({
+ id: 20,
+ is_minimized: true,
+ mass_mailing: false,
+ });
+ await this.start({
+ env: {
+ device: {
+ isMobile: true, // here isMobile is used for the small screen size, not actually for the mobile devices
+ },
+ },
+ });
+
+ await afterNextRender(() => document.querySelector(`.o_MessagingMenu_toggler`).click());
+ await afterNextRender(() =>
+ document.querySelector(`.o_MessagingMenu_dropdownMenu .o_NotificationList_preview`).click()
+ );
+ // insert some HTML in editable
+ await afterNextRender(() => {
+ document.querySelector(`.o_ComposerTextInput_textarea`).focus();
+ document.execCommand('insertText', false, "Test");
+ });
+ await afterNextRender(() => {
+ const kevt = new window.KeyboardEvent('keydown', { ctrlKey: true, key: "Enter" });
+ document.querySelector('.o_ComposerTextInput_textarea').dispatchEvent(kevt);
+ });
+ assert.containsOnce(
+ document.body,
+ '.o_Message',
+ "should now have single message in channel after posting message from pressing 'CTRL-Enter' in text input of composer for small screen"
+ );
+});
+
QUnit.test('[technical] chat window: composer state conservation on toggle home menu when folded', async function (assert) {
// technical as show/hide home menu simulation are involved and home menu implementation
// have side-effects on DOM that may make chat window components not work
diff --git a/addons/mail/static/src/components/composer_text_input/composer_text_input.js b/addons/mail/static/src/components/composer_text_input/composer_text_input.js
index 25796afff9d..6c0705ee40a 100644
--- a/addons/mail/static/src/components/composer_text_input/composer_text_input.js
+++ b/addons/mail/static/src/components/composer_text_input/composer_text_input.js
@@ -278,8 +278,7 @@ class ComposerTextInput extends Component {
!ev.altKey &&
!ev.ctrlKey &&
!ev.metaKey &&
- !ev.shiftKey &&
- !this.env.messaging.device.isMobile
+ !ev.shiftKey
) {
this.trigger('o-composer-text-input-send-shortcut');
ev.preventDefault();
diff --git a/addons/mail/static/src/components/thread_view/thread_view.js b/addons/mail/static/src/components/thread_view/thread_view.js
index 8a4898d6f3a..5b0f5f4a57a 100644
--- a/addons/mail/static/src/components/thread_view/thread_view.js
+++ b/addons/mail/static/src/components/thread_view/thread_view.js
@@ -20,7 +20,11 @@ class ThreadView extends Component {
constructor(...args) {
super(...args);
useShouldUpdateBasedOnProps();
- useStore((...args) => this._useStoreSelector(...args));
+ useStore((...args) => this._useStoreSelector(...args), {
+ compareDepth: {
+ threadTextInputSendShortcuts: 1,
+ },
+ });
useUpdate({ func: () => this._update() });
/**
* Reference of the composer. Useful to set focus on composer when
@@ -133,6 +137,7 @@ class ThreadView extends Component {
threadIsTemporary: thread && thread.isTemporary,
threadMassMailing: thread && thread.mass_mailing,
threadModel: thread && thread.model,
+ threadTextInputSendShortcuts: thread && thread.textInputSendShortcuts || [],
threadView,
threadViewIsLoading: threadView && threadView.isLoading,
};
diff --git a/addons/mail/static/src/components/thread_view/thread_view.xml b/addons/mail/static/src/components/thread_view/thread_view.xml
index 99c78279adc..495408cc8f6 100644
--- a/addons/mail/static/src/components/thread_view/thread_view.xml
+++ b/addons/mail/static/src/components/thread_view/thread_view.xml
@@ -38,7 +38,7 @@
isDoFocus="props.isDoFocus"
showAttachmentsExtensions="props.showComposerAttachmentsExtensions"
showAttachmentsFilenames="props.showComposerAttachmentsFilenames"
- textInputSendShortcuts="(threadView.thread.model === 'mail.channel' and threadView.thread.mass_mailing) ? ['ctrl-enter', 'meta-enter'] : ['enter']"
+ textInputSendShortcuts="threadView.textInputSendShortcuts"
t-ref="composer"
/>
</t>
diff --git a/addons/mail/static/src/models/thread_view/thread_view.js b/addons/mail/static/src/models/thread_view/thread_view.js
index 534fd2769a9..a7ccf0c7d4d 100644
--- a/addons/mail/static/src/models/thread_view/thread_view.js
+++ b/addons/mail/static/src/models/thread_view/thread_view.js
@@ -69,6 +69,33 @@ function factory(dependencies) {
/**
* @private
+ * @returns {mail.messaging}
+ */
+ _computeMessaging() {
+ return [['link', this.env.messaging]];
+ }
+
+ /**
+ * @private
+ * @returns {string[]}
+ */
+ _computeTextInputSendShortcuts() {
+ if (!this.thread) {
+ return;
+ }
+ const isMailingList = this.thread.model === 'mail.channel' && this.thread.mass_mailing;
+ // Actually in mobile there is a send button, so we need there 'enter' to allow new line.
+ // Hence, we want to use a different shortcut 'ctrl/meta enter' to send for small screen
+ // size with a non-mailing channel.
+ // here send will be done on clicking the button or using the 'ctrl/meta enter' shortcut.
+ if (this.env.messaging.device.isMobile || isMailingList) {
+ return ['ctrl-enter', 'meta-enter'];
+ }
+ return ['enter'];
+ }
+
+ /**
+ * @private
* @returns {integer|undefined}
*/
_computeThreadCacheInitialScrollHeight() {
@@ -199,6 +226,18 @@ function factory(dependencies) {
composer: many2one('mail.composer', {
related: 'thread.composer',
}),
+ /**
+ * Serves as compute dependency.
+ */
+ device: one2one('mail.device', {
+ related: 'messaging.device',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ deviceIsMobile: attr({
+ related: 'device.isMobile',
+ }),
hasComposerFocus: attr({
related: 'composer.hasFocus',
}),
@@ -255,6 +294,12 @@ function factory(dependencies) {
messages: many2many('mail.message', {
related: 'threadCache.messages',
}),
+ /**
+ * Serves as compute dependency.
+ */
+ messaging: many2one('mail.messaging', {
+ compute: '_computeMessaging',
+ }),
nonEmptyMessages: many2many('mail.message', {
related: 'threadCache.nonEmptyMessages',
}),
@@ -288,6 +333,20 @@ function factory(dependencies) {
related: 'threadViewer.stringifiedDomain',
}),
/**
+ * Determines the keyboard shortcuts that are available to send a message
+ * from the composer of this thread viewer.
+ */
+ textInputSendShortcuts: attr({
+ compute: '_computeTextInputSendShortcuts',
+ dependencies: [
+ 'device',
+ 'deviceIsMobile',
+ 'thread',
+ 'threadMassMailing',
+ 'threadModel',
+ ],
+ }),
+ /**
* Determines the `mail.thread` currently displayed by `this`.
*/
thread: many2one('mail.thread', {
@@ -336,6 +395,18 @@ function factory(dependencies) {
related: 'threadViewer.threadCacheInitialScrollPositions',
}),
/**
+ * Serves as compute dependency.
+ */
+ threadMassMailing: attr({
+ related: 'thread.mass_mailing',
+ }),
+ /**
+ * Serves as compute dependency.
+ */
+ threadModel: attr({
+ related: 'thread.model',
+ }),
+ /**
* Not a real field, used to trigger `thread.markAsSeen` when one of
* the dependencies changes.
*/