@bluebillywig/react-native-bb-player 8.42.14 → 8.42.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/BBPlayerModule.swift +1 -1
- package/ios/BBPlayerView.swift +300 -305
- package/ios/BBPlayerViewManager.swift +6 -0
- package/ios/BBShortsViewManager.swift +6 -0
- package/package.json +1 -1
- package/plugin/build/withIos.d.ts +6 -0
- package/plugin/build/withIos.d.ts.map +1 -1
- package/plugin/build/withIos.js +6 -33
- package/react-native-bb-player.podspec +12 -21
- package/ios/BBPlayerViewController.swift +0 -352
- package/ios/BBPlayerViewControllerDelegate.swift +0 -48
|
@@ -12,6 +12,12 @@ class BBPlayerViewManager: RCTViewManager {
|
|
|
12
12
|
return true
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Override moduleName to expose as "BBPlayerView" instead of default "BBPlayer"
|
|
16
|
+
// This is required for Fabric interop to find the component correctly
|
|
17
|
+
@objc override static func moduleName() -> String! {
|
|
18
|
+
return "BBPlayerView"
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
// MARK: - Helper to get view by tag
|
|
16
22
|
|
|
17
23
|
private func getView(_ reactTag: NSNumber) -> BBPlayerView? {
|
|
@@ -12,6 +12,12 @@ class BBShortsViewManager: RCTViewManager {
|
|
|
12
12
|
return true
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Override moduleName to expose as "BBShortsView" instead of default "BBShorts"
|
|
16
|
+
// This is required for Fabric interop to find the component correctly
|
|
17
|
+
@objc override static func moduleName() -> String! {
|
|
18
|
+
return "BBShortsView"
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
// MARK: - Helper to get view by tag
|
|
16
22
|
|
|
17
23
|
private func getView(_ reactTag: NSNumber) -> BBShortsView? {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bluebillywig/react-native-bb-player",
|
|
3
|
-
"version": "8.42.
|
|
3
|
+
"version": "8.42.15",
|
|
4
4
|
"description": "Blue Billywig Native Video Player for React Native - iOS AVPlayer and Android ExoPlayer integration",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -2,6 +2,12 @@ import { ConfigPlugin } from "expo/config-plugins";
|
|
|
2
2
|
import type { BBPlayerPluginProps } from "./index";
|
|
3
3
|
/**
|
|
4
4
|
* Configures iOS for the Blue Billywig Player SDK
|
|
5
|
+
*
|
|
6
|
+
* Note: BlueBillywigNativePlayerKit-iOS is available on CocoaPods trunk,
|
|
7
|
+
* so no custom pod source is needed.
|
|
8
|
+
*
|
|
9
|
+
* The SDK is automatically linked via React Native's autolinking mechanism
|
|
10
|
+
* through react-native.config.js. No manual pod configuration is needed.
|
|
5
11
|
*/
|
|
6
12
|
export declare const withIosBBPlayer: ConfigPlugin<BBPlayerPluginProps>;
|
|
7
13
|
//# sourceMappingURL=withIos.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withIos.d.ts","sourceRoot":"","sources":["../src/withIos.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"withIos.d.ts","sourceRoot":"","sources":["../src/withIos.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,CAAC,mBAAmB,CAU7D,CAAC"}
|
package/plugin/build/withIos.js
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withIosBBPlayer = void 0;
|
|
4
4
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
|
-
const BB_POD_SOURCE = "https://github.com/nickkraakman/test-specs.git";
|
|
6
|
-
const BB_POD_COMMENT = "# Blue Billywig SDK Pod Source";
|
|
7
5
|
/**
|
|
8
6
|
* Configures iOS for the Blue Billywig Player SDK
|
|
7
|
+
*
|
|
8
|
+
* Note: BlueBillywigNativePlayerKit-iOS is available on CocoaPods trunk,
|
|
9
|
+
* so no custom pod source is needed.
|
|
10
|
+
*
|
|
11
|
+
* The SDK is automatically linked via React Native's autolinking mechanism
|
|
12
|
+
* through react-native.config.js. No manual pod configuration is needed.
|
|
9
13
|
*/
|
|
10
14
|
const withIosBBPlayer = (config, props) => {
|
|
11
|
-
// Add BB pod source to Podfile
|
|
12
|
-
config = withBBPodSource(config);
|
|
13
15
|
// Optionally add background audio capability
|
|
14
16
|
if (props.enableBackgroundAudio) {
|
|
15
17
|
config = withBackgroundAudio(config);
|
|
@@ -17,35 +19,6 @@ const withIosBBPlayer = (config, props) => {
|
|
|
17
19
|
return config;
|
|
18
20
|
};
|
|
19
21
|
exports.withIosBBPlayer = withIosBBPlayer;
|
|
20
|
-
/**
|
|
21
|
-
* Adds the Blue Billywig CocoaPods source to the Podfile
|
|
22
|
-
*/
|
|
23
|
-
const withBBPodSource = (config) => {
|
|
24
|
-
return (0, config_plugins_1.withPodfile)(config, (config) => {
|
|
25
|
-
const podfile = config.modResults.contents;
|
|
26
|
-
// Check if already added
|
|
27
|
-
if (podfile.includes(BB_POD_SOURCE)) {
|
|
28
|
-
return config;
|
|
29
|
-
}
|
|
30
|
-
// Add source at the top of the Podfile (after any existing sources)
|
|
31
|
-
const sourceBlock = `${BB_POD_COMMENT}\nsource '${BB_POD_SOURCE}'\n`;
|
|
32
|
-
// Check if there's already a source line
|
|
33
|
-
if (podfile.includes("source '")) {
|
|
34
|
-
// Add after existing sources
|
|
35
|
-
const lastSourceIndex = podfile.lastIndexOf("source '");
|
|
36
|
-
const endOfLine = podfile.indexOf("\n", lastSourceIndex);
|
|
37
|
-
config.modResults.contents =
|
|
38
|
-
podfile.slice(0, endOfLine + 1) +
|
|
39
|
-
sourceBlock +
|
|
40
|
-
podfile.slice(endOfLine + 1);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
// Add at the beginning
|
|
44
|
-
config.modResults.contents = sourceBlock + "\n" + podfile;
|
|
45
|
-
}
|
|
46
|
-
return config;
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
22
|
/**
|
|
50
23
|
* Adds UIBackgroundModes with 'audio' to Info.plist for background audio playback
|
|
51
24
|
*/
|
|
@@ -2,18 +2,22 @@ require 'json'
|
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
|
|
5
|
+
# Use a fallback version for local development if version is 0.0.0-development
|
|
6
|
+
# This prevents CocoaPods from trying to validate a non-existent git tag
|
|
7
|
+
version = package['version']
|
|
8
|
+
if version.start_with?('0.0.0')
|
|
9
|
+
version = '0.0.1-local'
|
|
10
|
+
end
|
|
7
11
|
|
|
8
12
|
Pod::Spec.new do |s|
|
|
9
13
|
s.name = 'react-native-bb-player'
|
|
10
|
-
s.version =
|
|
14
|
+
s.version = version
|
|
11
15
|
s.summary = package['description']
|
|
12
16
|
s.description = 'React Native Module for Blue Billywig Native Player SDK'
|
|
13
17
|
s.license = package['license']
|
|
14
18
|
s.author = 'Blue Billywig'
|
|
15
19
|
s.homepage = 'https://github.com/bluebillywig/react-native-bb-player'
|
|
16
|
-
s.platforms = { :ios => '
|
|
20
|
+
s.platforms = { :ios => '14.0' }
|
|
17
21
|
s.swift_version = '5.4'
|
|
18
22
|
s.source = { :git => 'https://github.com/bluebillywig/react-native-bb-player.git', :tag => "v#{s.version}" }
|
|
19
23
|
s.static_framework = true
|
|
@@ -22,28 +26,15 @@ Pod::Spec.new do |s|
|
|
|
22
26
|
s.dependency 'BlueBillywigNativePlayerKit-iOS', '~> 8.42.0'
|
|
23
27
|
s.dependency 'BlueBillywigNativePlayerKit-iOS/GoogleCastSDK', '~> 8.42.0'
|
|
24
28
|
|
|
25
|
-
# TurboModule dependencies
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
s.dependency 'RCT-Folly'
|
|
29
|
-
s.dependency 'RCTRequired'
|
|
30
|
-
s.dependency 'RCTTypeSafety'
|
|
31
|
-
s.dependency 'ReactCommon/turbomodule/core'
|
|
32
|
-
end
|
|
29
|
+
# Note: TurboModule/New Architecture dependencies (React-Codegen, RCT-Folly, etc.)
|
|
30
|
+
# are automatically provided by React Native when New Architecture is enabled.
|
|
31
|
+
# No need to specify them here as they would create duplicate/conflicting deps.
|
|
33
32
|
|
|
34
33
|
# Swift/Objective-C compatibility
|
|
35
|
-
|
|
34
|
+
s.pod_target_xcconfig = {
|
|
36
35
|
'DEFINES_MODULE' => 'YES',
|
|
37
36
|
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
# Add compiler flag for New Architecture
|
|
41
|
-
if new_arch_enabled
|
|
42
|
-
xcconfig['OTHER_CPLUSPLUSFLAGS'] = '$(inherited) -DRCT_NEW_ARCH_ENABLED'
|
|
43
|
-
xcconfig['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++17'
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
s.pod_target_xcconfig = xcconfig
|
|
47
|
-
|
|
48
39
|
s.source_files = "ios/**/*.{h,m,mm,swift,hpp,cpp}"
|
|
49
40
|
end
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
import BBNativePlayerKit
|
|
2
|
-
import bbnativeshared
|
|
3
|
-
|
|
4
|
-
class BBPlayerViewController: UIViewController, BBNativePlayerViewDelegate {
|
|
5
|
-
var playerView: BBNativePlayerView?
|
|
6
|
-
var setViewSize: ((CGSize) -> Void)?
|
|
7
|
-
var lastHeight: CGFloat = 0
|
|
8
|
-
var jsonUrl: String = ""
|
|
9
|
-
var options: [String: Any] = [:]
|
|
10
|
-
var allowCollapseExpand: Bool {
|
|
11
|
-
return options["allowCollapseExpand"] as? Bool ?? false
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
weak var delegate: BBPlayerViewControllerDelegate?
|
|
15
|
-
|
|
16
|
-
// MARK: - Orientation Support
|
|
17
|
-
|
|
18
|
-
/// Always support all orientations at the view controller level
|
|
19
|
-
/// The AppDelegate enforces portrait-only for the main screen
|
|
20
|
-
/// This allows the fullscreen modal to rotate freely
|
|
21
|
-
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
22
|
-
return .allButUpsideDown
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/// Allow auto-rotation
|
|
26
|
-
override var shouldAutorotate: Bool {
|
|
27
|
-
return true
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/// Don't override preferredInterfaceOrientationForPresentation
|
|
31
|
-
/// Let the fullscreen modal (AVPlayerViewController) use its own preferred orientation
|
|
32
|
-
|
|
33
|
-
// NOTE: Removed refreshPlayerViewHierarchy() - it was unused dead code that forced
|
|
34
|
-
// GPU redraw on every layer in the hierarchy, which would cause severe heat/battery drain
|
|
35
|
-
|
|
36
|
-
override func viewDidLayoutSubviews() {
|
|
37
|
-
super.viewDidLayoutSubviews()
|
|
38
|
-
|
|
39
|
-
if allowCollapseExpand {
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Report height changes back to React Native for layout
|
|
44
|
-
let height = playerView?.bounds.size.height ?? 0
|
|
45
|
-
let size = CGSize(width: Double.nan, height: height)
|
|
46
|
-
|
|
47
|
-
if size.height != lastHeight {
|
|
48
|
-
setViewSize?(size)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
lastHeight = size.height
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
func setupPlayer() {
|
|
55
|
-
NSLog("BBPlayer: setupPlayer called")
|
|
56
|
-
playerView?.removeFromSuperview()
|
|
57
|
-
|
|
58
|
-
// Use the SDK's factory method which properly sets up the view controller hierarchy
|
|
59
|
-
playerView = BBNativePlayer.createPlayerView(
|
|
60
|
-
uiViewController: self,
|
|
61
|
-
frame: view.frame,
|
|
62
|
-
jsonUrl: jsonUrl,
|
|
63
|
-
options: options
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
if let playerView = playerView {
|
|
67
|
-
view.addSubview(playerView)
|
|
68
|
-
|
|
69
|
-
playerView.translatesAutoresizingMaskIntoConstraints = false
|
|
70
|
-
|
|
71
|
-
// Use full edge constraints to ensure playerView fills the view controller's view
|
|
72
|
-
// This is essential for fullscreen to work properly
|
|
73
|
-
NSLayoutConstraint.activate([
|
|
74
|
-
playerView.topAnchor.constraint(equalTo: view.topAnchor),
|
|
75
|
-
playerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
|
76
|
-
playerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
|
77
|
-
playerView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
|
|
78
|
-
])
|
|
79
|
-
|
|
80
|
-
playerView.delegate = self
|
|
81
|
-
NSLog("BBPlayer: Player view created and delegate set to: \(String(describing: playerView.delegate))")
|
|
82
|
-
} else {
|
|
83
|
-
NSLog("BBPlayer: ERROR - playerView is nil after createPlayerView!")
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
func bbNativePlayerView(didRequestCollapse playerView: BBNativePlayerView) {
|
|
88
|
-
if allowCollapseExpand {
|
|
89
|
-
let newSize = CGSize(width: Double.nan, height: 0)
|
|
90
|
-
setViewSize?(newSize)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .requestCollapse)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
func bbNativePlayerView(didRequestExpand playerView: BBNativePlayerView) {
|
|
97
|
-
if allowCollapseExpand {
|
|
98
|
-
let height = playerView.bounds.size.height
|
|
99
|
-
let newSize = CGSize(width: Double.nan, height: height)
|
|
100
|
-
setViewSize?(newSize)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .requestExpand)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didFailWithError error: String?) {
|
|
107
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .failWithError(error))
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
func didRequestOpenUrl(url: String?) {
|
|
111
|
-
// not available in the SDK
|
|
112
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .requestOpenUrl(url))
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
func didSetupWithJsonUrl(url: String?) {
|
|
116
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .setupWithJsonUrl(url))
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didTriggerAdError error: String?) {
|
|
120
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adError(error))
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
func bbNativePlayerView(didTriggerAdFinished playerView: BBNativePlayerView) {
|
|
124
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adFinished)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
func bbNativePlayerView(didTriggerAdLoadStart playerView: BBNativePlayerView) {
|
|
128
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adLoadStart)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
func bbNativePlayerView(didTriggerAdLoaded playerView: BBNativePlayerView) {
|
|
132
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adLoaded)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
func bbNativePlayerView(didTriggerAdNotFound playerView: BBNativePlayerView) {
|
|
136
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adNotFound)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
func bbNativePlayerView(didTriggerAdQuartile1 playerView: BBNativePlayerView) {
|
|
140
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adQuartile1)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
func bbNativePlayerView(didTriggerAdQuartile2 playerView: BBNativePlayerView) {
|
|
144
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adQuartile2)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
func bbNativePlayerView(didTriggerAdQuartile3 playerView: BBNativePlayerView) {
|
|
148
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adQuartile3)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
func bbNativePlayerView(didTriggerAdStarted playerView: BBNativePlayerView) {
|
|
152
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .adStarted)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
func bbNativePlayerView(didTriggerAllAdsCompleted playerView: BBNativePlayerView) {
|
|
156
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .allAdsCompleted)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
func bbNativePlayerView(didTriggerAutoPause playerView: BBNativePlayerView) {
|
|
160
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .autoPause(nil))
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
func bbNativePlayerView(didTriggerAutoPausePlay playerView: BBNativePlayerView) {
|
|
164
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .autoPausePlay(nil))
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
func bbNativePlayerView(didTriggerCanPlay playerView: BBNativePlayerView) {
|
|
168
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .canPlay)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
func bbNativePlayerView(
|
|
172
|
-
didTriggerCustomStatistics playerView: BBNativePlayerView, ident: String, ev: String,
|
|
173
|
-
aux: [String: String]
|
|
174
|
-
) {
|
|
175
|
-
delegate?.bbPlayerViewController(
|
|
176
|
-
self, didTriggerEvent: .customStatistics(ident: ident, ev: ev, aux: aux))
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
func bbNativePlayerView(
|
|
180
|
-
playerView: BBNativePlayerView, didTriggerDurationChange duration: Double
|
|
181
|
-
) {
|
|
182
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .durationChange(duration))
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
func bbNativePlayerView(didTriggerEnded playerView: BBNativePlayerView) {
|
|
186
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .ended)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
func bbNativePlayerView(didTriggerFullscreen playerView: BBNativePlayerView) {
|
|
190
|
-
NSLog("BBPlayer: FULLSCREEN ENTRY DELEGATE CALLED")
|
|
191
|
-
|
|
192
|
-
// Enable landscape orientation for fullscreen using shared global state
|
|
193
|
-
if let orientationLockClass = NSClassFromString("OrientationLock") as? NSObject.Type {
|
|
194
|
-
orientationLockClass.setValue(true, forKey: "isFullscreen")
|
|
195
|
-
NSLog("BBPlayer: Set OrientationLock.isFullscreen = true")
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Try to find and configure the presented AVPlayerViewController
|
|
199
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
|
|
200
|
-
guard let self = self else { return }
|
|
201
|
-
|
|
202
|
-
// Find the presented view controller (should be AVPlayerViewController)
|
|
203
|
-
if let presentedVC = self.presentedViewController {
|
|
204
|
-
NSLog("BBPlayer: Found presented VC: \(type(of: presentedVC))")
|
|
205
|
-
|
|
206
|
-
// Force attempt rotation on the presented VC
|
|
207
|
-
if #available(iOS 16.0, *) {
|
|
208
|
-
presentedVC.setNeedsUpdateOfSupportedInterfaceOrientations()
|
|
209
|
-
}
|
|
210
|
-
UIViewController.attemptRotationToDeviceOrientation()
|
|
211
|
-
} else {
|
|
212
|
-
NSLog("BBPlayer: No presented VC found")
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .fullscreen)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
func bbNativePlayerView(didTriggerMediaClipFailed playerView: BBNativePlayerView) {
|
|
220
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .mediaClipFailed)
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
func bbNativePlayerView(
|
|
224
|
-
playerView: BBNativePlayerView, didTriggerMediaClipLoaded data: MediaClip
|
|
225
|
-
) {
|
|
226
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .mediaClipLoaded(data))
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
func bbNativePlayerView(didTriggerModeChange playerView: BBNativePlayerView, mode: String?) {
|
|
230
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .modeChange(mode))
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
func bbNativePlayerView(didTriggerPause playerView: BBNativePlayerView) {
|
|
234
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .pause)
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didTriggerPhaseChange phase: Phase?) {
|
|
238
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .phaseChange(phase))
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
func bbNativePlayerView(didTriggerPlay playerView: BBNativePlayerView) {
|
|
242
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .play)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
func bbNativePlayerView(didTriggerPlaying playerView: BBNativePlayerView) {
|
|
246
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .playing)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didTriggerProjectLoaded data: Project) {
|
|
250
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .projectLoaded(data))
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
func bbNativePlayerView(didTriggerRetractFullscreen playerView: BBNativePlayerView) {
|
|
254
|
-
NSLog("BBPlayer: FULLSCREEN EXIT DELEGATE CALLED")
|
|
255
|
-
|
|
256
|
-
// CRITICAL: Disable landscape orientation FIRST using shared global state
|
|
257
|
-
if let orientationLockClass = NSClassFromString("OrientationLock") as? NSObject.Type {
|
|
258
|
-
orientationLockClass.setValue(false, forKey: "isFullscreen")
|
|
259
|
-
NSLog("BBPlayer: Set OrientationLock.isFullscreen = false")
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Force rotation back to portrait
|
|
263
|
-
if #available(iOS 16.0, *) {
|
|
264
|
-
if let windowScene = view.window?.windowScene {
|
|
265
|
-
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))
|
|
266
|
-
}
|
|
267
|
-
} else {
|
|
268
|
-
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Always attempt rotation to update orientation constraints
|
|
272
|
-
UIViewController.attemptRotationToDeviceOrientation()
|
|
273
|
-
|
|
274
|
-
// The SDK's internal AVPlayerViewController needs time to restore itself
|
|
275
|
-
// Wait for the modal dismissal animation to complete
|
|
276
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
|
|
277
|
-
guard let self = self, let playerView = self.playerView else { return }
|
|
278
|
-
|
|
279
|
-
NSLog("BBPlayer: Refreshing view hierarchy after fullscreen exit")
|
|
280
|
-
|
|
281
|
-
// Reset any transforms that might be lingering from fullscreen
|
|
282
|
-
// Use iterative approach instead of recursion to avoid deep stack calls
|
|
283
|
-
// Only reset views that actually have non-identity transforms to save CPU
|
|
284
|
-
var viewsToProcess: [UIView] = [playerView]
|
|
285
|
-
var transformsReset = 0
|
|
286
|
-
|
|
287
|
-
while !viewsToProcess.isEmpty {
|
|
288
|
-
let view = viewsToProcess.removeLast()
|
|
289
|
-
// Only reset if transform is not already identity (avoids unnecessary work)
|
|
290
|
-
if view.transform != .identity {
|
|
291
|
-
view.transform = .identity
|
|
292
|
-
transformsReset += 1
|
|
293
|
-
}
|
|
294
|
-
viewsToProcess.append(contentsOf: view.subviews)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if transformsReset > 0 {
|
|
298
|
-
NSLog("BBPlayer: Reset \(transformsReset) non-identity transforms")
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Single batched layout update instead of multiple calls
|
|
302
|
-
playerView.setNeedsLayout()
|
|
303
|
-
self.view.setNeedsLayout()
|
|
304
|
-
self.view.layoutIfNeeded() // This will also layout playerView as it's a subview
|
|
305
|
-
|
|
306
|
-
// Log the player state for debugging
|
|
307
|
-
let player = playerView.player
|
|
308
|
-
NSLog("BBPlayer: Player state after fullscreen: \(String(describing: player.state?.name))")
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .retractFullscreen)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
override func viewDidAppear(_ animated: Bool) {
|
|
315
|
-
super.viewDidAppear(animated)
|
|
316
|
-
if presentingViewController == nil {
|
|
317
|
-
print("BBPlayer: viewDidAppear after dismissing fullscreen")
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didTriggerSeeked seekOffset: Double) {
|
|
322
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .seeked(seekOffset))
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
func bbNativePlayerView(didTriggerSeeking playerView: BBNativePlayerView) {
|
|
326
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .seeking)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
func bbNativePlayerView(didTriggerStall playerView: BBNativePlayerView) {
|
|
330
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .stall)
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
func bbNativePlayerView(playerView: BBNativePlayerView, didTriggerStateChange state: State?) {
|
|
334
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .stateChange(state))
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
func bbNativePlayerView(didTriggerViewFinished playerView: BBNativePlayerView) {
|
|
338
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .viewFinished)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
func bbNativePlayerView(didTriggerViewStarted playerView: BBNativePlayerView) {
|
|
342
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .viewStarted)
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
func bbNativePlayerView(didTriggerVolumeChange playerView: BBNativePlayerView, volume: Double) {
|
|
346
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .volumeChange(volume))
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
func bbNativePlayerView(didTriggerApiReady playerView: BBNativePlayerView) {
|
|
350
|
-
delegate?.bbPlayerViewController(self, didTriggerEvent: .apiReady)
|
|
351
|
-
}
|
|
352
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import bbnativeshared
|
|
2
|
-
|
|
3
|
-
enum BBPlayerEvent {
|
|
4
|
-
case requestCollapse
|
|
5
|
-
case requestExpand
|
|
6
|
-
case failWithError(String?)
|
|
7
|
-
case requestOpenUrl(String?)
|
|
8
|
-
case setupWithJsonUrl(String?)
|
|
9
|
-
case adError(String?)
|
|
10
|
-
case adFinished
|
|
11
|
-
case adLoaded
|
|
12
|
-
case adLoadStart
|
|
13
|
-
case adNotFound
|
|
14
|
-
case adQuartile1
|
|
15
|
-
case adQuartile2
|
|
16
|
-
case adQuartile3
|
|
17
|
-
case adStarted
|
|
18
|
-
case allAdsCompleted
|
|
19
|
-
case autoPause(String?)
|
|
20
|
-
case autoPausePlay(String?)
|
|
21
|
-
case canPlay
|
|
22
|
-
case customStatistics(ident: String, ev: String, aux: [String: String])
|
|
23
|
-
case durationChange(Double)
|
|
24
|
-
case ended
|
|
25
|
-
case fullscreen
|
|
26
|
-
case mediaClipFailed
|
|
27
|
-
case mediaClipLoaded(MediaClip)
|
|
28
|
-
case modeChange(String?)
|
|
29
|
-
case pause
|
|
30
|
-
case phaseChange(Phase?)
|
|
31
|
-
case play
|
|
32
|
-
case playing
|
|
33
|
-
case projectLoaded(Project)
|
|
34
|
-
case retractFullscreen
|
|
35
|
-
case seeked(Double?)
|
|
36
|
-
case seeking
|
|
37
|
-
case stall
|
|
38
|
-
case stateChange(State?)
|
|
39
|
-
case viewFinished
|
|
40
|
-
case viewStarted
|
|
41
|
-
case volumeChange(Double)
|
|
42
|
-
case apiReady
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
protocol BBPlayerViewControllerDelegate: AnyObject {
|
|
46
|
-
func bbPlayerViewController(
|
|
47
|
-
_ controller: BBPlayerViewController, didTriggerEvent event: BBPlayerEvent)
|
|
48
|
-
}
|