Skip to content

fix: Restore CameraDevice neutralZoom - #4169

Open
ngocdevv wants to merge 1 commit into
mrousavy:mainfrom
ngocdevv:fix/restore-neutral-zoom
Open

fix: Restore CameraDevice neutralZoom#4169
ngocdevv wants to merge 1 commit into
mrousavy:mainfrom
ngocdevv:fix/restore-neutral-zoom

Conversation

@ngocdevv

Copy link
Copy Markdown

What

VisionCamera v5 no longer exposes CameraDevice.neutralZoom. On iOS virtual Cameras with an ultra-wide constituent, AVFoundation uses an internal zoom scale where minZoom can be 1 while the standard wide-angle lens is reached at 2. Consumers therefore cannot initialize at the natural user-facing 1x value without recreating native lens-selection logic.

This restores neutralZoom so consumers can start on the standard wide-angle lens and still allow zooming out to ultra-wide.

Closes #3845

How

  • Adds CameraDevice.neutralZoom to the Nitro spec and regenerates the Swift, Kotlin, and C++ bindings.
  • On iOS 18+, converts AVFoundation display zoom back to its internal factor using displayVideoZoomFactorMultiplier.
  • On older iOS versions, uses the virtual-device switchover factor immediately before the standard wide-angle constituent, matching the v4 behavior.
  • Returns 1.0 on Android and for physical Cameras.
  • Updates the zoom guide and adds Harness capability invariants for the restored property.

Test

  • bun camera specs
  • bun run build
  • bunx tsc --noEmit -p apps/simple-camera/tsconfig.json
  • bun example build:android (Kotlin, JNI/C++, four ABIs, debug APK)
  • xcodebuild -workspace apps/simple-camera/ios/SimpleCamera.xcworkspace -scheme SimpleCamera -configuration Debug -destination generic/platform=iOS\ Simulator CODE_SIGNING_ALLOWED=NO build
  • bun lint-swift
  • bun lint-kotlin
  • bun lint-js
  • bun docs types:check
  • bun docs check:links

@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

@ngocdevv is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

@mrousavy mrousavy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR.

I still haven't decided yet if we should have a .neutralZoom, or if we should just normalize zoom on iOS to also go below 1 so that it is like on Android..? Then zoom start is always 1 and we dont need to worry about anything else

*/
var neutralZoomFactor: Double {
if #available(iOS 18.0, *) {
let multiplier = displayVideoZoomFactorMultiplier

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value changes as the device starts zooming. So if you zoom in, and then ask device.neutralZoomFactor, it is no longer 1 (or 2) but might be any arbitrary number.
I think.

Comment on lines +24 to +38

guard
let wideAngleIndex = constituentDevices.firstIndex(where: {
$0.deviceType == .builtInWideAngleCamera
}),
wideAngleIndex > 0
else {
return 1
}

let switchoverIndex = wideAngleIndex - 1
guard virtualDeviceSwitchOverVideoZoomFactors.indices.contains(switchoverIndex) else {
return 1
}
return virtualDeviceSwitchOverVideoZoomFactors[switchoverIndex].doubleValue

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this Plan B and Plan C approach are kinda ugly. I'm not sure if there is a better way, but as it is, its a bit ugly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Neutral zoom?

2 participants