Skip to content

Commit

Permalink
feat: add getCurrentPosition to component's ref (#3824)
Browse files Browse the repository at this point in the history
* feat: add getCurrentPosition to component's ref
---------

Co-authored-by: mostafahasani <[email protected]>
  • Loading branch information
seyedmostafahasani and mostafahasani authored May 28, 2024
1 parent e23e02b commit c7f4d7b
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
import com.brentvatne.receiver.BecomingNoisyListener;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.google.ads.interactivemedia.v3.api.AdError;
Expand Down Expand Up @@ -697,6 +698,15 @@ private void initializePlayer() {
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) {
ExoTrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
self.trackSelector = new DefaultTrackSelector(getContext(), videoTrackSelectionFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.brentvatne.react

import com.brentvatne.common.toolbox.ReactBridgeUtils
import com.brentvatne.exoplayer.ReactExoplayerView
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
Expand Down Expand Up @@ -61,6 +62,13 @@ class VideoManagerModule(reactContext: ReactApplicationContext?) : ReactContextB
}
}

@ReactMethod
fun getCurrentPosition(reactTag: Int, promise: Promise) {
performOnPlayerView(reactTag) {
it?.getCurrentPosition(promise)
}
}

companion object {
private const val REACT_CLASS = "VideoManager"
}
Expand Down
9 changes: 9 additions & 0 deletions docs/pages/component/methods.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

### `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

```tsx
Expand Down
10 changes: 10 additions & 0 deletions ios/Video/RCTVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
@objc
func setOnClick(_: Any) {}
Expand Down
4 changes: 4 additions & 0 deletions ios/Video/RCTVideoManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ @interface RCT_EXTERN_MODULE (RCTVideoManager, RCTViewManager)

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
7 changes: 7 additions & 0 deletions ios/Video/RCTVideoManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
return true
}
Expand Down
7 changes: 7 additions & 0 deletions src/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface VideoRef {
) => void;
save: (options: object) => Promise<VideoSaveData>;
setVolume: (volume: number) => void;
getCurrentPosition: () => Promise<number>;
}

const Video = forwardRef<VideoRef, ReactVideoProps>(
Expand Down Expand Up @@ -295,6 +296,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
return VideoManager.setVolume(volume, getReactTag(nativeRef));
}, []);

const getCurrentPosition = useCallback(() => {
return VideoManager.getCurrentPosition(getReactTag(nativeRef));
}, []);

const onVideoLoadStart = useCallback(
(e: NativeSyntheticEvent<OnLoadStartData>) => {
hasPoster && setShowPoster(true);
Expand Down Expand Up @@ -512,6 +517,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
resume,
restoreUserInterfaceForPictureInPictureStopCompleted,
setVolume,
getCurrentPosition,
}),
[
seek,
Expand All @@ -522,6 +528,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
resume,
restoreUserInterfaceForPictureInPictureStopCompleted,
setVolume,
getCurrentPosition,
],
);

Expand Down
1 change: 1 addition & 0 deletions src/specs/VideoNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ export interface VideoManagerType {
reactTag: number,
) => Promise<void>;
setVolume: (volume: number, reactTag: number) => Promise<void>;
getCurrentPosition: (reactTag: number) => Promise<number>;
}

export interface VideoDecoderPropertiesType {
Expand Down

0 comments on commit c7f4d7b

Please sign in to comment.