From c599b631d879440f6fa64fc0c0634143b75a6217 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 2 Feb 2026 14:48:13 +0100 Subject: [PATCH 1/4] Extract contentProtection for endpoints on THEOlive event adapter --- ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift index 65428d3e5..6d1c36613 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift @@ -43,9 +43,9 @@ class THEOplayerRCTTHEOliveEventAdapter { if let adSrc = endpoint.adSrc { endpointData[PROP_ENDPOINT_AD_SRC] = adSrc } - //if let contentProtection = endpoint.contentProtection { - // TODO: not yet available on native iOS SDK. - //} + if let contentProtection = endpoint.channelContentProtection { + endpointData[PROP_ENDPOINT_CONTENT_PROTECTION] = contentProtection.toJSONEncodableDictionary() + } endpointData[PROP_ENDPOINT_WEIGHT] = endpoint.weight endpointData[PROP_ENDPOINT_PRIORITY] = endpoint.priority return endpointData From 3b2081f05821b3e965e9edca28f936ac9b016057 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 2 Feb 2026 14:49:19 +0100 Subject: [PATCH 2/4] Bump minimal iOS SDK version to support public contentProtection on endpoint --- react-native-theoplayer.podspec | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/react-native-theoplayer.podspec b/react-native-theoplayer.podspec index 2177e3664..aa2d987bd 100644 --- a/react-native-theoplayer.podspec +++ b/react-native-theoplayer.podspec @@ -43,37 +43,37 @@ Pod::Spec.new do |s| # THEOplayer Dependency puts "Adding THEOplayerSDK-core" - s.dependency "THEOplayerSDK-core", "~> 10.7" + s.dependency "THEOplayerSDK-core", "~> 10.10" # THEOlive Dependency puts "Adding THEOplayer-Integration-THEOlive" - s.dependency "THEOplayer-Integration-THEOlive", "~> 10.7" + s.dependency "THEOplayer-Integration-THEOlive", "~> 10.10" # Feature based integration dependencies if theofeatures.include?("GOOGLE_IMA") puts "Adding THEOplayer-Integration-GoogleIMA" - s.dependency "THEOplayer-Integration-GoogleIMA", "~> 10.7" + s.dependency "THEOplayer-Integration-GoogleIMA", "~> 10.10" end if theofeatures.include?("CHROMECAST") puts "Adding THEOplayer-Integration-GoogleCast" - s.ios.dependency "THEOplayer-Integration-GoogleCast", "~> 10.7" + s.ios.dependency "THEOplayer-Integration-GoogleCast", "~> 10.10" end if theofeatures.include?("THEO_ADS") puts "Adding THEOplayer-Integration-THEOads" - s.dependency "THEOplayer-Integration-THEOads", "~> 10.7" + s.dependency "THEOplayer-Integration-THEOads", "~> 10.10" end if theofeatures.include?("MILLICAST") puts "Adding THEOplayer-Integration-Millicast" - s.dependency "THEOplayer-Integration-Millicast", "~> 10.7" + s.dependency "THEOplayer-Integration-Millicast", "~> 10.10" end # Feature based connector dependencies if theofeatures.include?("SIDELOADED_TEXTTRACKS") puts "Adding THEOplayer-Connector-SideloadedSubtitle" - s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 10.7" + s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 10.10" end end From 142a0781f45cdc643c882553c79097012c56f33a Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 2 Feb 2026 14:50:35 +0100 Subject: [PATCH 3/4] Add changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 375cbd019..7f0b3fe66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fixed an issue on iOS where the onPlayerStateSync callback was not called from the main thread. +### Added + +- Added contentProtection extraction for THEOlive endpoints on iOS. + ## [10.9.0] - 26-01-29 ### Fixed From 231b0469f84bb2031f2889610293595417da35dc Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Wed, 25 Feb 2026 12:04:14 +0100 Subject: [PATCH 4/4] Extract ContentProtection data from theolive sources --- .../THEOplayerRCTTHEOliveEventAdapter.swift | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift index 6d1c36613..3076ac245 100644 --- a/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift +++ b/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift @@ -18,6 +18,16 @@ let PROP_ENDPOINT_CONTENT_PROTECTION: String = "contentProtection" let PROP_REASON_ERROR_CODE: String = "errorCode" let PROP_REASON_ERROR_MESSAGE: String = "errorMessage" +let PROP_CONTENTPROTECTION_INTEGRATION: String = "integration" +let PROP_CONTENTPROTECTION_FAIRPLAY: String = "fairplay" +let PROP_CONTENTPROTECTION_WIDEVINE: String = "widevine" +let PROP_CONTENTPROTECTION_PLAYREADY: String = "playready" + +let PROP_LICENSE_CONFIG_LICENSE_URL: String = "licenseUrl" + +let PROP_KEY_SYSTEM_CONFIG_LICENSE_URL: String = "licenseUrl" +let PROP_KEY_SYSTEM_CONFIG_CERTIFICATE_URL: String = "certificateUrl" + class THEOplayerRCTTHEOliveEventAdapter { #if canImport(THEOplayerTHEOliveIntegration) @@ -44,13 +54,54 @@ class THEOplayerRCTTHEOliveEventAdapter { endpointData[PROP_ENDPOINT_AD_SRC] = adSrc } if let contentProtection = endpoint.channelContentProtection { - endpointData[PROP_ENDPOINT_CONTENT_PROTECTION] = contentProtection.toJSONEncodableDictionary() + endpointData[PROP_ENDPOINT_CONTENT_PROTECTION] = THEOplayerRCTTHEOliveEventAdapter.fromContentProtection(contentProtection: contentProtection) } endpointData[PROP_ENDPOINT_WEIGHT] = endpoint.weight endpointData[PROP_ENDPOINT_PRIORITY] = endpoint.priority return endpointData } + class func fromContentProtection(contentProtection: (any THEOplayerTHEOliveIntegration.ChannelContentProtection)?) -> [String:Any] { + guard let contentProtection = contentProtection else { + return [:] + } + + var contentProtectionData: [String:Any] = [:] + contentProtectionData[PROP_CONTENTPROTECTION_INTEGRATION] = contentProtection.integration + if let keySystem = contentProtection.fairplay { + contentProtectionData[PROP_CONTENTPROTECTION_FAIRPLAY] = THEOplayerRCTTHEOliveEventAdapter.fromKeySystem(keySystem: keySystem) + } + if let licenseConfiguration = contentProtection.widevine { + contentProtectionData[PROP_CONTENTPROTECTION_WIDEVINE] = THEOplayerRCTTHEOliveEventAdapter.fromLicenseConfiguration(licenseConfiguration: licenseConfiguration) + } + if let licenseConfiguration = contentProtection.playready { + contentProtectionData[PROP_CONTENTPROTECTION_PLAYREADY] = THEOplayerRCTTHEOliveEventAdapter.fromLicenseConfiguration(licenseConfiguration: licenseConfiguration) + } + + return contentProtectionData + } + + class func fromKeySystem(keySystem: (any THEOplayerTHEOliveIntegration.KeySystemConfiguration)?) -> [String:Any] { + guard let keySystem = keySystem else { + return [:] + } + + var keySystemData: [String:Any] = [:] + keySystemData[PROP_KEY_SYSTEM_CONFIG_LICENSE_URL] = keySystem.licenseUrl + keySystemData[PROP_KEY_SYSTEM_CONFIG_CERTIFICATE_URL] = keySystem.certificateUrl + return keySystemData + } + + class func fromLicenseConfiguration(licenseConfiguration: (any THEOplayerTHEOliveIntegration.LicenseConfiguration)?) -> [String:Any] { + guard let licenseConfiguration = licenseConfiguration else { + return [:] + } + + var licenseConfigurationData: [String:Any] = [:] + licenseConfigurationData[PROP_LICENSE_CONFIG_LICENSE_URL] = licenseConfiguration.licenseUrl + return licenseConfigurationData + } + class func fromReason(reason: THEOplayerSDK.THEOError?) -> [String:Any] { guard let reason = reason else { return [:]