Skip to content

Commit c3267d6

Browse files
author
hoang.tran12
committed
add youtube nonstop
1 parent 32149b9 commit c3267d6

File tree

3 files changed

+208
-1
lines changed

3 files changed

+208
-1
lines changed

popup/tabs.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,10 @@ const tabs = [
104104
scripts: [
105105
s.youtube_downloadVideo,
106106
s.pictureInPicture,
107-
s.youtube_popupPlayer,
108107
s.youtube_toggleLight,
109108
s.youtube_viewDislikes,
109+
s.youtube_nonstop,
110+
s.youtube_popupPlayer,
110111
],
111112
},
112113
{

scripts/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ import getAllEmailsInWeb from "./getAllEmailsInWeb.js";
9292
import showTheImages from "./showTheImages.js";
9393
import showHiddenFields from "./showHiddenFields.js";
9494
import cssSelectorViewer from "./cssSelectorViewer.js";
95+
import youtube_nonstop from "./youtube_nonstop.js";
9596

9697
// inject badges
9798
const allScripts = {
@@ -190,6 +191,7 @@ const allScripts = {
190191
showTheImages: addBadge(showTheImages, BADGES.new),
191192
showHiddenFields: addBadge(showHiddenFields, BADGES.new),
192193
cssSelectorViewer: addBadge(cssSelectorViewer, BADGES.new),
194+
youtube_nonstop: addBadge(youtube_nonstop, BADGES.new),
193195
};
194196

195197
// inject id to all scripts

scripts/youtube_nonstop.js

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
export default {
2+
icon: "https://lh3.googleusercontent.com/OS9P4SJOFAg8lhCyaRTJ7y4ADF0TGpqFF904BcpCtdBjJIDBbNb_J8PpgoJ9QvariiG_RzgH8fCSSY_kQu-chQQ0Aw=w128-h128-e365-rj-sc0x00ffffff",
3+
name: {
4+
en: "Youtube nonstop",
5+
vi: "Youtube nonstop",
6+
},
7+
description: {
8+
en: 'Kiss the annoying "Video paused. Continue watching?" confirmation goodbye!',
9+
vi: "Phát youtube không còn bị làm phiền bởi popup 'Video đã tạm dừng. Bạn có muốn xem tiếp?' của youtube.",
10+
},
11+
blackList: [],
12+
whiteList: ["*://music.youtube.com", "*://www.youtube.com"],
13+
14+
func: function () {
15+
// source code from: https://chrome.google.com/webstore/detail/youtube-nonstop/nlkaejimjacpillmajjnopmpbkbnocid
16+
17+
try {
18+
const tag = "[Youtube NonStop]";
19+
const isYoutubeMusic = window.location.hostname === "music.youtube.com";
20+
21+
const popupEventNodename = isYoutubeMusic
22+
? "YTMUSIC-YOU-THERE-RENDERER"
23+
: "YT-CONFIRM-DIALOG-RENDERER";
24+
25+
const MutationObserver =
26+
window.MutationObserver || window.WebKitMutationObserver;
27+
let appObserver = null;
28+
const appName = isYoutubeMusic ? "ytmusic-app" : "ytd-app";
29+
const popupContainer = isYoutubeMusic
30+
? "ytmusic-popup-container"
31+
: "ytd-popup-container";
32+
33+
let pauseRequested = false;
34+
let pauseRequestedTimeout;
35+
const pauseRequestedTimeoutMillis = 5000;
36+
const idleTimeoutMillis = 5000;
37+
let lastInteractionTime = new Date().getTime();
38+
39+
let videoElement = null;
40+
41+
function log(message) {
42+
console.log(`${tag}[${getTimestamp()}] ${message}`);
43+
}
44+
45+
function debug(message) {
46+
console.debug(`${tag}[${getTimestamp()}] ${message}`);
47+
}
48+
49+
function asDoubleDigit(value) {
50+
return value < 10 ? "0" + value : value;
51+
}
52+
53+
function getTimestamp() {
54+
let dt = new Date();
55+
let time =
56+
asDoubleDigit(dt.getHours()) +
57+
":" +
58+
asDoubleDigit(dt.getMinutes()) +
59+
":" +
60+
asDoubleDigit(dt.getSeconds());
61+
return time;
62+
}
63+
64+
function isIdle() {
65+
return getIdleTime() >= idleTimeoutMillis;
66+
}
67+
68+
function getIdleTime() {
69+
return new Date().getTime() - lastInteractionTime;
70+
}
71+
72+
function listenForMediaKeys() {
73+
if (navigator.mediaSession === undefined) {
74+
log(
75+
"Your browser doesn't seem to support navigator.mediaSession yet :/"
76+
);
77+
return;
78+
}
79+
debug('Listening to "pause" media key...');
80+
navigator.mediaSession.setActionHandler("pause", () => {
81+
debug("Paused due to [media key pause]");
82+
pauseVideo();
83+
});
84+
navigator.mediaSession.yns_setActionHandler =
85+
navigator.mediaSession.setActionHandler;
86+
navigator.mediaSession.setActionHandler = (action, fn) => {
87+
if (action === "pause") {
88+
debug("Blocked attempt to override media key 'pause' action");
89+
return;
90+
}
91+
navigator.mediaSession.yns_setActionHandler(action, fn);
92+
};
93+
}
94+
95+
function listenForMouse() {
96+
const eventName = window.PointerEvent ? "pointer" : "mouse";
97+
debug(`Using ${eventName} events`);
98+
document.addEventListener(eventName + "down", (e) => {
99+
processInteraction(eventName + "down");
100+
});
101+
102+
document.addEventListener(eventName + "up", (e) => {
103+
processInteraction(eventName + "up");
104+
});
105+
}
106+
107+
function listenForKeyboard() {
108+
document.addEventListener("keydown", (e) => {
109+
processInteraction("keydown");
110+
});
111+
112+
document.addEventListener("keyup", (e) => {
113+
processInteraction("keyup");
114+
});
115+
}
116+
117+
function processInteraction(action) {
118+
if (pauseRequested) {
119+
debug(`Paused due to [${action}]`);
120+
pauseVideo();
121+
return;
122+
}
123+
lastInteractionTime = new Date().getTime();
124+
}
125+
126+
function observeApp() {
127+
debug(`Observing ${appName}...`);
128+
appObserver = new MutationObserver((mutations, observer) => {
129+
overrideVideoPause();
130+
});
131+
132+
appObserver.observe(document.querySelector(appName), {
133+
childList: true,
134+
subtree: true,
135+
});
136+
}
137+
138+
function listenForPopupEvent() {
139+
debug("Listening for popup event...");
140+
document.addEventListener("yt-popup-opened", (e) => {
141+
if (isIdle() && e.detail.nodeName === popupEventNodename) {
142+
debug("[closing popup]");
143+
document.querySelector(popupContainer).handleClosePopupAction_();
144+
pauseVideo();
145+
videoElement.play();
146+
}
147+
});
148+
}
149+
150+
function overrideVideoPause() {
151+
if (videoElement?.yns_pause !== undefined) return;
152+
if (document.querySelector("video") === null) return;
153+
154+
videoElement = document.querySelector("video");
155+
listenForMediaKeys();
156+
debug("Overriding video pause...");
157+
videoElement.yns_pause = videoElement.pause;
158+
videoElement.pause = () => {
159+
debug("Video pause requested");
160+
if (!isIdle()) {
161+
debug("Paused due to [pause]");
162+
pauseVideo();
163+
return;
164+
}
165+
pauseRequested = true;
166+
setPauseRequestedTimeout();
167+
};
168+
}
169+
170+
function setPauseRequestedTimeout(justClear = false) {
171+
clearTimeout(pauseRequestedTimeout);
172+
if (justClear) return;
173+
pauseRequestedTimeout = setTimeout(() => {
174+
pauseRequested = false;
175+
}, pauseRequestedTimeoutMillis);
176+
}
177+
178+
function pauseVideo() {
179+
videoElement?.yns_pause();
180+
pauseRequested = false;
181+
setPauseRequestedTimeout(true);
182+
}
183+
184+
listenForMouse();
185+
listenForKeyboard();
186+
187+
listenForPopupEvent();
188+
observeApp();
189+
190+
log(
191+
`Monitoring YouTube ${
192+
isYoutubeMusic ? "Music " : ""
193+
}for 'Confirm watching?' action...`
194+
);
195+
196+
alert("Youtube nonstop ENABLED\n\nĐã bật Youtube nonstop.");
197+
} catch (e) {
198+
alert(
199+
"Cannot enable youtube nonstop\n\n Không thể bật youtube nonstop\n\n Lỗi/Error: " +
200+
JSON.stringify(e)
201+
);
202+
}
203+
},
204+
};

0 commit comments

Comments
 (0)