aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTeddy Wing2020-05-08 17:09:50 +0200
committerTeddy Wing2020-05-08 17:16:47 +0200
commitc692a0a50ac8af8849e22dbca0326c274e50db38 (patch)
treecd2d15ad3fc41eaec5cdcaf27750d6f17367e18a /src
parent09de14b4812e82ff30dae2e1d6b892bc1d076d09 (diff)
downloadnetflix-immersive-c692a0a50ac8af8849e22dbca0326c274e50db38.tar.bz2
Automatically click the "Watch Credits" button
TV series on Netflix now display a "Watch Credits" button when the credits start rolling. We can hide this button using CSS and the credits will continue playing to the end, but while it's displayed, the player controls are hidden. Automatically click the button to make it go away and reactivate the player controls. The tricky thing, though, is that the "Watch Credits" button doesn't have a click handler. Instead, it listens to the "pointerdown" event, so we have to construct one programmatically (and turn on `bubbles`, otherwise the button doesn't react to the event) and dispatch it. Moved `with_player` to `wait_element`, because now I need to wait for more DOM elements than just the player element. Add a new `controls` module since I need to hide the player controls in both `fullscreen_credits` and `watch_credits`. Add the `DOM` lib to `tsconfig.json` to give us DOM types.
Diffstat (limited to 'src')
-rw-r--r--src/controls.ts23
-rw-r--r--src/fullscreen_credits.ts17
-rw-r--r--src/index.ts2
-rw-r--r--src/logger.ts5
-rw-r--r--src/player.ts16
-rw-r--r--src/wait_element.ts16
-rw-r--r--src/watch_credits.ts49
7 files changed, 102 insertions, 26 deletions
diff --git a/src/controls.ts b/src/controls.ts
new file mode 100644
index 0000000..ad8f47c
--- /dev/null
+++ b/src/controls.ts
@@ -0,0 +1,23 @@
+import logger from './logger';
+import wait_element from './wait_element';
+
+
+const controls = {
+ hide: function() {
+ logger.debug('hide():', 'Hiding controls');
+
+ wait_element('.PlayerControlsNeo__layout.PlayerControlsNeo__layout--active')
+ .then(function(controls) {
+ logger.debug('hide():', 'Controls:', controls);
+
+ controls
+ .classList
+ .replace(
+ 'PlayerControlsNeo__layout--active',
+ 'PlayerControlsNeo__layout--inactive'
+ );
+ });
+ }
+};
+
+export default controls;
diff --git a/src/fullscreen_credits.ts b/src/fullscreen_credits.ts
index d8b68b9..9844bb3 100644
--- a/src/fullscreen_credits.ts
+++ b/src/fullscreen_credits.ts
@@ -1,4 +1,5 @@
-import with_player from './player';
+import controls from './controls';
+import wait_element from './wait_element';
function init_mutation_observer (player) {
@@ -24,12 +25,7 @@ function init_mutation_observer (player) {
// .classList
// .add('PlayerControlsNeo__bottom-controls--faded');
- document.querySelector('.PlayerControlsNeo__layout.PlayerControlsNeo__layout--active')
- .classList
- .replace(
- 'PlayerControlsNeo__layout--active',
- 'PlayerControlsNeo__layout--inactive'
- );
+ controls.hide();
// .OriginalsPostPlay-BackgroundTrailer .BackToBrowse
@@ -48,7 +44,8 @@ function init_mutation_observer (player) {
}
export default function init () {
- with_player().then(function(player) {
- init_mutation_observer(player);
- });
+ wait_element('.NFPlayer.nf-player-container')
+ .then(function(player) {
+ init_mutation_observer(player);
+ });
}
diff --git a/src/index.ts b/src/index.ts
index 504a7d7..0097f62 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,8 @@
import fullscreen_credits from './fullscreen_credits';
+import watch_credits from './watch_credits';
import { styles } from './styles';
fullscreen_credits();
+watch_credits();
styles();
diff --git a/src/logger.ts b/src/logger.ts
new file mode 100644
index 0000000..d03b6f8
--- /dev/null
+++ b/src/logger.ts
@@ -0,0 +1,5 @@
+export default {
+ debug(...args) {
+ console.debug('NoSkip:', ...args);
+ }
+};
diff --git a/src/player.ts b/src/player.ts
deleted file mode 100644
index ea0e541..0000000
--- a/src/player.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export default function with_player (): Promise<HTMLElement> {
- return new Promise(function(resolve) {
- const interval = setInterval(
- function() {
- const player = document.querySelector('.NFPlayer.nf-player-container');
-
- if (player) {
- clearInterval(interval);
-
- resolve(player);
- }
- },
- 1000
- );
- });
-}
diff --git a/src/wait_element.ts b/src/wait_element.ts
new file mode 100644
index 0000000..f24b891
--- /dev/null
+++ b/src/wait_element.ts
@@ -0,0 +1,16 @@
+export default function wait_element (selector: string): Promise<Element> {
+ return new Promise(function(resolve) {
+ const interval = setInterval(
+ function() {
+ const element = document.querySelector(selector);
+
+ if (element) {
+ clearInterval(interval);
+
+ resolve(element);
+ }
+ },
+ 1000
+ );
+ });
+}
diff --git a/src/watch_credits.ts b/src/watch_credits.ts
new file mode 100644
index 0000000..3aba520
--- /dev/null
+++ b/src/watch_credits.ts
@@ -0,0 +1,49 @@
+import controls from './controls';
+import logger from './logger';
+import wait_element from './wait_element';
+
+
+// const watch_credits_button = document.querySelector('[data-uia="watch-credits-seamless-button"]');
+
+
+
+function init_mutation_observer (controls) {
+ var observer = new MutationObserver(function(mutation_list) {
+ for (var i = 0; i < mutation_list.length; i++) {
+ var mutation = mutation_list[i];
+ var element = mutation.target as HTMLElement;
+
+ var watch_credits_button: HTMLButtonElement = element.querySelector(
+ '[data-uia="watch-credits-seamless-button"]'
+ );
+
+ if (watch_credits_button) {
+ logger.debug('found Watch Credits button', watch_credits_button);
+
+ var pointer_event = new PointerEvent('pointerdown', { bubbles: true });
+ watch_credits_button.dispatchEvent(pointer_event);
+
+ controls.hide();
+
+ return;
+ }
+ }
+ });
+
+ observer.observe(
+ controls,
+ {
+ childList: true,
+ subtree: true
+ }
+ );
+}
+
+export default function init () {
+ wait_element('.PlayerControlsNeo__all-controls')
+ .then(function(controls) {
+ logger.debug('Controls element:', controls);
+
+ init_mutation_observer(controls);
+ });
+}