Repository navigation
Conversation
Present each alert from the topmost presented view controller instead of the bridge view controller, so a dialog appears above any view controller the app has presented over the web view. UIKit refuses to present from a view controller that already presents one, and the refusal has no error path, so the call never resolved. If the walk stops at a controller whose presented child is still being dismissed, reject the call instead of leaving it pending. Closes ionic-team#2404
theblang
force-pushed
the
fix/dialog-present-from-topmost-vc
branch
from
October 20, 2026 16:07
9174771 to
ba9d72e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2404
The problem
On iOS,
DialogPluginpresents every alert frombridge.viewController. If the app has another view controller presented over the web view, UIKit refuses the presentation, logsAttempt to present ... which is already presenting ..., and drops the alert. The action handlers never run, so the JS promise never settles.Any native screen presented over the web view triggers it: the camera or photo picker, a
QLPreviewController, the share sheet, the calendar edit sheet, or a sign-in sheet. The common case is an alert that a network response triggers while such a screen is open.The fix
The 3 methods now present through one private
present(_:for:). It walkspresentedViewControllerfrom the bridge view controller to the topmost controller and presents from there. With nothing presented, the walk returns the bridge view controller, so the existing behaviour is unchanged.The walk stops below a controller that
isBeingDismissed. UIKit refuses a presentation from its presenter until that dismissal ends, and the refusal has no error path:present(_:animated:completion:)returns, logs a warning, and never runs the completion. The call would stay pending forever. In that window the plugin now rejects the call instead, the same way the Share plugin rejects when a share is already in progress.#2574 applied the same walk to the Share plugin.
Testing
Tested in a Capacitor 8.5.3 app on an iPhone 18 Pro simulator, iOS 27:
Dialog.confirmshows above the picker and resolves on tap.Dialog.confirmbehaves as before.Dialog.alertandDialog.promptwere not tested on a device. They use the samepresent(_:).🤖 Generated with Claude Code