UNPKG

shaka-player

Version:
200 lines (181 loc) 6.2 kB
/*! @license * Shaka Player * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ goog.provide('shaka.polyfill.Orientation'); goog.require('shaka.log'); goog.require('shaka.util.FakeEvent'); goog.require('shaka.util.FakeEventTarget'); goog.require('shaka.polyfill'); /** * @summary A polyfill for systems that do not implement screen.orientation. * For now, this only handles systems that implement the deprecated * window.orientation feature... e.g. iPad. * @export */ shaka.polyfill.Orientation = class { /** * Install the polyfill if needed. * @export */ static install() { if (screen.orientation && screen.orientation.unlock) { // Not needed. shaka.log.info('Using native screen.orientation'); return; } if (screen.orientation != undefined) { // There are some platforms where screen.orientation is defined but // incomplete (e.g. Safari). // Install a very simple polyfill in that case. shaka.polyfill.Orientation.installBasedOnScreenMethods_(); } else if (window.orientation != undefined) { // There is no way to check to see if the 'orientationchange' event exists // on window, which could theoretically lead to this making a // screen.orientation object that doesn't actually work. // However, it looks like all platforms that support the deprecated // window.orientation feature also support that event. shaka.polyfill.Orientation.installBasedOnWindowMethods_(); } } /** * Modifies screen.orientation to add no-ops for missing methods. * Meant for cases where screen.orientation is defined, but has missing * methods that cannot be properly polyfilled. * @private */ static installBasedOnScreenMethods_() { if (screen.orientation.lock === undefined) { screen.orientation.lock = (orientation) => { shaka.log.info('screen.orientation.lock is a no-op'); return Promise.resolve(); }; } if (screen.orientation.unlock === undefined) { screen.orientation.unlock = () => { shaka.log.info('screen.orientation.unlock is a no-op'); }; } } /** * Makes a polyfill for orientation, based on window methods. * Note that some of the features this is based on are deprecated, so this * will not necessarily work on all platforms. * @private */ static installBasedOnWindowMethods_() { const orientation = new shaka.polyfill.Orientation.FakeOrientation(); screen.orientation = /** @type {!ScreenOrientation} */ (orientation); const setValues = () => { switch (window.orientation) { case -90: orientation.type = 'landscape-secondary'; orientation.angle = 270; break; case 0: orientation.type = 'portrait-primary'; orientation.angle = 0; break; case 90: orientation.type = 'landscape-primary'; orientation.angle = 90; break; case 180: orientation.type = 'portrait-secondary'; orientation.angle = 180; break; } }; setValues(); window.addEventListener('orientationchange', () => { setValues(); orientation.dispatchChangeEvent(); }); } }; shaka.polyfill.Orientation.FakeOrientation = class extends shaka.util.FakeEventTarget { /** */ constructor() { super(); /** @type {string} */ this.type = ''; /** @type {number} */ this.angle = 0; } /** Dispatch a 'change' event. */ dispatchChangeEvent() { const event = new shaka.util.FakeEvent('change'); this.dispatchEvent(event); } /** * @param {string} orientation * @return {!Promise} */ lock(orientation) { /** * @param {string} orientation * @return {boolean} */ const lockOrientation = (orientation) => { if (screen.lockOrientation) { return screen.lockOrientation(orientation); } if (screen.mozLockOrientation) { return screen.mozLockOrientation(orientation); } if (screen.msLockOrientation) { return screen.msLockOrientation(orientation); } return false; }; let success = false; // The set of input strings for screen.orientation.lock and for // screen.lockOrientation are almost, but not entirely, the same. switch (orientation) { case 'natural': success = lockOrientation('default'); break; case 'any': // It's not quite clear what locking the screen orientation to 'any' // is supposed to mean... presumably, that's equivalent to not being // locked? success = true; this.unlock(); break; default: success = lockOrientation(orientation); break; } // According to the docs, there "may be a delay" between the // lockOrientation method being called and the screen actually being // locked. Unfortunately, without any idea as to how long that delay is, // and with no events to listen for, we cannot account for it here. if (success) { return Promise.resolve(); } // Either locking was not available, or the process failed... either way, // reject this with a mock error. // This should be a DOMException, but there is not a public constructor for // that. So we make this look-alike instead. const unsupportedKeySystemError = new Error('screen.orientation.lock() is not available on this device'); unsupportedKeySystemError.name = 'NotSupportedError'; unsupportedKeySystemError['code'] = DOMException.NOT_SUPPORTED_ERR; return Promise.reject(unsupportedKeySystemError); } /** Unlock the screen orientation. */ unlock() { // screen.unlockOrientation has a return value, but // screen.orientation.unlock does not. So ignore the return value. if (screen.unlockOrientation) { screen.unlockOrientation(); } else if (screen.mozUnlockOrientation) { screen.mozUnlockOrientation(); } else if (screen.msUnlockOrientation) { screen.msUnlockOrientation(); } } }; shaka.polyfill.register(shaka.polyfill.Orientation.install);