@bluebillywig/react-native-bb-player 8.42.9 → 8.42.14

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/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ All notable changes to react-native-bb-player will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [8.42.10] - 2026-01-28
9
+
10
+ ### Added
11
+ - **TurboModule support** for React Native New Architecture (Fabric)
12
+ - Added `NativeBBPlayerModule` TurboModule spec for React Native codegen
13
+ - Native module now uses `TurboModuleRegistry` when available, with automatic fallback to legacy `NativeModules`
14
+ - Added architecture-specific source sets (`newarch`/`paper`) for Android
15
+ - iOS module converted to Objective-C++ (`.mm`) for C++ interop required by TurboModules
16
+
17
+ ### Changed
18
+ - `BBPlayerPackage.kt` now implements `TurboReactPackage` for New Architecture compatibility
19
+ - `BBPlayerModule.kt` extends generated `NativeBBPlayerModuleSpec` for type-safe TurboModule implementation
20
+ - Updated `react-native-bb-player.podspec` with New Architecture compiler flags and configuration
21
+ - Added `codegenConfig` to `package.json` for React Native codegen integration
22
+
23
+ ### Technical Details
24
+ - Supports both Old Architecture (Paper) and New Architecture (Fabric/TurboModules)
25
+ - Tested with React Native 0.82.1
26
+ - No breaking changes - existing apps continue to work without modification
27
+ - New Architecture is automatically detected and used when enabled in the app
28
+
8
29
  ## [2.0.0] - 2026-01-20
9
30
 
10
31
  ### Changed
@@ -44,5 +65,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
44
65
  - Android fullscreen landscape: proper orientation locking and state restoration
45
66
  - Performance optimizations: reduced bridge traffic and memory leak fixes
46
67
 
68
+ [8.42.10]: https://github.com/bluebillywig/react-native-bb-player/releases/tag/v8.42.10
47
69
  [2.0.0]: https://github.com/bluebillywig/react-native-bb-player/releases/tag/v2.0.0
48
70
  [1.0.0]: https://github.com/bluebillywig/react-native-bb-player/releases/tag/v1.0.0
package/README.md CHANGED
@@ -18,7 +18,7 @@ Native video player for React Native - powered by Blue Billywig's iOS and Androi
18
18
  |----------|-------------|---------------|
19
19
  | **iOS** | 12.0+ | AVPlayer |
20
20
  | **Android** | API 21+ (5.0+) | ExoPlayer |
21
- | **React Native** | 0.73+ | Old & New Architecture |
21
+ | **React Native** | 0.73+ | Old & New Architecture (TurboModules) |
22
22
  | **Expo** | SDK 51+ | With config plugin (optional) |
23
23
 
24
24
  ## Installation
@@ -673,6 +673,63 @@ function CustomScreen() {
673
673
  }
674
674
  ```
675
675
 
676
+ ## New Architecture (Fabric & TurboModules)
677
+
678
+ This package fully supports React Native's New Architecture, including:
679
+
680
+ - **Fabric** - The new rendering system
681
+ - **TurboModules** - The new native module system with synchronous access and lazy loading
682
+
683
+ ### Automatic Detection
684
+
685
+ The package automatically detects which architecture your app uses:
686
+ - **New Architecture enabled**: Uses `TurboModuleRegistry` for optimal performance
687
+ - **Old Architecture**: Falls back to `NativeModules` (no changes needed)
688
+
689
+ ### Enabling New Architecture
690
+
691
+ #### React Native 0.76+
692
+ New Architecture is enabled by default in React Native 0.76 and later.
693
+
694
+ #### React Native 0.73-0.75
695
+ Enable in your app's configuration:
696
+
697
+ **Android** (`android/gradle.properties`):
698
+ ```properties
699
+ newArchEnabled=true
700
+ ```
701
+
702
+ **iOS** (`ios/Podfile`):
703
+ ```ruby
704
+ ENV['RCT_NEW_ARCH_ENABLED'] = '1'
705
+ ```
706
+
707
+ Then rebuild your app:
708
+ ```bash
709
+ # iOS
710
+ cd ios && pod install && cd ..
711
+ npx react-native run-ios
712
+
713
+ # Android
714
+ cd android && ./gradlew clean && cd ..
715
+ npx react-native run-android
716
+ ```
717
+
718
+ ### No Code Changes Required
719
+
720
+ Your existing code works with both architectures. The package handles the architecture detection internally:
721
+
722
+ ```tsx
723
+ // This works on both Old and New Architecture
724
+ import { BBPlayerView } from '@bluebillywig/react-native-bb-player';
725
+
726
+ <BBPlayerView
727
+ ref={playerRef}
728
+ jsonUrl="https://demo.bbvms.com/p/default/c/4701337.json"
729
+ onDidTriggerPlay={() => console.log('Playing')}
730
+ />
731
+ ```
732
+
676
733
  ## FAQ
677
734
 
678
735
  ### Can I use this in production?
@@ -7,6 +7,15 @@ def safeExtGet(prop, fallback) {
7
7
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
8
8
  }
9
9
 
10
+ def isNewArchitectureEnabled() {
11
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
12
+ }
13
+
14
+ // Apply React Native plugin for codegen when new arch is enabled
15
+ if (isNewArchitectureEnabled()) {
16
+ apply plugin: "com.facebook.react"
17
+ }
18
+
10
19
  group = 'com.bluebillywig.bbplayer'
11
20
  version = '2.0.0'
12
21
 
@@ -19,6 +28,11 @@ android {
19
28
  targetSdk safeExtGet('targetSdkVersion', 36)
20
29
  versionCode 1
21
30
  versionName "2.0.0"
31
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
32
+ }
33
+
34
+ buildFeatures {
35
+ buildConfig true
22
36
  }
23
37
 
24
38
  buildTypes {
@@ -39,6 +53,12 @@ android {
39
53
  sourceSets {
40
54
  main {
41
55
  java.srcDirs = ['src/main/java']
56
+ if (isNewArchitectureEnabled()) {
57
+ // Include codegen-generated specs first (takes precedence)
58
+ java.srcDirs += ["build/generated/source/codegen/java"]
59
+ } else {
60
+ java.srcDirs += ['src/paper/java']
61
+ }
42
62
  }
43
63
  }
44
64
  }
@@ -4,21 +4,22 @@ import android.util.Log
4
4
  import com.facebook.react.bridge.Arguments
5
5
  import com.facebook.react.bridge.Promise
6
6
  import com.facebook.react.bridge.ReactApplicationContext
7
- import com.facebook.react.bridge.ReactContextBaseJavaModule
8
7
  import com.facebook.react.bridge.ReactMethod
9
8
  import com.facebook.react.bridge.UiThreadUtil
9
+ import com.facebook.react.module.annotations.ReactModule
10
10
  import com.facebook.react.uimanager.UIManagerHelper
11
11
  import com.facebook.react.uimanager.common.UIManagerType
12
12
 
13
13
  /**
14
14
  * Native Module for BBPlayer commands.
15
- * Works with both Old Architecture and New Architecture (Fabric).
15
+ * Works with both Old Architecture (Paper) and New Architecture (Fabric/TurboModules).
16
16
  *
17
- * This module stores references to BBPlayerView instances and dispatches
18
- * commands to them by their React view tag.
17
+ * This module looks up BBPlayerView instances by their React view tag and dispatches
18
+ * commands to them.
19
19
  */
20
+ @ReactModule(name = BBPlayerModule.NAME)
20
21
  class BBPlayerModule(private val reactContext: ReactApplicationContext) :
21
- ReactContextBaseJavaModule(reactContext) {
22
+ NativeBBPlayerModuleSpec(reactContext) {
22
23
 
23
24
  override fun getName(): String = NAME
24
25
 
@@ -60,85 +61,85 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
60
61
  }
61
62
 
62
63
  @ReactMethod
63
- fun play(viewTag: Int) {
64
- runOnUiThread(viewTag) { it.play() }
64
+ override fun play(viewTag: Double) {
65
+ runOnUiThread(viewTag.toInt()) { it.play() }
65
66
  }
66
67
 
67
68
  @ReactMethod
68
- fun pause(viewTag: Int) {
69
- runOnUiThread(viewTag) { it.pause() }
69
+ override fun pause(viewTag: Double) {
70
+ runOnUiThread(viewTag.toInt()) { it.pause() }
70
71
  }
71
72
 
72
73
  @ReactMethod
73
- fun seek(viewTag: Int, position: Double) {
74
- runOnUiThread(viewTag) { it.seek(position) }
74
+ override fun seek(viewTag: Double, position: Double) {
75
+ runOnUiThread(viewTag.toInt()) { it.seek(position) }
75
76
  }
76
77
 
77
78
  @ReactMethod
78
- fun seekRelative(viewTag: Int, offsetSeconds: Double) {
79
- runOnUiThread(viewTag) { it.seekRelative(offsetSeconds) }
79
+ override fun seekRelative(viewTag: Double, offsetSeconds: Double) {
80
+ runOnUiThread(viewTag.toInt()) { it.seekRelative(offsetSeconds) }
80
81
  }
81
82
 
82
83
  @ReactMethod
83
- fun setVolume(viewTag: Int, volume: Double) {
84
- runOnUiThread(viewTag) { it.setVolume(volume) }
84
+ override fun setVolume(viewTag: Double, volume: Double) {
85
+ runOnUiThread(viewTag.toInt()) { it.setVolume(volume) }
85
86
  }
86
87
 
87
88
  @ReactMethod
88
- fun setMuted(viewTag: Int, muted: Boolean) {
89
- runOnUiThread(viewTag) { it.setMuted(muted) }
89
+ override fun setMuted(viewTag: Double, muted: Boolean) {
90
+ runOnUiThread(viewTag.toInt()) { it.setMuted(muted) }
90
91
  }
91
92
 
92
93
  @ReactMethod
93
- fun enterFullscreen(viewTag: Int) {
94
- runOnUiThread(viewTag) { it.enterFullscreen() }
94
+ override fun enterFullscreen(viewTag: Double) {
95
+ runOnUiThread(viewTag.toInt()) { it.enterFullscreen() }
95
96
  }
96
97
 
97
98
  @ReactMethod
98
- fun enterFullscreenLandscape(viewTag: Int) {
99
- runOnUiThread(viewTag) { it.enterFullscreenLandscape() }
99
+ override fun enterFullscreenLandscape(viewTag: Double) {
100
+ runOnUiThread(viewTag.toInt()) { it.enterFullscreenLandscape() }
100
101
  }
101
102
 
102
103
  @ReactMethod
103
- fun exitFullscreen(viewTag: Int) {
104
- runOnUiThread(viewTag) { it.exitFullscreen() }
104
+ override fun exitFullscreen(viewTag: Double) {
105
+ runOnUiThread(viewTag.toInt()) { it.exitFullscreen() }
105
106
  }
106
107
 
107
108
  @ReactMethod
108
- fun collapse(viewTag: Int) {
109
- runOnUiThread(viewTag) { it.collapse() }
109
+ override fun collapse(viewTag: Double) {
110
+ runOnUiThread(viewTag.toInt()) { it.collapse() }
110
111
  }
111
112
 
112
113
  @ReactMethod
113
- fun expand(viewTag: Int) {
114
- runOnUiThread(viewTag) { it.expand() }
114
+ override fun expand(viewTag: Double) {
115
+ runOnUiThread(viewTag.toInt()) { it.expand() }
115
116
  }
116
117
 
117
118
  @ReactMethod
118
- fun autoPlayNextCancel(viewTag: Int) {
119
- runOnUiThread(viewTag) { it.autoPlayNextCancel() }
119
+ override fun autoPlayNextCancel(viewTag: Double) {
120
+ runOnUiThread(viewTag.toInt()) { it.autoPlayNextCancel() }
120
121
  }
121
122
 
122
123
  @ReactMethod
123
- fun destroy(viewTag: Int) {
124
- runOnUiThread(viewTag) { it.destroy() }
124
+ override fun destroy(viewTag: Double) {
125
+ runOnUiThread(viewTag.toInt()) { it.destroy() }
125
126
  }
126
127
 
127
128
  @ReactMethod
128
- fun showCastPicker(viewTag: Int) {
129
- runOnUiThread(viewTag) { it.showCastPicker() }
129
+ override fun showCastPicker(viewTag: Double) {
130
+ runOnUiThread(viewTag.toInt()) { it.showCastPicker() }
130
131
  }
131
132
 
132
133
  @ReactMethod
133
- fun loadWithClipId(
134
- viewTag: Int,
134
+ override fun loadWithClipId(
135
+ viewTag: Double,
135
136
  clipId: String,
136
137
  initiator: String?,
137
138
  autoPlay: Boolean,
138
139
  seekTo: Double
139
140
  ) {
140
141
  Log.d("BBPlayerModule", "loadWithClipId called - viewTag: $viewTag, clipId: $clipId, autoPlay: $autoPlay")
141
- runOnUiThread(viewTag) {
142
+ runOnUiThread(viewTag.toInt()) {
142
143
  it.loadWithClipId(
143
144
  clipId,
144
145
  initiator,
@@ -149,14 +150,14 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
149
150
  }
150
151
 
151
152
  @ReactMethod
152
- fun loadWithClipListId(
153
- viewTag: Int,
153
+ override fun loadWithClipListId(
154
+ viewTag: Double,
154
155
  clipListId: String,
155
156
  initiator: String?,
156
157
  autoPlay: Boolean,
157
158
  seekTo: Double
158
159
  ) {
159
- runOnUiThread(viewTag) {
160
+ runOnUiThread(viewTag.toInt()) {
160
161
  it.loadWithClipListId(
161
162
  clipListId,
162
163
  initiator,
@@ -167,14 +168,14 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
167
168
  }
168
169
 
169
170
  @ReactMethod
170
- fun loadWithProjectId(
171
- viewTag: Int,
171
+ override fun loadWithProjectId(
172
+ viewTag: Double,
172
173
  projectId: String,
173
174
  initiator: String?,
174
175
  autoPlay: Boolean,
175
176
  seekTo: Double
176
177
  ) {
177
- runOnUiThread(viewTag) {
178
+ runOnUiThread(viewTag.toInt()) {
178
179
  it.loadWithProjectId(
179
180
  projectId,
180
181
  initiator,
@@ -185,14 +186,14 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
185
186
  }
186
187
 
187
188
  @ReactMethod
188
- fun loadWithClipJson(
189
- viewTag: Int,
189
+ override fun loadWithClipJson(
190
+ viewTag: Double,
190
191
  clipJson: String,
191
192
  initiator: String?,
192
193
  autoPlay: Boolean,
193
194
  seekTo: Double
194
195
  ) {
195
- runOnUiThread(viewTag) {
196
+ runOnUiThread(viewTag.toInt()) {
196
197
  it.loadWithClipJson(
197
198
  clipJson,
198
199
  initiator,
@@ -203,14 +204,14 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
203
204
  }
204
205
 
205
206
  @ReactMethod
206
- fun loadWithClipListJson(
207
- viewTag: Int,
207
+ override fun loadWithClipListJson(
208
+ viewTag: Double,
208
209
  clipListJson: String,
209
210
  initiator: String?,
210
211
  autoPlay: Boolean,
211
212
  seekTo: Double
212
213
  ) {
213
- runOnUiThread(viewTag) {
214
+ runOnUiThread(viewTag.toInt()) {
214
215
  it.loadWithClipListJson(
215
216
  clipListJson,
216
217
  initiator,
@@ -221,14 +222,14 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
221
222
  }
222
223
 
223
224
  @ReactMethod
224
- fun loadWithProjectJson(
225
- viewTag: Int,
225
+ override fun loadWithProjectJson(
226
+ viewTag: Double,
226
227
  projectJson: String,
227
228
  initiator: String?,
228
229
  autoPlay: Boolean,
229
230
  seekTo: Double
230
231
  ) {
231
- runOnUiThread(viewTag) {
232
+ runOnUiThread(viewTag.toInt()) {
232
233
  it.loadWithProjectJson(
233
234
  projectJson,
234
235
  initiator,
@@ -239,12 +240,12 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
239
240
  }
240
241
 
241
242
  @ReactMethod
242
- fun loadWithJsonUrl(
243
- viewTag: Int,
243
+ override fun loadWithJsonUrl(
244
+ viewTag: Double,
244
245
  jsonUrl: String,
245
246
  autoPlay: Boolean
246
247
  ) {
247
- runOnUiThread(viewTag) {
248
+ runOnUiThread(viewTag.toInt()) {
248
249
  it.loadWithJsonUrl(jsonUrl, autoPlay)
249
250
  }
250
251
  }
@@ -254,9 +255,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
254
255
 
255
256
  // Getter methods with Promise support
256
257
  @ReactMethod
257
- fun getDuration(viewTag: Int, promise: Promise) {
258
+ override fun getDuration(viewTag: Double, promise: Promise) {
258
259
  UiThreadUtil.runOnUiThread {
259
- val view = findPlayerView(viewTag)
260
+ val view = findPlayerView(viewTag.toInt())
260
261
  if (view != null) {
261
262
  val duration = view.getDuration()
262
263
  promise.resolve(duration)
@@ -267,9 +268,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
267
268
  }
268
269
 
269
270
  @ReactMethod
270
- fun getCurrentTime(viewTag: Int, promise: Promise) {
271
+ override fun getCurrentTime(viewTag: Double, promise: Promise) {
271
272
  UiThreadUtil.runOnUiThread {
272
- val view = findPlayerView(viewTag)
273
+ val view = findPlayerView(viewTag.toInt())
273
274
  if (view != null) {
274
275
  val currentTime = view.getCurrentTime()
275
276
  promise.resolve(currentTime)
@@ -280,9 +281,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
280
281
  }
281
282
 
282
283
  @ReactMethod
283
- fun getMuted(viewTag: Int, promise: Promise) {
284
+ override fun getMuted(viewTag: Double, promise: Promise) {
284
285
  UiThreadUtil.runOnUiThread {
285
- val view = findPlayerView(viewTag)
286
+ val view = findPlayerView(viewTag.toInt())
286
287
  if (view != null) {
287
288
  val muted = view.getMuted()
288
289
  promise.resolve(muted)
@@ -293,9 +294,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
293
294
  }
294
295
 
295
296
  @ReactMethod
296
- fun getVolume(viewTag: Int, promise: Promise) {
297
+ override fun getVolume(viewTag: Double, promise: Promise) {
297
298
  UiThreadUtil.runOnUiThread {
298
- val view = findPlayerView(viewTag)
299
+ val view = findPlayerView(viewTag.toInt())
299
300
  if (view != null) {
300
301
  val volume = view.getVolume()
301
302
  promise.resolve(volume)
@@ -306,9 +307,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
306
307
  }
307
308
 
308
309
  @ReactMethod
309
- fun getPhase(viewTag: Int, promise: Promise) {
310
+ override fun getPhase(viewTag: Double, promise: Promise) {
310
311
  UiThreadUtil.runOnUiThread {
311
- val view = findPlayerView(viewTag)
312
+ val view = findPlayerView(viewTag.toInt())
312
313
  if (view != null) {
313
314
  val phase = view.getPhase()
314
315
  promise.resolve(phase?.name)
@@ -319,9 +320,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
319
320
  }
320
321
 
321
322
  @ReactMethod
322
- fun getState(viewTag: Int, promise: Promise) {
323
+ override fun getState(viewTag: Double, promise: Promise) {
323
324
  UiThreadUtil.runOnUiThread {
324
- val view = findPlayerView(viewTag)
325
+ val view = findPlayerView(viewTag.toInt())
325
326
  if (view != null) {
326
327
  val state = view.getState()
327
328
  promise.resolve(state?.name)
@@ -332,9 +333,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
332
333
  }
333
334
 
334
335
  @ReactMethod
335
- fun getMode(viewTag: Int, promise: Promise) {
336
+ override fun getMode(viewTag: Double, promise: Promise) {
336
337
  UiThreadUtil.runOnUiThread {
337
- val view = findPlayerView(viewTag)
338
+ val view = findPlayerView(viewTag.toInt())
338
339
  if (view != null) {
339
340
  val mode = view.getMode()
340
341
  promise.resolve(mode)
@@ -345,9 +346,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
345
346
  }
346
347
 
347
348
  @ReactMethod
348
- fun getClipData(viewTag: Int, promise: Promise) {
349
+ override fun getClipData(viewTag: Double, promise: Promise) {
349
350
  UiThreadUtil.runOnUiThread {
350
- val view = findPlayerView(viewTag)
351
+ val view = findPlayerView(viewTag.toInt())
351
352
  if (view != null) {
352
353
  val clipData = view.getClipData()
353
354
  if (clipData != null) {
@@ -368,9 +369,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
368
369
  }
369
370
 
370
371
  @ReactMethod
371
- fun getProjectData(viewTag: Int, promise: Promise) {
372
+ override fun getProjectData(viewTag: Double, promise: Promise) {
372
373
  UiThreadUtil.runOnUiThread {
373
- val view = findPlayerView(viewTag)
374
+ val view = findPlayerView(viewTag.toInt())
374
375
  if (view != null) {
375
376
  val projectData = view.getProjectData()
376
377
  if (projectData != null) {
@@ -389,9 +390,9 @@ class BBPlayerModule(private val reactContext: ReactApplicationContext) :
389
390
  }
390
391
 
391
392
  @ReactMethod
392
- fun getPlayoutData(viewTag: Int, promise: Promise) {
393
+ override fun getPlayoutData(viewTag: Double, promise: Promise) {
393
394
  UiThreadUtil.runOnUiThread {
394
- val view = findPlayerView(viewTag)
395
+ val view = findPlayerView(viewTag.toInt())
395
396
  if (view != null) {
396
397
  val playoutData = view.getPlayoutData()
397
398
  if (playoutData != null) {
@@ -1,13 +1,34 @@
1
1
  package com.bluebillywig.bbplayer
2
2
 
3
- import com.facebook.react.ReactPackage
3
+ import com.facebook.react.BaseReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
6
8
  import com.facebook.react.uimanager.ViewManager
7
9
 
8
- class BBPlayerPackage : ReactPackage {
9
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
- return listOf(BBPlayerModule(reactContext))
10
+ class BBPlayerPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return when (name) {
13
+ BBPlayerModule.NAME -> BBPlayerModule(reactContext)
14
+ else -> null
15
+ }
16
+ }
17
+
18
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
19
+ return ReactModuleInfoProvider {
20
+ mapOf(
21
+ BBPlayerModule.NAME to ReactModuleInfo(
22
+ BBPlayerModule.NAME,
23
+ BBPlayerModule::class.java.name,
24
+ false, // canOverrideExistingModule
25
+ false, // needsEagerInit
26
+ true, // hasConstants - deprecated but still needed
27
+ false, // isCxxModule
28
+ BuildConfig.IS_NEW_ARCHITECTURE_ENABLED // isTurboModule
29
+ )
30
+ )
31
+ }
11
32
  }
12
33
 
13
34
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
@@ -0,0 +1,12 @@
1
+ package com.bluebillywig.bbplayer;
2
+
3
+ /**
4
+ * Placeholder for New Architecture (Fabric/TurboModules).
5
+ * The actual spec is generated by React Native codegen during build.
6
+ * This file allows the project to compile before codegen runs.
7
+ *
8
+ * During New Architecture builds, this file is replaced by the codegen-generated spec.
9
+ */
10
+
11
+ // The codegen-generated spec will be in:
12
+ // android/build/generated/source/codegen/java/com/bluebillywig/bbplayer/NativeBBPlayerModuleSpec.java
@@ -0,0 +1,59 @@
1
+ package com.bluebillywig.bbplayer;
2
+
3
+ import com.facebook.react.bridge.Promise;
4
+ import com.facebook.react.bridge.ReactApplicationContext;
5
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
6
+
7
+ /**
8
+ * Abstract base class for BBPlayerModule on Old Architecture (Paper).
9
+ * This is used when codegen is not available (Old Architecture builds).
10
+ * The actual implementation extends this class.
11
+ */
12
+ public abstract class NativeBBPlayerModuleSpec extends ReactContextBaseJavaModule {
13
+ public NativeBBPlayerModuleSpec(ReactApplicationContext reactContext) {
14
+ super(reactContext);
15
+ }
16
+
17
+ // Void methods - playback control
18
+ public abstract void play(int viewTag);
19
+ public abstract void pause(int viewTag);
20
+ public abstract void seek(int viewTag, double position);
21
+ public abstract void seekRelative(int viewTag, double offsetSeconds);
22
+ public abstract void setMuted(int viewTag, boolean muted);
23
+ public abstract void setVolume(int viewTag, double volume);
24
+
25
+ // Void methods - fullscreen control
26
+ public abstract void enterFullscreen(int viewTag);
27
+ public abstract void enterFullscreenLandscape(int viewTag);
28
+ public abstract void exitFullscreen(int viewTag);
29
+
30
+ // Void methods - layout control
31
+ public abstract void collapse(int viewTag);
32
+ public abstract void expand(int viewTag);
33
+
34
+ // Void methods - other commands
35
+ public abstract void autoPlayNextCancel(int viewTag);
36
+ public abstract void destroy(int viewTag);
37
+ public abstract void showCastPicker(int viewTag);
38
+
39
+ // Load methods
40
+ public abstract void loadWithClipId(int viewTag, String clipId, String initiator, boolean autoPlay, double seekTo);
41
+ public abstract void loadWithClipListId(int viewTag, String clipListId, String initiator, boolean autoPlay, double seekTo);
42
+ public abstract void loadWithProjectId(int viewTag, String projectId, String initiator, boolean autoPlay, double seekTo);
43
+ public abstract void loadWithClipJson(int viewTag, String clipJson, String initiator, boolean autoPlay, double seekTo);
44
+ public abstract void loadWithClipListJson(int viewTag, String clipListJson, String initiator, boolean autoPlay, double seekTo);
45
+ public abstract void loadWithProjectJson(int viewTag, String projectJson, String initiator, boolean autoPlay, double seekTo);
46
+ public abstract void loadWithJsonUrl(int viewTag, String jsonUrl, boolean autoPlay);
47
+
48
+ // Promise getters
49
+ public abstract void getDuration(int viewTag, Promise promise);
50
+ public abstract void getCurrentTime(int viewTag, Promise promise);
51
+ public abstract void getMuted(int viewTag, Promise promise);
52
+ public abstract void getVolume(int viewTag, Promise promise);
53
+ public abstract void getPhase(int viewTag, Promise promise);
54
+ public abstract void getState(int viewTag, Promise promise);
55
+ public abstract void getMode(int viewTag, Promise promise);
56
+ public abstract void getClipData(int viewTag, Promise promise);
57
+ public abstract void getProjectData(int viewTag, Promise promise);
58
+ public abstract void getPlayoutData(int viewTag, Promise promise);
59
+ }
@@ -1,5 +1,9 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
 
3
+ #ifdef RCT_NEW_ARCH_ENABLED
4
+ #import <BBPlayerModuleSpec/BBPlayerModuleSpec.h>
5
+ #endif
6
+
3
7
  @interface RCT_EXTERN_MODULE(BBPlayerModule, NSObject)
4
8
 
5
9
  // Playback control
@@ -45,4 +49,12 @@ RCT_EXTERN_METHOD(getClipData:(nonnull NSNumber *)viewTag resolver:(RCTPromiseRe
45
49
  RCT_EXTERN_METHOD(getProjectData:(nonnull NSNumber *)viewTag resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
46
50
  RCT_EXTERN_METHOD(getPlayoutData:(nonnull NSNumber *)viewTag resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
47
51
 
52
+ #ifdef RCT_NEW_ARCH_ENABLED
53
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
54
+ (const facebook::react::ObjCTurboModule::InitParams &)params
55
+ {
56
+ return std::make_shared<facebook::react::NativeBBPlayerModuleSpecJSI>(params);
57
+ }
58
+ #endif
59
+
48
60
  @end