Compare commits

...

8 Commits

7 changed files with 149 additions and 103 deletions

View File

@@ -12,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.7
* Added injection script to default to 1080p playback
# Version: 1.6.4
* Fixing the prior fix causing load degredation
# Download
https://addons.mozilla.org/en-US/firefox/addon/better-youtube-plus/
@@ -34,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!

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

View File

@@ -6,7 +6,7 @@ const prefs = {
hd: true,
once: false,
higher: true,
quality: "hd1080",
quality: ["hd1080"],
log: false,
highFramerate: true
};
@@ -47,10 +47,10 @@ script.textContent = `
// ['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;
}
// 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') {

View File

@@ -1,10 +1,10 @@
{
"manifest_version": 2,
"name": "Better Youtube +",
"version": "1.5.7",
"version": "1.6.4",
"description": "Enhancements for Youtube to have a better experience.",
"applications": {
"browser_specific_settings": {
"gecko": {
"id": "betterYoutube@itdominator.com"
}
@@ -17,7 +17,7 @@
],
"content_scripts": [{
"matches": ["*://www.youtube.com/*"],
"matches": ["https://www.youtube.com/watch=?v=*"],
"js": ["inject.js"],
"run_at": "document_start",
"all_frames": true
@@ -29,4 +29,4 @@
},
"background": { "scripts": ["scripts/background.js"] }
}
}

View File

@@ -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>
@@ -51,40 +68,60 @@
let isEndlessWatch = false;
let shouldHideVol = true;
let OSName = "";
let count = 0;
// confirm dialog elm
const isYoutubeMusic = window.location.hostname === 'music.youtube.com';
let dialogElementQueryRef = isYoutubeMusic ? 'ytmusic-you-there-renderer' : 'yt-confirm-dialog-renderer';
let dialogElementQueryRef = 'yt-confirm-dialog-renderer';
// Options for the observer (which mutations to observe)
let observer, observer2;
let fullscreenObserver, endlessPlayObserver;
const observerConfig = { attributes: true };
const observerConfig2 = { childList: true, subtree: true };
// Start init
let existCondition = setInterval(function() {
if (document.getElementById("masthead-container")) {
clearInterval(existCondition);
// YouTube is a SPA — watch for page changes
const loadObserver = new MutationObserver(() => {
checkPageLoad();
});
loadObserver.observe(document.body, { childList: true, subtree: true });
function isYouTubePageLoaded() {
const videoPlayer = document.querySelector('video');
const titleElement = document.querySelector('#title h1');
return videoPlayer && titleElement && titleElement.textContent.trim().length > 0;
}
function checkPageLoad() {
if (isYouTubePageLoaded()) {
console.log("YouTube page fully loaded.");
loadObserver.disconnect();
setupProcess();
count = 0;
} else {
if (count == 12) { // ~ 6 sec through half sec loops
count = 0;
clearInterval(existCondition);
setupProcess();
} else {
count++;
}
console.log("Waiting for YouTube content...");
}
}, 500); // check every 500ms
}
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 +152,7 @@
}
}
const setupVariables = () => {
const setupVariables = async () => {
ytEnhancerMenu2 = document.getElementById("enhancerMenuID2");
ytThumbnailBttn = document.getElementById("ytThumbnailBttn");
ytLoopBttn = document.getElementById("ytLoopBttn");
@@ -137,13 +174,10 @@
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]; // Actual video object (I think...)
// Container of actual player (Used for floating window)
containerOfPlyrWndow = document.getElementById("player-container");
part = "https://img.youtube.com/vi/";
@@ -182,18 +216,18 @@
// Observer target for fullscreen action...
let targetNode = document.getElementsByTagName('ytd-app')[0];
// Create an observer instance linked to the callback function
observer = new MutationObserver(mutationCallback);
fullscreenObserver = new MutationObserver(mutationCallback);
// Start observing the target node for configured mutations
observer.observe(targetNode, observerConfig);
fullscreenObserver.observe(targetNode, observerConfig);
// ---- Endless play obsever ----
// Create an observer instance linked to the callback function
observer2 = new MutationObserver(mutationCallback);
endlessPlayObserver = new MutationObserver(mutationCallback);
// Start observing the target node for configured mutations
if (endlessPlayTag.checked == true) {
this.isEndlessWatch = true;
console.log("Endless play checked. Starting observer...");
observer2.observe(document, observerConfig2);
endlessPlayObserver.observe(document, observerConfig2);
}
}
@@ -205,7 +239,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;
@@ -220,7 +257,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";
@@ -242,12 +279,12 @@
endlessPlayTag.setAttribute("checked", false);
this.isEndlessWatch = false;
console.log("Stopping endless play...");
observer2.disconnect();
endlessPlayObserver.disconnect();
} else {
endlessPlayTag.setAttribute("checked", true);
this.isEndlessWatch = true;
console.log("Starting endless play...");
observer2.observe(confirmDialogElement, observerConfig2);
endlessPlayObserver.observe(document, observerConfig2);
}
}
@@ -281,7 +318,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 ;
}
@@ -291,13 +328,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 ;
@@ -338,7 +375,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;
@@ -448,7 +485,8 @@
if(e.preventDefault) e.preventDefault();
e.cancelBubble = true;
e.returnValue = false;
return false;
return false;
}
}
@@ -458,6 +496,6 @@
}
const setbuttonImage = (elm, path) => {
elm.style.backgroundImage = "url('" + browser.extension.getURL(path); + "')";
elm.style.backgroundImage = "url('" + browser.runtime.getURL(path); + "')";
}
}());
}());

View File

@@ -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;
}