diff --git a/src/js/player.js b/src/js/player.js index 49ea24d08c..f03cbfb144 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -2388,6 +2388,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_) { @@ -2405,7 +2406,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; @@ -2414,6 +2415,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_(); diff --git a/test/unit/player-play.test.js b/test/unit/player-play.test.js index c63b50ec7a..439e5df647 100644 --- a/test/unit/player-play.test.js +++ b/test/unit/player-play.test.js @@ -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', { @@ -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); +});