Skip to content

Commit dcee1a5

Browse files
committed
feat(queue): hide twitch recommended videos if queued video is next
1 parent 126553c commit dcee1a5

File tree

4 files changed

+53
-42
lines changed

4 files changed

+53
-42
lines changed

content/shared.js

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ chrome.runtime.sendMessage({ started: true }, {}, (response) => {
88

99
// Element may not be available right away when the page loads.
1010
window.getElement = (selector, callback) => {
11-
const search = () => document.querySelector(selector);
1211
let maxAttempts = 10;
1312
let iid = setInterval(() => {
14-
const $el = search();
13+
const $el = document.querySelector(selector);
1514
if ($el || --maxAttempts === 0) {
1615
clearInterval(iid);
1716
}
@@ -21,12 +20,13 @@ window.getElement = (selector, callback) => {
2120
}, 1000);
2221
};
2322

23+
// Adds a Next Video button next to the Play/Pause button of the video player.
2424
window.setNextButton = ($playButton, buttonClass) => {
2525
// Prepend all class names with app name to avoid collisions.
2626
let $thumbnail, $length, $title;
27-
const $nextButton = m('a.veefeed-next-button.' + buttonClass, {
27+
const $nextButton = m('a._veefeed-next-button.' + buttonClass, {
2828
onclick: (e) => {
29-
if ($nextButton.classList.contains('veefeed-show')) {
29+
if ($nextButton.classList.contains('_veefeed-show')) {
3030
window.location = $nextButton.href;
3131
}
3232
e.preventDefault();
@@ -41,14 +41,14 @@ window.setNextButton = ($playButton, buttonClass) => {
4141
}, m('path', {
4242
d: 'M 12,24 20.5,18 12,12 V 24 z M 22,12 v 12 h 2 V 12 h -2 z',
4343
})),
44-
m('div.veefeed-next-video', [
45-
m('div.veefeed-left-side', [
44+
m('div._veefeed-next-video', [
45+
m('div._veefeed-left-side', [
4646
$thumbnail = m('img'),
47-
$length = m('span.veefeed-length'),
47+
$length = m('span._veefeed-length'),
4848
]),
49-
m('div.veefeed-right-side', [
50-
m('div.veefeed-title-head', 'NEXT'),
51-
$title = m('div.veefeed-title'),
49+
m('div._veefeed-right-side', [
50+
m('div._veefeed-title-head', 'NEXT'),
51+
$title = m('div._veefeed-title'),
5252
]),
5353
]),
5454
]);
@@ -59,13 +59,14 @@ window.setNextButton = ($playButton, buttonClass) => {
5959
const onQueueUpdate = (video) => {
6060
if (video) {
6161
$nextButton.href = video.url;
62-
$nextButton.classList.add('veefeed-show');
62+
$nextButton.classList.add('_veefeed-show');
6363
$thumbnail.src = video.thumbnail;
6464
$length.textContent = formatVideoLength(video.length);
6565
$title.textContent = video.title;
6666
} else {
67-
$nextButton.classList.remove('veefeed-show');
67+
$nextButton.classList.remove('_veefeed-show');
6868
}
69+
queuedVideo = video;
6970
};
7071

7172
chrome.runtime.onMessage.addListener((message) => {
@@ -78,3 +79,14 @@ window.setNextButton = ($playButton, buttonClass) => {
7879

7980
return $nextButton;
8081
};
82+
83+
// Called when the video has ended.
84+
// Lets the background page know, in case there is a queued video.
85+
window.videoEnded = (msg) => {
86+
document.body.classList.add('_veefeed-ended');
87+
document.body.classList.toggle('_veefeed-queued-video', !!queuedVideo);
88+
chrome.runtime.sendMessage({
89+
ended: true,
90+
...msg,
91+
});
92+
};

content/style.css

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Since the original website's button classes are used to help style
22
* the next button, some of these properties need to be set as `!important` */
3-
.veefeed-next-button {
3+
._veefeed-next-button {
44
position: relative;
55
width: 0 !important;
66
visibility: hidden;
@@ -11,31 +11,31 @@
1111
}
1212

1313
/* Make the button bigger on Twitch */
14-
.qa-controls-bottom .veefeed-next-button {
14+
.qa-controls-bottom ._veefeed-next-button {
1515
margin-left: 4px;
1616
}
1717

18-
.qa-controls-bottom .veefeed-next-button svg path {
18+
.qa-controls-bottom ._veefeed-next-button svg path {
1919
transform: scale(1.35) translate(-5px, -5px)
2020
}
2121

22-
.veefeed-next-button.veefeed-show {
22+
._veefeed-next-button._veefeed-show {
2323
width: 3em !important;
2424
visibility: visible;
2525
transition: width 200ms;
2626
}
2727

2828
/* Hide YouTube's own Next Video button when veefeed's is shown. */
29-
.veefeed-next-button + .ytp-next-button {
29+
._veefeed-next-button + .ytp-next-button {
3030
transition: width 200ms, visibility 200ms step-end;
3131
}
3232

33-
.veefeed-next-button.veefeed-show + .ytp-next-button {
33+
._veefeed-next-button._veefeed-show + .ytp-next-button {
3434
width: 0;
3535
visibility: none;
3636
}
3737

38-
.veefeed-next-button svg {
38+
._veefeed-next-button svg {
3939
position: absolute;
4040
top: 0;
4141
left: 0;
@@ -44,7 +44,7 @@
4444
fill: #fff;
4545
}
4646

47-
.veefeed-next-video {
47+
._veefeed-next-video {
4848
position: absolute;
4949
left: -3em;
5050
bottom: calc(4em + 5px);
@@ -61,21 +61,21 @@
6161
color: rgba(238, 238, 238);
6262
}
6363

64-
.qa-controls-bottom .veefeed-next-video {
64+
.qa-controls-bottom ._veefeed-next-video {
6565
bottom: calc(4em + 30px);
6666
}
6767

68-
.veefeed-next-video .veefeed-left-side {
68+
._veefeed-next-video ._veefeed-left-side {
6969
position: relative;
7070
}
7171

72-
.veefeed-next-video .veefeed-left-side img {
72+
._veefeed-next-video ._veefeed-left-side img {
7373
width: 160px;
7474
min-width: 160px;
7575
height: 90px;
7676
}
7777

78-
.veefeed-next-video .veefeed-left-side .veefeed-length {
78+
._veefeed-next-video ._veefeed-left-side ._veefeed-length {
7979
position: absolute;
8080
bottom: 3px;
8181
right: 3px;
@@ -86,27 +86,31 @@
8686
vertical-align: top;
8787
}
8888

89-
.veefeed-next-video .veefeed-right-side {
89+
._veefeed-next-video ._veefeed-right-side {
9090
padding: 4px 9px;
9191
}
9292

93-
.veefeed-next-video .veefeed-right-side .veefeed-title-head {
93+
._veefeed-next-video ._veefeed-right-side ._veefeed-title-head {
9494
color: rgba(170, 170, 170) !important;
9595
}
9696

97-
.veefeed-next-video .veefeed-right-side .veefeed-title {
97+
._veefeed-next-video ._veefeed-right-side ._veefeed-title {
9898
color: rgba(238, 238, 238) !important;
9999
}
100100

101-
.player[data-ended="true"] .veefeed-next-button path,
102-
.ytp-play-button[title="Replay"] + .veefeed-next-button path {
101+
body._veefeed-ended ._veefeed-next-button path,
102+
.ytp-play-button[title="Replay"] + ._veefeed-next-button path {
103103
stroke: #6294df;
104104
fill: #6294df;
105105
}
106106

107-
.veefeed-next-button:hover .veefeed-next-video,
108-
.player[data-ended="true"] .veefeed-next-video,
109-
.ytp-play-button[title="Replay"] + .veefeed-next-button .veefeed-next-video {
107+
._veefeed-next-button:hover ._veefeed-next-video,
108+
body._veefeed-ended ._veefeed-next-video,
109+
.ytp-play-button[title="Replay"] + ._veefeed-next-button ._veefeed-next-video {
110110
display: flex;
111111
border: 1px solid #6294df;
112112
}
113+
114+
body._veefeed-queued-video .recommendations-overlay {
115+
display: none;
116+
}

content/twitch.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
/* global chrome, getElement, setNextButton */
1+
/* global chrome, getElement, setNextButton, videoEnded */
22

33
// Wait for player to load.
4-
getElement('.player', ($player) => {
4+
getElement('.player', () => {
55
// Since Twitch VODs don't have a proper title at page load on the tab,
66
// or even after the video loads, we get the title ourselves.
77
getElement('title', ($title) => {
@@ -18,12 +18,10 @@ getElement('.player', ($player) => {
1818
let valuenow = parseFloat($slider.getAttribute('aria-valuenow'));
1919
if (valuemax && valuenow + 1 > valuemax) {
2020
observer.disconnect();
21-
$player.setAttribute('data-ended', 'true');
2221
const $scroll = document.querySelector('main .simplebar-scroll-content');
2322
const $tip =
2423
document.querySelector('.qa-theatre-mode-button span.player-tip');
25-
chrome.runtime.sendMessage({
26-
ended: true,
24+
videoEnded({
2725
scrollTop: $tip.getAttribute('data-tip') === 'Exit Theatre Mode'
2826
? 0 : $scroll.scrollTop,
2927
});

content/youtube.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
/* global chrome, getElement, setNextButton */
1+
/* global chrome, getElement, setNextButton, videoEnded */
22

33
getElement('.ytp-play-button', ($playButton) => {
44
const observer = new MutationObserver(() => {
55
// if the video has ended, the play button will change to a
66
// swirly replay arrow.
77
if ($playButton.getAttribute('title') === 'Replay') {
88
observer.disconnect();
9-
chrome.runtime.sendMessage({
10-
ended: true,
11-
scrollTop: document.body.scrollTop,
12-
});
9+
videoEnded({ scrollTop: document.body.scrollTop });
1310
}
1411
});
1512
observer.observe($playButton, { attributes: true });

0 commit comments

Comments
 (0)