From 3aa248b2e0a0ba8a6fa76a20e7495ae15004cae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Tue, 5 Jul 2022 14:57:26 +0000 Subject: [PATCH] [IMP] mail: move activeSuggestionView to ComposerSuggestionListView Part of task-2741982 Part-of: odoo/odoo#95341 --- .../composer_suggestion_view.js | 6 +- .../composer_suggestion_view.xml | 2 +- .../models/composer_suggestion_list_view.js | 36 ++++++++- .../src/models/composer_suggestion_view.js | 4 +- .../mail/static/src/models/composer_view.js | 81 +++++-------------- 5 files changed, 61 insertions(+), 68 deletions(-) diff --git a/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.js b/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.js index dc2260f59f4..5c3a0787ec1 100644 --- a/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.js +++ b/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.js @@ -36,13 +36,13 @@ export class ComposerSuggestionView extends Component { _update() { if ( this.root.el && - this.composerSuggestionView.composerSuggestionListViewOwner.composerViewOwner.hasToScrollToActiveSuggestionView && - this.composerSuggestionView.composerViewOwnerAsActiveSuggestionView + this.composerSuggestionView.composerSuggestionListViewOwner.hasToScrollToActiveSuggestionView && + this.composerSuggestionView.composerSuggestionListViewOwnerAsActiveSuggestionView ) { this.root.el.scrollIntoView({ block: 'center', }); - this.composerSuggestionView.composerSuggestionListViewOwner.composerViewOwner.update({ hasToScrollToActiveSuggestionView: false }); + this.composerSuggestionView.composerSuggestionListViewOwner.update({ hasToScrollToActiveSuggestionView: false }); } } diff --git a/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.xml b/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.xml index 99d2efd8b9a..8e3206c6350 100644 --- a/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.xml +++ b/addons/mail/static/src/components/composer_suggestion_view/composer_suggestion_view.xml @@ -3,7 +3,7 @@ - + diff --git a/addons/mail/static/src/models/composer_suggestion_list_view.js b/addons/mail/static/src/models/composer_suggestion_list_view.js index a48212af4dd..c8c3889af12 100644 --- a/addons/mail/static/src/models/composer_suggestion_list_view.js +++ b/addons/mail/static/src/models/composer_suggestion_list_view.js @@ -1,13 +1,31 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { many, one } from '@mail/model/model_field'; +import { attr, many, one } from '@mail/model/model_field'; import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'ComposerSuggestionListView', identifyingFields: ['composerViewOwner'], recordMethods: { + /** + * Adapts the active suggestion it if the active suggestion is no longer + * part of the suggestions. + * + * @private + * @returns {FieldCommand} + */ + _computeActiveSuggestionView() { + if ( + this.mainSuggestionViews.includes(this.activeSuggestionView) || + this.extraSuggestionViews.includes(this.activeSuggestionView) + ) { + return; + } + const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews); + const firstSuggestionView = suggestionViews[0]; + return replace(firstSuggestionView); + }, /** * @returns {FieldCommand} */ @@ -30,6 +48,15 @@ registerModel({ }, }, fields: { + /** + * Determines the suggestion that is currently active. This suggestion + * is highlighted in the UI and it will be selected when the + * suggestion is confirmed by the user. + */ + activeSuggestionView: one('ComposerSuggestionView', { + compute: '_computeActiveSuggestionView', + inverse: 'composerSuggestionListViewOwnerAsActiveSuggestionView', + }), composerViewOwner: one('ComposerView', { inverse: 'composerSuggestionListView', readonly: true, @@ -40,6 +67,13 @@ registerModel({ inverse: 'composerSuggestionListViewOwnerAsExtraSuggestion', isCausal: true, }), + /** + * Determines whether the currently active suggestion should be scrolled + * into view. + */ + hasToScrollToActiveSuggestionView: attr({ + default: false, + }), mainSuggestionViews: many('ComposerSuggestionView', { compute: '_computeMainSuggestionViews', inverse: 'composerSuggestionListViewOwnerAsMainSuggestion', diff --git a/addons/mail/static/src/models/composer_suggestion_view.js b/addons/mail/static/src/models/composer_suggestion_view.js index 2af81f328b9..015033e6eae 100644 --- a/addons/mail/static/src/models/composer_suggestion_view.js +++ b/addons/mail/static/src/models/composer_suggestion_view.js @@ -20,7 +20,7 @@ registerModel({ */ onClick(ev) { ev.preventDefault(); - this.composerSuggestionListViewOwner.composerViewOwner.update({ activeSuggestionView: replace(this) }); + this.composerSuggestionListViewOwner.update({ activeSuggestionView: replace(this) }); const composerViewOwner = this.composerSuggestionListViewOwner.composerViewOwner; composerViewOwner.insertSuggestion(); composerViewOwner.closeSuggestions(); @@ -92,7 +92,7 @@ registerModel({ compute: '_computeComposerSuggestionListViewOwner', required: true, }), - composerViewOwnerAsActiveSuggestionView: one('ComposerView', { + composerSuggestionListViewOwnerAsActiveSuggestionView: one('ComposerSuggestionListView', { inverse: 'activeSuggestionView', }), composerSuggestionListViewOwnerAsExtraSuggestion: one('ComposerSuggestionListView', { diff --git a/addons/mail/static/src/models/composer_view.js b/addons/mail/static/src/models/composer_view.js index 6b1f24afc97..f01a5f8b4f0 100644 --- a/addons/mail/static/src/models/composer_view.js +++ b/addons/mail/static/src/models/composer_view.js @@ -134,7 +134,7 @@ registerModel({ this.composer.textInputContent.length ); } - const recordReplacement = this.activeSuggestionView.mentionText; + const recordReplacement = this.composerSuggestionListView.activeSuggestionView.mentionText; const updateData = { textInputContent: textLeft + recordReplacement + ' ' + textRight, textInputCursorEnd: textLeft.length + recordReplacement.length + 1, @@ -143,11 +143,11 @@ registerModel({ // Specific cases for channel and partner mentions: the message with // the mention will appear in the target channel, or be notified to // the target partner. - if (this.activeSuggestionView.suggestable.thread) { - Object.assign(updateData, { mentionedChannels: link(this.activeSuggestionView.suggestable.thread) }); + if (this.composerSuggestionListView.activeSuggestionView.suggestable.thread) { + Object.assign(updateData, { mentionedChannels: link(this.composerSuggestionListView.activeSuggestionView.suggestable.thread) }); } - if (this.activeSuggestionView.suggestable.partner) { - Object.assign(updateData, { mentionedPartners: link(this.activeSuggestionView.suggestable.partner) }); + if (this.composerSuggestionListView.activeSuggestionView.suggestable.partner) { + Object.assign(updateData, { mentionedPartners: link(this.composerSuggestionListView.activeSuggestionView.suggestable.partner) }); } this.composer.update(updateData); for (const composerView of this.composer.composerViews) { @@ -440,7 +440,7 @@ registerModel({ } if (this.hasSuggestions) { this.setPreviousSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } break; case 'ArrowDown': @@ -451,29 +451,29 @@ registerModel({ } if (this.hasSuggestions) { this.setNextSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } break; case 'Home': if (this.hasSuggestions) { this.setFirstSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } break; case 'End': if (this.hasSuggestions) { this.setLastSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } break; case 'Tab': if (this.hasSuggestions) { if (ev.shiftKey) { this.setPreviousSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } else { this.setNextSuggestionViewActive(); - this.update({ hasToScrollToActiveSuggestionView: true }); + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); } } break; @@ -676,7 +676,7 @@ registerModel({ setFirstSuggestionViewActive() { const suggestionViews = this.composerSuggestionListView.mainSuggestionViews.concat(this.composerSuggestionListView.extraSuggestionViews); const firstSuggestionView = suggestionViews[0]; - this.update({ activeSuggestionView: replace(firstSuggestionView) }); + this.composerSuggestionListView.update({ activeSuggestionView: replace(firstSuggestionView) }); }, /** * Sets the last suggestion as active. Main and extra records are @@ -685,7 +685,7 @@ registerModel({ setLastSuggestionViewActive() { const suggestionViews = this.composerSuggestionListView.mainSuggestionViews.concat(this.composerSuggestionListView.extraSuggestionViews); const { length, [length - 1]: lastSuggestionView } = suggestionViews; - this.update({ activeSuggestionView: replace(lastSuggestionView) }); + this.composerSuggestionListView.update({ activeSuggestionView: replace(lastSuggestionView) }); }, /** * Sets the next suggestion as active. Main and extra records are @@ -694,7 +694,7 @@ registerModel({ setNextSuggestionViewActive() { const suggestionViews = this.composerSuggestionListView.mainSuggestionViews.concat(this.composerSuggestionListView.extraSuggestionViews); const activeElementIndex = suggestionViews.findIndex( - suggestion => suggestion === this.activeSuggestionView + suggestion => suggestion === this.composerSuggestionListView.activeSuggestionView ); if (activeElementIndex === suggestionViews.length - 1) { // loop when reaching the end of the list @@ -702,7 +702,7 @@ registerModel({ return; } const nextSuggestionView = suggestionViews[activeElementIndex + 1]; - this.update({ activeSuggestionView: replace(nextSuggestionView) }); + this.composerSuggestionListView.update({ activeSuggestionView: replace(nextSuggestionView) }); }, /** * Sets the previous suggestion as active. Main and extra records are @@ -711,7 +711,7 @@ registerModel({ setPreviousSuggestionViewActive() { const suggestionViews = this.composerSuggestionListView.mainSuggestionViews.concat(this.composerSuggestionListView.extraSuggestionViews); const activeElementIndex = suggestionViews.findIndex( - suggestion => suggestion === this.activeSuggestionView + suggestion => suggestion === this.composerSuggestionListView.activeSuggestionView ); if (activeElementIndex === 0) { // loop when reaching the start of the list @@ -719,7 +719,7 @@ registerModel({ return; } const previousSuggestionView = suggestionViews[activeElementIndex - 1]; - this.update({ activeSuggestionView: replace(previousSuggestionView) }); + this.composerSuggestionListView.update({ activeSuggestionView: replace(previousSuggestionView) }); }, /** * Updates the textarea height of text input. @@ -759,33 +759,6 @@ registerModel({ } } }, - /** - * Clears the active suggestion on closing mentions or adapts it if - * the active suggestion is no longer part of the suggestions. - * - * @private - * @returns {FieldCommand} - */ - _computeActiveSuggestionView() { - if (!this.composerSuggestionListView) { - return clear(); - } - if ( - this.composerSuggestionListView.mainSuggestionViews.length === 0 && - this.composerSuggestionListView.extraSuggestionViews.length === 0 - ) { - return clear(); - } - if ( - this.composerSuggestionListView.mainSuggestionViews.includes(this.activeSuggestionView) || - this.composerSuggestionListView.extraSuggestionViews.includes(this.activeSuggestionView) - ) { - return; - } - const suggestionViews = this.composerSuggestionListView.mainSuggestionViews.concat(this.composerSuggestionListView.extraSuggestionViews); - const firstSuggestionView = suggestionViews[0]; - return replace(firstSuggestionView); - }, /** * @private * @returns {boolean} @@ -1384,9 +1357,11 @@ registerModel({ extraSuggestedRecords.length = Math.min(extraSuggestedRecords.length, limit - mainSuggestedRecords.length); this.update({ extraSuggestions: replace(extraSuggestedRecords.map(record => record.suggestable)), - hasToScrollToActiveSuggestionView: true, mainSuggestions: replace(mainSuggestedRecords.map(record => record.suggestable)), }); + if (this.composerSuggestionListView) { + this.composerSuggestionListView.update({ hasToScrollToActiveSuggestionView: true }); + } }, /** * @private @@ -1400,15 +1375,6 @@ registerModel({ } }, fields: { - /** - * Determines the suggestion that is currently active. This suggestion - * is highlighted in the UI and it will be selected when the - * suggestion is confirmed by the user. - */ - activeSuggestionView: one('ComposerSuggestionView', { - compute: '_computeActiveSuggestionView', - inverse: 'composerViewOwnerAsActiveSuggestionView', - }), /** * Determines the attachment list that will be used to display the attachments. */ @@ -1548,13 +1514,6 @@ registerModel({ hasToRestoreContent: attr({ default: false, }), - /** - * Determines whether the currently active suggestion should be scrolled - * into view. - */ - hasToScrollToActiveSuggestionView: attr({ - default: false, - }), isCompact: attr({ compute: '_computeIsCompact', default: true,