Add volume control using scroll wheel from myzel, with flow errors fixed (#1638)
* created function * removed console logs * made volume change on mousewheel functional * improved code * added precise volume control * updated behavior * fixed error * fix flow errors Co-authored-by: myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
parent
c146ccc432
commit
8aaa820e2f
2 changed files with 100 additions and 14 deletions
|
@ -6,6 +6,8 @@ import isUserTyping from 'util/detect-typing';
|
||||||
|
|
||||||
const SEEK_STEP_5 = 5;
|
const SEEK_STEP_5 = 5;
|
||||||
const SEEK_STEP = 10; // time to seek in seconds
|
const SEEK_STEP = 10; // time to seek in seconds
|
||||||
|
const VOLUME_CHANGE_ON_SCROLL = 0.05;
|
||||||
|
const PRECISE_VOLUME_CHANGE_ON_SCROLL = 0.01;
|
||||||
|
|
||||||
// check if active (clicked) element is part of video div, used for keyboard shortcuts (volume etc)
|
// check if active (clicked) element is part of video div, used for keyboard shortcuts (volume etc)
|
||||||
function activeElementIsPartOfVideoElement() {
|
function activeElementIsPartOfVideoElement() {
|
||||||
|
@ -14,24 +16,24 @@ function activeElementIsPartOfVideoElement() {
|
||||||
return videoElementParent.contains(activeElement);
|
return videoElementParent.contains(activeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
function volumeUp(event, playerRef) {
|
function volumeUp(event, playerRef, checkIsActive = true, amount = 0.05) {
|
||||||
// dont run if video element is not active element (otherwise runs when scrolling using keypad)
|
// dont run if video element is not active element (otherwise runs when scrolling using keypad)
|
||||||
const videoElementIsActive = activeElementIsPartOfVideoElement();
|
const videoElementIsActive = activeElementIsPartOfVideoElement();
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
if (!player || !videoElementIsActive) return;
|
if (!player || (checkIsActive && !videoElementIsActive)) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
player.volume(player.volume() + 0.05);
|
player.volume(player.volume() + amount);
|
||||||
OVERLAY.showVolumeverlay(player, Math.round(player.volume() * 100));
|
OVERLAY.showVolumeverlay(player, Math.round(player.volume() * 100));
|
||||||
player.userActive(true);
|
player.userActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function volumeDown(event, playerRef) {
|
function volumeDown(event, playerRef, checkIsActive = true, amount = 0.05) {
|
||||||
// dont run if video element is not active element (otherwise runs when scrolling using keypad)
|
// dont run if video element is not active element (otherwise runs when scrolling using keypad)
|
||||||
const videoElementIsActive = activeElementIsPartOfVideoElement();
|
const videoElementIsActive = activeElementIsPartOfVideoElement();
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
if (!player || !videoElementIsActive) return;
|
if (!player || (checkIsActive && !videoElementIsActive)) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
player.volume(player.volume() - 0.05);
|
player.volume(player.volume() - amount);
|
||||||
OVERLAY.showVolumeverlay(player, Math.round(player.volume() * 100));
|
OVERLAY.showVolumeverlay(player, Math.round(player.volume() * 100));
|
||||||
player.userActive(true);
|
player.userActive(true);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +96,7 @@ function changePlaybackSpeed(shouldSpeedUp: boolean, playerRef) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoJsKeyboardShorcuts = ({
|
const VideoJsShorcuts = ({
|
||||||
playNext,
|
playNext,
|
||||||
playPrevious,
|
playPrevious,
|
||||||
toggleVideoTheaterMode,
|
toggleVideoTheaterMode,
|
||||||
|
@ -163,15 +165,65 @@ const VideoJsKeyboardShorcuts = ({
|
||||||
if (e.keyCode === KEYCODES.NINE) seekVideo(90 / 100, playerRef, containerRef, true);
|
if (e.keyCode === KEYCODES.NINE) seekVideo(90 / 100, playerRef, containerRef, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var curried_function = function (playerRef: any, containerRef: any) {
|
const handleVideoScrollWheel = (event, playerRef, containerRef) => {
|
||||||
|
// Handle precise volume control when scrolling over the video player while holding down the "SHIFT"-key
|
||||||
|
const player = playerRef.current;
|
||||||
|
const videoNode = containerRef.current && containerRef.current.querySelector('video');
|
||||||
|
|
||||||
|
if (!videoNode || !player || isUserTyping() || !event.shiftKey) return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const delta = event.deltaY;
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
|
volumeDown(event, playerRef, false, PRECISE_VOLUME_CHANGE_ON_SCROLL);
|
||||||
|
} else if (delta < 0) {
|
||||||
|
volumeUp(event, playerRef, false, PRECISE_VOLUME_CHANGE_ON_SCROLL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVolumeBarScrollWheel = (event, volumeElement, playerRef, containerRef) => {
|
||||||
|
// Handle generic and precise volume control when scrolling over the volume bar
|
||||||
|
const player = playerRef.current;
|
||||||
|
const videoNode = containerRef.current && containerRef.current.querySelector('video');
|
||||||
|
|
||||||
|
if (!volumeElement || !player || !videoNode || isUserTyping()) return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
const delta = event.deltaY;
|
||||||
|
const changeAmount = event.shiftKey ? PRECISE_VOLUME_CHANGE_ON_SCROLL : VOLUME_CHANGE_ON_SCROLL;
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
|
volumeDown(event, playerRef, false, changeAmount);
|
||||||
|
} else if (delta < 0) {
|
||||||
|
volumeUp(event, playerRef, false, changeAmount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createKeyDownShortcutsHandler = function (playerRef: any, containerRef: any) {
|
||||||
return function curried_func(e: any) {
|
return function curried_func(e: any) {
|
||||||
handleKeyDown(e, playerRef, containerRef);
|
handleKeyDown(e, playerRef, containerRef);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
const createVideoScrollShortcutsHandler = function (playerRef: any, containerRef: any) {
|
||||||
|
return function curried_func(e: any) {
|
||||||
|
handleVideoScrollWheel(e, playerRef, containerRef);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const createVolumePanelScrollShortcutsHandler = function (volumeElement: any, playerRef: any, containerRef: any) {
|
||||||
|
return function curried_func(e: any) {
|
||||||
|
handleVolumeBarScrollWheel(e, volumeElement, playerRef, containerRef);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
curried_function,
|
createKeyDownShortcutsHandler,
|
||||||
|
createVideoScrollShortcutsHandler,
|
||||||
|
createVolumePanelScrollShortcutsHandler,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default VideoJsKeyboardShorcuts;
|
export default VideoJsShorcuts;
|
|
@ -15,7 +15,7 @@ import events from './videojs-events';
|
||||||
import eventTracking from 'videojs-event-tracking';
|
import eventTracking from 'videojs-event-tracking';
|
||||||
import functions from './videojs-functions';
|
import functions from './videojs-functions';
|
||||||
import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
||||||
import keyboardShorcuts from './videojs-keyboard-shortcuts';
|
import keyboardShorcuts from './videojs-shortcuts';
|
||||||
import LbryVolumeBarClass from './lbry-volume-bar';
|
import LbryVolumeBarClass from './lbry-volume-bar';
|
||||||
import Chromecast from './chromecast';
|
import Chromecast from './chromecast';
|
||||||
import playerjs from 'player.js';
|
import playerjs from 'player.js';
|
||||||
|
@ -103,6 +103,8 @@ type Props = {
|
||||||
activeLivestreamForChannel: any,
|
activeLivestreamForChannel: any,
|
||||||
doToast: ({ message: string, linkText: string, linkTarget: string }) => void,
|
doToast: ({ message: string, linkText: string, linkTarget: string }) => void,
|
||||||
};
|
};
|
||||||
|
const VIDEOJS_CONTROL_BAR_CLASS = 'ControlBar';
|
||||||
|
const VIDEOJS_VOLUME_PANEL_CLASS = 'VolumePanel';
|
||||||
|
|
||||||
const IS_IOS = platform.isIOS();
|
const IS_IOS = platform.isIOS();
|
||||||
const IS_MOBILE = platform.isMobile();
|
const IS_MOBILE = platform.isMobile();
|
||||||
|
@ -176,13 +178,22 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
const tapToUnmuteRef = useRef();
|
const tapToUnmuteRef = useRef();
|
||||||
const tapToRetryRef = useRef();
|
const tapToRetryRef = useRef();
|
||||||
const playerServerRef = useRef();
|
const playerServerRef = useRef();
|
||||||
|
const volumePanelRef = useRef();
|
||||||
|
|
||||||
|
const keyDownHandlerRef = useRef();
|
||||||
|
const videoScrollHandlerRef = useRef();
|
||||||
|
const volumePanelScrollHandlerRef = useRef();
|
||||||
|
|
||||||
const { url: livestreamVideoUrl } = activeLivestreamForChannel || {};
|
const { url: livestreamVideoUrl } = activeLivestreamForChannel || {};
|
||||||
const overrideNativeVhs = !platform.isIPhone();
|
const overrideNativeVhs = !platform.isIPhone();
|
||||||
const showQualitySelector = (!isLivestreamClaim && overrideNativeVhs) || livestreamVideoUrl;
|
const showQualitySelector = (!isLivestreamClaim && overrideNativeVhs) || livestreamVideoUrl;
|
||||||
|
|
||||||
// initiate keyboard shortcuts
|
// initiate keyboard shortcuts
|
||||||
const { curried_function } = keyboardShorcuts({
|
const {
|
||||||
|
createKeyDownShortcutsHandler,
|
||||||
|
createVideoScrollShortcutsHandler,
|
||||||
|
createVolumePanelScrollShortcutsHandler,
|
||||||
|
} = keyboardShorcuts({
|
||||||
isMobile,
|
isMobile,
|
||||||
isLivestreamClaim,
|
isLivestreamClaim,
|
||||||
toggleVideoTheaterMode,
|
toggleVideoTheaterMode,
|
||||||
|
@ -370,7 +381,23 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// Set reference in component state
|
// Set reference in component state
|
||||||
playerRef.current = vjsPlayer;
|
playerRef.current = vjsPlayer;
|
||||||
|
|
||||||
window.addEventListener('keydown', curried_function(playerRef, containerRef));
|
// volume control div, used for changing volume when scrolled over
|
||||||
|
volumePanelRef.current = playerRef.current
|
||||||
|
.getChild(VIDEOJS_CONTROL_BAR_CLASS)
|
||||||
|
.getChild(VIDEOJS_VOLUME_PANEL_CLASS)
|
||||||
|
.el();
|
||||||
|
|
||||||
|
const keyDownHandler = createKeyDownShortcutsHandler(playerRef, containerRef);
|
||||||
|
const videoScrollHandler = createVideoScrollShortcutsHandler(playerRef, containerRef);
|
||||||
|
const volumePanelHandler = createVolumePanelScrollShortcutsHandler(volumePanelRef, playerRef, containerRef);
|
||||||
|
window.addEventListener('keydown', keyDownHandler);
|
||||||
|
const containerDiv = containerRef.current;
|
||||||
|
containerDiv && containerDiv.addEventListener('wheel', videoScrollHandler);
|
||||||
|
if (volumePanelRef.current) volumePanelRef.current.addEventListener('wheel', volumePanelHandler);
|
||||||
|
|
||||||
|
keyDownHandlerRef.current = keyDownHandler;
|
||||||
|
videoScrollHandlerRef.current = videoScrollHandler;
|
||||||
|
volumePanelScrollHandlerRef.current = volumePanelHandler;
|
||||||
|
|
||||||
const controlBar = document.querySelector('.vjs-control-bar');
|
const controlBar = document.querySelector('.vjs-control-bar');
|
||||||
if (controlBar) {
|
if (controlBar) {
|
||||||
|
@ -441,7 +468,14 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('keydown', curried_function);
|
window.removeEventListener('keydown', keyDownHandlerRef.current);
|
||||||
|
const containerDiv = containerRef.current;
|
||||||
|
// $FlowFixMe
|
||||||
|
containerDiv && containerDiv.removeEventListener('wheel', videoScrollHandlerRef.current);
|
||||||
|
|
||||||
|
if (volumePanelRef.current) {
|
||||||
|
volumePanelRef.current.removeEventListener('wheel', volumePanelScrollHandlerRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
if (player) {
|
if (player) {
|
||||||
|
|
Loading…
Reference in a new issue