PiP improvements

This commit is contained in:
Arkadiusz Fal 2022-08-19 00:40:46 +02:00
parent ace8c6e3ff
commit 6c6ba19df4
16 changed files with 120 additions and 162 deletions

View File

@ -34,9 +34,9 @@ final class NetworkStateModel: ObservableObject {
var needsUpdates: Bool { var needsUpdates: Bool {
if let player = player { 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
} }
} }

View File

@ -35,10 +35,7 @@ final class AVPlayerBackend: PlayerBackend {
var aspectRatio: Double { var aspectRatio: Double {
#if os(iOS) #if os(iOS)
guard let view = model?.playerLayerView else { return VideoPlayerView.defaultAspectRatio } playerLayer.videoRect.width / playerLayer.videoRect.height
let videoRect = view.playerLayer.videoRect
return videoRect.width / videoRect.height
#else #else
VideoPlayerView.defaultAspectRatio VideoPlayerView.defaultAspectRatio
#endif #endif
@ -54,7 +51,10 @@ final class AVPlayerBackend: PlayerBackend {
} }
private(set) var avPlayer = AVPlayer() private(set) var avPlayer = AVPlayer()
private(set) var playerLayer = AVPlayerLayer()
#if os(tvOS)
var controller: AppleAVPlayerViewController? var controller: AppleAVPlayerViewController?
#endif
var startPictureInPictureOnPlay = false var startPictureInPictureOnPlay = false
private var asset: AVURLAsset? private var asset: AVURLAsset?
@ -79,6 +79,8 @@ final class AVPlayerBackend: PlayerBackend {
addFrequentTimeObserver() addFrequentTimeObserver()
addInfrequentTimeObserver() addInfrequentTimeObserver()
addPlayerTimeControlStatusObserver() addPlayerTimeControlStatusObserver()
playerLayer.player = avPlayer
} }
func bestPlayable(_ streams: [Stream], maxResolution _: ResolutionSetting) -> Stream? { func bestPlayable(_ streams: [Stream], maxResolution _: ResolutionSetting) -> Stream? {
@ -157,40 +159,10 @@ final class AVPlayerBackend: PlayerBackend {
avPlayer.replaceCurrentItem(with: nil) avPlayer.replaceCurrentItem(with: nil)
} }
#if os(tvOS) func closePiP() {
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() model.pipController?.stopPictureInPicture()
guard wasPlaying else {
return
} }
play()
}
#endif
private func loadSingleAsset( private func loadSingleAsset(
_ url: URL, _ url: URL,
stream: Stream, stream: Stream,

View File

@ -324,7 +324,7 @@ final class MPVBackend: PlayerBackend {
client?.stop() client?.stop()
} }
func closePiP(wasPlaying _: Bool) {} func closePiP() {}
func updateControls() { func updateControls() {
self.logger.info("updating controls") self.logger.info("updating controls")

View File

@ -45,7 +45,7 @@ protocol PlayerBackend {
func closeItem() func closeItem()
func closePiP(wasPlaying: Bool) func closePiP()
func updateControls() func updateControls()
func startControlsUpdates() func startControlsUpdates()

View File

@ -67,6 +67,8 @@ final class PlayerModel: ObservableObject {
} }
} }
var playerBackendView = PlayerBackendView()
@Published var playerSize: CGSize = .zero { didSet { @Published var playerSize: CGSize = .zero { didSet {
#if !os(tvOS) #if !os(tvOS)
backend.setSize(playerSize.width, playerSize.height) backend.setSize(playerSize.width, playerSize.height)
@ -167,9 +169,6 @@ final class PlayerModel: ObservableObject {
#endif #endif
private var currentArtwork: MPMediaItemArtwork? private var currentArtwork: MPMediaItemArtwork?
#if !os(macOS)
var playerLayerView: PlayerLayerView!
#endif
var onPresentPlayer: (() -> Void)? var onPresentPlayer: (() -> Void)?
private var remoteCommandCenterConfigured = false private var remoteCommandCenterConfigured = false
@ -207,6 +206,14 @@ final class PlayerModel: ObservableObject {
Defaults[.activeBackend] = .mpv Defaults[.activeBackend] = .mpv
playbackMode = Defaults[.playbackMode] 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() { func show() {
@ -421,7 +428,9 @@ final class PlayerModel: ObservableObject {
return 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) changeActiveBackend(from: activeBackend, to: qualityProfileBackend)
} }
@ -464,16 +473,10 @@ final class PlayerModel: ObservableObject {
} }
if !presentingPlayer, pauseOnHidingPlayer, !playingInPictureInPicture { if !presentingPlayer, pauseOnHidingPlayer, !playingInPictureInPicture {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in DispatchQueue.main.async { [weak self] in
self?.pause() self?.pause()
} }
} }
if !presentingPlayer, !pauseOnHidingPlayer, backend.isPlaying {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
self?.play()
}
}
} }
func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) { func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) {
@ -483,6 +486,10 @@ final class PlayerModel: ObservableObject {
pause() pause()
if to == .mpv {
closePiP()
}
Defaults[.activeBackend] = to Defaults[.activeBackend] = to
self.activeBackend = to self.activeBackend = to
@ -553,6 +560,7 @@ final class PlayerModel: ObservableObject {
func closeCurrentItem(finished: Bool = false) { func closeCurrentItem(finished: Bool = false) {
pause() pause()
closePiP()
prepareCurrentItemForHistory(finished: finished) prepareCurrentItemForHistory(finished: finished)
currentItem = nil currentItem = nil
@ -562,7 +570,6 @@ final class PlayerModel: ObservableObject {
aspectRatio = VideoPlayerView.defaultAspectRatio aspectRatio = VideoPlayerView.defaultAspectRatio
resetAutoplay() resetAutoplay()
closePiP()
exitFullScreen() exitFullScreen()
#if !os(macOS) #if !os(macOS)
@ -577,14 +584,11 @@ final class PlayerModel: ObservableObject {
return return
} }
let wasPlaying = isPlaying
pause()
#if os(tvOS) #if os(tvOS)
show() show()
#endif #endif
backend.closePiP(wasPlaying: wasPlaying) backend.closePiP()
} }
func handleQueueChange() { func handleQueueChange() {

View File

@ -132,6 +132,16 @@ struct ContentView: View {
@ViewBuilder var videoPlayer: some View { @ViewBuilder var videoPlayer: some View {
if player.presentingPlayer { if player.presentingPlayer {
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() VideoPlayerView()
.environmentObject(accounts) .environmentObject(accounts)
.environmentObject(comments) .environmentObject(comments)
@ -144,8 +154,6 @@ struct ContentView: View {
.environmentObject(subscriptions) .environmentObject(subscriptions)
.environmentObject(thumbnailsModel) .environmentObject(thumbnailsModel)
.environment(\.navigationStyle, navigationStyle) .environment(\.navigationStyle, navigationStyle)
.transition(.move(edge: .bottom))
}
} }
} }

View File

@ -6,8 +6,9 @@ struct AppleAVPlayerView: UIViewRepresentable {
@EnvironmentObject<PlayerModel> private var player @EnvironmentObject<PlayerModel> private var player
func makeUIView(context _: Context) -> some UIView { func makeUIView(context _: Context) -> some UIView {
player.playerLayerView = PlayerLayerView(frame: .zero) let playerLayerView = PlayerLayerView(frame: .zero)
return player.playerLayerView playerLayerView.player = player
return playerLayerView
} }
func updateUIView(_: UIViewType, context _: Context) {} func updateUIView(_: UIViewType, context _: Context) {}

View File

@ -227,8 +227,8 @@ struct PlayerControls: View {
HStack(spacing: 20) { HStack(spacing: 20) {
fullscreenButton fullscreenButton
#if os(iOS)
pipButton pipButton
#if os(iOS)
lockOrientationButton lockOrientationButton
#endif #endif

View File

@ -15,17 +15,6 @@ struct PlayerBackendView: View {
player.mpvPlayerView player.mpvPlayerView
case .appleAVPlayer: case .appleAVPlayer:
player.avPlayerView 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 .overlay(GeometryReader { proxy in

View File

@ -1,23 +1,51 @@
import AVFoundation import AVFoundation
import Foundation import Foundation
import UIKit #if os(macOS)
import AppKit
#else
import UIKit
#endif
final class PlayerLayerView: UIView { #if os(macOS)
var playerLayer = AVPlayerLayer() final class PlayerLayerView: NSView {
var player: PlayerModel! { didSet {
wantsLayer = true
}}
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
}
override func makeBackingLayer() -> CALayer {
player.avPlayerBackend.playerLayer
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
#else
final class PlayerLayerView: UIView {
var player: PlayerModel!
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
layer.addSublayer(playerLayer)
} }
private var layerAdded = false
@available(*, unavailable) @available(*, unavailable)
required init?(coder _: NSCoder) { required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() if !layerAdded {
playerLayer.frame = bounds layerAdded = true
layer.addSublayer(player.avPlayerBackend.playerLayer)
} }
} player.avPlayerBackend.playerLayer.frame = bounds
super.layoutSubviews()
}
}
#endif

View File

@ -33,7 +33,9 @@ struct VideoDetails: View {
@StateObject private var page: Page = .first() @StateObject private var page: Page = .first()
@Environment(\.navigationStyle) private var navigationStyle @Environment(\.navigationStyle) private var navigationStyle
#if os(iOS)
@Environment(\.verticalSizeClass) private var verticalSizeClass @Environment(\.verticalSizeClass) private var verticalSizeClass
#endif
@EnvironmentObject<AccountsModel> private var accounts @EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<CommentsModel> private var comments @EnvironmentObject<CommentsModel> private var comments
@ -227,7 +229,9 @@ struct VideoDetails: View {
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
} else if video.description != nil, !video.description!.isEmpty { } else if video.description != nil, !video.description!.isEmpty {
VideoDescription(video: video, detailsSize: detailsSize) VideoDescription(video: video, detailsSize: detailsSize)
#if os(iOS)
.padding(.bottom, fullScreenLayout ? 10 : SafeArea.insets.bottom) .padding(.bottom, fullScreenLayout ? 10 : SafeArea.insets.bottom)
#endif
} else { } else {
Text("No description") Text("No description")
.foregroundColor(.secondary) .foregroundColor(.secondary)

View File

@ -245,14 +245,14 @@ struct VideoPlayerView: View {
ZStack(alignment: .bottomLeading) { ZStack(alignment: .bottomLeading) {
#if os(tvOS) #if os(tvOS)
ZStack { ZStack {
PlayerBackendView() player.playerBackendView
tvControls tvControls
} }
.ignoresSafeArea() .ignoresSafeArea()
#else #else
GeometryReader { geometry in GeometryReader { geometry in
PlayerBackendView() player.playerBackendView
#if !os(tvOS) #if !os(tvOS)
.modifier( .modifier(
VideoPlayerSizeModifier( VideoPlayerSizeModifier(

View File

@ -59,10 +59,8 @@ struct VideoContextMenuView: View {
Section { Section {
playNowButton playNowButton
#if os(iOS)
playNowInPictureInPictureButton
#endif
#if !os(tvOS) #if !os(tvOS)
playNowInPictureInPictureButton
playNowInMusicMode playNowInMusicMode
#endif #endif
} }
@ -169,7 +167,8 @@ struct VideoContextMenuView: View {
private var playNowInPictureInPictureButton: some View { private var playNowInPictureInPictureButton: some View {
Button { Button {
player.controls.startPiP(startImmediately: false) player.controls.startPiP(startImmediately: player.presentingPlayer && player.activeBackend == .appleAVPlayer)
player.hide()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
player.play(video, at: watch?.timeToRestart, showingPlayer: false) player.play(video, at: watch?.timeToRestart, showingPlayer: false)

View File

@ -161,6 +161,7 @@
37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37169AA52729E2CC0011DE61 /* AccountsBridge.swift */; }; 37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37169AA52729E2CC0011DE61 /* AccountsBridge.swift */; };
37169AA72729E2CC0011DE61 /* 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 */; }; 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 */; }; 371B7E5C27596B8400D21217 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B7E5B27596B8400D21217 /* Comment.swift */; };
371B7E5D27596B8400D21217 /* 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 */; }; 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 */; }; 37BE0BD426A1D47D0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */; };
37BE0BD626A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */; }; 37BE0BD626A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */; };
37BE0BD726A1D4A90092E2DB /* 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 */; }; 37BE0BDC26A2367F0092E2DB /* AppleAVPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */; };
37BF661C27308859008CCFB0 /* DropFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BF661B27308859008CCFB0 /* DropFavorite.swift */; }; 37BF661C27308859008CCFB0 /* DropFavorite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BF661B27308859008CCFB0 /* DropFavorite.swift */; };
37BF661D27308859008CCFB0 /* 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 = "<group>"; }; 3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; }; 372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
372CFD14285F2E2A00B0B54B /* ControlsBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsBar.swift; sourceTree = "<group>"; }; 372CFD14285F2E2A00B0B54B /* ControlsBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsBar.swift; sourceTree = "<group>"; };
373031F22838388A000CFD59 /* PlayerLayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerLayerView.swift; sourceTree = "<group>"; }; 373031F22838388A000CFD59 /* PlayerLayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerLayerView.swift; sourceTree = "<group>"; tabWidth = 5; };
373031F428383A89000CFD59 /* PiPDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPDelegate.swift; sourceTree = "<group>"; }; 373031F428383A89000CFD59 /* PiPDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPDelegate.swift; sourceTree = "<group>"; };
3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; }; 3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; };
373197D82732015300EF734F /* RelatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedView.swift; sourceTree = "<group>"; }; 373197D82732015300EF734F /* RelatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedView.swift; sourceTree = "<group>"; };
@ -1161,7 +1161,6 @@
37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; }; 37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerView.swift; sourceTree = "<group>"; };
37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; }; 37BE0BD226A1D4780092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; };
37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; }; 37BE0BD526A1D4A90092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; };
37BE0BD926A214630092E2DB /* AppleAVPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerViewController.swift; sourceTree = "<group>"; };
37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; }; 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleAVPlayerView.swift; sourceTree = "<group>"; };
37BF661B27308859008CCFB0 /* DropFavorite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavorite.swift; sourceTree = "<group>"; }; 37BF661B27308859008CCFB0 /* DropFavorite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavorite.swift; sourceTree = "<group>"; };
37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavoriteOutside.swift; sourceTree = "<group>"; }; 37BF661E27308884008CCFB0 /* DropFavoriteOutside.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropFavoriteOutside.swift; sourceTree = "<group>"; };
@ -1889,7 +1888,6 @@
children = ( children = (
374C0542272496E4009BDDBE /* AppDelegate.swift */, 374C0542272496E4009BDDBE /* AppDelegate.swift */,
37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */, 37BE0BDB26A2367F0092E2DB /* AppleAVPlayerView.swift */,
37BE0BD926A214630092E2DB /* AppleAVPlayerViewController.swift */,
37FD43DB270470B70073EE42 /* InstancesSettings.swift */, 37FD43DB270470B70073EE42 /* InstancesSettings.swift */,
3751BA7D27E63F1D007B1A60 /* MPVOGLView.swift */, 3751BA7D27E63F1D007B1A60 /* MPVOGLView.swift */,
374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */, 374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */,
@ -2972,6 +2970,7 @@
377ABC4D286E6A78009C986F /* LocationsSettings.swift in Sources */, 377ABC4D286E6A78009C986F /* LocationsSettings.swift in Sources */,
3782B95027553A6700990149 /* SearchSuggestions.swift in Sources */, 3782B95027553A6700990149 /* SearchSuggestions.swift in Sources */,
371B7E6B2759791900D21217 /* CommentsModel.swift in Sources */, 371B7E6B2759791900D21217 /* CommentsModel.swift in Sources */,
37192D5528B0D5D60012EEDD /* PlayerLayerView.swift in Sources */,
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */, 371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
3756C2AB2861151C00E4B059 /* NetworkStateModel.swift in Sources */, 3756C2AB2861151C00E4B059 /* NetworkStateModel.swift in Sources */,
375EC95A289EEB8200751258 /* QualityProfileForm.swift in Sources */, 375EC95A289EEB8200751258 /* QualityProfileForm.swift in Sources */,
@ -3075,7 +3074,6 @@
377ABC49286E5887009C986F /* Sequence+Unique.swift in Sources */, 377ABC49286E5887009C986F /* Sequence+Unique.swift in Sources */,
3748186726A7627F0084E870 /* Video+Fixtures.swift in Sources */, 3748186726A7627F0084E870 /* Video+Fixtures.swift in Sources */,
3784B23E2728B85300B09468 /* ShareButton.swift in Sources */, 3784B23E2728B85300B09468 /* ShareButton.swift in Sources */,
37BE0BDA26A214630092E2DB /* AppleAVPlayerViewController.swift in Sources */,
375F7411289DC35A00747050 /* PlayerBackendView.swift in Sources */, 375F7411289DC35A00747050 /* PlayerBackendView.swift in Sources */,
37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */, 37FEF11427EFD8580033912F /* PlaceholderCell.swift in Sources */,
37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */, 37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */,

View File

@ -1,27 +1,16 @@
import Defaults import Defaults
import SwiftUI import SwiftUI
struct AppleAVPlayerView: NSViewControllerRepresentable { struct AppleAVPlayerView: NSViewRepresentable {
@EnvironmentObject<PlayerModel> private var player @EnvironmentObject<PlayerModel> private var player
@State private var controller: AppleAVPlayerViewController? func makeNSView(context _: Context) -> some NSView {
let playerLayerView = PlayerLayerView(frame: .zero)
init(controller: AppleAVPlayerViewController? = nil) { playerLayerView.player = player
self.controller = controller
return playerLayerView
} }
func makeNSViewController(context _: Context) -> AppleAVPlayerViewController { func updateNSView(_: NSViewType, context _: Context) {}
if self.controller != nil {
return self.controller!
}
let controller = AppleAVPlayerViewController()
controller.playerModel = player
player.avPlayerBackend.controller = controller
return controller
}
func updateNSViewController(_: AppleAVPlayerViewController, context _: Context) {}
} }

View File

@ -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
}
}