Merge pull request #358 from ajayyy/react

Categories Improvements
This commit is contained in:
Ajay Ramachandran 2020-06-02 19:40:11 -04:00 committed by GitHub
commit 28cddf92d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 138 deletions

View file

@ -1,7 +1,7 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "__MSG_Name__", "short_name": "__MSG_Name__",
"version": "1.2.29", "version": "1.2.30",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"content_scripts": [{ "content_scripts": [{

View file

@ -104,9 +104,6 @@
"voted": { "voted": {
"message": "Voted!" "message": "Voted!"
}, },
"voteFail": {
"message": "You have already voted this way before."
},
"serverDown": { "serverDown": {
"message": "It seems the server is down. Contact the dev immediately." "message": "It seems the server is down. Contact the dev immediately."
}, },
@ -496,7 +493,7 @@
"message": "Interaction Reminder (Subscribe)" "message": "Interaction Reminder (Subscribe)"
}, },
"category_selfpromo": { "category_selfpromo": {
"message": "Self-Promotion and Merchandise" "message": "Unpaid/Self Promotion"
}, },
"category_music_offtopic": { "category_music_offtopic": {
"message": "Music: Non-Music Section" "message": "Music: Non-Music Section"

View file

@ -1,4 +1,4 @@
import * as Types from "./types"; import * as CompileConfig from "../config.json";
import Config from "./config"; import Config from "./config";
// Make the config public for debugging purposes // Make the config public for debugging purposes
@ -30,7 +30,17 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
switch(request.message) { switch(request.message) {
case "openConfig": case "openConfig":
chrome.runtime.openOptionsPage(); chrome.runtime.openOptionsPage();
return return;
case "sendRequest":
sendRequestToCustomServer(request.type, request.url, request.data).then(async (response) => {
callback({
responseText: await response.text(),
status: response.status,
ok: response.ok
});
});
return true;
case "addSponsorTime": case "addSponsorTime":
addSponsorTime(request.time, request.videoID, callback); addSponsorTime(request.time, request.videoID, callback);
@ -47,7 +57,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
//this allows the callback to be called later //this allows the callback to be called later
return true; return true;
case "submitVote": case "submitVote":
submitVote(request.type, request.UUID, request.category, callback); submitVote(request.type, request.UUID, request.category).then(callback);
//this allows the callback to be called later //this allows the callback to be called later
return true; return true;
@ -147,7 +157,7 @@ function addSponsorTime(time, videoID, callback) {
}); });
} }
function submitVote(type, UUID, category, callback) { async function submitVote(type: number, UUID: string, category: string) {
let userID = Config.config.userID; let userID = Config.config.userID;
if (userID == undefined || userID === "undefined") { if (userID == undefined || userID === "undefined") {
@ -159,24 +169,60 @@ function submitVote(type, UUID, category, callback) {
let typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category; let typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category;
//publish this vote //publish this vote
utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection, function(xmlhttp, error) { let response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection);
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback({ if (response.ok) {
successType: 1 return {
}); successType: 1
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) { };
//duplicate vote } else if (response.status == 405) {
callback({ //duplicate vote
successType: 0, return {
statusCode: xmlhttp.status successType: 0,
}); statusCode: response.status
} else if (error) { };
//error while connect } else {
callback({ //error while connect
successType: -1, return {
statusCode: xmlhttp.status successType: -1,
}); statusCode: response.status
};
}
}
async function asyncRequestToServer(type: string, address: string, data = {}) {
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;
return await (sendRequestToCustomServer(type, serverAddress + address, data));
}
/**
* Sends a request to the specified url
*
* @param type The request type "GET", "POST", etc.
* @param address The address to add to the SponsorBlock server address
* @param callback
*/
async function sendRequestToCustomServer(type: string, url: string, data = {}) {
// If GET, convert JSON to parameters
if (type.toLowerCase() === "get") {
for (const key in data) {
let seperator = url.includes("?") ? "&" : "?";
let value = (typeof(data[key]) === "string") ? data[key]: JSON.stringify(data[key]);
url += seperator + key + "=" + value;
} }
data = null;
}
const response = await fetch(url, {
method: type,
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
body: data ? JSON.stringify(data) : null
}); });
return response;
} }

View file

@ -268,7 +268,7 @@ async function migrateOldFormats() {
let response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId"); let response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId");
if (response.ok) { if (response.ok) {
newChannelList.push((await response.json()).authorId); newChannelList.push((JSON.parse(response.responseText)).authorId);
} else { } else {
// Add it at the beginning so it gets converted later // Add it at the beginning so it gets converted later
newChannelList.unshift(item); newChannelList.unshift(item);

View file

@ -1,6 +1,6 @@
import Config from "./config"; import Config from "./config";
import { SponsorTime, CategorySkipOption, CategorySelection, VideoID, SponsorHideType } from "./types"; import { SponsorTime, CategorySkipOption, CategorySelection, VideoID, SponsorHideType, FetchResponse } from "./types";
import { ContentContainer } from "./types"; import { ContentContainer } from "./types";
import Utils from "./utils"; import Utils from "./utils";
@ -64,10 +64,6 @@ var channelWhitelisted = false;
// create preview bar // create preview bar
var previewBar: PreviewBar = null; var previewBar: PreviewBar = null;
// When not null, a sponsor is currently being previewed and auto skip should be enabled.
// This is set to a timeout function when that happens that will reset it after 3 seconds.
var previewResetter: NodeJS.Timeout = null;
//the player controls on the YouTube player //the player controls on the YouTube player
var controls = null; var controls = null;
@ -164,14 +160,7 @@ function messageListener(request: any, sender: any, sendResponse: (response: any
video.play(); video.play();
} }
// Start preview resetter return;
if (previewResetter !== null){
clearTimeout(previewResetter);
}
previewResetter = setTimeout(() => previewResetter = null, 4000);
return
case "getCurrentTime": case "getCurrentTime":
sendResponse({ sendResponse({
currentTime: getRealCurrentTime() currentTime: getRealCurrentTime()
@ -628,9 +617,9 @@ function sponsorsLookup(id: string) {
utils.asyncRequestToServer('GET', "/api/skipSegments", { utils.asyncRequestToServer('GET', "/api/skipSegments", {
videoID: id, videoID: id,
categories categories
}).then(async (response: Response) => { }).then(async (response: FetchResponse) => {
if (response.status === 200) { if (response.ok) {
let recievedSegments: SponsorTime[] = await response.json(); let recievedSegments: SponsorTime[] = JSON.parse(response.responseText);
if (!recievedSegments.length) { if (!recievedSegments.length) {
console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments)); console.error("[SponsorBlock] Server returned malformed response: " + JSON.stringify(recievedSegments));
return; return;
@ -866,7 +855,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
let endTimeIndex = getLatestEndTimeIndex(sponsorTimes, minSponsorTimeIndex); let endTimeIndex = getLatestEndTimeIndex(sponsorTimes, minSponsorTimeIndex);
let previewSponsorStartTimes = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments); let previewSponsorStartTimes = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments);
let previewSponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, currentTime, true, false); let previewSponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, currentTime, false, false);
let minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime)); let minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime));
let previewEndTimeIndex = getLatestEndTimeIndex(sponsorTimesSubmitting, minPreviewSponsorTimeIndex); let previewEndTimeIndex = getLatestEndTimeIndex(sponsorTimesSubmitting, minPreviewSponsorTimeIndex);
@ -970,13 +959,6 @@ function previewTime(time: number) {
if (video.paused){ if (video.paused){
video.play(); video.play();
} }
// Start preview resetter
if (previewResetter !== null){
clearTimeout(previewResetter);
}
previewResetter = setTimeout(() => previewResetter = null, 4000);
} }
//skip from the start time to the end time for a certain index sponsor time //skip from the start time to the end time for a certain index sponsor time
@ -984,7 +966,7 @@ function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: S
// There will only be one submission if it is manual skip // There will only be one submission if it is manual skip
let autoSkip: boolean = utils.getCategorySelection(skippingSegments[0].category).option === CategorySkipOption.AutoSkip; let autoSkip: boolean = utils.getCategorySelection(skippingSegments[0].category).option === CategorySkipOption.AutoSkip;
if (autoSkip || previewResetter !== null) { if (autoSkip || sponsorTimesSubmitting.includes(skippingSegments[0])) {
v.currentTime = skipTime[1]; v.currentTime = skipTime[1];
} }
@ -993,30 +975,30 @@ function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: S
if (!Config.config.dontShowNotice || !autoSkip) { if (!Config.config.dontShowNotice || !autoSkip) {
let skipNotice = new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer); let skipNotice = new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer);
} }
}
//send telemetry that a this sponsor was skipped //send telemetry that a this sponsor was skipped
if (Config.config.trackViewCount && autoSkip) { if (Config.config.trackViewCount && autoSkip) {
let alreadySkipped = false; let alreadySkipped = false;
let isPreviewSegment = false; let isPreviewSegment = false;
for (const segment of skippingSegments) { for (const segment of skippingSegments) {
let index = sponsorTimes.indexOf(segment); let index = sponsorTimes.indexOf(segment);
if (index !== -1 && !sponsorSkipped[index]) { if (index !== -1 && !sponsorSkipped[index]) {
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID); utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
sponsorSkipped[index] = true; sponsorSkipped[index] = true;
} else if (sponsorSkipped[index]) { } else if (sponsorSkipped[index]) {
alreadySkipped = true; alreadySkipped = true;
}
if (index !== -1) isPreviewSegment = true;
} }
// Count this as a skip if (index === -1) isPreviewSegment = true;
if (!alreadySkipped && !isPreviewSegment) { }
Config.config.minutesSaved = Config.config.minutesSaved + (skipTime[1] - skipTime[0]) / 60;
Config.config.skipCount = Config.config.skipCount + 1; // Count this as a skip
} if (!alreadySkipped && !isPreviewSegment) {
Config.config.minutesSaved = Config.config.minutesSaved + (skipTime[1] - skipTime[0]) / 60;
Config.config.skipCount = Config.config.skipCount + 1;
} }
} }
} }
@ -1395,10 +1377,6 @@ function vote(type: number, UUID: string, category?: string, skipNotice?: SkipNo
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) { if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
//success (treat rate limits as a success) //success (treat rate limits as a success)
skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category); skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category);
} else if (response.successType == 0) {
//failure: duplicate vote
skipNotice.setNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail"))
skipNotice.resetVoteButtonInfo.bind(skipNotice)();
} else if (response.successType == -1) { } else if (response.successType == -1) {
skipNotice.setNoticeInfoMessage.bind(skipNotice)(utils.getErrorMessage(response.statusCode)) skipNotice.setNoticeInfoMessage.bind(skipNotice)(utils.getErrorMessage(response.statusCode))
skipNotice.resetVoteButtonInfo.bind(skipNotice)(); skipNotice.resetVoteButtonInfo.bind(skipNotice)();
@ -1525,7 +1503,7 @@ async function sendSubmitMessage(){
document.getElementById("submitButton").style.animation = "unset"; document.getElementById("submitButton").style.animation = "unset";
(<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); (<HTMLImageElement> document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png");
alert(utils.getErrorMessage(response.status) + "\n\n" + (await response.text())); alert(utils.getErrorMessage(response.status) + "\n\n" + (response.responseText));
} }
} }

View file

@ -168,9 +168,9 @@ async function runThePopup(messageListener?: MessageListener) {
if (userID != undefined) { if (userID != undefined) {
//there are probably some views on these submissions then //there are probably some views on these submissions then
//get the amount of views from the sponsors submitted //get the amount of views from the sponsors submitted
utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(response) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (response.status == 200) {
let viewCount = JSON.parse(xmlhttp.responseText).viewCount; let viewCount = JSON.parse(response.responseText).viewCount;
if (viewCount != 0) { if (viewCount != 0) {
if (viewCount > 1) { if (viewCount > 1) {
PageElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); PageElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments");
@ -185,9 +185,9 @@ async function runThePopup(messageListener?: MessageListener) {
}); });
//get this time in minutes //get this time in minutes
utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(response) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (response.status == 200) {
let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; let minutesSaved = JSON.parse(response.responseText).timeSaved;
if (minutesSaved != 0) { if (minutesSaved != 0) {
if (minutesSaved != 1) { if (minutesSaved != 1) {
PageElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); PageElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower");
@ -797,9 +797,9 @@ async function runThePopup(messageListener?: MessageListener) {
//make the options username setting option visible //make the options username setting option visible
function setUsernameButton() { function setUsernameButton() {
//get username from the server //get username from the server
utils.sendRequestToServer("GET", "/api/getUsername?userID=" + Config.config.userID, function (xmlhttp, error) { utils.sendRequestToServer("GET", "/api/getUsername?userID=" + Config.config.userID, function (response) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (response.status == 200) {
PageElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; PageElements.usernameInput.value = JSON.parse(response.responseText).userName;
PageElements.submitUsername.style.display = "unset"; PageElements.submitUsername.style.display = "unset";
PageElements.usernameInput.style.display = "unset"; PageElements.usernameInput.style.display = "unset";
@ -808,13 +808,13 @@ async function runThePopup(messageListener?: MessageListener) {
PageElements.setUsername.style.display = "unset"; PageElements.setUsername.style.display = "unset";
PageElements PageElements
PageElements.setUsernameStatusContainer.style.display = "none"; PageElements.setUsernameStatusContainer.style.display = "none";
} else if (xmlhttp.readyState == 4) { } else {
PageElements.setUsername.style.display = "unset"; PageElements.setUsername.style.display = "unset";
PageElements.submitUsername.style.display = "none"; PageElements.submitUsername.style.display = "none";
PageElements.usernameInput.style.display = "none"; PageElements.usernameInput.style.display = "none";
PageElements.setUsernameStatusContainer.style.display = "unset"; PageElements.setUsernameStatusContainer.style.display = "unset";
PageElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); PageElements.setUsernameStatus.innerText = utils.getErrorMessage(response.status);
} }
}); });
} }
@ -826,15 +826,15 @@ async function runThePopup(messageListener?: MessageListener) {
PageElements.setUsernameStatus.innerText = "Loading..."; PageElements.setUsernameStatus.innerText = "Loading...";
//get the userID //get the userID
utils.sendRequestToServer("POST", "/api/setUsername?userID=" + Config.config.userID + "&username=" + PageElements.usernameInput.value, function (xmlhttp, error) { utils.sendRequestToServer("POST", "/api/setUsername?userID=" + Config.config.userID + "&username=" + PageElements.usernameInput.value, function (response) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (response.status == 200) {
//submitted //submitted
PageElements.submitUsername.style.display = "none"; PageElements.submitUsername.style.display = "none";
PageElements.usernameInput.style.display = "none"; PageElements.usernameInput.style.display = "none";
PageElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); PageElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success");
} else if (xmlhttp.readyState == 4) { } else {
PageElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); PageElements.setUsernameStatus.innerText = utils.getErrorMessage(response.status);
} }
}); });
@ -883,9 +883,6 @@ async function runThePopup(messageListener?: MessageListener) {
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) { if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
//success (treat rate limits as a success) //success (treat rate limits as a success)
addVoteMessage(chrome.i18n.getMessage("voted"), UUID) addVoteMessage(chrome.i18n.getMessage("voted"), UUID)
} else if (response.successType == 0) {
//failure: duplicate vote
addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID)
} else if (response.successType == -1) { } else if (response.successType == -1) {
addVoteMessage(utils.getErrorMessage(response.statusCode), UUID) addVoteMessage(utils.getErrorMessage(response.statusCode), UUID)
} }

View file

@ -22,6 +22,12 @@ interface ContentContainer {
} }
} }
interface FetchResponse {
responseText: string,
status: number,
ok: boolean
}
interface VideoDurationResponse { interface VideoDurationResponse {
duration: number; duration: number;
} }
@ -55,6 +61,7 @@ interface SponsorTime {
type VideoID = string; type VideoID = string;
export { export {
FetchResponse,
VideoDurationResponse, VideoDurationResponse,
ContentContainer, ContentContainer,
CategorySelection, CategorySelection,

View file

@ -1,5 +1,5 @@
import Config from "./config"; import Config from "./config";
import { CategorySelection, SponsorTime } from "./types"; import { CategorySelection, SponsorTime, FetchResponse } from "./types";
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
@ -276,29 +276,18 @@ class Utils {
* @param address The address to add to the SponsorBlock server address * @param address The address to add to the SponsorBlock server address
* @param callback * @param callback
*/ */
async asyncRequestToCustomServer(type: string, url: string, data = {}) { async asyncRequestToCustomServer(type: string, url: string, data = {}): Promise<FetchResponse> {
return new Promise((resolve) => {
// If GET, convert JSON to parameters // Ask the background script to do the work
if (type.toLowerCase() === "get") { chrome.runtime.sendMessage({
for (const key in data) { message: "sendRequest",
let seperator = url.includes("?") ? "&" : "?"; type,
let value = (typeof(data[key]) === "string") ? data[key]: JSON.stringify(data[key]); url,
url += seperator + key + "=" + value; data
} }, (response) => {
resolve(response);
data = null; });
} })
const response = await fetch(url, {
method: type,
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
body: data ? JSON.stringify(data) : null
});
return response;
} }
/** /**
@ -308,7 +297,7 @@ class Utils {
* @param address The address to add to the SponsorBlock server address * @param address The address to add to the SponsorBlock server address
* @param callback * @param callback
*/ */
async asyncRequestToServer(type: string, address: string, data = {}) { async asyncRequestToServer(type: string, address: string, data = {}): Promise<FetchResponse> {
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress; let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;
return await (this.asyncRequestToCustomServer(type, serverAddress + address, data)); return await (this.asyncRequestToCustomServer(type, serverAddress + address, data));
@ -321,25 +310,17 @@ class Utils {
* @param address The address to add to the SponsorBlock server address * @param address The address to add to the SponsorBlock server address
* @param callback * @param callback
*/ */
sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) { sendRequestToServer(type: string, address: string, callback?: (response: FetchResponse) => void) {
let xmlhttp = new XMLHttpRequest();
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress; let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;
xmlhttp.open(type, serverAddress + address, true); // Ask the background script to do the work
chrome.runtime.sendMessage({
if (callback != undefined) { message: "sendRequest",
xmlhttp.onreadystatechange = function () { type,
callback(xmlhttp, false); url: serverAddress + address
}; }, (response) => {
callback(response);
xmlhttp.onerror = function(ev) { });
callback(xmlhttp, true);
};
}
//submit this request
xmlhttp.send();
} }
getFormattedMinutes(seconds: number) { getFormattedMinutes(seconds: number) {