mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 03:57:52 +00:00
chore: Update message bubble orientation (#11348)
# Pull Request Template ## Description This PR includes, ### Changes 1. **Message Orientation**: - Updated the bubble orientation of Bot, Agent, and Private Note messages to align from **left** to **right**. 2. **Activity Message bubble Styling**: - Adjusted **padding** and **border-radius** for activity message bubbles for better alignment and appearance. | **Before** | **After** | | ------------- | ------------- | | <img width="559" alt="image" src="https://github.com/user-attachments/assets/18258ae0-0d8e-4447-a005-9b6643b71f81" /> | <img width="559" alt="image" src="https://github.com/user-attachments/assets/425785d8-17f9-4629-8301-f19f23aef201" /> | --- Fixes [CW-4263](https://linear.app/chatwoot/issue/CW-4263/v410-messages-history-incoming-and-outgoing-renders-in-one-line), https://github.com/chatwoot/chatwoot/issues/11340 ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/117bbb1dda98451883c9bb17f7cf016b?sid=05eae4d4-af11-4a41-a1d6-dc4e7e2cb281 ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
@@ -117,7 +117,7 @@ const props = defineProps({
|
||||
},
|
||||
conversationId: { type: Number, required: true },
|
||||
createdAt: { type: Number, required: true }, // eslint-disable-line vue/no-unused-properties
|
||||
currentUserId: { type: Number, required: true },
|
||||
currentUserId: { type: Number, required: true }, // eslint-disable-line vue/no-unused-properties
|
||||
groupWithNext: { type: Boolean, default: false },
|
||||
inboxId: { type: Number, default: null }, // eslint-disable-line vue/no-unused-properties
|
||||
inboxSupportsReplyTo: { type: Object, default: () => ({}) },
|
||||
@@ -173,7 +173,10 @@ const variant = computed(() => {
|
||||
return variants[props.messageType] || MESSAGE_VARIANTS.USER;
|
||||
});
|
||||
|
||||
const isMyMessage = computed(() => {
|
||||
const isBotOrAgentMessage = computed(() => {
|
||||
if (props.messageType === MESSAGE_TYPES.ACTIVITY) {
|
||||
return false;
|
||||
}
|
||||
// if an outgoing message is still processing, then it's definitely a
|
||||
// message sent by the current user
|
||||
if (
|
||||
@@ -186,13 +189,10 @@ const isMyMessage = computed(() => {
|
||||
const senderType = props.senderType ?? props.sender?.type;
|
||||
|
||||
if (!senderType || !senderId) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
senderType.toLowerCase() === SENDER_TYPES.USER.toLowerCase() &&
|
||||
props.currentUserId === senderId
|
||||
);
|
||||
return senderType.toLowerCase() === SENDER_TYPES.USER.toLowerCase();
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -200,7 +200,7 @@ const isMyMessage = computed(() => {
|
||||
* @returns {import('vue').ComputedRef<'left'|'right'|'center'>} The computed orientation
|
||||
*/
|
||||
const orientation = computed(() => {
|
||||
if (isMyMessage.value) {
|
||||
if (isBotOrAgentMessage.value) {
|
||||
return ORIENTATION.RIGHT;
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ const flexOrientationClass = computed(() => {
|
||||
|
||||
const gridClass = computed(() => {
|
||||
const map = {
|
||||
[ORIENTATION.LEFT]: 'grid grid-cols-[24px_1fr]',
|
||||
[ORIENTATION.RIGHT]: 'grid grid-cols-1fr',
|
||||
[ORIENTATION.LEFT]: 'grid grid-cols-1fr',
|
||||
[ORIENTATION.RIGHT]: 'grid grid-cols-[1fr_24px]',
|
||||
};
|
||||
|
||||
return map[orientation.value];
|
||||
@@ -231,13 +231,13 @@ const gridClass = computed(() => {
|
||||
const gridTemplate = computed(() => {
|
||||
const map = {
|
||||
[ORIENTATION.LEFT]: `
|
||||
"avatar bubble"
|
||||
"spacer meta"
|
||||
`,
|
||||
[ORIENTATION.RIGHT]: `
|
||||
"bubble"
|
||||
"meta"
|
||||
`,
|
||||
[ORIENTATION.RIGHT]: `
|
||||
"bubble avatar"
|
||||
"meta spacer"
|
||||
`,
|
||||
};
|
||||
|
||||
return map[orientation.value];
|
||||
@@ -251,7 +251,7 @@ const shouldGroupWithNext = computed(() => {
|
||||
|
||||
const shouldShowAvatar = computed(() => {
|
||||
if (props.messageType === MESSAGE_TYPES.ACTIVITY) return false;
|
||||
if (orientation.value === ORIENTATION.RIGHT) return false;
|
||||
if (orientation.value === ORIENTATION.LEFT) return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
@@ -444,7 +444,7 @@ provideMessageContext({
|
||||
isPrivate: computed(() => props.private),
|
||||
variant,
|
||||
orientation,
|
||||
isMyMessage,
|
||||
isBotOrAgentMessage,
|
||||
shouldGroupWithNext,
|
||||
});
|
||||
</script>
|
||||
@@ -476,14 +476,14 @@ provideMessageContext({
|
||||
'w-full': variant === MESSAGE_VARIANTS.EMAIL,
|
||||
},
|
||||
]"
|
||||
class="gap-x-3"
|
||||
class="gap-x-2"
|
||||
:style="{
|
||||
gridTemplateAreas: gridTemplate,
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-if="!shouldGroupWithNext && shouldShowAvatar"
|
||||
v-tooltip.right-end="avatarTooltip"
|
||||
v-tooltip.left-end="avatarTooltip"
|
||||
class="[grid-area:avatar] flex items-end"
|
||||
>
|
||||
<Avatar v-bind="avatarInfo" :size="24" />
|
||||
@@ -491,7 +491,8 @@ provideMessageContext({
|
||||
<div
|
||||
class="[grid-area:bubble] flex"
|
||||
:class="{
|
||||
'ltr:pl-9 rtl:pl-0 justify-end': orientation === ORIENTATION.RIGHT,
|
||||
'ltr:pl-8 rtl:pr-8 justify-end': orientation === ORIENTATION.RIGHT,
|
||||
'ltr:pr-8 rtl:pl-8': orientation === ORIENTATION.LEFT,
|
||||
'min-w-0': variant === MESSAGE_VARIANTS.EMAIL,
|
||||
}"
|
||||
@contextmenu="openContextMenu($event)"
|
||||
|
||||
@@ -14,7 +14,7 @@ const readableTime = computed(() =>
|
||||
<template>
|
||||
<BaseBubble
|
||||
v-tooltip.top="readableTime"
|
||||
class="px-2 py-0.5 !rounded-full flex min-w-0 items-center gap-2"
|
||||
class="px-3 py-1 !rounded-xl flex min-w-0 items-center gap-2"
|
||||
data-bubble-name="activity"
|
||||
>
|
||||
<span v-dompurify-html="content" :title="content" />
|
||||
|
||||
@@ -98,7 +98,7 @@ const MessageControl = Symbol('MessageControl');
|
||||
* @property {import('vue').Ref<Sender|null>} [sender=null] - The sender information
|
||||
* @property {import('vue').ComputedRef<MessageOrientation>} orientation - The visual variant of the message
|
||||
* @property {import('vue').ComputedRef<MessageVariant>} variant - The visual variant of the message
|
||||
* @property {import('vue').ComputedRef<boolean>} isMyMessage - Does the message belong to the current user
|
||||
* @property {import('vue').ComputedRef<boolean>} isBotOrAgentMessage - Does the message belong to the current user
|
||||
* @property {import('vue').ComputedRef<boolean>} isPrivate - Proxy computed value for private
|
||||
* @property {import('vue').ComputedRef<boolean>} shouldGroupWithNext - Should group with the next message or not, it is differnt from groupWithNext, this has a bypass for a failed message
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user