Compare commits
10 Commits
53adcfaf1e
...
master
Author | SHA1 | Date | |
---|---|---|---|
73eea44c7e | |||
55ca6491b0 | |||
9602ee3177 | |||
5cf1ab851f | |||
d9c6e2ca05 | |||
64b2623790 | |||
ec46bd5302 | |||
7d15cf00b4 | |||
2414a593c4 | |||
95f297d520 |
@@ -1,6 +1,7 @@
|
||||
# Better Youtube +
|
||||
Better YouTube + works to improve the YouTube experience by providing quick access to features we'd all like to have from the get-go.
|
||||
<br/>
|
||||
* It defaults playback to 1080p if able to.
|
||||
* It allows quick thumbnail access of the video.
|
||||
* It allows setting the loop mode easily.
|
||||
* It allows setting the loop mode to a ranged set.
|
||||
@@ -11,8 +12,8 @@ Better YouTube + works to improve the YouTube experience by providing quick acce
|
||||
* It shows volume level as you scroll.
|
||||
* It lets Unix, Linux, and MacOS systems have the ability to download the video using native app calls.
|
||||
|
||||
# Version: 1.5.4
|
||||
* Fixed loop breakage
|
||||
# Version: 1.6.1
|
||||
* Fixing click dead zones; changesd dl icon.
|
||||
|
||||
# Download
|
||||
https://addons.mozilla.org/en-US/firefox/addon/better-youtube-plus/
|
||||
@@ -33,4 +34,4 @@ To get downloading working do the following:
|
||||
1. Check that the [file permissions](https://en.wikipedia.org/wiki/File_system_permissions) for "youtube-dl-bridge.py" include the `execute` permission.
|
||||
2. Edit the "path" property of "web_video_dl.json" to point to the location of "youtube-dl-bridge.py" on your computer.
|
||||
3. copy "web_video_dl.json" to the correct location on your computer. See [App manifest location ](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_manifests#Manifest_location) to find the correct location for your OS.
|
||||
4. Install the webextension and enjoy!
|
||||
4. Install the webextension and enjoy!
|
BIN
images/pic1.png
BIN
images/pic1.png
Binary file not shown.
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 5.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 11 KiB |
149
src/inject.js
Normal file
149
src/inject.js
Normal file
@@ -0,0 +1,149 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
// ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto']
|
||||
const prefs = {
|
||||
hd: true,
|
||||
once: false,
|
||||
higher: true,
|
||||
quality: ["hd1080"],
|
||||
log: false,
|
||||
highFramerate: true
|
||||
};
|
||||
|
||||
|
||||
const script = document.createElement('script');
|
||||
Object.assign(script.dataset, prefs);
|
||||
script.textContent = `
|
||||
window.yttools = window.yttools || [];
|
||||
|
||||
{
|
||||
const isTypeSupported = MediaSource.isTypeSupported;
|
||||
MediaSource.isTypeSupported = function(videoType) {
|
||||
const prefs = resolutionChangeListener.prefs;
|
||||
// Block all queries regarding high-framerate support.
|
||||
if (prefs.highFramerate === 'false') {
|
||||
const matches = videoType.match(/framerate=(\\d+)/);
|
||||
if (matches && (matches[1] > 30)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return isTypeSupported(videoType);
|
||||
}
|
||||
}
|
||||
|
||||
function resolutionChangeListener(e) {
|
||||
const prefs = resolutionChangeListener.prefs;
|
||||
const player = resolutionChangeListener.player;
|
||||
const log = (...args) => prefs.log === 'true' && console.log('Better-Youtube-Plus: ', ...args);
|
||||
|
||||
try {
|
||||
if (e === 1 && player) {
|
||||
const levels = player.getAvailableQualityLevels();
|
||||
if (levels.length === 0) {
|
||||
return log("Returned empty quality levels...");
|
||||
}
|
||||
|
||||
// ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto']
|
||||
const qualities = player.getAvailableQualityLevels();
|
||||
const q = player.getPlaybackQuality();
|
||||
// if ((q.startsWith('h') && prefs.quality.startsWith('h')) && prefs.hd === 'true') {
|
||||
// console.log("Quality matches requested resolution...");
|
||||
// return;
|
||||
// }
|
||||
|
||||
const compare = (q1, q2) => {
|
||||
if (q2 === 'auto') {
|
||||
return false;
|
||||
}
|
||||
const i1 = qualities.indexOf(q1);
|
||||
const i2 = qualities.indexOf(q2);
|
||||
if (i1 === -1 || i2 === -1) {
|
||||
return false;
|
||||
}
|
||||
return i1 - i2 <= 0;
|
||||
};
|
||||
|
||||
if (prefs.higher === 'true' && compare(q, prefs.quality)) {
|
||||
return log('Quality is higher than ' + prefs.quality + '... skipping quality change.');
|
||||
}
|
||||
if (q === prefs.quality) {
|
||||
return log('Selected quality is okay...');
|
||||
}
|
||||
|
||||
const find = increase => {
|
||||
if (prefs.quality === 'highest') {
|
||||
return levels[0];
|
||||
}
|
||||
else {
|
||||
if (increase) {
|
||||
prefs.quality = qualities[qualities.indexOf(prefs.quality) - 1] || levels[0];
|
||||
}
|
||||
const index = levels.indexOf(prefs.quality);
|
||||
if (index !== -1) {
|
||||
return prefs.quality;
|
||||
}
|
||||
return find(true);
|
||||
}
|
||||
};
|
||||
|
||||
const nq = find();
|
||||
if (q === nq) {
|
||||
return log('Requested quality is unavailable... skipping change.');
|
||||
}
|
||||
player.setPlaybackQuality(nq);
|
||||
try {
|
||||
player.setPlaybackQualityRange(nq, nq);
|
||||
}
|
||||
catch (e) {}
|
||||
if (prefs.once === 'true') {
|
||||
player.removeEventListener('onStateChange', 'resolutionChangeListener');
|
||||
window.resolutionChangeListener = () => {};
|
||||
log("Removing Listener...");
|
||||
}
|
||||
|
||||
log('Quality was ' + q + ' and now is set to ' + nq);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
log(e);
|
||||
}
|
||||
}
|
||||
|
||||
resolutionChangeListener.prefs = document.currentScript.dataset;
|
||||
window.yttools.push(e => {
|
||||
resolutionChangeListener.player = e;
|
||||
resolutionChangeListener(1);
|
||||
e.addEventListener('onStateChange', resolutionChangeListener);
|
||||
});
|
||||
|
||||
function onYouTubePlayerReady(player) {
|
||||
if (yttools.resolved !== true) {
|
||||
yttools.resolved = true;
|
||||
yttools.forEach(c => {
|
||||
try {
|
||||
c(player);
|
||||
}
|
||||
catch (e) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('spfready', () => {
|
||||
if (typeof window.ytplayer === 'object' && window.ytplayer.config && yttools.resolved !== true) {
|
||||
window.ytplayer.config.args.jsapicallback = 'onYouTubePlayerReady';
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('yt-navigate-finish', () => {
|
||||
const player = document.querySelector('.html5-video-player');
|
||||
if (player && yttools.resolved !== true) {
|
||||
yttools.resolved = true;
|
||||
yttools.forEach(c => c(player));
|
||||
}
|
||||
});
|
||||
`;
|
||||
|
||||
document.documentElement.appendChild(script);
|
||||
script.remove();
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Better Youtube +",
|
||||
"version": "1.5.4",
|
||||
"version": "1.6.3",
|
||||
"description": "Enhancements for Youtube to have a better experience.",
|
||||
|
||||
"applications": {
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "betterYoutube@itdominator.com"
|
||||
}
|
||||
@@ -13,13 +13,20 @@
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"tabs",
|
||||
"*://*.youtube.com/*"
|
||||
"*://www.youtube.com/*"
|
||||
],
|
||||
|
||||
"content_scripts": [{
|
||||
"matches": ["*://www.youtube.com/*"],
|
||||
"js": ["inject.js"],
|
||||
"run_at": "document_start",
|
||||
"all_frames": true
|
||||
}],
|
||||
|
||||
"icons": {
|
||||
"48": "icons/betterYoutube_48.png",
|
||||
"96": "icons/betterYoutube_96.png"
|
||||
},
|
||||
|
||||
"background": { "scripts": ["scripts/background.js"] }
|
||||
}
|
||||
}
|
@@ -1,11 +1,20 @@
|
||||
(function() {
|
||||
const menuTemplate = `
|
||||
<div class="ytMenuStyle" id="enhancerMenuID" style="display: block;">
|
||||
<div id="ytThumbnailBttn" class="imageStyle" title="Video Thumbnails..."></div>
|
||||
<div id="ytLoopBttn" class="imageStyle" title="Start Loop..."/></div>
|
||||
<div id="ytFloatBttn" class="imageStyle" title="Float Video Container"/></div>
|
||||
<div id="ytDownloadBttn" class="imageStyle" title="Download Video..."/></div>
|
||||
</div>
|
||||
<ul class="ytMenuStyle" id="enhancerMenuID" style="display: block;">
|
||||
<li>
|
||||
<div id="ytThumbnailBttn" class="imageStyle" title="Video Thumbnails..."></div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ytLoopBttn" class="imageStyle" title="Start Loop..."/></div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ytFloatBttn" class="imageStyle" title="Float Video Container"/></div>
|
||||
</li>
|
||||
<li>
|
||||
<div id="ytDownloadBttn" class="imageStyle" title="Download Video..."/></div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
`
|
||||
const slugTemplate = `
|
||||
<div id="enhancerMenuID2">
|
||||
@@ -22,15 +31,23 @@
|
||||
</div>
|
||||
`
|
||||
const thumbnailTemplate = `
|
||||
<div id="ytThumbMenuID" class="ytThumbMenuStyle" style="display: none;">
|
||||
<a id="ytAMaxDefaultImgID" target="_blank" href=""><img id="ytMaxDefaultImgID" class="thumbImageStyle" src="" title="Max Resolution Default"/></a>
|
||||
<a id="ytAHqDefaultImgID" target="_blank" href=""><img id="ytHqDefaultImgID" class="thumbImageStyle" src="" title="High Quality Default"/></a>
|
||||
<a id="ytAMedDefaultImgID" target="_blank" href=""><img id="ytMqDefaultImgID" class="thumbImageStyle" src="" title="Medium Quality Default"></a>
|
||||
<a id="ytASdDefaultImgID" target="_blank" href=""><img id="ytSdDefaultImgID" class="thumbImageStyle" src="" title="Standard Quality Default"/></a>
|
||||
</div>
|
||||
<ul id="ytThumbMenuID" class="ytThumbMenuStyle" style="display: none;">
|
||||
<li>
|
||||
<a id="ytAMaxDefaultImgID" target="_blank" href=""><img id="ytMaxDefaultImgID" class="thumbImageStyle" src="" title="Max Resolution Default"/></a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="ytAHqDefaultImgID" target="_blank" href=""><img id="ytHqDefaultImgID" class="thumbImageStyle" src="" title="High Quality Default"/></a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="ytAMedDefaultImgID" target="_blank" href=""><img id="ytMqDefaultImgID" class="thumbImageStyle" src="" title="Medium Quality Default"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a id="ytASdDefaultImgID" target="_blank" href=""><img id="ytSdDefaultImgID" class="thumbImageStyle" src="" title="Standard Quality Default"/></a>
|
||||
</li>
|
||||
</ul>
|
||||
`
|
||||
const popedContainerTemplate = `
|
||||
<div id="draggable" style="display:none; block; top: 114px; left: 408px;">
|
||||
<div id="ytDraggable" style="display:none; bottom: 0px; right: 0px;">
|
||||
<iframe id="popIframe" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
autoplay="" allowfullscreen="true" width="650px" height="400px" frameborder="0" src="" />
|
||||
</iframe>
|
||||
@@ -78,13 +95,27 @@
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}, 500); // check every 500ms
|
||||
}, 500);
|
||||
|
||||
const setupProcess = () => {
|
||||
loadUI();
|
||||
setupVariables();
|
||||
fillUIAndSetupEvents();
|
||||
setupObservers();
|
||||
setupVariables().then(() => {
|
||||
let tid = -1;
|
||||
|
||||
function timer() {
|
||||
// Video Controler
|
||||
video = document.getElementsByTagName("video")[0];
|
||||
|
||||
if (video) {
|
||||
clearInterval(tid);
|
||||
|
||||
fillUIAndSetupEvents();
|
||||
setupObservers();
|
||||
}
|
||||
}
|
||||
|
||||
tid = setInterval(timer, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
const loadUI = () => {
|
||||
@@ -115,7 +146,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
const setupVariables = () => {
|
||||
const setupVariables = async () => {
|
||||
ytEnhancerMenu2 = document.getElementById("enhancerMenuID2");
|
||||
ytThumbnailBttn = document.getElementById("ytThumbnailBttn");
|
||||
ytLoopBttn = document.getElementById("ytLoopBttn");
|
||||
@@ -137,23 +168,19 @@
|
||||
ytMqDefaultImg = document.getElementById("ytMqDefaultImgID");
|
||||
ytSdDefaultImg = document.getElementById("ytSdDefaultImgID");
|
||||
|
||||
poppedContainer = document.getElementById("draggable");
|
||||
poppedContainer = document.getElementById("ytDraggable");
|
||||
ytIfrm = document.getElementById("popIframe");
|
||||
slugInputTag = document.getElementById("slugCopyZone");
|
||||
|
||||
// Video Controler
|
||||
video = document.getElementsByTagName("video")[0];
|
||||
// Container of actual player (Used for floating window)
|
||||
containerOfPlyrWndow = document.getElementById("player-container");
|
||||
|
||||
part = "https://img.youtube.com/vi/";
|
||||
part = "https://img.youtube.com/vi/";
|
||||
}
|
||||
|
||||
const fillUIAndSetupEvents = () => {
|
||||
slugInputTag.value = video.baseURI.slice(32, 32+11);
|
||||
ytRangeStart.value = "0:00";
|
||||
|
||||
// We need to wait for info to load before getting full duration
|
||||
setTimeout(function () {
|
||||
videoTimeLength = document.getElementsByClassName("ytp-time-duration")[0].innerText;
|
||||
ytRangeEnd.value = videoTimeLength;
|
||||
@@ -206,7 +233,10 @@
|
||||
controlsShowHideToggle(mutation.target);
|
||||
} else if (mutation.type === 'childList') {
|
||||
if (this.isEndlessWatch) {
|
||||
let elm = document.querySelector(dialogElementQueryRef).parentElement;
|
||||
let target = document.querySelector(dialogElementQueryRef);
|
||||
if (!target) continue
|
||||
|
||||
let elm = target.parentElement;
|
||||
elmDisplayState = elm.style.display;
|
||||
if (elmDisplayState !== 'none' && modalHasBeenClosed == false) {
|
||||
modalHasBeenClosed = true;
|
||||
@@ -221,7 +251,7 @@
|
||||
};
|
||||
|
||||
const controlsShowHideToggle = (elm) => {
|
||||
attrib = elm.getAttribute('masthead-hidden_');
|
||||
attrib = elm.getAttribute('masthead-hidden');
|
||||
if (attrib == null) { // if out of fullscreen
|
||||
ytEnhancerMenu.style.display = "block";
|
||||
ytEnhancerMenu2.style.display = "block";
|
||||
@@ -282,7 +312,7 @@
|
||||
clearInterval(ytVideoIntervalLoop);
|
||||
loopingInterval = false;
|
||||
ytLoopBttn.title = "Start Loop...";
|
||||
let ipath = browser.extension.getURL("/icons/loopFalse.png");
|
||||
let ipath = browser.runtime.getURL("/icons/loopFalse.png");
|
||||
setbuttonImage(ytLoopBttn, ipath);
|
||||
return ;
|
||||
}
|
||||
@@ -292,13 +322,13 @@
|
||||
console.log("Setting default loop marker...");
|
||||
video.loop = true;
|
||||
ytLoopBttn.title = "Stop Loop...";
|
||||
let ipath = browser.extension.getURL("/icons/loopTrue.png");
|
||||
let ipath = browser.runtime.getURL("/icons/loopTrue.png");
|
||||
setbuttonImage(ytLoopBttn, ipath);
|
||||
} else {
|
||||
console.log("Unsetting default loop marker...");
|
||||
video.loop = false;
|
||||
ytLoopBttn.title = "Start Loop...";
|
||||
let ipath = browser.extension.getURL("/icons/loopFalse.png");
|
||||
let ipath = browser.runtime.getURL("/icons/loopFalse.png");
|
||||
setbuttonImage(ytLoopBttn, ipath);
|
||||
}
|
||||
return ;
|
||||
@@ -339,7 +369,7 @@
|
||||
|
||||
// Setup interval check for 1 sec and compare value of current pos to end
|
||||
ytLoopBttn.title = "Stop Loop...";
|
||||
let ipath = browser.extension.getURL("/icons/loopTrue.png");
|
||||
let ipath = browser.runtime.getURL("/icons/loopTrue.png");
|
||||
setbuttonImage(ytLoopBttn, ipath);
|
||||
loopingInterval = true;
|
||||
|
||||
@@ -449,7 +479,8 @@
|
||||
if(e.preventDefault) e.preventDefault();
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,6 +490,6 @@
|
||||
}
|
||||
|
||||
const setbuttonImage = (elm, path) => {
|
||||
elm.style.backgroundImage = "url('" + browser.extension.getURL(path); + "')";
|
||||
elm.style.backgroundImage = "url('" + browser.runtime.getURL(path); + "')";
|
||||
}
|
||||
}());
|
||||
}());
|
@@ -11,11 +11,11 @@ yt-formatted-string > a:hover {
|
||||
|
||||
/* ID CSS */
|
||||
#enhancerMenuID2, .ytThumbMenuStyle, .ytMenuStyle {
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
background: rgba(0,0,0,0.64);
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
z-index: 100;
|
||||
position: fixed;
|
||||
background: rgba(0,0,0,0.64);
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#enhancerMenuID2 {
|
||||
@@ -25,8 +25,8 @@ yt-formatted-string > a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#enhancerMenuID, #enhancerMenuID2 {
|
||||
z-index: 5;
|
||||
#enhancerMenuID, #enhancerMenuID2, #ytThumbMenuID {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#volumeContainerID {
|
||||
@@ -36,17 +36,17 @@ yt-formatted-string > a:hover {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#draggable {
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 650px;
|
||||
height: 400px;
|
||||
padding-top: 50px;
|
||||
border-style: solid;
|
||||
border-color: rgba(0, 232, 255, 0.64);
|
||||
background: rgba(64, 64, 64, 0.64)
|
||||
#ytDraggable {
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 650px;
|
||||
height: 400px;
|
||||
padding-top: 50px;
|
||||
border-style: solid;
|
||||
border-color: rgba(0, 232, 255, 0.64);
|
||||
background: rgba(64, 64, 64, 0.64)
|
||||
}
|
||||
|
||||
#rangeEndID, #rangeStartID {
|
||||
@@ -56,9 +56,9 @@ yt-formatted-string > a:hover {
|
||||
}
|
||||
|
||||
#slugCopyZone, #rangeEndID, #rangeStartID {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
background: rgba(0,0,0,0.0);
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,34 +66,42 @@ yt-formatted-string > a:hover {
|
||||
.ytMenuStyle {
|
||||
top: 40%;
|
||||
width: 42px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ytThumbMenuStyle {
|
||||
display: none;
|
||||
bottom: 20px;
|
||||
display: none;
|
||||
bottom: 20px;
|
||||
}
|
||||
|
||||
.ytThumbMenuStyle > ul,
|
||||
.ytThumbMenuStyle > li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.ytThumbMenuStyle > li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.imageStyle {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: rgba(0,0,0,.64);
|
||||
background-size: 42px 42px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: rgba(0,0,0,.64);
|
||||
background-size: 42px 42px;
|
||||
}
|
||||
|
||||
.imageStyle:hover {
|
||||
background: rgba(12,160,193,.64);
|
||||
cursor: pointer;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 28px 28px;
|
||||
background: rgba(12,160,193,.64);
|
||||
cursor: pointer;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 28px 28px;
|
||||
}
|
||||
|
||||
.thumbImageStyle {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
margin: 0em 1em 0em 1em;
|
||||
float: left;
|
||||
}
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
margin: 0em 1em 0em 1em;
|
||||
float: left;
|
||||
}
|
Reference in New Issue
Block a user