[IMP] mail, *: move code from components to models (ThreadTypingIcon)
*: im_livechat Task-3004018. Part-of: odoo/odoo#103317
This commit is contained in:
committed by
Alexandre Kühn
parent
2ae8ad027c
commit
2e2700e69e
@@ -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'">
|
||||
|
||||
+2
-2
@@ -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();
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user