[IMP] mail, *: move code from components to models (ThreadTypingIcon)

*: im_livechat

Task-3004018.

Part-of: odoo/odoo#103317
This commit is contained in:
Louis Wicket (wil)
2022-10-17 18:11:20 +02:00
committed by Alexandre Kühn
parent 2ae8ad027c
commit 2e2700e69e
10 changed files with 110 additions and 83 deletions
@@ -3,11 +3,10 @@
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
<xpath expr="//*[@name='root']" position="inside">
<t t-elif="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'livechat'">
<t t-if="threadIconView.thread.orderedOtherTypingMembers.length > 0">
<t t-if="threadIconView.threadTypingIconView">
<ThreadTypingIcon
className="'o_ThreadIcon_typing'"
animation="'pulse'"
title="threadIconView.thread.typingStatusText"
record="threadIconView.threadTypingIconView"
/>
</t>
<t t-else="">
@@ -0,0 +1,21 @@
/** @odoo-module **/
import { registerPatch } from '@mail/model/model_core';
registerPatch({
name: 'ThreadIconView',
fields: {
threadTypingIconView: {
compute() {
if (
this.thread.channel &&
this.thread.channel.channel_type === 'livechat' &&
this.thread.orderedOtherTypingMembers.length > 0
) {
return {};
}
return this._super();
},
},
},
});
@@ -13,11 +13,10 @@
</t>
</t>
<t t-elif="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'chat' and threadIconView.thread.channel.correspondent">
<t t-if="threadIconView.thread.orderedOtherTypingMembers.length > 0">
<t t-if="threadIconView.threadTypingIconView">
<ThreadTypingIcon
className="'o_ThreadIcon_typing flex-grow-1'"
animation="'pulse'"
title="threadIconView.thread.typingStatusText"
record="threadIconView.threadTypingIconView"
/>
</t>
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'online'">
@@ -4,8 +4,8 @@
<t t-name="mail.ThreadTextualTypingStatus" owl="1">
<t t-if="threadTextualTypingStatusView">
<div class="o_ThreadTextualTypingStatus d-flex" t-attf-class="{{ className }}" t-ref="root">
<t t-if="threadTextualTypingStatusView.thread.orderedOtherTypingMembers.length > 0">
<ThreadTypingIcon animation="'pulse'" size="'medium'"/>
<t t-if="threadTextualTypingStatusView.threadTypingIconView">
<ThreadTypingIcon record="threadTextualTypingStatusView.threadTypingIconView"/>
<span class="o_ThreadTextualTypingStatus_separator ms-1"/>
<span class="text-truncate" t-esc="threadTextualTypingStatusView.thread.typingStatusText"/>
</t>
@@ -4,29 +4,19 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
export class ThreadTypingIcon extends Component {}
export class ThreadTypingIcon extends Component {
/**
* @returns {ThreadTypingIconView}
*/
get threadTypingIconView() {
return this.props.record;
}
}
Object.assign(ThreadTypingIcon, {
defaultProps: {
animation: 'none',
size: 'small',
},
props: {
animation: {
type: String,
validate: prop => ['bounce', 'none', 'pulse'].includes(prop),
optional: true,
},
size: {
type: String,
validate: prop => ['small', 'medium'].includes(prop),
optional: true,
},
title: {
type: String,
optional: true,
}
},
props: { record: Object },
template: 'mail.ThreadTypingIcon',
});
@@ -26,16 +26,8 @@
// Animation
// ------------------------------------------------------------------
.o_ThreadTypingIcon_dot.o-animationBounce {
// Note: duplicated animation because dependent on size, and current SASS version doesn't support var()
&.o-sizeMedium {
animation: o_ThreadTypingIcon_dot_animationBounce_sizeMedium_animation 1.5s linear infinite;
}
&.o-sizeSmall {
animation: o_ThreadTypingIcon_dot_animationBounce_sizeSmall_animation 1.5s linear infinite;
}
.o_ThreadTypingIcon_dot {
animation: o_ThreadTypingIcon_dot_animation 1.5s linear infinite;
&.o_ThreadTypingIcon_dot2 {
animation-delay: -1.35s;
@@ -46,37 +38,7 @@
}
}
.o_ThreadTypingIcon_dot.o-animationPulse {
animation: o_ThreadTypingIcon_dot_animationPulse_animation 1.5s linear infinite;
&.o_ThreadTypingIcon_dot2 {
animation-delay: -1.35s;
}
&.o_ThreadTypingIcon_dot3 {
animation-delay: -1.2s;
}
}
@keyframes o_ThreadTypingIcon_dot_animationBounce_sizeMedium_animation {
0%, 40%, 100% {
transform: initial;
}
20% {
transform: translateY(-$o-mail-thread-typing-icon-size-medium);
}
}
@keyframes o_ThreadTypingIcon_dot_animationBounce_sizeSmall_animation {
0%, 40%, 100% {
transform: initial;
}
20% {
transform: translateY(-$o-mail-thread-typing-icon-size-small);
}
}
@keyframes o_ThreadTypingIcon_dot_animationPulse_animation {
@keyframes o_ThreadTypingIcon_dot_animation {
0%, 40%, 100% {
opacity: initial;
}
@@ -2,26 +2,20 @@
<templates xml:space="preserve">
<t t-name="mail.ThreadTypingIcon" owl="1">
<div class="o_ThreadTypingIcon d-flex align-items-center" t-attf-class="{{ className }}" t-att-title="props.title" t-ref="root">
<div class="o_ThreadTypingIcon d-flex align-items-center" t-attf-class="{{ className }}" t-att-title="threadTypingIconView.title" t-ref="root">
<span class="o_ThreadTypingIcon_dot o_ThreadTypingIcon_dot1 d-flex flex-shrink-0 rounded-pill bg-500" t-att-class="{
'o-animationBounce': props.animation === 'bounce',
'o-animationPulse': props.animation === 'pulse',
'o-sizeMedium': props.size === 'medium',
'o-sizeSmall': props.size === 'small',
'o-sizeMedium': threadTypingIconView.size === 'medium',
'o-sizeSmall': threadTypingIconView.size === 'small',
}"/>
<span class="o_ThreadTypingIcon_separator flex-grow-1 flex-shrink-0"/>
<span class="o_ThreadTypingIcon_dot o_ThreadTypingIcon_dot2 d-flex flex-shrink-0 rounded-pill bg-500" t-att-class="{
'o-animationBounce': props.animation === 'bounce',
'o-animationPulse': props.animation === 'pulse',
'o-sizeMedium': props.size === 'medium',
'o-sizeSmall': props.size === 'small',
'o-sizeMedium': threadTypingIconView.size === 'medium',
'o-sizeSmall': threadTypingIconView.size === 'small',
}"/>
<span class="o_ThreadTypingIcon_separator flex-grow-1 flex-shrink-0"/>
<span class="o_ThreadTypingIcon_dot o_ThreadTypingIcon_dot3 d-flex flex-shrink-0 rounded-pill bg-500" t-att-class="{
'o-animationBounce': props.animation === 'bounce',
'o-animationPulse': props.animation === 'pulse',
'o-sizeMedium': props.size === 'medium',
'o-sizeSmall': props.size === 'small',
'o-sizeMedium': threadTypingIconView.size === 'medium',
'o-sizeSmall': threadTypingIconView.size === 'small',
}"/>
</div>
</t>
@@ -2,6 +2,7 @@
import { registerModel } from '@mail/model/model_core';
import { one } from '@mail/model/model_field';
import { clear } from '@mail/model/model_field_command';
registerModel({
name: 'ThreadIconView',
@@ -36,6 +37,20 @@ registerModel({
},
required: true,
}),
threadTypingIconView: one('ThreadTypingIconView', {
compute() {
if (
this.thread.channel &&
this.thread.channel.channel_type === 'chat' &&
this.thread.channel.correspondent &&
this.thread.orderedOtherTypingMembers.length > 0
) {
return {};
}
return clear();
},
inverse: 'threadIconViewOwner'
}),
threadViewTopbarOwner: one('ThreadViewTopbar', {
identifying: true,
inverse: 'threadIconView',
@@ -2,6 +2,7 @@
import { registerModel } from '@mail/model/model_core';
import { one } from '@mail/model/model_field';
import { clear } from '@mail/model/model_field_command';
registerModel({
name: 'ThreadTextualTypingStatusView',
@@ -16,5 +17,14 @@ registerModel({
},
required: true,
}),
threadTypingIconView: one('ThreadTypingIconView', {
compute() {
if (this.thread.orderedOtherTypingMembers.length > 0) {
return {};
}
return clear();
},
inverse: 'threadTextualTypingStatusViewOwner',
}),
},
});
@@ -0,0 +1,37 @@
/** @odoo-module **/
import { registerModel } from '@mail/model/model_core';
import { attr, one } from '@mail/model/model_field';
import { clear } from '@mail/model/model_field_command';
registerModel({
name: 'ThreadTypingIconView',
identifyingMode: 'xor',
fields: {
size: attr({
default: 'small',
compute() {
if (this.threadTextualTypingStatusViewOwner) {
return 'medium';
}
return clear();
},
}),
threadIconViewOwner: one('ThreadIconView', {
identifying: true,
inverse: 'threadTypingIconView',
}),
threadTextualTypingStatusViewOwner: one('ThreadTextualTypingStatusView', {
identifying: true,
inverse: 'threadTypingIconView',
}),
title: attr({
compute() {
if (this.threadIconViewOwner) {
return this.threadIconViewOwner.thread.typingStatusText;
}
return clear();
},
}),
},
});