Merge pull request #399 from ajayyy/react

Save category in preview submissions and other fixes
This commit is contained in:
Ajay Ramachandran
2020-07-03 21:20:53 -04:00
committed by GitHub
11 changed files with 193 additions and 211 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "SponsorBlock", "short_name": "SponsorBlock",
"version": "2.0.2.2", "version": "2.0.3",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"content_scripts": [{ "content_scripts": [{

View File

@@ -218,7 +218,7 @@
"message": "Show Notice Again" "message": "Show Notice Again"
}, },
"longDescription": { "longDescription": {
"message": "SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.", "message": "SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. \n\n You can also skip intros, outros, reminders to subscribe and other categories.",
"description": "Full description of the extension on the store pages." "description": "Full description of the extension on the store pages."
}, },
"website": { "website": {
@@ -472,9 +472,6 @@
"theKey": { "theKey": {
"message": "The key" "message": "The key"
}, },
"keyAlreadyUsedByYouTube": {
"message": "is already used by youtube. Please select another key."
},
"keyAlreadyUsed": { "keyAlreadyUsed": {
"message": "is bound to another action. Please select another key." "message": "is bound to another action. Please select another key."
}, },
@@ -489,13 +486,13 @@
"message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like." "message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like."
}, },
"category_intro": { "category_intro": {
"message": "Intro Animation" "message": "Intermission/Intro Animation"
}, },
"category_intro_description": { "category_intro_description": {
"message": "Intro animations that are recurring in the series or provide no direct value. This should not be used on music videos." "message": "An interval without actual content. Could be a pause, static frame, repeating animation. This should not be used for transitions containing information or be used on music videos."
}, },
"category_intro_short": { "category_intro_short": {
"message": "Intro" "message": "Intermission"
}, },
"category_outro": { "category_outro": {
"message": "Endcards/Credits" "message": "Endcards/Credits"

View File

@@ -40,21 +40,6 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
}); });
}); });
return true;
case "addSponsorTime":
addSponsorTime(request.time, request.videoID, callback);
//this allows the callback to be called later
return true;
case "getSponsorTimes":
getSponsorTimes(request.videoID, function(sponsorTimes) {
callback({
sponsorTimes
});
});
//this allows the callback to be called later
return true; return true;
case "submitVote": case "submitVote":
submitVote(request.type, request.UUID, request.category).then(callback); submitVote(request.type, request.UUID, request.category).then(callback);
@@ -127,38 +112,6 @@ function unregisterFirefoxContentScript(id: string) {
delete contentScriptRegistrations[id]; delete contentScriptRegistrations[id];
} }
//gets the sponsor times from memory
function getSponsorTimes(videoID, callback) {
let sponsorTimes = [];
let sponsorTimesStorage = Config.config.sponsorTimes.get(videoID);
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
sponsorTimes = sponsorTimesStorage;
}
callback(sponsorTimes);
}
function addSponsorTime(time, videoID, callback) {
getSponsorTimes(videoID, function(sponsorTimes) {
//add to sponsorTimes
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length < 2) {
//it is an end time
sponsorTimes[sponsorTimes.length - 1][1] = time;
} else {
//it is a start time
let sponsorTimesIndex = sponsorTimes.length;
sponsorTimes[sponsorTimesIndex] = [];
sponsorTimes[sponsorTimesIndex][0] = time;
}
//save this info
Config.config.sponsorTimes.set(videoID, sponsorTimes);
callback();
});
}
async function submitVote(type: number, UUID: string, category: string) { async function submitVote(type: number, UUID: string, category: string) {
let userID = Config.config.userID; let userID = Config.config.userID;

View File

@@ -134,13 +134,6 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.audio.volume = this.contentContainer().v.volume * 0.1; this.audio.volume = this.contentContainer().v.volume * 0.1;
this.audio.play(); this.audio.play();
} }
if (Config.config.categoryUpdateShowCount < 3 && Config.config.categorySelections.length <= 1) {
this.setNoticeInfoMessageWithOnClick(() => chrome.runtime.sendMessage({"message": "openConfig"})
, chrome.i18n.getMessage("categoryUpdate1"), chrome.i18n.getMessage("categoryUpdate2"));
Config.config.categoryUpdateShowCount = Config.config.categoryUpdateShowCount + 1
}
} }
render() { render() {

View File

@@ -322,7 +322,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
sponsorTimesSubmitting[this.props.index].category = this.categoryOptionRef.current.value; sponsorTimesSubmitting[this.props.index].category = this.categoryOptionRef.current.value;
Config.config.sponsorTimes.set(this.props.contentContainer().sponsorVideoID, utils.getSegmentsFromSponsorTimes(sponsorTimesSubmitting)); Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting);
this.props.contentContainer().updatePreviewBar(); this.props.contentContainer().updatePreviewBar();
} }
@@ -354,7 +354,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
sponsorTimes.splice(index, 1); sponsorTimes.splice(index, 1);
//save this //save this
Config.config.sponsorTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimes); Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimes);
this.props.contentContainer().updatePreviewBar(); this.props.contentContainer().updatePreviewBar();

View File

@@ -1,12 +1,13 @@
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
import { CategorySelection, CategorySkipOption, PreviewBarOption } from "./types"; import { CategorySelection, CategorySkipOption, PreviewBarOption, SponsorTime } from "./types";
import Utils from "./utils"; import Utils from "./utils";
const utils = new Utils(); const utils = new Utils();
interface SBConfig { interface SBConfig {
userID: string, userID: string,
sponsorTimes: SBMap<string, any>, // sponsorTimes: SBMap<string, SponsorTime[]>,
segmentTimes: SBMap<string, SponsorTime[]>,
whitelistedChannels: string[], whitelistedChannels: string[],
forceChannelCheck: boolean, forceChannelCheck: boolean,
startSponsorKeybind: string, startSponsorKeybind: string,
@@ -34,8 +35,6 @@ interface SBConfig {
checkForUnlistedVideos: boolean, checkForUnlistedVideos: boolean,
testingServer: boolean, testingServer: boolean,
categoryUpdateShowCount: number,
// What categories should be skipped // What categories should be skipped
categorySelections: CategorySelection[], categorySelections: CategorySelection[],
@@ -52,7 +51,7 @@ interface SBConfig {
"selfpromo": PreviewBarOption, "selfpromo": PreviewBarOption,
"preview-selfpromo": PreviewBarOption, "preview-selfpromo": PreviewBarOption,
"music_offtopic": PreviewBarOption, "music_offtopic": PreviewBarOption,
"preview-music_offtopic": PreviewBarOption "preview-music_offtopic": PreviewBarOption,
} }
} }
@@ -85,35 +84,39 @@ class SBMap<T, U> extends Map {
} }
} }
set(key, value) { get(key): U {
const result = super.set(key, value); return super.get(key);
}
rawSet(key, value) {
return super.set(key, value);
}
update() {
// Store updated SBMap locally // Store updated SBMap locally
chrome.storage.sync.set({ chrome.storage.sync.set({
[this.id]: encodeStoredItem(this) [this.id]: encodeStoredItem(this)
}); });
}
set(key: T, value: U) {
const result = super.set(key, value);
this.update();
return result; return result;
} }
delete(key) { delete(key) {
const result = super.delete(key); const result = super.delete(key);
// Store updated SBMap locally this.update();
chrome.storage.sync.set({
[this.id]: encodeStoredItem(this)
});
return result; return result;
} }
clear() { clear() {
const result = super.clear(); const result = super.clear();
chrome.storage.sync.set({ this.update();
[this.id]: encodeStoredItem(this)
});
return result; return result;
} }
} }
@@ -125,7 +128,7 @@ var Config: SBObject = {
configListeners: [], configListeners: [],
defaults: { defaults: {
userID: null, userID: null,
sponsorTimes: new SBMap("sponsorTimes"), segmentTimes: new SBMap("segmentTimes"),
whitelistedChannels: [], whitelistedChannels: [],
forceChannelCheck: false, forceChannelCheck: false,
startSponsorKeybind: ";", startSponsorKeybind: ";",
@@ -153,8 +156,6 @@ var Config: SBObject = {
checkForUnlistedVideos: false, checkForUnlistedVideos: false,
testingServer: false, testingServer: false,
categoryUpdateShowCount: 0,
categorySelections: [{ categorySelections: [{
name: "sponsor", name: "sponsor",
option: CategorySkipOption.AutoSkip option: CategorySkipOption.AutoSkip
@@ -240,24 +241,13 @@ function encodeStoredItem<T>(data: T): T | Array<any> {
* *
* @param {*} data * @param {*} data
*/ */
function decodeStoredItem<T>(id: string, data: T): T | SBMap<string, any> { function decodeStoredItem<T>(id: string, data: T): T | SBMap<string, SponsorTime[]> {
if (!Config.defaults[id]) return data; if (!Config.defaults[id]) return data;
if (Config.defaults[id] instanceof SBMap) { if (Config.defaults[id] instanceof SBMap) {
try { try {
let jsonData: any = data; if (!Array.isArray(data)) return data;
return new SBMap(id, data);
// Check if data is stored in the old format for SBMap (a JSON string)
if (typeof data === "string") {
try {
jsonData = JSON.parse(data);
} catch(e) {
// Continue normally (out of this if statement)
}
}
if (!Array.isArray(jsonData)) return data;
return new SBMap(id, jsonData);
} catch(e) { } catch(e) {
console.error("Failed to parse SBMap: " + id); console.error("Failed to parse SBMap: " + id);
} }
@@ -315,9 +305,9 @@ function fetchConfig() {
}); });
} }
async function migrateOldFormats() { function migrateOldFormats(config: SBConfig) {
if (Config.config["disableAutoSkip"]) { if (config["disableAutoSkip"]) {
for (const selection of Config.config.categorySelections) { for (const selection of config.categorySelections) {
if (selection.name === "sponsor") { if (selection.name === "sponsor") {
selection.option = CategorySkipOption.ManualSkip; selection.option = CategorySkipOption.ManualSkip;
@@ -327,62 +317,108 @@ async function migrateOldFormats() {
} }
// Auto vote removal // Auto vote removal
if (Config.config["autoUpvote"]) { if (config["autoUpvote"]) {
chrome.storage.sync.remove("autoUpvote"); chrome.storage.sync.remove("autoUpvote");
} }
// mobileUpdateShowCount removal // mobileUpdateShowCount removal
if (Config.config["mobileUpdateShowCount"] !== undefined) { if (config["mobileUpdateShowCount"] !== undefined) {
chrome.storage.sync.remove("mobileUpdateShowCount"); chrome.storage.sync.remove("mobileUpdateShowCount");
} }
// categoryUpdateShowCount removal
if (config["categoryUpdateShowCount"] !== undefined) {
chrome.storage.sync.remove("categoryUpdateShowCount");
}
// Channel URLS // Channel URLS
if (Config.config.whitelistedChannels.length > 0 && if (config.whitelistedChannels.length > 0 &&
(Config.config.whitelistedChannels[0] == null || Config.config.whitelistedChannels[0].includes("/"))) { (config.whitelistedChannels[0] == null || config.whitelistedChannels[0].includes("/"))) {
let newChannelList: string[] = []; const channelURLFixer = async() => {
for (const item of Config.config.whitelistedChannels) { let newChannelList: string[] = [];
if (item != null) { for (const item of config.whitelistedChannels) {
if (item.includes("/channel/")) { if (item != null) {
newChannelList.push(item.split("/")[2]); if (item.includes("/channel/")) {
} else if (item.includes("/user/") && utils.isContentScript()) { newChannelList.push(item.split("/")[2]);
// Replace channel URL with channelID } else if (item.includes("/user/") && utils.isContentScript()) {
let response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId");
if (response.ok) { // Replace channel URL with channelID
newChannelList.push((JSON.parse(response.responseText)).authorId); let response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId");
} else {
// Add it at the beginning so it gets converted later if (response.ok) {
newChannelList.push((JSON.parse(response.responseText)).authorId);
} else {
// Add it at the beginning so it gets converted later
newChannelList.unshift(item);
}
} else if (item.includes("/user/")) {
// Add it at the beginning so it gets converted later (The API can only be called in the content script due to CORS issues)
newChannelList.unshift(item); newChannelList.unshift(item);
} else {
newChannelList.push(item);
} }
} else if (item.includes("/user/")) {
// Add it at the beginning so it gets converted later (The API can only be called in the content script due to CORS issues)
newChannelList.unshift(item);
} else {
newChannelList.push(item);
} }
} }
config.whitelistedChannels = newChannelList;
} }
Config.config.whitelistedChannels = newChannelList; channelURLFixer();
} }
// Check if off-topic category needs to be removed // Check if off-topic category needs to be removed
for (let i = 0; i < Config.config.categorySelections.length; i++) { for (let i = 0; i < config.categorySelections.length; i++) {
if (Config.config.categorySelections[i].name === "offtopic") { if (config.categorySelections[i].name === "offtopic") {
Config.config.categorySelections.splice(i, 1); config.categorySelections.splice(i, 1);
// Call set listener // Call set listener
Config.config.categorySelections = Config.config.categorySelections; config.categorySelections = config.categorySelections;
break; break;
} }
} }
// Migrate old "sponsorTimes"
if (config["sponsorTimes"]) {
let jsonData: any = config["sponsorTimes"];
// Check if data is stored in the old format for SBMap (a JSON string)
if (typeof jsonData === "string") {
try {
jsonData = JSON.parse(jsonData);
} catch(e) {
// Continue normally (out of this if statement)
}
}
// Otherwise junk data
if (Array.isArray(jsonData)) {
let oldMap = new Map(jsonData);
oldMap.forEach((sponsorTimes: number[][], key) => {
let segmentTimes: SponsorTime[] = [];
for (const segment of sponsorTimes) {
segmentTimes.push({
segment: segment,
category: "sponsor",
UUID: null
});
}
config.segmentTimes.rawSet(key, segmentTimes);
});
config.segmentTimes.update();
}
chrome.storage.sync.remove("sponsorTimes");
}
} }
async function setupConfig() { async function setupConfig() {
await fetchConfig(); await fetchConfig();
addDefaults(); addDefaults();
convertJSON(); convertJSON();
Config.config = configProxy(); const config = configProxy();
migrateOldFormats(); migrateOldFormats(config);
Config.config = config;
} }
// Reset config // Reset config
@@ -401,6 +437,12 @@ function addDefaults() {
for (const key in Config.defaults) { for (const key in Config.defaults) {
if(!Config.localConfig.hasOwnProperty(key)) { if(!Config.localConfig.hasOwnProperty(key)) {
Config.localConfig[key] = Config.defaults[key]; Config.localConfig[key] = Config.defaults[key];
} else if (key === "barTypes") {
for (const key2 in Config.defaults[key]) {
if(!Config.localConfig[key].hasOwnProperty(key2)) {
Config.localConfig[key][key2] = Config.defaults[key][key2];
}
}
} }
} }
}; };

View File

@@ -323,13 +323,13 @@ async function videoIDChange(id) {
//warn them if they had unsubmitted times //warn them if they had unsubmitted times
if (previousVideoID != null) { if (previousVideoID != null) {
//get the sponsor times from storage //get the sponsor times from storage
let sponsorTimes = Config.config.sponsorTimes.get(previousVideoID); let sponsorTimes = Config.config.segmentTimes.get(previousVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0) { if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//warn them that they have unsubmitted sponsor times //warn them that they have unsubmitted sponsor times
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
message: "alertPrevious", message: "alertPrevious",
previousVideoID: previousVideoID previousVideoID: previousVideoID
}) });
} }
//set the previous video id to the currentID //set the previous video id to the currentID
@@ -347,10 +347,10 @@ async function videoIDChange(id) {
//make sure everything is properly added //make sure everything is properly added
updateVisibilityOfPlayerControlsButton().then(() => { updateVisibilityOfPlayerControlsButton().then(() => {
//see if the onvideo control image needs to be changed //see if the onvideo control image needs to be changed
let segments = Config.config.sponsorTimes.get(sponsorVideoID); let segments = Config.config.segmentTimes.get(sponsorVideoID);
if (segments != null && segments.length > 0 && segments[segments.length - 1].length >= 2) { if (segments != null && segments.length > 0 && segments[segments.length - 1].segment.length >= 2) {
changeStartSponsorButton(true, true); changeStartSponsorButton(true, true);
} else if (segments != null && segments.length > 0 && segments[segments.length - 1].length < 2) { } else if (segments != null && segments.length > 0 && segments[segments.length - 1].segment.length < 2) {
changeStartSponsorButton(false, true); changeStartSponsorButton(false, true);
} else { } else {
changeStartSponsorButton(true, false); changeStartSponsorButton(true, false);
@@ -1173,31 +1173,24 @@ function startSponsorClicked() {
}); });
} }
// Create raw segment list
let segments: number[][] = [];
for (const sponsorTime of sponsorTimesSubmitting) {
segments.push(sponsorTime.segment);
}
//save this info //save this info
Config.config.sponsorTimes.set(sponsorVideoID, segments); Config.config.segmentTimes.set(sponsorVideoID, sponsorTimesSubmitting);
updateSponsorTimesSubmitting(false) updateSponsorTimesSubmitting(false)
} }
function updateSponsorTimesSubmitting(getFromConfig: boolean = true) { function updateSponsorTimesSubmitting(getFromConfig: boolean = true) {
let segments = Config.config.sponsorTimes.get(sponsorVideoID); let segmentTimes = Config.config.segmentTimes.get(sponsorVideoID);
//see if this data should be saved in the sponsorTimesSubmitting variable //see if this data should be saved in the sponsorTimesSubmitting variable
if (getFromConfig && segments != undefined) { if (getFromConfig && segmentTimes != undefined) {
sponsorTimesSubmitting = []; sponsorTimesSubmitting = [];
for (const segment of segments) { for (const segmentTime of segmentTimes) {
sponsorTimesSubmitting.push({ sponsorTimesSubmitting.push({
segment: segment, segment: segmentTime.segment,
UUID: null, UUID: null,
// Default to sponsor category: segmentTime.category
category: "sponsor"
}); });
} }
} }
@@ -1321,7 +1314,7 @@ function clearSponsorTimes() {
let currentVideoID = sponsorVideoID; let currentVideoID = sponsorVideoID;
let sponsorTimes = Config.config.sponsorTimes.get(currentVideoID); let sponsorTimes = Config.config.segmentTimes.get(currentVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0) { if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let confirmMessage = chrome.i18n.getMessage("clearThis") + getSegmentsMessage(sponsorTimes) let confirmMessage = chrome.i18n.getMessage("clearThis") + getSegmentsMessage(sponsorTimes)
@@ -1329,7 +1322,7 @@ function clearSponsorTimes() {
if(!confirm(confirmMessage)) return; if(!confirm(confirmMessage)) return;
//clear the sponsor times //clear the sponsor times
Config.config.sponsorTimes.delete(currentVideoID); Config.config.segmentTimes.delete(currentVideoID);
//clear sponsor times submitting //clear sponsor times submitting
sponsorTimesSubmitting = []; sponsorTimesSubmitting = [];
@@ -1451,14 +1444,14 @@ async function sendSubmitMessage(){
} }
//update sponsorTimes //update sponsorTimes
Config.config.sponsorTimes.set(sponsorVideoID, utils.getSegmentsFromSponsorTimes(sponsorTimesSubmitting)); Config.config.segmentTimes.set(sponsorVideoID, sponsorTimesSubmitting);
// Check to see if any of the submissions are below the minimum duration set // Check to see if any of the submissions are below the minimum duration set
if (Config.config.minDuration > 0) { if (Config.config.minDuration > 0) {
for (let i = 0; i < sponsorTimesSubmitting.length; i++) { for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
if (sponsorTimesSubmitting[i].segment[1] - sponsorTimesSubmitting[i].segment[0] < Config.config.minDuration) { if (sponsorTimesSubmitting[i].segment[1] - sponsorTimesSubmitting[i].segment[0] < Config.config.minDuration) {
let confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" + let confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" +
getSegmentsMessage(utils.getSegmentsFromSponsorTimes(sponsorTimesSubmitting)); getSegmentsMessage(sponsorTimesSubmitting);
if(!confirm(confirmShort)) return; if(!confirm(confirmShort)) return;
} }
@@ -1488,7 +1481,7 @@ async function sendSubmitMessage(){
submitButton.addEventListener("animationend", animationEndListener); submitButton.addEventListener("animationend", animationEndListener);
//clear the sponsor times //clear the sponsor times
Config.config.sponsorTimes.delete(sponsorVideoID); Config.config.segmentTimes.delete(sponsorVideoID);
//add submissions to current sponsors list //add submissions to current sponsors list
if (sponsorTimes === null) sponsorTimes = []; if (sponsorTimes === null) sponsorTimes = [];
@@ -1516,12 +1509,12 @@ async function sendSubmitMessage(){
} }
//get the message that visually displays the video times //get the message that visually displays the video times
function getSegmentsMessage(segments: number[][]): string { function getSegmentsMessage(sponsorTimes: SponsorTime[]): string {
let sponsorTimesMessage = ""; let sponsorTimesMessage = "";
for (let i = 0; i < segments.length; i++) { for (let i = 0; i < sponsorTimes.length; i++) {
for (let s = 0; s < segments[i].length; s++) { for (let s = 0; s < sponsorTimes[i].segment.length; s++) {
let timeMessage = utils.getFormattedTime(segments[i][s]); let timeMessage = utils.getFormattedTime(sponsorTimes[i].segment[s]);
//if this is an end time //if this is an end time
if (s == 1) { if (s == 1) {
timeMessage = " to " + timeMessage; timeMessage = " to " + timeMessage;

View File

@@ -6,6 +6,8 @@
'use strict'; 'use strict';
import Config from "../config"; import Config from "../config";
import Utils from "../utils";
let utils = new Utils();
class PreviewBar { class PreviewBar {
container: HTMLUListElement; container: HTMLUListElement;
@@ -79,8 +81,8 @@ class PreviewBar {
tooltipTextWrapper.classList.remove("sbTooltipOneTitleThumbnailOffset"); tooltipTextWrapper.classList.remove("sbTooltipOneTitleThumbnailOffset");
} else if (category !== null) { } else if (category !== null) {
categoryTooltip.classList.remove("sbHidden"); categoryTooltip.classList.remove("sbHidden");
categoryTooltip.textContent = chrome.i18n.getMessage("category_" + category) categoryTooltip.textContent = utils.shortCategoryName(category)
|| (chrome.i18n.getMessage("preview") + " " + chrome.i18n.getMessage("category_" + category.split("preview-")[1])); || (chrome.i18n.getMessage("preview") + " " + utils.shortCategoryName(category.split("preview-")[1]));
// There is a title now // There is a title now
tooltip.classList.remove("ytp-tooltip-text-no-title"); tooltip.classList.remove("ytp-tooltip-text-no-title");

View File

@@ -237,7 +237,7 @@ function invidiousInstanceAddInit(element: HTMLElement, option: string) {
let setButton = element.querySelector(".text-change-set"); let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async function(e) { setButton.addEventListener("click", async function(e) {
if (textBox.value == "" || textBox.value.includes("/") || textBox.value.includes("http") || textBox.value.includes(":")) { if (textBox.value == "" || textBox.value.includes("/") || textBox.value.includes("http")) {
alert(chrome.i18n.getMessage("addInvidiousInstanceError")); alert(chrome.i18n.getMessage("addInvidiousInstanceError"));
} else { } else {
// Add this // Add this
@@ -298,19 +298,23 @@ function invidiousInit(checkbox: HTMLInputElement, option: string) {
* @param checkbox * @param checkbox
* @param option * @param option
*/ */
function invidiousOnClick(checkbox: HTMLInputElement, option: string) { async function invidiousOnClick(checkbox: HTMLInputElement, option: string) {
if (checkbox.checked) { return new Promise((resolve) => {
utils.setupExtraSitePermissions(function (granted) { if (checkbox.checked) {
if (!granted) { utils.setupExtraSitePermissions(function (granted) {
Config.config[option] = false; if (!granted) {
checkbox.checked = false; Config.config[option] = false;
} else { checkbox.checked = false;
checkbox.checked = true; } else {
} checkbox.checked = true;
}); }
} else {
utils.removeExtraSiteRegistration(); resolve();
} });
} else {
utils.removeExtraSiteRegistration();
}
});
} }
/** /**
@@ -358,15 +362,6 @@ function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) {
let button: HTMLElement = element.querySelector(".trigger-button"); let button: HTMLElement = element.querySelector(".trigger-button");
let option = element.getAttribute("sync-option"); let option = element.getAttribute("sync-option");
// Don't allow keys which are already listened for by youtube
let restrictedKeys = "1234567890,.jklftcibmJKLFTCIBMNP/<> -+";
if (restrictedKeys.indexOf(key) !== -1 ) {
closeKeybindOption(element, button);
alert(chrome.i18n.getMessage("theKey") + " " + key + " " + chrome.i18n.getMessage("keyAlreadyUsedByYouTube"));
return;
}
// Make sure keybind isn't used by the other listener // Make sure keybind isn't used by the other listener
// TODO: If other keybindings are going to be added, we need a better way to find the other keys used. // TODO: If other keybindings are going to be added, we need a better way to find the other keys used.
let otherKeybind = (option === "startSponsorKeybind") ? Config.config['submitKeybind'] : Config.config['startSponsorKeybind']; let otherKeybind = (option === "startSponsorKeybind") ? Config.config['submitKeybind'] : Config.config['startSponsorKeybind'];
@@ -435,8 +430,8 @@ function activatePrivateTextChange(element: HTMLElement) {
case "*": case "*":
let jsonData = JSON.parse(JSON.stringify(Config.localConfig)); let jsonData = JSON.parse(JSON.stringify(Config.localConfig));
// Fix sponsorTimes data as it is destroyed from the JSON stringify // Fix segmentTimes data as it is destroyed from the JSON stringify
jsonData.sponsorTimes = Config.encodeStoredItem(Config.localConfig.sponsorTimes); jsonData.segmentTimes = Config.encodeStoredItem(Config.localConfig.segmentTimes);
result = JSON.stringify(jsonData); result = JSON.stringify(jsonData);
break; break;
@@ -445,7 +440,7 @@ function activatePrivateTextChange(element: HTMLElement) {
textBox.value = result; textBox.value = result;
let setButton = element.querySelector(".text-change-set"); let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", () => { setButton.addEventListener("click", async () => {
let confirmMessage = element.getAttribute("confirm-message"); let confirmMessage = element.getAttribute("confirm-message");
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) { if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
@@ -460,15 +455,14 @@ function activatePrivateTextChange(element: HTMLElement) {
} }
Config.convertJSON(); Config.convertJSON();
// Reload options on page
init();
if (newConfig.supportInvidious) { if (newConfig.supportInvidious) {
let checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input"); let checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input");
checkbox.checked = true; checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious"); await invidiousOnClick(checkbox, "supportInvidious");
} }
window.location.reload();
} catch (e) { } catch (e) {
alert(chrome.i18n.getMessage("incorrectlyFormattedOptions")); alert(chrome.i18n.getMessage("incorrectlyFormattedOptions"));
@@ -519,8 +513,8 @@ function copyDebugOutputToClipboard() {
config: JSON.parse(JSON.stringify(Config.localConfig)) // Deep clone config object config: JSON.parse(JSON.stringify(Config.localConfig)) // Deep clone config object
}; };
// Fix sponsorTimes data as it is destroyed from the JSON stringify // Fix segmentTimes data as it is destroyed from the JSON stringify
output.config.sponsorTimes = Config.encodeStoredItem(Config.localConfig.sponsorTimes); output.config.segmentTimes = Config.encodeStoredItem(Config.localConfig.segmentTimes);
// Sanitise sensitive user config values // Sanitise sensitive user config values
delete output.config.userID; delete output.config.userID;

View File

@@ -119,7 +119,7 @@ async function runThePopup(messageListener?: MessageListener) {
let startTimeChosen = false; let startTimeChosen = false;
//the start and end time pairs (2d) //the start and end time pairs (2d)
let sponsorTimes = []; let sponsorTimes: SponsorTime[] = [];
//current video ID of this tab //current video ID of this tab
let currentVideoID = null; let currentVideoID = null;
@@ -252,9 +252,9 @@ async function runThePopup(messageListener?: MessageListener) {
} }
//load video times for this video //load video times for this video
let sponsorTimesStorage = Config.config.sponsorTimes.get(currentVideoID); let sponsorTimesStorage = Config.config.segmentTimes.get(currentVideoID);
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) { if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].segment.length < 2) {
startTimeChosen = true; startTimeChosen = true;
PageElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); PageElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd");
} }
@@ -336,13 +336,17 @@ async function runThePopup(messageListener?: MessageListener) {
let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0);
if (sponsorTimes[sponsorTimesIndex] == undefined) { if (sponsorTimes[sponsorTimesIndex] == undefined) {
sponsorTimes[sponsorTimesIndex] = []; sponsorTimes[sponsorTimesIndex] = {
segment: [],
category: "sponsor",
UUID: null
};
} }
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time; sponsorTimes[sponsorTimesIndex].segment[startTimeChosen ? 1 : 0] = response.time;
let localStartTimeChosen = startTimeChosen; let localStartTimeChosen = startTimeChosen;
Config.config.sponsorTimes.set(currentVideoID, sponsorTimes); Config.config.segmentTimes.set(currentVideoID, sponsorTimes);
//send a message to the client script //send a message to the client script
if (localStartTimeChosen) { if (localStartTimeChosen) {
@@ -528,7 +532,7 @@ async function runThePopup(messageListener?: MessageListener) {
} }
function previewSponsorTime(index) { function previewSponsorTime(index) {
let skipTime = sponsorTimes[index][0]; let skipTime = sponsorTimes[index].segment[0];
if (document.getElementById("startTimeMinutes" + index) != null) { if (document.getElementById("startTimeMinutes" + index) != null) {
//edit is currently open, use that time //edit is currently open, use that time
@@ -575,28 +579,28 @@ async function runThePopup(messageListener?: MessageListener) {
startTimeMinutes.id = "startTimeMinutes" + index; startTimeMinutes.id = "startTimeMinutes" + index;
startTimeMinutes.className = "sponsorTime popupElement"; startTimeMinutes.className = "sponsorTime popupElement";
startTimeMinutes.type = "text"; startTimeMinutes.type = "text";
startTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index][0])); startTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index].segment[0]));
startTimeMinutes.style.width = "45px"; startTimeMinutes.style.width = "45px";
let startTimeSeconds = document.createElement("input"); let startTimeSeconds = document.createElement("input");
startTimeSeconds.id = "startTimeSeconds" + index; startTimeSeconds.id = "startTimeSeconds" + index;
startTimeSeconds.className = "sponsorTime popupElement"; startTimeSeconds.className = "sponsorTime popupElement";
startTimeSeconds.type = "text"; startTimeSeconds.type = "text";
startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]); startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index].segment[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";
endTimeMinutes.type = "text"; endTimeMinutes.type = "text";
endTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index][1])); endTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index].segment[1]));
endTimeMinutes.style.width = "45px"; endTimeMinutes.style.width = "45px";
let endTimeSeconds = document.createElement("input"); let endTimeSeconds = document.createElement("input");
endTimeSeconds.id = "endTimeSeconds" + index; endTimeSeconds.id = "endTimeSeconds" + index;
endTimeSeconds.className = "sponsorTime popupElement"; endTimeSeconds.className = "sponsorTime popupElement";
endTimeSeconds.type = "text"; endTimeSeconds.type = "text";
endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]); endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index].segment[1]);
endTimeSeconds.style.width = "60px"; endTimeSeconds.style.width = "60px";
//the button to set the current time //the button to set the current time
@@ -668,11 +672,11 @@ async function runThePopup(messageListener?: MessageListener) {
} }
function saveSponsorTimeEdit(index, closeEditMode = true) { function saveSponsorTimeEdit(index, closeEditMode = true) {
sponsorTimes[index][0] = getSponsorTimeEditTimes("startTime", index); sponsorTimes[index].segment[0] = getSponsorTimeEditTimes("startTime", index);
sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index); sponsorTimes[index].segment[1] = getSponsorTimeEditTimes("endTime", index);
//save this //save this
Config.config.sponsorTimes.set(currentVideoID, sponsorTimes); Config.config.segmentTimes.set(currentVideoID, sponsorTimes);
messageHandler.query({ messageHandler.query({
active: true, active: true,
@@ -692,7 +696,7 @@ async function runThePopup(messageListener?: MessageListener) {
//deletes the sponsor time submitted at an index //deletes the sponsor time submitted at an index
function deleteSponsorTime(index) { function deleteSponsorTime(index) {
//if it is not a complete sponsor time //if it is not a complete sponsor time
if (sponsorTimes[index].length < 2) { if (sponsorTimes[index].segment.length < 2) {
messageHandler.query({ messageHandler.query({
active: true, active: true,
currentWindow: true currentWindow: true
@@ -710,7 +714,7 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimes.splice(index, 1); sponsorTimes.splice(index, 1);
//save this //save this
Config.config.sponsorTimes.set(currentVideoID, sponsorTimes); Config.config.segmentTimes.set(currentVideoID, sponsorTimes);
//if they are all removed //if they are all removed
if (sponsorTimes.length == 0) { if (sponsorTimes.length == 0) {
@@ -780,7 +784,7 @@ async function runThePopup(messageListener?: MessageListener) {
//hides and shows the submit times button when needed //hides and shows the submit times button when needed
function showSubmitTimesIfNecessary() { function showSubmitTimesIfNecessary() {
//check if an end time has been specified for the latest sponsor time //check if an end time has been specified for the latest sponsor time
if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length > 1) { if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].segment.length > 1) {
//show submit times button //show submit times button
document.getElementById("submitTimesContainer").style.display = "unset"; document.getElementById("submitTimesContainer").style.display = "unset";
} else { } else {

View File

@@ -350,6 +350,10 @@ class Utils {
return formatted; return formatted;
} }
shortCategoryName(categoryName: string): string {
return chrome.i18n.getMessage("category_" + categoryName + "_short") || chrome.i18n.getMessage("category_" + categoryName);
}
getRawSeconds(minutes: number, seconds: number): number { getRawSeconds(minutes: number, seconds: number): number {
return minutes * 60 + seconds; return minutes * 60 + seconds;
} }