@jwplayer/jwplayer-react-native 1.2.0 → 1.3.0

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 (32) hide show
  1. package/README.md +114 -21
  2. package/RNJWPlayer.podspec +1 -1
  3. package/android/build.gradle +14 -1
  4. package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerModule.java +19 -4
  5. package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerView.java +270 -105
  6. package/android/src/main/java/com/jwplayer/rnjwplayer/Util.java +13 -1
  7. package/badges/version.svg +1 -1
  8. package/docs/CONFIG-REFERENCE.md +747 -0
  9. package/docs/MIGRATION-GUIDE.md +617 -0
  10. package/docs/PLATFORM-DIFFERENCES.md +693 -0
  11. package/docs/props.md +15 -3
  12. package/index.d.ts +207 -249
  13. package/ios/RNJWPlayer/RNJWPlayerView.swift +278 -21
  14. package/ios/RNJWPlayer/RNJWPlayerViewController.swift +33 -16
  15. package/package.json +2 -2
  16. package/types/advertising.d.ts +514 -0
  17. package/types/index.d.ts +21 -0
  18. package/types/legacy.d.ts +82 -0
  19. package/types/platform-specific.d.ts +641 -0
  20. package/types/playlist.d.ts +410 -0
  21. package/types/unified-config.d.ts +591 -0
  22. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  23. package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
  24. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  25. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  26. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  27. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  28. package/android/.gradle/8.9/gc.properties +0 -0
  29. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  30. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  31. package/android/.gradle/vcs-1/gc.properties +0 -0
  32. package/docs/types.md +0 -254
package/index.d.ts CHANGED
@@ -2,35 +2,117 @@ declare module "@jwplayer/jwplayer-react-native" {
2
2
  import React from "react";
3
3
  import { ViewStyle } from "react-native";
4
4
 
5
+ // ============================================================================
6
+ // UNIFIED CONFIGURATION TYPES
7
+ // ============================================================================
8
+ // For detailed type definitions, see types/ directory
9
+ // Types are also available by importing from '@jwplayer/jwplayer-react-native/types'
10
+
11
+ // Main configuration interface - see types/unified-config.d.ts for full documentation
12
+ export interface JWPlayerConfig {
13
+ license: string;
14
+ file?: string;
15
+ sources?: any[];
16
+ playlist?: any[] | string;
17
+ playlistIndex?: number;
18
+ autostart?: boolean;
19
+ mute?: boolean;
20
+ repeat?: boolean;
21
+ preload?: 'auto' | 'none' | boolean;
22
+ stretching?: 'uniform' | 'fill' | 'exactfit' | 'none';
23
+ playbackRates?: number[];
24
+ playbackRateControls?: boolean;
25
+ bitrateUpperBound?: number;
26
+ advertising?: any;
27
+ related?: any;
28
+ pid?: string;
29
+ playerId?: string;
30
+ styling?: any;
31
+ uiConfig?: any;
32
+ backgroundAudioEnabled?: boolean;
33
+ category?: string;
34
+ categoryOptions?: string[];
35
+ mode?: string;
36
+ forceLegacyConfig?: boolean;
37
+ playlistItemCallbackEnabled?: boolean;
38
+ playerInModal?: boolean;
39
+ fullScreenOnLandscape?: boolean;
40
+ landscapeOnFullScreen?: boolean;
41
+ portraitOnExitFullScreen?: boolean;
42
+ exitFullScreenOnPortrait?: boolean;
43
+ enableLockScreenControls?: boolean;
44
+ pipEnabled?: boolean;
45
+ useTextureView?: boolean;
46
+ allowCrossProtocolRedirectsSupport?: boolean;
47
+ displaytitle?: boolean;
48
+ displayTitle?: boolean;
49
+ displaydescription?: boolean;
50
+ displayDescription?: boolean;
51
+ nextupoffset?: string | number;
52
+ thumbnailPreview?: number;
53
+ logoView?: any;
54
+ title?: string;
55
+ description?: string;
56
+ image?: string;
57
+ tracks?: any[];
58
+ starttime?: number;
59
+ mediaid?: string;
60
+ mediaId?: string;
61
+ [key: string]: any;
62
+ }
63
+
64
+ // Main configuration type alias
65
+ export type Config = JWPlayerConfig;
66
+
67
+ // Re-export common types with proper names
68
+ export type JWAdvertisingConfig = any;
69
+ export type JWPlaylistItem = any;
70
+ export type JWSource = any;
71
+ export type JWTrack = any;
72
+ export type JWImaDaiSettings = any;
73
+ export type JWImaSdkSettings = any;
74
+ export type JWAdBreak = any;
75
+ export type JWAdRules = any;
76
+ export type JWUiConfig = any;
77
+ export type JWLogoView = any;
78
+ export type JWRelatedConfig = any;
79
+ export type JWStyling = any;
80
+ export type ThumbnailPreview = 101 | 102 | 103;
81
+ export type Stretching = 'uniform' | 'fill' | 'exactfit' | 'none';
82
+
83
+ // ============================================================================
84
+ // BACKWARD COMPATIBILITY
85
+ // ============================================================================
86
+
87
+ /**
88
+ * @deprecated Use JWPlayerConfig or Config instead
89
+ * Maintained for backward compatibility
90
+ */
5
91
  interface JwConfig {
6
92
  pid?: string;
7
93
  mute?: boolean;
8
94
  forceLegacyConfig?: boolean;
9
- /**
10
- * If true, `onBeforeNextPlaylistItem` MUST be impelemented with `player.resolveNextPlaylistItem()` called in the callback or content will hang
11
- */
12
95
  playlistItemCallbackEnabled?: boolean;
13
96
  useTextureView?: boolean;
14
97
  autostart?: boolean;
15
- nextupoffset?: string | number; // String with % or number
98
+ nextupoffset?: string | number;
16
99
  repeat?: boolean;
17
- allowCrossProtocolRedirectsSupport?: boolean; // maybe android only?
100
+ allowCrossProtocolRedirectsSupport?: boolean;
18
101
  displaytitle?: boolean;
19
102
  displaydescription?: boolean;
20
- stretching?: JwStretching;
21
- thumbnailPreview?: JwThumbnailPreview;
103
+ stretching?: string;
104
+ thumbnailPreview?: number;
22
105
  preload?: boolean;
23
- playlist?: JwPlaylistItem[] | string;
24
- sources?: JwSource[]; // Can be used in place of `playlist` to build a playlist, but not recommended (cannot be used for DRM)
25
- file?: string; // Can be used in place of `playlist` to build a playlist, but not recommended (cannot be used for DRM)
106
+ playlist?: any[] | string;
107
+ sources?: any[];
108
+ file?: string;
26
109
  playlistIndex?: number;
27
- related?: JwRelatedConfig;
28
- uiConfig?: JwUiConfig;
29
- logoView?: JwLogoView;
30
- advertising?: JwAdvertisingConfig;
110
+ related?: any;
111
+ uiConfig?: any;
112
+ logoView?: any;
113
+ advertising?: any;
31
114
  playbackRates?: number[];
32
115
  playbackRateControls?: boolean;
33
- // Non-Json Parsing props
34
116
  license: string;
35
117
  playerInModal?: boolean;
36
118
  fullScreenOnLandscape?: boolean;
@@ -39,208 +121,72 @@ declare module "@jwplayer/jwplayer-react-native" {
39
121
  exitFullScreenOnPortrait?: boolean;
40
122
  enableLockScreenControls?: boolean;
41
123
  pipEnabled?: boolean;
42
- }
43
-
44
- type JwThumbnailPreview = 101 | 102 | 103;
45
-
46
- type JwStretching = "uniform" | "fill" | "exactfit" | "none";
47
-
48
- type JwAdvertisingConfig = VmapAdvertisingConfig | VastAdvertisingConfig | ImaVmapAdvertisingConfig
49
- | ImaAdvertisingConfig | ImaDaiAdvertisingConfig;
50
-
51
- interface JwAdRules {
52
- startOn?: number;
53
- frequency?: number;
54
- timeBetweenAds?: number;
55
- startOnSeek?: JwStartOnSeek;
56
- }
57
-
124
+ [key: string]: any;
125
+ }
126
+
127
+ // ============================================================================
128
+ // TYPE ALIASES FOR BACKWARD COMPATIBILITY
129
+ // ============================================================================
130
+
131
+ /**
132
+ * @deprecated Use Stretching from unified types
133
+ */
134
+ type JwStretching = Stretching;
135
+
136
+ /**
137
+ * @deprecated Use ThumbnailPreview from unified types
138
+ */
139
+ type JwThumbnailPreview = ThumbnailPreview;
140
+
141
+ // Re-export advertising types with legacy names for backward compatibility
142
+ /**
143
+ * @deprecated Advertising types are now imported from unified types
144
+ * Use JWAdvertisingConfig instead
145
+ */
146
+ type VmapAdvertisingConfig = import('./types').VmapAdvertisingConfig;
147
+ type VastAdvertisingConfig = import('./types').VastAdvertisingConfig;
148
+ type ImaVmapAdvertisingConfig = import('./types').ImaAdvertisingConfig;
149
+ type ImaAdvertisingConfig = import('./types').ImaAdvertisingConfig;
150
+ type ImaDaiAdvertisingConfig = import('./types').ImaDaiAdvertisingConfig;
151
+
152
+ /**
153
+ * @deprecated Use JWAdRules from unified types
154
+ */
58
155
  type JwStartOnSeek = "pre" | "none";
59
- interface VmapAdvertisingConfig {
60
- cuetext?: string;
61
- adpodmessage?: string;
62
- vpaidcontrols?: boolean;
63
- requestTimeout?: number;
64
- creativeTimeout?: number;
65
- conditionaladoptout?: boolean;
66
- schedule: string; // Must bestring for VMAP
67
- rules?: JwAdRules;
68
- allowedOmidVendors?: string[];
69
- omidSupport?: JwOmidSupport;
70
- admessage?: string;
71
- skipmessage?: string;
72
- skiptext?: string;
73
- skipoffset?: number;
74
- }
75
-
76
- interface VastAdvertisingConfig {
77
- cuetext?: string;
78
- adpodmessage?: string;
79
- vpaidcontrols?: boolean;
80
- requestTimeout?: number;
81
- creativeTimeout?: number;
82
- conditionaladoptout?: boolean;
83
- schedule?: JwAdBreak[]; // Array of breaks or object of breaks
84
- rules: JwAdRules;
85
- allowedOmidVendors?: string[];
86
- omidSupport?: JwOmidSupport;
87
- admessage?: string;
88
- skipmessage?: string;
89
- skiptext?: string;
90
- skipoffset?: number;
91
- }
92
-
156
+
157
+ /**
158
+ * @deprecated Use JWAdBreak from unified types
159
+ */
160
+ type JwAdType = "LINEAR" | "NONLINEAR";
161
+
162
+ /**
163
+ * @deprecated Use OmidSupport from unified types
164
+ */
93
165
  type JwOmidSupport = "auto" | "enabled" | "disabled";
94
-
95
- interface ImaVmapAdvertisingConfig {
96
- imaSdkSettings?: JwImaSdkSettings;
97
- tag?: string;
98
- }
99
-
100
- interface ImaAdvertisingConfig {
101
- imaSdkSettings?: JwImaSdkSettings;
102
- schedule?: JwAdBreak[] | JwAdBreak; // Array of breaks or object of breaks
103
- }
104
-
105
- interface ImaDaiAdvertisingConfig {
106
- imaDaiSettings?: JwImaDaiSettings;
107
- imaSdkSettings?: JwImaSdkSettings;
108
- }
109
-
110
- interface JwImaSdkSettings {
111
- sessionId?: string;
112
- ppid?: string;
113
- autoPlayAdBreaks?: boolean;
114
- language?: string;
115
- maxRedirects?: number; //int
116
- playerType?: string;
117
- playerVersion?: string;
118
- isDebugMode?: boolean;
119
- doesRestrictToCustomPlayer?: boolean;
120
- }
121
-
122
- interface JwLogoView {
123
- imageFile: string;
124
- fades: boolean; // margin required for fade on Android
125
- margin?: number;
126
- position?: JwLogoPosition;
127
- webLink: string;
128
- }
129
-
166
+
167
+ /**
168
+ * @deprecated Use LogoPosition from unified types
169
+ */
130
170
  type JwLogoPosition = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
131
171
 
132
- interface JwUiConfig { // all default to false. When using this, it's specify all or they are assumed false
133
- hasOverlay?: boolean;
134
- hasControlbar?: boolean;
135
- hasCenterControls?: boolean;
136
- hasNextUp?: boolean;
137
- hasSideSeek?: boolean;
138
- hasLogoView?: boolean;
139
- hasError?: boolean;
140
- hasPlaylist?: boolean;
141
- hasQualitySubMenu?: boolean;
142
- hasCaptionsSubMenu?: boolean;
143
- hasPlaybackRatesSubMenu?: boolean;
144
- hasAudiotracksSubMenu?: boolean;
145
- hasMenu?: boolean;
146
- hasPlayerControlsContainer?: boolean;
147
- hasCastingMenu?: boolean;
148
- hasChapters?: boolean;
149
- hasAds?: boolean;
150
- }
151
-
152
- interface JwRelatedConfig {
153
- file?: string;
154
- oncomplete?: JwRelatedOnComplete;
155
- onclick?: JwOnRelatedClick;
156
- // autoplaymessage: string; // deprecated
157
- autoplaytimer: number;
158
- }
159
-
160
- interface JwPlaylistItem {
161
- title?: string;
162
- description?: string;
163
- file?: string;
164
- image?: string;
165
- mediaid?: string;
166
- feedid?: string;
167
- recommendations?: string;
168
- starttime?: number; // double -- default 0.0
169
- duration: number; // int -- default 0
170
- tracks?: JwTrack[];
171
- sources?: JwSource[];
172
- externalMetadata?: JwExternalMetadata[];
173
- adschedule?: JwAdBreak[]; // array of schedules
174
- schedule?: { [key: string]: JwAdBreak };
175
- imaDaiSettings?: JwImaDaiSettings;
176
- httpheaders?: { [key: string]: string };
177
- /**
178
- * Data to be passed to Chromecast receiver (optional and typically used for DRM implementations)
179
- */
180
- userInfo?: { [key: string]: any };
181
- }
182
-
183
- interface JwImaDaiSettings {
184
- videoID?: string;
185
- cmsID?: string;
186
- assetKey?: string;
187
- apiKey?: string;
188
- streamType?: string;
189
- adTagParameters?: { [key: string]: string };
190
- }
191
-
192
- interface JwAdBreak {
193
- ad?: string | string[];
194
- offset?: string;
195
- skipoffset?: number;
196
- type?: JwAdType;
197
- custParams?: { [key: string]: string };
198
- }
199
-
200
- type JwAdType = "LINEAR" | "NONLINEAR";
201
-
202
- interface JwExternalMetadata {
203
- startTime?: number; // double
204
- endTime?: number; // double
205
- id: number; // int
206
- }
207
-
208
- interface JwSource {
209
- drm?: JwDrm;
210
- file?: string;
211
- label?: string;
212
- default?: string;
213
- type?: string;
214
- httpheaders?: { [key: string]: string };
215
- }
216
-
217
- interface JwDrm {
218
- widevine?: JwWidevine;
219
- fairplay?: JwFairplay;
220
- }
221
-
222
- interface JwFairplay {
223
- processSpcUrl?: string;
224
- certificateUrl?: string;
225
- }
226
-
227
- interface JwWidevine {
228
- url?: string;
229
- keySetId?: string;
230
- }
231
-
232
- interface JwTrack {
233
- id?: string;
234
- file?: string;
235
- kind: TrackKind;
236
- label?: string;
237
- default?: boolean;
238
- }
239
-
172
+ // Re-export playlist and media types for backward compatibility
173
+ /**
174
+ * @deprecated These types are now imported from unified types
175
+ * Direct usage is discouraged - import from './types' instead
176
+ */
240
177
  type JwRelatedOnComplete = "hide" | "show" | "none" | "autoplay";
241
-
242
178
  type JwOnRelatedClick = "play" | "link";
243
179
 
180
+ // ============================================================================
181
+ // LEGACY TYPE DEFINITIONS
182
+ // ============================================================================
183
+ // The following types are maintained for backward compatibility with existing code.
184
+ // New code should use the unified types imported from './types' above.
185
+ // These legacy definitions may be removed in a future major version.
186
+
187
+ /**
188
+ * @deprecated Use types from './types' instead
189
+ */
244
190
  interface AudioTrack {
245
191
  autoSelect: boolean;
246
192
  defaultTrack: boolean;
@@ -458,7 +404,10 @@ declare module "@jwplayer/jwplayer-react-native" {
458
404
  | "settings"
459
405
  | "languages"
460
406
  | "fullscreen";
461
- interface Config {
407
+ /**
408
+ * @deprecated Legacy iOS config interface - use JWPlayerConfig instead
409
+ */
410
+ interface LegacyIOSConfig {
462
411
  license: string;
463
412
  advertising?: Advertising;
464
413
  autostart?: boolean;
@@ -559,7 +508,7 @@ declare module "@jwplayer/jwplayer-react-native" {
559
508
  type NativeError = (event: BaseEvent<PlayerErrorEventProps> | BaseEvent<PlayerSetupErrorProps> | BaseEvent<PlayerErrorProps>) => void;
560
509
  type NativeWarning = (event: BaseEvent<PlayerWarningEventProps>) => void;
561
510
  interface PropsType {
562
- config: Config | JwConfig;
511
+ config: JWPlayerConfig | JwConfig | LegacyIOSConfig;
563
512
  style?: ViewStyle;
564
513
  controls?: boolean;
565
514
  forceLegacyConfig?: boolean;
@@ -661,9 +610,9 @@ declare module "@jwplayer/jwplayer-react-native" {
661
610
  changePlaylist(fileUrl: string): void;
662
611
  /**
663
612
  * Side load playlist items into an already setup player
664
- * @param playlistItems `PlaylistItem` or `JwPlaylistItem`
613
+ * @param playlistItems `PlaylistItem` or `JWPlaylistItem`
665
614
  */
666
- loadPlaylist(playlistItems: PlaylistItem[] | JwPlaylistItem[]): void;
615
+ loadPlaylist(playlistItems: PlaylistItem[] | JWPlaylistItem[]): void;
667
616
  /**
668
617
  * Side load playlist via URL into an already setup player
669
618
  * @param playlistUrl URL for playlist to load (format for response: json)
@@ -686,60 +635,69 @@ declare module "@jwplayer/jwplayer-react-native" {
686
635
  getCurrentCaptions(): Promise<number | null>;
687
636
  setVisibility(visibility: boolean, controls: JWControlType[]): void;
688
637
  /**
689
- * Recreates the player with a new configuration, handling cleanup and PiP state.
690
- *
691
- * NOTE: This method is only available on iOS. On Android, create a new player instance
692
- * with the new configuration instead.
638
+ * Reconfigures or recreates the player with a new configuration.
693
639
  *
694
640
  * IMPORTANT: This method should only be called after the player has been properly
695
641
  * initialized and is ready (i.e., after onPlayerReady has fired). Calling this
696
642
  * method before the player is ready may lead to undefined behavior.
697
643
  *
698
- * This method performs a complete player recreation by:
699
- * 1. Safely handling PiP state if active (waits for PiP to close)
700
- * 2. Performing complete cleanup of the current player instance
701
- * 3. Creating a new player instance with the provided config
644
+ * **Platform Behavior:**
645
+ *
646
+ * - **iOS**: Always performs a complete player recreation by:
647
+ * 1. Safely handling PiP state if active (waits for PiP to close)
648
+ * 2. Performing complete cleanup of the current player instance
649
+ * 3. Creating a new player instance with the provided config
702
650
  *
703
- * Use this method when you need to:
704
- * - Switch between different DRM configurations
651
+ * - **Android**: Intelligently determines whether to recreate or reconfigure:
652
+ * - ~90% of cases: Reconfigures existing player (preserves player instance, faster)
653
+ * - ~10% of cases: Recreates player (only when necessary, e.g., license changes)
654
+ * - Automatically handles state preservation (fullscreen, PiP)
655
+ *
656
+ * **Use this method when you need to:**
657
+ * - Switch to a new playlist or video programmatically
658
+ * - Update player configuration dynamically (e.g., from user settings)
705
659
  * - Handle content changes during PiP mode
706
- * - Force a complete player recreation
660
+ * - Write cross-platform code (same API works on both platforms)
707
661
  *
708
- * Do NOT use this method:
662
+ * **Do NOT use this method:**
709
663
  * - Before the player is ready (wait for onPlayerReady)
710
- * - For simple playlist updates (use loadPlaylist instead)
711
664
  * - When the player is not properly initialized
712
- * - On Android (create a new player instance instead)
665
+ *
666
+ * **For simple playlist updates, consider using `loadPlaylist()` instead.**
713
667
  *
714
668
  * @example
715
669
  * ```typescript
716
- * // Wait for player to be ready
717
- * onPlayerReady={() => {
718
- * // Now safe to use recreatePlayerWithConfig (iOS only)
719
- * if (Platform.OS === 'ios') {
720
- * playerRef.current?.recreatePlayerWithConfig({
721
- * ...config,
722
- * playlist: newPlaylist
723
- * });
724
- * } else {
725
- * // On Android, create a new player instance
726
- * setPlayerConfig({
727
- * ...config,
728
- * playlist: newPlaylist
729
- * });
730
- * }
731
- * }}
670
+ * // Cross-platform example - works the same on both iOS and Android
671
+ * const switchVideo = () => {
672
+ * playerRef.current?.recreatePlayerWithConfig({
673
+ * license: 'YOUR_LICENSE_KEY',
674
+ * playlist: [{
675
+ * file: 'https://example.com/video.mp4',
676
+ * title: 'New Video'
677
+ * }],
678
+ * autostart: true
679
+ * });
680
+ * };
681
+ *
682
+ * // Use inside onPlayerReady
683
+ * <JWPlayer
684
+ * ref={playerRef}
685
+ * config={initialConfig}
686
+ * onPlayerReady={() => {
687
+ * // Now safe to use recreatePlayerWithConfig
688
+ * console.log('Player ready, can switch content if needed');
689
+ * }}
690
+ * />
732
691
  * ```
733
692
  *
734
- * @platform ios
735
- * @param config The new configuration to apply to the recreated player
693
+ * @param config The new configuration to apply
736
694
  * @throws May throw if called before player is ready or with invalid config
737
695
  */
738
- recreatePlayerWithConfig(config: Config | JwConfig): void;
696
+ recreatePlayerWithConfig(config: JWPlayerConfig | JwConfig | LegacyIOSConfig): void;
739
697
  /**
740
698
  * Only called inside `onBeforeNextPlaylistItem` callback, and once per callback
741
- * @param playlistItem `PlaylistItem` or `JwPlaylistItem`
699
+ * @param playlistItem `PlaylistItem` or `JWPlaylistItem`
742
700
  */
743
- resolveNextPlaylistItem(playlistItem: PlaylistItem | JwPlaylistItem): void;
701
+ resolveNextPlaylistItem(playlistItem: PlaylistItem | JWPlaylistItem): void;
744
702
  }
745
703
  }