From 2c1a8e59f54e165a5556a2684a962142837a30e1 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Wed, 29 Jan 2025 22:56:08 +0530 Subject: [PATCH] chore: Next bubble improvements (#10759) --- .../dashboard/assets/scss/_woot.scss | 20 +++-- .../components-next/avatar/Avatar.vue | 4 +- .../components-next/message/Message.vue | 50 +++++++---- .../components-next/message/MessageList.vue | 19 ++++- .../message/bubbles/Activity.vue | 2 +- .../components-next/message/bubbles/Base.vue | 6 +- .../message/bubbles/BaseAttachment.vue | 4 +- .../message/bubbles/Email/Index.vue | 9 +- .../message/bubbles/Text/Index.vue | 7 +- .../message/chips/AttachmentChips.vue | 32 +++----- .../message/chips/AttachmentGrid.vue | 82 +++++++++++++++++++ .../components-next/message/chips/Audio.vue | 26 +++++- .../components-next/message/chips/File.vue | 17 +++- .../components-next/message/chips/Image.vue | 35 +++++++- .../components-next/message/chips/Video.vue | 34 +++++++- .../components-next/message/provider.js | 2 +- tailwind.config.js | 3 + theme/colors.js | 2 + 18 files changed, 283 insertions(+), 71 deletions(-) create mode 100644 app/javascript/dashboard/components-next/message/chips/AttachmentGrid.vue diff --git a/app/javascript/dashboard/assets/scss/_woot.scss b/app/javascript/dashboard/assets/scss/_woot.scss index d736d7b5a..29e3c7c60 100644 --- a/app/javascript/dashboard/assets/scss/_woot.scss +++ b/app/javascript/dashboard/assets/scss/_woot.scss @@ -146,17 +146,19 @@ --solid-2: 255 255 255; --solid-3: 255 255 255; --solid-active: 255 255 255; - --solid-amber: 252 232 193; - --solid-blue: 218 236 255; + --solid-amber: 255 228 181; + --solid-blue: 182 216 255; --solid-iris: 230 231 255; + --solid-purple: 202 202 255; + --solid-red: 255 212 219; --alpha-1: 67, 67, 67, 0.06; - --alpha-2: 201, 202, 207, 0.15; + --alpha-2: 196, 197, 198, 0.22; --alpha-3: 255, 255, 255, 0.96; - --black-alpha-1: 0, 0, 0, 0.12; + --black-alpha-1: 0, 0, 0, 0.08; --black-alpha-2: 0, 0, 0, 0.04; --border-blue: 39, 129, 246, 0.5; - --white-alpha: 255, 255, 255, 0.8; + --white-alpha: 255, 255, 255, 0.84; } .dark { @@ -240,16 +242,18 @@ --gray-12: 238 238 238; --background-color: 18 18 19; + --text-blue: 126 182 255; --border-strong: 52 52 52; --border-weak: 38 38 42; --solid-1: 23 23 26; --solid-2: 29 30 36; --solid-3: 44 45 54; --solid-active: 53 57 66; - --solid-amber: 42 37 30; - --solid-blue: 16 49 91; + --solid-amber: 56 50 41; + --solid-blue: 4 51 101; --solid-iris: 38 42 101; - --text-blue: 126 182 255; + --solid-purple: 51 51 107; + --solid-red: 78 46 55; --alpha-1: 36, 36, 36, 0.8; --alpha-2: 139, 147, 182, 0.15; diff --git a/app/javascript/dashboard/components-next/avatar/Avatar.vue b/app/javascript/dashboard/components-next/avatar/Avatar.vue index 65859b1c7..3cf6d3c88 100644 --- a/app/javascript/dashboard/components-next/avatar/Avatar.vue +++ b/app/javascript/dashboard/components-next/avatar/Avatar.vue @@ -50,16 +50,16 @@ const AVATAR_COLORS = { dark: [ ['#4B143D', '#FF8DCC'], ['#3F220D', '#FFA366'], - ['#2A2A2A', '#ADB1B8'], ['#023B37', '#0BD8B6'], + ['#2A2A2A', '#ADB1B8'], ['#27264D', '#A19EFF'], ['#1D2E62', '#9EB1FF'], ], light: [ ['#FBDCEF', '#C2298A'], ['#FFE0BB', '#99543A'], - ['#E8E8E8', '#60646C'], ['#CCF3EA', '#008573'], + ['#E8E8E8', '#60646C'], ['#EBEBFE', '#4747C2'], ['#E1E9FF', '#3A5BC7'], ], diff --git a/app/javascript/dashboard/components-next/message/Message.vue b/app/javascript/dashboard/components-next/message/Message.vue index df0602a49..150c57f85 100644 --- a/app/javascript/dashboard/components-next/message/Message.vue +++ b/app/javascript/dashboard/components-next/message/Message.vue @@ -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,11 @@ 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 ( @@ -182,17 +186,15 @@ const isMyMessage = computed(() => { ) { return true; } + const senderId = props.senderId ?? props.sender?.id; 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 +202,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 +223,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 +233,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 +253,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; }); @@ -414,6 +416,11 @@ const avatarInfo = computed(() => { }; }); +const avatarTooltip = computed(() => { + if (avatarInfo.value.name === '') return ''; + return `${t('CONVERSATION.SENT_BY')} ${avatarInfo.value.name}`; +}); + const setupHighlightTimer = () => { if (Number(route.query.messageId) !== Number(props.id)) { return; @@ -433,7 +440,7 @@ provideMessageContext({ isPrivate: computed(() => props.private), variant, orientation, - isMyMessage, + isBotOrAgentMessage, shouldGroupWithNext, }); @@ -443,7 +450,7 @@ provideMessageContext({
@@ -479,7 +487,13 @@ provideMessageContext({
{ nextMessageType === MESSAGE_TYPES.TEMPLATE && currentMessageType === MESSAGE_TYPES.TEMPLATE; - if (!hasSameSender || areBothTemplates) return false; + const areBothActivity = + nextMessageType === MESSAGE_TYPES.ACTIVITY && + currentMessageType === MESSAGE_TYPES.ACTIVITY; + + if (!hasSameSender || areBothTemplates || areBothActivity) return false; if (currentMessageType !== nextMessageType) return false; @@ -103,6 +107,17 @@ const getInReplyToMessage = parentMessage => { return replyMessage ? useCamelCase(replyMessage) : null; }; + +const getMessageSpacingClass = (message, messages, index) => { + // For non-activity messages, use groupWithNext logic + if (message.messageType !== MESSAGE_TYPES.ACTIVITY) { + return shouldGroupWithNext(index, messages) ? 'mb-1' : 'mb-6'; + } + + // For activity messages, check next message exists and is also an activity + const nextMessage = messages[index + 1]; + return nextMessage?.messageType === MESSAGE_TYPES.ACTIVITY ? 'mb-2' : 'mb-6'; +}; @@ -128,6 +144,7 @@ const getInReplyToMessage = parentMessage => { :inbox-supports-reply-to="inboxSupportsReplyTo" :current-user-id="currentUserId" :is-email-inbox="isAnEmailChannel" + :class="getMessageSpacingClass(message, unread, index)" data-clarity-mask="True" /> diff --git a/app/javascript/dashboard/components-next/message/bubbles/Activity.vue b/app/javascript/dashboard/components-next/message/bubbles/Activity.vue index d52286543..4e9300711 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Activity.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Activity.vue @@ -14,7 +14,7 @@ const readableTime = computed(() => diff --git a/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue b/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue index 1a7997f50..439c892dc 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Text/Index.vue @@ -20,12 +20,15 @@ const isEmpty = computed(() => {