import { requireNativeComponent, UIManager, findNodeHandle, Platform, type ViewProps } from 'react-native'; import React, { Component } from 'react'; const ELEMENTS_NATIVE_COMPONENT = 'RCTElementsPlayer'; const ELEMENTS_LINKING_ERROR = `The package 'connatix-player-sdk-react-native' doesn't seem to be linked. Make sure: \n\n` + Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo managed workflow\n'; type RCTElementsPlayerProps = ViewProps & { onSetElementsConfig: (event: any) => void onPlay: (event: any) => void onPause: (event: any) => void onSetVolume: (event: any) => void onSetQuality: (event: any) => void onGetQuality: (event: any) => void onDisableAdvertising: (event: any) => void onEnableAdvertising: (event: any) => void onSetMacros: (event: any) => void onSetPreRollBreak: (event: any) => void onSetPostRollBreak: (event: any) => void onAddFriendlyObstruction: (event: any) => void onRemoveFriendlyObstruction: (event: any) => void onGetVideoDetails: (event: any) => void onGetVideoCurrentPosition: (event: any) => void onGetVideoDuration: (event: any) => void onGetVideoIndex: (event: any) => void onSetVideoIndex: (event: any) => void onSetAutoQuality: (event: any) => void onGetAvailableQualities: (event: any) => void onToggleFullscreen: (event: any) => void onToggleSubtitles: (event: any) => void onGetSubtitles: (event: any) => void onSetSubtitle: (event: any) => void onListenFor: (event: any) => void onListenForMore: (event: any) => void onRemove: (event: any) => void onPlayerEvent: (event: any) => void }; const RCTElementsPlayer = UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT) != null ? requireNativeComponent(ELEMENTS_NATIVE_COMPONENT) : () => { throw new Error(ELEMENTS_LINKING_ERROR); }; type ElementsPlayerState = { setElementsConfigCallback: ((errorMessage: string | undefined, success: Boolean | undefined) => void) | undefined playCallback: ((errorMessage: string) => void) | undefined pauseCallback: ((errorMessage: string) => void) | undefined setVolumeCallback: ((errorMessage: string) => void) | undefined setQualityCallback: ((errorMessage: string) => void) | undefined getQualityCallback: ((errorMessage: string | undefined, quality: number | undefined) => void) | undefined disableAdvertisingCallback: ((errorMessage: string) => void) | undefined enableAdvertisingCallback: ((errorMessage: string) => void) | undefined setMacrosCallback: ((errorMessage: string) => void) | undefined setPreRollBreakCallback: ((errorMessage: string) => void) | undefined setPostRollBreakCallback: ((errorMessage: string) => void) | undefined addFriendlyObstructionCallback: ((errorMessage: string) => void) | undefined removeFriendlyObstructionCallback: ((errorMessage: string) => void) | undefined getVideoDetailsCallback: ((errorMessage: string | undefined, videoDetails: Map | undefined) => void) | undefined getVideoCurrentPositionCallback: ((errorMessage: string | undefined, position: number | undefined) => void) | undefined getVideoDurationCallback: ((errorMessage: string | undefined, duration: number | undefined) => void) | undefined getVideoIndexCallback: ((errorMessage: string | undefined, duration: number | undefined) => void) | undefined setVideoIndexCallback: ((errorMessage: string) => void) | undefined setAutoQualityCallback: ((errorMessage: string) => void) | undefined getAvailableQualitiesCallback: ((errorMessage: string | undefined, qualities: Array | undefined) => void) | undefined toggleFullscreenCallback: ((errorMessage: string) => void) | undefined toggleSubtitlesCallback: ((errorMessage: string) => void) | undefined getSubtitlesCallback: ((errorMessage: string | undefined, tracks: Array> | undefined) => void) | undefined setSubtitleCallback: ((errorMessage: string) => void) | undefined listenForCallback: ((errorMessage: string) => void) | undefined listenForMoreCallback: ((errorMessage: string) => void) | undefined removeCallback: ((errorMessage: string) => void) | undefined }; type ElementsPlayerProps = ViewProps & { onPlayerEvent?: ((event: any) => void) | undefined }; class ElementsPlayer extends Component{ constructor(props: ElementsPlayerProps) { super(props); this._handleNativeSetElementsConfigCallback = this._handleNativeSetElementsConfigCallback.bind(this); this._handleNativePlayCallback = this._handleNativePlayCallback.bind(this); this._handleNativePauseCallback = this._handleNativePauseCallback.bind(this); this._handleNativeSetVolumeCallback = this._handleNativeSetVolumeCallback.bind(this); this._handleNativeSetQualityCallback = this._handleNativeSetQualityCallback.bind(this); this._handleNativeGetQualityCallback = this._handleNativeGetQualityCallback.bind(this); this._handleNativeDisableAdvertisingCallback = this._handleNativeDisableAdvertisingCallback.bind(this); this._handleNativeEnableAdvertisingCallback = this._handleNativeEnableAdvertisingCallback.bind(this); this._handleNativeSetMacrosCallback = this._handleNativeSetMacrosCallback.bind(this); this._handleNativeSetPreRollBreakCallback = this._handleNativeSetPreRollBreakCallback.bind(this); this._handleNativeSetPostRollBreakCallback = this._handleNativeSetPostRollBreakCallback.bind(this); this._handleNativeAddFriendlyObstructionCallback = this._handleNativeAddFriendlyObstructionCallback.bind(this); this._handleNativeRemoveFriendlyObstructionCallback = this._handleNativeRemoveFriendlyObstructionCallback.bind(this); this._handleNativeGetVideoDetailsCallback = this._handleNativeGetVideoDetailsCallback.bind(this); this._handleNativeGetVideoCurrentPositionCallback = this._handleNativeGetVideoCurrentPositionCallback.bind(this); this._handleNativeGetVideoDurationCallback = this._handleNativeGetVideoDurationCallback.bind(this); this._handleNativeGetVideoIndexCallback = this._handleNativeGetVideoIndexCallback.bind(this); this._handleNativeSetVideoIndexCallback = this._handleNativeSetVideoIndexCallback.bind(this); this._handleNativeSetAutoQualityCallback = this._handleNativeSetAutoQualityCallback.bind(this); this._handleNativeGetAvailableQualitiesCallback = this._handleNativeGetAvailableQualitiesCallback.bind(this); this._handleNativeToggleFullscreenCallback = this._handleNativeToggleFullscreenCallback.bind(this); this._handleNativeToggleSubtitlesCallback = this._handleNativeToggleSubtitlesCallback.bind(this); this._handleNativeGetSubtitlesCallback = this._handleNativeGetSubtitlesCallback.bind(this); this._handleNativeSetSubtitleCallback = this._handleNativeSetSubtitleCallback.bind(this); this._handleNativeListenForCallback = this._handleNativeListenForCallback.bind(this); this._handleNativeListenForMoreCallback = this._handleNativeListenForMoreCallback.bind(this); this._handleNativeRemoveCallback = this._handleNativeRemoveCallback.bind(this); this._handleNativeOnPlayerEventCallback = this._handleNativeOnPlayerEventCallback.bind(this); } /** * Sets the configuration for the Elements player * @param config JSON string needed for the player to run * @param callback optional callback which returns true on success or error message on failure cases */ setElementsConfig(config: string, callback?: ((errorMessage: string | undefined, success: Boolean | undefined) => void) | undefined) { this.setState({setElementsConfigCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setElementsConfig, [config] ); } private _handleNativeSetElementsConfigCallback(event: any) { if (this.state.setElementsConfigCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setElementsConfigCallback(event.nativeEvent.error, undefined); this.setState({setElementsConfigCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.setElementsConfigCallback(undefined, event.nativeEvent.result); this.setState({setElementsConfigCallback: undefined}); } } /** * Stops every function of the player, including the ad session. The player will need to be restarted after this */ stopPlayer() { this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.stopPlayer); } /** * Sets the player state to "play" * @param callback optional callback for failure cases */ play(callback?: ((errorMessage: string) => void) | undefined) { this.setState({playCallback: callback}) this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.play); } private _handleNativePlayCallback(event: any) { if (this.state.playCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.playCallback(event.nativeEvent.error); this.setState({playCallback: undefined}); } } /** * Sets the player state to "pause" * @param callback optional callback for failure cases */ pause(callback?: ((errorMessage: string) => void) | undefined) { this.setState({pauseCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.pause); } private _handleNativePauseCallback(event: any) { if (this.state.pauseCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.pauseCallback(event.nativeEvent.error); this.setState({pauseCallback: undefined}); } } /** * Sets the player volume to the specified value * @param volume float between 0 and 1 * @param callback optional callback for failure cases */ setVolume(volume: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setVolumeCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setVolume, [volume] ); } private _handleNativeSetVolumeCallback(event: any) { if (this.state.setVolumeCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setVolumeCallback(event.nativeEvent.error); this.setState({setVolumeCallback: undefined}); } } /** * Sets the resolution of the video to the specified quality * @param quality int, only 360, 720 and 1080 supported * @param callback optional callback for failure cases */ setQuality(quality: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setQualityCallback: callback}) this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setQuality, [quality] ); } private _handleNativeSetQualityCallback(event: any) { if (this.state.setQualityCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setQualityCallback(event.nativeEvent.error); this.setState({setQualityCallback: undefined}) } } /** * Returns the current resolution of the video * @param callback callback for the Int quality on success or the error message on failure */ getQuality(callback: ((errorMessage: string | undefined, quality: number | undefined) => void) | undefined) { this.setState({getQualityCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getQuality); } private _handleNativeGetQualityCallback(event: any) { if (this.state.getQualityCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getQualityCallback(event.nativeEvent.error, undefined); this.setState({getQualityCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getQualityCallback(undefined, event.nativeEvent.result); this.setState({getQualityCallback: undefined}); } } /** * Pauses player advertising, note that a running ad will finish if this method is called * @param callback optional callback for failure cases */ disableAdvertising(callback?: ((errorMessage: string) => void) | undefined) { this.setState({disableAdvertisingCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.disableAdvertising); } private _handleNativeDisableAdvertisingCallback(event: any) { if (this.state.disableAdvertisingCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.disableAdvertisingCallback(event.nativeEvent.error); this.setState({disableAdvertisingCallback: undefined}); } } /** * If advertising was previously disabled by the 'disableAdvertising' call, it will enable it back * @param callback optional callback for failure cases */ enableAdvertising(callback?: ((errorMessage: string) => void) | undefined) { this.setState({enableAdvertisingCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.enableAdvertising); } private _handleNativeEnableAdvertisingCallback(event: any) { if (this.state.enableAdvertisingCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.enableAdvertisingCallback(event.nativeEvent.error); this.setState({enableAdvertisingCallback: undefined}); } } /** * Sets custom macros. The method uses key value pairs of macros { key: value }. Please note that Connatix Macros will NOT we overridden * @param macrosJsonString representing key value pairs of macros to be substituted in lineItems URLs before calling for VAST Ads. If any of the macro keys match the "Connatix macros" (ex: height, page_url), the values provided programmatically by the user will NOT override the values detected by the player, only for the externally loaded line items * @param callback optional callback for failure cases */ setMacros(macrosJsonString: string, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setMacrosCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setMacros, [macrosJsonString] ); } private _handleNativeSetMacrosCallback(event: any) { if (this.state.setMacrosCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setMacrosCallback(event.nativeEvent.error); this.setState({setMacrosCallback: undefined}); } } /** * Dynamically set the pre-roll break duration. This method needs to be called with the duration in seconds. To disable the break call this with 0 value * @param seconds number of seconds for the pre-roll break * @param callback optional callback for failure cases */ setPreRollBreak(seconds: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setPreRollBreakCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setPreRollBreak, [seconds] ); } private _handleNativeSetPreRollBreakCallback(event: any) { if (this.state.setPreRollBreakCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setPreRollBreakCallback(event.nativeEvent.error); this.setState({setPreRollBreakCallback: undefined}); } } /** * Dynamically set the post-roll break duration. This method needs to be called with the duration in seconds. To disable the break call this with 0 value * @param seconds number of seconds for the post-roll break * @param callback optional callback for failure cases */ setPostRollBreak(seconds: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setPostRollBreakCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setPostRollBreak, [seconds] ); } private _handleNativeSetPostRollBreakCallback(event: any) { if (this.state.setPostRollBreakCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setPostRollBreakCallback(event.nativeEvent.error); this.setState({setPostRollBreakCallback: undefined}); } } /** * Adds friendly obstruction which should then be excluded from all ad session viewability calculations. * It also provides a purpose and detailed reason string to pass forward to the measurement vendors. * This method will have no effect if called after the ad session has finished. * @param obstructionReactTag the react tag of the view to be excluded from all ad session viewability calculations * @param purpose the purpose of why this obstruction was necessary. Possible values: "videoControls", "closeAd", "notVisible", "other" * @param detailedReason an explanation for why this obstruction is part of the ad experience if not already obvious from the purpose. Can be null. If not null, must be 50 characters or less and only contain characters `A-z`, `0-9`, or spaces * @param callback optional callback for failure cases */ addFriendlyObstruction(obstructionReactTag: number, purpose: string, detailedReason: string, callback?: ((errorMessage: string) => void) | undefined) { this.setState({addFriendlyObstructionCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.addFriendlyObstruction, [obstructionReactTag, purpose, detailedReason] ); } private _handleNativeAddFriendlyObstructionCallback(event: any) { if (this.state.addFriendlyObstructionCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.addFriendlyObstructionCallback(event.nativeEvent.error); this.setState({addFriendlyObstructionCallback: undefined}); } } /** * Removes registered friendly obstruction. This method will have no effect if called after the ad session has finished * @param obstructionReactTag the react tag of the view to be removed from the list of registered friendly obstructions * @param callback optional callback for failure cases */ removeFriendlyObstruction(obstructionReactTag: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({removeFriendlyObstructionCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.removeFriendlyObstruction, [obstructionReactTag] ); } private _handleNativeRemoveFriendlyObstructionCallback(event: any) { if (this.state.removeFriendlyObstructionCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.removeFriendlyObstructionCallback(event.nativeEvent.error); this.setState({removeFriendlyObstructionCallback: undefined}); } } /** * Returns the details of the currently playing video * @param callback callback for the video details on success or the error message on failure */ getVideoDetails(callback: ((errorMessage: string | undefined, videoDetails: Map | undefined) => void) | undefined) { this.setState({getVideoDetailsCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getVideoDetails); } private _handleNativeGetVideoDetailsCallback(event: any) { if (this.state.getVideoDetailsCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getVideoDetailsCallback(event.nativeEvent.error, undefined); this.setState({getVideoDetailsCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getVideoDetailsCallback(undefined, event.nativeEvent.result); this.setState({getVideoDetailsCallback: undefined}); } } /** * Returns the timestamp of the currently playing video in seconds * @param callback callback for the video current position on success or the error message on failure */ getVideoCurrentPosition(callback: ((errorMessage: string | undefined, position: number | undefined) => void) | undefined) { this.setState({getVideoCurrentPositionCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getVideoCurrentPosition); } private _handleNativeGetVideoCurrentPositionCallback(event: any) { if (this.state.getVideoCurrentPositionCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getVideoCurrentPositionCallback(event.nativeEvent.error, undefined); this.setState({getVideoCurrentPositionCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getVideoCurrentPositionCallback(undefined, event.nativeEvent.result); this.setState({getVideoCurrentPositionCallback: undefined}); } } /** * Returns the duration of the currently playing video in seconds * @param callback callback for the video duration on success or the error message on failure */ getVideoDuration(callback: ((errorMessage: string | undefined, duration: number | undefined) => void) | undefined) { this.setState({getVideoDurationCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getVideoDuration); } private _handleNativeGetVideoDurationCallback(event: any) { if (this.state.getVideoDurationCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getVideoDurationCallback(event.nativeEvent.error, undefined); this.setState({getVideoDurationCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getVideoDurationCallback(undefined, event.nativeEvent.result); this.setState({getVideoDurationCallback: undefined}); } } /** * Returns the index of the video currently playing from the current playlist. If the playlist only has 1 video, the method returns the numeric value 0 * @param callback callback for the video index on success or the error message on failure */ getVideoIndex(callback: ((errorMessage: string | undefined, index: number | undefined) => void | undefined)) { this.setState({getVideoIndexCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getVideoIndex); } private _handleNativeGetVideoIndexCallback(event: any) { if (this.state.getVideoIndexCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getVideoIndexCallback(event.nativeEvent.error, undefined); this.setState({getVideoIndexCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getVideoIndexCallback(undefined, event.nativeEvent.result); this.setState({getVideoIndexCallback: undefined}); } } /** * Sets the playing video with the one found in the playlist at the index provided. The index provided should be a numeric value between 0 and the total number of videos in the current playlist - 1. If the index provided is less than 0 or greater or equal with the total number of videos, the method shows an error message and returns * @param index The index of the desired video in the playlist * @param callback Optional callback for failure cases */ setVideoIndex(index: number, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setVideoIndexCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setVideoIndex, [index] ); } private _handleNativeSetVideoIndexCallback(event: any) { if (this.state.setVideoIndexCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setVideoIndexCallback(event.nativeEvent.error); this.setState({setVideoIndexCallback: undefined}); } } /** * Sets the video quality to Auto. Auto quality will be determined by the height of the video element * @param callback optional callback for failure cases */ setAutoQuality(callback?: ((errorMessage: string) => void) | undefined) { this.setState({setAutoQualityCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setAutoQuality); } private _handleNativeSetAutoQualityCallback(event: any) { if (this.state.setAutoQualityCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setAutoQualityCallback(event.nativeEvent.error); this.setState({setAutoQualityCallback: undefined}); } } /** * Returns an array with the available resolutions of the currently playing video * @param callback callback for the available qualities array on success or the error message on failure */ getAvailableQualities(callback: ((errorMessage: string | undefined, qualities: Array | undefined) => void) | undefined) { this.setState({getAvailableQualitiesCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getAvailableQualities); } private _handleNativeGetAvailableQualitiesCallback(event: any) { if (this.state.getAvailableQualitiesCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getAvailableQualitiesCallback(event.nativeEvent.error, undefined); this.setState({getAvailableQualitiesCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getAvailableQualitiesCallback(undefined, event.nativeEvent.result); this.setState({getAvailableQualitiesCallback: undefined}); } } /** * Toggles the player full screen state. Only use this method on user interaction * @param callback optional callback for failure cases */ toggleFullscreen(callback?: ((errorMessage: string) => void) | undefined) { this.setState({toggleFullscreenCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.toggleFullscreen); } private _handleNativeToggleFullscreenCallback(event: any) { if (this.state.toggleFullscreenCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.toggleFullscreenCallback(event.nativeEvent.error); this.setState({toggleFullscreenCallback: undefined}); } } /** * Shows or hides the video subtitles based on the given boolean. Value is necessary * @param shouldShow boolean indicating whether to show subtitles or not * @param callback optional callback for failure cases */ toggleSubtitles(shouldShow: boolean, callback?: ((errorMessage: string) => void) | undefined) { this.setState({toggleSubtitlesCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.toggleSubtitles, [shouldShow] ); } private _handleNativeToggleSubtitlesCallback(event: any) { if (this.state.toggleSubtitlesCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.toggleSubtitlesCallback(event.nativeEvent.error); this.setState({toggleSubtitlesCallback: undefined}); } } /** * Returns the array of available subtitles for the current media * @param callback callback for the subtitles array on success or the error message on failure */ getSubtitles(callback: ((errorMessage: string | undefined, tracks: Array> | undefined) => void) | undefined) { this.setState({getSubtitlesCallback: callback}); this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.getSubtitles); } private _handleNativeGetSubtitlesCallback(event: any) { if (this.state.getSubtitlesCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.getSubtitlesCallback(event.nativeEvent.error, undefined); this.setState({getSubtitlesCallback: undefined}); return; } if (event.nativeEvent.result !== undefined) { this.state.getSubtitlesCallback(undefined, event.nativeEvent.result); this.setState({getSubtitlesCallback: undefined}); } } /** * Sets a subtitle from the array obtained from 'getSubtitles'. If no value is given or the subtitle is invalid (not found in the array), subtitles will be turned off * @param trackJsonString obtained from 'getSubtitles' * @param callback optional callback for failure cases */ setSubtitle(trackJsonString: string, callback?: ((errorMessage: string) => void) | undefined) { this.setState({setSubtitleCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.setSubtitle, [trackJsonString] ); } private _handleNativeSetSubtitleCallback(event: any) { if (this.state.setSubtitleCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.setSubtitleCallback(event.nativeEvent.error); this.setState({setSubtitleCallback: undefined}); } } /** * Listens to a single player event. Can be done once or as long as the player is alive * @param event the string event type to listen to * @param once boolean indicating whether the event is listened to once or indefinitely * @param callback optional callback for failure cases */ listenFor(event: string, once: boolean, callback?: ((errorMessage: string) => void) | undefined) { this.setState({listenForCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.listenFor, [event, once] ); } private _handleNativeListenForCallback(event: any) { if (this.state.listenForCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.listenForCallback(event.nativeEvent.error); this.setState({listenForCallback: undefined}); } } /** * Listens to a string array of player event * @param events Array of string to listen to indefinitely * @param callback optional callback for failure cases */ listenForMore(events: string[], callback?: ((errorMessage: string) => void) | undefined) { this.setState({listenForMoreCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.listenForMore, [events] ); } private _handleNativeListenForMoreCallback(event: any) { if (this.state.listenForMoreCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.listenForMoreCallback(event.nativeEvent.error); this.setState({listenForCallback: undefined}); } } /** * Listens to all available player events. Please check the documentation for all the possible event types */ listenForAllEvents() { this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.listenForAllEvents); } /** * Removes the listener for the specified player string event type * @param event stop listening for this string event * @param callback optional callback for failure cases */ remove(event: string, callback?: ((errorMessage: string) => void) | undefined) { this.setState({removeCallback: callback}); this._dispatchCommandWithArguments( UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.remove, [event] ); } private _handleNativeRemoveCallback(event: any) { if (this.state.removeCallback === undefined) { return; } if (event.nativeEvent.error !== undefined) { this.state.removeCallback(event.nativeEvent.error); this.setState({removeCallback: undefined}); } } /** * Removes the listeners for all player events */ removeAllEvents() { this._dispatchCommand(UIManager.getViewManagerConfig(ELEMENTS_NATIVE_COMPONENT).Commands.removeAllEvents); } private _handleNativeOnPlayerEventCallback(event: any) { if (!this.props.onPlayerEvent) { return; } this.props.onPlayerEvent(event.nativeEvent); } private _dispatchCommand(command: number | undefined) { if (command !== undefined) { UIManager?.dispatchViewManagerCommand( findNodeHandle(this), command, [] ); } } private _dispatchCommandWithArguments(command: number | undefined, args: any[]) { if (command !== undefined) { UIManager?.dispatchViewManagerCommand( findNodeHandle(this), command, args ); } } render() { return ( ); } } export default ElementsPlayer;