mirror of
https://github.com/yattee/yattee.git
synced 2026-10-29 16:07:20 +00:00
Support the iPhone Duo interior display in the player
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.
This commit is contained in:
@@ -114,6 +114,22 @@ private final class ExpandedPlayerHostingController<Content: View>: UIHostingCon
|
||||
guard let window = self?.view.window,
|
||||
let scene = window.windowScene else { return }
|
||||
window.frame = scene.coordinateSpace.bounds
|
||||
}, completion: { [weak self] _ in
|
||||
// Folding/unfolding the iPhone Duo (and display handoffs in
|
||||
// general) changes the safe area without a rotation; SwiftUI
|
||||
// keeps serving the previous insets to the sheet's GeometryReader
|
||||
// until the hosting controller's safe area is invalidated. Nudge
|
||||
// additionalSafeAreaInsets, the same trick the dismiss path uses
|
||||
// for the main window.
|
||||
guard let self else { return }
|
||||
let originalInsets = self.additionalSafeAreaInsets
|
||||
self.additionalSafeAreaInsets = UIEdgeInsets(
|
||||
top: originalInsets.top + 1,
|
||||
left: originalInsets.left,
|
||||
bottom: originalInsets.bottom,
|
||||
right: originalInsets.right
|
||||
)
|
||||
self.additionalSafeAreaInsets = originalInsets
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user