feat: add getCurrentPosition to component's ref (#3824)

* feat: add getCurrentPosition to component's ref
---------

Co-authored-by: mostafahasani <hasanie.mostafa@alopeyk.com>
This commit is contained in:
Seyed Mostafa Hasani 2024-05-28 02:00:38 -07:00 committed by GitHub
parent e23e02b359
commit c7f4d7b83b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 56 additions and 0 deletions

View File

@ -124,6 +124,7 @@ import com.brentvatne.react.R;
import com.brentvatne.receiver.AudioBecomingNoisyReceiver; import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
import com.brentvatne.receiver.BecomingNoisyListener; import com.brentvatne.receiver.BecomingNoisyListener;
import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ThemedReactContext;
import com.google.ads.interactivemedia.v3.api.AdError; import com.google.ads.interactivemedia.v3.api.AdError;
@ -697,6 +698,15 @@ public class ReactExoplayerView extends FrameLayout implements
mainHandler.postDelayed(mainRunnable, 1); mainHandler.postDelayed(mainRunnable, 1);
} }
public void getCurrentPosition(Promise promise) {
if (player != null) {
double currentPosition = player.getCurrentPosition() / 1000;
promise.resolve(currentPosition);
} else {
promise.reject("PLAYER_NOT_AVAILABLE", "Player is not initialized.");
}
}
private void initializePlayerCore(ReactExoplayerView self) { private void initializePlayerCore(ReactExoplayerView self) {
ExoTrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(); ExoTrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
self.trackSelector = new DefaultTrackSelector(getContext(), videoTrackSelectionFactory); self.trackSelector = new DefaultTrackSelector(getContext(), videoTrackSelectionFactory);

View File

@ -2,6 +2,7 @@ package com.brentvatne.react
import com.brentvatne.common.toolbox.ReactBridgeUtils import com.brentvatne.common.toolbox.ReactBridgeUtils
import com.brentvatne.exoplayer.ReactExoplayerView import com.brentvatne.exoplayer.ReactExoplayerView
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.ReactMethod
@ -61,6 +62,13 @@ class VideoManagerModule(reactContext: ReactApplicationContext?) : ReactContextB
} }
} }
@ReactMethod
fun getCurrentPosition(reactTag: Int, promise: Promise) {
performOnPlayerView(reactTag) {
it?.getCurrentPosition(promise)
}
}
companion object { companion object {
private const val REACT_CLASS = "VideoManager" private const val REACT_CLASS = "VideoManager"
} }

View File

@ -100,6 +100,15 @@ tolerance is the max distance in milliseconds from the seconds position that's a
This function will change the volume exactly like [volume](./props#volume) property. default value and range are the same then. This function will change the volume exactly like [volume](./props#volume) property. default value and range are the same then.
### `getCurrentPosition`
<PlatformsList types={['Android', 'iOS']} />
`getCurrentPosition(): Promise<number>`
This function retrieves and returns the precise current position of the video playback, measured in seconds.
This function will throw an error if player is not initialized.
### Example Usage ### Example Usage
```tsx ```tsx

View File

@ -1622,6 +1622,16 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
} }
} }
@objc
func getCurrentPlaybackTime(_ resolve: @escaping RCTPromiseResolveBlock, _ reject: @escaping RCTPromiseRejectBlock) {
if let player = _playerItem {
let currentTime = RCTVideoUtils.getCurrentTime(playerItem: player)
resolve(currentTime)
} else {
reject("PLAYER_NOT_AVAILABLE", "Player is not initialized.", nil)
}
}
// Workaround for #3418 - https://github.com/TheWidlarzGroup/react-native-video/issues/3418#issuecomment-2043508862 // Workaround for #3418 - https://github.com/TheWidlarzGroup/react-native-video/issues/3418#issuecomment-2043508862
@objc @objc
func setOnClick(_: Any) {} func setOnClick(_: Any) {}

View File

@ -88,4 +88,8 @@ RCT_EXTERN_METHOD(dismissFullscreenPlayer : (nonnull NSNumber*)reactTag)
RCT_EXTERN_METHOD(setVolume : (nonnull float*)volume reactTag : (nonnull NSNumber*)reactTag) RCT_EXTERN_METHOD(setVolume : (nonnull float*)volume reactTag : (nonnull NSNumber*)reactTag)
RCT_EXTERN_METHOD(getCurrentPosition
: (nonnull NSNumber*)reactTag resolver
: (RCTPromiseResolveBlock)resolve rejecter
: (RCTPromiseRejectBlock)reject)
@end @end

View File

@ -86,6 +86,13 @@ class RCTVideoManager: RCTViewManager {
}) })
} }
@objc(getCurrentPosition:resolver:rejecter:)
func getCurrentPosition(reactTag: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
performOnVideoView(withReactTag: reactTag, callback: { videoView in
videoView?.getCurrentPlaybackTime(resolve, reject)
})
}
override class func requiresMainQueueSetup() -> Bool { override class func requiresMainQueueSetup() -> Bool {
return true return true
} }

View File

@ -65,6 +65,7 @@ export interface VideoRef {
) => void; ) => void;
save: (options: object) => Promise<VideoSaveData>; save: (options: object) => Promise<VideoSaveData>;
setVolume: (volume: number) => void; setVolume: (volume: number) => void;
getCurrentPosition: () => Promise<number>;
} }
const Video = forwardRef<VideoRef, ReactVideoProps>( const Video = forwardRef<VideoRef, ReactVideoProps>(
@ -295,6 +296,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
return VideoManager.setVolume(volume, getReactTag(nativeRef)); return VideoManager.setVolume(volume, getReactTag(nativeRef));
}, []); }, []);
const getCurrentPosition = useCallback(() => {
return VideoManager.getCurrentPosition(getReactTag(nativeRef));
}, []);
const onVideoLoadStart = useCallback( const onVideoLoadStart = useCallback(
(e: NativeSyntheticEvent<OnLoadStartData>) => { (e: NativeSyntheticEvent<OnLoadStartData>) => {
hasPoster && setShowPoster(true); hasPoster && setShowPoster(true);
@ -512,6 +517,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
resume, resume,
restoreUserInterfaceForPictureInPictureStopCompleted, restoreUserInterfaceForPictureInPictureStopCompleted,
setVolume, setVolume,
getCurrentPosition,
}), }),
[ [
seek, seek,
@ -522,6 +528,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
resume, resume,
restoreUserInterfaceForPictureInPictureStopCompleted, restoreUserInterfaceForPictureInPictureStopCompleted,
setVolume, setVolume,
getCurrentPosition,
], ],
); );

View File

@ -389,6 +389,7 @@ export interface VideoManagerType {
reactTag: number, reactTag: number,
) => Promise<void>; ) => Promise<void>;
setVolume: (volume: number, reactTag: number) => Promise<void>; setVolume: (volume: number, reactTag: number) => Promise<void>;
getCurrentPosition: (reactTag: number) => Promise<number>;
} }
export interface VideoDecoderPropertiesType { export interface VideoDecoderPropertiesType {