fix: re-rendering of components when shifting from the unread list to the read list (#10835)

Fixes https://github.com/chatwoot/chatwoot/issues/10812

Demo


https://github.com/user-attachments/assets/a0f7eb64-8f6e-4992-a163-c972e85fb205

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
Shivam Mishra
2025-02-07 08:54:25 +05:30
committed by GitHub
parent c3601e16cf
commit be1999e7f8
3 changed files with 28 additions and 40 deletions

View File

@@ -15,18 +15,14 @@ import { useCamelCase } from 'dashboard/composables/useTransformKeys';
* @property {Array} messages - Array of all messages [These are not in camelcase] * @property {Array} messages - Array of all messages [These are not in camelcase]
*/ */
const props = defineProps({ const props = defineProps({
readMessages: {
type: Array,
default: () => [],
},
unReadMessages: {
type: Array,
default: () => [],
},
currentUserId: { currentUserId: {
type: Number, type: Number,
required: true, required: true,
}, },
firstUnreadId: {
type: Number,
default: null,
},
isAnEmailChannel: { isAnEmailChannel: {
type: Boolean, type: Boolean,
default: false, default: false,
@@ -41,12 +37,8 @@ const props = defineProps({
}, },
}); });
const unread = computed(() => { const allMessages = computed(() => {
return useCamelCase(props.unReadMessages, { deep: true }); return useCamelCase(props.messages, { deep: true });
});
const read = computed(() => {
return useCamelCase(props.readMessages, { deep: true });
}); });
/** /**
@@ -108,26 +100,18 @@ const getInReplyToMessage = parentMessage => {
<template> <template>
<ul class="px-4 bg-n-background"> <ul class="px-4 bg-n-background">
<slot name="beforeAll" /> <slot name="beforeAll" />
<template v-for="(message, index) in read" :key="message.id"> <template v-for="(message, index) in allMessages" :key="message.id">
<Message <slot
v-bind="message" v-if="firstUnreadId && message.id === firstUnreadId"
:is-email-inbox="isAnEmailChannel" name="unreadBadge"
:in-reply-to="getInReplyToMessage(message)"
:group-with-next="shouldGroupWithNext(index, read)"
:inbox-supports-reply-to="inboxSupportsReplyTo"
:current-user-id="currentUserId"
data-clarity-mask="True"
/> />
</template>
<slot name="beforeUnread" />
<template v-for="(message, index) in unread" :key="message.id">
<Message <Message
v-bind="message" v-bind="message"
:is-email-inbox="isAnEmailChannel"
:in-reply-to="getInReplyToMessage(message)" :in-reply-to="getInReplyToMessage(message)"
:group-with-next="shouldGroupWithNext(index, unread)" :group-with-next="shouldGroupWithNext(index, allMessages)"
:inbox-supports-reply-to="inboxSupportsReplyTo" :inbox-supports-reply-to="inboxSupportsReplyTo"
:current-user-id="currentUserId" :current-user-id="currentUserId"
:is-email-inbox="isAnEmailChannel"
data-clarity-mask="True" data-clarity-mask="True"
/> />
</template> </template>

View File

@@ -38,9 +38,10 @@ onMounted(() => {
}); });
const formatTime = time => { const formatTime = time => {
if (!time || Number.isNaN(time)) return '00:00';
const minutes = Math.floor(time / 60); const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60); const seconds = Math.floor(time % 60);
return `${minutes}:${seconds.toString().padStart(2, '0')}`; return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}; };
const toggleMute = () => { const toggleMute = () => {
@@ -49,7 +50,7 @@ const toggleMute = () => {
}; };
const onTimeUpdate = () => { const onTimeUpdate = () => {
currentTime.value = audioPlayer.value.currentTime; currentTime.value = audioPlayer.value?.currentTime;
}; };
const seek = event => { const seek = event => {

View File

@@ -243,6 +243,15 @@ export default {
unreadMessageCount() { unreadMessageCount() {
return this.currentChat.unread_count || 0; return this.currentChat.unread_count || 0;
}, },
unreadMessageLabel() {
const count =
this.unreadMessageCount > 9 ? '9+' : this.unreadMessageCount;
const label =
this.unreadMessageCount > 1
? 'CONVERSATION.UNREAD_MESSAGES'
: 'CONVERSATION.UNREAD_MESSAGE';
return `${count} ${this.$t(label)}`;
},
isInstagramDM() { isInstagramDM() {
return this.conversationType === 'instagram_direct_message'; return this.conversationType === 'instagram_direct_message';
}, },
@@ -492,12 +501,11 @@ export default {
<NextMessageList <NextMessageList
v-if="showNextBubbles" v-if="showNextBubbles"
class="conversation-panel" class="conversation-panel"
:read-messages="readMessages"
:un-read-messages="unReadMessages"
:current-user-id="currentUserId" :current-user-id="currentUserId"
:first-unread-id="unReadMessages[0]?.id"
:is-an-email-channel="isAnEmailChannel" :is-an-email-channel="isAnEmailChannel"
:inbox-supports-reply-to="inboxSupportsReplyTo" :inbox-supports-reply-to="inboxSupportsReplyTo"
:messages="currentChat ? currentChat.messages : []" :messages="getMessages"
> >
<template #beforeAll> <template #beforeAll>
<transition name="slide-up"> <transition name="slide-up">
@@ -507,15 +515,10 @@ export default {
</li> </li>
</transition> </transition>
</template> </template>
<template #beforeUnread> <template #unreadBadge>
<li v-show="unreadMessageCount != 0" class="unread--toast"> <li v-show="unreadMessageCount != 0" class="unread--toast">
<span> <span>
{{ unreadMessageCount > 9 ? '9+' : unreadMessageCount }} {{ unreadMessageLabel }}
{{
unreadMessageCount > 1
? $t('CONVERSATION.UNREAD_MESSAGES')
: $t('CONVERSATION.UNREAD_MESSAGE')
}}
</span> </span>
</li> </li>
</template> </template>