From da7bce26a2f16e1ebc65fe6798b0c18051255e6a Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Wed, 19 Aug 2026 14:13:56 +0200 Subject: [PATCH] Fix Request Access button doing nothing: run permission prompt on main thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit requestAccess() was dispatched onto the background queue used for AppleScript execution, on the assumption that a blocking call needed to be off-main. That's backwards for AEDeterminePermissionToAutomateTarget's consent dialog — like this app's existing NSAlert.runModal() calls, it needs to run on the main thread/run loop to actually display. Off-main, it silently returned without ever showing a prompt or changing state. Also added Log.mail diagnostics on both the status-only check and the prompting call so a future report of "still doesn't work" has an actual status code to look at instead of starting from scratch. --- oAI/Services/AppleMailService.swift | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/oAI/Services/AppleMailService.swift b/oAI/Services/AppleMailService.swift index 0db045b..af42420 100644 --- a/oAI/Services/AppleMailService.swift +++ b/oAI/Services/AppleMailService.swift @@ -61,7 +61,9 @@ final class AppleMailService { /// the Apple-Events equivalent of `EKEventStore.authorizationStatus(for:)`, reusing the same /// `PersonalDataAccessState` enum EventKitService/ContactsService/LocationMapsService use. var accessState: PersonalDataAccessState { - Self.mapAutomationPermissionStatus(Self.checkMailAutomationPermission(askUserIfNeeded: false)) + let status = Self.checkMailAutomationPermission(askUserIfNeeded: false) + Log.mail.debug("accessState: AEDeterminePermissionToAutomateTarget(askUserIfNeeded: false) returned \(status)") + return Self.mapAutomationPermissionStatus(status) } /// Pure mapping from an `AEDeterminePermissionToAutomateTarget` status code to the shared @@ -75,16 +77,18 @@ final class AppleMailService { } /// Triggers the real macOS "Confab wants to control Mail" Automation permission prompt if - /// the user hasn't been asked yet (a no-op if already granted or denied). Blocks until the - /// user responds, so this must run off the main thread. + /// the user hasn't been asked yet (a no-op if already granted or denied). Deliberately NOT + /// dispatched to the background `queue` used for AppleScript execution — the system consent + /// prompt needs to be raised from the main thread/run loop to actually display (same as this + /// codebase's existing blocking `NSAlert.runModal()` calls); calling it off-main appears to + /// silently fail (no dialog, no error, no state change — the exact symptom Rune hit live). + /// `AppleMailService` has no explicit actor annotation, so under this project's + /// `-default-isolation=MainActor` build setting this method already runs on the main actor. @discardableResult func requestAccess() async -> Bool { - await withCheckedContinuation { continuation in - queue.async { - let status = Self.checkMailAutomationPermission(askUserIfNeeded: true) - continuation.resume(returning: status == 0) - } - } + let status = Self.checkMailAutomationPermission(askUserIfNeeded: true) + Log.mail.info("requestAccess: AEDeterminePermissionToAutomateTarget(askUserIfNeeded: true) returned \(status)") + return status == 0 } private static func checkMailAutomationPermission(askUserIfNeeded: Bool) -> OSStatus {