diff --git a/Model/NetworkStateModel.swift b/Model/NetworkStateModel.swift index f4d2aa90..cc06af26 100644 --- a/Model/NetworkStateModel.swift +++ b/Model/NetworkStateModel.swift @@ -34,9 +34,9 @@ final class NetworkStateModel: ObservableObject { var needsUpdates: Bool { if let player = player { - return pausedForCache || player.isSeeking || player.isLoadingVideo || player.controls.presentingControlsOverlay + return !player.currentItem.isNil && (pausedForCache || player.isSeeking || player.isLoadingVideo || player.controls.presentingControlsOverlay) } - return pausedForCache + return false } } diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 5fca90bf..40c717e2 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -35,10 +35,7 @@ final class AVPlayerBackend: PlayerBackend { var aspectRatio: Double { #if os(iOS) - guard let view = model?.playerLayerView else { return VideoPlayerView.defaultAspectRatio } - - let videoRect = view.playerLayer.videoRect - return videoRect.width / videoRect.height + playerLayer.videoRect.width / playerLayer.videoRect.height #else VideoPlayerView.defaultAspectRatio #endif @@ -54,7 +51,10 @@ final class AVPlayerBackend: PlayerBackend { } private(set) var avPlayer = AVPlayer() - var controller: AppleAVPlayerViewController? + private(set) var playerLayer = AVPlayerLayer() + #if os(tvOS) + var controller: AppleAVPlayerViewController? + #endif var startPictureInPictureOnPlay = false private var asset: AVURLAsset? @@ -79,6 +79,8 @@ final class AVPlayerBackend: PlayerBackend { addFrequentTimeObserver() addInfrequentTimeObserver() addPlayerTimeControlStatusObserver() + + playerLayer.player = avPlayer } func bestPlayable(_ streams: [Stream], maxResolution _: ResolutionSetting) -> Stream? { @@ -157,39 +159,9 @@ final class AVPlayerBackend: PlayerBackend { avPlayer.replaceCurrentItem(with: nil) } - #if os(tvOS) - func closePiP(wasPlaying: Bool) { - let item = avPlayer.currentItem - let time = avPlayer.currentTime() - - avPlayer.replaceCurrentItem(with: nil) - - guard !item.isNil else { - return - } - - avPlayer.seek(to: time) - avPlayer.replaceCurrentItem(with: item) - - guard wasPlaying else { - return - } - - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in - self?.play() - } - } - #else - func closePiP(wasPlaying: Bool) { - model.pipController?.stopPictureInPicture() - - guard wasPlaying else { - return - } - - play() - } - #endif + func closePiP() { + model.pipController?.stopPictureInPicture() + } private func loadSingleAsset( _ url: URL, diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index ec11a577..a2dc6fc7 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -324,7 +324,7 @@ final class MPVBackend: PlayerBackend { client?.stop() } - func closePiP(wasPlaying _: Bool) {} + func closePiP() {} func updateControls() { self.logger.info("updating controls") diff --git a/Model/Player/Backends/PlayerBackend.swift b/Model/Player/Backends/PlayerBackend.swift index ae8f17d0..b3d65b0b 100644 --- a/Model/Player/Backends/PlayerBackend.swift +++ b/Model/Player/Backends/PlayerBackend.swift @@ -45,7 +45,7 @@ protocol PlayerBackend { func closeItem() - func closePiP(wasPlaying: Bool) + func closePiP() func updateControls() func startControlsUpdates() diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index 11a330b5..046c8b42 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -67,6 +67,8 @@ final class PlayerModel: ObservableObject { } } + var playerBackendView = PlayerBackendView() + @Published var playerSize: CGSize = .zero { didSet { #if !os(tvOS) backend.setSize(playerSize.width, playerSize.height) @@ -167,9 +169,6 @@ final class PlayerModel: ObservableObject { #endif private var currentArtwork: MPMediaItemArtwork? - #if !os(macOS) - var playerLayerView: PlayerLayerView! - #endif var onPresentPlayer: (() -> Void)? private var remoteCommandCenterConfigured = false @@ -207,6 +206,14 @@ final class PlayerModel: ObservableObject { Defaults[.activeBackend] = .mpv playbackMode = Defaults[.playbackMode] + + guard pipController.isNil else { return } + pipController = .init(playerLayer: avPlayerBackend.playerLayer) + let pipDelegate = PiPDelegate() + pipDelegate.player = self + + self.pipDelegate = pipDelegate + pipController?.delegate = pipDelegate } func show() { @@ -421,7 +428,9 @@ final class PlayerModel: ObservableObject { return } - if let qualityProfileBackend = qualityProfile?.backend, qualityProfileBackend != activeBackend { + if let qualityProfileBackend = qualityProfile?.backend, qualityProfileBackend != activeBackend, + qualityProfileBackend == .appleAVPlayer || !(avPlayerBackend.startPictureInPictureOnPlay || playingInPictureInPicture) + { changeActiveBackend(from: activeBackend, to: qualityProfileBackend) } @@ -464,16 +473,10 @@ final class PlayerModel: ObservableObject { } if !presentingPlayer, pauseOnHidingPlayer, !playingInPictureInPicture { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in + DispatchQueue.main.async { [weak self] in self?.pause() } } - - if !presentingPlayer, !pauseOnHidingPlayer, backend.isPlaying { - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in - self?.play() - } - } } func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) { @@ -483,6 +486,10 @@ final class PlayerModel: ObservableObject { pause() + if to == .mpv { + closePiP() + } + Defaults[.activeBackend] = to self.activeBackend = to @@ -553,6 +560,7 @@ final class PlayerModel: ObservableObject { func closeCurrentItem(finished: Bool = false) { pause() + closePiP() prepareCurrentItemForHistory(finished: finished) currentItem = nil @@ -562,7 +570,6 @@ final class PlayerModel: ObservableObject { aspectRatio = VideoPlayerView.defaultAspectRatio resetAutoplay() - closePiP() exitFullScreen() #if !os(macOS) @@ -577,14 +584,11 @@ final class PlayerModel: ObservableObject { return } - let wasPlaying = isPlaying - pause() - #if os(tvOS) show() #endif - backend.closePiP(wasPlaying: wasPlaying) + backend.closePiP() } func handleQueueChange() { diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index fa177d1e..5d1c4891 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -132,21 +132,29 @@ struct ContentView: View { @ViewBuilder var videoPlayer: some View { if player.presentingPlayer { - VideoPlayerView() - .environmentObject(accounts) - .environmentObject(comments) - .environmentObject(instances) - .environmentObject(navigation) - .environmentObject(player) - .environmentObject(playerControls) - .environmentObject(playlists) - .environmentObject(recents) - .environmentObject(subscriptions) - .environmentObject(thumbnailsModel) - .environment(\.navigationStyle, navigationStyle) + playerView .transition(.move(edge: .bottom)) + } else if player.activeBackend == .appleAVPlayer { + #if os(iOS) + playerView.offset(y: UIScreen.main.bounds.height) + #endif } } + + var playerView: some View { + VideoPlayerView() + .environmentObject(accounts) + .environmentObject(comments) + .environmentObject(instances) + .environmentObject(navigation) + .environmentObject(player) + .environmentObject(playerControls) + .environmentObject(playlists) + .environmentObject(recents) + .environmentObject(subscriptions) + .environmentObject(thumbnailsModel) + .environment(\.navigationStyle, navigationStyle) + } } struct ContentView_Previews: PreviewProvider { diff --git a/Shared/Player/AppleAVPlayerView.swift b/Shared/Player/AppleAVPlayerView.swift index 7e558e6d..8a112bc8 100644 --- a/Shared/Player/AppleAVPlayerView.swift +++ b/Shared/Player/AppleAVPlayerView.swift @@ -6,8 +6,9 @@ struct AppleAVPlayerView: UIViewRepresentable { @EnvironmentObject private var player func makeUIView(context _: Context) -> some UIView { - player.playerLayerView = PlayerLayerView(frame: .zero) - return player.playerLayerView + let playerLayerView = PlayerLayerView(frame: .zero) + playerLayerView.player = player + return playerLayerView } func updateUIView(_: UIViewType, context _: Context) {} diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift index ae46490b..3baedcf5 100644 --- a/Shared/Player/Controls/PlayerControls.swift +++ b/Shared/Player/Controls/PlayerControls.swift @@ -227,8 +227,8 @@ struct PlayerControls: View { HStack(spacing: 20) { fullscreenButton + pipButton #if os(iOS) - pipButton lockOrientationButton #endif diff --git a/Shared/Player/PlayerBackendView.swift b/Shared/Player/PlayerBackendView.swift index ec889b1c..b13e3082 100644 --- a/Shared/Player/PlayerBackendView.swift +++ b/Shared/Player/PlayerBackendView.swift @@ -15,17 +15,6 @@ struct PlayerBackendView: View { player.mpvPlayerView case .appleAVPlayer: player.avPlayerView - #if os(iOS) - .onAppear { - player.pipController = .init(playerLayer: player.playerLayerView.playerLayer) - let pipDelegate = PiPDelegate() - pipDelegate.player = player - - player.pipDelegate = pipDelegate - player.pipController?.delegate = pipDelegate - player.playerLayerView.playerLayer.player = player.avPlayerBackend.avPlayer - } - #endif } } .overlay(GeometryReader { proxy in diff --git a/Shared/Player/PlayerLayerView.swift b/Shared/Player/PlayerLayerView.swift index a23cefcc..a66b28f4 100644 --- a/Shared/Player/PlayerLayerView.swift +++ b/Shared/Player/PlayerLayerView.swift @@ -1,23 +1,51 @@ import AVFoundation import Foundation -import UIKit +#if os(macOS) + import AppKit +#else + import UIKit +#endif -final class PlayerLayerView: UIView { - var playerLayer = AVPlayerLayer() +#if os(macOS) + final class PlayerLayerView: NSView { + var player: PlayerModel! { didSet { + wantsLayer = true + }} - override init(frame: CGRect) { - super.init(frame: frame) + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + } - layer.addSublayer(playerLayer) + override func makeBackingLayer() -> CALayer { + player.avPlayerBackend.playerLayer + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } } +#else + final class PlayerLayerView: UIView { + var player: PlayerModel! - @available(*, unavailable) - required init?(coder _: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + override init(frame: CGRect) { + super.init(frame: frame) + } - override func layoutSubviews() { - super.layoutSubviews() - playerLayer.frame = bounds + private var layerAdded = false + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func layoutSubviews() { + if !layerAdded { + layerAdded = true + layer.addSublayer(player.avPlayerBackend.playerLayer) + } + player.avPlayerBackend.playerLayer.frame = bounds + super.layoutSubviews() + } } -} +#endif diff --git a/Shared/Player/VideoDetails.swift b/Shared/Player/VideoDetails.swift index b269fccb..944aec2a 100644 --- a/Shared/Player/VideoDetails.swift +++ b/Shared/Player/VideoDetails.swift @@ -33,7 +33,9 @@ struct VideoDetails: View { @StateObject private var page: Page = .first() @Environment(\.navigationStyle) private var navigationStyle - @Environment(\.verticalSizeClass) private var verticalSizeClass + #if os(iOS) + @Environment(\.verticalSizeClass) private var verticalSizeClass + #endif @EnvironmentObject private var accounts @EnvironmentObject private var comments @@ -227,7 +229,9 @@ struct VideoDetails: View { .redacted(reason: .placeholder) } else if video.description != nil, !video.description!.isEmpty { VideoDescription(video: video, detailsSize: detailsSize) + #if os(iOS) .padding(.bottom, fullScreenLayout ? 10 : SafeArea.insets.bottom) + #endif } else { Text("No description") .foregroundColor(.secondary) diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index a0c1d84a..c02a30fc 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -245,14 +245,14 @@ struct VideoPlayerView: View { ZStack(alignment: .bottomLeading) { #if os(tvOS) ZStack { - PlayerBackendView() + player.playerBackendView tvControls } .ignoresSafeArea() #else GeometryReader { geometry in - PlayerBackendView() + player.playerBackendView #if !os(tvOS) .modifier( VideoPlayerSizeModifier( diff --git a/Shared/Views/VideoContextMenuView.swift b/Shared/Views/VideoContextMenuView.swift index b3ca3836..6bb3fc0e 100644 --- a/Shared/Views/VideoContextMenuView.swift +++ b/Shared/Views/VideoContextMenuView.swift @@ -59,10 +59,8 @@ struct VideoContextMenuView: View { Section { playNowButton - #if os(iOS) - playNowInPictureInPictureButton - #endif #if !os(tvOS) + playNowInPictureInPictureButton playNowInMusicMode #endif } @@ -169,7 +167,8 @@ struct VideoContextMenuView: View { private var playNowInPictureInPictureButton: some View { Button { - player.controls.startPiP(startImmediately: false) + player.controls.startPiP(startImmediately: player.presentingPlayer && player.activeBackend == .appleAVPlayer) + player.hide() DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { player.play(video, at: watch?.timeToRestart, showingPlayer: false) diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index b9a1a2f4..c9f48084 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ 37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37169AA52729E2CC0011DE61 /* AccountsBridge.swift */; }; 37169AA72729E2CC0011DE61 /* AccountsBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37169AA52729E2CC0011DE61 /* AccountsBridge.swift */; }; 37169AA82729E2CC0011DE61 /* AccountsBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37169AA52729E2CC0011DE61 /* AccountsBridge.swift */; }; + 37192D5528B0D5D60012EEDD /* PlayerLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F22838388A000CFD59 /* PlayerLayerView.swift */; }; 371B7E5C27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; }; 371B7E5D27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; }; 371B7E5E27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; }; @@ -623,7 +624,6 @@ 37BE0BD426A1D47D0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */; }; 37BE0BD626A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */; }; 37BE0BD726A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */; }; - 37BE0BDA26A214630092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD926A214630092E2DB /* AppleAVPlayerViewController.swift */; }; 37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */; }; 37BF661C27308859008CCFB0 /* DropFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BF661B27308859008CCFB0 /* DropFavorite.swift */; }; 37BF661D27308859008CCFB0 /* DropFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BF661B27308859008CCFB0 /* DropFavorite.swift */; }; @@ -1000,7 +1000,7 @@ 3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = ""; }; 372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = ""; }; 372CFD14285F2E2A00B0B54B /* ControlsBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsBar.swift; sourceTree = ""; }; - 373031F22838388A000CFD59 /* PlayerLayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerLayerView.swift; sourceTree = ""; }; + 373031F22838388A000CFD59 /* PlayerLayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerLayerView.swift; sourceTree = ""; tabWidth = 5; }; 373031F428383A89000CFD59 /* PiPDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPDelegate.swift; sourceTree = ""; }; 3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = ""; }; 373197D82732015300EF734F /* RelatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedView.swift; sourceTree = ""; }; @@ -1161,7 +1161,6 @@ 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = ""; }; 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = ""; }; 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = ""; }; - 37BE0BD926A214630092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = ""; }; 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = ""; }; 37BF661B27308859008CCFB0 /* DropFavorite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavorite.swift; sourceTree = ""; }; 37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavoriteOutside.swift; sourceTree = ""; }; @@ -1889,7 +1888,6 @@ children = ( 374C0542272496E4009BDDBE /* AppDelegate.swift */, 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */, - 37BE0BD926A214630092E2DB /* AppleAVPlayerViewController.swift */, 37FD43DB270470B70073EE42 /* InstancesSettings.swift */, 3751BA7D27E63F1D007B1A60 /* MPVOGLView.swift */, 374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */, @@ -2972,6 +2970,7 @@ 377ABC4D286E6A78009C986F /* LocationsSettings.swift in Sources */, 3782B95027553A6700990149 /* SearchSuggestions.swift in Sources */, 371B7E6B2759791900D21217 /* CommentsModel.swift in Sources */, + 37192D5528B0D5D60012EEDD /* PlayerLayerView.swift in Sources */, 371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */, 3756C2AB2861151C00E4B059 /* NetworkStateModel.swift in Sources */, 375EC95A289EEB8200751258 /* QualityProfileForm.swift in Sources */, @@ -3075,7 +3074,6 @@ 377ABC49286E5887009C986F /* Sequence+Unique.swift in Sources */, 3748186726A7627F0084E870 /* Video+Fixtures.swift in Sources */, 3784B23E2728B85300B09468 /* ShareButton.swift in Sources */, - 37BE0BDA26A214630092E2DB /* AppleAVPlayerViewController.swift in Sources */, 375F7411289DC35A00747050 /* PlayerBackendView.swift in Sources */, 37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */, 37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */, diff --git a/macOS/AppleAVPlayerView.swift b/macOS/AppleAVPlayerView.swift index 16a384c0..800cc379 100644 --- a/macOS/AppleAVPlayerView.swift +++ b/macOS/AppleAVPlayerView.swift @@ -1,27 +1,16 @@ import Defaults import SwiftUI -struct AppleAVPlayerView: NSViewControllerRepresentable { +struct AppleAVPlayerView: NSViewRepresentable { @EnvironmentObject private var player - @State private var controller: AppleAVPlayerViewController? + func makeNSView(context _: Context) -> some NSView { + let playerLayerView = PlayerLayerView(frame: .zero) - init(controller: AppleAVPlayerViewController? = nil) { - self.controller = controller + playerLayerView.player = player + + return playerLayerView } - func makeNSViewController(context _: Context) -> AppleAVPlayerViewController { - if self.controller != nil { - return self.controller! - } - - let controller = AppleAVPlayerViewController() - - controller.playerModel = player - player.avPlayerBackend.controller = controller - - return controller - } - - func updateNSViewController(_: AppleAVPlayerViewController, context _: Context) {} + func updateNSView(_: NSViewType, context _: Context) {} } diff --git a/macOS/AppleAVPlayerViewController.swift b/macOS/AppleAVPlayerViewController.swift deleted file mode 100644 index a6c5073a..00000000 --- a/macOS/AppleAVPlayerViewController.swift +++ /dev/null @@ -1,34 +0,0 @@ -import AVKit -import SwiftUI - -final class AppleAVPlayerViewController: NSViewController { - var playerModel: PlayerModel! - var playerView = AVPlayerView() - var pictureInPictureDelegate = PictureInPictureDelegate() - - var aspectRatio: Double? { - let ratio = Double(playerView.videoBounds.width) / Double(playerView.videoBounds.height) - - if !ratio.isFinite { - return VideoPlayerView.defaultAspectRatio - } - - return [ratio, 1.0].max()! - } - - override func viewDidDisappear() { - super.viewDidDisappear() - } - - override func loadView() { - playerView.player = playerModel.avPlayerBackend.avPlayer - pictureInPictureDelegate.playerModel = playerModel - - playerView.controlsStyle = .none - playerView.allowsPictureInPicturePlayback = true - - playerView.pictureInPictureDelegate = pictureInPictureDelegate - - view = playerView - } -}