feat: auto-dismiss the stale Screen Broadcasting alert during broadcast start/stop - #24
Merged
Timo972 merged 6 commits intoAug 25, 2026
Conversation
…app's orientation
…is acknowledgement The alert-dismissal tap synthesized inside dismissBroadcastStoppedAlertWithLabels: previously waited synchronously for the synthesis acknowledgement (up to the event-synthesis timeout margin, ~15s, when the system sheds the event). That call runs inside run-loop spinners with much shorter deadlines (the ~3s post-stop sweep, the 5s already-captured wait, the confirm spin), and a spinner deadline cannot interrupt a nested synchronous call - so under the exact overload scenario these bounds exist for, the automation queue could stay blocked ~15s. The dismissal doesn't need the acknowledgement: every caller re-checks the alert's existence on its next spin iteration, so the tap is now fire-and-forget via a new FBXCTestDaemonsProxy +synthesizeEventAsyncWithRecord: that dispatches without waiting, logging (and otherwise ignoring) failures. A 1s re-attempt cooldown avoids re-tapping the same coordinates while the alert's dismissal animation is still in flight. The CONFIRM tap stays synchronous and untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The isCaptured-wait loop's dismissal log still said "dismissed" from before the dismissal tap became fire-and-forget; bring it in line with the other two dismissal log sites updated in 14457dd. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…it is gone Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… stop sweep The post-stop sweep previously exited YES the instant no matching alert was present, but SpringBoard publishes the iOS 26 "Screen Broadcasting" alert with a delay after the extension socket closes, so the sweep saw nothing and exited at t≈0, leaving the alert armed for the next start. Rework the sweep into a two-phase wait, gated on iOS 26+ (the alert does not exist on older iOS, where the start-side dismissal remains the safety net): wait out a 2s appearance grace period if the alert has not been seen yet, then once it has been seen, spin (retrying the dismissal tap, paced by the existing 1s cooldown) until it is observed gone, capped at a 5s overall timeout. The sweep stays best-effort and never affects the method's return value.
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.
Stacked on #23.
What
When a ReplayKit broadcast ends (the runner died mid-broadcast, or the broadcast was stopped programmatically), iOS 26 posts a modal system alert ("Screen Broadcasting", OK / Go to Application). While that alert is up, the broadcast picker flow cannot complete, so automated broadcast restarts fail until the alert is dismissed by hand.
This teaches the agent to dismiss it itself:
broadcast/startandbroadcast/stopaccept an optionaldismissButtonLabelsargument (default["OK"], pass localized labels on non-English devices — same contract asconfirmButtonLabels).Tests
No unit seam exists for this behavior (it is XCUI against SpringBoard); the full unit bundle (175 green) and iOS/watchOS builds serve as regression, and the three on-device acceptance scenarios (pre-existing alert → start succeeds; stop→start cycle leaves no alert; first-ever start unchanged) are device-verified separately. Docs updated in
docs/broadcast-extension.md.🤖 Generated with Claude Code