[IMP] mail: move code from components to models (ComposerTextInput)

+ Create ComposerTextInputView model
+ Replace uses of useRef with useRefToModel
+ Replace use of useUpdate with useUpdateToModel
+ Remove dead code (ComposerTextInput._isEmpty)

Task-3001200.

closes odoo/odoo#101707

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Louis Wicket (wil)
2022-10-04 17:01:26 +02:00
parent 35023260ee
commit 9cc35e276d
5 changed files with 77 additions and 77 deletions
@@ -84,7 +84,7 @@
'o-has-current-partner-avatar': composerView.hasCurrentPartnerAvatar,
'rounded-start-3': composerView.isCompact and composerView.hasCurrentPartnerAvatar,
}"
record="composerView"
record="composerView.textInput"
t-key="composerView.localId"
/>
<div class="o_Composer_buttons d-flex align-items-stretch align-self-stretch flex-shrink-0" t-att-class="{ 'o-composer-is-compact': composerView.isCompact, 'h-auto w-100 px-3': !composerView.isCompact, 'o-isDeviceSmall': messaging.device.isSmall, 'o-messaging-in-editing': composerView and composerView.messageViewInEditing, 'border-end': composerView.messageViewInEditing and !composerView.hasCurrentPartnerAvatar }">
@@ -1,7 +1,8 @@
/** @odoo-module **/
import { useComponentToModel } from '@mail/component_hooks/use_component_to_model';
import { useRefToModel } from '@mail/component_hooks/use_ref_to_model';
import { useUpdate } from '@mail/component_hooks/use_update';
import { useUpdateToModel } from '@mail/component_hooks/use_update_to_model';
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
@@ -13,70 +14,23 @@ export class ComposerTextInput extends Component {
*/
setup() {
super.setup();
useComponentToModel({ fieldName: 'component' });
useRefToModel({ fieldName: 'mirroredTextareaRef', refName: 'mirroredTextarea' });
useRefToModel({ fieldName: 'textareaRef', refName: 'textarea' });
/**
* Updates the composer text input content when composer is mounted
* as textarea content can't be changed from the DOM.
*/
useUpdate({ func: () => this._update() });
useUpdateToModel({ methodName: 'onComponentUpdate' });
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* @returns {ComposerView}
* @returns {ComposerTextInputView}
*/
get composerView() {
get composerTextInputView() {
return this.props.record;
}
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Determines whether the textarea is empty or not.
*
* @private
* @returns {boolean}
*/
_isEmpty() {
return this.composerView.textareaRef.el.value === "";
}
/**
* Updates the content and height of a textarea
*
* @private
*/
_update() {
if (!this.root.el) {
return;
}
if (this.composerView.doFocus) {
this.composerView.update({ doFocus: false });
if (this.messaging.device.isSmall) {
this.root.el.scrollIntoView();
}
this.composerView.textareaRef.el.focus();
}
if (this.composerView.hasToRestoreContent) {
this.composerView.textareaRef.el.value = this.composerView.composer.textInputContent;
if (this.composerView.isFocused) {
this.composerView.textareaRef.el.setSelectionRange(
this.composerView.composer.textInputCursorStart,
this.composerView.composer.textInputCursorEnd,
this.composerView.composer.textInputSelectionDirection,
);
}
this.composerView.update({ hasToRestoreContent: false });
}
this.composerView.updateTextInputHeight();
}
}
Object.assign(ComposerTextInput, {
@@ -2,18 +2,18 @@
<templates xml:space="preserve">
<t t-name="mail.ComposerTextInput" owl="1">
<t t-if="composerView">
<div class="o_ComposerTextInput position-relative bg-white" t-attf-class="{{ className }} {{ composerView.isCompact ? 'border border-end-0' : 'border-0' }}" t-att-class="{ 'border-start-0': composerView.isInChatWindow }" t-on-paste="composerView.onPasteTextInput" t-ref="root">
<t t-if="composerView.composerSuggestionListView">
<ComposerSuggestionListView record="composerView.composerSuggestionListView"/>
<t t-if="composerTextInputView">
<div class="o_ComposerTextInput position-relative bg-white" t-attf-class="{{ className }} {{ composerTextInputView.owner.isCompact ? 'border border-end-0' : 'border-0' }}" t-att-class="{ 'border-start-0': composerTextInputView.owner.isInChatWindow }" t-on-paste="composerTextInputView.owner.onPasteTextInput" t-ref="root">
<t t-if="composerTextInputView.owner.composerSuggestionListView">
<ComposerSuggestionListView record="composerTextInputView.owner.composerSuggestionListView"/>
</t>
<textarea class="o_ComposerTextInput_textarea o_ComposerTextInput_textareaStyle form-control px-3 border-0 shadow-none overflow-auto" t-att-class="{ 'o-composer-is-compact rounded-0 rounded-start-3': composerView.isCompact, 'rounded-3': !composerView.isCompact }" t-esc="composerView.composer.textInputContent" t-att-placeholder="composerView.composer.placeholder" t-on-click="composerView.onClickTextarea" t-on-focusin="composerView.onFocusinTextarea" t-on-focusout="composerView.onFocusoutTextarea" t-on-keydown="composerView.onKeydownTextarea" t-on-keyup="composerView.onKeyupTextarea" t-on-input="composerView.onInputTextarea" t-ref="textarea"/>
<textarea class="o_ComposerTextInput_textarea o_ComposerTextInput_textareaStyle form-control px-3 border-0 shadow-none overflow-auto" t-att-class="{ 'o-composer-is-compact rounded-0 rounded-start-3': composerTextInputView.owner.isCompact, 'rounded-3': !composerTextInputView.owner.isCompact }" t-esc="composerTextInputView.owner.composer.textInputContent" t-att-placeholder="composerTextInputView.owner.composer.placeholder" t-on-click="composerTextInputView.owner.onClickTextarea" t-on-focusin="composerTextInputView.owner.onFocusinTextarea" t-on-focusout="composerTextInputView.owner.onFocusoutTextarea" t-on-keydown="composerTextInputView.owner.onKeydownTextarea" t-on-keyup="composerTextInputView.owner.onKeyupTextarea" t-on-input="composerTextInputView.owner.onInputTextarea" t-ref="textarea"/>
<!--
This is an invisible textarea used to compute the composer
height based on the text content. We need it to downsize
the textarea properly without flicker.
-->
<textarea class="o_ComposerTextInput_mirroredTextarea o_ComposerTextInput_textareaStyle position-absolute px-3 border-0 overflow-hidden opacity-0" t-att-class="{ 'o-composer-is-compact rounded-0 rounded-start-3': composerView.isCompact, 'rounded-3': !composerView.isCompact }" t-esc="composerView.composer.textInputContent" t-ref="mirroredTextarea" disabled="1"/>
<textarea class="o_ComposerTextInput_mirroredTextarea o_ComposerTextInput_textareaStyle position-absolute px-3 border-0 overflow-hidden opacity-0" t-att-class="{ 'o-composer-is-compact rounded-0 rounded-start-3': composerTextInputView.owner.isCompact, 'rounded-3': !composerTextInputView.owner.isCompact }" t-esc="composerTextInputView.owner.composer.textInputContent" t-ref="mirroredTextarea" disabled="1"/>
</div>
</t>
</t>
@@ -0,0 +1,52 @@
/** @odoo-module **/
import { registerModel } from '@mail/model/model_core';
import { attr, one } from '@mail/model/model_field';
registerModel({
name: 'ComposerTextInputView',
recordMethods: {
onComponentUpdate() {
if (!this.component.root.el) {
return;
}
if (this.owner.doFocus) {
this.owner.update({ doFocus: false });
if (this.messaging.device.isSmall) {
this.component.root.el.scrollIntoView();
}
this.textareaRef.el.focus();
}
if (this.owner.hasToRestoreContent) {
this.textareaRef.el.value = this.owner.composer.textInputContent;
if (this.owner.isFocused) {
this.textareaRef.el.setSelectionRange(
this.owner.composer.textInputCursorStart,
this.owner.composer.textInputCursorEnd,
this.owner.composer.textInputSelectionDirection,
);
}
this.owner.update({ hasToRestoreContent: false });
}
this.owner.updateTextInputHeight();
},
},
fields: {
component: attr(),
/**
* This is the invisible textarea used to compute the composer height
* based on the text content. We need it to downsize the textarea
* properly without flicker.
*/
mirroredTextareaRef: attr(),
owner: one('ComposerView', {
identifying: true,
inverse: 'textInput',
}),
/**
* Reference of the textarea. Useful to set height, selection and
* content.
*/
textareaRef: attr(),
},
});
+12 -18
View File
@@ -284,10 +284,10 @@ registerModel({
return;
}
this.saveStateInStore();
if (this.textareaLastInputValue !== this.textareaRef.el.value) {
if (this.textareaLastInputValue !== this.textInput.textareaRef.el.value) {
this.handleCurrentPartnerIsTyping();
}
this.update({ textareaLastInputValue: this.textareaRef.el.value });
this.update({ textareaLastInputValue: this.textInput.textareaRef.el.value });
this.updateTextInputHeight();
},
/**
@@ -626,10 +626,10 @@ registerModel({
*/
saveStateInStore() {
this.composer.update({
textInputContent: this.textareaRef.el.value,
textInputCursorEnd: this.textareaRef.el.selectionEnd,
textInputCursorStart: this.textareaRef.el.selectionStart,
textInputSelectionDirection: this.textareaRef.el.selectionDirection,
textInputContent: this.textInput.textareaRef.el.value,
textInputCursorEnd: this.textInput.textareaRef.el.selectionEnd,
textInputCursorStart: this.textInput.textareaRef.el.selectionStart,
textInputSelectionDirection: this.textInput.textareaRef.el.selectionDirection,
});
},
/**
@@ -669,8 +669,8 @@ registerModel({
* Updates the textarea height of text input.
*/
updateTextInputHeight() {
this.mirroredTextareaRef.el.value = this.composer.textInputContent;
this.textareaRef.el.style.height = this.mirroredTextareaRef.el.scrollHeight + 'px';
this.textInput.mirroredTextareaRef.el.value = this.composer.textInputContent;
this.textInput.textareaRef.el.style.height = this.textInput.mirroredTextareaRef.el.scrollHeight + 'px';
},
/**
* Update a posted message when the message is ready.
@@ -1302,12 +1302,6 @@ registerModel({
identifying: true,
inverse: 'composerViewInEditing',
}),
/**
* This is the invisible textarea used to compute the composer height
* based on the text content. We need it to downsize the textarea
* properly without flicker.
*/
mirroredTextareaRef: attr(),
/**
* Determines the next function to execute after the current mention
* RPC is done, if any.
@@ -1426,10 +1420,10 @@ registerModel({
return this.composer.textInputContent.substring(this.suggestionDelimiterPosition + 1, this.composer.textInputCursorStart);
},
}),
/**
* Reference of the textarea. Useful to set height, selection and content.
*/
textareaRef: attr(),
textInput: one('ComposerTextInputView', {
default: {},
inverse: 'owner',
}),
/**
* States the thread view on which this composer allows editing (if any).
*/