From b06b136e18e2d016e3e6eed9bb09ef6a99b2dc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=CC=81lvaro=20Velad=20Galva=CC=81n?= Date: Tue, 28 Nov 2023 12:50:48 +0100 Subject: [PATCH 1/2] feat(UI): Add double tap to forward/rewind in the video --- build/types/ui | 2 + ui/controls.js | 43 +++++++++++ ui/externs/ui.js | 13 +++- ui/hidden_fast_forward_button.js | 119 +++++++++++++++++++++++++++++++ ui/hidden_rewind_button.js | 117 ++++++++++++++++++++++++++++++ ui/less/buttons.less | 50 +++++++++++++ ui/less/containers.less | 18 +++++ ui/ui.js | 2 + 8 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 ui/hidden_fast_forward_button.js create mode 100644 ui/hidden_rewind_button.js diff --git a/build/types/ui b/build/types/ui index c8bca18a49..4700e91320 100644 --- a/build/types/ui +++ b/build/types/ui @@ -16,6 +16,8 @@ +../../ui/element.js +../../ui/fast_forward_button.js +../../ui/fullscreen_button.js ++../../ui/hidden_fast_forward_button.js ++../../ui/hidden_rewind_button.js +../../ui/language_utils.js +../../ui/localization.js +../../ui/loop_button.js diff --git a/ui/controls.js b/ui/controls.js index 14806f7f59..2b3700a37d 100644 --- a/ui/controls.js +++ b/ui/controls.js @@ -16,6 +16,8 @@ goog.require('shaka.ui.AdCounter'); goog.require('shaka.ui.AdPosition'); goog.require('shaka.ui.BigPlayButton'); goog.require('shaka.ui.ContextMenu'); +goog.require('shaka.ui.HiddenFastForwardButton'); +goog.require('shaka.ui.HiddenRewindButton'); goog.require('shaka.ui.Locales'); goog.require('shaka.ui.Localization'); goog.require('shaka.ui.SeekBar'); @@ -847,6 +849,11 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget { this.addBufferingSpinner_(); } + if (this.config_.seekOnTaps) { + this.addFastForwardButtonOnControlsContainer_(); + this.addRewindButtonOnControlsContainer_(); + } + this.addDaiAdContainer_(); this.addControlsButtonPanel_(); @@ -970,6 +977,42 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget { svg.appendChild(spinnerCircle); } + /** + * Add fast-forward button on Controls container for moving video some + * seconds ahead when the video is tapped more than once, video seeks ahead + * some seconds for every extra tap. + * @private + */ + addFastForwardButtonOnControlsContainer_() { + const hiddenFastForwardContainer = shaka.util.Dom.createHTMLElement('div'); + hiddenFastForwardContainer.classList.add( + 'shaka-hidden-fast-forward-container'); + this.controlsContainer_.appendChild(hiddenFastForwardContainer); + + /** @private {shaka.ui.HiddenFastForwardButton} */ + this.hiddenFastForwardButton_ = + new shaka.ui.HiddenFastForwardButton(hiddenFastForwardContainer, this); + this.elements_.push(this.hiddenFastForwardButton_); + } + + /** + * Add Rewind button on Controls container for moving video some seconds + * behind when the video is tapped more than once, video seeks behind some + * seconds for every extra tap. + * @private + */ + addRewindButtonOnControlsContainer_() { + const hiddenRewindContainer = shaka.util.Dom.createHTMLElement('div'); + hiddenRewindContainer.classList.add( + 'shaka-hidden-rewind-container'); + this.controlsContainer_.appendChild(hiddenRewindContainer); + + /** @private {shaka.ui.HiddenRewindButton} */ + this.hiddenRewindButton_ = + new shaka.ui.HiddenRewindButton(hiddenRewindContainer, this); + this.elements_.push(this.hiddenRewindButton_); + } + /** @private */ addControlsButtonPanel_() { /** @private {!HTMLElement} */ diff --git a/ui/externs/ui.js b/ui/externs/ui.js index 2eb59feaca..1d6b0c01b5 100644 --- a/ui/externs/ui.js +++ b/ui/externs/ui.js @@ -98,7 +98,9 @@ shaka.extern.UIVolumeBarColors; * keyboardLargeSeekDistance: number, * fullScreenElement: HTMLElement, * preferDocumentPictureInPicture: boolean, - * showAudioChannelCountVariants: boolean + * showAudioChannelCountVariants: boolean, + * seekOnTaps: boolean, + * tapSeekDistance: number * }} * * @property {!Array.} controlPanelElements @@ -215,6 +217,15 @@ shaka.extern.UIVolumeBarColors; * displayed or if, on the contrary, only the language should be displayed * regardless of the channel count. * Defaults to true. + * @property {boolean} seekOnTaps + * Indicates whether or not a fast-forward and rewind tap button that seeks + * video some seconds. + * Defaults to true. + * @property {number} tapSeekDistance + * The time interval, in seconds, to seek when the user presses the left or + * right part of the video. If less than or equal to 0, + * no seeking will occur. + * Defaults to 10 seconds. * @exportDoc */ shaka.extern.UIConfiguration; diff --git a/ui/hidden_fast_forward_button.js b/ui/hidden_fast_forward_button.js new file mode 100644 index 0000000000..ddc8b245f8 --- /dev/null +++ b/ui/hidden_fast_forward_button.js @@ -0,0 +1,119 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.provide('shaka.ui.HiddenFastForwardButton'); + +goog.require('shaka.ui.Element'); +goog.require('shaka.util.Timer'); +goog.require('shaka.ui.Enums'); +goog.require('shaka.util.Dom'); + +goog.requireType('shaka.ui.Controls'); + +/** + * @extends {shaka.ui.Element} + * @final + * @export + */ +shaka.ui.HiddenFastForwardButton = class extends shaka.ui.Element { + /** + * @param {!HTMLElement} parent + * @param {!shaka.ui.Controls} controls + */ + constructor(parent, controls) { + super(parent, controls); + + /** @private {?number} */ + this.lastTouchEventTimeSet_ = null; + + /** @private {?boolean} */ + this.triggeredTouchValid_ = false; + + /** + * This timer will be used to hide fast forward button on video Container. + * When the timer ticks it will force button to be invisible. + * + * @private {shaka.util.Timer} + */ + this.hideFastForwardButtonContainerTimer_ = new shaka.util.Timer(() => { + this.hideFastForwardButtonContainer_(); + }); + + + /** @private {!HTMLElement} */ + this.fastforwardContainer_ = shaka.util.Dom.createHTMLElement('div'); + this.fastforwardContainer_.classList.add( + 'shaka-fast-foward-container'); + this.parent.appendChild(this.fastforwardContainer_); + + this.eventManager.listen( + this.fastforwardContainer_, 'touchstart', (event) => { + // In case any settings menu are open this assigns the first touch + // to close the menu. + if (this.controls.anySettingsMenusAreOpen()) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.controls.hideSettingsMenus(); + } else if (this.controls.getConfig().tapSeekDistance > 0) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.onFastForwardButtonClick_(); + } + }); + + /** @private {!HTMLElement} */ + this.fastForwardValue_ = shaka.util.Dom.createHTMLElement('span'); + this.fastForwardValue_.textContent = '0s'; + this.fastforwardContainer_.appendChild(this.fastForwardValue_); + + /** @private {!HTMLElement} */ + this.fastforwardIcon_ = shaka.util.Dom.createHTMLElement('span'); + this.fastforwardIcon_.classList.add( + 'shaka-forward-rewind-container-icon'); + this.fastforwardIcon_.textContent = + shaka.ui.Enums.MaterialDesignIcons.FAST_FORWARD; + this.fastforwardContainer_.appendChild(this.fastforwardIcon_); + } + + /** + * @private + */ + onFastForwardButtonClick_() { + const tapSeekDistance = this.controls.getConfig().tapSeekDistance; + // This stores the time for first touch and makes touch valid for + // next 1s so incase the touch event is triggered again within 1s + // this if condition fails and the video seeking happens. + if (!this.triggeredTouchValid_) { + this.triggeredTouchValid_ = true; + this.lastTouchEventTimeSet_ = Date.now(); + this.hideFastForwardButtonContainerTimer_.tickAfter(1); + } else if (this.lastTouchEventTimeSet_+1000 > Date.now()) { + // stops hidding of fast-forward button incase the timmer is active + // because of previous touch event. + this.hideFastForwardButtonContainerTimer_.stop(); + this.lastTouchEventTimeSet_ = Date.now(); + const position = + parseInt(this.fastForwardValue_.textContent, 10) + tapSeekDistance; + this.fastForwardValue_.textContent = position.toString() + 's'; + this.fastforwardContainer_.style.opacity = '1'; + this.hideFastForwardButtonContainerTimer_.tickAfter(1); + } + } + + /** + * @private + */ + hideFastForwardButtonContainer_() { + // Prevent adding seek value if its a single tap. + if (parseInt(this.fastForwardValue_.textContent, 10) != 0) { + this.video.currentTime = this.controls.getDisplayTime() + parseInt( + this.fastForwardValue_.textContent, 10); + } + this.fastforwardContainer_.style.opacity = '0'; + this.triggeredTouchValid_ = false; + this.fastForwardValue_.textContent = '0s'; + } +}; diff --git a/ui/hidden_rewind_button.js b/ui/hidden_rewind_button.js new file mode 100644 index 0000000000..fc2cb2467e --- /dev/null +++ b/ui/hidden_rewind_button.js @@ -0,0 +1,117 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.provide('shaka.ui.HiddenRewindButton'); + +goog.require('shaka.ui.Element'); +goog.require('shaka.util.Timer'); +goog.require('shaka.ui.Enums'); +goog.require('shaka.util.Dom'); + +goog.requireType('shaka.ui.Controls'); + +/** + * @extends {shaka.ui.Element} + * @final + * @export + */ +shaka.ui.HiddenRewindButton = class extends shaka.ui.Element { + /** + * @param {!HTMLElement} parent + * @param {!shaka.ui.Controls} controls + */ + constructor(parent, controls) { + super(parent, controls); + + /** @private {?number} */ + this.lastTouchEventTimeSet_ = null; + + /** @private {?boolean} */ + this.triggeredTouchValid_ = false; + + /** + * This timer will be used to hide rewind button on video Container. + * When the timer ticks it will force button to be invisible. + * + * @private {shaka.util.Timer} + */ + this.hideRewindButtonContainerTimer_ = new shaka.util.Timer(() => { + this.hideRewindButtonContainer_(); + }); + + /** @private {!HTMLElement} */ + this.rewindContainer_ = shaka.util.Dom.createHTMLElement('div'); + this.rewindContainer_.classList.add( + 'shaka-rewind-container'); + this.parent.appendChild(this.rewindContainer_); + + this.eventManager.listen(this.rewindContainer_, 'touchstart', (event) => { + // In case any settings menu are open this assigns the first touch + // to close the menu. + if (this.controls.anySettingsMenusAreOpen()) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.controls.hideSettingsMenus(); + } else if (this.controls.getConfig().tapSeekDistance > 0) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.onRewindButtonClick_(); + } + }); + + /** @private {!HTMLElement} */ + this.rewindValue_ = shaka.util.Dom.createHTMLElement('span'); + this.rewindValue_.textContent = '0s'; + this.rewindContainer_.appendChild(this.rewindValue_); + + /** @private {!HTMLElement} */ + this.rewindIcon_ = shaka.util.Dom.createHTMLElement('span'); + this.rewindIcon_.classList.add( + 'shaka-forward-rewind-container-icon'); + this.rewindIcon_.textContent = + shaka.ui.Enums.MaterialDesignIcons.REWIND; + this.rewindContainer_.appendChild(this.rewindIcon_); + } + + /** + * @private + */ + onRewindButtonClick_() { + const tapSeekDistance = this.controls.getConfig().tapSeekDistance; + // This stores the time for first touch and makes touch valid for + // next 1s so incase the touch event is triggered again within 1s + // this if condition fails and the video seeking happens. + if (!this.triggeredTouchValid_) { + this.triggeredTouchValid_ = true; + this.lastTouchEventTimeSet_ = Date.now(); + this.hideRewindButtonContainerTimer_.tickAfter(1); + } else if (this.lastTouchEventTimeSet_+1000 > Date.now()) { + // stops hidding of fast-forward button incase the timmer is active + // because of previous touch event. + this.hideRewindButtonContainerTimer_.stop(); + this.lastTouchEventTimeSet_ = Date.now(); + const position = + parseInt(this.rewindValue_.textContent, 10) - tapSeekDistance; + this.rewindValue_.textContent = position.toString() + 's'; + this.rewindContainer_.style.opacity = '1'; + this.hideRewindButtonContainerTimer_.tickAfter(1); + } + } + + /** + * @private + */ + hideRewindButtonContainer_() { + // Prevent adding seek value if its a single tap. + if (parseInt(this.rewindValue_.textContent, 10) != 0) { + this.video.currentTime = this.controls.getDisplayTime() + parseInt( + this.rewindValue_.textContent, 10); + } + this.rewindContainer_.style.opacity = '0'; + this.triggeredTouchValid_ = false; + this.rewindValue_.textContent = '0s'; + } +}; diff --git a/ui/less/buttons.less b/ui/less/buttons.less index fe9682df9e..a415db9a2d 100644 --- a/ui/less/buttons.less +++ b/ui/less/buttons.less @@ -106,3 +106,53 @@ outline: none; } } + +.shaka-fast-foward-container, +.shaka-rewind-container { + height: 100%; + width: 100%; + .shrinkable(); + .absolute-position(); + + /* Keep all the elements inside button div in center and in row */ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + + /* To be properly positioned, this should have no margin. */ + margin: 0; + + /* No border. */ + border: none; + + /* Setting text color to white */ + color: rgb(255 255 255); + + /* Setting background color to black so white text can be seen clearly */ + background-color: rgb(0 0 0 / 50%); + + cursor: default; + font-size: 20px; + + /* Hidding the container by setting opacity */ + opacity: 0; + + /* Make the text inside this button unselectable */ + .unselectable(); +} + +.shaka-fast-foward-container { + border-radius: 40% 0 0 40%; +} + +.shaka-rewind-container { + border-radius: 0 40% 40% 0; +} + +/* This class is instead of material-icon-round + * because the font-size of 24 doesn't look good */ +.shaka-forward-rewind-container-icon { + font-family: "Material Icons Round"; + font-size: 34px; +} diff --git a/ui/less/containers.less b/ui/less/containers.less index 253189f88a..a246b66a69 100644 --- a/ui/less/containers.less +++ b/ui/less/containers.less @@ -365,3 +365,21 @@ on a black background. */ filter: drop-shadow(0 0 2px rgba(255 255 255 / 50%)); } + +.shaka-hidden-fast-forward-container, +.shaka-hidden-rewind-container { + height: 100%; + width: 40%; + .shrinkable(); +} + +.shaka-hidden-fast-forward-container { + /* Keep the fast forward button to the right of this container. */ + .absolute-position(); + left: 60%; +} + +.shaka-hidden-rewind-container { + /* keep the rewind button to the left */ + .absolute-position(); +} diff --git a/ui/ui.js b/ui/ui.js index 166f43da13..222f2d7672 100644 --- a/ui/ui.js +++ b/ui/ui.js @@ -249,6 +249,8 @@ shaka.ui.Overlay = class { fullScreenElement: this.videoContainer_, preferDocumentPictureInPicture: true, showAudioChannelCountVariants: true, + seekOnTaps: true, + tapSeekDistance: 10, }; // eslint-disable-next-line no-restricted-syntax From adf801c25f16e33078f9ff1cd0f8654d3e161bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=CC=81lvaro=20Velad=20Galva=CC=81n?= Date: Wed, 29 Nov 2023 08:30:50 +0100 Subject: [PATCH 2/2] Add superclass --- build/types/ui | 1 + ui/hidden_fast_forward_button.js | 99 ++----------------------- ui/hidden_rewind_button.js | 97 ++----------------------- ui/hidden_seek_button.js | 121 +++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 184 deletions(-) create mode 100644 ui/hidden_seek_button.js diff --git a/build/types/ui b/build/types/ui index 4700e91320..547498ad49 100644 --- a/build/types/ui +++ b/build/types/ui @@ -18,6 +18,7 @@ +../../ui/fullscreen_button.js +../../ui/hidden_fast_forward_button.js +../../ui/hidden_rewind_button.js ++../../ui/hidden_seek_button.js +../../ui/language_utils.js +../../ui/localization.js +../../ui/loop_button.js diff --git a/ui/hidden_fast_forward_button.js b/ui/hidden_fast_forward_button.js index ddc8b245f8..27e216d03d 100644 --- a/ui/hidden_fast_forward_button.js +++ b/ui/hidden_fast_forward_button.js @@ -6,19 +6,17 @@ goog.provide('shaka.ui.HiddenFastForwardButton'); -goog.require('shaka.ui.Element'); -goog.require('shaka.util.Timer'); goog.require('shaka.ui.Enums'); -goog.require('shaka.util.Dom'); +goog.require('shaka.ui.HiddenSeekButton'); goog.requireType('shaka.ui.Controls'); /** - * @extends {shaka.ui.Element} + * @extends {shaka.ui.HiddenSeekButton} * @final * @export */ -shaka.ui.HiddenFastForwardButton = class extends shaka.ui.Element { +shaka.ui.HiddenFastForwardButton = class extends shaka.ui.HiddenSeekButton { /** * @param {!HTMLElement} parent * @param {!shaka.ui.Controls} controls @@ -26,94 +24,9 @@ shaka.ui.HiddenFastForwardButton = class extends shaka.ui.Element { constructor(parent, controls) { super(parent, controls); - /** @private {?number} */ - this.lastTouchEventTimeSet_ = null; - - /** @private {?boolean} */ - this.triggeredTouchValid_ = false; - - /** - * This timer will be used to hide fast forward button on video Container. - * When the timer ticks it will force button to be invisible. - * - * @private {shaka.util.Timer} - */ - this.hideFastForwardButtonContainerTimer_ = new shaka.util.Timer(() => { - this.hideFastForwardButtonContainer_(); - }); - - - /** @private {!HTMLElement} */ - this.fastforwardContainer_ = shaka.util.Dom.createHTMLElement('div'); - this.fastforwardContainer_.classList.add( - 'shaka-fast-foward-container'); - this.parent.appendChild(this.fastforwardContainer_); - - this.eventManager.listen( - this.fastforwardContainer_, 'touchstart', (event) => { - // In case any settings menu are open this assigns the first touch - // to close the menu. - if (this.controls.anySettingsMenusAreOpen()) { - // prevent the default changes that browser triggers - event.preventDefault(); - this.controls.hideSettingsMenus(); - } else if (this.controls.getConfig().tapSeekDistance > 0) { - // prevent the default changes that browser triggers - event.preventDefault(); - this.onFastForwardButtonClick_(); - } - }); - - /** @private {!HTMLElement} */ - this.fastForwardValue_ = shaka.util.Dom.createHTMLElement('span'); - this.fastForwardValue_.textContent = '0s'; - this.fastforwardContainer_.appendChild(this.fastForwardValue_); - - /** @private {!HTMLElement} */ - this.fastforwardIcon_ = shaka.util.Dom.createHTMLElement('span'); - this.fastforwardIcon_.classList.add( - 'shaka-forward-rewind-container-icon'); - this.fastforwardIcon_.textContent = + this.seekContainer.classList.add('shaka-fast-foward-container'); + this.seekIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.FAST_FORWARD; - this.fastforwardContainer_.appendChild(this.fastforwardIcon_); - } - - /** - * @private - */ - onFastForwardButtonClick_() { - const tapSeekDistance = this.controls.getConfig().tapSeekDistance; - // This stores the time for first touch and makes touch valid for - // next 1s so incase the touch event is triggered again within 1s - // this if condition fails and the video seeking happens. - if (!this.triggeredTouchValid_) { - this.triggeredTouchValid_ = true; - this.lastTouchEventTimeSet_ = Date.now(); - this.hideFastForwardButtonContainerTimer_.tickAfter(1); - } else if (this.lastTouchEventTimeSet_+1000 > Date.now()) { - // stops hidding of fast-forward button incase the timmer is active - // because of previous touch event. - this.hideFastForwardButtonContainerTimer_.stop(); - this.lastTouchEventTimeSet_ = Date.now(); - const position = - parseInt(this.fastForwardValue_.textContent, 10) + tapSeekDistance; - this.fastForwardValue_.textContent = position.toString() + 's'; - this.fastforwardContainer_.style.opacity = '1'; - this.hideFastForwardButtonContainerTimer_.tickAfter(1); - } - } - - /** - * @private - */ - hideFastForwardButtonContainer_() { - // Prevent adding seek value if its a single tap. - if (parseInt(this.fastForwardValue_.textContent, 10) != 0) { - this.video.currentTime = this.controls.getDisplayTime() + parseInt( - this.fastForwardValue_.textContent, 10); - } - this.fastforwardContainer_.style.opacity = '0'; - this.triggeredTouchValid_ = false; - this.fastForwardValue_.textContent = '0s'; + this.isRewind = false; } }; diff --git a/ui/hidden_rewind_button.js b/ui/hidden_rewind_button.js index fc2cb2467e..257a119dd7 100644 --- a/ui/hidden_rewind_button.js +++ b/ui/hidden_rewind_button.js @@ -6,19 +6,17 @@ goog.provide('shaka.ui.HiddenRewindButton'); -goog.require('shaka.ui.Element'); -goog.require('shaka.util.Timer'); goog.require('shaka.ui.Enums'); -goog.require('shaka.util.Dom'); +goog.require('shaka.ui.HiddenSeekButton'); goog.requireType('shaka.ui.Controls'); /** - * @extends {shaka.ui.Element} + * @extends {shaka.ui.HiddenSeekButton} * @final * @export */ -shaka.ui.HiddenRewindButton = class extends shaka.ui.Element { +shaka.ui.HiddenRewindButton = class extends shaka.ui.HiddenSeekButton { /** * @param {!HTMLElement} parent * @param {!shaka.ui.Controls} controls @@ -26,92 +24,9 @@ shaka.ui.HiddenRewindButton = class extends shaka.ui.Element { constructor(parent, controls) { super(parent, controls); - /** @private {?number} */ - this.lastTouchEventTimeSet_ = null; - - /** @private {?boolean} */ - this.triggeredTouchValid_ = false; - - /** - * This timer will be used to hide rewind button on video Container. - * When the timer ticks it will force button to be invisible. - * - * @private {shaka.util.Timer} - */ - this.hideRewindButtonContainerTimer_ = new shaka.util.Timer(() => { - this.hideRewindButtonContainer_(); - }); - - /** @private {!HTMLElement} */ - this.rewindContainer_ = shaka.util.Dom.createHTMLElement('div'); - this.rewindContainer_.classList.add( - 'shaka-rewind-container'); - this.parent.appendChild(this.rewindContainer_); - - this.eventManager.listen(this.rewindContainer_, 'touchstart', (event) => { - // In case any settings menu are open this assigns the first touch - // to close the menu. - if (this.controls.anySettingsMenusAreOpen()) { - // prevent the default changes that browser triggers - event.preventDefault(); - this.controls.hideSettingsMenus(); - } else if (this.controls.getConfig().tapSeekDistance > 0) { - // prevent the default changes that browser triggers - event.preventDefault(); - this.onRewindButtonClick_(); - } - }); - - /** @private {!HTMLElement} */ - this.rewindValue_ = shaka.util.Dom.createHTMLElement('span'); - this.rewindValue_.textContent = '0s'; - this.rewindContainer_.appendChild(this.rewindValue_); - - /** @private {!HTMLElement} */ - this.rewindIcon_ = shaka.util.Dom.createHTMLElement('span'); - this.rewindIcon_.classList.add( - 'shaka-forward-rewind-container-icon'); - this.rewindIcon_.textContent = + this.seekContainer.classList.add('shaka-rewind-container'); + this.seekIcon.textContent = shaka.ui.Enums.MaterialDesignIcons.REWIND; - this.rewindContainer_.appendChild(this.rewindIcon_); - } - - /** - * @private - */ - onRewindButtonClick_() { - const tapSeekDistance = this.controls.getConfig().tapSeekDistance; - // This stores the time for first touch and makes touch valid for - // next 1s so incase the touch event is triggered again within 1s - // this if condition fails and the video seeking happens. - if (!this.triggeredTouchValid_) { - this.triggeredTouchValid_ = true; - this.lastTouchEventTimeSet_ = Date.now(); - this.hideRewindButtonContainerTimer_.tickAfter(1); - } else if (this.lastTouchEventTimeSet_+1000 > Date.now()) { - // stops hidding of fast-forward button incase the timmer is active - // because of previous touch event. - this.hideRewindButtonContainerTimer_.stop(); - this.lastTouchEventTimeSet_ = Date.now(); - const position = - parseInt(this.rewindValue_.textContent, 10) - tapSeekDistance; - this.rewindValue_.textContent = position.toString() + 's'; - this.rewindContainer_.style.opacity = '1'; - this.hideRewindButtonContainerTimer_.tickAfter(1); - } - } - - /** - * @private - */ - hideRewindButtonContainer_() { - // Prevent adding seek value if its a single tap. - if (parseInt(this.rewindValue_.textContent, 10) != 0) { - this.video.currentTime = this.controls.getDisplayTime() + parseInt( - this.rewindValue_.textContent, 10); - } - this.rewindContainer_.style.opacity = '0'; - this.triggeredTouchValid_ = false; - this.rewindValue_.textContent = '0s'; + this.isRewind = true; } }; diff --git a/ui/hidden_seek_button.js b/ui/hidden_seek_button.js new file mode 100644 index 0000000000..5ea5138936 --- /dev/null +++ b/ui/hidden_seek_button.js @@ -0,0 +1,121 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +goog.provide('shaka.ui.HiddenSeekButton'); + +goog.require('shaka.ui.Element'); +goog.require('shaka.util.Timer'); +goog.require('shaka.util.Dom'); + +goog.requireType('shaka.ui.Controls'); + +/** + * @extends {shaka.ui.Element} + * @export + */ +shaka.ui.HiddenSeekButton = class extends shaka.ui.Element { + /** + * @param {!HTMLElement} parent + * @param {!shaka.ui.Controls} controls + */ + constructor(parent, controls) { + super(parent, controls); + + /** @private {?number} */ + this.lastTouchEventTimeSet_ = null; + + /** @private {?boolean} */ + this.triggeredTouchValid_ = false; + + /** + * This timer will be used to hide seek button on video Container. + * When the timer ticks it will force button to be invisible. + * + * @private {shaka.util.Timer} + */ + this.hideSeekButtonContainerTimer_ = new shaka.util.Timer(() => { + this.hideSeekButtonContainer_(); + }); + + /** @protected {!HTMLElement} */ + this.seekContainer = shaka.util.Dom.createHTMLElement('div'); + this.parent.appendChild(this.seekContainer); + + this.eventManager.listen(this.seekContainer, 'touchstart', (event) => { + // In case any settings menu are open this assigns the first touch + // to close the menu. + if (this.controls.anySettingsMenusAreOpen()) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.controls.hideSettingsMenus(); + } else if (this.controls.getConfig().tapSeekDistance > 0) { + // prevent the default changes that browser triggers + event.preventDefault(); + this.onSeekButtonClick_(); + } + }); + + /** @private {!HTMLElement} */ + this.seekValue_ = shaka.util.Dom.createHTMLElement('span'); + this.seekValue_.textContent = '0s'; + this.seekContainer.appendChild(this.seekValue_); + + + /** @protected {!HTMLElement} */ + this.seekIcon = shaka.util.Dom.createHTMLElement('span'); + this.seekIcon.classList.add( + 'shaka-forward-rewind-container-icon'); + this.seekContainer.appendChild(this.seekIcon); + + /** @protected {boolean} */ + this.isRewind = false; + } + + /** + * @private + */ + onSeekButtonClick_() { + const tapSeekDistance = this.controls.getConfig().tapSeekDistance; + // This stores the time for first touch and makes touch valid for + // next 1s so incase the touch event is triggered again within 1s + // this if condition fails and the video seeking happens. + if (!this.triggeredTouchValid_) { + this.triggeredTouchValid_ = true; + this.lastTouchEventTimeSet_ = Date.now(); + this.hideSeekButtonContainerTimer_.tickAfter(1); + } else if (this.lastTouchEventTimeSet_+1000 > Date.now()) { + // stops hidding of seek button incase the timmer is active + // because of previous touch event. + this.hideSeekButtonContainerTimer_.stop(); + this.lastTouchEventTimeSet_ = Date.now(); + let position = 0; + if (this.isRewind) { + position = + parseInt(this.seekValue_.textContent, 10) - tapSeekDistance; + } else { + position = + parseInt(this.seekValue_.textContent, 10) + tapSeekDistance; + } + this.seekValue_.textContent = position.toString() + 's'; + this.seekContainer.style.opacity = '1'; + this.hideSeekButtonContainerTimer_.tickAfter(1); + } + } + + /** + * @private + */ + hideSeekButtonContainer_() { + // Prevent adding seek value if its a single tap. + if (parseInt(this.seekValue_.textContent, 10) != 0) { + this.video.currentTime = this.controls.getDisplayTime() + parseInt( + this.seekValue_.textContent, 10); + } + this.seekContainer.style.opacity = '0'; + this.triggeredTouchValid_ = false; + this.seekValue_.textContent = '0s'; + } +};