From 63ba824a8688323bc5c294f0650aef5b515de035 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 3 Jul 2026 09:52:12 -0400 Subject: [PATCH 1/2] perf: make mailbox prefetch selection more selective Signed-off-by: Josh --- src/components/Mailbox.vue | 81 +++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue index 01c957e455..8dd4207880 100644 --- a/src/components/Mailbox.vue +++ b/src/components/Mailbox.vue @@ -67,6 +67,10 @@ import useMainStore from '../store/mainStore.js' import { mailboxHasRights } from '../util/acl.js' import { wait } from '../util/wait.js' +const ALWAYS_VISIBLE_SPECIAL_ROLES = ['draft', 'sent', 'trash'] +const MAX_PREFETCH_MAILBOXES = 5 +const MAX_ALWAYS_VISIBLE_PREFETCH = 3 + export default { name: 'Mailbox', components: { @@ -319,16 +323,81 @@ export default { } }, - async prefetchOtherMailboxes() { - for (const mailbox of this.mainStore.getRecursiveMailboxIterator(this.account.id)) { - if (mailbox.databaseId === this.mailbox.databaseId) { - continue + isAlwaysVisiblePrefetchCandidate(mailbox) { + return ALWAYS_VISIBLE_SPECIAL_ROLES.includes(mailbox.specialRole) + }, + + isTopLevelMailbox(mailbox) { + return mailbox.path === '' || mailbox.path === this.account.personalNamespace + }, + + getMailboxDisplayName(mailbox) { + return mailbox.displayName ?? mailbox.name ?? '' + }, + + sortMailboxesByDisplayName(mailboxes) { + return [...mailboxes].sort((a, b) => { + return this.getMailboxDisplayName(a).localeCompare(this.getMailboxDisplayName(b)) + }) + }, + + getMailboxesToPrefetch() { + const subscribedMailboxes = [...this.mainStore.getRecursiveMailboxIterator(this.account.id)] + .filter((mailbox) => mailbox.databaseId !== this.mailbox.databaseId) + .filter((mailbox) => mailbox.isSubscribed) + + const alwaysVisibleMailboxes = subscribedMailboxes + .filter((mailbox) => this.isAlwaysVisiblePrefetchCandidate(mailbox)) + .sort((a, b) => { + const aIndex = ALWAYS_VISIBLE_SPECIAL_ROLES.indexOf(a.specialRole) + const bIndex = ALWAYS_VISIBLE_SPECIAL_ROLES.indexOf(b.specialRole) + + if (aIndex !== bIndex) { + return aIndex - bIndex + } + + return this.getMailboxDisplayName(a).localeCompare(this.getMailboxDisplayName(b)) + }) + .slice(0, MAX_ALWAYS_VISIBLE_PREFETCH) + + const selectedIds = new Set(alwaysVisibleMailboxes.map((mailbox) => mailbox.databaseId)) + + const topLevelMailboxes = this.sortMailboxesByDisplayName( + subscribedMailboxes + .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) + .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) + .filter((mailbox) => this.isTopLevelMailbox(mailbox)) + ) + + const remainingMailboxes = this.sortMailboxesByDisplayName( + subscribedMailboxes + .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) + .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) + .filter((mailbox) => !this.isTopLevelMailbox(mailbox)) + ) + + const result = [...alwaysVisibleMailboxes] + + for (const mailbox of topLevelMailboxes) { + if (result.length >= MAX_PREFETCH_MAILBOXES) { + break } + result.push(mailbox) + selectedIds.add(mailbox.databaseId) + } - if (!mailbox.isSubscribed) { - continue + for (const mailbox of remainingMailboxes) { + if (result.length >= MAX_PREFETCH_MAILBOXES) { + break } + result.push(mailbox) + } + return result + }, + + async prefetchOtherMailboxes() { + for (const mailbox of this.getMailboxesToPrefetch()) { try { const envelopes = await this.mainStore.fetchEnvelopes({ mailboxId: mailbox.databaseId, From 9558e1dbdf743e0737fcbbcb18155c94e7ccd6be Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 3 Jul 2026 10:07:50 -0400 Subject: [PATCH 2/2] chore(Mailbox): make lint happy Signed-off-by: Josh --- src/components/Mailbox.vue | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue index 8dd4207880..ee4d0ec566 100644 --- a/src/components/Mailbox.vue +++ b/src/components/Mailbox.vue @@ -362,18 +362,16 @@ export default { const selectedIds = new Set(alwaysVisibleMailboxes.map((mailbox) => mailbox.databaseId)) - const topLevelMailboxes = this.sortMailboxesByDisplayName( - subscribedMailboxes - .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) - .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) - .filter((mailbox) => this.isTopLevelMailbox(mailbox)) + const topLevelMailboxes = this.sortMailboxesByDisplayName(subscribedMailboxes + .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) + .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) + .filter((mailbox) => this.isTopLevelMailbox(mailbox)) ) - const remainingMailboxes = this.sortMailboxesByDisplayName( - subscribedMailboxes - .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) - .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) - .filter((mailbox) => !this.isTopLevelMailbox(mailbox)) + const remainingMailboxes = this.sortMailboxesByDisplayName(subscribedMailboxes + .filter((mailbox) => !selectedIds.has(mailbox.databaseId)) + .filter((mailbox) => !this.isAlwaysVisiblePrefetchCandidate(mailbox)) + .filter((mailbox) => !this.isTopLevelMailbox(mailbox)) ) const result = [...alwaysVisibleMailboxes]