mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 13:33:42 +00:00
Fix possible crashes
This commit is contained in:
parent
dc3492fd96
commit
3f871bce2c
@ -360,8 +360,8 @@ final class MPVBackend: PlayerBackend {
|
|||||||
setRate(model.currentRate)
|
setRate(model.currentRate)
|
||||||
|
|
||||||
// After the video has ended, hitting play restarts the video from the beginning.
|
// After the video has ended, hitting play restarts the video from the beginning.
|
||||||
if currentTime?.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime() &&
|
if let currentTime, currentTime.seconds.formattedAsPlaybackTime() == model.playerTime.duration.seconds.formattedAsPlaybackTime() &&
|
||||||
currentTime!.seconds > 0 && model.playerTime.duration.seconds > 0
|
currentTime.seconds > 0 && model.playerTime.duration.seconds > 0
|
||||||
{
|
{
|
||||||
seek(to: 0, seekType: .loopRestart)
|
seek(to: 0, seekType: .loopRestart)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,10 @@ final class PlaylistsModel: ObservableObject {
|
|||||||
.onSuccess { resource in
|
.onSuccess { resource in
|
||||||
self.error = nil
|
self.error = nil
|
||||||
if let playlists: [Playlist] = resource.typedContent() {
|
if let playlists: [Playlist] = resource.typedContent() {
|
||||||
self.playlists = playlists
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
self.playlists = playlists
|
||||||
|
}
|
||||||
PlaylistsCacheModel.shared.storePlaylist(account: account, playlists: playlists)
|
PlaylistsCacheModel.shared.storePlaylist(account: account, playlists: playlists)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -1,211 +0,0 @@
|
|||||||
import AVKit
|
|
||||||
import Defaults
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
final class PlayerViewController: UIViewController {
|
|
||||||
var playerLoaded = false
|
|
||||||
var commentsModel: CommentsModel!
|
|
||||||
var navigationModel: NavigationModel!
|
|
||||||
var playerModel: PlayerModel!
|
|
||||||
var subscriptionsModel: SubscriptionsModel!
|
|
||||||
var playerView = AVPlayerViewController()
|
|
||||||
|
|
||||||
let persistenceController = PersistenceController.shared
|
|
||||||
|
|
||||||
#if !os(tvOS)
|
|
||||||
var aspectRatio: Double? {
|
|
||||||
let ratio = Double(playerView.videoBounds.width) / Double(playerView.videoBounds.height)
|
|
||||||
|
|
||||||
guard ratio.isFinite else {
|
|
||||||
return VideoPlayerView.defaultAspectRatio // swiftlint:disable:this implicit_return
|
|
||||||
}
|
|
||||||
|
|
||||||
return [ratio, 1.0].max()!
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
|
||||||
super.viewWillAppear(animated)
|
|
||||||
|
|
||||||
loadPlayer()
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
if !playerView.isBeingPresented, !playerView.isBeingDismissed {
|
|
||||||
present(playerView, animated: false)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
override func viewDidDisappear(_ animated: Bool) {
|
|
||||||
super.viewDidDisappear(animated)
|
|
||||||
|
|
||||||
if !playerModel.presentingPlayer, !Defaults[.pauseOnHidingPlayer], !playerModel.isPlaying {
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
|
||||||
self?.playerModel.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
func loadPlayer() {
|
|
||||||
guard !playerLoaded else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
playerModel.controller = self
|
|
||||||
playerView.player = playerModel.player
|
|
||||||
playerView.allowsPictureInPicturePlayback = true
|
|
||||||
#if os(iOS)
|
|
||||||
if #available(iOS 14.2, *) {
|
|
||||||
playerView.canStartPictureInPictureAutomaticallyFromInline = true
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
playerView.delegate = self
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
var infoViewControllers = [UIHostingController<AnyView>]()
|
|
||||||
if CommentsModel.enabled {
|
|
||||||
infoViewControllers.append(infoViewController([.comments], title: "Comments"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var queueSections = [NowPlayingView.ViewSection.playingNext]
|
|
||||||
if Defaults[.showHistoryInPlayer] {
|
|
||||||
queueSections.append(.playedPreviously)
|
|
||||||
}
|
|
||||||
|
|
||||||
infoViewControllers.append(contentsOf: [
|
|
||||||
infoViewController([.related], title: "Related"),
|
|
||||||
infoViewController(queueSections, title: "Queue")
|
|
||||||
])
|
|
||||||
|
|
||||||
playerView.customInfoViewControllers = infoViewControllers
|
|
||||||
#else
|
|
||||||
embedViewController()
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
func infoViewController(
|
|
||||||
_ sections: [NowPlayingView.ViewSection],
|
|
||||||
title: String
|
|
||||||
) -> UIHostingController<AnyView> {
|
|
||||||
let controller = UIHostingController(
|
|
||||||
rootView:
|
|
||||||
AnyV/Users/arek/Developer/Yattee/Shared/Player/PlayerViewController.swift.iew(
|
|
||||||
NowPlayingView(sections: sections, inInfoViewController: true)
|
|
||||||
.frame(maxHeight: 600)
|
|
||||||
.environmentObject(commentsModel)
|
|
||||||
.environmentObject(playerModel)
|
|
||||||
.environmentObject(subscriptionsModel)
|
|
||||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
controller.title = title
|
|
||||||
|
|
||||||
return controller
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
func embedViewController() {
|
|
||||||
playerView.view.frame = view.bounds
|
|
||||||
|
|
||||||
addChild(playerView)
|
|
||||||
view.addSubview(playerView.view)
|
|
||||||
|
|
||||||
playerView.didMove(toParent: self)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
extension PlayerViewController: AVPlayerViewControllerDelegate {
|
|
||||||
func playerViewControllerShouldDismiss(_: AVPlayerViewController) -> Bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_: AVPlayerViewController) -> Bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewControllerWillBeginDismissalTransition(_: AVPlayerViewController) {
|
|
||||||
if Defaults[.pauseOnHidingPlayer] {
|
|
||||||
playerModel.pause()
|
|
||||||
}
|
|
||||||
dismiss(animated: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewControllerDidEndDismissalTransition(_: AVPlayerViewController) {}
|
|
||||||
|
|
||||||
func playerViewController(
|
|
||||||
_: AVPlayerViewController,
|
|
||||||
willBeginFullScreenPresentationWithAnimationCoordinator context: UIViewControllerTransitionCoordinator
|
|
||||||
) {
|
|
||||||
playerModel.playingFullscreen = true
|
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
if !context.isCancelled, Defaults[.lockLandscapeWhenEnteringFullscreen] {
|
|
||||||
Orientation.lockOrientation(.landscape, andRotateTo: UIDevice.current.orientation.isLandscape ? nil : .landscapeRight)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewController(
|
|
||||||
_: AVPlayerViewController,
|
|
||||||
willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator
|
|
||||||
) {
|
|
||||||
let wasPlaying = playerModel.isPlaying
|
|
||||||
coordinator.animate(alongsideTransition: nil) { context in
|
|
||||||
#if os(iOS)
|
|
||||||
if wasPlaying {
|
|
||||||
self.playerModel.play()
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if !context.isCancelled {
|
|
||||||
#if os(iOS)
|
|
||||||
self.playerModel.lockedOrientation = nil
|
|
||||||
if Defaults[.enterFullscreenInLandscape] {
|
|
||||||
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.playerModel.playingFullscreen = false
|
|
||||||
|
|
||||||
if wasPlaying {
|
|
||||||
self.playerModel.play()
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewController(
|
|
||||||
_: AVPlayerViewController,
|
|
||||||
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
|
|
||||||
) {
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
||||||
if self.navigationModel.presentingChannel {
|
|
||||||
self.playerModel.playerNavigationLinkActive = true
|
|
||||||
} else {
|
|
||||||
self.playerModel.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
#if os(tvOS)
|
|
||||||
if self.playerModel.playingInPictureInPicture {
|
|
||||||
self.present(self.playerView, animated: false) {
|
|
||||||
completionHandler(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
completionHandler(true)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {
|
|
||||||
playerModel.playingInPictureInPicture = true
|
|
||||||
playerModel.playerNavigationLinkActive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {
|
|
||||||
playerModel.playingInPictureInPicture = false
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user