diff options
-rw-r--r-- | content.css | 12 | ||||
-rw-r--r-- | content.js | 158 | ||||
-rw-r--r-- | firefox_manifest.json | 3 | ||||
-rw-r--r-- | icons/PlayerInfoIconSponsorBlocker256px.png | bin | 0 -> 15797 bytes | |||
-rw-r--r-- | manifest.json | 8 | ||||
-rw-r--r-- | popup.css | 2 | ||||
-rw-r--r-- | popup.js | 242 |
7 files changed, 392 insertions, 33 deletions
diff --git a/content.css b/content.css index c4e8e7bf..933eb40f 100644 --- a/content.css +++ b/content.css @@ -1,3 +1,15 @@ +.popup { + z-index: 10; + width: 100%; + height: 500px; +} + +.smallLink { + font-size: 10px; + text-decoration: underline; + cursor: pointer; +} + .playerButtonImage { height: 60%; top: 0; @@ -32,6 +32,10 @@ var showingStartSponsor = true; //should the video controls buttons be added var hideVideoPlayerControls = false; +//becomes true when isInfoFound is called +//this is used to close the popup on YouTube when the other popup opens +var popupInitialised = false; + //should view counts be tracked var trackViewCount = false; chrome.storage.sync.get(["trackViewCount"], function(result) { @@ -55,7 +59,6 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) { chrome.runtime.onMessage.addListener( // Detect URL Changes function(request, sender, sendResponse) { - console.log(request.message) //message from background script if (request.message == "ytvideoid") { videoIDChange(request.id); @@ -63,7 +66,7 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes //messages from popup script if (request.message == "sponsorStart") { - sponsorMessageStarted(); + sponsorMessageStarted(sendResponse); } if (request.message == "isInfoFound") { @@ -72,7 +75,14 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes found: sponsorDataFound, sponsorTimes: sponsorTimes, UUIDs: UUIDs - }) + }); + + if (popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) { + //the popup should be closed now that another is opening + closeInfoMenu(); + } + + popupInitialised = true; } if (request.message == "getVideoID") { @@ -286,6 +296,7 @@ function removePlayerControlsButton() { //adds or removes the player controls button to what it should be function updateVisibilityOfPlayerControlsButton() { addPlayerControlsButton(); + addInfoButton(); addSubmitButton(); if (hideVideoPlayerControls) { removePlayerControlsButton(); @@ -293,6 +304,9 @@ function updateVisibilityOfPlayerControlsButton() { } function startSponsorClicked() { + //it can't update to this info yet + closeInfoMenu(); + toggleStartSponsorButton(); //send back current time with message @@ -329,6 +343,32 @@ function toggleStartSponsorButton() { changeStartSponsorButton(!showingStartSponsor, true); } +//shows the info button on the video player +function addInfoButton() { + if (document.getElementById("infoButton") != null) { + //it's already added + return; + } + + //make a submit button + let infoButton = document.createElement("button"); + infoButton.id = "infoButton"; + infoButton.className = "ytp-button playerButton"; + infoButton.setAttribute("title", "Open SponsorBlock Popup"); + infoButton.addEventListener("click", openInfoMenu); + + let infoImage = document.createElement("img"); + infoImage.id = "infoButtonImage"; + infoImage.className = "playerButtonImage"; + infoImage.src = chrome.extension.getURL("icons/PlayerInfoIconSponsorBlocker256px.png"); + + //add the image to the button + infoButton.appendChild(infoImage); + + let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; + referenceNode.prepend(infoButton); +} + //shows the submit button on the video player function addSubmitButton() { if (document.getElementById("submitButton") != null) { @@ -357,6 +397,50 @@ function addSubmitButton() { referenceNode.prepend(submitButton); } +function openInfoMenu() { + if (document.getElementById("sponsorBlockPopupContainer") != null) { + //it's already added + return; + } + + popupInitialised = false; + + //hide info button + document.getElementById("infoButton").style.display = "none"; + + let popup = document.createElement("div"); + popup.id = "sponsorBlockPopupContainer"; + + let popupFrame = document.createElement("iframe"); + popupFrame.id = "sponsorBlockPopupFrame" + popupFrame.src = chrome.extension.getURL("popup.html"); + popupFrame.className = "popup"; + + //close button + let closeButton = document.createElement("div"); + closeButton.innerText = "Close Popup"; + closeButton.classList = "smallLink"; + closeButton.setAttribute("align", "center"); + closeButton.addEventListener("click", closeInfoMenu); + + popup.appendChild(closeButton); + popup.appendChild(popupFrame); + + let parentNode = document.getElementById("secondary"); + + parentNode.prepend(popup); +} + +function closeInfoMenu() { + let popup = document.getElementById("sponsorBlockPopupContainer"); + if (popup != null) { + popup.remove(); + + //show info button + document.getElementById("infoButton").style.display = "unset"; + } +} + //Opens the notice that tells the user that a sponsor was just skipped function openSkipNotice(UUID){ if (dontShowNotice) { @@ -593,27 +677,47 @@ function dontShowNoticeAgain() { closeAllSkipNotices(); } -function sponsorMessageStarted() { +function sponsorMessageStarted(callback) { let v = document.querySelector('video'); //send back current time - chrome.runtime.sendMessage({ - message: "time", + callback({ time: v.currentTime - }); + }) //update button toggleStartSponsorButton(); } function submitSponsorTimes() { - if(!confirm("Are you sure you want to submit this?")) return; - if (document.getElementById("submitButton").style.display == "none") { //don't submit, not ready return; } + //it can't update to this info yet + closeInfoMenu(); + + let currentVideoID = getYouTubeVideoID(document.URL); + + let sponsorTimeKey = 'sponsorTimes' + currentVideoID; + chrome.storage.sync.get([sponsorTimeKey], function(result) { + let sponsorTimes = result[sponsorTimeKey]; + + if (sponsorTimes != undefined && sponsorTimes.length > 0) { + let confirmMessage = "Are you sure you want to submit this?\n\n" + getSponsorTimesMessage(sponsorTimes); + confirmMessage += "\n\nTo see more information, open the popup by clicking the extensions icon in the top right corner." + if(!confirm(confirmMessage)) return; + + sendSubmitMessage(); + } + }); + +} + +//send the message to the background js +//called after all the checks have been made that it's okay to do so +function sendSubmitMessage(){ //add loading animation document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png"); document.getElementById("submitButton").style.animation = "rotate 1s 0s infinite"; @@ -649,6 +753,42 @@ function submitSponsorTimes() { }); } +//get the message that visually displays the video times +function getSponsorTimesMessage(sponsorTimes) { + let sponsorTimesMessage = ""; + + for (let i = 0; i < sponsorTimes.length; i++) { + for (let s = 0; s < sponsorTimes[i].length; s++) { + let timeMessage = getFormattedTime(sponsorTimes[i][s]); + //if this is an end time + if (s == 1) { + timeMessage = " to " + timeMessage; + } else if (i > 0) { + //add commas if necessary + timeMessage = ", " + timeMessage; + } + + sponsorTimesMessage += timeMessage; + } + } + + return sponsorTimesMessage; +} + +//converts time in seconds to minutes:seconds +function getFormattedTime(seconds) { + let minutes = Math.floor(seconds / 60); + let secondsDisplay = Math.round(seconds - minutes * 60); + if (secondsDisplay < 10) { + //add a zero + secondsDisplay = "0" + secondsDisplay; + } + + let formatted = minutes+ ":" + secondsDisplay; + + return formatted; +} + function sendRequestToServer(type, address, callback) { let xmlhttp = new XMLHttpRequest(); diff --git a/firefox_manifest.json b/firefox_manifest.json index 4c2a0bad..0fb7e834 100644 --- a/firefox_manifest.json +++ b/firefox_manifest.json @@ -26,7 +26,8 @@ "icons/PlayerUploadIconSponsorBlocker256px.png", "icons/PlayerUploadFailedIconSponsorBlocker256px.png", "icons/upvote.png", - "icons/downvote.png" + "icons/downvote.png", + "icons/PlayerInfoIconSponsorBlocker256px.png" ], "permissions": [ "tabs", diff --git a/icons/PlayerInfoIconSponsorBlocker256px.png b/icons/PlayerInfoIconSponsorBlocker256px.png Binary files differnew file mode 100644 index 00000000..8a0e44a7 --- /dev/null +++ b/icons/PlayerInfoIconSponsorBlocker256px.png diff --git a/manifest.json b/manifest.json index c46fc801..c14a16aa 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { - "name": "SponsorBlock - YouTube Sponsorship Blocker", + "name": "SponsorBlock for YouTube - Skip Sponsorships", "short_name": "SponsorBlock", - "version": "1.0.14", + "version": "1.0.15", "description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.", "content_scripts": [ { @@ -26,7 +26,9 @@ "icons/PlayerUploadIconSponsorBlocker256px.png", "icons/PlayerUploadFailedIconSponsorBlocker256px.png", "icons/upvote.png", - "icons/downvote.png" + "icons/downvote.png", + "icons/PlayerInfoIconSponsorBlocker256px.png", + "popup.html" ], "permissions": [ "tabs", @@ -8,7 +8,7 @@ h1 { body { font-size: 14px; - width: 300px; + min-width: 300px; background-color: #ffd9d9; } @@ -220,40 +220,47 @@ function sendSponsorStartMessage() { }, tabs => { chrome.tabs.sendMessage( tabs[0].id, - {from: 'popup', message: 'sponsorStart'} + {from: 'popup', message: 'sponsorStart'}, + startSponsorCallback ); }); } -chrome.runtime.onMessage.addListener(function (request, sender, callback) { - if (request.message == "time") { - let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); +function startSponsorCallback(response) { + let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); - if (sponsorTimes[sponsorTimesIndex] == undefined) { - sponsorTimes[sponsorTimesIndex] = []; - } + if (sponsorTimes[sponsorTimesIndex] == undefined) { + sponsorTimes[sponsorTimesIndex] = []; + } - sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = request.time; + sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time; - let sponsorTimeKey = "sponsorTimes" + currentVideoID; - chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); + let sponsorTimeKey = "sponsorTimes" + currentVideoID; + chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); - updateStartTimeChosen(); + updateStartTimeChosen(); - //display video times on screen - displaySponsorTimes(); + //display video times on screen + displaySponsorTimes(); - //show submission section - document.getElementById("submissionSection").style.display = "unset"; + //show submission section + document.getElementById("submissionSection").style.display = "unset"; - showSubmitTimesIfNecessary(); - } -}); + showSubmitTimesIfNecessary(); +} //display the video times from the array function displaySponsorTimes() { //set it to the message - document.getElementById("sponsorMessageTimes").innerHTML = getSponsorTimesMessage(sponsorTimes); + let sponsorMessageTimes = document.getElementById("sponsorMessageTimes"); + + //remove all children + while (sponsorMessageTimes.firstChild) { + sponsorMessageTimes.removeChild(sponsorMessageTimes.firstChild); + } + + //add sponsor times + sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes)); } //display the video times from the array at the top, in a different section @@ -336,6 +343,185 @@ function getSponsorTimesMessage(sponsorTimes) { return sponsorTimesMessage; } +//get the message that visually displays the video times +//this version is a div that contains each with delete buttons +function getSponsorTimesMessageDiv(sponsorTimes) { + // let sponsorTimesMessage = ""; + let sponsorTimesContainer = document.createElement("div"); + sponsorTimesContainer.id = "sponsorTimesContainer"; + + for (let i = 0; i < sponsorTimes.length; i++) { + let currentSponsorTimeContainer = document.createElement("div"); + currentSponsorTimeContainer.id = "sponsorTimeContainer" + i; + let currentSponsorTimeMessage = ""; + + let deleteButton = document.createElement("span"); + deleteButton.id = "sponsorTimeDeleteButton" + i; + deleteButton.innerText = "Delete"; + deleteButton.className = "smallLink"; + let index = i; + deleteButton.addEventListener("click", () => deleteSponsorTime(index)); + + let spacer = document.createElement("span"); + spacer.innerText = " "; + + let editButton = document.createElement("span"); + editButton.id = "sponsorTimeEditButton" + i; + editButton.innerText = "Edit"; + editButton.className = "smallLink"; + editButton.addEventListener("click", () => editSponsorTime(index)); + + for (let s = 0; s < sponsorTimes[i].length; s++) { + let timeMessage = getFormattedTime(sponsorTimes[i][s]); + //if this is an end time + if (s == 1) { + timeMessage = " to " + timeMessage; + } else if (i > 0) { + //add commas if necessary + timeMessage = timeMessage; + } + + currentSponsorTimeMessage += timeMessage; + } + + currentSponsorTimeContainer.innerText = currentSponsorTimeMessage; + sponsorTimesContainer.appendChild(currentSponsorTimeContainer); + sponsorTimesContainer.appendChild(deleteButton); + + //only if it is a complete sponsor time + if (sponsorTimes[i].length > 1) { + sponsorTimesContainer.appendChild(spacer); + sponsorTimesContainer.appendChild(editButton); + } + } + + return sponsorTimesContainer; +} + +function editSponsorTime(index) { + let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index); + + //get sponsor time minutes and seconds boxes + let startTimeMinutes = document.createElement("input"); + startTimeMinutes.id = "startTimeMinutes" + index; + startTimeMinutes.type = "text"; + startTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][0]); + startTimeMinutes.style.width = "35"; + + let startTimeSeconds = document.createElement("input"); + startTimeSeconds.id = "startTimeSeconds" + index; + startTimeSeconds.type = "text"; + startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]); + startTimeSeconds.style.width = "42"; + + let endTimeMinutes = document.createElement("input"); + endTimeMinutes.id = "endTimeMinutes" + index; + endTimeMinutes.type = "text"; + endTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][1]); + endTimeMinutes.style.width = "35"; + + let endTimeSeconds = document.createElement("input"); + endTimeSeconds.id = "endTimeSeconds" + index; + endTimeSeconds.type = "text"; + endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]); + endTimeSeconds.style.width = "42"; + + let colonText = document.createElement("span"); + colonText.innerText = ":"; + + let toText = document.createElement("span"); + toText.innerText = " to "; + + //remove all children to replace + while (sponsorTimeContainer.firstChild) { + sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild); + } + + sponsorTimeContainer.appendChild(startTimeMinutes); + sponsorTimeContainer.appendChild(colonText); + sponsorTimeContainer.appendChild(startTimeSeconds); + sponsorTimeContainer.appendChild(toText); + sponsorTimeContainer.appendChild(endTimeMinutes); + sponsorTimeContainer.appendChild(colonText); + sponsorTimeContainer.appendChild(endTimeSeconds); + + //add save button and remove edit button + let saveButton = document.createElement("span"); + saveButton.id = "sponsorTimeSaveButton" + index; + saveButton.innerText = "Save"; + saveButton.className = "smallLink"; + saveButton.addEventListener("click", () => saveSponsorTimeEdit(index)); + + let editButton = document.getElementById("sponsorTimeEditButton" + index); + let sponsorTimesContainer = document.getElementById("sponsorTimesContainer"); + + sponsorTimesContainer.removeChild(editButton); + sponsorTimesContainer.appendChild(saveButton); +} + +function saveSponsorTimeEdit(index) { + let startTimeMinutes = document.getElementById("startTimeMinutes" + index); + let startTimeSeconds = document.getElementById("startTimeSeconds" + index); + + let endTimeMinutes = document.getElementById("endTimeMinutes" + index); + let endTimeSeconds = document.getElementById("endTimeSeconds" + index); + + sponsorTimes[index][0] = parseInt(startTimeMinutes.value) * 60 + parseFloat(startTimeSeconds.value); + sponsorTimes[index][1] = parseInt(endTimeMinutes.value) * 60 + parseFloat(endTimeSeconds.value); + + //save this + let sponsorTimeKey = "sponsorTimes" + currentVideoID; + chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); + + displaySponsorTimes(); +} + +//deletes the sponsor time submitted at an index +function deleteSponsorTime(index) { + //if it is not a complete sponsor time + if (sponsorTimes[index].length < 2) { + chrome.tabs.query({ + active: true, + currentWindow: true + }, function(tabs) { + chrome.tabs.sendMessage(tabs[0].id, { + message: "changeStartSponsorButton", + showStartSponsor: true, + uploadButtonVisible: false + }); + }); + + resetStartTimeChosen(); + } + + sponsorTimes.splice(index, 1); + + //save this + let sponsorTimeKey = "sponsorTimes" + currentVideoID; + chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); + + //update display + displaySponsorTimes(); + + //if they are all removed + if (sponsorTimes.length == 0) { + //update chrome tab + chrome.tabs.query({ + active: true, + currentWindow: true + }, function(tabs) { + chrome.tabs.sendMessage(tabs[0].id, { + message: "changeStartSponsorButton", + showStartSponsor: true, + uploadButtonVisible: false + }); + }); + + //hide submission section + document.getElementById("submissionSection").style.display = "none"; + } +} + function clearTimes() { //send new sponsor time state to tab if (sponsorTimes.length > 0) { @@ -588,6 +774,24 @@ function getFormattedTime(seconds) { return formatted; } +//converts time in seconds to minutes +function getTimeInMinutes(seconds) { + let minutes = Math.floor(seconds / 60); + + return minutes; +} + +//converts time in seconds to seconds past the last minute +function getTimeInFormattedSeconds(seconds) { + let secondsFormatted = (seconds % 60).toFixed(3); + + if (secondsFormatted < 10) { + secondsFormatted = "0" + secondsFormatted; + } + + return secondsFormatted; +} + function sendRequestToServer(type, address, callback) { let xmlhttp = new XMLHttpRequest(); |