diff --git a/README.md b/README.md index fb6fe43e..89aa4c8e 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,6 @@ None at the moment # Credit +The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) is used to grab the time the video was published. + Some icons made by Gregor Cresnar from www.flaticon.com and are licensed by CC 3.0 BY diff --git a/background.js b/background.js index c619bcbb..07743435 100644 --- a/background.js +++ b/background.js @@ -21,11 +21,10 @@ chrome.tabs.onUpdated.addListener( // On tab update chrome.runtime.onMessage.addListener(function (request, sender, callback) { if (request.message == "submitTimes") { - submitTimes(request.videoID); + submitTimes(request.videoID, callback); - callback({ - success: true - }); + //this allows the callback to be called later by the submitTimes function + return true; } else if (request.message == "ytvideoid") { if (previousVideoID != request.videoID) { videoIDChange(request.videoID); @@ -42,7 +41,10 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { //this allows the callback to be called later return true; } else if (request.message == "submitVote") { - submitVote(request.type, request.UUID) + submitVote(request.type, request.UUID, callback); + + //this allows the callback to be called later + return true; } }); @@ -51,7 +53,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { function getSponsorTimes(videoID, callback) { let sponsorTimes = []; let sponsorTimeKey = "sponsorTimes" + videoID; - chrome.storage.local.get([sponsorTimeKey], function(result) { + chrome.storage.sync.get([sponsorTimeKey], function(result) { let sponsorTimesStorage = result[sponsorTimeKey]; if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { sponsorTimes = sponsorTimesStorage; @@ -77,41 +79,70 @@ function addSponsorTime(time) { //save this info let sponsorTimeKey = "sponsorTimes" + previousVideoID; - chrome.storage.local.set({[sponsorTimeKey]: sponsorTimes}); + chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}); }); } -function submitVote(type, UUID) { - let xmlhttp = new XMLHttpRequest(); - +function submitVote(type, UUID, callback) { getUserID(function(userID) { //publish this vote - console.log(serverAddress + "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type); - xmlhttp.open('GET', serverAddress + "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, true); - - //submit this vote - xmlhttp.send(); + sendRequestToServer('GET', "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + callback({ + successType: 1 + }); + } else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) { + //duplicate vote + callback({ + successType: 0 + }); + } else if (error) { + //error while connect + callback({ + successType: -1 + }); + } + }) }) } -function submitTimes(videoID) { +function submitTimes(videoID, callback) { //get the video times from storage let sponsorTimeKey = 'sponsorTimes' + videoID; - chrome.storage.local.get([sponsorTimeKey], function(result) { + chrome.storage.sync.get([sponsorTimeKey], function(result) { let sponsorTimes = result[sponsorTimeKey]; if (sponsorTimes != undefined && sponsorTimes.length > 0) { //submit these times for (let i = 0; i < sponsorTimes.length; i++) { - let xmlhttp = new XMLHttpRequest(); - - let userIDStorage = getUserID(function(userIDStorage) { + getUserID(function(userIDStorage) { //submit the sponsorTime - xmlhttp.open('GET', serverAddress + "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] - + "&userID=" + userIDStorage, true); - xmlhttp.send(); + sendRequestToServer('GET', "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + + "&userID=" + userIDStorage, function(xmlhttp, error) { + if (xmlhttp.readyState == 4 && !error) { + callback({ + statusCode: xmlhttp.status + }); + } else if (error) { + callback({ + statusCode: -1 + }); + } + }); }); } + + //add these to the storage log + chrome.storage.sync.get(["sponsorTimesContributed"], function(result) { + let currentContributionAmount = 0; + if (result.sponsorTimesContributed != undefined) { + //current contribution amount is known + currentContributionAmount = result.sponsorTimesContributed; + } + + //save the amount contributed + chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length}); + }); } }); } @@ -121,7 +152,7 @@ function videoIDChange(currentVideoID) { if (previousVideoID != null) { //get the sponsor times from storage let sponsorTimeKey = 'sponsorTimes' + previousVideoID; - chrome.storage.local.get([sponsorTimeKey], function(result) { + chrome.storage.sync.get([sponsorTimeKey], function(result) { let sponsorTimes = result[sponsorTimeKey]; if (sponsorTimes != undefined && sponsorTimes.length > 0) { @@ -149,7 +180,7 @@ function getUserID(callback) { } //if it is not cached yet, grab it from storage - chrome.storage.local.get(["userID"], function(result) { + chrome.storage.sync.get(["userID"], function(result) { let userIDStorage = result.userID; if (userIDStorage != undefined) { userID = userIDStorage; @@ -159,13 +190,32 @@ function getUserID(callback) { userID = generateUUID(); //save this UUID - chrome.storage.local.set({"userID": userID}); + chrome.storage.sync.set({"userID": userID}); callback(userID); } }); } +function sendRequestToServer(type, address, callback) { + let xmlhttp = new XMLHttpRequest(); + + xmlhttp.open(type, serverAddress + address, true); + + if (callback != undefined) { + xmlhttp.onreadystatechange = function () { + callback(xmlhttp, false); + }; + + xmlhttp.onerror = function(ev) { + callback(xmlhttp, true); + }; + } + + //submit this request + xmlhttp.send(); +} + function getYouTubeVideoID(url) { // Return video id or false var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; var match = url.match(regExp); diff --git a/content.css b/content.css index 1a85c3ac..6126768a 100644 --- a/content.css +++ b/content.css @@ -1,8 +1,16 @@ +.playerButton { + height: 60%; + top: 0; + bottom: 0; + display: block; + margin: auto; +} + .sponsorSkipObject { font-family: 'Source Sans Pro', sans-serif; } -#sponsorSkipLogo { +.sponsorSkipLogo { height: 64px; position: absolute; top: 0; @@ -11,7 +19,12 @@ margin-left: 10px; } -#sponsorSkipNotice { +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.sponsorSkipNotice { min-height: 165px; min-width: 400px; background-color: rgba(255, 217, 217, 0.8); @@ -19,9 +32,18 @@ z-index: 1; border: 3px solid rgba(0, 0, 0, 0.8); margin-top: -50px; + + animation: fadeIn 0.5s; } -#sponsorSkipMessage { +/* if two are very close to eachother */ +.secondSkipNotice { + margin-left: 500px; + + transition: margin-left 0.2s; +} + +.sponsorSkipMessage { font-size: 18px; color: #000000; text-align: center; @@ -30,7 +52,7 @@ margin-top: 4px; } -#sponsorSkipInfo { +.sponsorSkipInfo { font-size: 10px; color: #000000; text-align: center; @@ -42,6 +64,8 @@ font-weight: bold; color: #000000; text-align: center; + margin-top: 0px; + margin-bottom: 0px; } #sponsorTimesThanksForVotingInfoText { @@ -49,6 +73,14 @@ font-weight: bold; color: #000000; text-align: center; + margin-top: 0px; +} + +.sponsorTimesInfoMessage { + font-size: 15px; + font-weight: bold; + color: #000000; + text-align: center; } .voteButton { @@ -60,6 +92,42 @@ filter: brightness(80%); } +.submitButton { + background-color:#ec1c1c; + -moz-border-radius:28px; + -webkit-border-radius:28px; + border-radius:28px; + border:1px solid #d31919; + display:inline-block; + cursor:pointer; + color:#ffffff; + font-size:14px; + padding:4px 15px; + text-decoration:none; + text-shadow:0px 0px 0px #662727; + + margin-top: 5px; + margin-right: 15px; +} +.submitButton:hover { + background-color:#bf2a2a; +} + +.submitButton:focus { + outline: none; + background-color:#bf2a2a; +} + +.submitButton:active { + position:relative; + top:1px; +} + +@keyframes rotate { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + .sponsorSkipButton { background-color:#ec1c1c; -moz-border-radius:28px; diff --git a/content.js b/content.js index 91e217f6..1fdccecc 100644 --- a/content.js +++ b/content.js @@ -36,7 +36,7 @@ var hideVideoPlayerControls = false; //if the notice should not be shown //happens when the user click's the "Don't show notice again" button var dontShowNotice = false; -chrome.storage.local.get(["dontShowNoticeAgain"], function(result) { +chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) { let dontShowNoticeAgain = result.dontShowNoticeAgain; if (dontShowNoticeAgain != undefined) { dontShowNotice = dontShowNoticeAgain; @@ -59,7 +59,8 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes //send the sponsor times along with if it's found sendResponse({ found: sponsorDataFound, - sponsorTimes: sponsorTimes + sponsorTimes: sponsorTimes, + UUIDs: UUIDs }) } @@ -73,8 +74,8 @@ chrome.runtime.onMessage.addListener( // Detect URL Changes dontShowNotice = false; } - if (request.message == "toggleStartSponsorButton") { - toggleStartSponsorButton(); + if (request.message == "changeStartSponsorButton") { + changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible); } if (request.message == "changeVideoPlayerControlsVisibility") { @@ -96,14 +97,16 @@ function videoIDChange(id) { }, function(response) { if (response != undefined) { let sponsorTimes = response.sponsorTimes; - if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) { + if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length >= 2) { + document.getElementById("submitButton").style.display = "unset"; + } else if (sponsorTimes != undefined && sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) { toggleStartSponsorButton(); } } }); //see if video control buttons should be added - chrome.storage.local.get(["hideVideoPlayerControls"], function(result) { + chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) { if (result.hideVideoPlayerControls != undefined) { hideVideoPlayerControls = result.hideVideoPlayerControls; } @@ -117,24 +120,34 @@ function sponsorsLookup(id) { let xmlhttp = new XMLHttpRequest(); //check database for sponsor times - xmlhttp.open('GET', serverAddress + "/api/getVideoSponsorTimes?videoID=" + id, true); + sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + sponsorDataFound = true; - xmlhttp.onreadystatechange = function () { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - sponsorDataFound = true; + sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes; + UUIDs = JSON.parse(xmlhttp.responseText).UUIDs; - sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes; - UUIDs = JSON.parse(xmlhttp.responseText).UUIDs; + // If the sponsor data exists, add the event to run on the videos "ontimeupdate" + v.ontimeupdate = function () { + sponsorCheck(sponsorTimes); + }; + } else if (xmlhttp.readyState == 4) { + sponsorDataFound = false; - // If the sponsor data exists, add the event to run on the videos "ontimeupdate" - v.ontimeupdate = function () { - sponsorCheck(sponsorTimes); - }; - } else { - sponsorDataFound = false; - } - }; - xmlhttp.send(null); + //check if this video was uploaded recently + //use the invidious api to get the time published + sendRequestToCustomServer('GET', "https://invidio.us/api/v1/videos/" + id, function(xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + let unixTimePublished = JSON.parse(xmlhttp.responseText).published; + + //if less than 3 days old + if ((Date.now() / 1000) - unixTimePublished < 259200) { + setTimeout(() => sponsorsLookup(id), 10000); + } + } + }); + } + }); } function sponsorCheck(sponsorTimes) { // Video skipping @@ -148,24 +161,26 @@ function sponsorCheck(sponsorTimes) { // Video skipping v.currentTime = sponsorTimes[i][1]; lastSponsorTimeSkipped = sponsorTimes[i][0]; - lastSponsorTimeSkippedUUID = UUIDs[i]; + + let currentUUID = UUIDs[i]; + lastSponsorTimeSkippedUUID = currentUUID; //send out the message saying that a sponsor message was skipped openSkipNotice(); - setTimeout(closeSkipNotice, 7000); + setTimeout(() => closeSkipNotice(currentUUID), 7000); } lastTime = v.currentTime; } } -function goBackToPreviousTime() { - if (lastSponsorTimeSkipped != null) { +function goBackToPreviousTime(UUID) { + if (sponsorTimes != undefined) { //add a tiny bit of time to make sure it is not skipped again - v.currentTime = lastSponsorTimeSkipped + 0.001; + v.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][0] + 0.001; - closeSkipNotice(); + closeSkipNotice(UUID); } } @@ -184,11 +199,7 @@ function addPlayerControlsButton() { let startSponsorImage = document.createElement("img"); startSponsorImage.id = "startSponsorImage"; - startSponsorImage.style.height = "60%"; - startSponsorImage.style.top = "0"; - startSponsorImage.style.bottom = "0"; - startSponsorImage.style.display = "block"; - startSponsorImage.style.margin = "auto"; + startSponsorImage.className = "playerButton"; startSponsorImage.src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png"); //add the image to the button @@ -201,6 +212,7 @@ function addPlayerControlsButton() { function removePlayerControlsButton() { document.getElementById("startSponsorButton").style.display = "none"; + document.getElementById("submitButton").style.display = "none"; } //adds or removes the player controls button to what it should be @@ -209,6 +221,7 @@ function updateVisibilityOfPlayerControlsButton() { removePlayerControlsButton(); } else { addPlayerControlsButton(); + addSubmitButton(); } } @@ -222,16 +235,58 @@ function startSponsorClicked() { }); } -function toggleStartSponsorButton() { - if (showingStartSponsor) { - showingStartSponsor = false; - document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png"); - } else { +function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { + if (showStartSponsor) { showingStartSponsor = true; document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png"); + + if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible) { + document.getElementById("submitButton").style.display = "unset"; + } else if (!uploadButtonVisible) { + //disable submit button + document.getElementById("submitButton").style.display = "none"; + } + } else { + showingStartSponsor = false; + document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png"); + + //disable submit button + document.getElementById("submitButton").style.display = "none"; } } +function toggleStartSponsorButton() { + changeStartSponsorButton(!showingStartSponsor, true); +} + +//shows the submit button on the video player +function addSubmitButton() { + if (document.getElementById("submitButton") != null) { + //it's already added + return; + } + + //make a submit button + let submitButton = document.createElement("button"); + submitButton.id = "submitButton"; + submitButton.className = "ytp-button"; + submitButton.setAttribute("title", "Submit Sponsor Times"); + submitButton.addEventListener("click", submitSponsorTimes); + //hide it at the start + submitButton.style.display = "none"; + + let submitImage = document.createElement("img"); + submitImage.id = "submitButtonImage"; + submitImage.className = "playerButton"; + submitImage.src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png"); + + //add the image to the button + submitButton.appendChild(submitImage); + + let referenceNode = document.getElementsByClassName("ytp-right-controls")[0]; + referenceNode.prepend(submitButton); +} + //Opens the notice that tells the user that a sponsor was just skipped function openSkipNotice(){ if (dontShowNotice) { @@ -239,40 +294,57 @@ function openSkipNotice(){ return; } + let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length; + + if (amountOfPreviousNotices > 0) { + //already exists + + let previousNotice = document.getElementsByClassName("sponsorSkipNotice")[0]; + previousNotice.classList.add("secondSkipNotice") + } + + let UUID = lastSponsorTimeSkippedUUID; + let noticeElement = document.createElement("div"); - noticeElement.id = "sponsorSkipNotice"; - noticeElement.className = "sponsorSkipObject"; + //what sponsor time this is about + noticeElement.id = "sponsorSkipNotice" + lastSponsorTimeSkippedUUID; + noticeElement.classList.add("sponsorSkipObject"); + noticeElement.classList.add("sponsorSkipNotice"); + noticeElement.style.zIndex = 1 + amountOfPreviousNotices; let logoElement = document.createElement("img"); - logoElement.id = "sponsorSkipLogo"; + logoElement.id = "sponsorSkipLogo" + lastSponsorTimeSkippedUUID; + logoElement.className = "sponsorSkipLogo"; logoElement.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png"); let noticeMessage = document.createElement("div"); - noticeMessage.id = "sponsorSkipMessage"; - noticeMessage.className = "sponsorSkipObject"; + noticeMessage.id = "sponsorSkipMessage" + lastSponsorTimeSkippedUUID; + noticeMessage.classList.add("sponsorSkipMessage"); + noticeMessage.classList.add("sponsorSkipObject"); noticeMessage.innerText = "Hey, you just skipped a sponsor!"; let noticeInfo = document.createElement("p"); - noticeInfo.id = "sponsorSkipInfo"; - noticeInfo.className = "sponsorSkipObject"; + noticeInfo.id = "sponsorSkipInfo" + lastSponsorTimeSkippedUUID; + noticeInfo.classList.add("sponsorSkipInfo"); + noticeInfo.classList.add("sponsorSkipObject"); noticeInfo.innerText = "This message will disapear in 7 seconds"; //thumbs up and down buttons let voteButtonsContainer = document.createElement("div"); - voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer"; + voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + lastSponsorTimeSkippedUUID; voteButtonsContainer.setAttribute("align", "center"); let upvoteButton = document.createElement("img"); - upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + lastSponsorTimeSkippedUUID; upvoteButton.className = "sponsorSkipObject voteButton"; upvoteButton.src = chrome.extension.getURL("icons/upvote.png"); - upvoteButton.addEventListener("click", upvote); + upvoteButton.addEventListener("click", () => vote(1, UUID)); let downvoteButton = document.createElement("img"); - downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + lastSponsorTimeSkippedUUID; downvoteButton.className = "sponsorSkipObject voteButton"; downvoteButton.src = chrome.extension.getURL("icons/downvote.png"); - downvoteButton.addEventListener("click", downvote); + downvoteButton.addEventListener("click", () => vote(0, UUID)); //add thumbs up and down buttons to the container voteButtonsContainer.appendChild(upvoteButton); @@ -284,12 +356,12 @@ function openSkipNotice(){ let goBackButton = document.createElement("button"); goBackButton.innerText = "Go back"; goBackButton.className = "sponsorSkipButton"; - goBackButton.addEventListener("click", goBackToPreviousTime); + goBackButton.addEventListener("click", () => goBackToPreviousTime(UUID)); let hideButton = document.createElement("button"); hideButton.innerText = "Dismiss"; hideButton.className = "sponsorSkipButton"; - hideButton.addEventListener("click", closeSkipNotice); + hideButton.addEventListener("click", () => closeSkipNotice(UUID)); let dontShowAgainButton = document.createElement("button"); dontShowAgainButton.innerText = "Don't Show This Again"; @@ -316,19 +388,23 @@ function openSkipNotice(){ referenceNode.prepend(noticeElement); } -function upvote() { - vote(1); - - closeSkipNotice(); -} - -function downvote() { - vote(0); - +function afterDownvote(UUID) { //change text to say thanks for voting //remove buttons - document.getElementById("sponsorTimesVoteButtonsContainer").removeChild(document.getElementById("sponsorTimesUpvoteButtonsContainer")); - document.getElementById("sponsorTimesVoteButtonsContainer").removeChild(document.getElementById("sponsorTimesDownvoteButtonsContainer")); + let upvoteButton = document.getElementById("sponsorTimesUpvoteButtonsContainer" + UUID); + let downvoteButton = document.getElementById("sponsorTimesDownvoteButtonsContainer" + UUID); + if (upvoteButton != null) { + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(upvoteButton); + } + if (downvoteButton != null) { + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(downvoteButton); + } + + let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + UUID); + if (previousInfoMessage != null) { + //remove it + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(previousInfoMessage); + } //add thanks for voting text let thanksForVotingText = document.createElement("p"); @@ -341,32 +417,89 @@ function downvote() { thanksForVotingInfoText.innerText = "Hit go back to get to where you came from." //add element to div - document.getElementById("sponsorTimesVoteButtonsContainer").appendChild(thanksForVotingText); - document.getElementById("sponsorTimesVoteButtonsContainer").appendChild(thanksForVotingInfoText); + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText); + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText); } -function vote(type) { +function addLoadingInfo(message, UUID) { + //change text to say thanks for message + //remove buttons + let upvoteButton = document.getElementById("sponsorTimesUpvoteButtonsContainer" + UUID); + let downvoteButton = document.getElementById("sponsorTimesDownvoteButtonsContainer" + UUID); + if (upvoteButton != null) { + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(upvoteButton); + } + if (downvoteButton != null) { + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(downvoteButton); + } + + let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + UUID); + if (previousInfoMessage != null) { + //remove it + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).removeChild(previousInfoMessage); + } + + //add thanks for voting text + let thanksForVotingText = document.createElement("p"); + thanksForVotingText.id = "sponsorTimesInfoMessage" + UUID; + thanksForVotingText.className = "sponsorTimesInfoMessage"; + thanksForVotingText.innerText = message; + + //add element to div + document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText); +} + +function vote(type, UUID) { + //add loading info + addLoadingInfo("Loading...", UUID) + chrome.runtime.sendMessage({ message: "submitVote", type: type, - UUID: lastSponsorTimeSkippedUUID + UUID: UUID + }, function(response) { + if (response != undefined) { + //see if it was a success or failure + if (response.successType == 1) { + //success + if (type == 0) { + afterDownvote(UUID); + } else if (type == 1) { + closeSkipNotice(UUID); + } + } else if (response.successType == 0) { + //failure: duplicate vote + addLoadingInfo("It seems you've already voted before", UUID) + } else if (response.successType == -1) { + //failure: duplicate vote + addLoadingInfo("A connection error has occured.", UUID) + } + } }); } -//Closes the notice that tells the user that a sponsor was just skipped -function closeSkipNotice(){ - let notice = document.getElementById("sponsorSkipNotice"); +//Closes the notice that tells the user that a sponsor was just skipped for this UUID +function closeSkipNotice(UUID){ + let notice = document.getElementById("sponsorSkipNotice" + UUID); if (notice != null) { notice.remove(); } } +//Closes all notices that tell the user that a sponsor was just skipped +function closeAllSkipNotices(){ + let notices = document.getElementsByClassName("sponsorSkipNotice"); + for (let i = 0; i < notices.length; i++) { + notices[i].remove(); + } +} + function dontShowNoticeAgain() { - chrome.storage.local.set({"dontShowNoticeAgain": true}); + chrome.storage.sync.set({"dontShowNoticeAgain": true}); dontShowNotice = true; - closeSkipNotice(); + closeAllSkipNotices(); } function sponsorMessageStarted() { @@ -382,6 +515,80 @@ function sponsorMessageStarted() { toggleStartSponsorButton(); } +function submitSponsorTimes() { + //add loading animation + document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png"); + document.getElementById("submitButton").style.animation = "rotate 1s 0s infinite"; + + let currentVideoID = getYouTubeVideoID(document.URL); + + chrome.runtime.sendMessage({ + message: "submitTimes", + videoID: currentVideoID + }, function(response) { + if (response != undefined) { + if (response.statusCode == 200) { + //hide loading message + let submitButton = document.getElementById("submitButton"); + //finish this animation + submitButton.style.animation = "rotate 1s"; + //when the animation is over, hide the button + submitButton.addEventListener("animationend", function() { + submitButton.style.animation = "unset"; + submitButton.style.display = "none"; + }); + + //clear the sponsor times + let sponsorTimeKey = "sponsorTimes" + currentVideoID; + chrome.storage.sync.set({[sponsorTimeKey]: []}); + } else { + //for a more detailed error message, they should check the popup + //show that the upload failed + document.getElementById("submitButton").style.animation = "unset"; + document.getElementById("submitButtonImage").src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); + } + } + }); +} + +function sendRequestToServer(type, address, callback) { + let xmlhttp = new XMLHttpRequest(); + + xmlhttp.open(type, serverAddress + address, true); + + if (callback != undefined) { + xmlhttp.onreadystatechange = function () { + callback(xmlhttp, false); + }; + + xmlhttp.onerror = function(ev) { + callback(xmlhttp, true); + }; + } + + //submit this request + xmlhttp.send(); +} + +function sendRequestToCustomServer(type, fullAddress, callback) { + let xmlhttp = new XMLHttpRequest(); + + xmlhttp.open(type, fullAddress, true); + + if (callback != undefined) { + xmlhttp.onreadystatechange = function () { + callback(xmlhttp, false); + }; + + xmlhttp.onerror = function(ev) { + callback(xmlhttp, true); + }; + } + + //submit this request + xmlhttp.send(); +} + function getYouTubeVideoID(url) { // Returns with video id else returns false var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; var match = url.match(regExp); diff --git a/icons/PlayerUploadFailedIconSponsorBlocker256px.png b/icons/PlayerUploadFailedIconSponsorBlocker256px.png new file mode 100644 index 00000000..57c80838 Binary files /dev/null and b/icons/PlayerUploadFailedIconSponsorBlocker256px.png differ diff --git a/icons/PlayerUploadIconSponsorBlocker256px.png b/icons/PlayerUploadIconSponsorBlocker256px.png new file mode 100644 index 00000000..5be42678 Binary files /dev/null and b/icons/PlayerUploadIconSponsorBlocker256px.png differ diff --git a/manifest.json b/manifest.json index c742d16d..f0a4ba7b 100644 --- a/manifest.json +++ b/manifest.json @@ -22,6 +22,8 @@ "icons/IconSponsorBlocker256px.png", "icons/PlayerStartIconSponsorBlocker256px.png", "icons/PlayerStopIconSponsorBlocker256px.png", + "icons/PlayerUploadIconSponsorBlocker256px.png", + "icons/PlayerUploadFailedIconSponsorBlocker256px.png", "icons/upvote.png", "icons/downvote.png" ], diff --git a/popup.css b/popup.css index 64ae0a17..ec2f1d59 100644 --- a/popup.css +++ b/popup.css @@ -12,6 +12,19 @@ body { background-color: #ffd9d9; } +.recordingSubtitle { + margin-bottom: 10px; +} + +.voteButton { + height: 32px; + margin-right: 15px; + cursor: pointer; +} +.voteButton:hover { + filter: brightness(80%); +} + .greenButton { background-color:#ec1c1c; -moz-border-radius:28px; diff --git a/popup.html b/popup.html index 79b7adde..b180d788 100644 --- a/popup.html +++ b/popup.html @@ -24,8 +24,26 @@
Click the button below when the sponsorship starts and ends to record and
@@ -48,8 +66,18 @@
+
+