@takeoffmedia/react-native-penthera 0.2.17 → 0.2.19

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/Catalog.swift CHANGED
@@ -1,3 +1,5 @@
1
+ import Foundation
2
+
1
3
  struct Catalog: Codable {
2
4
  var id: String = ""
3
5
  var url: String = ""
@@ -98,3 +100,46 @@ struct Event: Codable {
98
100
  var assetId: String = ""
99
101
  var body: String = ""
100
102
  }
103
+
104
+ struct DataInfo: Codable {
105
+ var id: String = ""
106
+ var title: String = ""
107
+ var episodeNumber: Int = 0
108
+ var duration: Int = 0
109
+ var seasonId: String = ""
110
+ var seasonTitle: String = ""
111
+ var dataOffers: [DataOffer] = []
112
+
113
+ struct DataOffer: Codable {
114
+ var bold: Bool = false
115
+ var label: String = ""
116
+ }
117
+ }
118
+
119
+ struct Subtitle: Codable {
120
+ var label: String = ""
121
+ var language: String = ""
122
+ var href: String? = ""
123
+ var url: String? = ""
124
+ }
125
+
126
+
127
+ struct DownloadItem: Codable {
128
+ let id: String
129
+ let title: String
130
+ let drm: Bool?
131
+ let path: String?
132
+ let thumbnails: Thumbnails?
133
+ let data: String?
134
+ let subtitles: String
135
+ }
136
+
137
+ struct AssetData: Codable {
138
+ let id: String
139
+ let url: String
140
+ let certificate: String?
141
+ let license: String?
142
+ let subtitles: [Subtitle]?
143
+ let js: String?
144
+ let css: String?
145
+ }
@@ -197,12 +197,10 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
197
197
  }
198
198
  return asset
199
199
  }
200
- func getAncillaryFiles(files: [String: AnyObject]) -> [VirtuosoAncillaryFile] {
200
+ func getAncillaryFiles(files: [String: String]) -> [VirtuosoAncillaryFile] {
201
201
  var ancillaryFiles: [VirtuosoAncillaryFile] = []
202
202
  files.forEach { file in
203
- guard let url = file.value as? String else {
204
- return
205
- }
203
+ let url = file.value
206
204
  guard let ancillaryFile = VirtuosoAncillaryFile(downloadUrl: url, andTag: file.key) else {
207
205
  return
208
206
  }
@@ -211,6 +209,22 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
211
209
  return ancillaryFiles
212
210
  }
213
211
 
212
+ // Función para convertir un String en un objeto DataInfo
213
+ func stringToSubtitles(_ jsonString: String) -> [Subtitle]? {
214
+ // Crear un Data a partir del String
215
+ if let jsonData = jsonString.data(using: .utf8) {
216
+ do {
217
+ // Decodificar el Data en un objeto DataInfo
218
+ let dataInfo = try JSONDecoder().decode([Subtitle].self, from: jsonData)
219
+ return dataInfo
220
+ } catch {
221
+ print("Error al decodificar el String en Subtitle: \(error)")
222
+ }
223
+ }
224
+ return nil
225
+ }
226
+
227
+
214
228
  @objc(download:withResolver:withRejecter:)
215
229
  func download(catalogString: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
216
230
  let virtuoso = VirtuosoDownloadEngine.instance()
@@ -232,6 +246,7 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
232
246
  return
233
247
  }
234
248
 
249
+
235
250
  let assetID = item["id"] as! String? ?? ""
236
251
 
237
252
  let hasDRM = item["drm"] as! Bool? ?? false
@@ -246,42 +261,67 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
246
261
  return
247
262
  }
248
263
  // Ancillary Files
249
- let thumbnails = item["thumbnails"] as! [String: AnyObject]? ?? [:]
250
- let subtitles = item["subtitles"] as! [String: AnyObject]? ?? [:]
251
- config.ancillaries = self.getAncillaryFiles(files: thumbnails) + self.getAncillaryFiles(files: subtitles)
264
+ var ancillarySubtitles: [String: String] = [:]
265
+ let thumbnails = item["thumbnails"] as! [String: String]? ?? [:]
266
+ if let subtitlesString = item["subtitles"] as? String {
267
+ if let subtitles = self.stringToSubtitles(subtitlesString) {
268
+ for subtitle in subtitles {
269
+ ancillarySubtitles[subtitle.language] = subtitle.href;
270
+ }
271
+ }
272
+ }
252
273
 
274
+ if let staticFile = item["static"] as? [String: AnyObject] {
275
+ if let js = staticFile["js"] as? String {
276
+ ancillarySubtitles["js"] = js
277
+ }
278
+ if let css = staticFile["css"] as? String {
279
+ ancillarySubtitles["css"] = css
280
+ }
281
+ }
253
282
 
283
+ if(ancillarySubtitles.count > 0){
284
+ config.ancillaries = self.getAncillaryFiles(files: thumbnails) + self.getAncillaryFiles(files: ancillarySubtitles)
285
+ }
254
286
  //DRM
255
- if(hasDRM) {
256
287
 
257
- guard let drm = data!["drm"] as! [String: AnyObject]? else {
258
- reject("No drm", nil, nil)
259
- return
260
- }
288
+ if(hasDRM) {
261
289
 
262
- let token = drm["token"] as! String? ?? ""
263
- let licenceHttpHeader = drm["licence_server_http_header"] as! String? ?? ""
264
- let licence = drm["licence_server"] as! String? ?? ""
265
- let cert = drm["fairplay_cert"] as! String? ?? ""
290
+ guard let drm = data!["drm"] as! [String: AnyObject]? else {
291
+ reject("No drm", nil, nil)
292
+ return
293
+ }
266
294
 
267
- guard let drmSetup = FairPlayDrmSetup(assetID: assetID, certificateUrl: cert, licenceUrl: licence, header: licenceHttpHeader, token: token) else {
268
- EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
269
- return
270
- }
295
+ let token = drm["token"] as! String? ?? ""
296
+ let licenceHttpHeader = drm["licence_server_http_header"] as! String? ?? ""
297
+ let licence = drm["licence_server"] as! String? ?? ""
298
+ let cert = drm["fairplay_cert"] as! String? ?? ""
299
+
300
+ guard let drmSetup = FairPlayDrmSetup(assetID: assetID, certificateUrl: cert, licenceUrl: licence, header: licenceHttpHeader, token: token) else {
301
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
302
+ return
303
+ }
304
+
305
+ if !drmSetup.configure() {
306
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
307
+ return
308
+ }
309
+ config.protectionType = .vde_AssetProtectionTypeFairPlay
271
310
 
272
- if !drmSetup.configure() {
273
- EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
274
- return
275
311
  }
276
- config.protectionType = .vde_AssetProtectionTypeFairPlay
277
312
 
278
- }
279
313
 
280
314
  let asset = VirtuosoAsset.init(config: config)
315
+ let data = item["data"]
316
+
317
+ if let dataInfoDict = data as? [AnyHashable: Any] {
318
+ asset?.userInfo = dataInfoDict
319
+ } else {
320
+ asset?.userInfo = nil
321
+ }
322
+
281
323
 
282
- let data = item["data"] as! [String: AnyObject]? ?? [:]
283
324
 
284
- asset?.userInfo = data
285
325
 
286
326
  config.ancillaries?.forEach{ file in
287
327
  asset?.add(file)
@@ -290,10 +330,6 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
290
330
  queue.append(asset!)
291
331
  resolve(assetID)
292
332
  }
293
-
294
-
295
- } catch {
296
- reject("penthera", error.localizedDescription, error)
297
333
  }
298
334
  }
299
335
 
@@ -427,15 +463,48 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
427
463
 
428
464
  let licenseURL = vcHttpServer?.fairPlayLicenseServerURL
429
465
  let certificateURL = vcHttpServer?.fairPlayCertificateDataURL(forSubType: nil)
466
+ var subtitlesResponse: [Subtitle] = []
467
+ var language: String? = nil, url: String? = nil, label: String? = nil
468
+ asset.userInfo.map{ userInfo in
469
+ if let subtitles = userInfo["subtitles"] as? Array<Dictionary<String, String>> {
470
+ for subtitle in subtitles {
471
+ for (key, value) in subtitle {
472
+ if key == "language" {
473
+ url = vcHttpServer?.ancillaryURLForAncillary(withTag: value, usingMime: "")
474
+ language = value
475
+ }
476
+ if key == "label" {
477
+ label = value
478
+ }
479
+ if(label != nil && language != nil && url != nil){
480
+ subtitlesResponse.append(
481
+ Subtitle(
482
+ label: label ?? "",
483
+ language: language ?? "",
484
+ url: url
485
+ )
486
+ )
487
+ label = nil
488
+ language = nil
489
+ url = nil
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
495
+
496
+ let assetDataObject = AssetData(
497
+ id: asset.assetID,
498
+ url: vcHttpServer?.playbackURL ?? "",
499
+ certificate: certificateURL,
500
+ license: licenseURL,
501
+ subtitles: subtitlesResponse,
502
+ js: vcHttpServer?.ancillaryURLForAncillary(withTag: "js", usingMime: ""),
503
+ css: vcHttpServer?.ancillaryURLForAncillary(withTag: "css", usingMime: "")
504
+ )
430
505
 
431
- let assetData = [
432
- "id": asset.assetID,
433
- "url": vcHttpServer?.playbackURL ?? "",
434
- "certificate": certificateURL ,
435
- "license": licenseURL
436
- ]
437
506
 
438
- let data = try decoder.encode(assetData)
507
+ let data = try decoder.encode(assetDataObject)
439
508
  let json = String(data: data, encoding: .utf8)!
440
509
  resolve(json)
441
510
 
@@ -460,5 +529,4 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
460
529
  EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ASSET_RESUME_DOWNLOAD_UPDATED, assetId: asset.assetID, body: "\(asset.isPaused)")
461
530
  }
462
531
 
463
-
464
532
  }
@@ -16,8 +16,8 @@
16
16
  endingColumnNumber = "9223372036854775807"
17
17
  startingLineNumber = "18"
18
18
  endingLineNumber = "18"
19
- landmarkName = "initializeSdk(user:backplaneUrl:publicKey:privateKey:resolve:reject:)"
20
- landmarkType = "7">
19
+ landmarkName = "Penthera"
20
+ landmarkType = "3">
21
21
  </BreakpointContent>
22
22
  </BreakpointProxy>
23
23
  <BreakpointProxy
@@ -32,7 +32,7 @@
32
32
  endingColumnNumber = "9223372036854775807"
33
33
  startingLineNumber = "25"
34
34
  endingLineNumber = "25"
35
- landmarkName = "initializeSdk(user:backplaneUrl:publicKey:privateKey:resolve:reject:)"
35
+ landmarkName = "updateStatusInfo()"
36
36
  landmarkType = "7">
37
37
  </BreakpointContent>
38
38
  </BreakpointProxy>
@@ -48,7 +48,7 @@
48
48
  endingColumnNumber = "9223372036854775807"
49
49
  startingLineNumber = "26"
50
50
  endingLineNumber = "26"
51
- landmarkName = "initializeSdk(user:backplaneUrl:publicKey:privateKey:resolve:reject:)"
51
+ landmarkName = "updateStatusInfo()"
52
52
  landmarkType = "7">
53
53
  </BreakpointContent>
54
54
  </BreakpointProxy>
@@ -64,7 +64,7 @@
64
64
  endingColumnNumber = "9223372036854775807"
65
65
  startingLineNumber = "101"
66
66
  endingLineNumber = "101"
67
- landmarkName = "getDownloads(blank:resolve:reject:)"
67
+ landmarkName = "initializeSdk(user:backplaneUrl:publicKey:privateKey:resolve:reject:)"
68
68
  landmarkType = "7">
69
69
  </BreakpointContent>
70
70
  </BreakpointProxy>
@@ -80,7 +80,7 @@
80
80
  endingColumnNumber = "9223372036854775807"
81
81
  startingLineNumber = "149"
82
82
  endingLineNumber = "149"
83
- landmarkName = "getDownloads(blank:resolve:reject:)"
83
+ landmarkName = "getDownloadedAsset(assetID:)"
84
84
  landmarkType = "7">
85
85
  </BreakpointContent>
86
86
  </BreakpointProxy>
@@ -96,7 +96,7 @@
96
96
  endingColumnNumber = "9223372036854775807"
97
97
  startingLineNumber = "148"
98
98
  endingLineNumber = "148"
99
- landmarkName = "getDownloads(blank:resolve:reject:)"
99
+ landmarkName = "getDownloadedAsset(assetID:)"
100
100
  landmarkType = "7">
101
101
  </BreakpointContent>
102
102
  </BreakpointProxy>
@@ -16,11 +16,19 @@ type Progress = string;
16
16
  export type AssetProgress = {
17
17
  [key: string]: Progress;
18
18
  };
19
+ export type Subtitle = {
20
+ url: string;
21
+ label: string;
22
+ language: string;
23
+ };
19
24
  export interface InterfaceDataPlay {
20
25
  url?: string;
21
26
  license?: string;
22
27
  certificate?: string;
23
28
  id?: string;
29
+ subtitles?: Subtitle[];
30
+ js?: string;
31
+ css?: string;
24
32
  }
25
33
  export type PentheraState = {
26
34
  assets: PentheraTypes.ItemCatalog[] | [];
@@ -1 +1 @@
1
- {"version":3,"file":"usePenthera.types.d.ts","sourceRoot":"","sources":["../../../../src/hooks/usePenthera/usePenthera.types.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,oBAAY,aAAa;IACvB,gBAAgB,qBAAqB;IACrC,qBAAqB,0BAA0B;IAC/C,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,6BAA6B,kCAAkC;IAC/D,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,mBAAmB,wBAAwB;CAC5C;AACD,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAC7B,KAAK,QAAQ,GAAG,MAAM,CAAC;AAEvB,MAAM,MAAM,aAAa,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC;IACzC,cAAc,EAAE,aAAa,GAAG,EAAE,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC/C,oBAAoB,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7D,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,cAAc,KAAK,IAAI,CAAC;IACzD,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7D,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,mBAAmB,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,iBAAiB,KAAK,IAAI,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC"}
1
+ {"version":3,"file":"usePenthera.types.d.ts","sourceRoot":"","sources":["../../../../src/hooks/usePenthera/usePenthera.types.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,oBAAY,aAAa;IACvB,gBAAgB,qBAAqB;IACrC,qBAAqB,0BAA0B;IAC/C,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;IACvC,mBAAmB,wBAAwB;IAC3C,6BAA6B,kCAAkC;IAC/D,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;IACjC,mBAAmB,wBAAwB;CAC5C;AACD,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAC7B,KAAK,QAAQ,GAAG,MAAM,CAAC;AAEvB,MAAM,MAAM,aAAa,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC;IACzC,cAAc,EAAE,aAAa,GAAG,EAAE,CAAC;IACnC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,WAAW,KAAK,IAAI,CAAC;IACrD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC/C,oBAAoB,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7D,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,cAAc,KAAK,IAAI,CAAC;IACzD,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7D,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,mBAAmB,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,iBAAiB,KAAK,IAAI,CAAC;CACtE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takeoffmedia/react-native-penthera",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "test",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -18,11 +18,20 @@ export type AssetProgress = {
18
18
  [key: string]: Progress;
19
19
  };
20
20
 
21
+ export type Subtitle = {
22
+ url: string;
23
+ label: string;
24
+ language: string;
25
+ };
26
+
21
27
  export interface InterfaceDataPlay {
22
28
  url?: string;
23
29
  license?: string;
24
30
  certificate?: string;
25
31
  id?: string;
32
+ subtitles?: Subtitle[];
33
+ js?: string;
34
+ css?: string;
26
35
  }
27
36
 
28
37
  export type PentheraState = {