Fix camera stuck in landscape - improve orientation detection

Issues fixed:
1. On app launch, UIDevice.current.orientation may be .unknown or .faceUp
   causing no orientation to be set (defaulting to landscape)

2. When phone is flat, orientation was being skipped

Solution:
- Track lastValidOrientation as fallback
- When device orientation is invalid, get from windowScene.interfaceOrientation
- Use last known good orientation if all else fails
- Default to portrait (90°) if nothing else works

This ensures the camera preview starts in the correct orientation
and stays properly rotated during use.
This commit is contained in:
Matt Bruce 2026-01-02 16:03:13 -06:00
parent e66487cabf
commit 6fb3c4e212

View File

@ -153,6 +153,9 @@ class CameraPreviewUIView: UIView {
updatePreviewOrientation() updatePreviewOrientation()
} }
/// Tracks the last valid orientation for fallback
private var lastValidOrientation: UIDeviceOrientation = .portrait
@objc private func handleOrientationChange() { @objc private func handleOrientationChange() {
updatePreviewOrientation() updatePreviewOrientation()
} }
@ -161,9 +164,36 @@ class CameraPreviewUIView: UIView {
guard let connection = previewLayer?.connection else { return } guard let connection = previewLayer?.connection else { return }
// Get rotation angle based on device orientation // Get rotation angle based on device orientation
let deviceOrientation = UIDevice.current.orientation var deviceOrientation = UIDevice.current.orientation
// If device orientation is flat or unknown, try to get from interface orientation
if !deviceOrientation.isValidInterfaceOrientation {
// Use last known good orientation, or get from window scene
if let windowScene = window?.windowScene {
switch windowScene.interfaceOrientation {
case .portrait:
deviceOrientation = .portrait
case .portraitUpsideDown:
deviceOrientation = .portraitUpsideDown
case .landscapeLeft:
deviceOrientation = .landscapeRight // Interface and device are inverted
case .landscapeRight:
deviceOrientation = .landscapeLeft // Interface and device are inverted
case .unknown:
deviceOrientation = lastValidOrientation
@unknown default:
deviceOrientation = lastValidOrientation
}
} else {
deviceOrientation = lastValidOrientation
}
} else {
// Store this as the last valid orientation
lastValidOrientation = deviceOrientation
}
// Calculate rotation angle (in degrees) for the preview layer // Calculate rotation angle (in degrees) for the preview layer
// For front camera in portrait: sensor is landscape, so rotate 90°
let rotationAngle: CGFloat let rotationAngle: CGFloat
switch deviceOrientation { switch deviceOrientation {
case .portrait: case .portrait:
@ -174,10 +204,7 @@ class CameraPreviewUIView: UIView {
rotationAngle = 180 rotationAngle = 180
case .landscapeRight: case .landscapeRight:
rotationAngle = 0 rotationAngle = 0
case .faceUp, .faceDown, .unknown: default:
// Keep current orientation for flat/unknown positions
return
@unknown default:
rotationAngle = 90 // Default to portrait rotationAngle = 90 // Default to portrait
} }