@takeoffmedia/react-native-penthera 0.1.13 → 0.2.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 (67) hide show
  1. package/ios/Catalog.swift +2 -0
  2. package/ios/Penthera copy.swift +501 -0
  3. package/ios/Penthera.m +0 -4
  4. package/ios/Penthera.swift +6 -7
  5. package/ios/Penthera.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  6. package/ios/Penthera.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  7. package/ios/Penthera.xcodeproj/project.xcworkspace/xcuserdata/joseguerreroot.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  8. package/ios/Penthera.xcodeproj/xcuserdata/joseguerreroot.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +104 -0
  9. package/ios/Penthera.xcodeproj/xcuserdata/joseguerreroot.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  10. package/lib/commonjs/hooks/usePenthera/index.js +28 -0
  11. package/lib/commonjs/hooks/usePenthera/index.js.map +1 -0
  12. package/lib/commonjs/hooks/usePenthera/usePenthera.js +184 -0
  13. package/lib/commonjs/hooks/usePenthera/usePenthera.js.map +1 -0
  14. package/lib/commonjs/{utils/Penthera.js → hooks/usePenthera/usePenthera.types.js} +1 -1
  15. package/lib/commonjs/hooks/usePenthera/usePenthera.types.js.map +1 -0
  16. package/lib/commonjs/index.js +11 -19
  17. package/lib/commonjs/index.js.map +1 -1
  18. package/lib/commonjs/nativeModules/index.js +7 -2
  19. package/lib/commonjs/nativeModules/index.js.map +1 -1
  20. package/lib/module/hooks/usePenthera/index.js +3 -0
  21. package/lib/module/hooks/usePenthera/index.js.map +1 -0
  22. package/lib/module/hooks/usePenthera/usePenthera.js +176 -0
  23. package/lib/module/hooks/usePenthera/usePenthera.js.map +1 -0
  24. package/lib/module/{utils/Penthera.js → hooks/usePenthera/usePenthera.types.js} +1 -1
  25. package/lib/module/hooks/usePenthera/usePenthera.types.js.map +1 -0
  26. package/lib/module/index.js +1 -3
  27. package/lib/module/index.js.map +1 -1
  28. package/lib/module/nativeModules/index.js +7 -2
  29. package/lib/module/nativeModules/index.js.map +1 -1
  30. package/lib/typescript/hooks/usePenthera/index.d.ts +3 -0
  31. package/lib/typescript/hooks/usePenthera/index.d.ts.map +1 -0
  32. package/lib/typescript/hooks/usePenthera/usePenthera.d.ts +4 -0
  33. package/lib/typescript/hooks/usePenthera/usePenthera.d.ts.map +1 -0
  34. package/lib/typescript/hooks/usePenthera/usePenthera.types.d.ts +44 -0
  35. package/lib/typescript/hooks/usePenthera/usePenthera.types.d.ts.map +1 -0
  36. package/lib/typescript/index.d.ts +1 -2
  37. package/lib/typescript/index.d.ts.map +1 -1
  38. package/lib/typescript/interface/PentheraTypes.d.ts +6 -0
  39. package/lib/typescript/interface/PentheraTypes.d.ts.map +1 -1
  40. package/lib/typescript/nativeModules/index.d.ts +1 -1
  41. package/lib/typescript/nativeModules/index.d.ts.map +1 -1
  42. package/package.json +4 -1
  43. package/src/hooks/usePenthera/index.ts +2 -0
  44. package/src/hooks/usePenthera/usePenthera.tsx +209 -0
  45. package/src/hooks/usePenthera/usePenthera.types.ts +46 -0
  46. package/src/index.tsx +1 -3
  47. package/src/interface/PentheraTypes.ts +7 -0
  48. package/src/nativeModules/index.ts +16 -9
  49. package/lib/commonjs/hooks/index.js +0 -13
  50. package/lib/commonjs/hooks/index.js.map +0 -1
  51. package/lib/commonjs/hooks/usePenthera.js +0 -147
  52. package/lib/commonjs/hooks/usePenthera.js.map +0 -1
  53. package/lib/commonjs/utils/Penthera.js.map +0 -1
  54. package/lib/module/hooks/index.js +0 -2
  55. package/lib/module/hooks/index.js.map +0 -1
  56. package/lib/module/hooks/usePenthera.js +0 -141
  57. package/lib/module/hooks/usePenthera.js.map +0 -1
  58. package/lib/module/utils/Penthera.js.map +0 -1
  59. package/lib/typescript/hooks/index.d.ts +0 -2
  60. package/lib/typescript/hooks/index.d.ts.map +0 -1
  61. package/lib/typescript/hooks/usePenthera.d.ts +0 -21
  62. package/lib/typescript/hooks/usePenthera.d.ts.map +0 -1
  63. package/lib/typescript/utils/Penthera.d.ts +0 -12
  64. package/lib/typescript/utils/Penthera.d.ts.map +0 -1
  65. package/src/hooks/index.ts +0 -1
  66. package/src/hooks/usePenthera.ts +0 -156
  67. package/src/utils/Penthera.ts +0 -11
package/ios/Catalog.swift CHANGED
@@ -20,6 +20,7 @@ struct OfflineCatalog: Codable {
20
20
  var licenseUrl: String = ""
21
21
  var isCompleted: Bool
22
22
  var isPaused: Bool
23
+ var percentage: Float?
23
24
  }
24
25
 
25
26
  struct Thumbnails: Codable {
@@ -58,6 +59,7 @@ struct DataItem: Codable {
58
59
  var isExpired: Bool?
59
60
  var inForcedExpire: Bool?
60
61
  var effectiveExpiryDate: String?
62
+
61
63
  }
62
64
 
63
65
  struct Offers: Codable {
@@ -0,0 +1,501 @@
1
+ import VirtuosoClientDownloadEngine
2
+
3
+ @objc(Penthera)
4
+ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
5
+ var downloadEngineNotifications: VirtuosoDownloadEngineNotificationManager!
6
+
7
+ public override init() {
8
+ super.init()
9
+ EventEmitter.sharedInstance.registerEventEmitter(eventEmitter: self)
10
+ }
11
+
12
+ var statusDownload: StatusDownload = StatusDownload()
13
+
14
+ @objc(initializeSdk:withBackplaneUrl:withPublicKey:withPrivateKey:withResolver:withRejecter:)
15
+ func initializeSdk(user: String, backplaneUrl: String, publicKey: String, privateKey: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
16
+ guard let engineConfig = VirtuosoEngineConfig(
17
+ user: user,
18
+ backplaneUrl: backplaneUrl,
19
+ publicKey: publicKey,
20
+ privateKey: privateKey) else {
21
+ return reject("Penthera", "engine Config", nil)
22
+ }
23
+ self.downloadEngineNotifications = VirtuosoDownloadEngineNotificationManager.init(delegate: self)
24
+ let virtuoso = VirtuosoDownloadEngine.instance()
25
+ virtuoso.startup(engineConfig) { status in
26
+ switch(status) {
27
+ case .vde_EngineStartupSuccess:
28
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: "Virtuoso Success", assetId: "test", body: "asset")
29
+ resolve("Success")
30
+ case .vde_EngineStartupAlreadyStarted:
31
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Aready Started")
32
+ resolve("Already Started")
33
+ case .vde_EngineStartupSuccessNoBackplane:
34
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Backplane")
35
+ resolve("No Backplane")
36
+ case .vde_EngineStartupInvalidOptions:
37
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Invalid")
38
+ resolve("Invalid Option")
39
+ case .vde_EngineStartupMethodIsDeprecated:
40
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Method Decraped")
41
+ resolve("Decraped")
42
+ case .vde_EngineStartupInternalException:
43
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Internal Exception")
44
+ resolve("Internal Exception")
45
+ case .vde_EngineDataMigrationError:
46
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Migrate Error")
47
+ resolve("Error")
48
+ @unknown default:
49
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", body: "Virtuoso Default")
50
+ resolve("Error Default")
51
+ }
52
+ }
53
+ }
54
+
55
+ func timeIntervalToString(_ timeInterval: TimeInterval?) -> String {
56
+ let formatter = DateComponentsFormatter()
57
+ formatter.allowedUnits = [.hour, .minute, .second]
58
+ formatter.unitsStyle = .positional
59
+ formatter.zeroFormattingBehavior = .pad
60
+ guard let interval = timeInterval else {
61
+ return "00:00:00"
62
+ }
63
+ return formatter.string(from: interval) ?? "00:00:00"
64
+ }
65
+
66
+ func dateToString (_ date: Date?) -> String? {
67
+ let dateFormatter = DateFormatter()
68
+ dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
69
+ return date != nil ? dateFormatter.string(from: date!) : nil
70
+ }
71
+
72
+
73
+ @objc(getDownloads:withResolver:withRejecter:)
74
+ func getDownloads(blank: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
75
+ let completedAssets = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
76
+ let pendingAssets = VirtuosoAsset.pendingAssets(withAvailabilityFilter: false)
77
+ var offlineCatalogs: [OfflineCatalog] = []
78
+
79
+ for case let va as VirtuosoAsset in completedAssets {
80
+ let thumbnail = va.findAllAncillaries(withTag: "thumbnail").first
81
+ let show = va.findAllAncillaries(withTag: "show").first
82
+ let thumbnails = Thumbnails(
83
+ thumbnail: thumbnail?.fileDownloadURL ?? "",
84
+ show: show?.fileDownloadURL ?? ""
85
+ )
86
+
87
+ let expiryDate = va.expiryDate // Assuming this is a valid Date object
88
+ let effectiveExpiryDate = va.effectiveExpiryDate // Assuming this is a valid Date object
89
+
90
+ let dataItem = DataItem(
91
+ title: va.userInfo?["title"] as? String,
92
+ seasonId: va.userInfo?["seasonId"] as? String,
93
+ seasonTitle: va.userInfo?["seasonTitle"] as? String,
94
+ duration: va.duration,
95
+ estimatedSize: Int(va.estimatedSize),
96
+ dataOffers: parseDataOffer(offer: va.userInfo?["dataOffers"] as Any),
97
+ expiryDate: dateToString(expiryDate),
98
+ expiryAfterPlay: timeIntervalToString(va.expiryAfterPlay),
99
+ expiryAfterDownload: timeIntervalToString(va.expiryAfterDownload),
100
+ isExpired: va.isExpired,
101
+ inForcedExpire: va.inForcedExpire,
102
+ effectiveExpiryDate: dateToString(effectiveExpiryDate!)
103
+ )
104
+ let catalog = OfflineCatalog(
105
+ id: va.assetID,
106
+ title: va.description,
107
+ data: dataItem,
108
+ thumbnails: thumbnails,
109
+ isCompleted: va.isPlayable,
110
+ isPaused: va.isPaused,
111
+ percentage: Float(va.fractionComplete) / Float(va.estimatedSize)
112
+ )
113
+ offlineCatalogs.append(catalog)
114
+ }
115
+
116
+ for case let va as VirtuosoAsset in pendingAssets {
117
+
118
+ let thumbnail = va.findAllAncillaries(withTag: "thumbnail").first
119
+ let show = va.findAllAncillaries(withTag: "show").first
120
+ let thumbnails = Thumbnails(
121
+ thumbnail: thumbnail?.fileDownloadURL ?? "",
122
+ show: show?.fileDownloadURL ?? ""
123
+ )
124
+
125
+ let expiryDate = va.expiryDate // Assuming this is a valid Date object
126
+ let effectiveExpiryDate = va.effectiveExpiryDate // Assuming this is a valid Date object
127
+ let dataItem = DataItem(
128
+ title: va.userInfo?["title"] as? String,
129
+ seasonId: va.userInfo?["seasonId"] as? String,
130
+ seasonTitle: va.userInfo?["seasonTitle"] as? String,
131
+ duration: va.duration,
132
+ estimatedSize: Int(va.estimatedSize),
133
+ dataOffers: parseDataOffer(offer: va.userInfo?["dataOffers"] as Any),
134
+ expiryAfterPlay: timeIntervalToString(va.expiryAfterPlay),
135
+ expiryAfterDownload: timeIntervalToString(va.expiryAfterDownload),
136
+ isExpired: va.isExpired
137
+ )
138
+
139
+ let catalog = OfflineCatalog(
140
+ id: va.assetID,
141
+ title: va.description,
142
+ data: dataItem,
143
+ thumbnails: thumbnails,
144
+ isCompleted: false,
145
+ isPaused: va.isPaused,
146
+ percentage: Float(va.fractionComplete) / Float(va.estimatedSize)
147
+ )
148
+ offlineCatalogs.append(catalog)
149
+ }
150
+
151
+ let decoder = JSONEncoder()
152
+ do {
153
+ let data = try decoder.encode(offlineCatalogs)
154
+ let json = String(data: data, encoding: .utf8)!
155
+ resolve(json)
156
+ } catch {
157
+ reject("penthere", error.localizedDescription, error)
158
+ }
159
+ //resolve(downloadComplete.map{ ($0 as? VirtuosoAsset)?.assetID })
160
+ }
161
+
162
+ func getDownloadedAsset(assetID: String) -> VirtuosoAsset? {
163
+ // assets that have finished downloading
164
+ let completedAssets = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
165
+ guard let asset = completedAssets.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
166
+ return nil
167
+ }
168
+ return asset
169
+ }
170
+
171
+ public func downloadEngineDidStartDownloadingAsset(_ asset: VirtuosoAsset) {
172
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.DID_START_DOWNLOADING, assetId: asset.assetID, body: "")
173
+ }
174
+
175
+ public func downloadEngineProgressUpdated(for asset: VirtuosoAsset) {
176
+ let percentage: Float = Float(asset.fractionComplete)/Float(asset.estimatedSize)
177
+ if(percentage.isFinite) {
178
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.PROGRESS_UPDATED, assetId: asset.assetID, body: "\(Int(asset.fractionComplete*100))")
179
+ }
180
+ }
181
+
182
+ public func downloadEngineProgressUpdatedProcessing(for asset: VirtuosoAsset) {
183
+
184
+ }
185
+
186
+ public func downloadEngineDidFinishDownloadingAsset(_ asset: VirtuosoAsset) {
187
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.DOWNLOAD_COMPLETE, assetId: asset.assetID, body: "")
188
+ }
189
+
190
+ public func downloadEngineDidEncounterError(for asset: VirtuosoAsset, error: Error?, task: URLSessionTask?, data: Data?, statusCode: NSNumber?) {
191
+ asset.delete()
192
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ERROR_DOWNLOAD, assetId: asset.assetID, body: error.debugDescription ?? "Error downloading")
193
+ /*EventEmitter.sharedInstance.dispatch(name: "penthera", body: "\(asset.assetID): Engine did encounter error \(error?.localizedDescription ?? "-")")*/
194
+ }
195
+
196
+ public func downloadEngineInternalQueueUpdate(asset: VirtuosoAsset) {
197
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineInternalQueueUpdate", body: "Queue updated", assetId: asset.assetID)
198
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineInternalQueueUpdate", assetId: asset.assetID, body: "Queue updated")
199
+ }
200
+
201
+ public func downloadEngineStartupComplete(_ succeeded: Bool, asset: VirtuosoAsset) {
202
+ //EventEmitter.sharedInstance.dispatch(name: "penthera", code: "Test downloadEngineStartupComplete", body: "SDK startup complete", assetId: asset.assetID)
203
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: "TEST downloadEngineStartupComplete", assetId: asset.assetID, body: "SDK startup complete")
204
+ }
205
+ func getPendingAsset(assetID: String) -> VirtuosoAsset? {
206
+ let pendingAssets = VirtuosoAsset.pendingAssets(withAvailabilityFilter: false)
207
+ guard let asset = pendingAssets.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
208
+ return nil
209
+ }
210
+ return asset
211
+ }
212
+ func getAncillaryFiles(files: [String: AnyObject]) -> [VirtuosoAncillaryFile] {
213
+ var ancillaryFiles: [VirtuosoAncillaryFile] = []
214
+ files.forEach { file in
215
+ guard let url = file.value as? String else {
216
+ return
217
+ }
218
+ guard let ancillaryFile = VirtuosoAncillaryFile(downloadUrl: url, andTag: file.key) else {
219
+ return
220
+ }
221
+ ancillaryFiles.append(ancillaryFile)
222
+ }
223
+ return ancillaryFiles
224
+ }
225
+
226
+ @objc(download:withResolver:withRejecter:)
227
+ func download(catalogString: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
228
+ let virtuoso = VirtuosoDownloadEngine.instance()
229
+ var queue = virtuoso.assetsInQueue()
230
+
231
+ //let decoder = JSONDecoder()
232
+
233
+ do {
234
+
235
+
236
+ let data = catalogString.getDictionary()
237
+
238
+ guard let item = data!["item"] as! [String: AnyObject]? else {
239
+ reject("No item", nil, nil)
240
+ return
241
+ }
242
+ guard let url = data!["url"] as? String else {
243
+ reject("No url", nil, nil)
244
+ return
245
+ }
246
+
247
+ let assetID = item["id"] as! String? ?? ""
248
+ let hasDRM = item["drm"] as! Bool? ?? false
249
+ let title = item["title"] as! String? ?? ""
250
+
251
+ let downloadAsset = getDownloadedAsset(assetID: assetID)
252
+ let pendingAsset = getPendingAsset(assetID: assetID)
253
+
254
+ if (pendingAsset != nil) {
255
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.PENDING_ASSET_FOUND, assetId: assetID, body: "")
256
+ pendingAsset?.delete()
257
+ return
258
+ }
259
+
260
+ if(downloadAsset == nil && pendingAsset == nil) {
261
+ DispatchQueue.global(qos: .background).async {
262
+ guard let config = VirtuosoAssetConfig(url: url,
263
+ assetID: assetID,
264
+ description: String(describing: title),
265
+ type: .vde_AssetTypeHLS) else {
266
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.CONFIG_ASSET_FAILED, assetId: assetID, body: "-")
267
+ return
268
+ }
269
+ // Ancillary Files
270
+ let thumbnails = item["thumbnails"] as! [String: AnyObject]? ?? [:]
271
+ let subtitles = item["subtitles"] as! [String: AnyObject]? ?? [:]
272
+ config.ancillaries = self.getAncillaryFiles(files: thumbnails) + self.getAncillaryFiles(files: subtitles)
273
+
274
+
275
+ //DRM
276
+ if(hasDRM) {
277
+
278
+ guard let drm = data!["drm"] as! [String: AnyObject]? else {
279
+ reject("No drm", nil, nil)
280
+ return
281
+ }
282
+
283
+ let token = drm["token"] as! String? ?? ""
284
+ let licenceHttpHeader = drm["licence_server_http_header"] as! String? ?? ""
285
+ let licence = drm["licence_server"] as! String? ?? ""
286
+ let cert = drm["fairplay_cert"] as! String? ?? ""
287
+
288
+ guard let drmSetup = FairPlayDrmSetup(assetID: assetID, certificateUrl: cert, licenceUrl: licence, header: licenceHttpHeader, token: token) else {
289
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
290
+ return
291
+ }
292
+
293
+ if !drmSetup.configure() {
294
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.FAIR_PLAY_LICENSE_DELEGATE_ERROR, assetId: "", body: "")
295
+ return
296
+ }
297
+ config.protectionType = .vde_AssetProtectionTypeFairPlay
298
+
299
+ }
300
+
301
+ let asset = VirtuosoAsset.init(config: config)
302
+
303
+ let data = item["data"] as! [String: AnyObject]? ?? [:]
304
+
305
+ asset?.userInfo = data
306
+
307
+ config.ancillaries?.forEach{ file in
308
+ asset?.add(file)
309
+ }
310
+
311
+
312
+ //asset?.add(subtitle!)
313
+
314
+ //let calendar = Calendar.current
315
+ //guard let expiryDate = calendar.date(byAdding: .minute, value: 1, to: Date()) else {
316
+ // return
317
+ //}
318
+
319
+ //asset?.expiryAfterDownload = expiryDate.timeIntervalSinceNow
320
+
321
+ queue.append(asset!)
322
+ resolve(assetID)
323
+ //resolve(queue.count)
324
+ }
325
+ }
326
+
327
+ } catch {
328
+ reject("penthera", error.localizedDescription, error)
329
+ }
330
+ }
331
+
332
+ @objc(delete:withResolver:withRejecter:)
333
+ func delete(assetID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
334
+ //DispatchQueue.global(qos: .background).async {
335
+
336
+ let downloadComplete = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
337
+ if(downloadComplete.count > 0) {
338
+ for case let va as VirtuosoAsset in downloadComplete {
339
+ if(va.assetID == assetID){
340
+ va.delete()
341
+ }
342
+ }
343
+ //(downloadComplete.first as! VirtuosoAsset).delete()
344
+ }
345
+ resolve("Delete complete")
346
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
347
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ASSET_DELETED, assetId: assetID, body: "")
348
+ }
349
+ }
350
+
351
+
352
+
353
+ @objc(deleteMany:withResolver:withRejecter:)
354
+ func deleteMany(assetIDS: [String], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
355
+ // initialize assetResponse {}. Ex {"123":false, "543":false}
356
+ var assetsResponse: [String: Bool] = Dictionary(uniqueKeysWithValues: assetIDS.map { ($0, false) })
357
+
358
+ let downloadComplete = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
359
+ if(downloadComplete.count > 0) {
360
+ var assetsToDelete: [VirtuosoAsset] = []
361
+ for asset in downloadComplete {
362
+ if let va = asset as? VirtuosoAsset, assetIDS.contains(va.assetID) {
363
+ assetsToDelete.append(va)
364
+ assetsResponse[va.assetID] = true
365
+ if assetsToDelete.count == assetIDS.count { // Se encontraron todos los assets, break for.
366
+ break
367
+ }
368
+ }
369
+ }
370
+
371
+
372
+ VirtuosoAsset.delete(assetsToDelete) { () in
373
+ resolve(assetsResponse)
374
+ }
375
+ } else {
376
+ // No hay assets completados para eliminar
377
+ let errorMessage = "deleteMany: completedAssets is empty"
378
+ let userInfo = [NSLocalizedDescriptionKey: errorMessage]
379
+ let error = NSError(domain: "takeoffmedia-react-native-penthera", code: 0, userInfo: userInfo)
380
+ reject("ASSET_DELETE_ERROR", errorMessage, error)
381
+ }
382
+ }
383
+
384
+
385
+
386
+ @objc open override func supportedEvents() -> [String] {
387
+ return EventEmitter.sharedInstance.allEvents
388
+ }
389
+
390
+ @objc(playAsset:withResolver:withRejecter:)
391
+ func playAsset(assetID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
392
+
393
+ let downloadComplete = VirtuosoAsset.completedAssets(withAvailabilityFilter: false)
394
+ guard let asset = downloadComplete.filter({ ($0 as! VirtuosoAsset).assetID == assetID }).first as? VirtuosoAsset else {
395
+ reject("Error streaming asset", "", nil)
396
+ return
397
+ }
398
+
399
+ let decoder = JSONEncoder()
400
+
401
+ do {
402
+
403
+
404
+ // let subtitle = vcHttpServer?.ancillaryURLForAncillary(withTag: "subtitle", usingMime: "text/vtt")
405
+ // let thumbnailOffline = asset.findAllAncillaries(withTag: "thumbnailOffline").first
406
+ //let wallpaper = asset.findAllAncillaries(withTag: "wallpaper").first
407
+
408
+ let vcHttpServer = VirtuosoClientHTTPServer(asset: asset)
409
+
410
+ let licenseURL = vcHttpServer?.fairPlayLicenseServerURL
411
+ let certificateURL = vcHttpServer?.fairPlayCertificateDataURL(forSubType: nil)
412
+
413
+ //let avContentKeySession = VirtuosoLicenseManager.registeredAVContentKeySession()
414
+
415
+ //let userInfoData = try encoder.encode(asset.userInfo)
416
+ //let userInfo = String(data: userInfoData, encoding: .utf8)
417
+
418
+ let assetData = [
419
+ "id": asset.assetID,
420
+ "url": vcHttpServer?.playbackURL ?? "",
421
+ "certificate": certificateURL ,
422
+ "license": licenseURL
423
+ ]
424
+
425
+ let data = try decoder.encode(assetData)
426
+ let json = String(data: data, encoding: .utf8)!
427
+ resolve(json)
428
+
429
+ // let config = PlayerConfig()
430
+ // config.styleConfig.userInterfaceType = .system
431
+ // config.key = "ASSSSSS"
432
+
433
+ // let player = PlayerFactory.create(playerConfig: config)
434
+
435
+ // guard let streamUrl = URL(string: vcHttpServer!.playbackURL) else {
436
+ // return
437
+ // }
438
+
439
+ // // Create a SourceConfig
440
+ // let sourceConfig = SourceConfig(url: streamUrl, type: .hls)
441
+ // print(streamUrl.absoluteString)
442
+
443
+ // // Optionally set additional properties
444
+ // sourceConfig.title = "Art of motion"
445
+
446
+ // DispatchQueue.main.async {
447
+ // let source = SourceFactory.create(from: sourceConfig)
448
+
449
+ // player.load(source: source)
450
+
451
+
452
+ // let viewController = UIApplication.shared.windows.first?.rootViewController as? UIViewController
453
+
454
+ // let playerView = PlayerView(player: player, frame: (viewController?.view.bounds)!)
455
+
456
+ // // Adding the view to the a container View
457
+ // viewController?.view.addSubview(playerView)
458
+ // viewController?.view.bringSubviewToFront(playerView)
459
+ // }
460
+
461
+
462
+ /*
463
+ let demoPlayer = DemoPlayerViewController()
464
+ DispatchQueue.main.async {
465
+ asset.play(using: .vde_AssetPlaybackTypeLocal,
466
+ andPlayer: demoPlayer as VirtuosoPlayer,
467
+ onSuccess: {
468
+ // Present the player
469
+
470
+ let viewController = UIApplication.shared.windows.first?.rootViewController as? UIViewController
471
+ viewController?.present(demoPlayer, animated: true)
472
+ //self.present(demoPlayer, animated: true, completion: nil)
473
+ },
474
+ onFail: {
475
+ //self.error = nil
476
+ })
477
+ }*/
478
+
479
+ } catch {
480
+ reject("penthere", error.localizedDescription, error)
481
+ }
482
+ }
483
+
484
+
485
+ @objc(pauseDownload:withResolver:withRejecter:)
486
+ func pauseDownload(assetID: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
487
+ let pendingAsset = getPendingAsset(assetID: assetID)
488
+ if (pendingAsset != nil) {
489
+ self.pauseAsset(asset: pendingAsset!)
490
+ return
491
+ }
492
+
493
+ }
494
+
495
+ func pauseAsset(asset: VirtuosoAsset) {
496
+ asset.isPaused = !asset.isPaused
497
+ EventEmitter.sharedInstance.dispatch(name: "penthera", code: PentheraEvent.ASSET_RESUME_DOWNLOAD_UPDATED, assetId: asset.assetID, body: "\(asset.isPaused)")
498
+ }
499
+
500
+
501
+ }
package/ios/Penthera.m CHANGED
@@ -4,10 +4,6 @@
4
4
 
5
5
  @interface RCT_EXTERN_MODULE(Penthera, RCTEventEmitter)
6
6
 
7
- RCT_EXTERN_METHOD(multiply:(float)a withB:(float)b
8
- withResolver:(RCTPromiseResolveBlock)resolve
9
- withRejecter:(RCTPromiseRejectBlock)reject)
10
-
11
7
  RCT_EXTERN_METHOD(initializeSdk:(NSString*)user
12
8
  withBackplaneUrl:(NSString*)backplaneUrl
13
9
  withPublicKey:(NSString*)publicKey
@@ -11,11 +11,6 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
11
11
 
12
12
  var statusDownload: StatusDownload = StatusDownload()
13
13
 
14
- @objc(multiply:withB:withResolver:withRejecter:)
15
- func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
16
- resolve(a*b)
17
- }
18
-
19
14
  @objc(initializeSdk:withBackplaneUrl:withPublicKey:withPrivateKey:withResolver:withRejecter:)
20
15
  func initializeSdk(user: String, backplaneUrl: String, publicKey: String, privateKey: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
21
16
  guard let engineConfig = VirtuosoEngineConfig(
@@ -91,6 +86,7 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
91
86
 
92
87
  let expiryDate = va.expiryDate // Assuming this is a valid Date object
93
88
  let effectiveExpiryDate = va.effectiveExpiryDate // Assuming this is a valid Date object
89
+
94
90
  let dataItem = DataItem(
95
91
  title: va.userInfo?["title"] as? String,
96
92
  seasonId: va.userInfo?["seasonId"] as? String,
@@ -111,7 +107,9 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
111
107
  data: dataItem,
112
108
  thumbnails: thumbnails,
113
109
  isCompleted: va.isPlayable,
114
- isPaused: va.isPaused)
110
+ isPaused: va.isPaused,
111
+ percentage: Float(va.fractionComplete) / Float(va.estimatedSize)
112
+ )
115
113
  offlineCatalogs.append(catalog)
116
114
  }
117
115
 
@@ -144,7 +142,8 @@ class Penthera: RCTEventEmitter, VirtuosoDownloadEngineNotificationsDelegate {
144
142
  data: dataItem,
145
143
  thumbnails: thumbnails,
146
144
  isCompleted: false,
147
- isPaused: va.isPaused
145
+ isPaused: va.isPaused,
146
+ percentage: Float(va.fractionComplete) / Float(va.estimatedSize)
148
147
  )
149
148
  offlineCatalogs.append(catalog)
150
149
  }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "self:">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>