Playback-rate: fix popup behavior (#1650)
* Playback-rate: fix popup behavior - Part of 1637 - invokes the popup menu when clicked. - This also makes the button consistent with other `MenuButton`s, i.e. to invoke a menu popup when clicked instead of hovered. * Adjust CSS Co-authored-by: Raphael Wickihalder <raphael.wickihalder@odysee.com>
This commit is contained in:
parent
d5b7f25191
commit
d3365d69f9
3 changed files with 119 additions and 1 deletions
|
@ -0,0 +1,95 @@
|
|||
import videojs from 'video.js';
|
||||
|
||||
const IS_DEV = process.env.NODE_ENV !== 'production';
|
||||
const CONTROL_BAR = 'ControlBar';
|
||||
const PLAYBACK_RATE_MENU_BUTTON = 'PlaybackRateMenuButton';
|
||||
const MENU = 'Menu';
|
||||
|
||||
const Menu = videojs.getComponent(MENU);
|
||||
const PlaybackRateMenuButton = videojs.getComponent(PLAYBACK_RATE_MENU_BUTTON);
|
||||
|
||||
class LbryPlaybackRateMenuButton extends PlaybackRateMenuButton {
|
||||
static replaceExisting(player) {
|
||||
try {
|
||||
const controlBar = player.getChild(CONTROL_BAR);
|
||||
const playbackRateMenuButton = controlBar.getChild(PLAYBACK_RATE_MENU_BUTTON);
|
||||
controlBar.removeChild(playbackRateMenuButton);
|
||||
controlBar.addChild(new LbryPlaybackRateMenuButton(player));
|
||||
} catch (error) {
|
||||
if (IS_DEV) throw Error('\n\nvideojs.jsx: Playback rate hierarchy changed?\n\n' + error);
|
||||
}
|
||||
}
|
||||
|
||||
constructor(player, options = {}) {
|
||||
super(player, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default behavior cycles through the selection, while the popup is
|
||||
* invoked by hover. We have removed the hover behavior (1637) since it is
|
||||
* annoying when accidentally hovered, and it's also needed to address a
|
||||
* z-order issue.
|
||||
*
|
||||
* With the hover behavior gone, we need to override the default click
|
||||
* behavior to invoke the popup instead of cycling through the settings.
|
||||
*
|
||||
* Ref: https://github.com/videojs/video.js/issues/3394#issuecomment-230793773
|
||||
* @param event
|
||||
*/
|
||||
handleClick(event) {
|
||||
if (this.buttonPressed_) {
|
||||
this.unpressButton();
|
||||
} else {
|
||||
this.pressButton();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The default menu behavior is to dismiss the popup when losing focus, unless
|
||||
* the new focus is on the associated button. The associated button is
|
||||
* specifically defined as the first child, but PlaybackRateMenuButton
|
||||
* implements it as the second child.
|
||||
*
|
||||
* Fixed by reversing the check to use `relatedTarget.parentElement` instead.
|
||||
* It shouldn't matter which sub-element was clicked, as long as it's part of
|
||||
* the button.
|
||||
*
|
||||
* @param event
|
||||
* @param menu
|
||||
*/
|
||||
handleMenuBlur(event, menu) {
|
||||
const relatedTarget = event.relatedTarget || document.activeElement;
|
||||
|
||||
if (
|
||||
!menu.children().some((element) => {
|
||||
return element.el() === relatedTarget;
|
||||
})
|
||||
) {
|
||||
const btn = menu.menuButton_;
|
||||
if (btn && btn.buttonPressed_ && relatedTarget.parentElement !== btn.el()) {
|
||||
btn.unpressButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createMenu() {
|
||||
const menu = new Menu(this.player_, { menuButton: this });
|
||||
|
||||
// Override the original with ours. Must be done after the constructor
|
||||
// is called, as that is where `boundHandleBlur_` is originally set.
|
||||
menu.boundHandleBlur_ = (e) => this.handleMenuBlur(e, menu);
|
||||
|
||||
this.hideThreshold_ = 0; // Must reset. See `MenuButton::createMenu` notes.
|
||||
this.items = this.createItems();
|
||||
|
||||
if (this.items) {
|
||||
for (let i = 0; i < this.items.length; ++i) {
|
||||
menu.addItem(this.items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
export default LbryPlaybackRateMenuButton;
|
|
@ -16,6 +16,7 @@ import eventTracking from 'videojs-event-tracking';
|
|||
import functions from './videojs-functions';
|
||||
import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
||||
import keyboardShorcuts from './videojs-shortcuts';
|
||||
import LbryPlaybackRateMenuButton from './lbry-playback-rate';
|
||||
import LbryVolumeBarClass from './lbry-volume-bar';
|
||||
import Chromecast from './chromecast';
|
||||
import playerjs from 'player.js';
|
||||
|
@ -278,8 +279,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
|||
|
||||
// runAds(internalFeatureEnabled, allowPreRoll, player, embedded);
|
||||
|
||||
// Replace volume bar with custom LBRY volume bar
|
||||
LbryVolumeBarClass.replaceExisting(player);
|
||||
LbryPlaybackRateMenuButton.replaceExisting(player);
|
||||
|
||||
// Add reloadSourceOnError plugin
|
||||
player.reloadSourceOnError({ errorInterval: 10 });
|
||||
|
|
|
@ -205,6 +205,16 @@ $control-bar-popup-font-size: 0.8rem;
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.vjs-lock-showing {
|
||||
@media (max-width: $breakpoint-small) {
|
||||
width: 8em !important;
|
||||
// overflow-y:scroll;
|
||||
.vjs-menu-content {
|
||||
max-height: 176px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[dir] .vjs-menu-button-popup .vjs-menu .vjs-menu-content {
|
||||
//background-color: rgba(43, 51, 63);
|
||||
background-color: rgba(var(--color-header-button-base), 0.9);
|
||||
|
@ -239,6 +249,18 @@ $control-bar-popup-font-size: 0.8rem;
|
|||
background-color: var(--color-primary);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-small) {
|
||||
padding: 0.1em 0;
|
||||
margin-left: var(--spacing-xxs);
|
||||
margin-right: var(--spacing-xxs);
|
||||
&:first-child {
|
||||
margin-top: var(--spacing-xxs);
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: var(--spacing-xxs);
|
||||
}
|
||||
}
|
||||
}
|
||||
.vjs-selected {
|
||||
background-color: var(--color-primary);
|
||||
|
|
Loading…
Reference in a new issue