Conversation
waitForDimensions gated its first-frame wait on getBrowser()?.os === 'iOS'. browserParser decides iOS versus macOS for Safari by whether the user agent contains `mobile/`, and iPadOS has sent the desktop Macintosh user agent by default since iPadOS 13, so iPads took the old path and read getSettings() immediately. The same device flipped between the two paths depending on the per-site "Request Mobile Website" setting. Measured on an iPad 6 running iPadOS 17, front camera, held in portrait: the track reports 1280x960 for ~600ms and then corrects to 960x1280 at the first painted frame, in 5 of 5 captures. That is the window waitForDimensions was reading inside, so a portrait iPad announced itself to the room as landscape. Adds isIPadOS()/isAppleMobile() and gates on the latter. isIPadOS() keys on touch capability, which separates the two platforms cleanly: macOS Safari implements no touch events at all (TouchEvent undefined, maxTouchPoints 0 regardless of any attached touchscreen) while the iPad reports maxTouchPoints 5. It is scoped to Safari on a Macintosh user agent, so no other browser reaches the check. Deliberately a separate helper rather than a fix inside browserParser: iPadOS spoofs the Mac version too, so reporting os: 'iOS' there would leave osVersion at '10.15.7' and silently break isSafari17Based() and isSafariSvcApi(), which compare it. The gate stays narrow rather than running everywhere. On macOS Safari the first frame takes 487-826ms (measured over 10 captures) and getSettings() never changes, so waiting there would be pure added publish latency on the critical path for a bug that platform does not have. Fixes #2107
🦋 Changeset detectedLatest commit: ba76fe8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
size-limit report 📦
|
1egoman
commented
Sep 18, 2026
Comment on lines
+303
to
+329
| /** | ||
| * iPadOS has sent the desktop Macintosh user agent by default since iPadOS 13, so `getBrowser()` | ||
| * reports `os: 'macOS'` there and every `os === 'iOS'` check misses it. macOS Safari implements no | ||
| * touch events at all (`TouchEvent` undefined, `maxTouchPoints` 0) regardless of any touchscreen | ||
| * attached, so touch capability separates the two. Measured on an iPad 6 / iPadOS 17 | ||
| * (`maxTouchPoints` 5) against macOS Safari 26.4 (`maxTouchPoints` 0). | ||
| * | ||
| * Deliberately a separate helper rather than a fix in `browserParser`: iPadOS spoofs the Mac | ||
| * version too, so reporting `os: 'iOS'` there would leave `osVersion` at `10.15.7` and silently | ||
| * break {@link isSafari17Based} and {@link isSafariSvcApi}, which compare it. | ||
| */ | ||
| export function isIPadOS(): boolean { | ||
| if (!isWeb()) { | ||
| return false; | ||
| } | ||
| const b = getBrowser(); | ||
| return b?.name === 'Safari' && b?.os === 'macOS' && navigator.maxTouchPoints > 1; | ||
| } | ||
|
|
||
| /** | ||
| * iPhone, iPad and iOS-hosted browsers — everything running the Apple camera capture pipeline, | ||
| * including iPads that present themselves as a Mac. | ||
| */ | ||
| export function isAppleMobile(): boolean { | ||
| return getBrowser()?.os === 'iOS' || isIPadOS(); | ||
| } | ||
|
|
Contributor
Author
There was a problem hiding this comment.
This is the highest risk part of this change.
As a datapoint, I have an older ipad 6 and iphone 11 kicking around along with my mac - I ran the above functions on all three platforms and isIPadOS() returned true only for the ipad, and isAppleMobile() returned true for both the ipad and iphone.
Related issue: #1788. Not 100% sure this handles all cases right though and would like another perspective before merging.
xianshijing-lk
approved these changes
Sep 18, 2026
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.
Updates the check from #2100 to also wait for the first video frame to go through the capture pipeline on iPads (as well as iPhones) as iPads suffer from the same issue.
More info / context can be found in #2107 (comment).