diff --git a/Shared/Defaults.swift b/Shared/Defaults.swift index 7cb4c317..8f28a0d3 100644 --- a/Shared/Defaults.swift +++ b/Shared/Defaults.swift @@ -86,6 +86,7 @@ extension Defaults.Keys { #if os(iOS) static let honorSystemOrientationLock = Key("honorSystemOrientationLock", default: true) static let enterFullscreenInLandscape = Key("enterFullscreenInLandscape", default: UIDevice.current.userInterfaceIdiom == .phone) + static let lockLandscapeOnRotation = Key("lockLandscapeOnRotation", default: false) static let lockLandscapeWhenEnteringFullscreen = Key("lockLandscapeWhenEnteringFullscreen", default: false) #endif } diff --git a/Shared/Player/PlayerViewController.swift b/Shared/Player/PlayerViewController.swift index 26bf3211..c023dd49 100644 --- a/Shared/Player/PlayerViewController.swift +++ b/Shared/Player/PlayerViewController.swift @@ -137,9 +137,15 @@ extension PlayerViewController: AVPlayerViewControllerDelegate { func playerViewController( _: AVPlayerViewController, - willBeginFullScreenPresentationWithAnimationCoordinator _: UIViewControllerTransitionCoordinator + willBeginFullScreenPresentationWithAnimationCoordinator context: UIViewControllerTransitionCoordinator ) { playerModel.playingFullscreen = true + + #if os(iOS) + if !context.isCancelled, Defaults[.lockLandscapeWhenEnteringFullscreen] { + Orientation.lockOrientation(.landscape, andRotateTo: UIDevice.current.orientation.isLandscape ? nil : .landscapeRight) + } + #endif } func playerViewController( diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index 67b1b577..a7ab7f0b 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -28,13 +28,11 @@ struct VideoPlayerView: View { @Default(.enterFullscreenInLandscape) private var enterFullscreenInLandscape @Default(.honorSystemOrientationLock) private var honorSystemOrientationLock - @Default(.lockLandscapeWhenEnteringFullscreen) private var lockLandscapeWhenEnteringFullscreen + @Default(.lockLandscapeOnRotation) private var lockLandscapeOnRotation @State private var motionManager: CMMotionManager! @State private var orientation = UIInterfaceOrientation.portrait @State private var lastOrientation: UIInterfaceOrientation? - - private var orientationThrottle = Throttle(interval: 2) #endif @EnvironmentObject private var accounts @@ -140,7 +138,11 @@ struct VideoPlayerView: View { #endif } .background(colorScheme == .dark ? Color.black : Color.white) - .modifier(VideoDetailsPaddingModifier(geometry: geometry, aspectRatio: player.controller?.aspectRatio, fullScreen: fullScreenDetails)) + .modifier(VideoDetailsPaddingModifier( + geometry: geometry, + aspectRatio: player.controller?.aspectRatio, + fullScreen: fullScreenDetails + )) } #endif } @@ -231,7 +233,11 @@ struct VideoPlayerView: View { #if os(iOS) private func configureOrientationUpdatesBasedOnAccelerometer() { - if UIDevice.current.orientation.isLandscape, enterFullscreenInLandscape, !player.playingFullscreen { + if UIDevice.current.orientation.isLandscape, + enterFullscreenInLandscape, + !player.playingFullscreen, + !player.playingInPictureInPicture + { DispatchQueue.main.async { player.enterFullScreen() } @@ -244,7 +250,7 @@ struct VideoPlayerView: View { motionManager = CMMotionManager() motionManager.accelerometerUpdateInterval = 0.2 motionManager.startAccelerometerUpdates(to: OperationQueue()) { data, _ in - guard player.presentingPlayer, !data.isNil else { + guard player.presentingPlayer, !player.playingInPictureInPicture, !data.isNil else { return } @@ -278,11 +284,12 @@ struct VideoPlayerView: View { player.enterFullScreen() - let orientationLockMask = orientation == .landscapeLeft ? UIInterfaceOrientationMask.landscapeLeft : .landscapeRight + let orientationLockMask = orientation == .landscapeLeft ? + UIInterfaceOrientationMask.landscapeLeft : .landscapeRight Orientation.lockOrientation(orientationLockMask, andRotateTo: orientation) - guard lockLandscapeWhenEnteringFullscreen else { + guard lockLandscapeOnRotation else { return } @@ -307,7 +314,11 @@ struct VideoPlayerView: View { private func handleOrientationDidChangeNotification() { let newOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation - if newOrientation?.isLandscape ?? false, player.presentingPlayer, lockLandscapeWhenEnteringFullscreen, !player.lockedOrientation.isNil { + if newOrientation?.isLandscape ?? false, + player.presentingPlayer, + lockLandscapeOnRotation, + !player.lockedOrientation.isNil + { Orientation.lockOrientation(.landscape, andRotateTo: newOrientation) return } diff --git a/Shared/Settings/PlayerSettings.swift b/Shared/Settings/PlayerSettings.swift index 084a786e..3030392c 100644 --- a/Shared/Settings/PlayerSettings.swift +++ b/Shared/Settings/PlayerSettings.swift @@ -18,8 +18,9 @@ struct PlayerSettings: View { @Default(.pauseOnHidingPlayer) private var pauseOnHidingPlayer #if os(iOS) @Default(.honorSystemOrientationLock) private var honorSystemOrientationLock - @Default(.lockLandscapeWhenEnteringFullscreen) private var lockLandscapeWhenEnteringFullscreen + @Default(.lockLandscapeOnRotation) private var lockLandscapeOnRotation @Default(.enterFullscreenInLandscape) private var enterFullscreenInLandscape + @Default(.lockLandscapeWhenEnteringFullscreen) private var lockLandscapeWhenEnteringFullscreen #endif @Default(.closePiPOnNavigation) private var closePiPOnNavigation @Default(.closePiPOnOpeningPlayer) private var closePiPOnOpeningPlayer @@ -85,16 +86,6 @@ struct PlayerSettings: View { channelSubscribersToggle } - #if os(iOS) - Section(header: SettingsHeader(text: "Orientation")) { - if idiom == .pad { - enterFullscreenInLandscapeToggle - } - honorSystemOrientationLockToggle - lockLandscapeWhenEnteringFullscreenToggle - } - #endif - Section(header: SettingsHeader(text: "Picture in Picture")) { closePiPOnNavigationToggle closePiPOnOpeningPlayerToggle @@ -102,6 +93,17 @@ struct PlayerSettings: View { closePiPAndOpenPlayerOnEnteringForegroundToggle #endif } + + #if os(iOS) + Section(header: SettingsHeader(text: "Orientation"), footer: orientationFooter) { + if idiom == .pad { + enterFullscreenInLandscapeToggle + } + honorSystemOrientationLockToggle + lockLandscapeOnRotationToggle + lockLandscapeWhenEnteringFullscreenToggle + } + #endif } } @@ -212,10 +214,18 @@ struct PlayerSettings: View { Toggle("Enter fullscreen in landscape", isOn: $enterFullscreenInLandscape) } - private var lockLandscapeWhenEnteringFullscreenToggle: some View { - Toggle("Lock landscape on rotation", isOn: $lockLandscapeWhenEnteringFullscreen) + private var lockLandscapeOnRotationToggle: some View { + Toggle("Lock landscape on rotation", isOn: $lockLandscapeOnRotation) .disabled(!enterFullscreenInLandscape) } + + private var lockLandscapeWhenEnteringFullscreenToggle: some View { + Toggle("Rotate and lock landscape on entering fullscreen", isOn: $lockLandscapeWhenEnteringFullscreen) + } + + private var orientationFooter: some View { + Text("Orientation settings are experimental and do not yet work properly with all devices and iOS versions") + } #endif private var closePiPOnNavigationToggle: some View { diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index bec551fa..419ac9f0 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -2726,7 +2726,7 @@ INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UIRequiresFullScreen = NO; + INFOPLIST_KEY_UIRequiresFullScreen = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; @@ -2758,7 +2758,7 @@ INFOPLIST_FILE = iOS/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UIRequiresFullScreen = NO; + INFOPLIST_KEY_UIRequiresFullScreen = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";