import Defaults import Foundation import Repeat import SwiftUI final class OrientationModel { static var shared = OrientationModel() var orientation = UIInterfaceOrientation.portrait var lastOrientation: UIInterfaceOrientation? var orientationDebouncer = Debouncer(.milliseconds(300)) var orientationObserver: Any? private var player = PlayerModel.shared func configureOrientationUpdatesBasedOnAccelerometer() { let currentOrientation = OrientationTracker.shared.currentInterfaceOrientation if currentOrientation.isLandscape, Defaults[.enterFullscreenInLandscape], !Defaults[.honorSystemOrientationLock], !player.playingFullScreen, !player.currentItem.isNil, player.lockedOrientation.isNil || player.lockedOrientation!.contains(.landscape), !player.playingInPictureInPicture, player.presentingPlayer { DispatchQueue.main.async { self.player.controls.presentingControls = false self.player.enterFullScreen(showControls: false) } player.onPresentPlayer.append { Orientation.lockOrientation(.allButUpsideDown, andRotateTo: currentOrientation) } } orientationObserver = NotificationCenter.default.addObserver( forName: OrientationTracker.deviceOrientationChangedNotification, object: nil, queue: .main ) { _ in guard !Defaults[.honorSystemOrientationLock], self.player.presentingPlayer, !self.player.playingInPictureInPicture, self.player.lockedOrientation.isNil else { return } let orientation = OrientationTracker.shared.currentInterfaceOrientation guard self.lastOrientation != orientation else { return } self.lastOrientation = orientation DispatchQueue.main.async { guard Defaults[.enterFullscreenInLandscape], self.player.presentingPlayer else { return } self.orientationDebouncer.callback = { DispatchQueue.main.async { if orientation.isLandscape { self.player.controls.presentingControls = false self.player.enterFullScreen(showControls: false) Orientation.lockOrientation(OrientationTracker.shared.currentInterfaceOrientationMask, andRotateTo: orientation) } else { self.player.exitFullScreen(showControls: false) Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait) } } } self.orientationDebouncer.call() } } } func stopOrientationUpdates() { guard let observer = orientationObserver else { return } NotificationCenter.default.removeObserver(observer) } func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation? = nil) { if let rotateOrientation { self.orientation = rotateOrientation lastOrientation = rotateOrientation } Orientation.lockOrientation(orientation, andRotateTo: rotateOrientation) } }