Skip to content

Commit 39e366e

Browse files
committed
Fixed PiP kinda + Crash issue
1 parent c42216f commit 39e366e

3 files changed

Lines changed: 73 additions & 69 deletions

File tree

Sora/MediaUtils/CustomPlayer/CustomPlayer.swift

Lines changed: 72 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import MediaPlayer
1212
import AVFoundation
1313
import MarqueeLabel
1414

15-
class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDelegate {
15+
class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDelegate, AVPlayerViewControllerDelegate {
1616
private var airplayButton: AVRoutePickerView!
1717
let module: ScrapingModule
1818
let streamURL: String
@@ -68,21 +68,13 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
6868
return UserDefaults.standard.bool(forKey: "doubleTapSeekEnabled")
6969
}
7070

71-
private var isPipButtonVisible: Bool {
72-
if UserDefaults.standard.object(forKey: "pipButtonVisible") == nil {
73-
return true
74-
}
75-
return UserDefaults.standard.bool(forKey: "pipButtonVisible")
76-
}
77-
7871
private var isAutoplayEnabled: Bool {
7972
if UserDefaults.standard.object(forKey: "autoplayNext") == nil {
8073
return true
8174
}
8275
return UserDefaults.standard.bool(forKey: "autoplayNext")
8376
}
8477
private var pipController: AVPictureInPictureController?
85-
private var pipButton: UIButton!
8678

8779
var portraitButtonVisibleConstraints: [NSLayoutConstraint] = []
8880
var portraitButtonHiddenConstraints: [NSLayoutConstraint] = []
@@ -187,7 +179,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
187179
skip85Button,
188180
controlButtonsContainer,
189181
volumeSliderHostingView,
190-
pipButton,
191182
airplayButton,
192183
timeBatteryContainer,
193184
endTimeIcon,
@@ -207,7 +198,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
207198

208199
views.append(contentsOf: view.subviews.filter {
209200
$0 is UIVisualEffectView ||
210-
($0.layer.cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != pipButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
201+
($0.layer.cornerRadius > 0 && $0 != dismissButton && $0 != lockButton && $0 != dimButton && $0 != holdSpeedIndicator && $0 != volumeSliderHostingView)
211202
})
212203

213204
return views
@@ -496,7 +487,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
496487
view.addSubview(capsuleContainer)
497488
capsuleContainer.alpha = isControlsVisible ? 1.0 : 0.0
498489

499-
let buttons: [UIView] = [airplayButton, pipButton, lockButton, dimButton]
490+
let buttons: [UIView] = [airplayButton, lockButton, dimButton]
500491
for btn in buttons {
501492
btn.removeFromSuperview()
502493
capsuleContainer.addSubview(btn)
@@ -728,7 +719,6 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
728719
skipIntroButton?.removeFromSuperview()
729720
skipOutroButton?.removeFromSuperview()
730721
skip85Button?.removeFromSuperview()
731-
pipButton?.removeFromSuperview()
732722
airplayButton?.removeFromSuperview()
733723
menuButton?.removeFromSuperview()
734724
speedButton?.removeFromSuperview()
@@ -807,6 +797,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
807797
playerViewController = AVPlayerViewController()
808798
playerViewController.player = player
809799
playerViewController.showsPlaybackControls = false
800+
playerViewController.delegate = self
801+
810802
addChild(playerViewController)
811803
if playerViewController.view.superview == nil {
812804
view.addSubview(playerViewController.view)
@@ -2205,18 +2197,23 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
22052197
}
22062198
}
22072199

2208-
@objc private func pipButtonTapped(_ sender: UIButton) {
2209-
guard let pip = pipController else { return }
2210-
if pip.isPictureInPictureActive {
2211-
pip.stopPictureInPicture()
2212-
} else {
2213-
pip.startPictureInPicture()
2214-
}
2215-
}
2216-
22172200
@objc private func startPipIfNeeded() {
2218-
Logger.shared.log("PIP", type: "Genral")
2219-
pipController!.startPictureInPicture()
2201+
guard let pipController = pipController else {
2202+
Logger.shared.log("PiP controller not available", type: "Error")
2203+
return
2204+
}
2205+
2206+
guard AVPictureInPictureController.isPictureInPictureSupported() else {
2207+
Logger.shared.log("PiP not supported on this device", type: "Error")
2208+
return
2209+
}
2210+
2211+
guard !pipController.isPictureInPictureActive else {
2212+
Logger.shared.log("PiP already active", type: "Debug")
2213+
return
2214+
}
2215+
2216+
pipController.startPictureInPicture()
22202217
}
22212218

22222219
@objc private func lockTapped() {
@@ -3568,47 +3565,20 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
35683565

35693566
playerViewController.allowsPictureInPicturePlayback = true
35703567

3571-
let playerLayerContainer = UIView()
3572-
playerLayerContainer.translatesAutoresizingMaskIntoConstraints = false
3573-
view.insertSubview(playerLayerContainer, at: 0)
3574-
3575-
NSLayoutConstraint.activate([
3576-
playerLayerContainer.topAnchor.constraint(equalTo: view.topAnchor),
3577-
playerLayerContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
3578-
playerLayerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
3579-
playerLayerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor)
3580-
])
3581-
3582-
let pipPlayerLayer = AVPlayerLayer(player: playerViewController.player)
3583-
pipPlayerLayer.frame = playerViewController.view.layer.bounds
3584-
pipPlayerLayer.videoGravity = .resizeAspect
3585-
3586-
playerViewController.view.layer.insertSublayer(pipPlayerLayer, at: 0)
3587-
pipController = AVPictureInPictureController(playerLayer: pipPlayerLayer)
3568+
if let playerLayer = playerViewController.view.layer.sublayers?.first(where: { $0 is AVPlayerLayer }) as? AVPlayerLayer {
3569+
pipController = AVPictureInPictureController(playerLayer: playerLayer)
3570+
} else {
3571+
pipController = AVPictureInPictureController(playerLayer: AVPlayerLayer(player: player))
3572+
}
35883573
pipController?.delegate = self
35893574

3590-
let Image = UIImage(systemName: "pip", withConfiguration: cfg)
3591-
pipButton = UIButton(type: .system)
3592-
pipButton.setImage(Image, for: .normal)
3593-
pipButton.tintColor = .white
3594-
pipButton.addTarget(self, action: #selector(pipButtonTapped(_:)), for: .touchUpInside)
3595-
3596-
controlsContainerView.addSubview(pipButton)
3597-
pipButton.translatesAutoresizingMaskIntoConstraints = false
3598-
35993575
NSLayoutConstraint.activate([
3600-
pipButton.centerYAnchor.constraint(equalTo: dimButton.centerYAnchor),
3601-
pipButton.trailingAnchor.constraint(equalTo: dimButton.leadingAnchor, constant: -8),
3602-
pipButton.widthAnchor.constraint(equalToConstant: 30),
3603-
pipButton.heightAnchor.constraint(equalToConstant: 24),
3604-
airplayButton.centerYAnchor.constraint(equalTo: pipButton.centerYAnchor),
3605-
airplayButton.trailingAnchor.constraint(equalTo: pipButton.leadingAnchor, constant: -4),
3576+
airplayButton.centerYAnchor.constraint(equalTo: dimButton.centerYAnchor),
3577+
airplayButton.trailingAnchor.constraint(equalTo: dimButton.leadingAnchor, constant: -8),
36063578
airplayButton.widthAnchor.constraint(equalToConstant: 24),
36073579
airplayButton.heightAnchor.constraint(equalToConstant: 24)
36083580
])
36093581

3610-
pipButton.isHidden = !isPipButtonVisible
3611-
36123582
NotificationCenter.default.addObserver(self, selector: #selector(startPipIfNeeded), name: UIApplication.didEnterBackgroundNotification, object: nil)
36133583
}
36143584

@@ -3701,18 +3671,42 @@ class GradientOverlayButton: UIButton {
37013671

37023672
extension CustomMediaPlayerViewController: AVPictureInPictureControllerDelegate {
37033673
func pictureInPictureControllerWillStartPictureInPicture(_ pipController: AVPictureInPictureController) {
3704-
pipButton.alpha = 0.5
3674+
// PiP will start
37053675
}
37063676

37073677
func pictureInPictureControllerDidStopPictureInPicture(_ pipController: AVPictureInPictureController) {
3708-
pipButton.alpha = 1.0
3678+
// PiP did stop
37093679
}
37103680

37113681
func pictureInPictureController(_ pipController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
37123682
Logger.shared.log("PiP failed to start: \(error.localizedDescription)", type: "Error")
37133683
}
37143684
}
37153685

3686+
// MARK: - AVPlayerViewControllerDelegate
3687+
extension CustomMediaPlayerViewController {
3688+
func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
3689+
let windowScene = UIApplication.shared.connectedScenes
3690+
.filter { $0.activationState == .foregroundActive }
3691+
.compactMap { $0 as? UIWindowScene }
3692+
.first
3693+
3694+
let window = windowScene?.windows.first(where: { $0.isKeyWindow })
3695+
3696+
if let topVC = window?.rootViewController?.topmostViewController() {
3697+
if topVC != self {
3698+
topVC.present(self, animated: true) {
3699+
completionHandler(true)
3700+
}
3701+
} else {
3702+
completionHandler(true)
3703+
}
3704+
} else {
3705+
completionHandler(false)
3706+
}
3707+
}
3708+
}
3709+
37163710
extension CustomMediaPlayerViewController {
37173711
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
37183712
return true
@@ -3897,3 +3891,21 @@ extension CustomMediaPlayerViewController {
38973891
}
38983892
}
38993893
}
3894+
3895+
extension UIViewController {
3896+
func topmostViewController() -> UIViewController {
3897+
if let presented = self.presentedViewController {
3898+
return presented.topmostViewController()
3899+
}
3900+
3901+
if let navigation = self as? UINavigationController {
3902+
return navigation.visibleViewController?.topmostViewController() ?? navigation
3903+
}
3904+
3905+
if let tabBar = self as? UITabBarController {
3906+
return tabBar.selectedViewController?.topmostViewController() ?? tabBar
3907+
}
3908+
3909+
return self
3910+
}
3911+
}

Sora/Utlis & Misc/Extensions/JavaScriptCore+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ extension JSContext {
165165
if httpMethod == "GET" && !bodyIsEmpty {
166166
Logger.shared.log("GET request must not have a body", type: "Error")
167167
DispatchQueue.main.async {
168-
reject.call(withArguments: ["GET request must not have a body"])
168+
resolve.call(withArguments: ["GET request must not have a body"])
169169
}
170170
return
171171
}

Sora/Views/SettingsView/SettingsSubViews/SettingsViewPlayer.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ struct SettingsViewPlayer: View {
204204
@AppStorage("skip85Visible") private var skip85Visible: Bool = true
205205
@AppStorage("doubleTapSeekEnabled") private var doubleTapSeekEnabled: Bool = false
206206
@AppStorage("skipIntroOutroVisible") private var skipIntroOutroVisible: Bool = true
207-
@AppStorage("pipButtonVisible") private var pipButtonVisible: Bool = true
208207
@AppStorage("autoplayNext") private var autoplayNext: Bool = true
209208

210209
@AppStorage("videoQualityWiFi") private var wifiQuality: String = VideoQualityPreference.defaultWiFiPreference.rawValue
@@ -241,13 +240,6 @@ struct SettingsViewPlayer: View {
241240
showDivider: true
242241
)
243242

244-
SettingsToggleRow(
245-
icon: "pip",
246-
title: NSLocalizedString("Show PiP Button", comment: ""),
247-
isOn: $pipButtonVisible,
248-
showDivider: true
249-
)
250-
251243
SettingsToggleRow(
252244
icon: "play.circle.fill",
253245
title: NSLocalizedString("Autoplay Next", comment: ""),

0 commit comments

Comments
 (0)