Skip to content

Commit 19ef5d3

Browse files
mdrbohlavclaude
andcommitted
fix(share): present share sheet from the topmost view controller on iOS
On iOS, share() rejected with "Can't share while sharing is in progress" whenever any view controller was presented over the bridge view controller, not only when a share sheet was already open. Any app that presents a native modal over the webview - an in-app browser, a camera or document picker, a secondary WKWebView, a native auth session - could not share while that modal was on screen, and the error reported a share state that did not exist. Removing the guard alone is not enough: bridge.viewController cannot present while it already has a presentedViewController, so UIKit logs "Attempt to present ... which is already presenting ..." and no sheet appears. Walk the presentation chain and reject only when a UIActivityViewController is found in it, then present from the topmost view controller. Anchor the iPad popover to that controller's own view, since setCenteredPopover anchors to bridge.viewController.view, which is not in the presenter's hierarchy when presenting from a different view controller. Behaviour is unchanged when nothing is presented. This aligns iOS with the Android implementation, which tracks an isPresenting flag and already rejects only during an actual share. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 0bfde98 commit 19ef5d3

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

share/ios/Sources/SharePlugin/SharePlugin.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,28 @@ public class SharePlugin: CAPPlugin, CAPBridgedPlugin {
6464
}
6565

6666
}
67-
if self?.bridge?.viewController?.presentedViewController != nil {
68-
call.reject("Can't share while sharing is in progress")
69-
return
67+
// Present from the topmost presented view controller so the share sheet appears
68+
// above any view controller the app has presented over the webview. With nothing
69+
// presented this resolves to the bridge view controller, i.e. unchanged behaviour.
70+
// A share is only in progress when a share sheet is already presented.
71+
var presenter = self?.bridge?.viewController
72+
while let presented = presenter?.presentedViewController {
73+
if presented is UIActivityViewController {
74+
call.reject("Can't share while sharing is in progress")
75+
return
76+
}
77+
presenter = presented
78+
}
79+
// `setCenteredPopover` anchors to the bridge view controller's view, which is not in
80+
// the presenter's hierarchy when presenting from a different view controller. Anchor
81+
// the popover to the presenting view controller's own view instead, centered and
82+
// without an arrow, matching `setCenteredPopover` behaviour.
83+
if let popover = actionController.popoverPresentationController, let presenterView = presenter?.view {
84+
popover.sourceView = presenterView
85+
popover.sourceRect = CGRect(x: presenterView.bounds.midX, y: presenterView.bounds.midY, width: 0, height: 0)
86+
popover.permittedArrowDirections = []
7087
}
71-
self?.setCenteredPopover(actionController)
72-
self?.bridge?.viewController?.present(actionController, animated: true, completion: nil)
88+
presenter?.present(actionController, animated: true, completion: nil)
7389
}
7490
}
7591
}

0 commit comments

Comments
 (0)