From db7e59b65eef62445c00471c114f931ac9928bce Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 8 Nov 2021 13:12:28 +0100 Subject: [PATCH] pulling the guts out --- ...nts.jsx => videojs-keyboard-shortcuts.jsx} | 0 .../viewers/videoViewer/internal/videojs.jsx | 214 +----------------- 2 files changed, 5 insertions(+), 209 deletions(-) rename ui/component/viewers/videoViewer/internal/{videojs-events.jsx => videojs-keyboard-shortcuts.jsx} (100%) diff --git a/ui/component/viewers/videoViewer/internal/videojs-events.jsx b/ui/component/viewers/videoViewer/internal/videojs-keyboard-shortcuts.jsx similarity index 100% rename from ui/component/viewers/videoViewer/internal/videojs-events.jsx rename to ui/component/viewers/videoViewer/internal/videojs-keyboard-shortcuts.jsx diff --git a/ui/component/viewers/videoViewer/internal/videojs.jsx b/ui/component/viewers/videoViewer/internal/videojs.jsx index f3f21bc72..7a4aa5c39 100644 --- a/ui/component/viewers/videoViewer/internal/videojs.jsx +++ b/ui/component/viewers/videoViewer/internal/videojs.jsx @@ -3,7 +3,6 @@ import React, { useEffect, useRef, useState } from 'react'; // import { SIMPLE_SITE } from 'config'; import Button from 'component/button'; import * as ICONS from 'constants/icons'; -import * as KEYCODES from 'constants/keycodes'; import classnames from 'classnames'; import videojs from 'video.js'; import 'videojs-contrib-ads'; // must be loaded in this order @@ -15,14 +14,13 @@ import './plugins/videojs-mobile-ui/plugin'; import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin'; import recsys from './plugins/videojs-recsys/plugin'; import qualityLevels from 'videojs-contrib-quality-levels'; -import isUserTyping from 'util/detect-typing'; import runAds from './ads'; import LbryVolumeBarClass from './lbry-volume-bar'; +import keyboardShorcuts from './videojs-keyboard-shortcuts'; import events from './videojs-events'; -const { handleKeyDown, curried_function } = events(); - -const isDev = process.env.NODE_ENV !== 'production'; +const { curried_function } = keyboardShorcuts(); +const { initializeEvents } = events(); export type Player = { on: (string, (any) => void) => void, @@ -174,165 +172,6 @@ export default React.memo(function VideoJs(props: Props) { }, }; - const tapToUnmuteRef = useRef(); - const tapToRetryRef = useRef(); - - const TAP = { - NONE: 'NONE', - UNMUTE: 'UNMUTE', - RETRY: 'RETRY', - }; - - function showTapButton(tapButton) { - const setButtonVisibility = (theRef, newState) => { - // Use the DOM to control the state of the button to prevent re-renders. - if (theRef.current) { - const curState = theRef.current.style.visibility === 'visible'; - if (newState !== curState) { - theRef.current.style.visibility = newState ? 'visible' : 'hidden'; - } - } - }; - - switch (tapButton) { - case TAP.NONE: - setButtonVisibility(tapToUnmuteRef, false); - setButtonVisibility(tapToRetryRef, false); - break; - case TAP.UNMUTE: - setButtonVisibility(tapToUnmuteRef, true); - setButtonVisibility(tapToRetryRef, false); - break; - case TAP.RETRY: - setButtonVisibility(tapToUnmuteRef, false); - setButtonVisibility(tapToRetryRef, true); - break; - default: - if (isDev) throw new Error('showTapButton: unexpected ref'); - break; - } - } - - function unmuteAndHideHint() { - const player = playerRef.current; - if (player) { - player.muted(false); - if (player.volume() === 0) { - player.volume(1.0); - } - } - showTapButton(TAP.NONE); - } - - function retryVideoAfterFailure() { - const player = playerRef.current; - if (player) { - setReload(Date.now()); - showTapButton(TAP.NONE); - } - } - - function resolveCtrlText(e) { - // Override the player's control text. We override to: - // 1. Add keyboard shortcut to the tool-tip. - // 2. Override videojs' i18n and use our own (don't want to have 2 systems). - // - // Notes: - // - For dynamic controls (e.g. play/pause), those unfortunately need to be - // updated again at their event-listener level (that's just the way videojs - // updates the text), hence the need to listen to 'play', 'pause' and 'volumechange' - // on top of just 'loadstart'. - // - videojs changes the MuteToggle text at 'loadstart', so this was chosen - // as the listener to update static texts. - - const setLabel = (controlBar, childName, label) => { - const c = controlBar.getChild(childName); - if (c) { - c.controlText(label); - } - }; - - const player = playerRef.current; - if (player) { - const ctrlBar = player.getChild('controlBar'); - switch (e.type) { - case 'play': - setLabel(ctrlBar, 'PlayToggle', __('Pause (space)')); - break; - case 'pause': - setLabel(ctrlBar, 'PlayToggle', __('Play (space)')); - break; - case 'volumechange': - ctrlBar - .getChild('VolumePanel') - .getChild('MuteToggle') - .controlText(player.muted() || player.volume() === 0 ? __('Unmute (m)') : __('Mute (m)')); - break; - case 'fullscreenchange': - setLabel( - ctrlBar, - 'FullscreenToggle', - player.isFullscreen() ? __('Exit Fullscreen (f)') : __('Fullscreen (f)') - ); - break; - case 'loadstart': - // --- Do everything --- - setLabel(ctrlBar, 'PlaybackRateMenuButton', __('Playback Rate (<, >)')); - setLabel(ctrlBar, 'QualityButton', __('Quality')); - setLabel(ctrlBar, 'PlayNextButton', __('Play Next (SHIFT+N)')); - setLabel(ctrlBar, 'PlayPreviousButton', __('Play Previous (SHIFT+P)')); - setLabel(ctrlBar, 'TheaterModeButton', videoTheaterMode ? __('Default Mode (t)') : __('Theater Mode (t)')); - setLabel(ctrlBar, 'AutoplayNextButton', autoplaySetting ? __('Autoplay Next On') : __('Autoplay Next Off')); - - resolveCtrlText({ type: 'play' }); - resolveCtrlText({ type: 'pause' }); - resolveCtrlText({ type: 'volumechange' }); - resolveCtrlText({ type: 'fullscreenchange' }); - break; - default: - if (isDev) throw Error('Unexpected: ' + e.type); - break; - } - } - } - - function onInitialPlay() { - const player = playerRef.current; - if (player && (player.muted() || player.volume() === 0)) { - // The css starts as "hidden". We make it visible here without - // re-rendering the whole thing. - showTapButton(TAP.UNMUTE); - } else { - showTapButton(TAP.NONE); - } - } - - function onVolumeChange() { - const player = playerRef.current; - if (player && !player.muted()) { - showTapButton(TAP.NONE); - } - } - - function onError() { - const player = playerRef.current; - showTapButton(TAP.RETRY); - - // reattach initial play listener in case we recover from error successfully - // $FlowFixMe - player.one('play', onInitialPlay); - - if (player && player.loadingSpinner) { - player.loadingSpinner.hide(); - } - } - - const onEnded = React.useCallback(() => { - if (!adUrl) { - showTapButton(TAP.NONE); - } - }, [adUrl]); - // Create the video DOM element and wrapper function createVideoPlayerDOM(container) { if (!container) return; @@ -393,23 +232,7 @@ export default React.memo(function VideoJs(props: Props) { runAds(internalFeatureEnabled, allowPreRoll, player); - // kick player in the butt, sometimes it doesn't always autoplay when it should - player.on('loadstart', function (event) { - if (autoplay) { - player.play(); - } - }); - - // Add various event listeners to player - player.one('play', onInitialPlay); - player.on('play', resolveCtrlText); - player.on('pause', resolveCtrlText); - player.on('loadstart', resolveCtrlText); - player.on('fullscreenchange', resolveCtrlText); - player.on('volumechange', resolveCtrlText); - player.on('volumechange', onVolumeChange); - player.on('error', onError); - player.on('ended', onEnded); + initializeEvents(player); // Replace volume bar with custom LBRY volume bar LbryVolumeBarClass.replaceExisting(player); @@ -458,33 +281,6 @@ export default React.memo(function VideoJs(props: Props) { } }, [replay]); - useEffect(() => { - const player = playerRef.current; - if (player) { - const controlBar = player.getChild('controlBar'); - controlBar - .getChild('TheaterModeButton') - .controlText(videoTheaterMode ? __('Default Mode (t)') : __('Theater Mode (t)')); - } - }, [videoTheaterMode]); - - useEffect(() => { - const player = playerRef.current; - if (player) { - const touchOverlay = player.getChild('TouchOverlay'); - const controlBar = player.getChild('controlBar') || touchOverlay.getChild('controlBar'); - const autoplayButton = controlBar.getChild('AutoplayNextButton'); - - if (autoplayButton) { - const title = autoplaySetting ? __('Autoplay Next On') : __('Autoplay Next Off'); - - autoplayButton.controlText(title); - autoplayButton.setAttribute('aria-label', title); - autoplayButton.setAttribute('aria-checked', autoplaySetting); - } - } - }, [autoplaySetting]); - // This lifecycle hook is only called once (on mount), or when `isAudio` or `source` changes. useEffect(() => { const vjsElement = createVideoPlayerDOM(containerRef.current); @@ -505,7 +301,7 @@ export default React.memo(function VideoJs(props: Props) { // Cleanup return () => { - window.removeEventListener('keydown', handleKeyDown); + window.removeEventListener('keydown', curried_function); const player = playerRef.current; if (player) {