From ac606cf061522d8e92c3215b569f37313809fadb Mon Sep 17 00:00:00 2001 From: Akash Tom Date: Thu, 25 Jun 2026 14:57:52 +0530 Subject: [PATCH 1/3] fix(screener): correct icon, restrict move/add, batch triage requests - getIcon: the Screener's 'eye' icon is authoritative, so a stray Mailbox Settings icon can't make it render as a generic folder - exclude the Screener (a system folder) from move/add target lists and from the Folders management list - batch Block/Allow so rapid triage no longer fires concurrent sieve rebuilds that race on the shared automation script (CannotChangeConstantError) - rename SCREENING_MAILBOX_NAME -> SCREENER_MAILBOX_NAME and mailboxIds.screening -> .screener for naming consistency Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/components/AppSidebar.vue | 4 +- frontend/src/components/MailActions.vue | 8 +-- .../components/Settings/AccountSettings.vue | 2 +- .../components/Settings/FolderSettings.vue | 14 ++-- frontend/src/components/ThreadHeader.vue | 2 + frontend/src/constants.ts | 4 +- frontend/src/pages/MailboxView.vue | 2 +- frontend/src/pages/ScreenerView.vue | 64 +++++++++++++++---- frontend/src/stores/user.ts | 8 +-- frontend/src/utils/index.ts | 8 ++- frontend/src/utils/useThreadActions.ts | 16 ++++- mail/api/mail.py | 10 +-- mail/api/sieve.py | 8 +-- 13 files changed, 106 insertions(+), 44 deletions(-) diff --git a/frontend/src/components/AppSidebar.vue b/frontend/src/components/AppSidebar.vue index 89ceb0a43..275b8b411 100644 --- a/frontend/src/components/AppSidebar.vue +++ b/frontend/src/components/AppSidebar.vue @@ -275,7 +275,7 @@ const mailboxItems = computed( ?.filter((mailbox: MailboxData) => mailbox.subscribed) ?.map((mailbox: MailboxData) => { // The Screening folder opens the dedicated Screener page, not the thread list. - const isScreener = mailbox.id === store.mailboxIds.screening + const isScreener = mailbox.id === store.mailboxIds.screener return { mailboxId: mailbox.id, label: getMailboxName(mailbox), @@ -328,7 +328,7 @@ const sidebarItems = computed(() => { // Screening is a roleless folder; it gets its own nameless group pinned to the top of the // sidebar, separate from the default and custom mailboxes. const isScreening = (item: { mailboxId?: string }) => - !!store.mailboxIds.screening && item.mailboxId === store.mailboxIds.screening + !!store.mailboxIds.screener && item.mailboxId === store.mailboxIds.screener const screenerItem = mailboxItems.value.find((item) => isScreening(item)) diff --git a/frontend/src/components/MailActions.vue b/frontend/src/components/MailActions.vue index c818d9624..ca19de537 100644 --- a/frontend/src/components/MailActions.vue +++ b/frontend/src/components/MailActions.vue @@ -203,20 +203,20 @@ const moreActions = (mail: Mail): GroupedAction[] => [ label: __('Accept Sender'), onClick: () => handleScreenSender('Accepted'), icon: CircleCheck, - condition: () => mailbox === mailboxIds.screening, + condition: () => mailbox === mailboxIds.screener, }, { label: __('Reject Sender'), onClick: () => handleScreenSender('Reject'), icon: Ban, - condition: () => mailbox === mailboxIds.screening, + condition: () => mailbox === mailboxIds.screener, }, { label: __('Block Sender'), onClick: () => handleBlockAddress(true), icon: Ban, condition: () => - mailbox !== mailboxIds.screening && + mailbox !== mailboxIds.screener && !identities.data.some((i: Identity) => i.email === mail.from_email) && !isSenderBlocked(mail.from_email), }, @@ -225,7 +225,7 @@ const moreActions = (mail: Mail): GroupedAction[] => [ onClick: () => handleBlockAddress(false), icon: LockOpen, condition: () => - mailbox !== mailboxIds.screening && isSenderBlocked(mail.from_email), + mailbox !== mailboxIds.screener && isSenderBlocked(mail.from_email), }, ], }, diff --git a/frontend/src/components/Settings/AccountSettings.vue b/frontend/src/components/Settings/AccountSettings.vue index 6b1c05b32..fcc058279 100644 --- a/frontend/src/components/Settings/AccountSettings.vue +++ b/frontend/src/components/Settings/AccountSettings.vue @@ -196,7 +196,7 @@ const save = async () => { askMoveToInbox = screeningChanged && !accountSettings.doc.enable_screening && - (mailboxes.data?.find((m: MailboxData) => m.id === mailboxIds.screening) + (mailboxes.data?.find((m: MailboxData) => m.id === mailboxIds.screener) ?.total_threads ?? 0) > 0 await accountSettings.save.submit() // Sync the shared user data so compose picks up the new default and the junk flow picks up diff --git a/frontend/src/components/Settings/FolderSettings.vue b/frontend/src/components/Settings/FolderSettings.vue index 28a6a2b30..7c523bbc5 100644 --- a/frontend/src/components/Settings/FolderSettings.vue +++ b/frontend/src/components/Settings/FolderSettings.vue @@ -3,9 +3,9 @@

{{ __('Folders') }}