fix: Conversation list overlay issue with Virtua virtualizer (#13648)

This commit is contained in:
Sivin Varghese
2026-02-25 20:18:34 +05:30
committed by GitHub
parent b98c614669
commit 5aef9d2dd0
5 changed files with 30 additions and 10 deletions

View File

@@ -955,10 +955,8 @@ watch(conversationFilters, (newVal, oldVal) => {
ref="virtualListRef" ref="virtualListRef"
v-slot="{ item, index }" v-slot="{ item, index }"
:data="conversationList" :data="conversationList"
:overscan="10"
> >
<ConversationItem <ConversationItem
:key="item.id"
:source="item" :source="item"
:label="label" :label="label"
:team-id="teamId" :team-id="teamId"

View File

@@ -50,7 +50,6 @@ export default {
<template> <template>
<ConversationCard <ConversationCard
:key="source.id"
:active-label="label" :active-label="label"
:team-id="teamId" :team-id="teamId"
:folders-id="foldersId" :folders-id="foldersId"

View File

@@ -24,6 +24,10 @@ export default {
type: [String, Date, Number], type: [String, Date, Number],
default: '', default: '',
}, },
conversationId: {
type: [String, Number],
default: '',
},
}, },
data() { data() {
return { return {
@@ -74,6 +78,15 @@ export default {
createdAtTimestamp() { createdAtTimestamp() {
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp); this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
}, },
conversationId() {
// Reset display values and timer when the row is recycled to a different conversation.
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
if (this.isAutoRefreshEnabled) {
clearTimeout(this.timer);
this.createTimer();
}
},
}, },
mounted() { mounted() {
if (this.isAutoRefreshEnabled) { if (this.isAutoRefreshEnabled) {
@@ -111,7 +124,6 @@ export default {
v-tooltip.top="{ v-tooltip.top="{
content: tooltipText, content: tooltipText,
delay: { show: 1000, hide: 0 }, delay: { show: 1000, hide: 0 },
hideOnClick: true,
}" }"
class="ml-auto leading-4 text-xxs text-n-slate-10 hover:text-n-slate-11" class="ml-auto leading-4 text-xxs text-n-slate-10 hover:text-n-slate-11"
> >

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed, ref, watch } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore, useMapGetter } from 'dashboard/composables/store'; import { useStore, useMapGetter } from 'dashboard/composables/store';
import { getLastMessage } from 'dashboard/helper/conversationHelper'; import { getLastMessage } from 'dashboard/helper/conversationHelper';
@@ -50,10 +50,21 @@ const store = useStore();
const hovered = ref(false); const hovered = ref(false);
const showContextMenu = ref(false); const showContextMenu = ref(false);
const contextMenu = ref({ const contextMenu = ref({ x: null, y: null });
x: null,
y: null, // Reset UI state when conversation changes at same index (no :key, instance reused on reorder)
}); // This prevents context menu/hover state from leaking to a different conversation
// Emit contextMenuToggle(false) to sync parent state if menu was open during recycling
const resetState = () => {
if (showContextMenu.value) {
emit('contextMenuToggle', false);
}
hovered.value = false;
showContextMenu.value = false;
contextMenu.value = { x: null, y: null };
};
watch(() => props.chat.id, resetState);
const currentChat = useMapGetter('getSelectedChat'); const currentChat = useMapGetter('getSelectedChat');
const inboxesList = useMapGetter('inboxes/getInboxes'); const inboxesList = useMapGetter('inboxes/getInboxes');
@@ -352,6 +363,7 @@ const deleteConversation = () => {
<TimeAgo <TimeAgo
:last-activity-timestamp="chat.timestamp" :last-activity-timestamp="chat.timestamp"
:created-at-timestamp="chat.created_at" :created-at-timestamp="chat.created_at"
:conversation-id="chat.id"
/> />
</span> </span>
<span <span

View File

@@ -36,7 +36,6 @@ export default {
v-tooltip="{ v-tooltip="{
content: tooltipText, content: tooltipText,
delay: { show: 1500, hide: 0 }, delay: { show: 1500, hide: 0 },
hideOnClick: true,
}" }"
class="shrink-0 rounded-sm inline-flex items-center justify-center w-3.5 h-3.5" class="shrink-0 rounded-sm inline-flex items-center justify-center w-3.5 h-3.5"
:class="{ :class="{