Skip to content

Commit

Permalink
fix: replay button broken for native playback (#8142)
Browse files Browse the repository at this point in the history
* fix: replay button broken for native playback

* remove debug logging

* move fix to player

* comment

* add unit test

* add native browser stubs

* reset stubs and test currentTime
  • Loading branch information
adrums86 authored Mar 6, 2023
1 parent 2a99a78 commit b7116be
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2320,6 +2320,7 @@ class Player extends Component {
this.playCallbacks_.push(callback);

const isSrcReady = Boolean(!this.changingSrc_ && (this.src() || this.currentSrc()));
const isSafariOrIOS = Boolean(browser.IS_ANY_SAFARI || browser.IS_IOS);

// treat calls to play_ somewhat like the `one` event function
if (this.waitToPlay_) {
Expand All @@ -2337,7 +2338,7 @@ class Player extends Component {

// if we are in Safari, there is a high chance that loadstart will trigger after the gesture timeperiod
// in that case, we need to prime the video element by calling load so it'll be ready in time
if (!isSrcReady && (browser.IS_ANY_SAFARI || browser.IS_IOS)) {
if (!isSrcReady && isSafariOrIOS) {
this.load();
}
return;
Expand All @@ -2346,6 +2347,12 @@ class Player extends Component {
// If the player/tech is ready and we have a source, we can attempt playback.
const val = this.techGet_('play');

// For native playback, reset the progress bar if we get a play call from a replay.
const isNativeReplay = isSafariOrIOS && this.hasClass('vjs-ended');

if (isNativeReplay) {
this.resetProgressBar_();
}
// play was terminated if the returned value is null
if (val === null) {
this.runPlayTerminatedQueue_();
Expand Down
33 changes: 33 additions & 0 deletions test/unit/player-play.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sinon from 'sinon';
import {silencePromise} from '../../src/js/utils/promise';
import TestHelpers from './test-helpers';
import * as browser from '../../src/js/utils/browser.js';

QUnit.module('Player#play', {

Expand Down Expand Up @@ -104,3 +105,35 @@ QUnit.test('tech ready + has source + changing source = wait for loadstart', fun
this.player.trigger('loadstart');
assert.strictEqual(this.techPlayCallCount, 1, 'tech_.play was called');
});

QUnit.test('play call from native replay calls resetProgressBar_', function(assert) {
const origSafari = browser.IS_ANY_SAFARI;
const origIOS = browser.IS_IOS;

browser.stub_IS_ANY_SAFARI(true);

// Mock the player having a source.
this.player.src('xyz.mp4');
this.clock.tick(100);

// Attempt to play, but silence the promise that might be returned.
silencePromise(this.player.play());
assert.strictEqual(this.techPlayCallCount, 1, 'tech_.play was called');

// add vjs-ended for replay logic and play again.
this.player.addClass('vjs-ended');

silencePromise(this.player.play());
assert.strictEqual(this.techPlayCallCount, 2, 'tech_.play was called');
assert.strictEqual(this.techCurrentTimeCallCount, 1, 'tech_.currentTime was called');

// Reset safari stub and try replay in iOS.
browser.stub_IS_ANY_SAFARI(origSafari);
browser.stub_IS_IOS(true);

silencePromise(this.player.play());
assert.strictEqual(this.techPlayCallCount, 3, 'tech_.play was called');
assert.strictEqual(this.techCurrentTimeCallCount, 2, 'tech_.currentTime was called');

browser.stub_IS_IOS(origIOS);
});

0 comments on commit b7116be

Please sign in to comment.