From 11de73b7dacec5bbd4fab6ef8610342a84a0bb29 Mon Sep 17 00:00:00 2001 From: amtins Date: Fri, 19 May 2023 16:44:55 +0200 Subject: [PATCH] feat: add an option to handle smooth seeking --- .../control-bar/progress-control/seek-bar.js | 4 ++ .../control-bar/time-controls/time-display.js | 16 ++++- src/js/player.js | 4 +- test/unit/player.test.js | 63 +++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/js/control-bar/progress-control/seek-bar.js b/src/js/control-bar/progress-control/seek-bar.js index 75bab62894..ad0f452ed2 100644 --- a/src/js/control-bar/progress-control/seek-bar.js +++ b/src/js/control-bar/progress-control/seek-bar.js @@ -324,6 +324,10 @@ class SeekBar extends Slider { // Set new time (tell player to seek to new time) this.userSeek_(newTime); + + if (this.player_.options_.enableSmoothSeeking) { + this.update(); + } } enable() { diff --git a/src/js/control-bar/time-controls/time-display.js b/src/js/control-bar/time-controls/time-display.js index fb9a0ffeeb..9c6af2d0f4 100644 --- a/src/js/control-bar/time-controls/time-display.js +++ b/src/js/control-bar/time-controls/time-display.js @@ -26,7 +26,7 @@ class TimeDisplay extends Component { constructor(player, options) { super(player, options); - this.on(player, ['timeupdate', 'ended'], (e) => this.updateContent(e)); + this.on(player, ['timeupdate', 'ended', 'seeking'], (e) => this.update(e)); this.updateTextNode_(); } @@ -71,6 +71,20 @@ class TimeDisplay extends Component { super.dispose(); } + /** + * Updates the displayed time according to the `updateContent` function which is defined in the child class. + * + * @param {Event} [event] + * The `timeupdate`, `ended` or `seeking` (if enableSmoothSeeking is true) event that caused this function to be called. + */ + update(event) { + if (!this.player_.options_.enableSmoothSeeking && event.type === 'seeking') { + return; + } + + this.updateContent(event); + } + /** * Updates the time display text node with a new time * diff --git a/src/js/player.js b/src/js/player.js index e516d7aea1..dca1c9e607 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -5290,7 +5290,9 @@ Player.prototype.options_ = { breakpoints: {}, responsive: false, audioOnlyMode: false, - audioPosterMode: false + audioPosterMode: false, + // Default smooth seeking to false + enableSmoothSeeking: false }; [ diff --git a/test/unit/player.test.js b/test/unit/player.test.js index d8f9534263..7cd731f6f2 100644 --- a/test/unit/player.test.js +++ b/test/unit/player.test.js @@ -3349,3 +3349,66 @@ QUnit.test('crossOrigin value should be maintained after loadMedia is called', f playerExample2.dispose(); playerExample3.dispose(); }); + +QUnit.test('smooth seeking set to false should not update the display time components or the seek bar', function(assert) { + const player = TestHelpers.makePlayer({}); + const { + currentTimeDisplay, + remainingTimeDisplay, + progressControl: { + seekBar + } + } = player.controlBar; + const currentTimeDisplayUpdateContent = sinon.spy(currentTimeDisplay, 'updateContent'); + const remainingTimeDisplayUpdateContent = sinon.spy(remainingTimeDisplay, 'updateContent'); + const seekBarUpdate = sinon.spy(seekBar, 'update'); + + assert.false(player.options().enableSmoothSeeking, 'enableSmoothSeeking is false by default'); + + player.trigger('seeking'); + + assert.ok(currentTimeDisplayUpdateContent.notCalled, 'currentTimeDisplay updateContent was not called'); + assert.ok(remainingTimeDisplayUpdateContent.notCalled, 'currentTimeDisplay updateContent was not called'); + + seekBar.trigger('mousedown'); + seekBar.trigger('mousemove'); + + assert.ok(seekBarUpdate.notCalled, 'seekBar update was not called'); + + currentTimeDisplayUpdateContent.restore(); + remainingTimeDisplayUpdateContent.restore(); + seekBarUpdate.restore(); + player.dispose(); +}); + +QUnit.test('smooth seeking set to true should update the display time components and the seek bar', function(assert) { + const player = TestHelpers.makePlayer({enableSmoothSeeking: true}); + const { + currentTimeDisplay, + remainingTimeDisplay, + progressControl: { + seekBar + } + } = player.controlBar; + const currentTimeDisplayUpdateContent = sinon.spy(currentTimeDisplay, 'updateContent'); + const remainingTimeDisplayUpdateContent = sinon.spy(remainingTimeDisplay, 'updateContent'); + const seekBarUpdate = sinon.spy(seekBar, 'update'); + + assert.true(player.options().enableSmoothSeeking, 'enableSmoothSeeking is true'); + + player.duration(1); + player.trigger('seeking'); + + assert.ok(currentTimeDisplayUpdateContent.called, 'currentTimeDisplay updateContent was called'); + assert.ok(remainingTimeDisplayUpdateContent.called, 'remainingTimeDisplay updateContent was called'); + + seekBar.trigger('mousedown'); + seekBar.trigger('mousemove'); + + assert.ok(seekBarUpdate.called, 'seekBar update was called'); + + currentTimeDisplayUpdateContent.restore(); + remainingTimeDisplayUpdateContent.restore(); + seekBarUpdate.restore(); + player.dispose(); +});