react-native-theoplayer 1.5.0 → 1.6.1

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.
@@ -210,7 +210,9 @@ public class ReactTHEOplayerView extends FrameLayout implements LifecycleEventLi
210
210
  player.play();
211
211
  }
212
212
 
213
- seekTo(this.seekTime);
213
+ if (this.seekTime != TIME_UNSET) {
214
+ seekTo(this.seekTime);
215
+ }
214
216
  }
215
217
  }, 1);
216
218
  }
@@ -14,3 +14,6 @@ let DEBUG_THEOPLAYER_INTERACTION = DEBUG && true
14
14
 
15
15
  // Debug flag to monitor all updates made on bridged properties
16
16
  let DEBUG_PROP_UPDATES = DEBUG && true
17
+
18
+ // Debug flag to monitor correct SourceDescription buildup
19
+ let DEBUG_SOURCE_DESCRIPTION_BUIDER = DEBUG && true
@@ -0,0 +1,212 @@
1
+ // THEOplayerRCTSourceDescriptionBuilder.swift
2
+
3
+ import Foundation
4
+ import THEOplayerSDK
5
+ import UIKit
6
+
7
+ let SD_PROP_SOURCES: String = "sources"
8
+ let SD_PROP_POSTER: String = "poster"
9
+ let SD_PROP_TEXTTRACKS: String = "textTracks"
10
+ let SD_PROP_SRC: String = "src"
11
+ let SD_PROP_TYPE: String = "type"
12
+ let SD_PROP_INTEGRATION: String = "integration"
13
+ let SD_PROP_SRC_LANG: String = "srclang"
14
+ let SD_PROP_DEFAULT: String = "default"
15
+ let SD_PROP_LABEL: String = "label"
16
+ let SD_PROP_KIND: String = "kind"
17
+ let SD_PROP_FORMAT: String = "format"
18
+ let SD_PROP_CONTENT_PROTECTION: String = "contentProtection"
19
+
20
+ let EXTENSION_HLS: String = ".m3u8"
21
+ let EXTENSION_MP4: String = ".mp4"
22
+ let EXTENSION_MP3: String = ".mp3"
23
+
24
+ let MIMETYPE_HLS = "application/x-mpegurl"
25
+ let MIMETYPE_MP4 = "video/mp4"
26
+ let MIMETYPE_MP3 = "audio/mpeg"
27
+
28
+ let DRM_INTEGRATION_ID_EZDRM = "ezdrm"
29
+ let DRM_INTEGRATION_ID_KEYOS = "keyos"
30
+ let DRM_INTEGRATION_ID_VERIMATRIX = "verimatrix"
31
+
32
+ class THEOplayerRCTSourceDescriptionBuilder {
33
+
34
+ /**
35
+ Builds a THEOplayer SourceDescription that can be passed as a source for the THEOplayer.
36
+ - returns: a THEOplayer TypedSource. In case of SSAI we support GoogleDAITypedSource with GoogleDAIVodConfiguration or GoogleDAILiveConfiguration
37
+ */
38
+ static func buildSourceDescription(_ sourceData: NSDictionary) -> SourceDescription? {
39
+ // 1. Extract "sources"
40
+ guard let sourcesData = sourceData[SD_PROP_SOURCES] else {
41
+ return nil
42
+ }
43
+
44
+ var typedSources: [TypedSource] = []
45
+ // case: array of source objects
46
+ if let sourcesDataArray = sourcesData as? [[String:Any]] {
47
+ for typedSourceData in sourcesDataArray {
48
+ if let typedSource = THEOplayerRCTSourceDescriptionBuilder.buildTypedSource(typedSourceData) {
49
+ typedSources.append(typedSource)
50
+ } else {
51
+ if DEBUG_SOURCE_DESCRIPTION_BUIDER {
52
+ print("[NATIVE] Could not create THEOplayer TypedSource from sourceData array")
53
+ }
54
+ return nil
55
+ }
56
+ }
57
+ }
58
+ // case: single source object
59
+ else if let typedSourceData = sourcesData as? [String:Any] {
60
+ if let typedSource = THEOplayerRCTSourceDescriptionBuilder.buildTypedSource(typedSourceData) {
61
+ typedSources.append(typedSource)
62
+ } else {
63
+ if DEBUG_SOURCE_DESCRIPTION_BUIDER {
64
+ print("[NATIVE] Could not create THEOplayer TypedSource from sourceData")
65
+ }
66
+ return nil
67
+ }
68
+ }
69
+
70
+ // 2. extract 'poster'
71
+ let poster = sourceData[SD_PROP_POSTER] as? String
72
+
73
+ // 3. extract 'textTracks'
74
+ var textTrackDescriptions: [TextTrackDescription]?
75
+ if let textTracksDataArray = sourceData[SD_PROP_TEXTTRACKS] as? [[String:Any]] {
76
+ textTrackDescriptions = []
77
+ for textTracksData in textTracksDataArray {
78
+ if let textTrackDescription = THEOplayerRCTSourceDescriptionBuilder.buildTextTrackDescriptions(textTracksData) {
79
+ textTrackDescriptions?.append(textTrackDescription)
80
+ } else {
81
+ if DEBUG_SOURCE_DESCRIPTION_BUIDER {
82
+ print("[NATIVE] Could not create THEOplayer TextTrackDescription from textTrackData array")
83
+ }
84
+ return nil
85
+ }
86
+ }
87
+
88
+ }
89
+
90
+ // 4. construct and return SourceDescription
91
+ return SourceDescription(sources: typedSources,
92
+ textTracks: textTrackDescriptions,
93
+ poster: poster,
94
+ metadata: nil) // TODO
95
+ }
96
+
97
+ // MARK: Private build methods
98
+
99
+ /**
100
+ Creates a THEOplayer TypedSource. This requires a source property for non SSAI strreams (either as a string or as an object contiaining a src property). For SSAI streams the TypeSource can be created from the ssai property.
101
+ - returns: a THEOplayer TypedSource. In case of SSAI we support GoogleDAITypedSource with GoogleDAIVodConfiguration or GoogleDAILiveConfiguration
102
+ */
103
+ private static func buildTypedSource(_ typedSourceData: [String:Any]) -> TypedSource? {
104
+ if let src = typedSourceData[SD_PROP_SRC] as? String {
105
+ // extract the type
106
+ let type = typedSourceData[SD_PROP_TYPE] as? String ?? THEOplayerRCTSourceDescriptionBuilder.extractMimeType(src)
107
+ // check for a contentProtection
108
+ var contentProtection: MultiplatformDRMConfiguration?
109
+ if let contentProtectionData = typedSourceData[SD_PROP_CONTENT_PROTECTION] as? [String:Any] {
110
+ contentProtection = THEOplayerRCTSourceDescriptionBuilder.buildContentProtection(contentProtectionData)
111
+ }
112
+
113
+ return TypedSource(src: src,
114
+ type: type,
115
+ drm: contentProtection)
116
+ }
117
+
118
+ if DEBUG_SOURCE_DESCRIPTION_BUIDER {
119
+ print("[NATIVE] THEOplayer TypedSource requires 'src' property in 'sources' description")
120
+ }
121
+ return nil
122
+ }
123
+
124
+ /**
125
+ Creates a THEOplayer TextTrackDescription. This requires a textTracks property in the RN source description.
126
+ - returns: a THEOplayer TextTrackDescription
127
+ */
128
+ private static func buildTextTrackDescriptions(_ textTracksData: [String:Any]) -> TextTrackDescription? {
129
+ if let textTrackSrc = textTracksData[SD_PROP_SRC] as? String,
130
+ let textTrackSrcLang = textTracksData[SD_PROP_SRC_LANG] as? String {
131
+ let textTrackIsDefault = textTracksData[SD_PROP_DEFAULT] as? Bool
132
+ let textTrackLabel = textTracksData[SD_PROP_LABEL] as? String
133
+ let textTrackKind = THEOplayerRCTSourceDescriptionBuilder.extractTextTrackKind(textTracksData[SD_PROP_KIND] as? String)
134
+ let textTrackFormat = THEOplayerRCTSourceDescriptionBuilder.extractTextTrackFormat(textTracksData[SD_PROP_FORMAT] as? String)
135
+ print(textTrackKind._rawValue)
136
+ print(textTrackFormat._rawValue)
137
+ return TextTrackDescription(src: textTrackSrc,
138
+ srclang: textTrackSrcLang,
139
+ isDefault: textTrackIsDefault,
140
+ kind: textTrackKind,
141
+ label: textTrackLabel,
142
+ format: textTrackFormat)
143
+ }
144
+ return nil
145
+ }
146
+
147
+ /**
148
+ Creates a THEOplayer DRMConfiguration. This requires a contentProtection property in the RN source description.
149
+ - returns: a THEOplayer DRMConfiguration
150
+ */
151
+ private static func buildContentProtection(_ contentProtectionData: [String:Any]) -> MultiplatformDRMConfiguration? {
152
+ do {
153
+ let data = try JSONSerialization.data(withJSONObject: contentProtectionData)
154
+ if let integration = contentProtectionData[SD_PROP_INTEGRATION] as? String {
155
+ switch integration {
156
+ case DRM_INTEGRATION_ID_EZDRM: return try JSONDecoder().decode(EzdrmDRMConfiguration.self, from: data)
157
+ case DRM_INTEGRATION_ID_KEYOS: return try JSONDecoder().decode(KeyOSDRMConfiguration.self, from: data)
158
+ case DRM_INTEGRATION_ID_VERIMATRIX: return try JSONDecoder().decode(VerimatrixDRMConfiguration.self, from: data)
159
+ default: print("[NATIVE] \(integration): unsupported drm integration")
160
+ }
161
+ } else {
162
+ print("[NATIVE] integration type not specified... trying default drm integration")
163
+ return try JSONDecoder().decode(MultiplatformDRMConfiguration.self, from: data)
164
+ }
165
+ } catch {
166
+ print("[NATIVE] unsupported contentProtection data format")
167
+ }
168
+ return nil
169
+ }
170
+
171
+
172
+ // MARK: Helper methods
173
+
174
+ private static func extractMimeType(_ src: String) -> String {
175
+ if src.suffix(5) == EXTENSION_HLS {
176
+ return MIMETYPE_HLS
177
+ } else if src.suffix(4) == EXTENSION_MP4 {
178
+ return MIMETYPE_MP4
179
+ } else if src.suffix(4) == EXTENSION_MP3 {
180
+ return MIMETYPE_MP3
181
+ }
182
+ return MIMETYPE_HLS
183
+ }
184
+
185
+ private static func extractTextTrackKind(_ kindString: String?) -> THEOplayerSDK.TextTrackKind {
186
+ guard let kind = kindString else {
187
+ return THEOplayerSDK.TextTrackKind.none
188
+ }
189
+
190
+ switch kind {
191
+ case "subtitles": return THEOplayerSDK.TextTrackKind.subtitles
192
+ case "captions": return THEOplayerSDK.TextTrackKind.captions
193
+ case "description": return THEOplayerSDK.TextTrackKind.description
194
+ case "chapters": return THEOplayerSDK.TextTrackKind.chapters
195
+ case "metadata": return THEOplayerSDK.TextTrackKind.metadata
196
+ default: return THEOplayerSDK.TextTrackKind.none
197
+
198
+ }
199
+ }
200
+
201
+ private static func extractTextTrackFormat(_ formatString: String?) -> THEOplayerSDK.TextTrackFormat {
202
+ guard let format = formatString else {
203
+ return THEOplayerSDK.TextTrackFormat.none
204
+ }
205
+
206
+ if format == "webvtt" {
207
+ return THEOplayerSDK.TextTrackFormat.WebVTT
208
+ } else {
209
+ return THEOplayerSDK.TextTrackFormat.none
210
+ }
211
+ }
212
+ }
@@ -70,14 +70,13 @@ class THEOplayerRCTView: UIView {
70
70
  // MARK: - Property bridging
71
71
  @objc(setSrc:)
72
72
  func setSrc(srcDict: NSDictionary) {
73
- do {
74
- // store sourceDescription
75
- let data = try JSONSerialization.data(withJSONObject: srcDict)
76
- let sourceDescription = try JSONDecoder().decode(SourceDescription.self, from: data)
77
- self.src = sourceDescription
73
+ // build THEOplayer SourceDescription
74
+ if let src = THEOplayerRCTSourceDescriptionBuilder.buildSourceDescription(srcDict) {
75
+ self.src = src
78
76
  if DEBUG_PROP_UPDATES { print("[NATIVE] src prop updated.") }
79
- } catch {
80
- print(error)
77
+ } else {
78
+ if DEBUG_PROP_UPDATES { print("[NATIVE] failed to update THEOplayer source.") }
79
+ return
81
80
  }
82
81
 
83
82
  if (self.player == nil) {
@@ -12,7 +12,7 @@ let REMOVE_CUE: Int = 1
12
12
  class THEOplayerRCTViewEventHandler {
13
13
  // MARK: Members
14
14
  private weak var player: THEOplayer?
15
- private var currentPresentationMode = PresentationMode.inline // TheoPlayer's initial presentationMode
15
+ private var currentPresentationMode = THEOplayerSDK.PresentationMode.inline // TheoPlayer's initial presentationMode
16
16
 
17
17
  // MARK: Events
18
18
  var onNativePlay: RCTDirectEventBlock?
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-theoplayer",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "A THEOplayer video component for react-native.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -17,12 +17,10 @@
17
17
  "!lib/typescript/example",
18
18
  "!android/build",
19
19
  "!ios/build",
20
- "!**/__tests__",
21
20
  "!**/__fixtures__",
22
21
  "!**/__mocks__"
23
22
  ],
24
23
  "scripts": {
25
- "test": "jest",
26
24
  "typescript": "tsc --noEmit",
27
25
  "lint": "eslint \"**/*.{ts,tsx}\"",
28
26
  "prepare": "bob build",
@@ -51,7 +49,6 @@
51
49
  "@commitlint/config-conventional": "^11.0.0",
52
50
  "@react-native-community/eslint-config": "^2.0.0",
53
51
  "@release-it/conventional-changelog": "^2.0.0",
54
- "@types/jest": "^26.0.0",
55
52
  "@types/react": "^17.0.1",
56
53
  "@types/react-native": "0.64.2",
57
54
  "commitlint": "^11.0.0",
@@ -60,7 +57,6 @@
60
57
  "eslint-plugin-prettier": "^3.1.3",
61
58
  "eslint-plugin-react-native": "^4.0.0",
62
59
  "husky": "^6.0.0",
63
- "jest": "^26.0.1",
64
60
  "pod-install": "^0.1.0",
65
61
  "prettier": "^2.0.5",
66
62
  "react": "17.0.1",
@@ -73,13 +69,6 @@
73
69
  "react": "*",
74
70
  "react-native": "*"
75
71
  },
76
- "jest": {
77
- "preset": "react-native",
78
- "modulePathIgnorePatterns": [
79
- "<rootDir>/example/node_modules",
80
- "<rootDir>/lib/"
81
- ]
82
- },
83
72
  "commitlint": {
84
73
  "extends": [
85
74
  "@commitlint/config-conventional"
@@ -0,0 +1 @@
1
+ export {};