The in-app orientation lock pinned the player to the orientation it
opened in even where programmatic rotation is refused, so rotating the
half-open device did nothing. OrientationManager now ignores lock
requests and drops the current lock while canRotateProgrammatically is
false. The YATTEE_FORCE_TABLETOP override only applies on the interior
display size and flags the same state, matching a real .partiallyOpen
hinge instead of forcing the layout on the folded exterior display.
The interior display refuses programmatic rotation
(UISceneErrorDomain 101: "The current windowing mode does not allow for
programmatic changes to interface orientation"), so the rotate/fullscreen
button did nothing there and the failure was swallowed.
- OrientationManager tracks `canRotateProgrammatically` (from the hinge
state, cleared when a geometry request is refused) and is @Observable.
- The fullscreen button takes the iPad path when rotation is unavailable:
details toggle in portrait, floating panel toggle in landscape, icon
follows the panel state; orientation lock is hidden. The refused request
itself falls back to the details toggle. Accelerometer-driven rotation
requests are gated the same way.
- Corner layout gate is size-only on iOS (≥900×600 including safe areas,
so the status bar toggling with the layout can't oscillate it); the
layout-mode setting is exposed on foldables via a hinge presence check.
- Corner layout on iPhone always hides the status bar (the interior's
landscape bar is a ~57pt column) and pads by the live top inset only,
instead of the transient 82pt inset seen while unfolding.
- The player hosting controller nudges its safe area after size
transitions so fold/unfold doesn't leave SwiftUI with stale insets.
- List row hairlines read displayScale from the SwiftUI environment
- MPV render views take contentScaleFactor from traitCollection and
re-apply it on UITraitDisplayScale changes
- ExpandedPlayerWindow scales against the presenting view's own height
- MPVPiPBridge sizes the PiP layer from the container view's window
scene screen (UIScreen.main kept only as a nil-window fallback)
- WideScreenPlayerLayout falls back to the offered geometry size
- Remote control fullscreen state comes from the player sheet's layout
pass via NavigationCoordinator.isWideScreenLayoutActive instead of
screen bounds aspect
- Orientation TODOs for Dynamic Island side detection and
prefersInterfaceOrientationLocked