1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-16 07:10:31 +05:30
yattee/Shared/Player/AppleAVPlayerView.swift

164 lines
6.6 KiB
Swift
Raw Normal View History

2022-05-21 02:53:14 +05:30
import AVKit
2021-09-25 13:48:22 +05:30
import Defaults
2021-07-19 04:02:46 +05:30
import SwiftUI
2023-05-21 02:19:10 +05:30
#if !os(macOS)
final class AppleAVPlayerViewControllerDelegate: NSObject, AVPlayerViewControllerDelegate {
2023-05-21 22:41:11 +05:30
#if os(iOS)
@Default(.rotateToLandscapeOnEnterFullScreen) private var rotateToLandscapeOnEnterFullScreen
@Default(.avPlayerUsesSystemControls) private var avPlayerUsesSystemControls
#endif
2023-05-21 02:19:10 +05:30
var player: PlayerModel { .shared }
func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_: AVPlayerViewController) -> Bool {
false
}
2023-06-08 02:49:00 +05:30
#if os(iOS)
func playerViewController(_: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator _: UIViewControllerTransitionCoordinator) {
2023-05-21 22:41:11 +05:30
guard rotateToLandscapeOnEnterFullScreen.isRotating else { return }
if PlayerModel.shared.currentVideoIsLandscape {
let delay = PlayerModel.shared.activeBackend == .appleAVPlayer && avPlayerUsesSystemControls ? 0.8 : 0
// not sure why but first rotation call is ignore so doing rotate to same orientation first
Delay.by(delay) {
let orientation = OrientationTracker.shared.currentDeviceOrientation.isLandscape ? OrientationTracker.shared.currentInterfaceOrientation : self.rotateToLandscapeOnEnterFullScreen.interaceOrientation
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: OrientationTracker.shared.currentInterfaceOrientation)
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: orientation)
}
}
2023-06-08 02:49:00 +05:30
}
2023-05-21 02:19:10 +05:30
2023-06-08 02:49:00 +05:30
func playerViewController(_: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
let wasPlaying = player.isPlaying
coordinator.animate(alongsideTransition: nil) { context in
2023-05-21 02:19:10 +05:30
if wasPlaying {
self.player.play()
}
2023-06-08 02:49:00 +05:30
if !context.isCancelled {
#if os(iOS)
self.player.lockedOrientation = nil
2023-05-21 02:19:10 +05:30
2023-06-08 02:49:00 +05:30
if Constants.isIPhone {
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
}
2023-05-21 02:19:10 +05:30
2023-06-08 02:49:00 +05:30
if wasPlaying {
self.player.play()
}
2023-05-21 02:19:10 +05:30
2023-06-08 02:49:00 +05:30
self.player.playingFullScreen = false
#endif
}
2023-05-21 02:19:10 +05:30
}
}
2023-06-08 02:49:00 +05:30
func playerViewController(_: AVPlayerViewController, restoreUserInterfaceForFullScreenExitWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
withAnimation(nil) {
player.presentingPlayer = true
}
completionHandler(true)
}
#endif
2023-05-21 02:19:10 +05:30
func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {}
func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {}
func playerViewControllerDidStartPictureInPicture(_: AVPlayerViewController) {
player.playingInPictureInPicture = true
player.avPlayerBackend.startPictureInPictureOnPlay = false
player.avPlayerBackend.startPictureInPictureOnSwitch = false
player.controls.objectWillChange.send()
if Defaults[.closePlayerOnOpeningPiP] { Delay.by(0.1) { self.player.hide() } }
}
func playerViewControllerDidStopPictureInPicture(_: AVPlayerViewController) {
player.playingInPictureInPicture = false
player.controls.objectWillChange.send()
}
func playerViewController(_: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
player.presentingPlayer = true
withAnimation(.linear(duration: 0.3)) {
self.player.playingInPictureInPicture = false
Delay.by(0.5) {
completionHandler(true)
Delay.by(0.2) {
self.player.play()
}
}
}
}
}
#endif
2022-08-21 02:35:40 +05:30
#if os(iOS)
2023-05-21 02:19:10 +05:30
struct AppleAVPlayerView: UIViewControllerRepresentable {
@State private var controller = AVPlayerViewController()
func makeUIViewController(context _: Context) -> AVPlayerViewController {
setupController()
return controller
}
func updateUIViewController(_: AVPlayerViewController, context _: Context) {
setupController()
}
func setupController() {
controller.delegate = PlayerModel.shared.appleAVPlayerViewControllerDelegate
controller.allowsPictureInPicturePlayback = true
if #available(iOS 14.2, *) {
controller.canStartPictureInPictureAutomaticallyFromInline = true
}
PlayerModel.shared.avPlayerBackend.controller = controller
}
}
struct AppleAVPlayerLayerView: UIViewRepresentable {
2022-08-21 02:35:40 +05:30
func makeUIView(context _: Context) -> some UIView {
2023-05-21 02:19:10 +05:30
PlayerLayerView(frame: .zero)
2022-08-21 02:35:40 +05:30
}
func updateUIView(_: UIViewType, context _: Context) {}
2021-07-19 04:02:46 +05:30
}
2023-05-21 02:19:10 +05:30
#elseif os(tvOS)
2022-08-21 02:35:40 +05:30
struct AppleAVPlayerView: UIViewControllerRepresentable {
func makeUIViewController(context _: Context) -> AppleAVPlayerViewController {
let controller = AppleAVPlayerViewController()
PlayerModel.shared.avPlayerBackend.controller = controller
2022-08-21 02:35:40 +05:30
return controller
}
func updateUIViewController(_: AppleAVPlayerViewController, context _: Context) {
PlayerModel.shared.rebuildTVMenu()
2022-08-21 02:35:40 +05:30
}
}
2023-05-21 02:19:10 +05:30
#else
struct AppleAVPlayerView: NSViewRepresentable {
func makeNSView(context _: Context) -> some NSView {
let view = AVPlayerView()
view.player = PlayerModel.shared.avPlayerBackend.avPlayer
view.showsFullScreenToggleButton = true
view.allowsPictureInPicturePlayback = true
2023-05-23 02:18:11 +05:30
view.pictureInPictureDelegate = MacOSPiPDelegate.shared
2023-05-21 02:19:10 +05:30
return view
}
func updateNSView(_: NSViewType, context _: Context) {}
}
struct AppleAVPlayerLayerView: NSViewRepresentable {
func makeNSView(context _: Context) -> some NSView {
PlayerLayerView(frame: .zero)
}
func updateNSView(_: NSViewType, context _: Context) {}
}
2022-08-21 02:35:40 +05:30
#endif