perf: keep-alive inbox layout to skip refetch on admin round-trip

This commit is contained in:
Abhinav Raut
2026-05-26 03:00:02 +05:30
parent e5ffe11394
commit cd8eb5ee26
3 changed files with 35 additions and 63 deletions
+6 -2
View File
@@ -112,7 +112,11 @@
<PageHeader />
<!-- Main content -->
<RouterView class="flex-grow" />
<RouterView v-slot="{ Component }">
<keep-alive include="InboxLayout">
<component :is="Component" class="flex-grow" />
</keep-alive>
</RouterView>
</div>
<ViewForm v-model:openDialog="openCreateViewForm" v-model:view="view" />
</Sidebar>
@@ -191,7 +195,7 @@ watch(
() => route.path,
(path) => {
if (path.startsWith('/inboxes') && path !== '/inboxes/search') {
lastInboxPath.value = path.replace(/\/conversation\/[^/]+$/, '')
lastInboxPath.value = path
}
}
)
@@ -6,11 +6,7 @@
@layout="onLayoutChange"
>
<!-- Conversation List Panel -->
<ResizablePanel
:default-size="panelSizes[0]"
:min-size="20"
:max-size="45"
>
<ResizablePanel :default-size="panelSizes[0]" :min-size="20" :max-size="45">
<ConversationList />
</ResizablePanel>
@@ -19,7 +15,9 @@
<!-- Conversation Detail Panel -->
<ResizablePanel :default-size="panelSizes[1]" :min-size="30">
<router-view v-slot="{ Component }">
<component :is="Component" />
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</ResizablePanel>
</ResizablePanelGroup>
@@ -36,6 +34,8 @@ import {
ResizableHandle
} from '@shared-ui/components/ui/resizable'
defineOptions({ name: 'InboxLayout' })
const route = useRoute()
const isSearchRoute = computed(() => route.name === 'search')
@@ -18,37 +18,33 @@ const viewID = computed(() => route.params.viewID)
const conversationStore = useConversationStore()
// Init conversations list based on route params
onMounted(() => {
// Fetch list based on type
if (type.value) {
// Set list status if not already set
if (!conversationStore.getListStatus) {
conversationStore.setListStatus(CONVERSATION_DEFAULT_STATUSES.OPEN, false)
}
conversationStore.fetchConversationsList(true, type.value)
}
// Fetch team list.
if (teamID.value) {
// Set list status if not already set
if (!conversationStore.getListStatus) {
conversationStore.setListStatus(CONVERSATION_DEFAULT_STATUSES.OPEN, false)
}
conversationStore.fetchConversationsList(
true,
CONVERSATION_LIST_TYPE.TEAM_UNASSIGNED,
teamID.value
)
}
// Fetch view list.
let lastFetchedKey = ''
const fetchForCurrentRoute = () => {
if (!type.value && !teamID.value && !viewID.value) return
const key = `${type.value || ''}|${teamID.value || ''}|${viewID.value || ''}`
if (key === lastFetchedKey) return
lastFetchedKey = key
if (viewID.value) {
// Empty out list status as views are already filtered.
conversationStore.setListStatus('', false)
conversationStore.fetchConversationsList(true, CONVERSATION_LIST_TYPE.VIEW, 0, [], viewID.value)
return
}
})
// Drift recovery for missed WS updates; paused while tab is hidden.
if (!conversationStore.getListStatus) {
conversationStore.setListStatus(CONVERSATION_DEFAULT_STATUSES.OPEN, false)
}
if (type.value) {
conversationStore.fetchConversationsList(true, type.value)
} else {
conversationStore.fetchConversationsList(true, CONVERSATION_LIST_TYPE.TEAM_UNASSIGNED, teamID.value)
}
}
onMounted(fetchForCurrentRoute)
const visibility = useDocumentVisibility()
const { pause, resume } = useIntervalFn(
() => conversationStore.refreshConversationList(),
@@ -63,33 +59,5 @@ watch(visibility, v => {
}
})
// Refetch when route params change
watch(
[type, teamID, viewID],
([newType, newTeamID, newViewID], [oldType, oldTeamID, oldViewID]) => {
if (newType !== oldType && newType) {
// Set list status if not already set
if (!conversationStore.getListStatus) {
conversationStore.setListStatus(CONVERSATION_DEFAULT_STATUSES.OPEN, false)
}
conversationStore.fetchConversationsList(true, newType)
}
if (newTeamID !== oldTeamID && newTeamID) {
// Set list status if not already set
if (!conversationStore.getListStatus) {
conversationStore.setListStatus(CONVERSATION_DEFAULT_STATUSES.OPEN, false)
}
conversationStore.fetchConversationsList(
true,
CONVERSATION_LIST_TYPE.TEAM_UNASSIGNED,
newTeamID
)
}
if (newViewID !== oldViewID && newViewID) {
// Empty out list status as views are already filtered.
conversationStore.setListStatus('', false)
conversationStore.fetchConversationsList(true, CONVERSATION_LIST_TYPE.VIEW, 0, [], newViewID)
}
}
)
watch([type, teamID, viewID], fetchForCurrentRoute)
</script>