Skip to content

Lock to the screen's orientation, and hide the lock on iPad - #1637

Merged
GianniCarlo merged 2 commits into
developfrom
fix/orientation-lock-ipad-duo
Oct 11, 2026
Merged

GianniCarlo merged 2 commits into
developfrom
fix/orientation-lock-ipad-duo

Conversation

@GianniCarlo

Copy link
Copy Markdown
Collaborator

Problem

  • It saved the device's orientation, not the screen's. A phone lying flat reports face up, which counted as portrait, so turning the lock on in bed with the app in landscape flipped it to portrait.
  • iPad never honored it. iOS doesn't ask an app that supports multitasking for its supported orientations, so the toggle did nothing there.
  • iPhone Duo's inner display ignores supported orientations too (Apple's guidance); the outer display honors them like any iPhone.

Changes

  • OrientationLock (new): the rule both root controllers repeated (AppHostingViewController, AppNavigationController), plus saving and clearing.
  • Saving: the interface's orientation (effectiveGeometry.interfaceOrientation), in the same stored format, so existing locks keep working.
  • SettingsAppearanceSectionView: the toggle shows on iPhone only (iPhone Duo included, where it works while closed).

Tried and dropped

iOS 26's interface orientation lock preference (prefersInterfaceOrientationLocked, set only while the scene is in the saved orientation) as the iPad mechanism. On the iPad simulator, in both Full Screen Apps and Windowed Apps, iOS asked the presented controller once, got true, and never applied it: effectiveGeometry.isInterfaceOrientationLocked stayed false, the UI kept rotating, and it never asked again after setNeedsUpdateOfPrefersInterfaceOrientationLocked().

Testing

  • iPhone 17 Pro simulator: with the lock on, Settings and the player stay portrait in both landscapes; video fullscreen still rotates to landscape and back, with the lock on or off; with it off, the UI rotates.
  • iPad Air simulator: the toggle is gone from Appearance.
  • Device: iPhone 17.

… iPad

The orientation lock saved the device's orientation when it was turned on.
A phone lying flat reports face up, which counted as portrait, so turning
the lock on in bed with the app in landscape flipped it to portrait. It now
saves the interface's orientation, in the same stored format, so existing
locks keep working.

iPad never honored the lock: iOS doesn't ask an app that supports
multitasking for its supported orientations. iOS 26's interface orientation
lock preference didn't help either; the iPad simulator never applied it, in
full screen or windowed. So the toggle now shows on iPhone only, where it
works, including iPhone Duo while closed (its inner display ignores locks).

The rule both root controllers repeated moves to OrientationLock.
@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

✅ Claude PR Review — PASS

This PR moves the orientation-lock rule into a new OrientationLock helper. Both root controllers now use it, and so does the Settings toggle, which saves it through the helper. The lock now records the screen's orientation (effectiveGeometry.interfaceOrientation) instead of the device's, and keeps the same stored format, so locks saved by earlier versions still work. The toggle now shows on iPhone only. I checked it against the surrounding code: the deployment target is iOS 26, so effectiveGeometry is always available; WindowHelper is @MainActor and is only called from the view's onChange; the stored key, UserDefaults.standard and the setNeedsUpdateOfSupportedInterfaceOrientations() call are unchanged; and VideoFullscreenViewController still sets its own supportedInterfaceOrientations, so fullscreen video isn't affected. There are no threading, player/AVAudioSession, CoreData/SwiftData or entitlement concerns, and the new unit tests use their own UserDefaults suite. One leftover: an iPad user who turned the lock on with an earlier version keeps that saved value with no way to clear it. Since iPad ignores the lock anyway, it does no harm.

Findings: no findings

Converged: nothing new this round, and no earlier finding is open.

Model claude-opus-5-5 · run log · 0 new · 0 carried over · 0 resolved · advisory (a human should still review). Findings are de-duplicated across pushes; an earlier finding closes only when the verification pass judges it against the current code — fixed, no longer applicable, accepted by a maintainer, or a duplicate of a finding reported on this push.

OrientationLock takes the UserDefaults to use (.standard by default) so the
tests can pass their own suite. They pin the stored format: values earlier
versions saved (including face up and face down, which lock to portrait), the
interface orientation saved now, and clearing it.
@GianniCarlo
GianniCarlo merged commit 95e67e6 into develop Oct 11, 2026
3 checks passed
@GianniCarlo
GianniCarlo deleted the fix/orientation-lock-ipad-duo branch October 11, 2026 20:46

This branch was successfully deployed

1 active deployment
reviewer — b732b669 Deployed Oct 11, 2026 by GianniCarlo via review #252
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.

1 participant