Compare commits

...

14 commits

Author SHA1 Message Date
Anthony
df84c4ccbd
more debugging work 2021-09-02 22:42:21 +02:00
Anthony
9b88463886
hide big play button 2021-08-31 19:07:45 +02:00
Anthony
abbd524ead
turn off big play button 2021-08-31 17:33:17 +02:00
Anthony
29dafce0a8
only show centered button mobile 2021-08-30 23:18:24 +02:00
Anthony
429ead3b3b
working on desktop 2021-08-30 22:27:30 +02:00
Anthony
fdfabe7ccf
testing this 2021-08-30 21:57:51 +02:00
Anthony
38740d7e43
seeing if this fixes offcenter play button 2021-08-30 21:48:47 +02:00
Anthony
391e2e25a2
fix off center button 2021-08-30 21:18:12 +02:00
Anthony
1a4bc2a543
hide div properly 2021-08-30 20:44:27 +02:00
Anthony
ed62423c02
show the volume button 2021-08-30 20:18:56 +02:00
Anthony
91fe871be3
commit to push up to anton for testing 2021-08-30 20:18:56 +02:00
Anthony
fb1e3e703b
hide play button if autoplay next is on 2021-08-30 20:18:56 +02:00
Anthony
0e9ac90ae5
display a play button when paused on ios 2021-08-30 20:18:56 +02:00
Anthony
7bf2fa490f
add big button when paused ios 2021-08-30 20:18:56 +02:00
4 changed files with 105 additions and 39 deletions

View file

@ -151,8 +151,8 @@ const onPlayerReady = (player, options) => {
* Never shows if the endscreen plugin is present * Never shows if the endscreen plugin is present
*/ */
const mobileUi = function(options) { const mobileUi = function(options) {
// if (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) { if (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {
if (videojs.browser.IS_ANDROID) { // if (videojs.browser.IS_ANDROID) {
this.ready(() => { this.ready(() => {
onPlayerReady(this, videojs.mergeOptions(defaults, options)); onPlayerReady(this, videojs.mergeOptions(defaults, options));
}); });

View file

@ -59,6 +59,7 @@ type Props = {
userId: ?number, userId: ?number,
// allowPreRoll: ?boolean, // allowPreRoll: ?boolean,
shareTelemetry: boolean, shareTelemetry: boolean,
showAutoplayCountdown: boolean
}; };
// type VideoJSOptions = { // type VideoJSOptions = {
@ -84,11 +85,12 @@ const VIDEO_JS_OPTIONS = {
controls: true, controls: true,
html5: { html5: {
vhs: { vhs: {
overrideNative: !videojs.browser.IS_ANY_SAFARI, overrideNative: true, // don't override on safari
}, },
}, },
}; };
// keys to bind to for keyboard shortcuts
const SPACE_BAR_KEYCODE = 32; const SPACE_BAR_KEYCODE = 32;
const SMALL_F_KEYCODE = 70; const SMALL_F_KEYCODE = 70;
const SMALL_M_KEYCODE = 77; const SMALL_M_KEYCODE = 77;
@ -118,6 +120,7 @@ const SEEK_BACKWARD_KEYCODE_5 = ARROW_LEFT_KEYCODE;
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
// register videojs plugins
if (!Object.keys(videojs.getPlugins()).includes('eventTracking')) { if (!Object.keys(videojs.getPlugins()).includes('eventTracking')) {
videojs.registerPlugin('eventTracking', eventTracking); videojs.registerPlugin('eventTracking', eventTracking);
} }
@ -197,6 +200,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
userId, userId,
// allowPreRoll, // allowPreRoll,
shareTelemetry, shareTelemetry,
showAutoplayCountdown,
} = props; } = props;
const [reload, setReload] = useState('initial'); const [reload, setReload] = useState('initial');
@ -217,11 +221,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
eventTracking: true, eventTracking: true,
overlay: OVERLAY.OVERLAY_DATA, overlay: OVERLAY.OVERLAY_DATA,
}, },
// fixes problem of errant CC button showing up on iOS // bigPlayButton: false,
// the true fix here is to fix the m3u8 file, see: https://github.com/lbryio/lbry-desktop/pull/6315
controlBar: {
subsCapsButton: false,
},
}; };
const tapToUnmuteRef = useRef(); const tapToUnmuteRef = useRef();
@ -246,6 +246,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
switch (tapButton) { switch (tapButton) {
case TAP.NONE: case TAP.NONE:
document.getElementsByClassName('video-js--tap-to-unmute')[0].style.visibility = 'hidden';
setButtonVisibility(tapToUnmuteRef, false); setButtonVisibility(tapToUnmuteRef, false);
setButtonVisibility(tapToRetryRef, false); setButtonVisibility(tapToRetryRef, false);
break; break;
@ -263,14 +264,18 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} }
} }
// unmute video when player hits "Tap to unmute button"
function unmuteAndHideHint() { function unmuteAndHideHint() {
const player = playerRef.current; const player = playerRef.current;
if (player) { if (player) {
// unmute the video
player.muted(false); player.muted(false);
// turn the volume all the way up if it's at 0
if (player.volume() === 0) { if (player.volume() === 0) {
player.volume(1.0); player.volume(1.0);
} }
} }
// hide "Tap to unmute" button
showTapButton(TAP.NONE); showTapButton(TAP.NONE);
} }
@ -296,29 +301,29 @@ export default React.memo<Props>(function VideoJs(props: Props) {
// as the listener to update static texts. // as the listener to update static texts.
const player = playerRef.current; const player = playerRef.current;
if (player) { if (player) {
const controlBar = player.getChild('controlBar'); // const controlBar = player.getChild('controlBar');
switch (e.type) { switch (e.type) {
case 'play': case 'play':
controlBar.getChild('PlayToggle').controlText(__('Pause (space)')); // controlBar.getChild('PlayToggle').controlText(__('Pause (space)'));
break; break;
case 'pause': case 'pause':
controlBar.getChild('PlayToggle').controlText(__('Play (space)')); // controlBar.getChild('PlayToggle').controlText(__('Play (space)'));
break; break;
case 'volumechange': case 'volumechange':
controlBar // controlBar
.getChild('VolumePanel') // .getChild('VolumePanel')
.getChild('MuteToggle') // .getChild('MuteToggle')
.controlText(player.muted() || player.volume() === 0 ? __('Unmute (m)') : __('Mute (m)')); // .controlText(player.muted() || player.volume() === 0 ? __('Unmute (m)') : __('Mute (m)'));
break; break;
case 'fullscreenchange': case 'fullscreenchange':
controlBar // controlBar
.getChild('FullscreenToggle') // .getChild('FullscreenToggle')
.controlText(player.isFullscreen() ? __('Exit Fullscreen (f)') : __('Fullscreen (f)')); // .controlText(player.isFullscreen() ? __('Exit Fullscreen (f)') : __('Fullscreen (f)'));
break; break;
case 'loadstart': case 'loadstart':
// --- Do everything --- // --- Do everything ---
controlBar.getChild('PlaybackRateMenuButton').controlText(__('Playback Rate (<, >)')); // controlBar.getChild('PlaybackRateMenuButton').controlText(__('Playback Rate (<, >)'));
controlBar.getChild('QualityButton').controlText(__('Quality')); // controlBar.getChild('QualityButton').controlText(__('Quality'));
resolveCtrlText({ type: 'play' }); resolveCtrlText({ type: 'play' });
resolveCtrlText({ type: 'pause' }); resolveCtrlText({ type: 'pause' });
resolveCtrlText({ type: 'volumechange' }); resolveCtrlText({ type: 'volumechange' });
@ -329,7 +334,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
// (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)' // (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)'
// as a prop here so we can say "Theater mode|Default mode" instead of // as a prop here so we can say "Theater mode|Default mode" instead of
// "Toggle Theater mode". // "Toggle Theater mode".
controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)')); // controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)'));
break; break;
default: default:
if (isDev) throw Error('Unexpected: ' + e.type); if (isDev) throw Error('Unexpected: ' + e.type);
@ -340,6 +345,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
function onInitialPlay() { function onInitialPlay() {
const player = playerRef.current; const player = playerRef.current;
// show the unmute button if the video is muted
if (player && (player.muted() || player.volume() === 0)) { if (player && (player.muted() || player.volume() === 0)) {
// The css starts as "hidden". We make it visible here without // The css starts as "hidden". We make it visible here without
// re-rendering the whole thing. // re-rendering the whole thing.
@ -357,6 +363,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} }
function onError() { function onError() {
console.log('error!');
const player = playerRef.current; const player = playerRef.current;
showTapButton(TAP.RETRY); showTapButton(TAP.RETRY);
@ -492,7 +499,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
wrapper.setAttribute('data-vjs-player', 'true'); wrapper.setAttribute('data-vjs-player', 'true');
const el = document.createElement(isAudio ? 'audio' : 'video'); const el = document.createElement(isAudio ? 'audio' : 'video');
el.className = 'video-js vjs-big-play-centered '; el.className = 'video-js vjs-big-play-centered';
wrapper.appendChild(el); wrapper.appendChild(el);
container.appendChild(wrapper); container.appendChild(wrapper);
@ -625,10 +633,11 @@ export default React.memo<Props>(function VideoJs(props: Props) {
window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keydown', handleKeyDown);
const player = playerRef.current; const player = playerRef.current;
if (player) { player.pause()
player.dispose(); player.dispose();
window.player = undefined; window.oldPlayer = window.player;
} window.player = undefined;
}; };
}, [isAudio]); }, [isAudio]);
@ -666,6 +675,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
}); });
}, [source, reload]); }, [source, reload]);
console.log('RUNNING HERE VIDEOJS!');
return ( return (
// $FlowFixMe // $FlowFixMe
<div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}> <div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}>

View file

@ -109,6 +109,13 @@ function VideoViewer(props: Props) {
breaks because some browsers (e.g. Firefox) block autoplay but leave the player.play Promise pending */ breaks because some browsers (e.g. Firefox) block autoplay but leave the player.play Promise pending */
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const IS_IOS =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
console.log("RUNNING HERE PARENT VIEW.")
// force everything to recent when URI changes, can cause weird corner cases otherwise (e.g. navigate while autoplay is true) // force everything to recent when URI changes, can cause weird corner cases otherwise (e.g. navigate while autoplay is true)
useEffect(() => { useEffect(() => {
if (uri && previousUri && uri !== previousUri) { if (uri && previousUri && uri !== previousUri) {
@ -203,7 +210,17 @@ function VideoViewer(props: Props) {
playerReadyDependencyList.push(desktopPlayStartTime); playerReadyDependencyList.push(desktopPlayStartTime);
} }
let alreadyRunning = false;
const onPlayerReady = useCallback((player: Player) => { const onPlayerReady = useCallback((player: Player) => {
console.log('already running');
console.log(alreadyRunning)
console.log(new Date())
alreadyRunning = true;
console.log("PLAYER READY CALLBACK")
if (!embedded) { if (!embedded) {
player.muted(muted); player.muted(muted);
player.volume(volume); player.volume(volume);
@ -212,23 +229,52 @@ function VideoViewer(props: Props) {
} }
const shouldPlay = !embedded || autoplayIfEmbedded; const shouldPlay = !embedded || autoplayIfEmbedded;
// console.log('should play');
// console.log(shouldPlay);
// TODO: this is causing issues with videos starting randomly
// https://blog.videojs.com/autoplay-best-practices-with-video-js/#Programmatic-Autoplay-and-Success-Failure-Detection // https://blog.videojs.com/autoplay-best-practices-with-video-js/#Programmatic-Autoplay-and-Success-Failure-Detection
if (shouldPlay) { if (shouldPlay) {
const playPromise = player.play(); console.log('starting video!');
const timeoutPromise = new Promise((resolve, reject) =>
setTimeout(() => reject(PLAY_TIMEOUT_ERROR), PLAY_TIMEOUT_LIMIT)
);
Promise.race([playPromise, timeoutPromise]).catch((error) => { (async function() {
if (typeof error === 'object' && error.name && error.name === 'NotAllowedError') { try {
if (player.autoplay() && !player.muted()) { console.log('is playing already');
// player.muted(true); console.log(isPlaying);
// another version had player.play() console.log('player');
console.log(player);
// console.log('is paused!');
// console.log(player.paused());
const isAlreadyPlaying = isPlaying;
setIsPlaying(true);
if (!isAlreadyPlaying) {
console.log('STARTING PLAYER')
const playerResponse = player.play();
const isPaused = player.paused();
// console.log(playerResponse)
// await new Promise(resolve => setTimeout(resolve, 2000));
// console.log(playerResponse);
if (IS_IOS && isPaused) {
document.getElementsByClassName('video-js--tap-to-unmute')[0].style.visibility = 'visible';
player.muted(true);
const iosResponse = player.play();
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(iosResponse);
}
} else {
console.log('ALREADY HAVE PLAYER, DISPOSING!!')
player.dispose()
} }
console.log('\n\n')
} catch (err) {
console.log(err);
} }
setIsLoading(false); })();
setIsPlaying(false);
});
} }
setIsLoading(shouldPlay); // if we are here outside of an embed, we're playing setIsLoading(shouldPlay); // if we are here outside of an embed, we're playing
@ -261,6 +307,7 @@ function VideoViewer(props: Props) {
changeMute(player.muted()); changeMute(player.muted());
} }
}); });
player.on('ratechange', () => { player.on('ratechange', () => {
const HAVE_NOTHING = 0; // https://docs.videojs.com/player#readyState const HAVE_NOTHING = 0; // https://docs.videojs.com/player#readyState
if (player && player.readyState() !== HAVE_NOTHING) { if (player && player.readyState() !== HAVE_NOTHING) {
@ -289,7 +336,7 @@ function VideoViewer(props: Props) {
{isEndededEmbed && <FileViewerEmbeddedEnded uri={uri} />} {isEndededEmbed && <FileViewerEmbeddedEnded uri={uri} />}
{embedded && !isEndededEmbed && <FileViewerEmbeddedTitle uri={uri} />} {embedded && !isEndededEmbed && <FileViewerEmbeddedTitle uri={uri} />}
{/* disable this loading behavior because it breaks when player.play() promise hangs */} {/* disable this loading behavior because it breaks when player.play() promise hangs */}
{isLoading && <LoadingScreen status={__('Loading')} />} {/* {isLoading && <LoadingScreen status={__('Loading')} />} */}
{!isFetchingAd && adUrl && ( {!isFetchingAd && adUrl && (
<> <>
@ -336,6 +383,7 @@ function VideoViewer(props: Props) {
userId={userId} userId={userId}
allowPreRoll={!embedded && !authenticated} allowPreRoll={!embedded && !authenticated}
shareTelemetry={shareTelemetry} shareTelemetry={shareTelemetry}
showAutoplayCountdown={autoplaySetting}
/> />
)} )}
</div> </div>

View file

@ -150,3 +150,10 @@
.bottom-gradient { .bottom-gradient {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.4) 0%, transparent 72px); background-image: linear-gradient(to top, rgba(0, 0, 0, 0.4) 0%, transparent 72px);
} }
.vjs-big-play-button {
// if the user is using a mouse
@media (pointer: none), (pointer:coarse) {
display: none !important;
}
}