refactor(lint): apply automatic eslint fixes

This commit is contained in:
Max Baumann
2020-12-12 22:57:41 +01:00
parent 105c148ccc
commit 36558f5460
16 changed files with 313 additions and 313 deletions

View File

@@ -5,13 +5,13 @@ import Config from "./config";
(<any> window).SB = Config; (<any> window).SB = Config;
import Utils from "./utils"; import Utils from "./utils";
var utils = new Utils({ const utils = new Utils({
registerFirefoxContentScript, registerFirefoxContentScript,
unregisterFirefoxContentScript unregisterFirefoxContentScript
}); });
// Used only on Firefox, which does not support non persistent background pages. // Used only on Firefox, which does not support non persistent background pages.
var contentScriptRegistrations = {}; const contentScriptRegistrations = {};
// Register content script if needed // Register content script if needed
if (utils.isFirefox()) { if (utils.isFirefox()) {
@@ -91,7 +91,7 @@ chrome.runtime.onInstalled.addListener(function (object) {
* @param {JSON} options * @param {JSON} options
*/ */
function registerFirefoxContentScript(options) { function registerFirefoxContentScript(options) {
let oldRegistration = contentScriptRegistrations[options.id]; const oldRegistration = contentScriptRegistrations[options.id];
if (oldRegistration) oldRegistration.unregister(); if (oldRegistration) oldRegistration.unregister();
browser.contentScripts.register({ browser.contentScripts.register({
@@ -121,10 +121,10 @@ async function submitVote(type: number, UUID: string, category: string) {
Config.config.userID = userID; Config.config.userID = userID;
} }
let typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category; const typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category;
//publish this vote //publish this vote
let response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection); const response = await asyncRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection);
if (response.ok) { if (response.ok) {
return { return {
@@ -146,7 +146,7 @@ async function submitVote(type: number, UUID: string, category: string) {
} }
async function asyncRequestToServer(type: string, address: string, data = {}) { async function asyncRequestToServer(type: string, address: string, data = {}) {
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress; const serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;
return await (sendRequestToCustomServer(type, serverAddress + address, data)); return await (sendRequestToCustomServer(type, serverAddress + address, data));
} }
@@ -162,8 +162,8 @@ async function sendRequestToCustomServer(type: string, url: string, data = {}) {
// If GET, convert JSON to parameters // If GET, convert JSON to parameters
if (type.toLowerCase() === "get") { if (type.toLowerCase() === "get") {
for (const key in data) { for (const key in data) {
let seperator = url.includes("?") ? "&" : "?"; const seperator = url.includes("?") ? "&" : "?";
let value = (typeof(data[key]) === "string") ? data[key]: JSON.stringify(data[key]); const value = (typeof(data[key]) === "string") ? data[key]: JSON.stringify(data[key]);
url += seperator + key + "=" + value; url += seperator + key + "=" + value;
} }

View File

@@ -55,7 +55,7 @@ class CategoryChooserComponent extends React.Component<CategoryChooserProps, Cat
} }
getCategorySkipOptions(): JSX.Element[] { getCategorySkipOptions(): JSX.Element[] {
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
for (const category of CompileConfig.categoryList) { for (const category of CompileConfig.categoryList) {
elements.push( elements.push(

View File

@@ -145,9 +145,9 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
} }
getCategorySkipOptions(): JSX.Element[] { getCategorySkipOptions(): JSX.Element[] {
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
let optionNames = ["disable", "showOverlay", "manualSkip", "autoSkip"]; const optionNames = ["disable", "showOverlay", "manualSkip", "autoSkip"];
for (const optionName of optionNames) { for (const optionName of optionNames) {
elements.push( elements.push(

View File

@@ -35,7 +35,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
constructor(props: NoticeProps) { constructor(props: NoticeProps) {
super(props); super(props);
let maxCountdownTime = () => { const maxCountdownTime = () => {
if (this.props.maxCountdownTime) return this.props.maxCountdownTime(); if (this.props.maxCountdownTime) return this.props.maxCountdownTime();
else return 4; else return 4;
}; };
@@ -65,7 +65,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
} }
render() { render() {
let noticeStyle: React.CSSProperties = { const noticeStyle: React.CSSProperties = {
zIndex: this.props.zIndex || (50 + this.amountOfPreviousNotices) zIndex: this.props.zIndex || (50 + this.amountOfPreviousNotices)
} }
@@ -152,7 +152,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
countdown() { countdown() {
if (!this.props.timed) return; if (!this.props.timed) return;
let countdownTime = this.state.countdownTime - 1; const countdownTime = this.state.countdownTime - 1;
if (countdownTime <= 0) { if (countdownTime <= 0) {
//remove this from setInterval //remove this from setInterval
@@ -166,7 +166,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
if (countdownTime == 3) { if (countdownTime == 3) {
//start fade out animation //start fade out animation
let notice = document.getElementById("sponsorSkipNotice" + this.idSuffix); const notice = document.getElementById("sponsorSkipNotice" + this.idSuffix);
notice.style.removeProperty("animation"); notice.style.removeProperty("animation");
notice.classList.add("sponsorSkipNoticeFadeOut"); notice.classList.add("sponsorSkipNoticeFadeOut");
} }
@@ -190,7 +190,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
}); });
//remove the fade out class if it exists //remove the fade out class if it exists
let notice = document.getElementById("sponsorSkipNotice" + this.idSuffix); const notice = document.getElementById("sponsorSkipNotice" + this.idSuffix);
notice.classList.remove("sponsorSkipNoticeFadeOut"); notice.classList.remove("sponsorSkipNoticeFadeOut");
notice.style.animation = "none"; notice.style.animation = "none";
} }
@@ -234,23 +234,23 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
}); });
} }
addNoticeInfoMessage(message: string, message2: string = "") { addNoticeInfoMessage(message: string, message2 = "") {
//TODO: Replace //TODO: Replace
let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + this.idSuffix); const previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + this.idSuffix);
if (previousInfoMessage != null) { if (previousInfoMessage != null) {
//remove it //remove it
document.getElementById("sponsorSkipNotice" + this.idSuffix).removeChild(previousInfoMessage); document.getElementById("sponsorSkipNotice" + this.idSuffix).removeChild(previousInfoMessage);
} }
let previousInfoMessage2 = document.getElementById("sponsorTimesInfoMessage" + this.idSuffix + "2"); const previousInfoMessage2 = document.getElementById("sponsorTimesInfoMessage" + this.idSuffix + "2");
if (previousInfoMessage2 != null) { if (previousInfoMessage2 != null) {
//remove it //remove it
document.getElementById("sponsorSkipNotice" + this.idSuffix).removeChild(previousInfoMessage2); document.getElementById("sponsorSkipNotice" + this.idSuffix).removeChild(previousInfoMessage2);
} }
//add info //add info
let thanksForVotingText = document.createElement("p"); const thanksForVotingText = document.createElement("p");
thanksForVotingText.id = "sponsorTimesInfoMessage" + this.idSuffix; thanksForVotingText.id = "sponsorTimesInfoMessage" + this.idSuffix;
thanksForVotingText.className = "sponsorTimesInfoMessage"; thanksForVotingText.className = "sponsorTimesInfoMessage";
thanksForVotingText.innerText = message; thanksForVotingText.innerText = message;
@@ -259,7 +259,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix)); document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix));
if (message2 !== undefined) { if (message2 !== undefined) {
let thanksForVotingText2 = document.createElement("p"); const thanksForVotingText2 = document.createElement("p");
thanksForVotingText2.id = "sponsorTimesInfoMessage" + this.idSuffix + "2"; thanksForVotingText2.id = "sponsorTimesInfoMessage" + this.idSuffix + "2";
thanksForVotingText2.className = "sponsorTimesInfoMessage"; thanksForVotingText2.className = "sponsorTimesInfoMessage";
thanksForVotingText2.innerText = message2; thanksForVotingText2.innerText = message2;

View File

@@ -17,7 +17,7 @@ class NoticeTextSelectionComponent extends React.Component<NoticeTextSelectionPr
} }
render() { render() {
let style: React.CSSProperties = {}; const style: React.CSSProperties = {};
if (this.props.onClick) { if (this.props.onClick) {
style.cursor = "pointer"; style.cursor = "pointer";
style.textDecoration = "underline" style.textDecoration = "underline"

View File

@@ -4,7 +4,7 @@ import Config from "../config"
import { ContentContainer, SponsorHideType, SponsorTime } from "../types"; import { ContentContainer, SponsorHideType, SponsorTime } from "../types";
import Utils from "../utils"; import Utils from "../utils";
var utils = new Utils(); const utils = new Utils();
import NoticeComponent from "./NoticeComponent"; import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
@@ -74,7 +74,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.contentContainer = props.contentContainer; this.contentContainer = props.contentContainer;
this.audio = null; this.audio = null;
let categoryName = chrome.i18n.getMessage(this.segments.length > 1 ? "multipleSegments" const categoryName = chrome.i18n.getMessage(this.segments.length > 1 ? "multipleSegments"
: "category_" + this.segments[0].category + "_short") || chrome.i18n.getMessage("category_" + this.segments[0].category); : "category_" + this.segments[0].category + "_short") || chrome.i18n.getMessage("category_" + this.segments[0].category);
let noticeTitle = categoryName + " " + chrome.i18n.getMessage("skipped"); let noticeTitle = categoryName + " " + chrome.i18n.getMessage("skipped");
if (!this.autoSkip) { if (!this.autoSkip) {
@@ -98,7 +98,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
if (this.amountOfPreviousNotices > 0) { if (this.amountOfPreviousNotices > 0) {
//another notice exists //another notice exists
let previousNotice = document.getElementsByClassName("sponsorSkipNotice")[0]; const previousNotice = document.getElementsByClassName("sponsorSkipNotice")[0];
previousNotice.classList.add("secondSkipNotice") previousNotice.classList.add("secondSkipNotice")
} }
@@ -137,7 +137,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
render() { render() {
let noticeStyle: React.CSSProperties = { const noticeStyle: React.CSSProperties = {
zIndex: 50 + this.amountOfPreviousNotices zIndex: 50 + this.amountOfPreviousNotices
} }
if (this.contentContainer().onMobileYouTube) { if (this.contentContainer().onMobileYouTube) {
@@ -286,7 +286,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
getSubmissionChooser(): JSX.Element[] { getSubmissionChooser(): JSX.Element[] {
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
for (let i = 0; i < this.segments.length; i++) { for (let i = 0; i < this.segments.length; i++) {
elements.push( elements.push(
@@ -321,7 +321,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
); );
} }
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
for (let i = 0; i < this.state.messages.length; i++) { for (let i = 0; i < this.state.messages.length; i++) {
elements.push( elements.push(
@@ -397,7 +397,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
getCategoryOptions() { getCategoryOptions() {
let elements = []; const elements = [];
for (const category of Config.config.categorySelections) { for (const category of Config.config.categorySelections) {
elements.push( elements.push(
@@ -448,10 +448,10 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
getUnskippedModeInfo(index: number, buttonText: string) { getUnskippedModeInfo(index: number, buttonText: string) {
let self = this; const self = this;
let maxCountdownTime = function() { const maxCountdownTime = function() {
let sponsorTime = self.segments[index]; const sponsorTime = self.segments[index];
let duration = Math.round((sponsorTime.segment[1] - self.contentContainer().v.currentTime) * (1 / self.contentContainer().v.playbackRate)); const duration = Math.round((sponsorTime.segment[1] - self.contentContainer().v.currentTime) * (1 / self.contentContainer().v.playbackRate));
return Math.max(duration, 4); return Math.max(duration, 4);
}; };

View File

@@ -6,7 +6,7 @@ import * as CompileConfig from "../../config.json";
import Utils from "../utils"; import Utils from "../utils";
import { ContentContainer, SponsorTime } from "../types"; import { ContentContainer, SponsorTime } from "../types";
import SubmissionNoticeComponent from "./SubmissionNoticeComponent"; import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
var utils = new Utils(); const utils = new Utils();
export interface SponsorTimeEditProps { export interface SponsorTimeEditProps {
index: number, index: number,
@@ -64,7 +64,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
render() { render() {
let style: React.CSSProperties = { const style: React.CSSProperties = {
textAlign: "center" textAlign: "center"
}; };
@@ -74,7 +74,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
// This method is required to get !important // This method is required to get !important
// https://stackoverflow.com/a/45669262/1985387 // https://stackoverflow.com/a/45669262/1985387
let oldYouTubeDarkStyles = (node) => { const oldYouTubeDarkStyles = (node) => {
if (node) { if (node) {
node.style.setProperty("color", "black", "important"); node.style.setProperty("color", "black", "important");
node.style.setProperty("text-shadow", "none", "important"); node.style.setProperty("text-shadow", "none", "important");
@@ -83,8 +83,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
// Create time display // Create time display
let timeDisplay: JSX.Element; let timeDisplay: JSX.Element;
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
let segment = sponsorTime.segment; const segment = sponsorTime.segment;
if (this.state.editing) { if (this.state.editing) {
timeDisplay = ( timeDisplay = (
<div id={"sponsorTimesContainer" + this.idSuffix} <div id={"sponsorTimesContainer" + this.idSuffix}
@@ -102,7 +102,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
type="text" type="text"
value={this.state.sponsorTimeEdits[0]} value={this.state.sponsorTimeEdits[0]}
onChange={(e) => { onChange={(e) => {
let sponsorTimeEdits = this.state.sponsorTimeEdits; const sponsorTimeEdits = this.state.sponsorTimeEdits;
sponsorTimeEdits[0] = e.target.value; sponsorTimeEdits[0] = e.target.value;
this.setState({sponsorTimeEdits}); this.setState({sponsorTimeEdits});
@@ -121,7 +121,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
type="text" type="text"
value={this.state.sponsorTimeEdits[1]} value={this.state.sponsorTimeEdits[1]}
onChange={(e) => { onChange={(e) => {
let sponsorTimeEdits = this.state.sponsorTimeEdits; const sponsorTimeEdits = this.state.sponsorTimeEdits;
sponsorTimeEdits[1] = e.target.value; sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits}); this.setState({sponsorTimeEdits});
@@ -216,7 +216,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
getCategoryOptions() { getCategoryOptions() {
let elements = [( const elements = [(
<option value={"chooseACategory"} <option value={"chooseACategory"}
key={"chooseACategory"}> key={"chooseACategory"}>
{chrome.i18n.getMessage("chooseACategory")} {chrome.i18n.getMessage("chooseACategory")}
@@ -268,7 +268,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
setTimeTo(index: number, time: number) { setTimeTo(index: number, time: number) {
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
sponsorTime.segment[index] = sponsorTime.segment[index] =
time; time;
@@ -287,7 +287,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.saveEditTimes(); this.saveEditTimes();
} else { } else {
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
this.setState({ this.setState({
editing: true, editing: true,
@@ -303,7 +303,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
saveEditTimes() { saveEditTimes() {
let sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting;
if (this.state.editing) { if (this.state.editing) {
const startTime = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]); const startTime = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]);
@@ -323,26 +323,26 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
previewTime(): void { previewTime(): void {
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
let index = this.props.index; const index = this.props.index;
let skipTime = sponsorTimes[index].segment[0]; const skipTime = sponsorTimes[index].segment[0];
this.props.contentContainer().previewTime(skipTime - 2); this.props.contentContainer().previewTime(skipTime - 2);
} }
inspectTime(): void { inspectTime(): void {
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
let index = this.props.index; const index = this.props.index;
let skipTime = sponsorTimes[index].segment[0]; const skipTime = sponsorTimes[index].segment[0];
this.props.contentContainer().previewTime(skipTime + 0.000001, false); this.props.contentContainer().previewTime(skipTime + 0.000001, false);
} }
deleteTime(): void { deleteTime(): void {
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
let index = this.props.index; const index = this.props.index;
//if it is not a complete sponsor time //if it is not a complete sponsor time
if (sponsorTimes[index].segment.length < 2) { if (sponsorTimes[index].segment.length < 2) {

View File

@@ -39,7 +39,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
this.contentContainer = props.contentContainer; this.contentContainer = props.contentContainer;
this.callback = props.callback; this.callback = props.callback;
let noticeTitle = chrome.i18n.getMessage("confirmNoticeTitle"); const noticeTitle = chrome.i18n.getMessage("confirmNoticeTitle");
// Setup state // Setup state
this.state = { this.state = {
@@ -114,13 +114,13 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
} }
getSponsorTimeMessages(): JSX.Element[] | JSX.Element { getSponsorTimeMessages(): JSX.Element[] | JSX.Element {
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
this.timeEditRefs = []; this.timeEditRefs = [];
let sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
for (let i = 0; i < sponsorTimes.length; i++) { for (let i = 0; i < sponsorTimes.length; i++) {
let timeRef = React.createRef<SponsorTimeEditComponent>(); const timeRef = React.createRef<SponsorTimeEditComponent>();
elements.push( elements.push(
<SponsorTimeEditComponent key={i} <SponsorTimeEditComponent key={i}
@@ -139,7 +139,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
} }
getMessageBoxes(): JSX.Element[] | JSX.Element { getMessageBoxes(): JSX.Element[] | JSX.Element {
let elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
for (let i = 0; i < this.state.messages.length; i++) { for (let i = 0; i < this.state.messages.length; i++) {
elements.push( elements.push(
@@ -167,7 +167,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
ref.current.saveEditTimes(); ref.current.saveEditTimes();
} }
let sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting;
for (const sponsorTime of sponsorTimesSubmitting) { for (const sponsorTime of sponsorTimesSubmitting) {
if (sponsorTime.category === "chooseACategory") { if (sponsorTime.category === "chooseACategory") {
alert(chrome.i18n.getMessage("youMustSelectACategory")); alert(chrome.i18n.getMessage("youMustSelectACategory"));

View File

@@ -132,7 +132,7 @@ class SBMap<T, U> extends Map {
} }
} }
var Config: SBObject = { const Config: SBObject = {
/** /**
* Callback function when an option is updated * Callback function when an option is updated
*/ */
@@ -286,7 +286,7 @@ function configProxy(): any {
} }
}); });
var handler: ProxyHandler<any> = { const handler: ProxyHandler<any> = {
set(obj, prop, value) { set(obj, prop, value) {
Config.localConfig[prop] = value; Config.localConfig[prop] = value;
@@ -298,7 +298,7 @@ function configProxy(): any {
}, },
get(obj, prop): any { get(obj, prop): any {
let data = Config.localConfig[prop]; const data = Config.localConfig[prop];
return obj[prop] || data; return obj[prop] || data;
}, },
@@ -351,7 +351,7 @@ function migrateOldFormats(config: SBConfig) {
if (config.whitelistedChannels.length > 0 && if (config.whitelistedChannels.length > 0 &&
(config.whitelistedChannels[0] == null || config.whitelistedChannels[0].includes("/"))) { (config.whitelistedChannels[0] == null || config.whitelistedChannels[0].includes("/"))) {
const channelURLFixer = async() => { const channelURLFixer = async() => {
let newChannelList: string[] = []; const newChannelList: string[] = [];
for (const item of config.whitelistedChannels) { for (const item of config.whitelistedChannels) {
if (item != null) { if (item != null) {
if (item.includes("/channel/")) { if (item.includes("/channel/")) {
@@ -360,7 +360,7 @@ function migrateOldFormats(config: SBConfig) {
// Replace channel URL with channelID // Replace channel URL with channelID
let response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId"); const 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((JSON.parse(response.responseText)).authorId); newChannelList.push((JSON.parse(response.responseText)).authorId);
@@ -408,9 +408,9 @@ function migrateOldFormats(config: SBConfig) {
// Otherwise junk data // Otherwise junk data
if (Array.isArray(jsonData)) { if (Array.isArray(jsonData)) {
let oldMap = new Map(jsonData); const oldMap = new Map(jsonData);
oldMap.forEach((sponsorTimes: number[][], key) => { oldMap.forEach((sponsorTimes: number[][], key) => {
let segmentTimes: SponsorTime[] = []; const segmentTimes: SponsorTime[] = [];
for (const segment of sponsorTimes) { for (const segment of sponsorTimes) {
segmentTimes.push({ segmentTimes.push({
segment: segment, segment: segment,
@@ -442,7 +442,7 @@ async function setupConfig() {
// Reset config // Reset config
function resetConfig() { function resetConfig() {
Config.config = Config.defaults; Config.config = Config.defaults;
}; }
function convertJSON(): void { function convertJSON(): void {
Object.keys(Config.localConfig).forEach(key => { Object.keys(Config.localConfig).forEach(key => {
@@ -463,7 +463,7 @@ function addDefaults() {
} }
} }
} }
}; }
// Sync config // Sync config
setupConfig(); setupConfig();

View File

@@ -4,7 +4,7 @@ import { SponsorTime, CategorySkipOption, CategorySelection, VideoID, SponsorHid
import { ContentContainer } from "./types"; import { ContentContainer } from "./types";
import Utils from "./utils"; import Utils from "./utils";
var utils = new Utils(); const utils = new Utils();
import runThePopup from "./popup"; import runThePopup from "./popup";
@@ -17,80 +17,80 @@ import SubmissionNotice from "./render/SubmissionNotice";
utils.wait(() => Config.config !== null, 5000, 10).then(addCSS); utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
//was sponsor data found when doing SponsorsLookup //was sponsor data found when doing SponsorsLookup
var sponsorDataFound = false; let sponsorDataFound = false;
var previousVideoID: VideoID = null; let previousVideoID: VideoID = null;
//the actual sponsorTimes if loaded and UUIDs associated with them //the actual sponsorTimes if loaded and UUIDs associated with them
var sponsorTimes: SponsorTime[] = null; let sponsorTimes: SponsorTime[] = null;
//what video id are these sponsors for //what video id are these sponsors for
var sponsorVideoID: VideoID = null; let sponsorVideoID: VideoID = null;
// JSON video info // JSON video info
var videoInfo: any = null; let videoInfo: any = null;
//the channel this video is about //the channel this video is about
var channelID; let channelID;
// Skips are scheduled to ensure precision. // Skips are scheduled to ensure precision.
// Skips are rescheduled every seeking event. // Skips are rescheduled every seeking event.
// Skips are canceled every seeking event // Skips are canceled every seeking event
var currentSkipSchedule: NodeJS.Timeout = null; let currentSkipSchedule: NodeJS.Timeout = null;
var seekListenerSetUp = false let seekListenerSetUp = false
/** @type {Array[boolean]} Has the sponsor been skipped */ /** @type {Array[boolean]} Has the sponsor been skipped */
var sponsorSkipped: boolean[] = []; let sponsorSkipped: boolean[] = [];
//the video //the video
var video: HTMLVideoElement; let video: HTMLVideoElement;
var onInvidious; let onInvidious;
var onMobileYouTube; let onMobileYouTube;
//the video id of the last preview bar update //the video id of the last preview bar update
var lastPreviewBarUpdate; let lastPreviewBarUpdate;
//whether the duration listener listening for the duration changes of the video has been setup yet //whether the duration listener listening for the duration changes of the video has been setup yet
var durationListenerSetUp = false; let durationListenerSetUp = false;
// Is the video currently being switched // Is the video currently being switched
var switchingVideos = null; let switchingVideos = null;
// Used by the play and playing listeners to make sure two aren't // Used by the play and playing listeners to make sure two aren't
// called at the same time // called at the same time
var lastCheckTime = 0; let lastCheckTime = 0;
var lastCheckVideoTime = -1; let lastCheckVideoTime = -1;
//is this channel whitelised from getting sponsors skipped //is this channel whitelised from getting sponsors skipped
var channelWhitelisted = false; let channelWhitelisted = false;
// create preview bar // create preview bar
var previewBar: PreviewBar = null; let previewBar: PreviewBar = null;
//the player controls on the YouTube player //the player controls on the YouTube player
var controls = null; let controls = null;
// Direct Links after the config is loaded // Direct Links after the config is loaded
utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYouTubeVideoID(document.URL))); utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYouTubeVideoID(document.URL)));
//the amount of times the sponsor lookup has retried //the amount of times the sponsor lookup has retried
//this only happens if there is an error //this only happens if there is an error
var sponsorLookupRetries = 0; let sponsorLookupRetries = 0;
//if showing the start sponsor button or the end sponsor button on the player //if showing the start sponsor button or the end sponsor button on the player
var showingStartSponsor = true; let showingStartSponsor = true;
//the sponsor times being prepared to be submitted //the sponsor times being prepared to be submitted
var sponsorTimesSubmitting: SponsorTime[] = []; let sponsorTimesSubmitting: SponsorTime[] = [];
//becomes true when isInfoFound is called //becomes true when isInfoFound is called
//this is used to close the popup on YouTube when the other popup opens //this is used to close the popup on YouTube when the other popup opens
var popupInitialised = false; let popupInitialised = false;
var submissionNotice: SubmissionNotice = null; let submissionNotice: SubmissionNotice = null;
// If there is an advert playing (or about to be played), this is true // If there is an advert playing (or about to be played), this is true
var isAdPlaying = false; let isAdPlaying = false;
// Contains all of the functions and variables needed by the skip notice // Contains all of the functions and variables needed by the skip notice
var skipNoticeContentContainer: ContentContainer = () => ({ const skipNoticeContentContainer: ContentContainer = () => ({
vote, vote,
dontShowNoticeAgain, dontShowNoticeAgain,
unskipSponsorTime, unskipSponsorTime,
@@ -218,13 +218,13 @@ if (!Config.configListeners.includes(contentConfigUpdateListener)) {
//check for hotkey pressed //check for hotkey pressed
document.onkeydown = function(e: KeyboardEvent){ document.onkeydown = function(e: KeyboardEvent){
var key = e.key; const key = e.key;
let video = document.getElementById("movie_player"); const video = document.getElementById("movie_player");
let startSponsorKey = Config.config.startSponsorKeybind; const startSponsorKey = Config.config.startSponsorKeybind;
let submitKey = Config.config.submitKeybind; const submitKey = Config.config.submitKeybind;
//is the video in focus, otherwise they could be typing a comment //is the video in focus, otherwise they could be typing a comment
if (document.activeElement === video) { if (document.activeElement === video) {
@@ -296,7 +296,7 @@ async function videoIDChange(id) {
} }
if (isUnlisted()) { if (isUnlisted()) {
let shouldContinue = confirm(chrome.i18n.getMessage("confirmPrivacy")); const shouldContinue = confirm(chrome.i18n.getMessage("confirmPrivacy"));
if(!shouldContinue) return; if(!shouldContinue) return;
} }
} }
@@ -323,7 +323,7 @@ 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.segmentTimes.get(previousVideoID); const sponsorTimes = Config.config.segmentTimes.get(previousVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0 && new URL(document.URL).host !== "music.youtube.com") { if (sponsorTimes != undefined && sponsorTimes.length > 0 && new URL(document.URL).host !== "music.youtube.com") {
//warn them that they have unsubmitted sponsor times //warn them that they have unsubmitted sponsor times
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
@@ -347,7 +347,7 @@ 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.segmentTimes.get(sponsorVideoID); const segments = Config.config.segmentTimes.get(sponsorVideoID);
if (segments != null && segments.length > 0 && segments[segments.length - 1].segment.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].segment.length < 2) { } else if (segments != null && segments.length > 0 && segments[segments.length - 1].segment.length < 2) {
@@ -368,7 +368,7 @@ async function videoIDChange(id) {
} }
function handleMobileControlsMutations(): void { function handleMobileControlsMutations(): void {
let mobileYouTubeSelector = ".progress-bar-background"; const mobileYouTubeSelector = ".progress-bar-background";
updateVisibilityOfPlayerControlsButton().then((createdButtons) => { updateVisibilityOfPlayerControlsButton().then((createdButtons) => {
if (createdButtons) { if (createdButtons) {
@@ -470,14 +470,14 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
if (currentTime === undefined || currentTime === null) currentTime = video.currentTime; if (currentTime === undefined || currentTime === null) currentTime = video.currentTime;
let skipInfo = getNextSkipIndex(currentTime, includeIntersectingSegments, includeNonIntersectingSegments); const skipInfo = getNextSkipIndex(currentTime, includeIntersectingSegments, includeNonIntersectingSegments);
if (skipInfo.index === -1) return; if (skipInfo.index === -1) return;
let currentSkip = skipInfo.array[skipInfo.index]; const currentSkip = skipInfo.array[skipInfo.index];
let skipTime: number[] = [currentSkip.segment[0], skipInfo.array[skipInfo.endIndex].segment[1]]; const skipTime: number[] = [currentSkip.segment[0], skipInfo.array[skipInfo.endIndex].segment[1]];
let timeUntilSponsor = skipTime[0] - currentTime; const timeUntilSponsor = skipTime[0] - currentTime;
let videoID = sponsorVideoID; const videoID = sponsorVideoID;
// Find all indexes in between the start and end // Find all indexes in between the start and end
let skippingSegments = [skipInfo.array[skipInfo.index]]; let skippingSegments = [skipInfo.array[skipInfo.index]];
@@ -496,7 +496,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ShowOverlay if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ShowOverlay
&& skipInfo.array !== sponsorTimesSubmitting) return; && skipInfo.array !== sponsorTimesSubmitting) return;
let skippingFunction = () => { const skippingFunction = () => {
let forcedSkipTime: number = null; let forcedSkipTime: number = null;
let forcedIncludeIntersectingSegments = false; let forcedIncludeIntersectingSegments = false;
let forcedIncludeNonIntersectingSegments = true; let forcedIncludeNonIntersectingSegments = true;
@@ -529,7 +529,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
* This makes sure the videoID is still correct and if the sponsorTime is included * This makes sure the videoID is still correct and if the sponsorTime is included
*/ */
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean { function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
let currentVideoID = getYouTubeVideoID(document.URL); const currentVideoID = getYouTubeVideoID(document.URL);
if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime && (!sponsorTimes || !sponsorTimes.includes(sponsorTime)) && !sponsorTimesSubmitting.includes(sponsorTime))) { if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime && (!sponsorTimes || !sponsorTimes.includes(sponsorTime)) && !sponsorTimesSubmitting.includes(sponsorTime))) {
// Something has really gone wrong // Something has really gone wrong
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be."); console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
@@ -614,7 +614,7 @@ async function sponsorsLookup(id: string) {
//made true once a setTimeout has been created to try again after a server error //made true once a setTimeout has been created to try again after a server error
let recheckStarted = false; let recheckStarted = false;
// Create categories list // Create categories list
let categories: string[] = []; const categories: string[] = [];
for (const categorySelection of Config.config.categorySelections) { for (const categorySelection of Config.config.categorySelections) {
categories.push(categorySelection.name); categories.push(categorySelection.name);
} }
@@ -649,7 +649,7 @@ async function sponsorsLookup(id: string) {
} }
} }
let recievedSegments: SponsorTime[] = result; const recievedSegments: SponsorTime[] = result;
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;
@@ -713,7 +713,7 @@ function retryFetch(id: string): void {
//check if this video was uploaded recently //check if this video was uploaded recently
utils.wait(() => !!videoInfo).then(() => { utils.wait(() => !!videoInfo).then(() => {
let dateUploaded = videoInfo?.microformat?.playerMicroformatRenderer?.uploadDate; const dateUploaded = videoInfo?.microformat?.playerMicroformatRenderer?.uploadDate;
//if less than 3 days old //if less than 3 days old
if (Date.now() - new Date(dateUploaded).getTime() < 259200000) { if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
@@ -733,7 +733,7 @@ function retryFetch(id: string): void {
function startSkipScheduleCheckingForStartSponsors() { function startSkipScheduleCheckingForStartSponsors() {
if (!switchingVideos) { if (!switchingVideos) {
// See if there are any starting sponsors // See if there are any starting sponsors
let startingSponsor: number = -1; let startingSponsor = -1;
for (const time of sponsorTimes) { for (const time of sponsorTimes) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) { if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) {
startingSponsor = time.segment[0]; startingSponsor = time.segment[0];
@@ -763,7 +763,7 @@ function startSkipScheduleCheckingForStartSponsors() {
function getVideoInfo() { function getVideoInfo() {
sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID, function(xmlhttp, error) { sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1]; const decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
if (!decodedData) { if (!decodedData) {
console.error("[SB] Failed at getting video info from YouTube."); console.error("[SB] Failed at getting video info from YouTube.");
return; return;
@@ -803,7 +803,7 @@ function getYouTubeVideoID(url: string) {
//Get ID from searchParam //Get ID from searchParam
if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) { if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) {
let id = urlObject.searchParams.get("v"); const id = urlObject.searchParams.get("v");
return id.length == 11 ? id : false; return id.length == 11 ? id : false;
} else if (urlObject.pathname.startsWith("/embed/")) { } else if (urlObject.pathname.startsWith("/embed/")) {
try { try {
@@ -836,10 +836,10 @@ function updatePreviewBar() {
let localSponsorTimes = sponsorTimes; let localSponsorTimes = sponsorTimes;
if (localSponsorTimes == null) localSponsorTimes = []; if (localSponsorTimes == null) localSponsorTimes = [];
let allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting); const allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting);
//create an array of the sponsor types //create an array of the sponsor types
let types = []; const types = [];
for (let i = 0; i < localSponsorTimes.length; i++) { for (let i = 0; i < localSponsorTimes.length; i++) {
if (localSponsorTimes[i].hidden === SponsorHideType.Visible) { if (localSponsorTimes[i].hidden === SponsorHideType.Visible) {
types.push(localSponsorTimes[i].category); types.push(localSponsorTimes[i].category);
@@ -872,7 +872,7 @@ function whitelistCheck() {
} }
//see if this is a whitelisted channel //see if this is a whitelisted channel
let whitelistedChannels = Config.config.whitelistedChannels; const whitelistedChannels = Config.config.whitelistedChannels;
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelID)) { if (whitelistedChannels != undefined && whitelistedChannels.includes(channelID)) {
channelWhitelisted = true; channelWhitelisted = true;
@@ -888,17 +888,17 @@ function whitelistCheck() {
function getNextSkipIndex(currentTime: number, includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean): function getNextSkipIndex(currentTime: number, includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean):
{array: SponsorTime[], index: number, endIndex: number, openNotice: boolean} { {array: SponsorTime[], index: number, endIndex: number, openNotice: boolean} {
let sponsorStartTimes = getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments); const sponsorStartTimes = getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments);
let sponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, true, true); const sponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimes, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, true, true);
let minSponsorTimeIndex = sponsorStartTimes.indexOf(Math.min(...sponsorStartTimesAfterCurrentTime)); const minSponsorTimeIndex = sponsorStartTimes.indexOf(Math.min(...sponsorStartTimesAfterCurrentTime));
let endTimeIndex = getLatestEndTimeIndex(sponsorTimes, minSponsorTimeIndex); const endTimeIndex = getLatestEndTimeIndex(sponsorTimes, minSponsorTimeIndex);
let previewSponsorStartTimes = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments); const previewSponsorStartTimes = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments);
let previewSponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, false, false); const previewSponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimesSubmitting, includeIntersectingSegments, includeNonIntersectingSegments, currentTime, false, false);
let minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime)); const minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime));
let previewEndTimeIndex = getLatestEndTimeIndex(sponsorTimesSubmitting, minPreviewSponsorTimeIndex); const previewEndTimeIndex = getLatestEndTimeIndex(sponsorTimesSubmitting, minPreviewSponsorTimeIndex);
if ((minPreviewSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) || if ((minPreviewSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) ||
sponsorStartTimes[minSponsorTimeIndex] < previewSponsorStartTimes[minPreviewSponsorTimeIndex]) { sponsorStartTimes[minSponsorTimeIndex] < previewSponsorStartTimes[minPreviewSponsorTimeIndex]) {
@@ -931,7 +931,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
* @param index Index of the given sponsor * @param index Index of the given sponsor
* @param hideHiddenSponsors * @param hideHiddenSponsors
*/ */
function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideHiddenSponsors: boolean = true): number { function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideHiddenSponsors = true): number {
// Only combine segments for AutoSkip // Only combine segments for AutoSkip
if (index == -1 || if (index == -1 ||
utils.getCategorySelection(sponsorTimes[index].category)?.option !== CategorySkipOption.AutoSkip) return index; utils.getCategorySelection(sponsorTimes[index].category)?.option !== CategorySkipOption.AutoSkip) return index;
@@ -940,8 +940,8 @@ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideH
let latestEndTimeIndex = index; let latestEndTimeIndex = index;
for (let i = 0; i < sponsorTimes?.length; i++) { for (let i = 0; i < sponsorTimes?.length; i++) {
let currentSegment = sponsorTimes[i].segment; const currentSegment = sponsorTimes[i].segment;
let latestEndTime = sponsorTimes[latestEndTimeIndex].segment[1]; const latestEndTime = sponsorTimes[latestEndTimeIndex].segment[1];
if (currentSegment[0] <= latestEndTime && currentSegment[1] > latestEndTime if (currentSegment[0] <= latestEndTime && currentSegment[1] > latestEndTime
&& (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible) && (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible)
@@ -970,10 +970,10 @@ function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideH
* the current time, but end after * the current time, but end after
*/ */
function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean, function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments: boolean, includeNonIntersectingSegments: boolean,
minimum?: number, onlySkippableSponsors: boolean = false, hideHiddenSponsors: boolean = false): number[] { minimum?: number, onlySkippableSponsors = false, hideHiddenSponsors = false): number[] {
if (sponsorTimes === null) return []; if (sponsorTimes === null) return [];
let startTimes: number[] = []; const startTimes: number[] = [];
for (let i = 0; i < sponsorTimes?.length; i++) { for (let i = 0; i < sponsorTimes?.length; i++) {
if ((minimum === undefined if ((minimum === undefined
@@ -1006,7 +1006,7 @@ function previewTime(time: number, unpause = true) {
//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
function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: SponsorTime[], openNotice: boolean) { function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: SponsorTime[], openNotice: boolean) {
// 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; const autoSkip: boolean = utils.getCategorySelection(skippingSegments[0].category)?.option === CategorySkipOption.AutoSkip;
if ((autoSkip || sponsorTimesSubmitting.includes(skippingSegments[0])) && v.currentTime !== skipTime[1]) { if ((autoSkip || sponsorTimesSubmitting.includes(skippingSegments[0])) && v.currentTime !== skipTime[1]) {
// Fix for looped videos not working when skipping to the end #426 // Fix for looped videos not working when skipping to the end #426
@@ -1031,7 +1031,7 @@ function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: S
let isPreviewSegment = false; let isPreviewSegment = false;
for (const segment of skippingSegments) { for (const segment of skippingSegments) {
let index = sponsorTimes.indexOf(segment); const index = sponsorTimes.indexOf(segment);
if (index !== -1 && !sponsorSkipped[index]) { if (index !== -1 && !sponsorSkipped[index]) {
utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID); utils.asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
@@ -1066,7 +1066,7 @@ function createButton(baseID, title, callback, imageName, isDraggable=false): bo
if (document.getElementById(baseID + "Button") != null) return false; if (document.getElementById(baseID + "Button") != null) return false;
// Button HTML // Button HTML
let newButton = document.createElement("button"); const newButton = document.createElement("button");
newButton.draggable = isDraggable; newButton.draggable = isDraggable;
newButton.id = baseID + "Button"; newButton.id = baseID + "Button";
newButton.classList.add("playerButton"); newButton.classList.add("playerButton");
@@ -1077,7 +1077,7 @@ function createButton(baseID, title, callback, imageName, isDraggable=false): bo
}); });
// Image HTML // Image HTML
let newButtonImage = document.createElement("img"); const newButtonImage = document.createElement("img");
newButton.draggable = isDraggable; newButton.draggable = isDraggable;
newButtonImage.id = baseID + "Image"; newButtonImage.id = baseID + "Image";
newButtonImage.className = "playerButtonImage"; newButtonImage.className = "playerButtonImage";
@@ -1093,7 +1093,7 @@ function createButton(baseID, title, callback, imageName, isDraggable=false): bo
} }
function getControls(): HTMLElement | boolean { function getControls(): HTMLElement | boolean {
let controlsSelectors = [ const controlsSelectors = [
// YouTube // YouTube
".ytp-right-controls", ".ytp-right-controls",
// Mobile YouTube // Mobile YouTube
@@ -1103,7 +1103,7 @@ function getControls(): HTMLElement | boolean {
] ]
for (const controlsSelector of controlsSelectors) { for (const controlsSelector of controlsSelectors) {
let controls = document.querySelectorAll(controlsSelector); const controls = document.querySelectorAll(controlsSelector);
if (controls && controls.length > 0) { if (controls && controls.length > 0) {
return <HTMLElement> controls[controls.length - 1]; return <HTMLElement> controls[controls.length - 1];
@@ -1111,13 +1111,13 @@ function getControls(): HTMLElement | boolean {
} }
return false; return false;
}; }
//adds all the player controls buttons //adds all the player controls buttons
async function createButtons(): Promise<boolean> { async function createButtons(): Promise<boolean> {
if (onMobileYouTube) return; if (onMobileYouTube) return;
let result = await utils.wait(getControls).catch(); const result = await utils.wait(getControls).catch();
//set global controls variable //set global controls variable
controls = result; controls = result;
@@ -1138,7 +1138,7 @@ async function updateVisibilityOfPlayerControlsButton(): Promise<boolean> {
//not on a proper video yet //not on a proper video yet
if (!sponsorVideoID) return false; if (!sponsorVideoID) return false;
let createdButtons = await createButtons(); const createdButtons = await createButtons();
if (Config.config.hideVideoPlayerControls || onInvidious) { if (Config.config.hideVideoPlayerControls || onInvidious) {
document.getElementById("startSponsorButton").style.display = "none"; document.getElementById("startSponsorButton").style.display = "none";
@@ -1168,8 +1168,8 @@ async function updateVisibilityOfPlayerControlsButton(): Promise<boolean> {
*/ */
function getRealCurrentTime(): number { function getRealCurrentTime(): number {
// Used to check if replay button // Used to check if replay button
let playButtonSVGData = document.querySelector(".ytp-play-button")?.querySelector(".ytp-svg-fill")?.getAttribute("d"); const playButtonSVGData = document.querySelector(".ytp-play-button")?.querySelector(".ytp-svg-fill")?.getAttribute("d");
let replaceSVGData = "M 18,11 V 7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z"; const replaceSVGData = "M 18,11 V 7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z";
if (playButtonSVGData === replaceSVGData) { if (playButtonSVGData === replaceSVGData) {
// At the end of the video // At the end of the video
@@ -1204,8 +1204,8 @@ function startSponsorClicked() {
updateSponsorTimesSubmitting(false) updateSponsorTimesSubmitting(false)
} }
function updateSponsorTimesSubmitting(getFromConfig: boolean = true) { function updateSponsorTimesSubmitting(getFromConfig = true) {
let segmentTimes = Config.config.segmentTimes.get(sponsorVideoID); const 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 && segmentTimes != undefined) { if (getFromConfig && segmentTimes != undefined) {
@@ -1234,7 +1234,7 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
if(!sponsorVideoID) return false; if(!sponsorVideoID) return false;
//if it isn't visible, there is no data //if it isn't visible, there is no data
let shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none" const shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none"
document.getElementById("deleteButton").style.display = shouldHide; document.getElementById("deleteButton").style.display = shouldHide;
if (showStartSponsor) { if (showStartSponsor) {
@@ -1275,12 +1275,12 @@ function openInfoMenu() {
sendRequestToCustomServer('GET', chrome.extension.getURL("popup.html"), function(xmlhttp) { sendRequestToCustomServer('GET', chrome.extension.getURL("popup.html"), function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var popup = document.createElement("div"); const popup = document.createElement("div");
popup.id = "sponsorBlockPopupContainer"; popup.id = "sponsorBlockPopupContainer";
popup.innerHTML = xmlhttp.responseText popup.innerHTML = xmlhttp.responseText
//close button //close button
let closeButton = document.createElement("div"); const closeButton = document.createElement("div");
closeButton.innerText = chrome.i18n.getMessage("closePopup"); closeButton.innerText = chrome.i18n.getMessage("closePopup");
closeButton.classList.add("smallLink"); closeButton.classList.add("smallLink");
closeButton.setAttribute("align", "center"); closeButton.setAttribute("align", "center");
@@ -1291,7 +1291,7 @@ function openInfoMenu() {
//add the close button //add the close button
popup.prepend(closeButton); popup.prepend(closeButton);
let parentNodes = document.querySelectorAll("#secondary"); const parentNodes = document.querySelectorAll("#secondary");
let parentNode = null; let parentNode = null;
for (let i = 0; i < parentNodes.length; i++) { for (let i = 0; i < parentNodes.length; i++) {
if (parentNodes[i].firstElementChild !== null) { if (parentNodes[i].firstElementChild !== null) {
@@ -1306,7 +1306,7 @@ function openInfoMenu() {
//make the logo source not 404 //make the logo source not 404
//query selector must be used since getElementByID doesn't work on a node and this isn't added to the document yet //query selector must be used since getElementByID doesn't work on a node and this isn't added to the document yet
let logo = <HTMLImageElement> popup.querySelector("#sponsorBlockPopupLogo"); const logo = <HTMLImageElement> popup.querySelector("#sponsorBlockPopupLogo");
logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png"); logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png");
//remove the style sheet and font that are not necessary //remove the style sheet and font that are not necessary
@@ -1322,7 +1322,7 @@ function openInfoMenu() {
} }
function closeInfoMenu() { function closeInfoMenu() {
let popup = document.getElementById("sponsorBlockPopupContainer"); const popup = document.getElementById("sponsorBlockPopupContainer");
if (popup != null) { if (popup != null) {
popup.remove(); popup.remove();
@@ -1337,12 +1337,12 @@ function clearSponsorTimes() {
//it can't update to this info yet //it can't update to this info yet
closeInfoMenu(); closeInfoMenu();
let currentVideoID = sponsorVideoID; const currentVideoID = sponsorVideoID;
let sponsorTimes = Config.config.segmentTimes.get(currentVideoID); const 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) const confirmMessage = chrome.i18n.getMessage("clearThis") + getSegmentsMessage(sponsorTimes)
+ "\n" + chrome.i18n.getMessage("confirmMSG") + "\n" + chrome.i18n.getMessage("confirmMSG")
if(!confirm(confirmMessage)) return; if(!confirm(confirmMessage)) return;
@@ -1367,7 +1367,7 @@ function vote(type: number, UUID: string, category?: string, skipNotice?: SkipNo
skipNotice.setNoticeInfoMessage.bind(skipNotice)(); skipNotice.setNoticeInfoMessage.bind(skipNotice)();
} }
let sponsorIndex = utils.getSponsorIndexFromUUID(sponsorTimes, UUID); const sponsorIndex = utils.getSponsorIndexFromUUID(sponsorTimes, UUID);
// Don't vote for preview sponsors // Don't vote for preview sponsors
if (sponsorIndex == -1 || sponsorTimes[sponsorIndex].UUID === null) return; if (sponsorIndex == -1 || sponsorTimes[sponsorIndex].UUID === null) return;
@@ -1410,7 +1410,7 @@ function vote(type: number, UUID: string, category?: string, skipNotice?: SkipNo
//Closes all notices that tell the user that a sponsor was just skipped //Closes all notices that tell the user that a sponsor was just skipped
function closeAllSkipNotices(){ function closeAllSkipNotices(){
let notices = document.getElementsByClassName("sponsorSkipNotice"); const notices = document.getElementsByClassName("sponsorSkipNotice");
for (let i = 0; i < notices.length; i++) { for (let i = 0; i < notices.length; i++) {
notices[i].remove(); notices[i].remove();
} }
@@ -1446,7 +1446,7 @@ function submitSponsorTimes() {
//it can't update to this info yet //it can't update to this info yet
closeInfoMenu(); closeInfoMenu();
let currentVideoID = sponsorVideoID; const currentVideoID = sponsorVideoID;
if (sponsorTimesSubmitting !== undefined && sponsorTimesSubmitting.length > 0) { if (sponsorTimesSubmitting !== undefined && sponsorTimesSubmitting.length > 0) {
submissionNotice = new SubmissionNotice(skipNoticeContentContainer, sendSubmitMessage); submissionNotice = new SubmissionNotice(skipNoticeContentContainer, sendSubmitMessage);
@@ -1475,7 +1475,7 @@ async function sendSubmitMessage(){
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" + const confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" +
getSegmentsMessage(sponsorTimesSubmitting); getSegmentsMessage(sponsorTimesSubmitting);
if(!confirm(confirmShort)) return; if(!confirm(confirmShort)) return;
@@ -1483,7 +1483,7 @@ async function sendSubmitMessage(){
} }
} }
let response = await utils.asyncRequestToServer("POST", "/api/skipSegments", { const response = await utils.asyncRequestToServer("POST", "/api/skipSegments", {
videoID: sponsorVideoID, videoID: sponsorVideoID,
userID: Config.config.userID, userID: Config.config.userID,
segments: sponsorTimesSubmitting segments: sponsorTimesSubmitting
@@ -1491,11 +1491,11 @@ async function sendSubmitMessage(){
if (response.status === 200) { if (response.status === 200) {
//hide loading message //hide loading message
let submitButton = document.getElementById("submitButton"); const submitButton = document.getElementById("submitButton");
submitButton.style.animation = "rotate 1s"; submitButton.style.animation = "rotate 1s";
//finish this animation //finish this animation
//when the animation is over, hide the button //when the animation is over, hide the button
let animationEndListener = function() { const animationEndListener = function() {
changeStartSponsorButton(true, false); changeStartSponsorButton(true, false);
submitButton.style.animation = "none"; submitButton.style.animation = "none";
@@ -1569,10 +1569,10 @@ function isUnlisted(): boolean {
function addCSS() { function addCSS() {
if (!utils.isFirefox() && Config.config.invidiousInstances.includes(new URL(document.URL).host)) { if (!utils.isFirefox() && Config.config.invidiousInstances.includes(new URL(document.URL).host)) {
window.addEventListener("DOMContentLoaded", () => { window.addEventListener("DOMContentLoaded", () => {
let head = document.getElementsByTagName("head")[0]; const head = document.getElementsByTagName("head")[0];
for (const file of utils.css) { for (const file of utils.css) {
let fileref = document.createElement("link"); const fileref = document.createElement("link");
fileref.rel = "stylesheet"; fileref.rel = "stylesheet";
fileref.type = "text/css"; fileref.type = "text/css";
@@ -1585,7 +1585,7 @@ function addCSS() {
} }
function sendRequestToCustomServer(type, fullAddress, callback) { function sendRequestToCustomServer(type, fullAddress, callback) {
let xmlhttp = new XMLHttpRequest(); const xmlhttp = new XMLHttpRequest();
xmlhttp.open(type, fullAddress, true); xmlhttp.open(type, fullAddress, true);
@@ -1607,7 +1607,7 @@ function sendRequestToCustomServer(type, fullAddress, callback) {
* Update the isAdPlaying flag and hide preview bar/controls if ad is playing * Update the isAdPlaying flag and hide preview bar/controls if ad is playing
*/ */
function updateAdFlag() { function updateAdFlag() {
let wasAdPlaying = isAdPlaying; const wasAdPlaying = isAdPlaying;
isAdPlaying = document.getElementsByClassName('ad-showing').length > 0; isAdPlaying = document.getElementsByClassName('ad-showing').length > 0;
if(wasAdPlaying != isAdPlaying) { if(wasAdPlaying != isAdPlaying) {
@@ -1631,10 +1631,10 @@ function showTimeWithoutSkips(allSponsorTimes): void {
} }
// YouTube player time display // YouTube player time display
let display = document.getElementsByClassName("ytp-time-display notranslate")[0]; const display = document.getElementsByClassName("ytp-time-display notranslate")[0];
if (!display) return; if (!display) return;
let formatedTime = utils.getFormattedTime(video.duration - skipDuration); const formatedTime = utils.getFormattedTime(video.duration - skipDuration);
const durationID = "sponsorBlockDurationAfterSkips"; const durationID = "sponsorBlockDurationAfterSkips";
let duration = document.getElementById(durationID); let duration = document.getElementById(durationID);

View File

@@ -7,7 +7,7 @@
import Config from "../config"; import Config from "../config";
import Utils from "../utils"; import Utils from "../utils";
let utils = new Utils(); const utils = new Utils();
class PreviewBar { class PreviewBar {
container: HTMLUListElement; container: HTMLUListElement;
@@ -34,12 +34,12 @@ class PreviewBar {
setupHoverText() { setupHoverText() {
if (this.onMobileYouTube || this.onInvidious) return; if (this.onMobileYouTube || this.onInvidious) return;
let seekBar = document.querySelector(".ytp-progress-bar-container"); const seekBar = document.querySelector(".ytp-progress-bar-container");
// Create label placeholder // Create label placeholder
let tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper"); const tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper");
let titleTooltip = document.querySelector(".ytp-tooltip-title"); const titleTooltip = document.querySelector(".ytp-tooltip-title");
let categoryTooltip = document.createElement("div"); const categoryTooltip = document.createElement("div");
categoryTooltip.className = "sbHidden ytp-tooltip-title"; categoryTooltip.className = "sbHidden ytp-tooltip-title";
categoryTooltip.id = "sponsor-block-category-tooltip" categoryTooltip.id = "sponsor-block-category-tooltip"
@@ -64,12 +64,12 @@ class PreviewBar {
return; return;
} }
let tooltips = document.querySelectorAll(".ytp-tooltip-text"); const tooltips = document.querySelectorAll(".ytp-tooltip-text");
for (const tooltip of tooltips) { for (const tooltip of tooltips) {
let splitData = tooltip.textContent.split(":"); const splitData = tooltip.textContent.split(":");
if (splitData.length === 2 && !isNaN(parseInt(splitData[0])) && !isNaN(parseInt(splitData[1]))) { if (splitData.length === 2 && !isNaN(parseInt(splitData[0])) && !isNaN(parseInt(splitData[1]))) {
// Add label // Add label
let timeInSeconds = parseInt(splitData[0]) * 60 + parseInt(splitData[1]); const timeInSeconds = parseInt(splitData[0]) * 60 + parseInt(splitData[1]);
// Find category at that location // Find category at that location
let category = null; let category = null;
@@ -130,8 +130,8 @@ class PreviewBar {
} }
updateColor(segment, color, opacity) { updateColor(segment, color, opacity) {
let bars = <NodeListOf<HTMLElement>> document.querySelectorAll('[data-vs-segment-type=' + segment + ']'); const bars = <NodeListOf<HTMLElement>> document.querySelectorAll('[data-vs-segment-type=' + segment + ']');
for (let bar of bars) { for (const bar of bars) {
bar.style.backgroundColor = color; bar.style.backgroundColor = color;
bar.style.opacity = opacity; bar.style.opacity = opacity;
} }
@@ -158,7 +158,7 @@ class PreviewBar {
width = (timestamps[i][1] - timestamps[i][0]) / duration * 100; width = (timestamps[i][1] - timestamps[i][0]) / duration * 100;
width = Math.floor(width * 100) / 100; width = Math.floor(width * 100) / 100;
let bar = this.createBar(); const bar = this.createBar();
bar.setAttribute('data-vs-segment-type', types[i]); bar.setAttribute('data-vs-segment-type', types[i]);
bar.style.backgroundColor = Config.config.barTypes[types[i]].color; bar.style.backgroundColor = Config.config.barTypes[types[i]].color;
@@ -172,7 +172,7 @@ class PreviewBar {
} }
createBar() { createBar() {
let bar = document.createElement('li'); const bar = document.createElement('li');
bar.classList.add('previewbar'); bar.classList.add('previewbar');
bar.innerHTML = '&nbsp;'; bar.innerHTML = '&nbsp;';
return bar; return bar;

View File

@@ -6,7 +6,7 @@ import * as CompileConfig from "../config.json";
import Utils from "./utils"; import Utils from "./utils";
import CategoryChooser from "./render/CategoryChooser"; import CategoryChooser from "./render/CategoryChooser";
var utils = new Utils(); const utils = new Utils();
window.addEventListener('DOMContentLoaded', init); window.addEventListener('DOMContentLoaded', init);
@@ -27,19 +27,19 @@ async function init() {
await utils.wait(() => Config.config !== null); await utils.wait(() => Config.config !== null);
// Set all of the toggle options to the correct option // Set all of the toggle options to the correct option
let optionsContainer = document.getElementById("options"); const optionsContainer = document.getElementById("options");
let optionsElements = optionsContainer.querySelectorAll("*"); const optionsElements = optionsContainer.querySelectorAll("*");
for (let i = 0; i < optionsElements.length; i++) { for (let i = 0; i < optionsElements.length; i++) {
switch (optionsElements[i].getAttribute("option-type")) { switch (optionsElements[i].getAttribute("option-type")) {
case "toggle": case "toggle":
let option = optionsElements[i].getAttribute("sync-option"); const option = optionsElements[i].getAttribute("sync-option");
let optionResult = Config.config[option]; const optionResult = Config.config[option];
let checkbox = optionsElements[i].querySelector("input"); const checkbox = optionsElements[i].querySelector("input");
let reverse = optionsElements[i].getAttribute("toggle-type") === "reverse"; const reverse = optionsElements[i].getAttribute("toggle-type") === "reverse";
let confirmMessage = optionsElements[i].getAttribute("confirm-message"); const confirmMessage = optionsElements[i].getAttribute("confirm-message");
if (optionResult != undefined) { if (optionResult != undefined) {
checkbox.checked = optionResult; checkbox.checked = optionResult;
@@ -76,7 +76,7 @@ async function init() {
// Enable the notice // Enable the notice
Config.config["dontShowNotice"] = false; Config.config["dontShowNotice"] = false;
let showNoticeSwitch = <HTMLInputElement> document.querySelector("[sync-option='dontShowNotice'] > label > label > input"); const showNoticeSwitch = <HTMLInputElement> document.querySelector("[sync-option='dontShowNotice'] > label > label > input");
showNoticeSwitch.checked = true; showNoticeSwitch.checked = true;
} }
@@ -85,10 +85,10 @@ async function init() {
}); });
break; break;
case "text-change": case "text-change":
let textChangeOption = optionsElements[i].getAttribute("sync-option"); const textChangeOption = optionsElements[i].getAttribute("sync-option");
let textChangeInput = <HTMLInputElement> optionsElements[i].querySelector(".option-text-box"); const textChangeInput = <HTMLInputElement> optionsElements[i].querySelector(".option-text-box");
let textChangeSetButton = <HTMLElement> optionsElements[i].querySelector(".text-change-set"); const textChangeSetButton = <HTMLElement> optionsElements[i].querySelector(".text-change-set");
textChangeInput.value = Config.config[textChangeOption]; textChangeInput.value = Config.config[textChangeOption];
@@ -96,7 +96,7 @@ async function init() {
// See if anything extra must be done // See if anything extra must be done
switch (textChangeOption) { switch (textChangeOption) {
case "serverAddress": case "serverAddress":
let result = validateServerAddress(textChangeInput.value); const result = validateServerAddress(textChangeInput.value);
if (result !== null) { if (result !== null) {
textChangeInput.value = result; textChangeInput.value = result;
@@ -106,7 +106,7 @@ async function init() {
// Permission needed on Firefox // Permission needed on Firefox
if (utils.isFirefox()) { if (utils.isFirefox()) {
let permissionSuccess = await new Promise((resolve, reject) => { const permissionSuccess = await new Promise((resolve, reject) => {
chrome.permissions.request({ chrome.permissions.request({
origins: [textChangeInput.value + "/"], origins: [textChangeInput.value + "/"],
permissions: [] permissions: []
@@ -123,7 +123,7 @@ async function init() {
}); });
// Reset to the default if needed // Reset to the default if needed
let textChangeResetButton = <HTMLElement> optionsElements[i].querySelector(".text-change-reset"); const textChangeResetButton = <HTMLElement> optionsElements[i].querySelector(".text-change-reset");
textChangeResetButton.addEventListener("click", () => { textChangeResetButton.addEventListener("click", () => {
if (!confirm(chrome.i18n.getMessage("areYouSureReset"))) return; if (!confirm(chrome.i18n.getMessage("areYouSureReset"))) return;
@@ -134,10 +134,10 @@ async function init() {
break; break;
case "private-text-change": case "private-text-change":
let button = optionsElements[i].querySelector(".trigger-button"); const button = optionsElements[i].querySelector(".trigger-button");
button.addEventListener("click", () => activatePrivateTextChange(<HTMLElement> optionsElements[i])); button.addEventListener("click", () => activatePrivateTextChange(<HTMLElement> optionsElements[i]));
let privateTextChangeOption = optionsElements[i].getAttribute("sync-option"); const privateTextChangeOption = optionsElements[i].getAttribute("sync-option");
// See if anything extra must be done // See if anything extra must be done
switch (privateTextChangeOption) { switch (privateTextChangeOption) {
case "invidiousInstances": case "invidiousInstances":
@@ -146,7 +146,7 @@ async function init() {
break; break;
case "button-press": case "button-press":
let actionButton = optionsElements[i].querySelector(".trigger-button"); const actionButton = optionsElements[i].querySelector(".trigger-button");
switch(optionsElements[i].getAttribute("sync-option")) { switch(optionsElements[i].getAttribute("sync-option")) {
case "copyDebugInformation": case "copyDebugInformation":
@@ -156,7 +156,7 @@ async function init() {
break; break;
case "keybind-change": case "keybind-change":
let keybindButton = optionsElements[i].querySelector(".trigger-button"); const keybindButton = optionsElements[i].querySelector(".trigger-button");
keybindButton.addEventListener("click", () => activateKeybindChange(<HTMLElement> optionsElements[i])); keybindButton.addEventListener("click", () => activateKeybindChange(<HTMLElement> optionsElements[i]));
break; break;
@@ -165,9 +165,9 @@ async function init() {
break; break;
case "number-change": case "number-change":
let numberChangeOption = optionsElements[i].getAttribute("sync-option"); const numberChangeOption = optionsElements[i].getAttribute("sync-option");
let configValue = Config.config[numberChangeOption]; const configValue = Config.config[numberChangeOption];
let numberInput = optionsElements[i].querySelector("input"); const numberInput = optionsElements[i].querySelector("input");
if (isNaN(configValue) || configValue < 0) { if (isNaN(configValue) || configValue < 0) {
numberInput.value = Config.defaults[numberChangeOption]; numberInput.value = Config.defaults[numberChangeOption];
@@ -196,8 +196,8 @@ async function init() {
* @param {String} element * @param {String} element
*/ */
function optionsConfigUpdateListener(changes) { function optionsConfigUpdateListener(changes) {
let optionsContainer = document.getElementById("options"); const optionsContainer = document.getElementById("options");
let optionsElements = optionsContainer.querySelectorAll("*"); const optionsElements = optionsContainer.querySelectorAll("*");
for (let i = 0; i < optionsElements.length; i++) { for (let i = 0; i < optionsElements.length; i++) {
switch (optionsElements[i].getAttribute("option-type")) { switch (optionsElements[i].getAttribute("option-type")) {
@@ -213,8 +213,8 @@ function optionsConfigUpdateListener(changes) {
* @param element * @param element
*/ */
function updateDisplayElement(element: HTMLElement) { function updateDisplayElement(element: HTMLElement) {
let displayOption = element.getAttribute("sync-option") const displayOption = element.getAttribute("sync-option")
let displayText = Config.config[displayOption]; const displayText = Config.config[displayOption];
element.innerText = displayText; element.innerText = displayText;
// See if anything extra must be run // See if anything extra must be run
@@ -232,10 +232,10 @@ function updateDisplayElement(element: HTMLElement) {
* @param option * @param option
*/ */
function invidiousInstanceAddInit(element: HTMLElement, option: string) { function invidiousInstanceAddInit(element: HTMLElement, option: string) {
let textBox = <HTMLInputElement> element.querySelector(".option-text-box"); const textBox = <HTMLInputElement> element.querySelector(".option-text-box");
let button = element.querySelector(".trigger-button"); const button = element.querySelector(".trigger-button");
let setButton = element.querySelector(".text-change-set"); const 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")) { if (textBox.value == "" || textBox.value.includes("/") || textBox.value.includes("http")) {
alert(chrome.i18n.getMessage("addInvidiousInstanceError")); alert(chrome.i18n.getMessage("addInvidiousInstanceError"));
@@ -248,7 +248,7 @@ function invidiousInstanceAddInit(element: HTMLElement, option: string) {
Config.config[option] = instanceList; Config.config[option] = instanceList;
let checkbox = <HTMLInputElement> document.querySelector("#support-invidious input"); const checkbox = <HTMLInputElement> document.querySelector("#support-invidious input");
checkbox.checked = true; checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious"); invidiousOnClick(checkbox, "supportInvidious");
@@ -261,7 +261,7 @@ function invidiousInstanceAddInit(element: HTMLElement, option: string) {
} }
}); });
let resetButton = element.querySelector(".invidious-instance-reset"); const resetButton = element.querySelector(".invidious-instance-reset");
resetButton.addEventListener("click", function(e) { resetButton.addEventListener("click", function(e) {
if (confirm(chrome.i18n.getMessage("resetInvidiousInstanceAlert"))) { if (confirm(chrome.i18n.getMessage("resetInvidiousInstanceAlert"))) {
// Set to a clone of the default // Set to a clone of the default
@@ -323,20 +323,20 @@ async function invidiousOnClick(checkbox: HTMLInputElement, option: string) {
* @param element * @param element
*/ */
function activateKeybindChange(element: HTMLElement) { function activateKeybindChange(element: HTMLElement) {
let button = element.querySelector(".trigger-button"); const button = element.querySelector(".trigger-button");
if (button.classList.contains("disabled")) return; if (button.classList.contains("disabled")) return;
button.classList.add("disabled"); button.classList.add("disabled");
let option = element.getAttribute("sync-option"); const option = element.getAttribute("sync-option");
let currentlySet = Config.config[option] !== null ? chrome.i18n.getMessage("keybindCurrentlySet") : ""; const currentlySet = Config.config[option] !== null ? chrome.i18n.getMessage("keybindCurrentlySet") : "";
let status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status"); const status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescription") + currentlySet; status.innerText = chrome.i18n.getMessage("keybindDescription") + currentlySet;
if (Config.config[option] !== null) { if (Config.config[option] !== null) {
let statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key"); const statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = Config.config[option]; statusKey.innerText = Config.config[option];
} }
@@ -352,19 +352,19 @@ function activateKeybindChange(element: HTMLElement) {
* @param e * @param e
*/ */
function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) { function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) {
var key = e.key; const key = e.key;
if (["Shift", "Control", "Meta", "Alt", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Tab"].indexOf(key) !== -1) { if (["Shift", "Control", "Meta", "Alt", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Tab"].indexOf(key) !== -1) {
// Wait for more // Wait for more
document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true}); document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true});
} else { } else {
let button: HTMLElement = element.querySelector(".trigger-button"); const button: HTMLElement = element.querySelector(".trigger-button");
let option = element.getAttribute("sync-option"); const option = element.getAttribute("sync-option");
// 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']; const otherKeybind = (option === "startSponsorKeybind") ? Config.config['submitKeybind'] : Config.config['startSponsorKeybind'];
if (key === otherKeybind) { if (key === otherKeybind) {
closeKeybindOption(element, button); closeKeybindOption(element, button);
@@ -381,10 +381,10 @@ function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) {
Config.config[option] = key; Config.config[option] = key;
let status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status"); const status = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete"); status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete");
let statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key"); const statusKey = <HTMLElement> element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = key; statusKey.innerText = key;
button.classList.remove("disabled"); button.classList.remove("disabled");
@@ -408,13 +408,13 @@ function closeKeybindOption(element: HTMLElement, button: HTMLElement) {
* @param element * @param element
*/ */
function activatePrivateTextChange(element: HTMLElement) { function activatePrivateTextChange(element: HTMLElement) {
let button = element.querySelector(".trigger-button"); const button = element.querySelector(".trigger-button");
if (button.classList.contains("disabled")) return; if (button.classList.contains("disabled")) return;
button.classList.add("disabled"); button.classList.add("disabled");
let textBox = <HTMLInputElement> element.querySelector(".option-text-box"); const textBox = <HTMLInputElement> element.querySelector(".option-text-box");
let option = element.getAttribute("sync-option"); const option = element.getAttribute("sync-option");
// See if anything extra must be done // See if anything extra must be done
switch (option) { switch (option) {
@@ -428,7 +428,7 @@ function activatePrivateTextChange(element: HTMLElement) {
// See if anything extra must be done // See if anything extra must be done
switch (option) { switch (option) {
case "*": case "*":
let jsonData = JSON.parse(JSON.stringify(Config.localConfig)); const jsonData = JSON.parse(JSON.stringify(Config.localConfig));
// Fix segmentTimes data as it is destroyed from the JSON stringify // Fix segmentTimes data as it is destroyed from the JSON stringify
jsonData.segmentTimes = Config.encodeStoredItem(Config.localConfig.segmentTimes); jsonData.segmentTimes = Config.encodeStoredItem(Config.localConfig.segmentTimes);
@@ -439,9 +439,9 @@ function activatePrivateTextChange(element: HTMLElement) {
textBox.value = result; textBox.value = result;
let setButton = element.querySelector(".text-change-set"); const setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async () => { setButton.addEventListener("click", async () => {
let confirmMessage = element.getAttribute("confirm-message"); const confirmMessage = element.getAttribute("confirm-message");
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) { if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
@@ -449,14 +449,14 @@ function activatePrivateTextChange(element: HTMLElement) {
switch (option) { switch (option) {
case "*": case "*":
try { try {
let newConfig = JSON.parse(textBox.value); const newConfig = JSON.parse(textBox.value);
for (const key in newConfig) { for (const key in newConfig) {
Config.config[key] = newConfig[key]; Config.config[key] = newConfig[key];
} }
Config.convertJSON(); Config.convertJSON();
if (newConfig.supportInvidious) { if (newConfig.supportInvidious) {
let checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input"); const checkbox = <HTMLInputElement> document.querySelector("#support-invidious > label > label > input");
checkbox.checked = true; checkbox.checked = true;
await invidiousOnClick(checkbox, "supportInvidious"); await invidiousOnClick(checkbox, "supportInvidious");
@@ -503,7 +503,7 @@ function validateServerAddress(input: string): string {
function copyDebugOutputToClipboard() { function copyDebugOutputToClipboard() {
// Build output debug information object // Build output debug information object
let output = { const output = {
debug: { debug: {
userAgent: navigator.userAgent, userAgent: navigator.userAgent,
platform: navigator.platform, platform: navigator.platform,
@@ -530,5 +530,5 @@ function copyDebugOutputToClipboard() {
}) })
.catch(err => { .catch(err => {
alert(chrome.i18n.getMessage("copyDebugInformationFailed")); alert(chrome.i18n.getMessage("copyDebugInformationFailed"));
});; });
} }

View File

@@ -2,7 +2,7 @@ import Config from "./config";
import Utils from "./utils"; import Utils from "./utils";
import { SponsorTime, SponsorHideType } from "./types"; import { SponsorTime, SponsorHideType } from "./types";
var utils = new Utils(); const utils = new Utils();
interface MessageListener { interface MessageListener {
(request: any, sender: any, callback: (response: any) => void): void; (request: any, sender: any, callback: (response: any) => void): void;
@@ -39,13 +39,13 @@ class MessageHandler {
//make this a function to allow this to run on the content page //make this a function to allow this to run on the content page
async function runThePopup(messageListener?: MessageListener) { async function runThePopup(messageListener?: MessageListener) {
var messageHandler = new MessageHandler(messageListener); const messageHandler = new MessageHandler(messageListener);
utils.localizeHtmlPage(); utils.localizeHtmlPage();
await utils.wait(() => Config.config !== null); await utils.wait(() => Config.config !== null);
var PageElements: any = {}; const PageElements: any = {};
["sponsorStart", ["sponsorStart",
// Top toggles // Top toggles
@@ -125,7 +125,7 @@ async function runThePopup(messageListener?: MessageListener) {
let currentVideoID = null; let currentVideoID = null;
//see if discord link can be shown //see if discord link can be shown
let hideDiscordLink = Config.config.hideDiscordLink; const hideDiscordLink = Config.config.hideDiscordLink;
if (hideDiscordLink == undefined || !hideDiscordLink) { if (hideDiscordLink == undefined || !hideDiscordLink) {
let hideDiscordLaunches = Config.config.hideDiscordLaunches; let hideDiscordLaunches = Config.config.hideDiscordLaunches;
//only if less than 10 launches //only if less than 10 launches
@@ -140,7 +140,7 @@ async function runThePopup(messageListener?: MessageListener) {
} }
//show proper disable skipping button //show proper disable skipping button
let disableSkipping = Config.config.disableSkipping; const disableSkipping = Config.config.disableSkipping;
if (disableSkipping != undefined && disableSkipping) { if (disableSkipping != undefined && disableSkipping) {
PageElements.disableSkipping.style.display = "none"; PageElements.disableSkipping.style.display = "none";
PageElements.enableSkipping.style.display = "unset"; PageElements.enableSkipping.style.display = "unset";
@@ -148,7 +148,7 @@ async function runThePopup(messageListener?: MessageListener) {
//if the don't show notice again variable is true, an option to //if the don't show notice again variable is true, an option to
// disable should be available // disable should be available
let dontShowNotice = Config.config.dontShowNotice; const dontShowNotice = Config.config.dontShowNotice;
if (dontShowNotice != undefined && dontShowNotice) { if (dontShowNotice != undefined && dontShowNotice) {
PageElements.showNoticeAgain.style.display = "unset"; PageElements.showNoticeAgain.style.display = "unset";
} }
@@ -164,13 +164,13 @@ async function runThePopup(messageListener?: MessageListener) {
PageElements.sponsorTimesContributionsContainer.style.display = "unset"; PageElements.sponsorTimesContributionsContainer.style.display = "unset";
//get the userID //get the userID
let userID = Config.config.userID; const userID = Config.config.userID;
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(response) { utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(response) {
if (response.status == 200) { if (response.status == 200) {
let viewCount = JSON.parse(response.responseText).viewCount; const 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");
@@ -187,7 +187,7 @@ async function runThePopup(messageListener?: MessageListener) {
//get this time in minutes //get this time in minutes
utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(response) { utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(response) {
if (response.status == 200) { if (response.status == 200) {
let minutesSaved = JSON.parse(response.responseText).timeSaved; const 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");
@@ -252,7 +252,7 @@ async function runThePopup(messageListener?: MessageListener) {
} }
//load video times for this video //load video times for this video
let sponsorTimesStorage = Config.config.segmentTimes.get(currentVideoID); const 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].segment.length < 2) { if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].segment.length < 2) {
startTimeChosen = true; startTimeChosen = true;
@@ -333,7 +333,7 @@ async function runThePopup(messageListener?: MessageListener) {
} }
function startSponsorCallback(response) { function startSponsorCallback(response) {
let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); const sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0);
if (sponsorTimes[sponsorTimesIndex] == undefined) { if (sponsorTimes[sponsorTimesIndex] == undefined) {
sponsorTimes[sponsorTimesIndex] = { sponsorTimes[sponsorTimesIndex] = {
@@ -345,7 +345,7 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimes[sponsorTimesIndex].segment[startTimeChosen ? 1 : 0] = response.time; sponsorTimes[sponsorTimesIndex].segment[startTimeChosen ? 1 : 0] = response.time;
let localStartTimeChosen = startTimeChosen; const localStartTimeChosen = startTimeChosen;
Config.config.segmentTimes.set(currentVideoID, sponsorTimes); Config.config.segmentTimes.set(currentVideoID, sponsorTimes);
//send a message to the client script //send a message to the client script
@@ -378,9 +378,9 @@ async function runThePopup(messageListener?: MessageListener) {
} }
//add them as buttons to the issue reporting container //add them as buttons to the issue reporting container
let container = document.getElementById("issueReporterTimeButtons"); const container = document.getElementById("issueReporterTimeButtons");
for (let i = 0; i < request.sponsorTimes.length; i++) { for (let i = 0; i < request.sponsorTimes.length; i++) {
let sponsorTimeButton = document.createElement("button"); const sponsorTimeButton = document.createElement("button");
sponsorTimeButton.className = "warningButton popupElement"; sponsorTimeButton.className = "warningButton popupElement";
let extraInfo = ""; let extraInfo = "";
@@ -394,23 +394,23 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i].segment[0]) + " " + chrome.i18n.getMessage("to") + " " + getFormattedTime(request.sponsorTimes[i].segment[1]) + extraInfo; sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i].segment[0]) + " " + chrome.i18n.getMessage("to") + " " + getFormattedTime(request.sponsorTimes[i].segment[1]) + extraInfo;
let votingButtons = document.createElement("div"); const votingButtons = document.createElement("div");
let UUID = request.sponsorTimes[i].UUID; const UUID = request.sponsorTimes[i].UUID;
//thumbs up and down buttons //thumbs up and down buttons
let voteButtonsContainer = document.createElement("div"); const voteButtonsContainer = document.createElement("div");
voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID; voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID;
voteButtonsContainer.setAttribute("align", "center"); voteButtonsContainer.setAttribute("align", "center");
voteButtonsContainer.style.display = "none" voteButtonsContainer.style.display = "none"
let upvoteButton = document.createElement("img"); const upvoteButton = document.createElement("img");
upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID; upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID;
upvoteButton.className = "voteButton popupElement"; upvoteButton.className = "voteButton popupElement";
upvoteButton.src = chrome.extension.getURL("icons/upvote.png"); upvoteButton.src = chrome.extension.getURL("icons/upvote.png");
upvoteButton.addEventListener("click", () => vote(1, UUID)); upvoteButton.addEventListener("click", () => vote(1, UUID));
let downvoteButton = document.createElement("img"); const downvoteButton = document.createElement("img");
downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID; downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID;
downvoteButton.className = "voteButton popupElement"; downvoteButton.className = "voteButton popupElement";
downvoteButton.src = chrome.extension.getURL("icons/downvote.png"); downvoteButton.src = chrome.extension.getURL("icons/downvote.png");
@@ -473,29 +473,29 @@ async function runThePopup(messageListener?: MessageListener) {
//this version is a div that contains each with delete buttons //this version is a div that contains each with delete buttons
function getSponsorTimesMessageDiv(sponsorTimes) { function getSponsorTimesMessageDiv(sponsorTimes) {
// let sponsorTimesMessage = ""; // let sponsorTimesMessage = "";
let sponsorTimesContainer = document.createElement("div"); const sponsorTimesContainer = document.createElement("div");
sponsorTimesContainer.id = "sponsorTimesContainer"; sponsorTimesContainer.id = "sponsorTimesContainer";
for (let i = 0; i < sponsorTimes.length; i++) { for (let i = 0; i < sponsorTimes.length; i++) {
let currentSponsorTimeContainer = document.createElement("div"); const currentSponsorTimeContainer = document.createElement("div");
currentSponsorTimeContainer.id = "sponsorTimeContainer" + i; currentSponsorTimeContainer.id = "sponsorTimeContainer" + i;
currentSponsorTimeContainer.className = "sponsorTime popupElement"; currentSponsorTimeContainer.className = "sponsorTime popupElement";
let currentSponsorTimeMessage = ""; let currentSponsorTimeMessage = "";
let deleteButton = document.createElement("span"); const deleteButton = document.createElement("span");
deleteButton.id = "sponsorTimeDeleteButton" + i; deleteButton.id = "sponsorTimeDeleteButton" + i;
deleteButton.innerText = "Delete"; deleteButton.innerText = "Delete";
deleteButton.className = "mediumLink popupElement"; deleteButton.className = "mediumLink popupElement";
let index = i; const index = i;
deleteButton.addEventListener("click", () => deleteSponsorTime(index)); deleteButton.addEventListener("click", () => deleteSponsorTime(index));
let previewButton = document.createElement("span"); const previewButton = document.createElement("span");
previewButton.id = "sponsorTimePreviewButton" + i; previewButton.id = "sponsorTimePreviewButton" + i;
previewButton.innerText = "Preview"; previewButton.innerText = "Preview";
previewButton.className = "mediumLink popupElement"; previewButton.className = "mediumLink popupElement";
previewButton.addEventListener("click", () => previewSponsorTime(index)); previewButton.addEventListener("click", () => previewSponsorTime(index));
let editButton = document.createElement("span"); const editButton = document.createElement("span");
editButton.id = "sponsorTimeEditButton" + i; editButton.id = "sponsorTimeEditButton" + i;
editButton.innerText = "Edit"; editButton.innerText = "Edit";
editButton.className = "mediumLink popupElement"; editButton.className = "mediumLink popupElement";
@@ -565,38 +565,38 @@ async function runThePopup(messageListener?: MessageListener) {
//hide submit button //hide submit button
document.getElementById("submitTimesContainer").style.display = "none"; document.getElementById("submitTimesContainer").style.display = "none";
let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index); const sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index);
//the button to set the current time //the button to set the current time
let startTimeNowButton = document.createElement("span"); const startTimeNowButton = document.createElement("span");
startTimeNowButton.id = "startTimeNowButton" + index; startTimeNowButton.id = "startTimeNowButton" + index;
startTimeNowButton.innerText = "(Now)"; startTimeNowButton.innerText = "(Now)";
startTimeNowButton.className = "tinyLink popupElement"; startTimeNowButton.className = "tinyLink popupElement";
startTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("startTime", index)); 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"); const startTimeMinutes = document.createElement("input");
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].segment[0])); startTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index].segment[0]));
startTimeMinutes.style.width = "45px"; startTimeMinutes.style.width = "45px";
let startTimeSeconds = document.createElement("input"); const 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].segment[0]); startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index].segment[0]);
startTimeSeconds.style.width = "60px"; startTimeSeconds.style.width = "60px";
let endTimeMinutes = document.createElement("input"); const 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].segment[1])); endTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index].segment[1]));
endTimeMinutes.style.width = "45px"; endTimeMinutes.style.width = "45px";
let endTimeSeconds = document.createElement("input"); const 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";
@@ -604,16 +604,16 @@ async function runThePopup(messageListener?: MessageListener) {
endTimeSeconds.style.width = "60px"; endTimeSeconds.style.width = "60px";
//the button to set the current time //the button to set the current time
let endTimeNowButton = document.createElement("span"); const endTimeNowButton = document.createElement("span");
endTimeNowButton.id = "endTimeNowButton" + index; endTimeNowButton.id = "endTimeNowButton" + index;
endTimeNowButton.innerText = "(Now)"; endTimeNowButton.innerText = "(Now)";
endTimeNowButton.className = "tinyLink popupElement"; endTimeNowButton.className = "tinyLink popupElement";
endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index)); endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index));
let colonText = document.createElement("span"); const colonText = document.createElement("span");
colonText.innerText = ":"; colonText.innerText = ":";
let toText = document.createElement("span"); const toText = document.createElement("span");
toText.innerText = " " + chrome.i18n.getMessage("to") + " "; toText.innerText = " " + chrome.i18n.getMessage("to") + " ";
//remove all children to replace //remove all children to replace
@@ -632,14 +632,14 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimeContainer.appendChild(endTimeNowButton); sponsorTimeContainer.appendChild(endTimeNowButton);
//add save button and remove edit button //add save button and remove edit button
let saveButton = document.createElement("span"); const saveButton = document.createElement("span");
saveButton.id = "sponsorTimeSaveButton" + index; saveButton.id = "sponsorTimeSaveButton" + index;
saveButton.innerText = "Save"; saveButton.innerText = "Save";
saveButton.className = "mediumLink popupElement"; saveButton.className = "mediumLink popupElement";
saveButton.addEventListener("click", () => saveSponsorTimeEdit(index)); saveButton.addEventListener("click", () => saveSponsorTimeEdit(index));
let editButton = document.getElementById("sponsorTimeEditButton" + index); const editButton = document.getElementById("sponsorTimeEditButton" + index);
let sponsorTimesContainer = document.getElementById("sponsorTimesContainer"); const sponsorTimesContainer = document.getElementById("sponsorTimesContainer");
sponsorTimesContainer.replaceChild(saveButton, editButton); sponsorTimesContainer.replaceChild(saveButton, editButton);
} }
@@ -653,8 +653,8 @@ async function runThePopup(messageListener?: MessageListener) {
tabs[0].id, tabs[0].id,
{message: "getCurrentTime"}, {message: "getCurrentTime"},
function (response) { function (response) {
let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index); const minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index);
let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index); const seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index);
minutes.value = String(getTimeInMinutes(response.currentTime)); minutes.value = String(getTimeInMinutes(response.currentTime));
seconds.value = getTimeInFormattedSeconds(response.currentTime); seconds.value = getTimeInFormattedSeconds(response.currentTime);
@@ -665,8 +665,8 @@ async function runThePopup(messageListener?: MessageListener) {
//id start name is whether it is the startTime or endTime //id start name is whether it is the startTime or endTime
//gives back the time in seconds //gives back the time in seconds
function getSponsorTimeEditTimes(idStartName, index): number { function getSponsorTimeEditTimes(idStartName, index): number {
let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index); const minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index);
let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index); const seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index);
return parseInt(minutes.value) * 60 + parseFloat(seconds.value); return parseInt(minutes.value) * 60 + parseFloat(seconds.value);
} }
@@ -858,13 +858,13 @@ async function runThePopup(messageListener?: MessageListener) {
} }
function addVoteMessage(message, UUID) { function addVoteMessage(message, UUID) {
let container = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID); const container = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID);
//remove all children //remove all children
while (container.firstChild) { while (container.firstChild) {
container.removeChild(container.firstChild); container.removeChild(container.firstChild);
} }
let thanksForVotingText = document.createElement("h2"); const thanksForVotingText = document.createElement("h2");
thanksForVotingText.innerText = message; thanksForVotingText.innerText = message;
//there are already breaks there //there are already breaks there
thanksForVotingText.style.marginBottom = "0px"; thanksForVotingText.style.marginBottom = "0px";
@@ -901,15 +901,15 @@ async function runThePopup(messageListener?: MessageListener) {
//converts time in seconds to minutes:seconds //converts time in seconds to minutes:seconds
function getFormattedTime(seconds) { function getFormattedTime(seconds) {
let minutes = Math.floor(seconds / 60); const minutes = Math.floor(seconds / 60);
let secondsDisplayNumber = Math.round(seconds - minutes * 60); const secondsDisplayNumber = Math.round(seconds - minutes * 60);
let secondsDisplay = String(secondsDisplayNumber); let secondsDisplay = String(secondsDisplayNumber);
if (secondsDisplayNumber < 10) { if (secondsDisplayNumber < 10) {
//add a zero //add a zero
secondsDisplay = "0" + secondsDisplay; secondsDisplay = "0" + secondsDisplay;
} }
let formatted = minutes + ":" + secondsDisplay; const formatted = minutes + ":" + secondsDisplay;
return formatted; return formatted;
} }
@@ -984,7 +984,7 @@ async function runThePopup(messageListener?: MessageListener) {
} }
//remove this channel //remove this channel
let index = whitelistedChannels.indexOf(response.channelID); const index = whitelistedChannels.indexOf(response.channelID);
whitelistedChannels.splice(index, 1); whitelistedChannels.splice(index, 1);
//change button //change button
@@ -1034,14 +1034,14 @@ async function runThePopup(messageListener?: MessageListener) {
//converts time in seconds to minutes //converts time in seconds to minutes
function getTimeInMinutes(seconds) { function getTimeInMinutes(seconds) {
let minutes = Math.floor(seconds / 60); const minutes = Math.floor(seconds / 60);
return minutes; return minutes;
} }
//converts time in seconds to seconds past the last minute //converts time in seconds to seconds past the last minute
function getTimeInFormattedSeconds(seconds) { function getTimeInFormattedSeconds(seconds) {
let minutes = seconds % 60; const minutes = seconds % 60;
let secondsFormatted = minutes.toFixed(3); let secondsFormatted = minutes.toFixed(3);
if (minutes < 10) { if (minutes < 10) {
@@ -1059,7 +1059,7 @@ async function runThePopup(messageListener?: MessageListener) {
* @returns {string} * @returns {string}
*/ */
function getFormattedHours(minues) { function getFormattedHours(minues) {
let hours = Math.floor(minues / 60); const hours = Math.floor(minues / 60);
return (hours > 0 ? hours + "h " : "") + (minues % 60).toFixed(1); return (hours > 0 ? hours + "h " : "") + (minues % 60).toFixed(1);
} }
@@ -1068,7 +1068,7 @@ async function runThePopup(messageListener?: MessageListener) {
if (chrome.tabs != undefined) { if (chrome.tabs != undefined) {
//add the width restriction (because Firefox) //add the width restriction (because Firefox)
let link = <HTMLLinkElement> document.getElementById("sponsorBlockStyleSheet"); const link = <HTMLLinkElement> document.getElementById("sponsorBlockStyleSheet");
(<CSSStyleSheet> link.sheet).insertRule('.popupBody { width: 325 }', 0); (<CSSStyleSheet> link.sheet).insertRule('.popupBody { width: 325 }', 0);
//this means it is actually opened in the popup //this means it is actually opened in the popup

View File

@@ -14,7 +14,7 @@ class SkipNotice {
skipNoticeRef: React.MutableRefObject<SkipNoticeComponent>; skipNoticeRef: React.MutableRefObject<SkipNoticeComponent>;
constructor(segments: SponsorTime[], autoSkip: boolean = false, contentContainer: ContentContainer) { constructor(segments: SponsorTime[], autoSkip = false, contentContainer: ContentContainer) {
this.segments = segments; this.segments = segments;
this.autoSkip = autoSkip; this.autoSkip = autoSkip;
this.contentContainer = contentContainer; this.contentContainer = contentContainer;
@@ -24,7 +24,7 @@ class SkipNotice {
|| document.getElementById("movie_player") || document.querySelector("#player-container .video-js"); || document.getElementById("movie_player") || document.querySelector("#player-container .video-js");
if (referenceNode == null) { if (referenceNode == null) {
//for embeds //for embeds
let player = document.getElementById("player"); const player = document.getElementById("player");
referenceNode = player.firstChild as HTMLElement; referenceNode = player.firstChild as HTMLElement;
let index = 1; let index = 1;
@@ -40,7 +40,7 @@ class SkipNotice {
referenceNode = document.querySelector("#main-panel.ytmusic-player-page"); referenceNode = document.querySelector("#main-panel.ytmusic-player-page");
} }
let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length; const amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
//this is the suffix added at the end of every id //this is the suffix added at the end of every id
let idSuffix = ""; let idSuffix = "";
for (const segment of this.segments) { for (const segment of this.segments) {

View File

@@ -24,7 +24,7 @@ class SubmissionNotice {
|| document.getElementById("movie_player") || document.querySelector("#player-container .video-js"); || document.getElementById("movie_player") || document.querySelector("#player-container .video-js");
if (referenceNode == null) { if (referenceNode == null) {
//for embeds //for embeds
let player = document.getElementById("player"); const player = document.getElementById("player");
referenceNode = player.firstChild as HTMLElement; referenceNode = player.firstChild as HTMLElement;
let index = 1; let index = 1;

View File

@@ -28,15 +28,15 @@ class Utils {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
setTimeout(() => reject("TIMEOUT"), timeout); setTimeout(() => reject("TIMEOUT"), timeout);
let intervalCheck = () => { const intervalCheck = () => {
let result = condition(); const result = condition();
if (result !== false) { if (result !== false) {
resolve(result); resolve(result);
clearInterval(interval); clearInterval(interval);
}; }
}; };
let interval = setInterval(intervalCheck, check); const interval = setInterval(intervalCheck, check);
//run the check once first, this speeds it up a lot //run the check once first, this speeds it up a lot
intervalCheck(); intervalCheck();
@@ -56,7 +56,7 @@ class Utils {
let permissions = ["declarativeContent"]; let permissions = ["declarativeContent"];
if (this.isFirefox()) permissions = []; if (this.isFirefox()) permissions = [];
let self = this; const self = this;
chrome.permissions.request({ chrome.permissions.request({
origins: this.getInvidiousInstancesRegex(), origins: this.getInvidiousInstancesRegex(),
@@ -80,19 +80,19 @@ class Utils {
* For now, it is just SB.config.invidiousInstances. * For now, it is just SB.config.invidiousInstances.
*/ */
setupExtraSiteContentScripts() { setupExtraSiteContentScripts() {
let self = this; const self = this;
if (this.isFirefox()) { if (this.isFirefox()) {
let firefoxJS = []; const firefoxJS = [];
for (const file of this.js) { for (const file of this.js) {
firefoxJS.push({file}); firefoxJS.push({file});
} }
let firefoxCSS = []; const firefoxCSS = [];
for (const file of this.css) { for (const file of this.css) {
firefoxCSS.push({file}); firefoxCSS.push({file});
} }
let registration = { const registration = {
message: "registerContentScript", message: "registerContentScript",
id: "invidious", id: "invidious",
allFrames: true, allFrames: true,
@@ -108,7 +108,7 @@ class Utils {
} }
} else { } else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() { chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() {
let conditions = []; const conditions = [];
for (const regex of self.getInvidiousInstancesRegex()) { for (const regex of self.getInvidiousInstancesRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({ conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex } pageUrl: { urlMatches: regex }
@@ -116,7 +116,7 @@ class Utils {
} }
// Add page rule // Add page rule
let rule = { const rule = {
id: "invidious", id: "invidious",
conditions, conditions,
// This API is experimental and not visible by the TypeScript compiler // This API is experimental and not visible by the TypeScript compiler
@@ -137,7 +137,7 @@ class Utils {
*/ */
removeExtraSiteRegistration() { removeExtraSiteRegistration() {
if (this.isFirefox()) { if (this.isFirefox()) {
let id = "invidious"; const id = "invidious";
if (this.backgroundScriptContainer) { if (this.backgroundScriptContainer) {
this.backgroundScriptContainer.unregisterFirefoxContentScript(id); this.backgroundScriptContainer.unregisterFirefoxContentScript(id);
@@ -163,7 +163,7 @@ class Utils {
* @param sponsorTimes * @param sponsorTimes
*/ */
getSegmentsFromSponsorTimes(sponsorTimes: SponsorTime[]): number[][] { getSegmentsFromSponsorTimes(sponsorTimes: SponsorTime[]): number[][] {
let segments: number[][] = []; const segments: number[][] = [];
for (const sponsorTime of sponsorTimes) { for (const sponsorTime of sponsorTimes) {
segments.push(sponsorTime.segment); segments.push(sponsorTime.segment);
} }
@@ -195,17 +195,17 @@ class Utils {
localizeHtmlPage() { localizeHtmlPage() {
//Localize by replacing __MSG_***__ meta tags //Localize by replacing __MSG_***__ meta tags
var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; const objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children;
for (var j = 0; j < objects.length; j++) { for (let j = 0; j < objects.length; j++) {
var obj = objects[j]; const obj = objects[j];
let localizedMessage = this.getLocalizedMessage(obj.innerHTML.toString()); const localizedMessage = this.getLocalizedMessage(obj.innerHTML.toString());
if (localizedMessage) obj.innerHTML = localizedMessage; if (localizedMessage) obj.innerHTML = localizedMessage;
} }
} }
getLocalizedMessage(text) { getLocalizedMessage(text) {
var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) { const valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) {
return v1 ? chrome.i18n.getMessage(v1) : ""; return v1 ? chrome.i18n.getMessage(v1) : "";
}); });
@@ -220,7 +220,7 @@ class Utils {
* @returns {String[]} Invidious Instances in regex form * @returns {String[]} Invidious Instances in regex form
*/ */
getInvidiousInstancesRegex() { getInvidiousInstancesRegex() {
var invidiousInstancesRegex = []; const invidiousInstancesRegex = [];
for (const url of Config.config.invidiousInstances) { for (const url of Config.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*"); invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*"); invidiousInstancesRegex.push("http://*." + url + "/*");
@@ -230,10 +230,10 @@ class Utils {
} }
generateUserID(length = 36) { generateUserID(length = 36) {
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = ""; let result = "";
if (window.crypto && window.crypto.getRandomValues) { if (window.crypto && window.crypto.getRandomValues) {
let values = new Uint32Array(length); const values = new Uint32Array(length);
window.crypto.getRandomValues(values); window.crypto.getRandomValues(values);
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
result += charset[values[i] % charset.length]; result += charset[values[i] % charset.length];
@@ -298,7 +298,7 @@ class Utils {
* @param callback * @param callback
*/ */
async asyncRequestToServer(type: string, address: string, data = {}): Promise<FetchResponse> { async asyncRequestToServer(type: string, address: string, data = {}): Promise<FetchResponse> {
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress; const 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));
} }
@@ -311,7 +311,7 @@ class Utils {
* @param callback * @param callback
*/ */
sendRequestToServer(type: string, address: string, callback?: (response: FetchResponse) => void) { sendRequestToServer(type: string, address: string, callback?: (response: FetchResponse) => void) {
let serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress; const serverAddress = Config.config.testingServer ? CompileConfig.testingServerAddress : Config.config.serverAddress;
// Ask the background script to do the work // Ask the background script to do the work
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
@@ -324,15 +324,15 @@ class Utils {
} }
getFormattedTime(seconds: number, precise?: boolean): string { getFormattedTime(seconds: number, precise?: boolean): string {
let hours = Math.floor(seconds / 60 / 60); const hours = Math.floor(seconds / 60 / 60);
let minutes = Math.floor(seconds / 60) % 60; const minutes = Math.floor(seconds / 60) % 60;
let minutesDisplay = String(minutes); let minutesDisplay = String(minutes);
let secondsNum = seconds % 60; let secondsNum = seconds % 60;
if (!precise) { if (!precise) {
secondsNum = Math.floor(secondsNum); secondsNum = Math.floor(secondsNum);
} }
let secondsDisplay: string = String(precise ? secondsNum.toFixed(3) : secondsNum); let secondsDisplay = String(precise ? secondsNum.toFixed(3) : secondsNum);
if (secondsNum < 10) { if (secondsNum < 10) {
//add a zero //add a zero
@@ -343,7 +343,7 @@ class Utils {
minutesDisplay = "0" + minutesDisplay; minutesDisplay = "0" + minutesDisplay;
} }
let formatted = (hours ? hours + ":" : "") + minutesDisplay + ":" + secondsDisplay; const formatted = (hours ? hours + ":" : "") + minutesDisplay + ":" + secondsDisplay;
return formatted; return formatted;
} }