lbry-desktop/ui/component/viewers/videoViewer/internal/plugins/videojs-mobile-ui/plugin.js
mayeaux 87c94e3c1c
Reuse videojs instance between video reload, return mobile UI plugin for iOS (#1512)
* add mobile plugin back on ios

* further touchups and fix ios

* finish mobile functionality

* dont show big play button on mobile

* remove logs

* proof of concept

* dont go full screen on rotate

* add back functionality

* replace dispose event with navigate away

* bugfix

* turn off show if you liked button and nag only on homepage

* add back old functionality

* ending event not working

* test here

* working but needs cleanup

* more player touchups

* bugfix

* add settings button on mobile

* more touchups

* more cleanups

* touchup loading functionality

* fix hover thumbnails

* touchup and eslint fix

* fix repopulation bug

* change recsys event name

* bugfix events

* change the way buttons are removed and added

* finish chapters button

* refactor to use videojs methods

* refactor to fix autoplay next

* ux touchups

* seems to be behaving properly

* control bar behaving how it should

* fix control bar on ios

* working on flow and eslint errors

* bugfix and flow fixes

* bring back nudge

* fix playlist button bug

* remove chapter markers properly

* show big play button

* bugfix recsys closed event

* fix analytics bug

* fix embeds

* bugfix

* possible bugfix for kp

* bugfix playlist buttons

* fix issue with mobile ui plugin

* fix firefox autoplay issue

* fix bug for play on floating player closed

* bugfix volume control for ios

* instantiate new player if switching between claim types

* fix flow and lint errors

* fix control bar not showing up when switching sources

* dispose old player if recreating

* bugfix save position

* reset recsys data between videos

* fix audio upload posters

* clear claimSrcVhs on reload

* bugfix errant image previews showing up

* reset player value of having already switched quality

* fix watch position not being used

* bugfix switching between sources not perserving position

* fix save position bug

* fix playlist buttons

* bugfix

* code cleanup and add back 5 second feature
2022-06-10 12:18:58 -04:00

165 lines
4.8 KiB
JavaScript

import videojs from 'video.js';
import './touchOverlay.js';
import window from 'global/window';
import './plugin.scss';
const VERSION = '0.4.1';
// Default options for the plugin.
const defaults = {
fullscreen: {
enterOnRotate: true,
lockOnRotate: true,
iOS: false,
},
touchControls: {
seekSeconds: 5,
tapTimeout: 300,
disableOnEnd: false,
},
};
const screen = window.screen;
const angle = () => {
// iOS
if (typeof window.orientation === 'number') {
return window.orientation;
}
// Android
if (screen && screen.orientation && screen.orientation.angle) {
return window.orientation;
}
videojs.log('angle unknown');
return 0;
};
// Cross-compatibility for Video.js 5 and 6.
const registerPlugin = videojs.registerPlugin || videojs.plugin;
/**
* Add UI and event listeners
*
* @function onPlayerReady
* @param {Player} player
* A Video.js player object.
*
* @param {Object} [options={}]
* A plain object containing options for the plugin.
*/
const onPlayerReady = (player, options) => {
player.addClass('vjs-mobile-ui');
if (options.touchControls.disableOnEnd || typeof player.endscreen === 'function') {
player.addClass('vjs-mobile-ui-disable-end');
}
if (
options.fullscreen.iOS &&
videojs.browser.IS_IOS &&
videojs.browser.IOS_VERSION > 9 &&
!player.el_.ownerDocument.querySelector('.bc-iframe')
) {
player.tech_.el_.setAttribute('playsinline', 'playsinline');
player.tech_.supportsFullScreen = () => false;
}
const controlBar = player.getChild('ControlBar');
// Insert before the ControlBar:
const controlBarIdx = player.children_.indexOf(controlBar);
player.addChild('touchOverlay', options.touchControls, controlBarIdx);
// Make the TouchOverlay the new parent of the ControlBar.
// This allows the ControlBar to listen to the same classes as TouchOverlay.
player.removeChild(controlBar);
const touchOverlay = player.getChild('touchOverlay');
touchOverlay.addChild(controlBar);
// Tweak controlBar to Mobile style:
controlBar.removeChild('PlayToggle'); // Use Overlay's instead.
let locked = false;
const rotationHandler = () => {
const currentAngle = angle();
if (currentAngle === 90 || currentAngle === 270 || currentAngle === -90) {
if (player.paused() === false) {
player.requestFullscreen();
if (options.fullscreen.lockOnRotate && screen.orientation && screen.orientation.lock) {
screen.orientation
.lock('landscape')
.then(() => {
locked = true;
})
.catch(() => {
videojs.log('orientation lock not allowed');
});
}
}
}
if (currentAngle === 0 || currentAngle === 180) {
if (player.isFullscreen()) {
player.exitFullscreen();
}
}
};
if (player.options.enterOnRotate) {
if (videojs.browser.IS_IOS) {
window.addEventListener('orientationchange', rotationHandler);
} else {
// addEventListener('orientationchange') is not a user interaction on Android
screen.orientation.onchange = rotationHandler;
}
}
player.on('ended', (_) => {
if (locked === true) {
screen.orientation.unlock();
locked = false;
}
});
};
/**
* A video.js plugin.
*
* Adds a monile UI for player control, and fullscreen orientation control
*
* @function mobileUi
* @param {Object} [options={}]
* Plugin options.
* @param {Object} [options.fullscreen={}]
* Fullscreen options.
* @param {boolean} [options.fullscreen.enterOnRotate=true]
* Whether to go fullscreen when rotating to landscape
* @param {boolean} [options.fullscreen.lockOnRotate=true]
* Whether to lock orientation when rotating to landscape
* Unlocked when exiting fullscreen or on 'ended'
* @param {boolean} [options.fullscreen.iOS=false]
* Whether to disable iOS's native fullscreen so controls can work
* @param {Object} [options.touchControls={}]
* Touch UI options.
* @param {int} [options.touchControls.seekSeconds=10]
* Number of seconds to seek on double-tap
* @param {int} [options.touchControls.tapTimeout=300]
* Interval in ms to be considered a doubletap
* @param {boolean} [options.touchControls.disableOnEnd=false]
* Whether to disable when the video ends (e.g., if there is an endscreen)
* Never shows if the endscreen plugin is present
*/
function mobileUi(options) {
if (videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) {
this.ready(() => onPlayerReady(this, videojs.mergeOptions(defaults, options)));
}
}
// Register the plugin with video.js.
registerPlugin('mobileUi', mobileUi);
// Include the version number.
mobileUi.VERSION = VERSION;
export default mobileUi;