2022-08-28 17:18:49 +00:00
|
|
|
import Defaults
|
|
|
|
import Foundation
|
2024-09-01 10:42:31 +00:00
|
|
|
import Logging
|
2023-05-20 14:04:58 +00:00
|
|
|
import Repeat
|
2022-08-28 17:18:49 +00:00
|
|
|
import SwiftUI
|
|
|
|
|
2023-05-20 14:04:58 +00:00
|
|
|
final class OrientationModel {
|
|
|
|
static var shared = OrientationModel()
|
2024-09-01 10:42:31 +00:00
|
|
|
let logger = Logger(label: "stream.yattee.orientation.model")
|
2023-05-20 14:04:58 +00:00
|
|
|
|
|
|
|
var orientation = UIInterfaceOrientation.portrait
|
|
|
|
var lastOrientation: UIInterfaceOrientation?
|
|
|
|
var orientationDebouncer = Debouncer(.milliseconds(300))
|
2023-09-23 13:07:27 +00:00
|
|
|
var orientationObserver: Any?
|
2023-05-20 14:04:58 +00:00
|
|
|
|
2024-09-06 13:11:31 +00:00
|
|
|
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
|
|
|
|
@Default(.enterFullscreenInLandscape) private var enterFullscreenInLandscape
|
|
|
|
|
2023-05-20 14:04:58 +00:00
|
|
|
private var player = PlayerModel.shared
|
|
|
|
|
2024-09-01 10:42:31 +00:00
|
|
|
func startOrientationUpdates() {
|
|
|
|
// Ensure the orientation observer is active
|
2022-08-28 17:18:49 +00:00
|
|
|
orientationObserver = NotificationCenter.default.addObserver(
|
|
|
|
forName: OrientationTracker.deviceOrientationChangedNotification,
|
|
|
|
object: nil,
|
|
|
|
queue: .main
|
|
|
|
) { _ in
|
2024-09-01 10:42:31 +00:00
|
|
|
self.logger.info("Notification received: Device orientation changed.")
|
|
|
|
|
|
|
|
// We only allow .portrait and are not showing the player
|
2024-09-06 13:11:31 +00:00
|
|
|
guard (!self.player.presentingPlayer && !self.lockPortraitWhenBrowsing) || self.player.presentingPlayer
|
2022-08-28 17:18:49 +00:00
|
|
|
else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let orientation = OrientationTracker.shared.currentInterfaceOrientation
|
2024-09-01 10:42:31 +00:00
|
|
|
self.logger.info("Current interface orientation: \(orientation)")
|
2022-08-28 17:18:49 +00:00
|
|
|
|
2024-09-01 10:42:31 +00:00
|
|
|
// Always update lastOrientation to keep track of the latest state
|
|
|
|
if self.lastOrientation != orientation {
|
|
|
|
self.lastOrientation = orientation
|
|
|
|
self.logger.info("Orientation changed to: \(orientation)")
|
|
|
|
} else {
|
|
|
|
self.logger.info("Orientation has not changed.")
|
2022-08-28 17:18:49 +00:00
|
|
|
}
|
|
|
|
|
2024-09-01 10:42:31 +00:00
|
|
|
// Only take action if the player is active and presenting
|
2024-09-06 13:11:31 +00:00
|
|
|
guard (!self.player.isOrientationLocked && !self.player.playingInPictureInPicture) || (!self.lockPortraitWhenBrowsing && !self.player.presentingPlayer) || (!self.lockPortraitWhenBrowsing && self.player.presentingPlayer && !self.player.isOrientationLocked)
|
2024-09-01 10:42:31 +00:00
|
|
|
else {
|
|
|
|
self.logger.info("Only updating orientation without actions.")
|
|
|
|
return
|
|
|
|
}
|
2022-08-28 17:18:49 +00:00
|
|
|
|
|
|
|
DispatchQueue.main.async {
|
2023-05-20 14:04:58 +00:00
|
|
|
self.orientationDebouncer.callback = {
|
2022-08-31 19:24:46 +00:00
|
|
|
DispatchQueue.main.async {
|
|
|
|
if orientation.isLandscape {
|
2024-09-06 13:11:31 +00:00
|
|
|
if self.enterFullscreenInLandscape, self.player.presentingPlayer {
|
2024-09-01 10:42:31 +00:00
|
|
|
self.logger.info("Entering fullscreen because orientation is landscape.")
|
|
|
|
self.player.controls.presentingControls = false
|
|
|
|
self.player.enterFullScreen(showControls: false)
|
|
|
|
}
|
2022-08-31 19:24:46 +00:00
|
|
|
Orientation.lockOrientation(OrientationTracker.shared.currentInterfaceOrientationMask, andRotateTo: orientation)
|
|
|
|
} else {
|
2024-09-01 10:42:31 +00:00
|
|
|
self.logger.info("Exiting fullscreen because orientation is portrait.")
|
|
|
|
if self.player.playingFullScreen {
|
|
|
|
self.player.exitFullScreen(showControls: false)
|
|
|
|
}
|
2024-09-06 13:11:31 +00:00
|
|
|
if self.lockPortraitWhenBrowsing {
|
2024-09-01 10:42:31 +00:00
|
|
|
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
|
|
|
|
} else {
|
|
|
|
Orientation.lockOrientation(OrientationTracker.shared.currentInterfaceOrientationMask, andRotateTo: orientation)
|
|
|
|
}
|
2022-08-31 19:24:46 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-28 17:18:49 +00:00
|
|
|
}
|
2023-05-20 14:04:58 +00:00
|
|
|
self.orientationDebouncer.call()
|
2022-08-28 17:18:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 14:04:58 +00:00
|
|
|
func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation? = nil) {
|
2024-09-01 10:42:31 +00:00
|
|
|
logger.info("Locking orientation to: \(orientation), rotating to: \(String(describing: rotateOrientation)).")
|
2023-05-20 14:04:58 +00:00
|
|
|
if let rotateOrientation {
|
|
|
|
self.orientation = rotateOrientation
|
|
|
|
lastOrientation = rotateOrientation
|
|
|
|
}
|
|
|
|
Orientation.lockOrientation(orientation, andRotateTo: rotateOrientation)
|
|
|
|
}
|
2022-08-28 17:18:49 +00:00
|
|
|
}
|