@bluebillywig/react-native-bb-player 8.44.0 → 8.45.4

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.
Files changed (55) hide show
  1. package/README.md +80 -59
  2. package/android/build.gradle +4 -3
  3. package/android/src/main/java/com/bluebillywig/bbplayer/BBPlayerModule.kt +174 -28
  4. package/android/src/main/java/com/bluebillywig/bbplayer/BBPlayerView.kt +70 -167
  5. package/android/src/main/java/com/bluebillywig/bbplayer/BBPlayerViewManager.kt +9 -7
  6. package/android/src/paper/java/com/bluebillywig/bbplayer/NativeBBPlayerModuleSpec.java +19 -8
  7. package/ios/BBPlayerModule.mm +17 -8
  8. package/ios/BBPlayerModule.swift +192 -26
  9. package/ios/BBPlayerView.swift +55 -140
  10. package/ios/BBPlayerViewManager.m +2 -2
  11. package/ios/BBPlayerViewManager.swift +12 -0
  12. package/lib/commonjs/BBModalPlayer.js +21 -0
  13. package/lib/commonjs/BBModalPlayer.js.map +1 -0
  14. package/lib/commonjs/BBOutstreamView.js +2 -1
  15. package/lib/commonjs/BBOutstreamView.js.map +1 -1
  16. package/lib/commonjs/BBPlayerView.js +0 -1
  17. package/lib/commonjs/BBPlayerView.js.map +1 -1
  18. package/lib/commonjs/NativeCommands.js +32 -24
  19. package/lib/commonjs/NativeCommands.js.map +1 -1
  20. package/lib/commonjs/index.js +9 -1
  21. package/lib/commonjs/index.js.map +1 -1
  22. package/lib/commonjs/specs/NativeBBPlayerModule.js.map +1 -1
  23. package/lib/module/BBModalPlayer.js +17 -0
  24. package/lib/module/BBModalPlayer.js.map +1 -0
  25. package/lib/module/BBOutstreamView.js +2 -1
  26. package/lib/module/BBOutstreamView.js.map +1 -1
  27. package/lib/module/BBPlayerView.js +0 -1
  28. package/lib/module/BBPlayerView.js.map +1 -1
  29. package/lib/module/NativeCommands.js +32 -24
  30. package/lib/module/NativeCommands.js.map +1 -1
  31. package/lib/module/index.js +1 -0
  32. package/lib/module/index.js.map +1 -1
  33. package/lib/module/specs/NativeBBPlayerModule.js.map +1 -1
  34. package/lib/typescript/src/BBModalPlayer.d.ts +13 -0
  35. package/lib/typescript/src/BBModalPlayer.d.ts.map +1 -0
  36. package/lib/typescript/src/BBOutstreamView.d.ts.map +1 -1
  37. package/lib/typescript/src/BBPlayer.types.d.ts +28 -20
  38. package/lib/typescript/src/BBPlayer.types.d.ts.map +1 -1
  39. package/lib/typescript/src/BBPlayerView.d.ts +0 -2
  40. package/lib/typescript/src/BBPlayerView.d.ts.map +1 -1
  41. package/lib/typescript/src/NativeCommands.d.ts +10 -9
  42. package/lib/typescript/src/NativeCommands.d.ts.map +1 -1
  43. package/lib/typescript/src/index.d.ts +2 -0
  44. package/lib/typescript/src/index.d.ts.map +1 -1
  45. package/lib/typescript/src/specs/NativeBBPlayerModule.d.ts +13 -8
  46. package/lib/typescript/src/specs/NativeBBPlayerModule.d.ts.map +1 -1
  47. package/package.json +9 -10
  48. package/src/BBModalPlayer.ts +33 -0
  49. package/src/BBOutstreamView.tsx +2 -1
  50. package/src/BBPlayer.types.ts +35 -17
  51. package/src/BBPlayerView.tsx +0 -12
  52. package/src/NativeCommands.ts +45 -26
  53. package/src/index.ts +2 -0
  54. package/src/specs/NativeBBPlayerModule.ts +23 -8
  55. package/android/proguard-rules.pro +0 -59
@@ -268,6 +268,8 @@ const BBOutstreamView = forwardRef<BBOutstreamViewMethods, BBOutstreamViewProps>
268
268
  enterFullscreen: () => playerRef.current?.enterFullscreen(),
269
269
  enterFullscreenLandscape: () => playerRef.current?.enterFullscreenLandscape(),
270
270
  exitFullscreen: () => playerRef.current?.exitFullscreen(),
271
+ presentModal: () => playerRef.current?.presentModal(),
272
+ closeModal: () => playerRef.current?.closeModal(),
271
273
  showCastPicker: () => playerRef.current?.showCastPicker(),
272
274
  destroy: () => playerRef.current?.destroy(),
273
275
  autoPlayNextCancel: () => playerRef.current?.autoPlayNextCancel(),
@@ -288,7 +290,6 @@ const BBOutstreamView = forwardRef<BBOutstreamViewMethods, BBOutstreamViewProps>
288
290
  loadWithJsonUrl: (...args: Parameters<BBPlayerViewMethods['loadWithJsonUrl']>) =>
289
291
  playerRef.current?.loadWithJsonUrl(...args),
290
292
  getDuration: () => playerRef.current?.getDuration() ?? Promise.resolve(null),
291
- getCurrentTime: () => playerRef.current?.getCurrentTime() ?? Promise.resolve(null),
292
293
  getMuted: () => playerRef.current?.getMuted() ?? Promise.resolve(null),
293
294
  getVolume: () => playerRef.current?.getVolume() ?? Promise.resolve(null),
294
295
  getPhase: () => playerRef.current?.getPhase() ?? Promise.resolve(null),
@@ -8,6 +8,21 @@ import type {
8
8
  State,
9
9
  } from "./types";
10
10
 
11
+ /**
12
+ * Context for playlist/collection navigation.
13
+ * Enables "next up" list and proper playlist navigation in the player.
14
+ */
15
+ export type LoadContext = {
16
+ /** Context entity type (always 'MediaClipList' for playlists) */
17
+ contextEntityType?: 'MediaClipList';
18
+ /** Playlist ID for "next up" list */
19
+ contextEntityId?: string;
20
+ /** Context collection type (always 'MediaClipList' for collections) */
21
+ contextCollectionType?: 'MediaClipList';
22
+ /** Collection ID if playing within a collection */
23
+ contextCollectionId?: string;
24
+ };
25
+
11
26
  /**
12
27
  * Options for loading a clip via loadClip()
13
28
  */
@@ -20,6 +35,8 @@ export type LoadClipOptions = {
20
35
  seekTo?: number;
21
36
  /** Initiator identifier for analytics */
22
37
  initiator?: string;
38
+ /** Playlist/collection context for navigation */
39
+ context?: LoadContext;
23
40
  };
24
41
 
25
42
  /**
@@ -45,6 +62,10 @@ export type BBPlayerViewMethods = {
45
62
  enterFullscreen: () => void;
46
63
  enterFullscreenLandscape: () => void;
47
64
  exitFullscreen: () => void;
65
+ /** Present native SDK modal (iOS: overFullScreen with swipe-to-close, Android: in-place fullscreen) */
66
+ presentModal: () => void;
67
+ /** Close native SDK modal */
68
+ closeModal: () => void;
48
69
  collapse: () => void;
49
70
  expand: () => void;
50
71
  autoPlayNextCancel: () => void;
@@ -74,43 +95,48 @@ export type BBPlayerViewMethods = {
74
95
  clipId: string,
75
96
  initiator?: string,
76
97
  autoPlay?: boolean,
77
- seekTo?: number
98
+ seekTo?: number,
99
+ context?: LoadContext
78
100
  ) => void;
79
101
  loadWithClipListId: (
80
102
  clipListId: string,
81
103
  initiator?: string,
82
104
  autoPlay?: boolean,
83
- seekTo?: number
105
+ seekTo?: number,
106
+ context?: LoadContext
84
107
  ) => void;
85
108
  loadWithProjectId: (
86
109
  projectId: string,
87
110
  initiator?: string,
88
111
  autoPlay?: boolean,
89
- seekTo?: number
112
+ seekTo?: number,
113
+ context?: LoadContext
90
114
  ) => void;
91
115
  loadWithClipJson: (
92
116
  clipJson: string,
93
117
  initiator?: string,
94
118
  autoPlay?: boolean,
95
- seekTo?: number
119
+ seekTo?: number,
120
+ context?: LoadContext
96
121
  ) => void;
97
122
  loadWithClipListJson: (
98
123
  clipListJson: string,
99
124
  initiator?: string,
100
125
  autoPlay?: boolean,
101
- seekTo?: number
126
+ seekTo?: number,
127
+ context?: LoadContext
102
128
  ) => void;
103
129
  loadWithProjectJson: (
104
130
  projectJson: string,
105
131
  initiator?: string,
106
132
  autoPlay?: boolean,
107
- seekTo?: number
133
+ seekTo?: number,
134
+ context?: LoadContext
108
135
  ) => void;
109
- loadWithJsonUrl: (jsonUrl: string, autoPlay?: boolean) => void;
136
+ loadWithJsonUrl: (jsonUrl: string, autoPlay?: boolean, context?: LoadContext) => void;
110
137
 
111
138
  // Getter methods (async)
112
139
  getDuration: () => Promise<number | null>;
113
- getCurrentTime: () => Promise<number | null>;
114
140
  getMuted: () => Promise<boolean | null>;
115
141
  getVolume: () => Promise<number | null>;
116
142
  getPhase: () => Promise<string | null>;
@@ -140,7 +166,7 @@ export type BBPlayerViewMethods = {
140
166
  * const state = await playerRef.current?.getPlayerState();
141
167
  * if (state) {
142
168
  * console.log(`Playing: ${state.state === 'PLAYING'}`);
143
- * console.log(`Progress: ${state.currentTime}/${state.duration}`);
169
+ * console.log(`Duration: ${state.duration}`);
144
170
  * }
145
171
  */
146
172
  getPlayerState: () => Promise<BBPlayerState | null>;
@@ -165,10 +191,6 @@ export type BBPlayerViewProps = {
165
191
  * JSON URL to load player configuration from.
166
192
  */
167
193
  jsonUrl?: string;
168
- /**
169
- * Enable periodic time update events (onDidTriggerTimeUpdate).
170
- */
171
- enableTimeUpdates?: boolean;
172
194
  onDidFailWithError?: (error: string) => void;
173
195
  onDidRequestCollapse?: () => void;
174
196
  onDidRequestExpand?: () => void;
@@ -205,7 +227,6 @@ export type BBPlayerViewProps = {
205
227
  onDidTriggerSeeking?: () => void;
206
228
  onDidTriggerStall?: () => void;
207
229
  onDidTriggerStateChange?: (state: State) => void;
208
- onDidTriggerTimeUpdate?: (currentTime: number, duration: number) => void;
209
230
  onDidTriggerViewFinished?: () => void;
210
231
  onDidTriggerViewStarted?: () => void;
211
232
  onDidTriggerVolumeChange?: (volume: number) => void;
@@ -226,8 +247,6 @@ export type BBPlayerState = {
226
247
  phase: Phase;
227
248
  /** Current playback mode */
228
249
  mode: string | null;
229
- /** Current playback position in seconds */
230
- currentTime: number;
231
250
  /** Total duration in seconds */
232
251
  duration: number;
233
252
  /** Whether audio is muted */
@@ -264,7 +283,6 @@ export type BBPlayerEventPayloads = {
264
283
  stateChange: { state: State };
265
284
  phaseChange: { phase: Phase };
266
285
  modeChange: { mode: string };
267
- timeUpdate: { currentTime: number; duration: number };
268
286
  durationChange: { duration: number };
269
287
  volumeChange: { volume: number; muted: boolean };
270
288
  seeked: { position: number };
@@ -82,9 +82,6 @@ type NativeBBPlayerViewProps = Override<
82
82
  onDidTriggerStateChange?: (
83
83
  event: NativeSyntheticEvent<{ state: State }>
84
84
  ) => void;
85
- onDidTriggerTimeUpdate?: (
86
- event: NativeSyntheticEvent<{ currentTime: number; duration: number }>
87
- ) => void;
88
85
  onDidTriggerViewFinished?: (event: NativeSyntheticEvent<{}>) => void;
89
86
  onDidTriggerViewStarted?: (event: NativeSyntheticEvent<{}>) => void;
90
87
  onDidTriggerVolumeChange?: (
@@ -310,15 +307,6 @@ const BBPlayerView = forwardRef<BBPlayerViewMethods, BBPlayerViewProps>(
310
307
  props.onDidTriggerStateChange?.(event.nativeEvent.state)
311
308
  : undefined
312
309
  }
313
- onDidTriggerTimeUpdate={
314
- props.onDidTriggerTimeUpdate
315
- ? (event) =>
316
- props.onDidTriggerTimeUpdate?.(
317
- event.nativeEvent.currentTime,
318
- event.nativeEvent.duration
319
- )
320
- : undefined
321
- }
322
310
  onDidTriggerViewFinished={
323
311
  props.onDidTriggerViewFinished
324
312
  ? () => props.onDidTriggerViewFinished?.()
@@ -1,6 +1,6 @@
1
1
  import { NativeModules, findNodeHandle } from "react-native";
2
2
 
3
- import type { LoadClipOptions, BBPlayerState } from "./BBPlayer.types";
3
+ import type { LoadClipOptions, LoadContext, BBPlayerState } from "./BBPlayer.types";
4
4
  import type { State, Phase } from "./types";
5
5
 
6
6
  // Try TurboModule first, fallback to legacy NativeModules
@@ -81,6 +81,14 @@ export function createCommands(viewRef: React.RefObject<any>) {
81
81
  const tag = getViewTag(viewRef);
82
82
  if (tag != null) BBPlayerModule?.exitFullscreen(tag);
83
83
  },
84
+ presentModal: () => {
85
+ const tag = getViewTag(viewRef);
86
+ if (tag != null) BBPlayerModule?.presentModal(tag);
87
+ },
88
+ closeModal: () => {
89
+ const tag = getViewTag(viewRef);
90
+ if (tag != null) BBPlayerModule?.closeModal(tag);
91
+ },
84
92
  collapse: () => {
85
93
  const tag = getViewTag(viewRef);
86
94
  if (tag != null) BBPlayerModule?.collapse(tag);
@@ -110,12 +118,14 @@ export function createCommands(viewRef: React.RefObject<any>) {
110
118
  const tag = getViewTag(viewRef);
111
119
  if (tag != null) {
112
120
  // Use loadWithClipId under the hood, passing playout as initiator if provided
121
+ const contextJson = options?.context ? JSON.stringify(options.context) : null;
113
122
  BBPlayerModule?.loadWithClipId(
114
123
  tag,
115
124
  clipId,
116
125
  options?.initiator ?? options?.playout ?? null,
117
126
  options?.autoPlay ?? false,
118
- options?.seekTo ?? 0
127
+ options?.seekTo ?? 0,
128
+ contextJson
119
129
  );
120
130
  }
121
131
  },
@@ -125,16 +135,19 @@ export function createCommands(viewRef: React.RefObject<any>) {
125
135
  clipId: string,
126
136
  initiator?: string,
127
137
  autoPlay?: boolean,
128
- seekTo?: number
138
+ seekTo?: number,
139
+ context?: LoadContext
129
140
  ) => {
130
141
  const tag = getViewTag(viewRef);
131
142
  if (tag != null) {
143
+ const contextJson = context ? JSON.stringify(context) : null;
132
144
  BBPlayerModule?.loadWithClipId(
133
145
  tag,
134
146
  clipId,
135
147
  initiator ?? null,
136
148
  autoPlay ?? false,
137
- seekTo ?? 0
149
+ seekTo ?? 0,
150
+ contextJson
138
151
  );
139
152
  }
140
153
  },
@@ -142,16 +155,19 @@ export function createCommands(viewRef: React.RefObject<any>) {
142
155
  clipListId: string,
143
156
  initiator?: string,
144
157
  autoPlay?: boolean,
145
- seekTo?: number
158
+ seekTo?: number,
159
+ context?: LoadContext
146
160
  ) => {
147
161
  const tag = getViewTag(viewRef);
148
162
  if (tag != null) {
163
+ const contextJson = context ? JSON.stringify(context) : null;
149
164
  BBPlayerModule?.loadWithClipListId(
150
165
  tag,
151
166
  clipListId,
152
167
  initiator ?? null,
153
168
  autoPlay ?? false,
154
- seekTo ?? 0
169
+ seekTo ?? 0,
170
+ contextJson
155
171
  );
156
172
  }
157
173
  },
@@ -159,16 +175,19 @@ export function createCommands(viewRef: React.RefObject<any>) {
159
175
  projectId: string,
160
176
  initiator?: string,
161
177
  autoPlay?: boolean,
162
- seekTo?: number
178
+ seekTo?: number,
179
+ context?: LoadContext
163
180
  ) => {
164
181
  const tag = getViewTag(viewRef);
165
182
  if (tag != null) {
183
+ const contextJson = context ? JSON.stringify(context) : null;
166
184
  BBPlayerModule?.loadWithProjectId(
167
185
  tag,
168
186
  projectId,
169
187
  initiator ?? null,
170
188
  autoPlay ?? false,
171
- seekTo ?? 0
189
+ seekTo ?? 0,
190
+ contextJson
172
191
  );
173
192
  }
174
193
  },
@@ -176,16 +195,19 @@ export function createCommands(viewRef: React.RefObject<any>) {
176
195
  clipJson: string,
177
196
  initiator?: string,
178
197
  autoPlay?: boolean,
179
- seekTo?: number
198
+ seekTo?: number,
199
+ context?: LoadContext
180
200
  ) => {
181
201
  const tag = getViewTag(viewRef);
182
202
  if (tag != null) {
203
+ const contextJson = context ? JSON.stringify(context) : null;
183
204
  BBPlayerModule?.loadWithClipJson(
184
205
  tag,
185
206
  clipJson,
186
207
  initiator ?? null,
187
208
  autoPlay ?? false,
188
- seekTo ?? 0
209
+ seekTo ?? 0,
210
+ contextJson
189
211
  );
190
212
  }
191
213
  },
@@ -193,16 +215,19 @@ export function createCommands(viewRef: React.RefObject<any>) {
193
215
  clipListJson: string,
194
216
  initiator?: string,
195
217
  autoPlay?: boolean,
196
- seekTo?: number
218
+ seekTo?: number,
219
+ context?: LoadContext
197
220
  ) => {
198
221
  const tag = getViewTag(viewRef);
199
222
  if (tag != null) {
223
+ const contextJson = context ? JSON.stringify(context) : null;
200
224
  BBPlayerModule?.loadWithClipListJson(
201
225
  tag,
202
226
  clipListJson,
203
227
  initiator ?? null,
204
228
  autoPlay ?? false,
205
- seekTo ?? 0
229
+ seekTo ?? 0,
230
+ contextJson
206
231
  );
207
232
  }
208
233
  },
@@ -210,23 +235,27 @@ export function createCommands(viewRef: React.RefObject<any>) {
210
235
  projectJson: string,
211
236
  initiator?: string,
212
237
  autoPlay?: boolean,
213
- seekTo?: number
238
+ seekTo?: number,
239
+ context?: LoadContext
214
240
  ) => {
215
241
  const tag = getViewTag(viewRef);
216
242
  if (tag != null) {
243
+ const contextJson = context ? JSON.stringify(context) : null;
217
244
  BBPlayerModule?.loadWithProjectJson(
218
245
  tag,
219
246
  projectJson,
220
247
  initiator ?? null,
221
248
  autoPlay ?? false,
222
- seekTo ?? 0
249
+ seekTo ?? 0,
250
+ contextJson
223
251
  );
224
252
  }
225
253
  },
226
- loadWithJsonUrl: (jsonUrl: string, autoPlay?: boolean) => {
254
+ loadWithJsonUrl: (jsonUrl: string, autoPlay?: boolean, context?: LoadContext) => {
227
255
  const tag = getViewTag(viewRef);
228
256
  if (tag != null) {
229
- BBPlayerModule?.loadWithJsonUrl(tag, jsonUrl, autoPlay ?? true);
257
+ const contextJson = context ? JSON.stringify(context) : null;
258
+ BBPlayerModule?.loadWithJsonUrl(tag, jsonUrl, autoPlay ?? true, contextJson);
230
259
  }
231
260
  },
232
261
 
@@ -240,13 +269,6 @@ export function createCommands(viewRef: React.RefObject<any>) {
240
269
  }
241
270
  return null;
242
271
  },
243
- getCurrentTime: async (): Promise<number | null> => {
244
- const tag = getViewTag(viewRef);
245
- if (tag != null && BBPlayerModule?.getCurrentTime) {
246
- return BBPlayerModule.getCurrentTime(tag);
247
- }
248
- return null;
249
- },
250
272
  getMuted: async (): Promise<boolean | null> => {
251
273
  const tag = getViewTag(viewRef);
252
274
  if (tag != null && BBPlayerModule?.getMuted) {
@@ -330,7 +352,6 @@ export function createCommands(viewRef: React.RefObject<any>) {
330
352
  state,
331
353
  phase,
332
354
  mode,
333
- currentTime,
334
355
  duration,
335
356
  muted,
336
357
  volume,
@@ -341,7 +362,6 @@ export function createCommands(viewRef: React.RefObject<any>) {
341
362
  BBPlayerModule.getState?.(tag) ?? null,
342
363
  BBPlayerModule.getPhase?.(tag) ?? null,
343
364
  BBPlayerModule.getMode?.(tag) ?? null,
344
- BBPlayerModule.getCurrentTime?.(tag) ?? 0,
345
365
  BBPlayerModule.getDuration?.(tag) ?? 0,
346
366
  BBPlayerModule.getMuted?.(tag) ?? false,
347
367
  BBPlayerModule.getVolume?.(tag) ?? 1,
@@ -354,7 +374,6 @@ export function createCommands(viewRef: React.RefObject<any>) {
354
374
  state: (state as State) ?? "IDLE",
355
375
  phase: (phase as Phase) ?? "INIT",
356
376
  mode: mode ?? null,
357
- currentTime: currentTime ?? 0,
358
377
  duration: duration ?? 0,
359
378
  muted: muted ?? false,
360
379
  volume: volume ?? 1,
package/src/index.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  export { default as BBPlayerView } from "./BBPlayerView";
3
3
  export { default as BBShortsView } from "./BBShortsView";
4
4
  export { default as BBOutstreamView } from "./BBOutstreamView";
5
+ export { BBModalPlayer } from "./BBModalPlayer";
6
+ export type { ModalPlayerOptions } from "./BBModalPlayer";
5
7
  export * from "./BBPlayer.types";
6
8
  export * from "./BBShortsView"; // Export BBShortsView types
7
9
  export * from "./BBOutstreamView"; // Export BBOutstreamView types
@@ -14,6 +14,8 @@ export interface Spec extends TurboModule {
14
14
  enterFullscreen(viewTag: number): void;
15
15
  enterFullscreenLandscape(viewTag: number): void;
16
16
  exitFullscreen(viewTag: number): void;
17
+ presentModal(viewTag: number): void;
18
+ closeModal(viewTag: number): void;
17
19
 
18
20
  // Void methods - layout control
19
21
  collapse(viewTag: number): void;
@@ -30,48 +32,53 @@ export interface Spec extends TurboModule {
30
32
  clipId: string,
31
33
  initiator: string | null,
32
34
  autoPlay: boolean,
33
- seekTo: number
35
+ seekTo: number,
36
+ contextJson: string | null
34
37
  ): void;
35
38
  loadWithClipListId(
36
39
  viewTag: number,
37
40
  clipListId: string,
38
41
  initiator: string | null,
39
42
  autoPlay: boolean,
40
- seekTo: number
43
+ seekTo: number,
44
+ contextJson: string | null
41
45
  ): void;
42
46
  loadWithProjectId(
43
47
  viewTag: number,
44
48
  projectId: string,
45
49
  initiator: string | null,
46
50
  autoPlay: boolean,
47
- seekTo: number
51
+ seekTo: number,
52
+ contextJson: string | null
48
53
  ): void;
49
54
  loadWithClipJson(
50
55
  viewTag: number,
51
56
  clipJson: string,
52
57
  initiator: string | null,
53
58
  autoPlay: boolean,
54
- seekTo: number
59
+ seekTo: number,
60
+ contextJson: string | null
55
61
  ): void;
56
62
  loadWithClipListJson(
57
63
  viewTag: number,
58
64
  clipListJson: string,
59
65
  initiator: string | null,
60
66
  autoPlay: boolean,
61
- seekTo: number
67
+ seekTo: number,
68
+ contextJson: string | null
62
69
  ): void;
63
70
  loadWithProjectJson(
64
71
  viewTag: number,
65
72
  projectJson: string,
66
73
  initiator: string | null,
67
74
  autoPlay: boolean,
68
- seekTo: number
75
+ seekTo: number,
76
+ contextJson: string | null
69
77
  ): void;
70
- loadWithJsonUrl(viewTag: number, jsonUrl: string, autoPlay: boolean): void;
78
+ loadWithJsonUrl(viewTag: number, jsonUrl: string, autoPlay: boolean, contextJson: string | null): void;
71
79
 
72
80
  // Promise getters
73
81
  getDuration(viewTag: number): Promise<number | null>;
74
- getCurrentTime(viewTag: number): Promise<number | null>;
75
82
  getMuted(viewTag: number): Promise<boolean | null>;
76
83
  getVolume(viewTag: number): Promise<number | null>;
77
84
  getPhase(viewTag: number): Promise<string | null>;
@@ -80,6 +87,14 @@ export interface Spec extends TurboModule {
80
87
  getClipData(viewTag: number): Promise<Object | null>;
81
88
  getProjectData(viewTag: number): Promise<Object | null>;
82
89
  getPlayoutData(viewTag: number): Promise<Object | null>;
90
+
91
+ // Modal player (module-level, no React view needed)
92
+ presentModalPlayer(jsonUrl: string, optionsJson: string | null, contextJson: string | null): void;
93
+ dismissModalPlayer(): void;
94
+
95
+ // Event emitter support (required for NativeEventEmitter)
96
+ addListener(eventName: string): void;
97
+ removeListeners(count: number): void;
83
98
  }
84
99
 
85
100
  // Use get() instead of getEnforcing() to avoid crash when module not registered
@@ -1,59 +0,0 @@
1
- # Expo BB Player ProGuard Rules
2
- # Optimizations for release builds
3
-
4
- # Keep Blue Billywig Native Player SDK classes
5
- -keep class com.bluebillywig.** { *; }
6
- -keep interface com.bluebillywig.** { *; }
7
- -keepclassmembers class com.bluebillywig.** { *; }
8
-
9
- # Keep Blue Billywig Native Shared classes
10
- -keep class com.bluebillywig.bbnativeshared.** { *; }
11
- -keep interface com.bluebillywig.bbnativeshared.** { *; }
12
-
13
- # Keep Expo BB Player module classes
14
- -keep class expo.modules.bbplayer.** { *; }
15
- -keep interface expo.modules.bbplayer.** { *; }
16
-
17
- # Keep Expo Modules API classes that are accessed via reflection
18
- -keep class expo.modules.kotlin.** { *; }
19
- -keepclassmembers class expo.modules.kotlin.** { *; }
20
-
21
- # Keep delegate interfaces and their implementations
22
- -keep class * implements com.bluebillywig.bbnativeplayersdk.BBNativePlayerViewDelegate { *; }
23
-
24
- # Keep enum classes used by the SDK
25
- -keepclassmembers enum com.bluebillywig.bbnativeshared.enums.** { *; }
26
-
27
- # Keep model classes that are serialized/deserialized
28
- -keepclassmembers class com.bluebillywig.bbnativeshared.model.** { *; }
29
-
30
- # Remove debug logging in release builds (already guarded by BuildConfig.DEBUG)
31
- -assumenosideeffects class android.util.Log {
32
- public static *** d(...);
33
- public static *** v(...);
34
- public static *** i(...);
35
- }
36
-
37
- # Optimize - but not aggressively to avoid breaking functionality
38
- -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
39
- -optimizationpasses 5
40
- -allowaccessmodification
41
-
42
- # Keep line numbers for better crash reports
43
- -keepattributes SourceFile,LineNumberTable
44
-
45
- # Keep annotations
46
- -keepattributes *Annotation*
47
-
48
- # Keep native methods
49
- -keepclasseswithmembernames class * {
50
- native <methods>;
51
- }
52
-
53
- # Keep custom view constructors (required for Android layout inflation)
54
- -keepclasseswithmembers class * {
55
- public <init>(android.content.Context, android.util.AttributeSet);
56
- }
57
- -keepclasseswithmembers class * {
58
- public <init>(android.content.Context, android.util.AttributeSet, int);
59
- }