[IMP] mail,snailmail: replace component lifecycle method to hook

In preparation to using OWL v2 in discuss code

Task-2694189

closes odoo/odoo#80033

Related: odoo/enterprise#22354
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Alexandre Kühn
2021-11-19 15:08:30 +00:00
parent ec05e72dcf
commit 2d88871d8e
37 changed files with 163 additions and 135 deletions
@@ -16,8 +16,8 @@ export class Activity extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.state = useState({
areDetailsVisible: false,
});
@@ -3,23 +3,24 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onMounted, useRef } = owl.hooks;
export class ActivityMarkDonePopover extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this._feedbackTextareaRef = useRef('feedbackTextarea');
onMounted(() => this._mounted());
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
mounted() {
_mounted() {
this._feedbackTextareaRef.el.focus();
if (this.activity.feedbackBackup) {
this._feedbackTextareaRef.el.value = this.activity.feedbackBackup;
@@ -6,6 +6,9 @@ const { Component } = owl;
export class AttachmentCard extends Component {
/**
* @override
*/
setup() {
super.setup();
useComponentToModel({ fieldName: 'component', modelName: 'mail.attachment_card', propNameAsRecordLocalId: 'attachmentCardLocalId' });
@@ -12,8 +12,8 @@ export class AttachmentDeleteConfirmDialog extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
// to manually trigger the dialog close event
this._dialogRef = useRef('dialog');
}
@@ -6,6 +6,9 @@ const { Component } = owl;
export class AttachmentImage extends Component {
/**
* @override
*/
setup() {
super.setup();
useComponentToModel({ fieldName: 'component', modelName: 'mail.attachment_image', propNameAsRecordLocalId: 'attachmentImageLocalId' });
@@ -7,7 +7,7 @@ import { link } from '@mail/model/model_field_command';
import { hidePDFJSButtons } from '@web/legacy/js/libs/pdfjs';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onMounted, onPatched, onWillUnmount, useRef } = owl.hooks;
const MIN_SCALE = 0.5;
const SCROLL_ZOOM_STEP = 0.1;
@@ -18,8 +18,8 @@ export class AttachmentViewer extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.MIN_SCALE = MIN_SCALE;
/**
* Used to ensure that the ref is always up to date, which seems to be needed if the element
@@ -51,9 +51,12 @@ export class AttachmentViewer extends Component {
*/
this._translate = { x: 0, y: 0, dx: 0, dy: 0 };
this._onClickGlobal = this._onClickGlobal.bind(this);
onMounted(() => this._mounted());
onPatched(() => this._patched());
onWillUnmount(() => this._willUnmount());
}
mounted() {
_mounted() {
this.el.focus();
this._handleImageLoad();
this._hideUnwantedPdfJsButtons();
@@ -63,12 +66,12 @@ export class AttachmentViewer extends Component {
/**
* When a new image is displayed, show a spinner until it is loaded.
*/
patched() {
_patched() {
this._handleImageLoad();
this._hideUnwantedPdfJsButtons();
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickGlobal);
}
@@ -3,10 +3,20 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { onMounted, onWillUnmount } = owl.hooks;
export class AutocompleteInput extends Component {
mounted() {
/**
* @override
*/
setup() {
super.setup();
onMounted(() => this._mounted());
onWillUnmount(() => this._willUnmount());
}
_mounted() {
if (this.props.isFocusOnMount) {
this.el.focus();
}
@@ -32,7 +42,7 @@ export class AutocompleteInput extends Component {
};
}
willUnmount() {
_willUnmount() {
$(this.el).autocomplete('destroy');
}
@@ -12,8 +12,8 @@ export class ChatWindow extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
useUpdate({ func: () => this._update() });
/**
* Reference of the header of the chat window.
@@ -34,14 +34,8 @@ export class ChatWindow extends Component {
// the following are passed as props to children
this._onAutocompleteSelect = this._onAutocompleteSelect.bind(this);
this._onAutocompleteSource = this._onAutocompleteSource.bind(this);
this._constructor(...args);
}
/**
* Allows patching constructor.
*/
_constructor() {}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
@@ -3,15 +3,15 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onMounted, onPatched, onWillUnmount, useRef } = owl.hooks;
export class ChatWindowHiddenMenu extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this);
/**
* Reference of the dropup list. Useful to auto-set max height based on
@@ -22,18 +22,21 @@ export class ChatWindowHiddenMenu extends Component {
* The intent of the toggle button depends on the last rendered state.
*/
this._wasMenuOpen;
onMounted(() => this._mounted());
onPatched(() => this._patched());
onWillUnmount(() => this._willUnmount());
}
mounted() {
_mounted() {
this._apply();
document.addEventListener('click', this._onClickCaptureGlobal, true);
}
patched() {
_patched() {
this._apply();
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickCaptureGlobal, true);
}
@@ -12,8 +12,8 @@ export class Chatter extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
useUpdate({ func: () => this._update() });
useRefToModel({ fieldName: 'threadRef', modelName: 'mail.chatter', propNameAsRecordLocalId: 'chatterLocalId', refName: 'thread' });
/**
@@ -4,6 +4,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
import { clear } from '@mail/model/model_field_command';
const { Component } = owl;
const { onWillUpdateProps } = owl.hooks;
const getChatterNextTemporaryId = (function () {
let tmpId = 0;
@@ -26,19 +27,16 @@ export class ChatterContainer extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.chatter = undefined;
this.chatterId = getChatterNextTemporaryId();
this._insertFromProps(this.props);
onWillUpdateProps(nextProps => this._willUpdateProps(nextProps));
}
/**
* @override
*/
willUpdateProps(nextProps) {
_willUpdateProps(nextProps) {
this._insertFromProps(nextProps);
return super.willUpdateProps(...arguments);
}
/**
@@ -8,15 +8,15 @@ import {
} from '@mail/utils/utils';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onMounted, onWillUnmount, useRef } = owl.hooks;
export class Composer extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.isDropZoneVisible = useDragVisibleDropZone();
/**
* Reference of the emoji popover. Useful to include emoji popover as
@@ -34,13 +34,15 @@ export class Composer extends Component {
*/
this._textInputRef = useRef('textInput');
this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this);
onMounted(() => this._mounted());
onWillUnmount(() => this._willUnmount());
}
mounted() {
_mounted() {
document.addEventListener('click', this._onClickCaptureGlobal, true);
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickCaptureGlobal, true);
}
@@ -22,8 +22,11 @@ class FormViewDialogComponentAdapter extends ComponentAdapter {
export class ComposerSuggestedRecipient extends Component {
constructor(...args) {
super(...args);
/**
* @override
*/
setup() {
super.setup();
this.id = _.uniqueId('o_ComposerSuggestedRecipient_');
useUpdate({ func: () => this._update() });
/**
@@ -10,8 +10,8 @@ export class ComposerSuggestedRecipientList extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.state = useState({
hasShowMoreButton: false,
});
@@ -11,8 +11,8 @@ export class ComposerSuggestion extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
useUpdate({ func: () => this._update() });
}
@@ -12,8 +12,8 @@ export class ComposerTextInput extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* Updates the composer text input content when composer is mounted
* as textarea content can't be changed from the DOM.
@@ -3,35 +3,31 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onMounted, onWillUnmount, useRef } = owl.hooks;
export class Dialog extends Component {
/**
* @param {...any} args
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* Reference to the component used inside this dialog.
*/
this._componentRef = useRef('component');
this._onClickGlobal = this._onClickGlobal.bind(this);
this._onKeydownDocument = this._onKeydownDocument.bind(this);
this._constructor();
onMounted(() => this._mounted());
onWillUnmount(() => this._willUnmount());
}
/**
* Allows patching constructor.
*/
_constructor() {}
mounted() {
_mounted() {
document.addEventListener('click', this._onClickGlobal, true);
document.addEventListener('keydown', this._onKeydownDocument);
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickGlobal, true);
document.removeEventListener('keydown', this._onKeydownDocument);
}
@@ -3,14 +3,24 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { onMounted, onPatched } = owl.hooks;
export class DialogManager extends Component {
mounted() {
/**
* @override
*/
setup() {
super.setup();
onMounted(() => this._mounted());
onPatched(() => this._patched());
}
_mounted() {
this._checkDialogOpen();
}
patched() {
_patched() {
this._checkDialogOpen();
}
@@ -5,18 +5,21 @@ import { link, unlink } from '@mail/model/model_field_command';
import { useUpdate } from '@mail/component_hooks/use_update/use_update';
const { Component } = owl;
const { onWillUnmount } = owl.hooks;
export class Discuss extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this._updateLocalStoreProps();
// bind since passed as props
this._onMobileAddItemHeaderInputSelect = this._onMobileAddItemHeaderInputSelect.bind(this);
this._onMobileAddItemHeaderInputSource = this._onMobileAddItemHeaderInputSource.bind(this);
useUpdate({ func: () => this._update() });
onWillUnmount(() => this._willUnmount());
}
_update() {
@@ -42,7 +45,7 @@ export class Discuss extends Component {
this._updateLocalStoreProps();
}
willUnmount() {
_willUnmount() {
if (this.discuss) {
this.discuss.close();
}
@@ -12,8 +12,8 @@ export class DiscussSidebar extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
useUpdate({ func: () => this._update() });
useRefToModel({ fieldName: 'startAMeetingButtonRef', modelName: 'mail.discuss', propNameAsRecordLocalId: 'localId', refName: 'startAMeetingButton' });
/**
@@ -9,8 +9,8 @@ export class DropZone extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.state = useState({
/**
* Determine whether the user is dragging files over the dropzone.
@@ -9,10 +9,10 @@ const { Component } = owl;
export class EmojisPopover extends Component {
/**
* @param {...any} args
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.emojis = emojis;
useUpdate({ func: () => this._update() });
}
@@ -21,8 +21,8 @@ export class FileUploader extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this._fileInputRef = useRef('fileInput');
this._fileUploadId = _.uniqueId('o_FileUploader_fileupload');
}
@@ -6,11 +6,12 @@ const { Component } = owl;
const { useState } = owl.hooks;
export class FollowButton extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.state = useState({
/**
* Determine whether the unfollow button is highlighted or not.
@@ -3,14 +3,15 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { useRef, useState } = owl.hooks;
const { onMounted, onWillUnmount, useRef, useState } = owl.hooks;
export class FollowerListMenu extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
this.state = useState({
/**
* Determine whether the dropdown is open or not.
@@ -19,13 +20,15 @@ export class FollowerListMenu extends Component {
});
this._dropdownRef = useRef('dropdown');
this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this);
onMounted(() => this._mounted());
onWillUnmount(() => this._willUnmount());
}
mounted() {
_mounted() {
document.addEventListener('click', this._onClickCaptureGlobal, true);
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickCaptureGlobal, true);
}
@@ -10,7 +10,7 @@ import { format } from 'web.field_utils';
import { getLangDatetimeFormat } from 'web.time';
const { Component, useState } = owl;
const { useRef } = owl.hooks;
const { onWillUnmount, useRef } = owl.hooks;
const READ_MORE = _lt("read more");
const READ_LESS = _lt("read less");
@@ -20,8 +20,9 @@ export class Message extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
useComponentToModel({ fieldName: 'component', modelName: 'mail.message_view', propNameAsRecordLocalId: 'messageViewLocalId' });
this.state = useState({
/**
* Determine whether the message is hovered. When message is hovered
@@ -58,23 +59,10 @@ export class Message extends Component {
* regular time.
*/
this._intervalId = undefined;
this._constructor();
onWillUnmount(() => this._willUnmount());
}
/**
* Allows patching constructor.
*/
_constructor() {}
/**
* @override
*/
setup() {
super.setup();
useComponentToModel({ fieldName: 'component', modelName: 'mail.message_view', propNameAsRecordLocalId: 'messageViewLocalId' });
}
willUnmount() {
_willUnmount() {
clearInterval(this._intervalId);
}
@@ -7,6 +7,9 @@ const { Component } = owl;
export class MessageActionList extends Component {
/**
* @override
*/
setup() {
super.setup();
useRefToModel({ fieldName: 'reactionPopoverRef', modelName: 'mail.message_action_list', propNameAsRecordLocalId: 'messageActionListLocalId', refName: 'reactionPopover' });
@@ -5,7 +5,7 @@ import { useRenderedValues } from '@mail/component_hooks/use_rendered_values/use
import { useUpdate } from '@mail/component_hooks/use_update/use_update';
const { Component } = owl;
const { useRef } = owl.hooks;
const { onWillPatch, useRef } = owl.hooks;
export class MessageList extends Component {
@@ -58,9 +58,10 @@ export class MessageList extends Component {
// use onMounted/onPatched, and the calls from useRenderedValues must
// happen first to save the values before useUpdate accesses them.
useUpdate({ func: () => this._update() });
onWillPatch(() => this._willPatch());
}
willPatch() {
_willPatch() {
this._willPatchSnapshot = {
scrollHeight: this._getScrollableElement().scrollHeight,
scrollTop: this._getScrollableElement().scrollTop,
@@ -3,14 +3,15 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { onMounted, onWillUnmount } = owl.hooks;
export class MessagingMenu extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* global JS generated ID for this component. Useful to provide a
* custom class to autocomplete input, so that click in an autocomplete
@@ -22,29 +23,18 @@ export class MessagingMenu extends Component {
this._onMobileNewMessageInputSelect = this._onMobileNewMessageInputSelect.bind(this);
this._onMobileNewMessageInputSource = this._onMobileNewMessageInputSource.bind(this);
this._onClickCaptureGlobal = this._onClickCaptureGlobal.bind(this);
this._constructor(...args);
}
/**
* Allows patching constructor.
*/
_constructor() {}
/**
* @override
*/
setup() {
// for now, the legacy env is needed for internal functions such as
// `useModels` to work
this.env = owl.Component.env;
super.setup();
onMounted(() => this._mounted());
onWillUnmount(() => this._willUnmount());
}
mounted() {
_mounted() {
document.addEventListener('click', this._onClickCaptureGlobal, true);
}
willUnmount() {
_willUnmount() {
document.removeEventListener('click', this._onClickCaptureGlobal, true);
}
@@ -10,8 +10,8 @@ export class NotificationGroup extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* Reference of the "mark as read" button. Useful to disable the
* top-level click handler when clicking on this specific button.
@@ -3,10 +3,19 @@
import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
const { onMounted } = owl.hooks;
export class NotificationList extends Component {
mounted() {
/**
* @override
*/
setup() {
super.setup();
onMounted(() => this._mounted());
}
_mounted() {
this._loadPreviews();
}
@@ -9,6 +9,9 @@ const { Component } = owl;
export class PopoverView extends Component {
/**
* @override
*/
setup() {
super.setup();
useComponentToModel({ fieldName: 'component', modelName: 'mail.popover_view', propNameAsRecordLocalId: 'popoverViewLocalId' });
@@ -5,7 +5,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
import { browser } from "@web/core/browser/browser";
const { Component } = owl;
const { useState } = owl.hooks;
const { onWillStart, useState } = owl.hooks;
export class RtcConfigurationMenu extends Component {
@@ -17,9 +17,10 @@ export class RtcConfigurationMenu extends Component {
this.state = useState({
userDevices: undefined,
});
onWillStart(() => this._willStart());
}
async willStart() {
async _willStart() {
this.state.userDevices = await browser.navigator.mediaDevices.enumerateDevices();
}
@@ -12,8 +12,8 @@ export class ThreadNeedactionPreview extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* Reference of the "mark as read" button. Useful to disable the
* top-level click handler when clicking on this specific button.
@@ -12,8 +12,8 @@ export class ThreadPreview extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
/**
* Reference of the "mark as read" button. Useful to disable the
* top-level click handler when clicking on this specific button.
@@ -10,8 +10,8 @@ patch(Message.prototype, 'snailmail/static/src/components/message/message.js', {
/**
* @override
*/
_constructor() {
this._super(...arguments);
setup() {
this._super();
this.snailmailState = useState({
// Determine if the error dialog is displayed.
hasDialog: false,
@@ -12,8 +12,8 @@ class SnailmailErrorDialog extends Component {
/**
* @override
*/
constructor(...args) {
super(...args);
setup() {
super.setup();
// to manually trigger the dialog close event
this._dialogRef = useRef('dialog');
}