package com.blaze.rtnblazesdk import android.util.Log import com.blaze.blazesdk.analytics.models.BlazeAnalyticsEvent import com.blaze.blazesdk.delegates.BlazeCastingDelegate import com.blaze.blazesdk.delegates.BlazeCastingState import com.blaze.blazesdk.delegates.BlazePipDelegate import com.blaze.blazesdk.delegates.BlazePipState import com.blaze.blazesdk.delegates.BlazeFollowEntitiesDelegate import com.blaze.blazesdk.delegates.BlazePlayerEntryPointDelegate import com.blaze.blazesdk.delegates.BlazeSDKDelegate import com.blaze.blazesdk.delegates.models.BlazeCTAActionType import com.blaze.blazesdk.delegates.models.BlazeFollowEntityClickedParams import com.blaze.blazesdk.delegates.models.BlazePlaybackModificationRequest import com.blaze.blazesdk.delegates.models.BlazePlaybackModificationResponse import com.blaze.blazesdk.style.shared.models.BlazePlayerCustomActionButtonParams import com.blaze.blazesdk.delegates.models.BlazePlayerEvent import com.blaze.blazesdk.delegates.models.BlazePlayerType import com.blaze.blazesdk.follow.models.BlazeFollowEntity import com.blaze.blazesdk.external_modules.BlazeExternalModulesBinder import com.blaze.blazesdk.features.moments.models.configuration.BlazeMomentsLoopBehavior import com.blaze.blazesdk.features.moments.models.configuration.BlazeMomentsPlaybackConfiguration import com.blaze.blazesdk.features.search.models.BlazeSearchScreenParams import com.blaze.blazesdk.features.shared.models.ui_shared.BlazeLinkActionHandleType import com.blaze.blazesdk.prefetch.models.BlazeCachingLevel import com.blaze.blazesdk.shared.BlazeSDK import com.blaze.blazesdk.shared.models.BlazeEntryPointTriggerSource import com.blaze.blazesdk.shared.results.BlazeResult import com.blaze.rtnblazesdk.events.SdkModuleJsEvent import com.blaze.rtnblazesdk.shared.blazeAsyncBridge import com.blaze.rtnblazesdk.shared.callJSMethod import com.blaze.rtnblazesdk.utils.extractCachingLevel import com.blaze.rtnblazesdk.utils.extractDataSource import com.blaze.rtnblazesdk.utils.extractMomentsPlayerStyle import com.blaze.rtnblazesdk.utils.extractStoriesPlayerStyle import com.blaze.rtnblazesdk.utils.extractMomentsPlaybackConfiguration import com.blaze.rtnblazesdk.utils.extractVideosPlaybackConfiguration import com.blaze.rtnblazesdk.utils.extractVideosPlayerStyle import com.blaze.rtnblazesdk.utils.getBooleanOrNull import com.blaze.rtnblazesdk.utils.handleResult import com.blaze.rtnblazesdk.utils.rejectWith import com.facebook.proguard.annotations.DoNotStrip import com.facebook.react.bridge.NoSuchKeyException import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReadableArray import com.facebook.react.bridge.ReadableMap import javax.annotation.Nonnull class BlazeSdkModule(private val context: ReactApplicationContext): ReactContextBaseJavaModule(context) { @Nonnull override fun getName(): String { return NAME } private val reactNativeSDKHelper = BlazeReactSDKHelper() private var appOverridesCTAHandling: Boolean = false private val globalDelegate = object : BlazeSDKDelegate { override fun onErrorThrown(error: BlazeResult.Error) { val event = SdkModuleJsEvent.ErrorThrown(error) sendJsEvent(event) } override fun onEventTriggered(eventData: BlazeAnalyticsEvent) { val event = SdkModuleJsEvent.AnalyticEventTriggered(eventData) sendJsEvent(event) } override suspend fun playbackModificationHandler(request: BlazePlaybackModificationRequest): BlazePlaybackModificationResponse { val fallbackResponse = request.response() val asyncBridge = context.blazeAsyncBridge ?: return fallbackResponse return try { asyncBridge.callJSMethod( name = PLAYBACK_MODIFICATION_METHOD_NAME, params = request, ) } catch (e: Exception) { Log.d(TAG, "Error playbackModificationHandler: ${e.message}") fallbackResponse } } } private val playerEntryPointDelegate = object : BlazePlayerEntryPointDelegate { override fun onDataLoadComplete( playerType: BlazePlayerType, sourceId: String?, itemsCount: Int, result: BlazeResult ) { val event = SdkModuleJsEvent.DataLoadCompleted(playerType, sourceId, itemsCount, result) sendJsEvent(event) } override fun onDataLoadStarted(playerType: BlazePlayerType, sourceId: String?) { val event = SdkModuleJsEvent.DataLoadStarted(playerType, sourceId) sendJsEvent(event) } override fun onPlayerDidAppear(playerType: BlazePlayerType, sourceId: String?) { val event = SdkModuleJsEvent.PlayerDidAppear(playerType, sourceId) sendJsEvent(event) } override fun onPlayerDidDismiss(playerType: BlazePlayerType, sourceId: String?) { val event = SdkModuleJsEvent.PlayerDidDismiss(playerType, sourceId) sendJsEvent(event) } override fun onTriggerCTA( playerType: BlazePlayerType, sourceId: String?, actionType: BlazeCTAActionType, actionParam: String ): Boolean { val event = SdkModuleJsEvent.TriggerCTA(playerType, sourceId, actionType, actionParam) sendJsEvent(event) return appOverridesCTAHandling } override fun onTriggerPlayerBodyTextLink( playerType: BlazePlayerType, sourceId: String?, actionParam: String ): BlazeLinkActionHandleType { val event = SdkModuleJsEvent.TriggerPlayerBodyTextLink(playerType, sourceId, actionParam) sendJsEvent(event) return BlazeLinkActionHandleType.DEEPLINK } override fun onPlayerEventTriggered( playerType: BlazePlayerType, sourceId: String?, event: BlazePlayerEvent ) { try { val event = SdkModuleJsEvent.TriggerPlayerEventTriggered( playerType = playerType, sourceId = sourceId, event = event ) sendJsEvent(event) } catch (e: Throwable) { Log.e(TAG, "onPlayerEventTriggered: Exception - $e") } } override fun onTriggerCustomActionButton( playerType: BlazePlayerType, sourceId: String?, customParams: BlazePlayerCustomActionButtonParams ) { val event = SdkModuleJsEvent.TriggerCustomActionButton(playerType, sourceId, customParams) sendJsEvent(event) } override fun onReadStatusChanged( playerType: BlazePlayerType, sourceId: String?, dataSourceStringRepresentation: String, isEntireContentRead: Boolean, itemReadStatus: Map ) { val event = SdkModuleJsEvent.ReadStatusChanged(playerType, sourceId, dataSourceStringRepresentation, isEntireContentRead, itemReadStatus) sendJsEvent(event) } } private val followEntitiesDelegate = object : BlazeFollowEntitiesDelegate { override fun onFollowEntityClicked(followEntityParams: BlazeFollowEntityClickedParams) { val event = SdkModuleJsEvent.FollowEntityClicked( playerType = followEntityParams.playerType, sourceId = followEntityParams.sourceId, newFollowingState = followEntityParams.newFollowingState, followEntityId = followEntityParams.followEntity.entityId ) sendJsEvent(event) } } private val castingDelegate = object : BlazeCastingDelegate { override fun onCastingStateChanged( playerType: BlazePlayerType, sourceId: String?, newState: BlazeCastingState ) { val event = SdkModuleJsEvent.CastingStateChanged(playerType, sourceId, newState) sendJsEvent(event) } } private val pipDelegate = object : BlazePipDelegate { override fun onPipStateChanged( playerType: BlazePlayerType, sourceId: String?, newState: BlazePipState ) { val event = SdkModuleJsEvent.PiPStateChanged(playerType, sourceId, newState) sendJsEvent(event) } } init { BlazeExternalModulesBinder.reactNativeSDKHelper = reactNativeSDKHelper } @ReactMethod @DoNotStrip fun init(options: ReadableMap, promise: Promise) { try { setAppOverrideCtaHandling(options) val cachingLevel = options.extractCachingLevel() ?: BlazeCachingLevel.DEFAULT BlazeSdkModuleRepo.cachingLevel = cachingLevel BlazeSDK.init( apiKey = options.getString(KEY_INIT_API_KEY)!!, externalUserId = options.getString(KEY_INIT_EXTERNAL_USER_ID), geoLocation = options.getString(KEY_INIT_GEO_LOCATION), cachingSize = options.getInt(KEY_INIT_CACHING_SIZE), cachingLevel = cachingLevel, completionBlock = { promise.resolve(BlazeResult.Success(true).toString()) }, errorBlock = { e: BlazeResult.Error -> promise.handleResult(e) }, sdkDelegate = globalDelegate, playerEntryPointDelegate = playerEntryPointDelegate, ) BlazeSDK.followEntitiesManager.delegate = followEntitiesDelegate BlazeSDK.castingManager.delegate = castingDelegate BlazeSDK.pipManager.delegate = pipDelegate val reactStoryPlayerStyle = options.getMap(KEY_INIT_DEFAULT_STORY_PLAYER_STYLE) val reactMomentPlayerStyle = options.getMap(KEY_INIT_DEFAULT_MOMENT_PLAYER_STYLE) val reactVideosPlayerStyle = options.getMap(KEY_INIT_DEFAULT_VIDEO_PLAYER_STYLE) reactStoryPlayerStyle.extractStoriesPlayerStyle(context).also { BlazeSDK.setDefaultStoryPlayerStyle(it) } reactMomentPlayerStyle.extractMomentsPlayerStyle(context).also { BlazeSDK.setDefaultMomentsPlayerStyle(it) } reactVideosPlayerStyle.extractVideosPlayerStyle(context).also { BlazeSDK.setDefaultVideosPlayerStyle(it) } } catch (e: Exception) { promise.rejectWith(e.toString()) Log.e(TAG, "init: Exception - $e") } } private fun ReadableMap.extractCachingLevel(): BlazeCachingLevel? { return getString(KEY_INIT_CACHING_LEVEL)?.extractCachingLevel() } private fun setAppOverrideCtaHandling(options: ReadableMap) { // getBoolean can throw exception while getString will return null if no such key try { appOverridesCTAHandling = options.getBoolean(KEY_INIT_APP_OVERRIDES_CTA_HANDLING) } catch(e: NoSuchKeyException) { } } private fun sendJsEvent(event: SdkModuleJsEvent) { context.emitDeviceEvent(event.eventName, event.params) } @ReactMethod @DoNotStrip fun playStory(options: ReadableMap, promise: Promise) { try { val storyId = options.getString(KEY_STORY_OPT_STORY_ID) ?: run { promise.rejectWith("no story id") return } val pageId = options.getString(KEY_STORY_OPT_PAGE_ID) val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractStoriesPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT BlazeSDK.playStory( storyId = storyId, pageId = pageId, storyPlayerStyle = playerStyle, triggerSource = triggerSource ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun playStories(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for playStories") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractStoriesPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT val shouldOrderContentByReadStatus = options.getBooleanOrNull("shouldOrderContentByReadStatus") ?: true BlazeSDK.playStories( dataSource = dataSource, entryContentId = entryContentId, storyPlayerStyle = playerStyle, triggerSource = triggerSource, shouldOrderContentByReadStatus = shouldOrderContentByReadStatus ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun prepareStories(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for prepareStories") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) BlazeSDK.prepareStories(dataSource = dataSource, entryContentId = entryContentId) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun playMoment(options: ReadableMap, promise: Promise) { try { val momentId = options.getString(KEY_MOMENT_OPT_MOMENT_ID) ?: run { promise.rejectWith("no moment id") return } val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractMomentsPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT BlazeSDK.playMoment( momentId = momentId, momentsPlayerStyle = playerStyle, triggerSource = triggerSource ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun playMoments(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for playMoments") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractMomentsPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT val shouldOrderContentByReadStatus = options.getBooleanOrNull("shouldOrderContentByReadStatus") ?: true BlazeSDK.playMoments( dataSource = dataSource, entryContentId = entryContentId, momentsPlayerStyle = playerStyle, triggerSource = triggerSource, shouldOrderContentByReadStatus = shouldOrderContentByReadStatus ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun prepareMoments(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for prepareMoments") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) BlazeSDK.prepareMoments(dataSource = dataSource, entryContentId = entryContentId) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun appendMomentsToPlayer(options: ReadableMap, promise: Promise) { try { val sourceId = options.getString(KEY_ENTRY_POINT_SOURCE_ID) ?: run { promise.rejectWith("Missing sourceId in appendMomentsToPlayer options") return } val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for appendMomentsToPlayer") return } val shouldOrderContentByReadStatus = options.getBooleanOrNull("shouldOrderContentByReadStatus") ?: false BlazeSDK.appendMomentsToPlayer( sourceId = sourceId, dataSourceType = dataSource, shouldOrderContentByReadStatus = shouldOrderContentByReadStatus ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun playVideo(options: ReadableMap, promise: Promise) { try { val videoId = options.getString(KEY_VIDEO_OPT_VIDEO_ID) ?: run { promise.rejectWith("no video id") return } val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractVideosPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT val playbackConfiguration = options.getMap(KEY_ENTRY_POINT_PLAYBACK_CONFIGURATION) .extractVideosPlaybackConfiguration() ?: BlazeSDK.getDefaultVideosPlaybackConfiguration() BlazeSDK.playVideo( videoId = videoId, videosPlayerStyle = playerStyle, triggerSource = triggerSource, playbackConfiguration = playbackConfiguration ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun playVideos(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for playVideos") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) val playerStyle = options.getMap(KEY_ENTRY_POINT_PLAYER_THEME) .extractVideosPlayerStyle(context) val triggerSource = options.getString("triggerSource")?.asEntryPointTriggerSource ?: BlazeEntryPointTriggerSource.ENTRYPOINT val shouldOrderContentByReadStatus = options.getBooleanOrNull("shouldOrderContentByReadStatus") ?: true val playbackConfiguration = options.getMap(KEY_ENTRY_POINT_PLAYBACK_CONFIGURATION) .extractVideosPlaybackConfiguration() ?: BlazeSDK.getDefaultVideosPlaybackConfiguration() BlazeSDK.playVideos( dataSource = dataSource, entryContentId = entryContentId, videosPlayerStyle = playerStyle, triggerSource = triggerSource, shouldOrderContentByReadStatus = shouldOrderContentByReadStatus, playbackConfiguration = playbackConfiguration ) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun prepareVideos(options: ReadableMap, promise: Promise) { try { val dataSource = options.getMap(KEY_ENTRY_POINT_DATA_SOURCE)?.extractDataSource() ?: run { promise.rejectWith("Error parsing data source for prepareVideos") return } val entryContentId = options.getString(KEY_ENTRY_POINT_CONTENT_ID) BlazeSDK.prepareVideos(dataSource = dataSource, entryContentId = entryContentId) { result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun setDefaultVideosPlaybackConfiguration(config: ReadableMap, promise: Promise) { try { val playbackConfig = (config as ReadableMap?).extractVideosPlaybackConfiguration() ?: run { promise.rejectWith("Invalid playback configuration") return } BlazeSDK.setDefaultVideosPlaybackConfiguration(playbackConfig) promise.resolve(null) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun getDefaultVideosPlaybackConfiguration(promise: Promise) { try { val config = BlazeSDK.getDefaultVideosPlaybackConfiguration() val result = Arguments.createMap().apply { putBoolean("multiAspectRatio", config.multiAspectRatio) putBoolean("shouldOpenInLandscape", config.shouldOpenOnLandscape) putMap("pipConfiguration", Arguments.createMap().apply { putBoolean("enterPipOnAppBackground", config.pip.enterPipOnAppBackground) }) } promise.resolve(result) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun setDefaultMomentsPlaybackConfiguration(config: ReadableMap, promise: Promise) { try { val playbackConfig = (config as ReadableMap?).extractMomentsPlaybackConfiguration() ?: run { promise.rejectWith("Invalid moments playback configuration") return } BlazeSDK.setDefaultMomentsPlaybackConfiguration(playbackConfig) promise.resolve(null) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun getDefaultMomentsPlaybackConfiguration(promise: Promise) { try { val config = BlazeSDK.getDefaultMomentsPlaybackConfiguration() val result = Arguments.createMap().apply { val loopBehavior = Arguments.createMap().apply { when (config.loopBehavior) { is BlazeMomentsLoopBehavior.InfiniteLoop -> { putString("type", "infiniteLoop") } is BlazeMomentsLoopBehavior.LoopAndAdvance -> { putString("type", "loopAndAdvance") putInt("numberOfPlays", (config.loopBehavior as BlazeMomentsLoopBehavior.LoopAndAdvance).numberOfPlays) } } } putMap("loopBehavior", loopBehavior) } promise.resolve(result) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun dismissPlayer(promise: Promise) { BlazeSDK.dismissCurrentPlayer() promise.resolve(true) } @DoNotStrip @ReactMethod(isBlockingSynchronousMethod = true) fun isInitialized(): Boolean { return BlazeSDK.isInitialized() } @ReactMethod @DoNotStrip fun setExternalUserId(externalUserId: String?, promise: Promise) { BlazeSDK.setExternalUserId(externalUserId) { result -> promise.handleResult(result) } } @ReactMethod @DoNotStrip fun setDoNotTrack(doNotTrack: Boolean, promise: Promise) { BlazeSDK.setDoNotTrack(doNotTrack) promise.resolve(doNotTrack) } @ReactMethod @DoNotStrip fun setDisableAnalytics(disableAnalytics: Boolean, promise: Promise) { BlazeSDK.disableAnalytics = disableAnalytics promise.resolve(disableAnalytics) } @ReactMethod @DoNotStrip fun handleUniversalLink(link: String, promise: Promise) { try { BlazeSDK.handleUniversalLink(link){ result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun canHandleUniversalLink(link: String, promise: Promise) { try { val canHandle = BlazeSDK.canHandleUniversalLink(link) promise.resolve(canHandle) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun updateGeoRestriction(geoLocation: String?, promise: Promise) { val updatedGeoLocation = if (geoLocation.isNullOrEmpty()) null else geoLocation try { BlazeSDK.updateGeoRestriction(updatedGeoLocation){ result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun canHandlePushNotification(payload: ReadableMap, promise: Promise) { try { // This is needed for now since the Android SDK requires . Remove if it changes. val hashMap = payload.toHashMap() as HashMap val canHandle = BlazeSDK.canHandlePushNotification(hashMap) promise.resolve(canHandle) } catch (e: Exception) { promise.rejectWith("Error parsing the payload: $e") } } @ReactMethod @DoNotStrip fun handleNotificationPayload(payload: ReadableMap, promise: Promise) { try { // This is needed for now since the Android SDK requires . Remove if it changes. val hashMap = payload.toHashMap() as HashMap BlazeSDK.handlePushNotificationPayload(hashMap){ result -> promise.handleResult(result) } } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun setFollowedEntities(entityIds: ReadableArray, promise: Promise) { try { val entities = (0 until entityIds.size()).mapNotNull { entityIds.getString(it)?.let { id -> BlazeFollowEntity(id) } }.toSet() BlazeSDK.followEntitiesManager.setFollowedEntities(entities) promise.resolve(null) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun insertFollowedEntities(entityIds: ReadableArray, promise: Promise) { try { val entities = (0 until entityIds.size()).mapNotNull { entityIds.getString(it)?.let { id -> BlazeFollowEntity(id) } }.toSet() BlazeSDK.followEntitiesManager.insertFollowedEntities(entities) promise.resolve(null) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun removeFollowedEntities(entityIds: ReadableArray, promise: Promise) { try { val entities = (0 until entityIds.size()).mapNotNull { entityIds.getString(it)?.let { id -> BlazeFollowEntity(id) } }.toSet() BlazeSDK.followEntitiesManager.removeFollowedEntities(entities) promise.resolve(null) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun getFollowedEntities(promise: Promise) { try { val entities = BlazeSDK.followEntitiesManager.getFollowedEntities() val ids = Arguments.createArray().apply { entities.forEach { pushString(it.entityId) } } promise.resolve(ids) } catch (e: Exception) { promise.rejectWith(e.toString()) } } @ReactMethod @DoNotStrip fun setPreferredLanguage(language: String?, promise: Promise) { BlazeSDK.setPreferredLanguage(language) promise.resolve(null) } @ReactMethod @DoNotStrip fun showSearchScreen(options: ReadableMap, promise: Promise) { val dataSourceType = options.getMap("suggestionsDataSource")?.extractDataSource() if (dataSourceType == null) { promise.rejectWith("suggestionsDataSource is required on Android") return } val searchParams = BlazeSearchScreenParams(suggestionsDataSource = dataSourceType) BlazeSDK.screens.showSearchScreen(searchParams = searchParams) { result -> promise.handleResult(result) } } @ReactMethod @DoNotStrip fun stopActiveCastingSession(promise: Promise) { BlazeSDK.castingManager.stopActiveCastingSession() promise.resolve(null) } @ReactMethod @DoNotStrip fun stopActivePiPSession(promise: Promise) { BlazeSDK.pipManager.stopActivePiPSession() promise.resolve(null) } @ReactMethod @DoNotStrip fun isPiPActive(promise: Promise) { promise.resolve(BlazeSDK.pipManager.isActive) } companion object { const val NAME = "RTNBlazeSdk" val TAG: String = BlazeSdkModule::class.java.simpleName const val KEY_INIT_API_KEY = "apiKey" const val KEY_INIT_EXTERNAL_USER_ID = "externalUserId" const val KEY_INIT_GEO_LOCATION = "geoLocation" const val KEY_INIT_CACHING_SIZE = "cachingSize" const val KEY_INIT_CACHING_LEVEL = "cachingLevel" const val KEY_INIT_APP_OVERRIDES_CTA_HANDLING = "appOverridesCTAHandling" const val KEY_INIT_DEFAULT_STORY_PLAYER_STYLE = "defaultStoryPlayerStyle" const val KEY_INIT_DEFAULT_MOMENT_PLAYER_STYLE = "defaultMomentsPlayerStyle" const val KEY_INIT_DEFAULT_VIDEO_PLAYER_STYLE = "defaultVideosPlayerStyle" const val KEY_STORY_OPT_STORY_ID = "storyId" const val KEY_STORY_OPT_PAGE_ID = "pageId" const val KEY_MOMENT_OPT_MOMENT_ID = "momentId" const val KEY_VIDEO_OPT_VIDEO_ID = "videoId" const val KEY_ENTRY_POINT_DATA_SOURCE = "dataSource" const val KEY_ENTRY_POINT_PLAYER_THEME = "playerStyle" const val KEY_ENTRY_POINT_SOURCE_ID = "sourceId" const val KEY_ENTRY_POINT_CONTENT_ID = "entryContentId" const val KEY_ENTRY_POINT_PLAYBACK_CONFIGURATION = "playbackConfiguration" private const val PLAYBACK_MODIFICATION_METHOD_NAME = "Blaze.GlobalDelegate.playbackModificationHandler" } } val String.asEntryPointTriggerSource: BlazeEntryPointTriggerSource? get() = when (this) { "notification" -> BlazeEntryPointTriggerSource.NOTIFICATION "deepLink" -> BlazeEntryPointTriggerSource.DEEPLINK "entryPoint" -> BlazeEntryPointTriggerSource.ENTRYPOINT else -> null }