diff options
| -rw-r--r-- | netflix-immersive.user.js | 59 | ||||
| -rw-r--r-- | src/index.ts | 4 | ||||
| -rw-r--r-- | src/seamless.ts | 73 | ||||
| -rw-r--r-- | src/styles.ts | 2 | 
4 files changed, 131 insertions, 7 deletions
| diff --git a/netflix-immersive.user.js b/netflix-immersive.user.js index cbb8624..dcfdde6 100644 --- a/netflix-immersive.user.js +++ b/netflix-immersive.user.js @@ -131,11 +131,12 @@ function init() {  }  exports.default = init; -},{"./wait_element":6}],3:[function(require,module,exports){ +},{"./logger":4,"./wait_element":7}],3:[function(require,module,exports){  "use strict";  Object.defineProperty(exports, "__esModule", { value: true });  var fullscreen_credits_1 = require("./fullscreen_credits");  var logger_1 = require("./logger"); +var seamless_1 = require("./seamless");  var styles_1 = require("./styles");  var watch_credits_1 = require("./watch_credits");  function main() { @@ -143,12 +144,13 @@ function main() {      styles_1.default();      fullscreen_credits_1.default();      watch_credits_1.default(); +    seamless_1.default();  }  main();  // Reinitialise when the page changes.  window.onpopstate = main; -},{"./fullscreen_credits":2,"./logger":4,"./styles":5,"./watch_credits":7}],4:[function(require,module,exports){ +},{"./fullscreen_credits":2,"./logger":4,"./seamless":5,"./styles":6,"./watch_credits":8}],4:[function(require,module,exports){  "use strict";  var __spreadArrays = (this && this.__spreadArrays) || function () {      for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; @@ -171,6 +173,51 @@ exports.default = {  },{}],5:[function(require,module,exports){  "use strict";  Object.defineProperty(exports, "__esModule", { value: true }); +var logger_1 = require("./logger"); +var wait_element_1 = require("./wait_element"); +// Hide the cursor when seamless credits are played. +function init_mutation_observer(player) { +    var observer = new MutationObserver(function (mutation_list) { +        var _loop_1 = function () { +            var mutation = mutation_list[i]; +            var player_1 = mutation.target; +            var seamless_controls = document.querySelector('.SeamlessControls--container'); +            if (seamless_controls) { +                logger_1.default.debug('seamless', 'init_mutation_observer()', 'Handling seamless'); +                var style_el_1 = document.createElement('style'); +                // Hide the cursor. +                document.head.appendChild(style_el_1); +                var stylesheet = style_el_1.sheet; +                stylesheet.insertRule("\n\t\t\t\t\tbody {\n\t\t\t\t\t\tcursor: none !important;\n\t\t\t\t\t}", stylesheet.cssRules.length); +                document.body.onmousemove = function () { +                    document.head.removeChild(style_el_1); +                }; +                return { value: void 0 }; +            } +        }; +        for (var i = 0; i < mutation_list.length; i++) { +            var state_1 = _loop_1(); +            if (typeof state_1 === "object") +                return state_1.value; +        } +    }); +    observer.observe(player, { +        childList: true, +        subtree: true +    }); +} +// Initialise the mutation observer when the video player becomes available. +function init() { +    wait_element_1.default('.watch-video--player-view') +        .then(function (player) { +        init_mutation_observer(player); +    }); +} +exports.default = init; + +},{"./logger":4,"./wait_element":7}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true });  // Adds CSS to the page to hide superfluous user interface elements.  function styles() {      var style = document.createElement('style'); @@ -178,12 +225,12 @@ function styles() {      var stylesheet = style.sheet;      // 2021.08.13: May want to remove `.player-view-childrens`, which is now      // replaced by `.advisory-container`. -    stylesheet.insertRule("\n\t\t/* \"Back to Browse\" button that appears when credits are minimised. */\n\t\t.OriginalsPostPlay-BackgroundTrailer .BackToBrowse,\n\n\t\t/* Promo that appears during credis */\n\t\t.OriginalsPostPlay-BackgroundTrailer,\n\n\t\t/* Age rating. */\n\t\t.player-view-childrens,\n\t\t.advisory-container,\n\n\t\t/* \"Watch Credits\" button. */\n\t\t[data-uia=\"watch-credits-seamless-button\"],\n\n\t\t/* Skip buttons. */\n\t\ta[aria-label=\"Skip Intro\"],\n\t\ta[aria-label=\"Skip Recap\"],\n\t\ta[aria-label=\"Next Episode\"],\n\t\t[data-uia=\"next-episode-seamless-button\"] {\n\t\t\tvisibility: hidden !important;\n\t\t}", stylesheet.cssRules.length); +    stylesheet.insertRule("\n\t\t/* \"Back to Browse\" button that appears when credits are minimised. */\n\t\t.OriginalsPostPlay-BackgroundTrailer .BackToBrowse,\n\t\t.watch-video--seamless-back,\n\n\t\t/* Promo that appears during credis */\n\t\t.OriginalsPostPlay-BackgroundTrailer,\n\t\t.SeamlessControls--background-artwork-visible,\n\n\t\t/* Age rating. */\n\t\t.player-view-childrens,\n\t\t.advisory-container,\n\n\t\t/* \"Watch Credits\" button. */\n\t\t[data-uia=\"watch-credits-seamless-button\"],\n\n\t\t/* Skip buttons. */\n\t\ta[aria-label=\"Skip Intro\"],\n\t\ta[aria-label=\"Skip Recap\"],\n\t\ta[aria-label=\"Next Episode\"],\n\t\t[data-uia=\"next-episode-seamless-button\"] {\n\t\t\tvisibility: hidden !important;\n\t\t}", stylesheet.cssRules.length);      stylesheet.insertRule("\n\t\t/* Remove white border around credits. */\n\t\t.NFPlayer.can-resume:hover {\n\t\t\tborder: none !important;\n\t\t}", stylesheet.cssRules.length);  }  exports.default = styles; -},{}],6:[function(require,module,exports){ +},{}],7:[function(require,module,exports){  "use strict";  Object.defineProperty(exports, "__esModule", { value: true });  var logger_1 = require("./logger"); @@ -203,7 +250,7 @@ function wait_element(selector) {  }  exports.default = wait_element; -},{"./logger":4}],7:[function(require,module,exports){ +},{"./logger":4}],8:[function(require,module,exports){  "use strict";  Object.defineProperty(exports, "__esModule", { value: true });  var controls_1 = require("./controls"); @@ -242,4 +289,4 @@ function init() {  }  exports.default = init; -},{"./controls":1,"./logger":4,"./wait_element":6}]},{},[3]); +},{"./controls":1,"./logger":4,"./wait_element":7}]},{},[3]); diff --git a/src/index.ts b/src/index.ts index 4d3a951..237d232 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -// Copyright (c) 2020  Teddy Wing +// Copyright (c) 2020–2021  Teddy Wing  //  // This file is part of Immersive.  // @@ -17,6 +17,7 @@  import fullscreen_credits from './fullscreen_credits';  import logger from './logger'; +import seamless from './seamless';  import styles from './styles';  import watch_credits from './watch_credits'; @@ -27,6 +28,7 @@ function main () {  	styles();  	fullscreen_credits();  	watch_credits(); +	seamless();  } diff --git a/src/seamless.ts b/src/seamless.ts new file mode 100644 index 0000000..50595d9 --- /dev/null +++ b/src/seamless.ts @@ -0,0 +1,73 @@ +// Copyright (c) 2021  Teddy Wing +// +// This file is part of Immersive. +// +// Immersive is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Immersive is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Immersive. If not, see <https://www.gnu.org/licenses/>. + +import logger from './logger'; +import wait_element from './wait_element'; + + +// Hide the cursor when seamless credits are played. +function init_mutation_observer (player) { +	const observer = new MutationObserver(function(mutation_list) { +		for (var i = 0; i < mutation_list.length; i++) { +			const mutation = mutation_list[i]; +			const player = mutation.target as HTMLElement; + +			const seamless_controls = document.querySelector( +				'.SeamlessControls--container' +			); + +			if (seamless_controls) { +				logger.debug('seamless', 'init_mutation_observer()', 'Handling seamless'); +				const style_el = document.createElement('style'); + +				// Hide the cursor. +				document.head.appendChild(style_el); + +				const stylesheet = style_el.sheet as CSSStyleSheet; + +				stylesheet.insertRule(` +					body { +						cursor: none !important; +					}`, +					stylesheet.cssRules.length +				); + +				document.body.onmousemove = function() { +					document.head.removeChild(style_el); +				} + +				return; +			} +		} +	}); + +	observer.observe( +		player, +		{ +			childList: true, +			subtree: true +		} +	); +} + +// Initialise the mutation observer when the video player becomes available. +export default function init () { +	wait_element('.watch-video--player-view') +		.then(function(player) { +			init_mutation_observer(player); +		}); +} diff --git a/src/styles.ts b/src/styles.ts index 3661fff..2b6ba24 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -28,9 +28,11 @@ export default function styles () {  	stylesheet.insertRule(`  		/* "Back to Browse" button that appears when credits are minimised. */  		.OriginalsPostPlay-BackgroundTrailer .BackToBrowse, +		.watch-video--seamless-back,  		/* Promo that appears during credis */  		.OriginalsPostPlay-BackgroundTrailer, +		.SeamlessControls--background-artwork-visible,  		/* Age rating. */  		.player-view-childrens, | 
