Skip to content

Commit

Permalink
feat: Improve currentTime to allow it to be called before player is r…
Browse files Browse the repository at this point in the history
…eady (videojs#6507)

In the cases where the player isn't ready, or we are in the middle of changing sources, we will wait for `canplay` and then seek to the provided time without requiring Video.js users to handle this themselves.

Co-authored-by: Marco Garay <[email protected]>
  • Loading branch information
marcosmx and marcosmx authored Mar 25, 2020
1 parent 4a82283 commit 768adb1
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,7 @@ class Player extends Component {
// we set it to zero here to ensure that if we do start actually caching
// it, we reset it along with everything else.
currentTime: 0,
initTime: 0,
inactivityTimeout: this.options_.inactivityTimeout,
duration: NaN,
lastVolume: 1,
Expand Down Expand Up @@ -2416,7 +2417,14 @@ class Player extends Component {
if (seconds < 0) {
seconds = 0;
}
if (!this.isReady_ || this.changingSrc_ || !this.tech_ || !this.tech_.isReady_) {
this.cache_.initTime = seconds;
this.off('canplay', this.applyInitTime_);
this.one('canplay', this.applyInitTime_);
return;
}
this.techCall_('setCurrentTime', seconds);
this.cache_.initTime = 0;
return;
}

Expand All @@ -2430,6 +2438,15 @@ class Player extends Component {
return this.cache_.currentTime;
}

/**
* Apply the value of initTime stored in cache as currentTime.
*
* @private
*/
applyInitTime_() {
this.currentTime(this.cache_.initTime);
}

/**
* Normally gets the length in time of the video in seconds;
* in all but the rarest use cases an argument will NOT be passed to the method
Expand Down
6 changes: 6 additions & 0 deletions test/unit/player-play.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ QUnit.module('Player#play', {
this.clock = sinon.useFakeTimers();
this.player = TestHelpers.makePlayer({});
this.techPlayCallCount = 0;
this.techCurrentTimeCallCount = 0;
this.initTime = 0;
this.player.tech_.play = () => {
this.techPlayCallCount++;
};
this.player.tech_.setCurrentTime = (seconds) => {
this.techCurrentTimeCallCount++;
this.initTime = seconds;
};
},

afterEach() {
Expand Down
28 changes: 28 additions & 0 deletions test/unit/player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2213,3 +2213,31 @@ QUnit.test('controlBar behaviour with mouseenter and mouseleave events', functio

player.dispose();
});

QUnit.test('Should be able to set a currentTime after player initialization as soon the canplay event is fired', function(assert) {
const player = TestHelpers.makePlayer({});

player.src('xyz.mp4');
player.currentTime(500);
assert.strictEqual(player.currentTime(), 0, 'currentTime value was not changed');
this.clock.tick(100);
player.trigger('canplay');
assert.strictEqual(player.currentTime(), 500, 'currentTime value is the one passed after initialization');
});

QUnit.test('Should accept multiple calls to currentTime after player initialization and apply the last value as soon the canplay event is fired', function(assert) {
const player = TestHelpers.makePlayer({});
const spyInitTime = sinon.spy(player, 'applyInitTime_');
const spyCurrentTime = sinon.spy(player, 'currentTime');

player.src('xyz.mp4');
player.currentTime(500);
player.currentTime(600);
player.currentTime(700);
player.currentTime(800);
this.clock.tick(100);
player.trigger('canplay');
assert.equal(spyInitTime.callCount, 1, 'After multiple calls to currentTime just apply the last one');
assert.ok(spyCurrentTime.calledAfter(spyInitTime), 'currentTime was called on canplay event listener');
assert.equal(player.currentTime(), 800, 'The last value passed is stored as the currentTime value');
});

0 comments on commit 768adb1

Please sign in to comment.