diff --git a/.changeset/expo-authview-ondismiss-non-dismissible.md b/.changeset/expo-authview-ondismiss-non-dismissible.md new file mode 100644 index 00000000000..7c5fbe99812 --- /dev/null +++ b/.changeset/expo-authview-ondismiss-non-dismissible.md @@ -0,0 +1,5 @@ +--- +'@clerk/expo': patch +--- + +Fix `AuthView`'s `onDismiss` never firing on iOS when `isDismissible` is `false`. The callback now runs once the auth flow completes, matching Android, so an app-owned modal or screen wrapping the view can close after sign-in. diff --git a/packages/expo/ios/ClerkAuthNativeView.swift b/packages/expo/ios/ClerkAuthNativeView.swift index e76a8be1b1c..5f8d2ba66d5 100644 --- a/packages/expo/ios/ClerkAuthNativeView.swift +++ b/packages/expo/ios/ClerkAuthNativeView.swift @@ -44,9 +44,8 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { onAuthEvent(["type": type.rawValue]) } - private func sendDismissIfNeeded() { - // SwiftUI dismissals detach the hosted view without calling UIKit dismiss(). - guard currentDismissible, !didSendDismiss else { return } + private func sendDismiss() { + guard !didSendDismiss else { return } didSendDismiss = true sendAuthEvent(type: .dismissed) } @@ -56,7 +55,11 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { } override func hostedViewDidDetachFromWindow() { - sendDismissIfNeeded() + // SwiftUI dismissals detach the hosted view without calling UIKit dismiss(). + // A non-dismissible view never self-dismisses, so a detach there is the host + // tearing the view down rather than a dismissal to report. + guard currentDismissible else { return } + sendDismiss() } override public func layoutSubviews() { @@ -119,7 +122,7 @@ public class ClerkAuthNativeView: ClerkNativeViewHost { hostBackAction: hostBackAction, onEvent: { [weak self] event, _ in if event == .dismissed { - self?.sendDismissIfNeeded() + self?.sendDismiss() } } ) diff --git a/packages/expo/ios/ClerkNativeBridge.swift b/packages/expo/ios/ClerkNativeBridge.swift index 57fbbb92013..002b44d517b 100644 --- a/packages/expo/ios/ClerkNativeBridge.swift +++ b/packages/expo/ios/ClerkNativeBridge.swift @@ -939,6 +939,7 @@ final class ClerkNativeBridge { // MARK: - Inline View Creation + @MainActor func makeAuthViewController( mode: String, dismissible: Bool, @@ -958,6 +959,10 @@ final class ClerkNativeBridge { darkTheme: darkTheme, logoState: logoState, logoMaxHeight: logoMaxHeight + ) + .environment( + \.clerkAuthFlowCompletionAction, + ClerkAuthFlowCompletionAction { onEvent(.dismissed, [:]) } ), onDismiss: dismissible ? { onEvent(.dismissed, [:]) } : nil )