Compare commits

...

63 Commits

Author SHA1 Message Date
Ajay Ramachandran
137ba895bb Merge pull request #110 from ajayyy/experimental
Update master
2019-08-13 13:06:10 -04:00
Ajay Ramachandran
ecc48de396 Merge pull request #109 from ajayyy/experimental-ajay
Fixed preview bar
2019-08-13 13:05:52 -04:00
Ajay Ramachandran
aa95687b56 Update version number 2019-08-13 13:03:08 -04:00
Ajay Ramachandran
a8147738ef Raised retry limit for when the server is down. 2019-08-13 13:02:54 -04:00
Ajay Ramachandran
4a3d36b952 Fixed preview bar.
Made it reset when no sponsors are found.

Made it wait until the video metadata is loaded if necessary.
2019-08-13 13:02:35 -04:00
Ajay Ramachandran
f9bd82db35 Merge pull request #103 from OfficialNoob/patch-20
Added switch for chrome.runtime.onMessage
2019-08-13 00:32:43 -04:00
Ajay Ramachandran
c8438b9d59 Updated formatting 2019-08-13 00:32:33 -04:00
Ajay Ramachandran
5347340c1c Merge pull request #107 from ajayyy/experimental-ajay
Preview bar, downvote to hide sponsor, usernames
2019-08-12 23:44:53 -04:00
Ajay Ramachandran
524e443f4d Updated build number 2019-08-12 23:44:14 -04:00
Ajay Ramachandran
b9091c3a97 Made it get the current username when letting you edit it. 2019-08-12 23:32:10 -04:00
Ajay Ramachandran
5445146b56 Added ability to set your username 2019-08-12 23:20:35 -04:00
Ajay Ramachandran
13d0e4a33a Made it still possible to vote on downvoted sponsors.
Added "(hidden)" to the button.

Resolves https://github.com/ajayyy/SponsorBlock/issues/28
2019-08-12 20:22:00 -04:00
Ajay Ramachandran
8f0a9d97f6 Downvoting now temporarily hides the sponsor time. 2019-08-12 20:00:42 -04:00
Ajay Ramachandran
5feed6bfcc Added preview bar with the sponsors 2019-08-12 19:34:44 -04:00
Ajay Ramachandran
5916baf5ea Merge pull request #105 from ajayyy/experimental
Lowered permissions + Edit panel additions
2019-08-12 16:05:28 -04:00
Ajay Ramachandran
1c3a857fcf Merge pull request #104 from ajayyy/experimental-ajay
Edit panel additions
2019-08-12 16:01:56 -04:00
Ajay Ramachandran
640ad58c65 Updated version number 2019-08-12 15:59:06 -04:00
Ajay Ramachandran
41aa58e004 Fixed userIDs not being properly submitted. 2019-08-12 15:58:25 -04:00
Ajay Ramachandran
6b3eb09198 Added button to set edit to the current time. 2019-08-12 15:27:35 -04:00
Official Noob
44c4671977 Added switch for chrome.runtime.onMessage 2019-08-12 17:41:26 +01:00
Ajay Ramachandran
ac118173a5 Made preview also save the edit. 2019-08-12 12:26:52 -04:00
Ajay Ramachandran
3f815a18c4 Added a sponsor time preview.
It skips 2 seconds before the start time so you can preview how it feels.

Also increased the space between the times and the clear times button.

Resolves https://github.com/ajayyy/SponsorBlock/issues/66
2019-08-12 12:21:20 -04:00
Ajay Ramachandran
e281b90699 Fixed sponsor times not properly saving 2019-08-12 12:05:16 -04:00
Ajay Ramachandran
012a36b931 Increased button padding 2019-08-12 12:04:57 -04:00
Ajay Ramachandran
43e3d03e9a Added better error checking 2019-08-12 12:02:01 -04:00
Ajay Ramachandran
5adeeed634 Made editing not possible on unfinished sponsors.
Resolved https://github.com/ajayyy/SponsorBlock/issues/77
2019-08-12 11:42:39 -04:00
Ajay Ramachandran
29a8608f9d Merge pull request #90 from OfficialNoob/patch-19
Removed tabs permission
2019-08-12 11:36:57 -04:00
Official Noob
67c4acbc5e Removed videoID as now message active tab 2019-08-12 13:38:35 +01:00
Official Noob
a5d605f539 Removed videoID as now message active tab 2019-08-12 13:38:27 +01:00
Ajay Ramachandran
66b6985c5e Merge pull request #101 from ajayyy/experimental
Better lookups + userID generator improvements
2019-08-11 23:24:17 -04:00
Ajay Ramachandran
0025785a78 Updated version number 2019-08-11 23:22:20 -04:00
Ajay Ramachandran
ba284aec2f Merge pull request #100 from ajayyy/experimental-ajay
More lookups
2019-08-11 23:19:40 -04:00
Ajay Ramachandran
5ffe207a86 Made it retry a sponsor lookup each second if there is a connection error.
It will stop after 15 tries.
2019-08-11 23:18:50 -04:00
Ajay Ramachandran
3a4d867ae3 Made it check again for sponsors after submitting. 2019-08-11 23:13:07 -04:00
Ajay Ramachandran
7a2c57aae9 Merge pull request #73 from OfficialNoob/patch-13
Made UUID less predictable
2019-08-11 23:08:54 -04:00
Ajay Ramachandran
05faa7e138 Merge branch 'master' into patch-13 2019-08-11 23:07:27 -04:00
Official Noob
f254a99d6f notifications 2019-08-11 21:21:04 +01:00
Official Noob
19a1a5efda Added alertPrevious message 2019-08-11 21:20:10 +01:00
Official Noob
28322f19b5 videoID 2019-08-11 19:36:52 +01:00
Official Noob
c7d03aa423 videoID 2019-08-11 19:32:44 +01:00
Official Noob
60242df3c9 Removed stuff thats in utils.js 2019-08-11 19:29:38 +01:00
Official Noob
1aab52edbe Remove userID 2019-08-11 19:27:38 +01:00
Ajay Ramachandran
2580577ce0 Added comments 2019-08-11 12:49:25 -04:00
Official Noob
1ab33375ec Update background.js 2019-08-11 13:51:59 +01:00
Official Noob
e1f5046ace Merge branch 'experimental' into patch-19 2019-08-11 13:38:00 +01:00
Official Noob
b28087f723 Kind of better :/ 2019-08-09 11:34:08 +01:00
Official Noob
866cc33f0e Update content.js 2019-08-08 20:33:05 +01:00
Official Noob
02448307ab Update background.js 2019-08-08 20:32:18 +01:00
Official Noob
1b5d5f8a3a Added tab update back 2019-08-08 20:15:23 +01:00
Official Noob
6707d6df8d Added onUpdated back as did not work 2019-08-08 19:59:15 +01:00
Official Noob
883871123a Update content.js 2019-08-08 19:26:26 +01:00
Official Noob
301e16b8f1 Removed tabUpdate as detecting in contentscript 2019-08-08 19:25:29 +01:00
Official Noob
e1f1814748 Moved code from background.js 2019-08-08 17:03:58 +01:00
Official Noob
074f7c5456 Switched callback to onTabs 2019-08-08 16:50:33 +01:00
Official Noob
2a64afe9dc camelCase 2019-08-08 16:48:00 +01:00
Official Noob
4c12bb9c2f camelCase 2019-08-08 16:45:23 +01:00
Official Noob
22e7c6a40d Sync Video ID with Storage API 2019-08-08 14:44:48 +01:00
Official Noob
a9ea22f505 Get ID from storage API 2019-08-08 14:43:15 +01:00
Official Noob
2067b1c787 Removed unused lines 2019-08-08 14:04:21 +01:00
Official Noob
410f5fc138 Update background.js 2019-08-08 14:03:13 +01:00
Official Noob
077efd2de3 Moving to content script 2019-08-08 14:02:06 +01:00
Official Noob
62632792cc Removed tabs permission 2019-08-08 13:28:50 +01:00
Official Noob
bbbb4f4877 Made UUID less predictable 2019-08-04 20:01:39 +01:00
8 changed files with 478 additions and 141 deletions

View File

@@ -1,55 +1,43 @@
//when a new tab is highlighted
chrome.tabs.onActivated.addListener(
function(activeInfo) {
chrome.tabs.get(activeInfo.tabId, function(tab) {
let id = getYouTubeVideoID(tab.url);
//if this even is a YouTube tab
if (id) {
videoIDChange(id, activeInfo.tabId);
}
})
}
);
//when a tab changes URLs
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo != undefined && changeInfo.url != undefined) { chrome.tabs.sendMessage(tabId, {
let id = getYouTubeVideoID(changeInfo.url); message: 'update',
});
//if URL changed and is youtube video message contentScript the video id
if (changeInfo.url && id) {
videoIDChange(id, tabId);
}
}
}); });
chrome.runtime.onMessage.addListener(function (request, sender, callback) { chrome.runtime.onMessage.addListener(function (request, sender, callback) {
if (request.message == "submitTimes") { switch(request.message) {
submitTimes(request.videoID, callback); case "submitTimes":
submitTimes(request.videoID, callback);
//this allows the callback to be called later by the submitTimes function
return true; //this allows the callback to be called later by the submitTimes function
} else if (request.message == "addSponsorTime") { return true;
addSponsorTime(request.time, request.videoID, callback); case "addSponsorTime":
addSponsorTime(request.time, request.videoID, callback);
//this allows the callback to be called later
return true; //this allows the callback to be called later
} else if (request.message == "getSponsorTimes") { return true;
getSponsorTimes(request.videoID, function(sponsorTimes) { case "getSponsorTimes":
callback({ getSponsorTimes(request.videoID, function(sponsorTimes) {
sponsorTimes: sponsorTimes callback({
}) sponsorTimes: sponsorTimes
}); })
});
//this allows the callback to be called later
return true; //this allows the callback to be called later
} else if (request.message == "submitVote") { return true;
submitVote(request.type, request.UUID, callback); case "submitVote":
submitVote(request.type, request.UUID, callback);
//this allows the callback to be called later
return true; //this allows the callback to be called later
} return true;
case "alertPrevious":
chrome.notifications.create("stillThere" + Math.random(), {
type: "basic",
title: "Do you want to submit the sponsor times for video id " + request.previousVideoID + "?",
message: "You seem to have left some sponsor times unsubmitted. Go back to that page to submit them (they are not deleted).",
iconUrl: "./icons/LogoSponsorBlocker256px.png"
});
}
}); });
//add help page on install //add help page on install
@@ -154,7 +142,7 @@ function submitVote(type, UUID, callback) {
function submitTimes(videoID, callback) { function submitTimes(videoID, callback) {
//get the video times from storage //get the video times from storage
let sponsorTimeKey = 'sponsorTimes' + videoID; let sponsorTimeKey = 'sponsorTimes' + videoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) { chrome.storage.sync.get([sponsorTimeKey, "userID"], function(result) {
let sponsorTimes = result[sponsorTimeKey]; let sponsorTimes = result[sponsorTimeKey];
let userID = result.userID; let userID = result.userID;
@@ -193,56 +181,6 @@ function submitTimes(videoID, callback) {
}); });
} }
function videoIDChange(currentVideoID, tabId) {
//send a message to the content script
chrome.tabs.sendMessage(tabId, {
message: 'ytvideoid',
id: currentVideoID
});
chrome.storage.sync.get(["sponsorVideoID", "previousVideoID"], function(result) {
const sponsorVideoID = result.sponsorVideoID;
const previousVideoID = result.previousVideoID;
//not a url change
if (sponsorVideoID == currentVideoID){
return;
}
chrome.storage.sync.set({
"sponsorVideoID": currentVideoID
});
//warn them if they had unsubmitted times
if (previousVideoID != null) {
//get the sponsor times from storage
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//warn them that they have unsubmitted sponsor times
chrome.notifications.create("stillThere" + Math.random(), {
type: "basic",
title: "Do you want to submit the sponsor times for watch?v=" + previousVideoID + "?",
message: "You seem to have left some sponsor times unsubmitted. Go back to that page to submit them (they are not deleted).",
iconUrl: "./icons/LogoSponsorBlocker256px.png"
});
}
//set the previous video id to the currentID
chrome.storage.sync.set({
"previousVideoID": currentVideoID
});
});
} else {
chrome.storage.sync.set({
"previousVideoID": currentVideoID
});
}
});
}
function sendRequestToServer(type, address, callback) { function sendRequestToServer(type, address, callback) {
let xmlhttp = new XMLHttpRequest(); let xmlhttp = new XMLHttpRequest();
@@ -262,5 +200,21 @@ function sendRequestToServer(type, address, callback) {
xmlhttp.send(); xmlhttp.send();
} }
//uuid generator function from https://gist.github.com/jed/982883 function generateUUID(length = 36) {
function generateUUID(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,generateUUID)} let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
let isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
if (window.crypto && window.crypto.getRandomValues) {
values = new Uint32Array(length);
window.crypto.getRandomValues(values);
for (i = 0; i < length; i++) {
result += charset[values[i] % charset.length];
}
return result;
} else {
for (let i = 0; i < length; i++) {
result += charset[Math.floor(Math.random() * charset.length)];
}
return result;
}
}

View File

@@ -1,3 +1,21 @@
#previewbar {
overflow: visible;
padding: 0;
margin: 0;
position: absolute;
width: 100%;
pointer-events: none;
height: 100%;
transform: scaleY(0.6) translateY(-30%) translateY(1.5px);
z-index: 40;
}
.previewbar {
display: inline-block;
height: 100%;
}
.popup { .popup {
z-index: 10; z-index: 10;
width: 100%; width: 100%;

View File

@@ -1,24 +1,33 @@
//was sponsor data found when doing SponsorsLookup //was sponsor data found when doing SponsorsLookup
var sponsorDataFound = false; var sponsorDataFound = false;
var previousVideoID = null;
//the actual sponsorTimes if loaded and UUIDs associated with them //the actual sponsorTimes if loaded and UUIDs associated with them
var sponsorTimes = null; var sponsorTimes = null;
var UUIDs = null; var UUIDs = null;
//what video id are these sponsors for //what video id are these sponsors for
var sponsorVideoID = null; var sponsorVideoID = null;
//these are sponsors that have been downvoted
var hiddenSponsorTimes = [];
//the time this video is starting at when first played, if not zero //the time this video is starting at when first played, if not zero
var youtubeVideoStartTime = null; var youtubeVideoStartTime = null;
//the video //the video
var v; var v;
var listenerAdded;
//the channel this video is about //the channel this video is about
var channelURL; var channelURL;
//is this channel whitelised from getting sponsors skipped //is this channel whitelised from getting sponsors skipped
var channelWhitelisted = false; var channelWhitelisted = false;
// create preview bar
let progressBar = document.getElementsByClassName("ytp-progress-bar-container")[0] || document.getElementsByClassName("no-model cue-range-markers")[0];
var previewBar = new PreviewBar(progressBar);
if(id = getYouTubeVideoID(document.URL)){ // Direct Links if(id = getYouTubeVideoID(document.URL)){ // Direct Links
videoIDChange(id); videoIDChange(id);
} }
@@ -29,6 +38,10 @@ var lastTime = -1;
//the actual time (not video time) that the last skip happened //the actual time (not video time) that the last skip happened
var lastUnixTimeSkipped = -1; var lastUnixTimeSkipped = -1;
//the amount of times the sponsor lookup has retried
//this only happens if there is an error
var sponsorLookupRetries = 0;
//the last time in the video a sponsor was skipped //the last time in the video a sponsor was skipped
//used for the go back button //used for the go back button
var lastSponsorTimeSkipped = null; var lastSponsorTimeSkipped = null;
@@ -77,14 +90,14 @@ chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
//get messages from the background script and the popup //get messages from the background script and the popup
chrome.runtime.onMessage.addListener(messageListener); chrome.runtime.onMessage.addListener(messageListener);
function messageListener(request, sender, sendResponse) { function messageListener(request, sender, sendResponse) {
//message from background script
if (request.message == "ytvideoid") {
videoIDChange(request.id);
}
//messages from popup script //messages from popup script
if (request.message == "update") {
if(id = getYouTubeVideoID(document.URL)) videoIDChange(id);
}
if (request.message == "sponsorStart") { if (request.message == "sponsorStart") {
sponsorMessageStarted(sendResponse); sponsorMessageStarted(sendResponse);
} }
@@ -98,6 +111,7 @@ function messageListener(request, sender, sendResponse) {
sendResponse({ sendResponse({
found: sponsorDataFound, found: sponsorDataFound,
sponsorTimes: sponsorTimes, sponsorTimes: sponsorTimes,
hiddenSponsorTimes: hiddenSponsorTimes,
UUIDs: UUIDs UUIDs: UUIDs
}); });
@@ -115,6 +129,16 @@ function messageListener(request, sender, sendResponse) {
}) })
} }
if (request.message == "skipToTime") {
v.currentTime = request.time;
}
if (request.message == "getCurrentTime") {
sendResponse({
currentTime: v.currentTime
});
}
if (request.message == "getChannelURL") { if (request.message == "getChannelURL") {
sendResponse({ sendResponse({
channelURL: channelURL channelURL: channelURL
@@ -179,11 +203,33 @@ document.onkeydown = function(e){
} }
function videoIDChange(id) { function videoIDChange(id) {
//not a url change
if (sponsorVideoID == id){
return;
}
//not a url change
if (sponsorVideoID == id) return;
//warn them if they had unsubmitted times
if (previousVideoID != null) {
//get the sponsor times from storage
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//warn them that they have unsubmitted sponsor times
chrome.runtime.sendMessage({
message: "alertPrevious",
previousVideoID: previousVideoID
})
}
//set the previous video id to the currentID
previousVideoID = id;
});
} else {
//set the previous id now, don't wait for chrome.storage.get
previousVideoID = id;
}
//close popup //close popup
closeInfoMenu(); closeInfoMenu();
@@ -195,6 +241,10 @@ function videoIDChange(id) {
sponsorTimes = null; sponsorTimes = null;
UUIDs = null; UUIDs = null;
sponsorVideoID = id; sponsorVideoID = id;
sponsorLookupRetries = 0;
//empty the preview bar
previewBar.set([], [], 0);
//see if there is a video start time //see if there is a video start time
youtubeVideoStartTime = getYouTubeVideoStartTime(document.URL); youtubeVideoStartTime = getYouTubeVideoStartTime(document.URL);
@@ -273,9 +323,21 @@ function sponsorsLookup(id) {
sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes; sponsorTimes = JSON.parse(xmlhttp.responseText).sponsorTimes;
UUIDs = JSON.parse(xmlhttp.responseText).UUIDs; UUIDs = JSON.parse(xmlhttp.responseText).UUIDs;
//update the preview bar
//leave the type blank for now until categories are added
console.log(v.duration)
if (isNaN(v.duration)) {
//wait until it is loaded
v.addEventListener('durationchange', updatePreviewBar);
} else {
//set it now
updatePreviewBar();
}
getChannelID(); getChannelID();
} else if (xmlhttp.readyState == 4) { sponsorLookupRetries = 0;
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 404) {
sponsorDataFound = false; sponsorDataFound = false;
//check if this video was uploaded recently //check if this video was uploaded recently
@@ -290,6 +352,13 @@ function sponsorsLookup(id) {
} }
} }
}); });
sponsorLookupRetries = 0;
} else if (xmlhttp.readyState == 4 && sponsorLookupRetries < 90) {
//some error occurred, try again in a second
setTimeout(() => sponsorsLookup(id), 1000);
sponsorLookupRetries++;
} }
}); });
@@ -299,6 +368,13 @@ function sponsorsLookup(id) {
}; };
} }
function updatePreviewBar() {
previewBar.set(sponsorTimes, [], v.duration);
//the listener is only needed once
v.removeEventListener('durationchange', updatePreviewBar);
}
function getChannelID() { function getChannelID() {
//get channel id //get channel id
let channelContainers = document.querySelectorAll("#owner-name"); let channelContainers = document.querySelectorAll("#owner-name");
@@ -378,7 +454,7 @@ function checkSponsorTime(sponsorTimes, index, openNotice) {
lastTime = v.currentTime - 0.0001; lastTime = v.currentTime - 0.0001;
} }
if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0])) { if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0]) && !hiddenSponsorTimes.includes(index)) {
//skip it //skip it
skipToTime(v, index, sponsorTimes, openNotice); skipToTime(v, index, sponsorTimes, openNotice);
@@ -889,6 +965,26 @@ function afterDownvote(UUID) {
//add element to div //add element to div
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText); document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingText);
document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText); document.getElementById("sponsorTimesVoteButtonsContainer" + UUID).appendChild(thanksForVotingInfoText);
//remove this sponsor from the sponsors looked up
//find which one it is
for (let i = 0; i < sponsorTimes.length; i++) {
if (UUIDs[i] == UUID) {
//this one is the one to hide
//add this as a hidden sponsorTime
hiddenSponsorTimes.push(i);
let sponsorTimesLeft = sponsorTimes.slice();
for (let j = 0; j < hiddenSponsorTimes.length; j++) {
//remove this sponsor time
sponsorTimesLeft.splice(hiddenSponsorTimes[j], 1);
}
//update the preview
previewBar.set(sponsorTimesLeft, [], v.duration);
}
}
} }
function addLoadingInfo(message, UUID) { function addLoadingInfo(message, UUID) {
@@ -1048,6 +1144,9 @@ function sendSubmitMessage(){
//clear the sponsor times //clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID; let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: []}); chrome.storage.sync.set({[sponsorTimeKey]: []});
//request the sponsors from the server again
sponsorsLookup(currentVideoID);
} else { } else {
//for a more detailed error message, they should check the popup //for a more detailed error message, they should check the popup
//show that the upload failed //show that the upload failed

View File

@@ -1,7 +1,7 @@
{ {
"name": "SponsorBlock for YouTube - Skip Sponsorships", "name": "SponsorBlock for YouTube - Skip Sponsorships",
"short_name": "SponsorBlock", "short_name": "SponsorBlock",
"version": "1.0.30", "version": "1.0.35",
"description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.", "description": "Skip over sponsorship on YouTube videos. Report sponsors on videos you watch to save the time of others.",
"content_scripts": [ "content_scripts": [
{ {
@@ -11,6 +11,7 @@
"all_frames": true, "all_frames": true,
"js": [ "js": [
"config.js", "config.js",
"utils/previewBar.js",
"utils.js", "utils.js",
"content.js", "content.js",
"popup.js" "popup.js"
@@ -36,7 +37,6 @@
"popup.html" "popup.html"
], ],
"permissions": [ "permissions": [
"tabs",
"storage", "storage",
"notifications", "notifications",
"https://sponsor.ajay.app/*" "https://sponsor.ajay.app/*"

View File

@@ -80,8 +80,14 @@ h1.popupElement {
.mediumLink.popupElement { .mediumLink.popupElement {
font-size: 15px; font-size: 15px;
padding-left: 15px; margin-left: 25px;
padding-right: 15px; margin-right: 25px;
text-decoration: underline;
cursor: pointer;
}
.tinyLink.popupElement {
font-size: 10px;
text-decoration: underline; text-decoration: underline;
cursor: pointer; cursor: pointer;
} }

View File

@@ -93,6 +93,8 @@
</div> </div>
</b> </b>
<br/>
<button id="clearTimes" class="smallButton popupElement">Clear Times</button> <button id="clearTimes" class="smallButton popupElement">Clear Times</button>
@@ -112,6 +114,31 @@
</div> </div>
<div id="setUsernameContainer" class="popupElement">
<br/>
<br/>
<button id="setUsernameButton" class="warningButton popupElement">Set Username</button>
</div>
<div id="setUsername" class="popupElement" style="display: none">
<br/>
<h3>Set Username</h3>
<div id="setUsernameStatusContainer" style="display: none">
<h2 id="setUsernameStatus"></h2>
</div>
<input id="usernameInput" hint="Username"></input>
<br/>
<br/>
<button id="submitUsername" class="warningButton popupElement">Submit Username</button>
</div>
<div id="discordButtonContainer" class="popupElement" style="display: none"> <div id="discordButtonContainer" class="popupElement" style="display: none">
<br/> <br/>
@@ -119,7 +146,7 @@
<br/> <br/>
Come join the official discord server to give suggestions and feedback! Come join the official discord server to give suggestions and feedback!
<br/> <br/>

191
popup.js
View File

@@ -54,6 +54,14 @@ function runThePopup() {
// submitTimesInfoMessage // submitTimesInfoMessage
"submitTimesInfoMessageContainer", "submitTimesInfoMessageContainer",
"submitTimesInfoMessage", "submitTimesInfoMessage",
// Username
"setUsernameContainer",
"setUsernameButton",
"setUsernameStatusContainer",
"setUsernameStatus",
"setUsername",
"usernameInput",
"submitUsername",
// More // More
"submissionSection", "submissionSection",
"mainControls", "mainControls",
@@ -78,6 +86,8 @@ function runThePopup() {
SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls); SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls);
SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking); SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking);
SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking); SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking);
SB.setUsernameButton.addEventListener("click", setUsernameButton);
SB.submitUsername.addEventListener("click", submitUsername);
SB.optionsButton.addEventListener("click", openOptions); SB.optionsButton.addEventListener("click", openOptions);
SB.reportAnIssue.addEventListener("click", reportAnIssue); SB.reportAnIssue.addEventListener("click", reportAnIssue);
SB.hideDiscordButton.addEventListener("click", hideDiscordButton); SB.hideDiscordButton.addEventListener("click", hideDiscordButton);
@@ -201,17 +211,25 @@ function runThePopup() {
} }
}); });
chrome.tabs.query({ chrome.tabs.query({
active: true, active: true,
currentWindow: true currentWindow: true
}, loadTabData); }, onTabs);
function onTabs(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) {
if (result != undefined && result.videoID) {
currentVideoID = result.videoID;
loadTabData(tabs);
} else if (result == undefined && chrome.runtime.lastError) {
//this isn't a YouTube video then, or at least the content script is not loaded
displayNoVideo();
}
});
}
function loadTabData(tabs) { function loadTabData(tabs) {
//set current videoID
currentVideoID = getYouTubeVideoID(tabs[0].url);
if (!currentVideoID) { if (!currentVideoID) {
//this isn't a YouTube video then //this isn't a YouTube video then
displayNoVideo(); displayNoVideo();
@@ -376,7 +394,14 @@ function runThePopup() {
for (let i = 0; i < request.sponsorTimes.length; i++) { for (let i = 0; i < request.sponsorTimes.length; i++) {
let sponsorTimeButton = document.createElement("button"); let sponsorTimeButton = document.createElement("button");
sponsorTimeButton.className = "warningButton popupElement"; sponsorTimeButton.className = "warningButton popupElement";
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]);
let extraInfo = "";
if (request.hiddenSponsorTimes.includes(i)) {
//this one is hidden
extraInfo = " (hidden)";
}
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]) + extraInfo;
let votingButtons = document.createElement("div"); let votingButtons = document.createElement("div");
@@ -465,8 +490,11 @@ function runThePopup() {
let index = i; let index = i;
deleteButton.addEventListener("click", () => deleteSponsorTime(index)); deleteButton.addEventListener("click", () => deleteSponsorTime(index));
let spacer = document.createElement("span"); let previewButton = document.createElement("span");
spacer.innerText = " "; previewButton.id = "sponsorTimePreviewButton" + i;
previewButton.innerText = "Preview";
previewButton.className = "mediumLink popupElement";
previewButton.addEventListener("click", () => previewSponsorTime(index));
let editButton = document.createElement("span"); let editButton = document.createElement("span");
editButton.id = "sponsorTimeEditButton" + i; editButton.id = "sponsorTimeEditButton" + i;
@@ -488,19 +516,46 @@ function runThePopup() {
} }
currentSponsorTimeContainer.innerText = currentSponsorTimeMessage; currentSponsorTimeContainer.innerText = currentSponsorTimeMessage;
currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index));
sponsorTimesContainer.appendChild(currentSponsorTimeContainer); sponsorTimesContainer.appendChild(currentSponsorTimeContainer);
sponsorTimesContainer.appendChild(deleteButton); sponsorTimesContainer.appendChild(deleteButton);
//only if it is a complete sponsor time //only if it is a complete sponsor time
if (sponsorTimes[i].length > 1) { if (sponsorTimes[i].length > 1) {
sponsorTimesContainer.appendChild(previewButton);
sponsorTimesContainer.appendChild(editButton); sponsorTimesContainer.appendChild(editButton);
currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index));
} }
} }
return sponsorTimesContainer; return sponsorTimesContainer;
} }
function previewSponsorTime(index) {
let skipTime = sponsorTimes[index][0];
if (document.getElementById("startTimeMinutes" + index) != null) {
//edit is currently open, use that time
skipTime = getSponsorTimeEditTimes("startTime", index);
//save the edit
saveSponsorTimeEdit(index, false);
}
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id, {
message: "skipToTime",
time: skipTime - 2
}
);
});
}
function editSponsorTime(index) { function editSponsorTime(index) {
if (document.getElementById("startTimeMinutes" + index) != null) { if (document.getElementById("startTimeMinutes" + index) != null) {
@@ -513,6 +568,13 @@ function runThePopup() {
let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index); let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index);
//the button to set the current time
let startTimeNowButton = document.createElement("span");
startTimeNowButton.id = "startTimeNowButton" + index;
startTimeNowButton.innerText = "(Now)";
startTimeNowButton.className = "tinyLink popupElement";
startTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("startTime", index));
//get sponsor time minutes and seconds boxes //get sponsor time minutes and seconds boxes
let startTimeMinutes = document.createElement("input"); let startTimeMinutes = document.createElement("input");
startTimeMinutes.id = "startTimeMinutes" + index; startTimeMinutes.id = "startTimeMinutes" + index;
@@ -527,7 +589,7 @@ function runThePopup() {
startTimeSeconds.type = "text"; startTimeSeconds.type = "text";
startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]); startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]);
startTimeSeconds.style.width = "60px"; startTimeSeconds.style.width = "60px";
let endTimeMinutes = document.createElement("input"); let endTimeMinutes = document.createElement("input");
endTimeMinutes.id = "endTimeMinutes" + index; endTimeMinutes.id = "endTimeMinutes" + index;
endTimeMinutes.className = "sponsorTime popupElement"; endTimeMinutes.className = "sponsorTime popupElement";
@@ -541,6 +603,13 @@ function runThePopup() {
endTimeSeconds.type = "text"; endTimeSeconds.type = "text";
endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]); endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]);
endTimeSeconds.style.width = "60px"; endTimeSeconds.style.width = "60px";
//the button to set the current time
let endTimeNowButton = document.createElement("span");
endTimeNowButton.id = "endTimeNowButton" + index;
endTimeNowButton.innerText = "(Now)";
endTimeNowButton.className = "tinyLink popupElement";
endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index));
let colonText = document.createElement("span"); let colonText = document.createElement("span");
colonText.innerText = ":"; colonText.innerText = ":";
@@ -553,6 +622,7 @@ function runThePopup() {
sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild); sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild);
} }
sponsorTimeContainer.appendChild(startTimeNowButton);
sponsorTimeContainer.appendChild(startTimeMinutes); sponsorTimeContainer.appendChild(startTimeMinutes);
sponsorTimeContainer.appendChild(colonText); sponsorTimeContainer.appendChild(colonText);
sponsorTimeContainer.appendChild(startTimeSeconds); sponsorTimeContainer.appendChild(startTimeSeconds);
@@ -560,6 +630,7 @@ function runThePopup() {
sponsorTimeContainer.appendChild(endTimeMinutes); sponsorTimeContainer.appendChild(endTimeMinutes);
sponsorTimeContainer.appendChild(colonText); sponsorTimeContainer.appendChild(colonText);
sponsorTimeContainer.appendChild(endTimeSeconds); sponsorTimeContainer.appendChild(endTimeSeconds);
sponsorTimeContainer.appendChild(endTimeNowButton);
//add save button and remove edit button //add save button and remove edit button
let saveButton = document.createElement("span"); let saveButton = document.createElement("span");
@@ -573,16 +644,37 @@ function runThePopup() {
sponsorTimesContainer.replaceChild(saveButton, editButton); sponsorTimesContainer.replaceChild(saveButton, editButton);
} }
function setEditTimeToCurrentTime(idStartName, index) {
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id,
{message: "getCurrentTime"},
function (response) {
let minutes = document.getElementById(idStartName + "Minutes" + index);
let seconds = document.getElementById(idStartName + "Seconds" + index);
minutes.value = getTimeInMinutes(response.currentTime);
seconds.value = getTimeInFormattedSeconds(response.currentTime);
});
});
}
//id start name is whether it is the startTime or endTime
//gives back the time in seconds
function getSponsorTimeEditTimes(idStartName, index) {
let minutes = document.getElementById(idStartName + "Minutes" + index);
let seconds = document.getElementById(idStartName + "Seconds" + index);
return parseInt(minutes.value) * 60 + parseFloat(seconds.value);
}
function saveSponsorTimeEdit(index) { function saveSponsorTimeEdit(index, closeEditMode = true) {
let startTimeMinutes = document.getElementById("startTimeMinutes" + index); sponsorTimes[index][0] = getSponsorTimeEditTimes("startTime", index);
let startTimeSeconds = document.getElementById("startTimeSeconds" + index); sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", 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 //save this
let sponsorTimeKey = "sponsorTimes" + currentVideoID; let sponsorTimeKey = "sponsorTimes" + currentVideoID;
@@ -598,9 +690,11 @@ function runThePopup() {
}); });
}); });
displaySponsorTimes(); if (closeEditMode) {
displaySponsorTimes();
showSubmitTimesIfNecessary(); showSubmitTimesIfNecessary();
}
} }
//deletes the sponsor time submitted at an index //deletes the sponsor time submitted at an index
@@ -911,11 +1005,64 @@ function runThePopup() {
} }
} }
//make the options div visisble //make the options div visible
function openOptions() { function openOptions() {
document.getElementById("optionsButtonContainer").style.display = "none"; document.getElementById("optionsButtonContainer").style.display = "none";
document.getElementById("options").style.display = "unset"; document.getElementById("options").style.display = "unset";
} }
//make the options username setting option visible
function setUsernameButton() {
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
//get username from the server
sendRequestToServer("GET", "/api/getUsername?userID=" + result.userID, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
SB.usernameInput.value = JSON.parse(xmlhttp.responseText).userName;
SB.submitUsername.style.display = "unset";
SB.usernameInput.style.display = "unset";
SB.setUsernameContainer.style.display = "none";
SB.setUsername.style.display = "unset";
} else {
SB.setUsername.style.display = "unset";
SB.submitUsername.style.display = "none";
SB.usernameInput.style.display = "none";
SB.setUsernameStatus.innerText = "Couldn't connect to server. Error code: " + xmlhttp.status;
}
});
});
}
//submit the new username
function submitUsername() {
//add loading indicator
SB.setUsernameStatusContainer.style.display = "unset";
SB.setUsernameStatus.innerText = "Loading...";
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
sendRequestToServer("POST", "/api/setUsername?userID=" + result.userID + "&username=" + SB.usernameInput.value, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//submitted
SB.submitUsername.style.display = "none";
SB.usernameInput.style.display = "none";
SB.setUsernameStatus.innerText = "Success!";
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 400) {
SB.setUsernameStatus.innerText = "Bad Request";
} else {
SB.setUsernameStatus.innerText = getErrorMessage(EN_US, xmlhttp.status);
}
});
});
SB.setUsernameContainer.style.display = "none";
SB.setUsername.style.display = "unset";
}
//this is not a YouTube video page //this is not a YouTube video page
function displayNoVideo() { function displayNoVideo() {

86
utils/previewBar.js Normal file
View File

@@ -0,0 +1,86 @@
/*
This is based on code from VideoSegments.
https://github.com/videosegments/videosegments/commits/f1e111bdfe231947800c6efdd51f62a4e7fef4d4/segmentsbar/segmentsbar.js
*/
'use strict';
let barTypes = {
"undefined": {
color: "#00d400",
opacity: "0.5"
},
"sponsor": {
color: "#00d400",
opacity: "0.5"
}
};
class PreviewBar {
constructor(parent) {
this.container = document.createElement('ul');
this.container.id = 'previewbar';
this.parent = parent;
this.bars = []
this.updatePosition();
}
updatePosition() {
//below the seek bar
// this.parent.insertAdjacentElement("afterEnd", this.container);
//on the seek bar
this.parent.insertAdjacentElement("afterBegin", this.container);
}
updateColor(segment, color, opacity) {
let bars = document.querySelectorAll('[data-vs-segment-type=' + segment + ']');
for (let bar of bars) {
bar.style.backgroundColor = color;
bar.style.opacity = opacity;
}
}
set(timestamps, types, duration) {
while (this.container.firstChild) {
this.container.removeChild(this.container.firstChild);
}
if (!timestamps || !types) {
return;
}
// to avoid rounding error resulting in width more than 100%
duration = Math.floor(duration * 100) / 100;
let width;
for (let i = 0; i < timestamps.length; i++) {
width = (timestamps[i][1] - timestamps[i][0]) / duration * 100;
width = Math.floor(width * 100) / 100;
let bar = this.createBar();
bar.setAttribute('data-vs-segment-type', types[i]);
bar.style.backgroundColor = barTypes[types[i]].color;
bar.style.opacity = barTypes[types[i]].opacity;
bar.style.width = width + '%';
bar.style.left = (timestamps[i][0] / duration * 100) + "%";
bar.style.position = "absolute"
this.container.insertAdjacentElement('beforeEnd', bar);
this.bars[i] = bar;
}
}
createBar() {
let bar = document.createElement('li');
bar.classList.add('previewbar');
bar.innerHTML = '&nbsp;';
return bar;
}
remove() {
this.container.remove();
this.container = undefined;
}
}