mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +00:00
Fixed PiP kinda + Crash issue
This commit is contained in:
parent
c42216f793
commit
39e366e896
3 changed files with 73 additions and 69 deletions
|
|
@ -12,7 +12,7 @@ import MediaPlayer
|
|||
import AVFoundation
|
||||
import MarqueeLabel
|
||||
|
||||
class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||
class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDelegate, AVPlayerViewControllerDelegate {
|
||||
private var airplayButton: AVRoutePickerView!
|
||||
let module: ScrapingModule
|
||||
let streamURL: String
|
||||
|
|
@ -68,13 +68,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
return UserDefaults.standard.bool(forKey: "doubleTapSeekEnabled")
|
||||
}
|
||||
|
||||
private var isPipButtonVisible: Bool {
|
||||
if UserDefaults.standard.object(forKey: "pipButtonVisible") == nil {
|
||||
return true
|
||||
}
|
||||
return UserDefaults.standard.bool(forKey: "pipButtonVisible")
|
||||
}
|
||||
|
||||
private var isAutoplayEnabled: Bool {
|
||||
if UserDefaults.standard.object(forKey: "autoplayNext") == nil {
|
||||
return true
|
||||
|
|
@ -82,7 +75,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
return UserDefaults.standard.bool(forKey: "autoplayNext")
|
||||
}
|
||||
private var pipController: AVPictureInPictureController?
|
||||
private var pipButton: UIButton!
|
||||
|
||||
var portraitButtonVisibleConstraints: [NSLayoutConstraint] = []
|
||||
var portraitButtonHiddenConstraints: [NSLayoutConstraint] = []
|
||||
|
|
@ -187,7 +179,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
skip85Button,
|
||||
controlButtonsContainer,
|
||||
volumeSliderHostingView,
|
||||
pipButton,
|
||||
airplayButton,
|
||||
timeBatteryContainer,
|
||||
endTimeIcon,
|
||||
|
|
@ -207,7 +198,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
|
||||
views.append(contentsOf: view.subviews.filter {
|
||||
$0 is UIVisualEffectView ||
|
||||
($0.layer.cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != pipButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
|
||||
($0.layer.cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
|
||||
})
|
||||
|
||||
return views
|
||||
|
|
@ -496,7 +487,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
view.addSubview(capsuleContainer)
|
||||
capsuleContainer.alpha = isControlsVisible ? 1.0 : 0.0
|
||||
|
||||
let buttons: [UIView] = [airplayButton, pipButton, lockButton, dimButton]
|
||||
let buttons: [UIView] = [airplayButton, lockButton, dimButton]
|
||||
for btn in buttons {
|
||||
btn.removeFromSuperview()
|
||||
capsuleContainer.addSubview(btn)
|
||||
|
|
@ -728,7 +719,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
skipIntroButton?.removeFromSuperview()
|
||||
skipOutroButton?.removeFromSuperview()
|
||||
skip85Button?.removeFromSuperview()
|
||||
pipButton?.removeFromSuperview()
|
||||
airplayButton?.removeFromSuperview()
|
||||
menuButton?.removeFromSuperview()
|
||||
speedButton?.removeFromSuperview()
|
||||
|
|
@ -807,6 +797,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
playerViewController = AVPlayerViewController()
|
||||
playerViewController.player = player
|
||||
playerViewController.showsPlaybackControls = false
|
||||
playerViewController.delegate = self
|
||||
|
||||
addChild(playerViewController)
|
||||
if playerViewController.view.superview == nil {
|
||||
view.addSubview(playerViewController.view)
|
||||
|
|
@ -2205,18 +2197,23 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
}
|
||||
}
|
||||
|
||||
@objc private func pipButtonTapped(_ sender: UIButton) {
|
||||
guard let pip = pipController else { return }
|
||||
if pip.isPictureInPictureActive {
|
||||
pip.stopPictureInPicture()
|
||||
} else {
|
||||
pip.startPictureInPicture()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func startPipIfNeeded() {
|
||||
Logger.shared.log("PIP", type: "Genral")
|
||||
pipController!.startPictureInPicture()
|
||||
guard let pipController = pipController else {
|
||||
Logger.shared.log("PiP controller not available", type: "Error")
|
||||
return
|
||||
}
|
||||
|
||||
guard AVPictureInPictureController.isPictureInPictureSupported() else {
|
||||
Logger.shared.log("PiP not supported on this device", type: "Error")
|
||||
return
|
||||
}
|
||||
|
||||
guard !pipController.isPictureInPictureActive else {
|
||||
Logger.shared.log("PiP already active", type: "Debug")
|
||||
return
|
||||
}
|
||||
|
||||
pipController.startPictureInPicture()
|
||||
}
|
||||
|
||||
@objc private func lockTapped() {
|
||||
|
|
@ -3568,47 +3565,20 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
|
|||
|
||||
playerViewController.allowsPictureInPicturePlayback = true
|
||||
|
||||
let playerLayerContainer = UIView()
|
||||
playerLayerContainer.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.insertSubview(playerLayerContainer, at: 0)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
playerLayerContainer.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
playerLayerContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
playerLayerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
playerLayerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor)
|
||||
])
|
||||
|
||||
let pipPlayerLayer = AVPlayerLayer(player: playerViewController.player)
|
||||
pipPlayerLayer.frame = playerViewController.view.layer.bounds
|
||||
pipPlayerLayer.videoGravity = .resizeAspect
|
||||
|
||||
playerViewController.view.layer.insertSublayer(pipPlayerLayer, at: 0)
|
||||
pipController = AVPictureInPictureController(playerLayer: pipPlayerLayer)
|
||||
if let playerLayer = playerViewController.view.layer.sublayers?.first(where: { $0 is AVPlayerLayer }) as? AVPlayerLayer {
|
||||
pipController = AVPictureInPictureController(playerLayer: playerLayer)
|
||||
} else {
|
||||
pipController = AVPictureInPictureController(playerLayer: AVPlayerLayer(player: player))
|
||||
}
|
||||
pipController?.delegate = self
|
||||
|
||||
let Image = UIImage(systemName: "pip", withConfiguration: cfg)
|
||||
pipButton = UIButton(type: .system)
|
||||
pipButton.setImage(Image, for: .normal)
|
||||
pipButton.tintColor = .white
|
||||
pipButton.addTarget(self, action: #selector(pipButtonTapped(_:)), for: .touchUpInside)
|
||||
|
||||
controlsContainerView.addSubview(pipButton)
|
||||
pipButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
pipButton.centerYAnchor.constraint(equalTo: dimButton.centerYAnchor),
|
||||
pipButton.trailingAnchor.constraint(equalTo: dimButton.leadingAnchor, constant: -8),
|
||||
pipButton.widthAnchor.constraint(equalToConstant: 30),
|
||||
pipButton.heightAnchor.constraint(equalToConstant: 24),
|
||||
airplayButton.centerYAnchor.constraint(equalTo: pipButton.centerYAnchor),
|
||||
airplayButton.trailingAnchor.constraint(equalTo: pipButton.leadingAnchor, constant: -4),
|
||||
airplayButton.centerYAnchor.constraint(equalTo: dimButton.centerYAnchor),
|
||||
airplayButton.trailingAnchor.constraint(equalTo: dimButton.leadingAnchor, constant: -8),
|
||||
airplayButton.widthAnchor.constraint(equalToConstant: 24),
|
||||
airplayButton.heightAnchor.constraint(equalToConstant: 24)
|
||||
])
|
||||
|
||||
pipButton.isHidden = !isPipButtonVisible
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(startPipIfNeeded), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
||||
}
|
||||
|
||||
|
|
@ -3701,11 +3671,11 @@ class GradientOverlayButton: UIButton {
|
|||
|
||||
extension CustomMediaPlayerViewController: AVPictureInPictureControllerDelegate {
|
||||
func pictureInPictureControllerWillStartPictureInPicture(_ pipController: AVPictureInPictureController) {
|
||||
pipButton.alpha = 0.5
|
||||
// PiP will start
|
||||
}
|
||||
|
||||
func pictureInPictureControllerDidStopPictureInPicture(_ pipController: AVPictureInPictureController) {
|
||||
pipButton.alpha = 1.0
|
||||
// PiP did stop
|
||||
}
|
||||
|
||||
func pictureInPictureController(_ pipController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
|
||||
|
|
@ -3713,6 +3683,30 @@ extension CustomMediaPlayerViewController: AVPictureInPictureControllerDelegate
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - AVPlayerViewControllerDelegate
|
||||
extension CustomMediaPlayerViewController {
|
||||
func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
|
||||
let windowScene = UIApplication.shared.connectedScenes
|
||||
.filter { $0.activationState == .foregroundActive }
|
||||
.compactMap { $0 as? UIWindowScene }
|
||||
.first
|
||||
|
||||
let window = windowScene?.windows.first(where: { $0.isKeyWindow })
|
||||
|
||||
if let topVC = window?.rootViewController?.topmostViewController() {
|
||||
if topVC != self {
|
||||
topVC.present(self, animated: true) {
|
||||
completionHandler(true)
|
||||
}
|
||||
} else {
|
||||
completionHandler(true)
|
||||
}
|
||||
} else {
|
||||
completionHandler(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CustomMediaPlayerViewController {
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
return true
|
||||
|
|
@ -3897,3 +3891,21 @@ extension CustomMediaPlayerViewController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIViewController {
|
||||
func topmostViewController() -> UIViewController {
|
||||
if let presented = self.presentedViewController {
|
||||
return presented.topmostViewController()
|
||||
}
|
||||
|
||||
if let navigation = self as? UINavigationController {
|
||||
return navigation.visibleViewController?.topmostViewController() ?? navigation
|
||||
}
|
||||
|
||||
if let tabBar = self as? UITabBarController {
|
||||
return tabBar.selectedViewController?.topmostViewController() ?? tabBar
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ extension JSContext {
|
|||
if httpMethod == "GET" && !bodyIsEmpty {
|
||||
Logger.shared.log("GET request must not have a body", type: "Error")
|
||||
DispatchQueue.main.async {
|
||||
reject.call(withArguments: ["GET request must not have a body"])
|
||||
resolve.call(withArguments: ["GET request must not have a body"])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,7 +204,6 @@ struct SettingsViewPlayer: View {
|
|||
@AppStorage("skip85Visible") private var skip85Visible: Bool = true
|
||||
@AppStorage("doubleTapSeekEnabled") private var doubleTapSeekEnabled: Bool = false
|
||||
@AppStorage("skipIntroOutroVisible") private var skipIntroOutroVisible: Bool = true
|
||||
@AppStorage("pipButtonVisible") private var pipButtonVisible: Bool = true
|
||||
@AppStorage("autoplayNext") private var autoplayNext: Bool = true
|
||||
|
||||
@AppStorage("videoQualityWiFi") private var wifiQuality: String = VideoQualityPreference.defaultWiFiPreference.rawValue
|
||||
|
|
@ -241,13 +240,6 @@ struct SettingsViewPlayer: View {
|
|||
showDivider: true
|
||||
)
|
||||
|
||||
SettingsToggleRow(
|
||||
icon: "pip",
|
||||
title: NSLocalizedString("Show PiP Button", comment: ""),
|
||||
isOn: $pipButtonVisible,
|
||||
showDivider: true
|
||||
)
|
||||
|
||||
SettingsToggleRow(
|
||||
icon: "play.circle.fill",
|
||||
title: NSLocalizedString("Autoplay Next", comment: ""),
|
||||
|
|
|
|||
Loading…
Reference in a new issue