fix: ensure progress is sent before onEnd callback (#3872)

* fix: add onProgress event before onEnd
This commit is contained in:
Olivier Bouillet 2024-06-03 12:13:52 +02:00 committed by GitHub
parent adedc052f0
commit 7133c96cac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 30 deletions

View File

@ -57,9 +57,7 @@ class Source {
}
/** return true if this and src are equals */
fun isEquals(source: Source): Boolean {
return this == source
}
fun isEquals(source: Source): Boolean = this == source
/** Metadata to display in notification */
class Metadata {

View File

@ -258,29 +258,36 @@ public class ReactExoplayerView extends FrameLayout implements
private long lastBufferDuration = -1;
private long lastDuration = -1;
private void updateProgress() {
if (player != null) {
if (playerControlView != null && isPlayingAd() && controls) {
playerControlView.hide();
}
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
long duration = player.getDuration();
long pos = player.getCurrentPosition();
if (pos > duration) {
pos = duration;
}
if (lastPos != pos
|| lastBufferDuration != bufferedDuration
|| lastDuration != duration) {
lastPos = pos;
lastBufferDuration = bufferedDuration;
lastDuration = duration;
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
}
}
}
private final Handler progressHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_PROGRESS) {
if (player != null) {
if (playerControlView != null && isPlayingAd() && controls) {
playerControlView.hide();
}
long pos = player.getCurrentPosition();
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
long duration = player.getDuration();
if (lastPos != pos
|| lastBufferDuration != bufferedDuration
|| lastDuration != duration) {
lastPos = pos;
lastBufferDuration = bufferedDuration;
lastDuration = duration;
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
}
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
}
updateProgress();
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
}
}
};
@ -1337,6 +1344,7 @@ public class ReactExoplayerView extends FrameLayout implements
break;
case Player.STATE_ENDED:
text += "ended";
updateProgress();
eventEmitter.end();
onStopPlayback();
setKeepScreenOn(false);
@ -1614,6 +1622,7 @@ public class ReactExoplayerView extends FrameLayout implements
// so we need to explicitly detect it.
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
&& player.getRepeatMode() == Player.REPEAT_MODE_ONE) {
updateProgress();
eventEmitter.end();
}
}

View File

@ -312,7 +312,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
// MARK: - Progress
func sendProgressUpdate() {
func sendProgressUpdate(didEnd: Bool = false) {
#if !USE_GOOGLE_IMA
// If we dont use Ads and onVideoProgress is not defined we dont need to run this code
guard onVideoProgress != nil else { return }
@ -334,11 +334,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
let currentPlaybackTime = _player?.currentItem?.currentDate()
let duration = CMTimeGetSeconds(playerDuration)
let currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero)
var currentTimeSecs = CMTimeGetSeconds(currentTime ?? .zero)
NotificationCenter.default.post(name: NSNotification.Name("RCTVideo_progress"), object: nil, userInfo: [
"progress": NSNumber(value: currentTimeSecs / duration),
])
if currentTimeSecs > duration || didEnd {
currentTimeSecs = duration
}
if currentTimeSecs >= 0 {
#if USE_GOOGLE_IMA
@ -348,10 +348,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
#endif
onVideoProgress?([
"currentTime": NSNumber(value: Float(currentTimeSecs)),
"currentTime": currentTimeSecs,
"playableDuration": RCTVideoUtils.calculatePlayableDuration(_player, withSource: _source),
"atValue": NSNumber(value: currentTime?.value ?? .zero),
"currentPlaybackTime": NSNumber(value: NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value),
"atValue": currentTime?.value ?? .zero,
"currentPlaybackTime": NSNumber(value: Double(currentPlaybackTime?.timeIntervalSince1970 ?? 0 * 1000)).int64Value,
"target": reactTag,
"seekableDuration": RCTVideoUtils.calculateSeekableDuration(_player),
])
@ -1570,6 +1570,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
@objc
func handlePlayerItemDidReachEnd(notification: NSNotification!) {
sendProgressUpdate(didEnd: true)
onVideoEnd?(["target": reactTag as Any])
#if USE_GOOGLE_IMA
if notification.object as? AVPlayerItem == _player?.currentItem {