fix: remove setNativeProps usage (#3605)
				
					
				
			* fix: remove `setNativeProps` usage * code review
This commit is contained in:
		| @@ -70,7 +70,6 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | |||||||
|     private static final String PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback"; |     private static final String PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback"; | ||||||
|     private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; |     private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; | ||||||
|     private static final String PROP_REPORT_BANDWIDTH = "reportBandwidth"; |     private static final String PROP_REPORT_BANDWIDTH = "reportBandwidth"; | ||||||
|     private static final String PROP_SEEK = "seek"; |  | ||||||
|     private static final String PROP_RATE = "rate"; |     private static final String PROP_RATE = "rate"; | ||||||
|     private static final String PROP_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount"; |     private static final String PROP_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount"; | ||||||
|     private static final String PROP_MAXIMUM_BIT_RATE = "maxBitRate"; |     private static final String PROP_MAXIMUM_BIT_RATE = "maxBitRate"; | ||||||
| @@ -321,11 +320,6 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi | |||||||
|         videoView.setReportBandwidth(reportBandwidth); |         videoView.setReportBandwidth(reportBandwidth); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @ReactProp(name = PROP_SEEK) |  | ||||||
|     public void setSeek(final ReactExoplayerView videoView, final float seek) { |  | ||||||
|         videoView.seekTo(Math.round(seek * 1000f)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @ReactProp(name = PROP_RATE) |     @ReactProp(name = PROP_RATE) | ||||||
|     public void setRate(final ReactExoplayerView videoView, final float rate) { |     public void setRate(final ReactExoplayerView videoView, final float rate) { | ||||||
|         videoView.setRateModifier(rate); |         videoView.setRateModifier(rate); | ||||||
|   | |||||||
| @@ -1,38 +0,0 @@ | |||||||
| package com.brentvatne.react; |  | ||||||
|  |  | ||||||
| import android.view.View; |  | ||||||
|  |  | ||||||
| import androidx.annotation.NonNull; |  | ||||||
|  |  | ||||||
| import com.brentvatne.exoplayer.ReactExoplayerView; |  | ||||||
| import com.facebook.react.bridge.ReactApplicationContext; |  | ||||||
| import com.facebook.react.bridge.ReactContextBaseJavaModule; |  | ||||||
| import com.facebook.react.bridge.ReactMethod; |  | ||||||
| import com.facebook.react.uimanager.UIManagerModule; |  | ||||||
|  |  | ||||||
| public class VideoManagerModule extends ReactContextBaseJavaModule { |  | ||||||
|     private static final String REACT_CLASS = "VideoManager"; |  | ||||||
|  |  | ||||||
|     public VideoManagerModule(ReactApplicationContext reactContext) { |  | ||||||
|         super(reactContext); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @NonNull |  | ||||||
|     @Override |  | ||||||
|     public String getName() { |  | ||||||
|         return REACT_CLASS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @ReactMethod |  | ||||||
|     public void setPlayerPauseState(Boolean paused, int reactTag) { |  | ||||||
|         UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class); |  | ||||||
|         uiManager.prependUIBlock(manager -> { |  | ||||||
|             View view = manager.resolveView(reactTag); |  | ||||||
|  |  | ||||||
|             if (view instanceof ReactExoplayerView) { |  | ||||||
|                 ReactExoplayerView videoView = (ReactExoplayerView) view; |  | ||||||
|                 videoView.setPausedModifier(paused); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -0,0 +1,59 @@ | |||||||
|  | package com.brentvatne.react | ||||||
|  |  | ||||||
|  | import com.brentvatne.common.toolbox.ReactBridgeUtils | ||||||
|  | import com.brentvatne.exoplayer.ReactExoplayerView | ||||||
|  | import com.facebook.react.bridge.ReactApplicationContext | ||||||
|  | import com.facebook.react.bridge.ReactContextBaseJavaModule | ||||||
|  | import com.facebook.react.bridge.ReactMethod | ||||||
|  | import com.facebook.react.bridge.ReadableMap | ||||||
|  | import com.facebook.react.bridge.UiThreadUtil | ||||||
|  | import com.facebook.react.uimanager.UIManagerModule | ||||||
|  | import kotlin.math.roundToInt | ||||||
|  |  | ||||||
|  | class VideoManagerModule(reactContext: ReactApplicationContext?) : ReactContextBaseJavaModule(reactContext) { | ||||||
|  |     override fun getName(): String { | ||||||
|  |         return REACT_CLASS | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun performOnPlayerView(reactTag: Int, callback: (ReactExoplayerView?) -> Unit) { | ||||||
|  |         UiThreadUtil.runOnUiThread { | ||||||
|  |             val view = if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { | ||||||
|  |                 reactApplicationContext.fabricUIManager?.resolveView( | ||||||
|  |                     reactTag | ||||||
|  |                 ) | ||||||
|  |             } else { | ||||||
|  |                 val uiManager = reactApplicationContext.getNativeModule(UIManagerModule::class.java) | ||||||
|  |                 uiManager?.resolveView(reactTag) | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (view is ReactExoplayerView) { | ||||||
|  |                 callback(view) | ||||||
|  |             } else { | ||||||
|  |                 callback(null) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ReactMethod | ||||||
|  |     fun setPlayerPauseState(paused: Boolean?, reactTag: Int) { | ||||||
|  |         performOnPlayerView(reactTag) { | ||||||
|  |             it?.setPausedModifier(paused!!) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @ReactMethod | ||||||
|  |     fun seek(info: ReadableMap, reactTag: Int) { | ||||||
|  |         if (!info.hasKey("time")) { | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val time = ReactBridgeUtils.safeGetInt(info, "time") | ||||||
|  |         performOnPlayerView(reactTag) { | ||||||
|  |             it?.seekTo((time * 1000f).roundToInt().toLong()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         private const val REACT_CLASS = "VideoManager" | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -28,7 +28,6 @@ RCT_EXPORT_VIEW_PROPERTY(pictureInPicture, BOOL); | |||||||
| RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString); | RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString); | ||||||
| RCT_EXPORT_VIEW_PROPERTY(mixWithOthers, NSString); | RCT_EXPORT_VIEW_PROPERTY(mixWithOthers, NSString); | ||||||
| RCT_EXPORT_VIEW_PROPERTY(rate, float); | RCT_EXPORT_VIEW_PROPERTY(rate, float); | ||||||
| RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary); |  | ||||||
| RCT_EXPORT_VIEW_PROPERTY(fullscreen, BOOL); | RCT_EXPORT_VIEW_PROPERTY(fullscreen, BOOL); | ||||||
| RCT_EXPORT_VIEW_PROPERTY(fullscreenAutorotate, BOOL); | RCT_EXPORT_VIEW_PROPERTY(fullscreenAutorotate, BOOL); | ||||||
| RCT_EXPORT_VIEW_PROPERTY(fullscreenOrientation, NSString); | RCT_EXPORT_VIEW_PROPERTY(fullscreenOrientation, NSString); | ||||||
| @@ -74,6 +73,8 @@ RCT_EXTERN_METHOD(save | |||||||
|                   : (RCTPromiseResolveBlock)resolve rejecter |                   : (RCTPromiseResolveBlock)resolve rejecter | ||||||
|                   : (RCTPromiseRejectBlock)reject) |                   : (RCTPromiseRejectBlock)reject) | ||||||
|  |  | ||||||
|  | RCT_EXTERN_METHOD(seek : (NSDictionary*)info reactTag : (nonnull NSNumber*)reactTag) | ||||||
|  |  | ||||||
| RCT_EXTERN_METHOD(setLicenseResult : (NSString*)license licenseUrl : (NSString*)licenseUrl reactTag : (nonnull NSNumber*)reactTag) | RCT_EXTERN_METHOD(setLicenseResult : (NSString*)license licenseUrl : (NSString*)licenseUrl reactTag : (nonnull NSNumber*)reactTag) | ||||||
|  |  | ||||||
| RCT_EXTERN_METHOD(setLicenseResultError : (NSString*)error licenseUrl : (NSString*)licenseUrl reactTag : (nonnull NSNumber*)reactTag) | RCT_EXTERN_METHOD(setLicenseResultError : (NSString*)error licenseUrl : (NSString*)licenseUrl reactTag : (nonnull NSNumber*)reactTag) | ||||||
|   | |||||||
| @@ -11,77 +11,70 @@ class RCTVideoManager: RCTViewManager { | |||||||
|         return bridge.uiManager.methodQueue |         return bridge.uiManager.methodQueue | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     func performOnVideoView(withReactTag reactTag: NSNumber, callback: @escaping (RCTVideo?) -> Void) { | ||||||
|  |         DispatchQueue.main.async { [weak self] in | ||||||
|  |             guard let self else { | ||||||
|  |                 callback(nil) | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             guard let view = self.bridge.uiManager.view(forReactTag: reactTag) as? RCTVideo else { | ||||||
|  |                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: \(String(describing: view))") | ||||||
|  |                 callback(nil) | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             callback(view) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @objc(save:reactTag:resolver:rejecter:) |     @objc(save:reactTag:resolver:rejecter:) | ||||||
|     func save(options: NSDictionary, reactTag: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { |     func save(options: NSDictionary, reactTag: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.save(options: options, resolve: resolve, reject: reject) | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 view.save(options: options, resolve: resolve, reject: reject) |  | ||||||
|             } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @objc(seek:reactTag:) | ||||||
|  |     func seek(info: NSDictionary, reactTag: NSNumber) { | ||||||
|  |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|  |             videoView?.setSeek(info) | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @objc(setLicenseResult:licenseUrl:reactTag:) |     @objc(setLicenseResult:licenseUrl:reactTag:) | ||||||
|     func setLicenseResult(license: NSString, licenseUrl: NSString, reactTag: NSNumber) { |     func setLicenseResult(license: NSString, licenseUrl: NSString, reactTag: NSNumber) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.setLicenseResult(license as String, licenseUrl as String) | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 view.setLicenseResult(license as String, licenseUrl as String) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @objc(setLicenseResultError:licenseUrl:reactTag:) |     @objc(setLicenseResultError:licenseUrl:reactTag:) | ||||||
|     func setLicenseResultError(error: NSString, licenseUrl: NSString, reactTag: NSNumber) { |     func setLicenseResultError(error: NSString, licenseUrl: NSString, reactTag: NSNumber) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.setLicenseResultError(error as String, licenseUrl as String) | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 view.setLicenseResultError(error as String, licenseUrl as String) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @objc(dismissFullscreenPlayer:) |     @objc(dismissFullscreenPlayer:) | ||||||
|     func dismissFullscreenPlayer(_ reactTag: NSNumber) { |     func dismissFullscreenPlayer(_ reactTag: NSNumber) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.dismissFullscreenPlayer() | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 view.dismissFullscreenPlayer() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @objc(presentFullscreenPlayer:) |     @objc(presentFullscreenPlayer:) | ||||||
|     func presentFullscreenPlayer(_ reactTag: NSNumber) { |     func presentFullscreenPlayer(_ reactTag: NSNumber) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.presentFullscreenPlayer() | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 view.presentFullscreenPlayer() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @objc(setPlayerPauseState:reactTag:) |     @objc(setPlayerPauseState:reactTag:) | ||||||
|     func setPlayerPauseState(paused: NSNumber, reactTag: NSNumber) { |     func setPlayerPauseState(paused: NSNumber, reactTag: NSNumber) { | ||||||
|         bridge.uiManager.prependUIBlock { _, viewRegistry in |         performOnVideoView(withReactTag: reactTag, callback: { videoView in | ||||||
|             let view = viewRegistry?[reactTag] |             videoView?.setPaused(paused.boolValue) | ||||||
|             if !(view is RCTVideo) { |         }) | ||||||
|                 RCTLogError("Invalid view returned from registry, expecting RCTVideo, got: %@", String(describing: view)) |  | ||||||
|             } else if let view = view as? RCTVideo { |  | ||||||
|                 let paused = paused.boolValue |  | ||||||
|                 view.setPaused(paused) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override class func requiresMainQueueSetup() -> Bool { |     override class func requiresMainQueueSetup() -> Bool { | ||||||
|   | |||||||
| @@ -227,19 +227,22 @@ const Video = forwardRef<VideoRef, ReactVideoProps>( | |||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       Platform.select({ |       const callSeekFunction = () => { | ||||||
|         ios: () => { |         VideoManager.seek( | ||||||
|           nativeRef.current?.setNativeProps({ |           { | ||||||
|             seek: { |  | ||||||
|             time, |             time, | ||||||
|             tolerance: tolerance || 0, |             tolerance: tolerance || 0, | ||||||
|           }, |           }, | ||||||
|           }); |           getReactTag(nativeRef), | ||||||
|         }, |         ); | ||||||
|  |       }; | ||||||
|  |  | ||||||
|  |       Platform.select({ | ||||||
|  |         ios: callSeekFunction, | ||||||
|  |         android: callSeekFunction, | ||||||
|         default: () => { |         default: () => { | ||||||
|           nativeRef.current?.setNativeProps({ |           // TODO: Implement VideoManager.seek for windows | ||||||
|             seek: time, |           nativeRef.current?.setNativeProps({seek: time}); | ||||||
|           }); |  | ||||||
|         }, |         }, | ||||||
|       })(); |       })(); | ||||||
|     }, []); |     }, []); | ||||||
|   | |||||||
| @@ -537,6 +537,7 @@ export type VideoSaveData = { | |||||||
|  |  | ||||||
| export interface VideoManagerType { | export interface VideoManagerType { | ||||||
|   save: (option: object, reactTag: number) => Promise<VideoSaveData>; |   save: (option: object, reactTag: number) => Promise<VideoSaveData>; | ||||||
|  |   seek: (option: Seek, reactTag: number) => Promise<void>; | ||||||
|   setPlayerPauseState: (paused: boolean, reactTag: number) => Promise<void>; |   setPlayerPauseState: (paused: boolean, reactTag: number) => Promise<void>; | ||||||
|   setLicenseResult: ( |   setLicenseResult: ( | ||||||
|     result: string, |     result: string, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user