Compare commits

..

11 Commits
4.4.3 ... 4.4.5

Author SHA1 Message Date
Ajay
c0f8f5e1d0 bump version 2022-05-25 14:16:45 -04:00
Ajay Ramachandran
e948e1e569 Merge pull request #1331 from mchangrh/updateDependencies
update dependencies & bump minimum node version
2022-05-25 00:01:10 -04:00
Ajay
5289e62d43 Use virtual time for determining whether to skip and increase skip buffer
Potentially fix recent issue with skips not triggering
2022-05-24 23:54:05 -04:00
Ajay
eda7aac5ef Add time to log messages 2022-05-24 23:31:43 -04:00
Michael C
d9f4ab0d04 specify jest as cjs, change eslintrc to .json 2022-05-24 21:23:05 -04:00
Michael C
2665327729 update dependencies & bump minimum node version (#1329)
- bump all dependences
- add github-actions reporter to jest
- convert (most) webpack configs to ESM
  - manifest.cjs cannot be converted since there is no native .json import until node 17
2022-05-24 21:14:36 -04:00
Ajay
4738c1897f bump version 2022-05-24 14:05:13 -04:00
Ajay
cfbb194a61 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2022-05-24 14:04:54 -04:00
Ajay
9ad21e8ea1 Fix channel id regex 2022-05-24 14:04:53 -04:00
Ajay Ramachandran
941fc2985d Merge pull request #1238 from AlecRust/fix-unused-vars-lint
Fix @typescript-eslint/no-unused-vars lint warnings
2022-05-24 13:17:27 -04:00
Alec Rust
463ce258bf Fix @typescript-eslint/no-unused-vars lint warnings 2022-04-23 15:44:21 +01:00
16 changed files with 3520 additions and 2905 deletions

View File

@@ -1,34 +0,0 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
jest: true,
jasmine: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
sourceType: "module",
},
plugins: ["react", "@typescript-eslint"],
rules: {
// TODO: Remove warn rules when not needed anymore
"no-self-assign": "off",
"@typescript-eslint/no-empty-interface": "off",
"react/prop-types": [2, { ignore: ['children'] }]
},
settings: {
react: {
version: "detect",
},
},
};

33
.eslintrc.json Normal file
View File

@@ -0,0 +1,33 @@
{
"env": {
"browser": true,
"es2021": true,
"node": true,
"jest": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint"],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"no-self-assign": "off",
"@typescript-eslint/no-empty-interface": "off",
"react/prop-types": [2, { "ignore": ["children"] }]
},
"settings": {
"react": {
"version": "detect"
}
}
}

View File

@@ -5,4 +5,5 @@ module.exports = {
"transform": { "transform": {
"^.+\\.ts$": "ts-jest" "^.+\\.ts$": "ts-jest"
}, },
"reporters": ["github-actions"]
}; };

View File

@@ -1,7 +1,7 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "SponsorBlock", "short_name": "SponsorBlock",
"version": "4.4.3", "version": "4.4.5",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app", "homepage_url": "https://sponsor.ajay.app",

6152
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,39 +3,40 @@
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "background.js", "main": "background.js",
"type": "module",
"dependencies": { "dependencies": {
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/chrome": "^0.0.180", "@types/chrome": "^0.0.188",
"@types/firefox-webext-browser": "^94.0.1", "@types/firefox-webext-browser": "^94.0.1",
"@types/jest": "^27.4.1", "@types/jest": "^27.5.1",
"@types/react": "^17.0.43", "@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14", "@types/react-dom": "^17.0.14",
"@types/selenium-webdriver": "^4.0.18", "@types/selenium-webdriver": "^4.1.0",
"@types/wicg-mediasession": "^1.1.3", "@types/wicg-mediasession": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/eslint-plugin": "^5.26.0",
"@typescript-eslint/parser": "^5.17.0", "@typescript-eslint/parser": "^5.26.0",
"chromedriver": "^100.0.0", "chromedriver": "^101.0.0",
"concurrently": "^7.0.0", "concurrently": "^7.2.1",
"copy-webpack-plugin": "^10.2.4", "copy-webpack-plugin": "^11.0.0",
"eslint": "^8.12.0", "eslint": "^8.16.0",
"eslint-plugin-react": "^7.29.4", "eslint-plugin-react": "^7.30.0",
"fork-ts-checker-webpack-plugin": "^7.2.1", "fork-ts-checker-webpack-plugin": "^7.2.11",
"jest": "^27.5.1", "jest": "^28.1.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"schema-utils": "^4.0.0", "schema-utils": "^4.0.0",
"selenium-webdriver": "^4.1.1", "selenium-webdriver": "^4.1.2",
"speed-measure-webpack-plugin": "^1.5.0", "speed-measure-webpack-plugin": "^1.5.0",
"ts-jest": "^27.1.4", "ts-jest": "^28.0.3",
"ts-loader": "^9.2.8", "ts-loader": "^9.3.0",
"ts-node": "^10.7.0", "ts-node": "^10.8.0",
"typescript": "4.6", "typescript": "4.7",
"web-ext": "^6.8.0", "web-ext": "^6.8.0",
"webpack": "^5.64.4", "webpack": "^5.72.1",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-merge": "^4.2.2" "webpack-merge": "^5.8.0"
}, },
"scripts": { "scripts": {
"web-run": "npm run web-run:chrome", "web-run": "npm run web-run:chrome",
@@ -65,7 +66,7 @@
"lint:fix": "eslint src --fix" "lint:fix": "eslint src --fix"
}, },
"engines": { "engines": {
"node": ">=12.20.0" "node": ">=16"
}, },
"funding": [ "funding": [
{ {

View File

@@ -1,7 +1,7 @@
import * as React from "react"; import * as React from "react";
import * as CompileConfig from "../../config.json"; import * as CompileConfig from "../../config.json";
import Config from "../config" import Config from "../config"
import { Category, ContentContainer, SponsorHideType, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types"; import { Category, ContentContainer, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types";
import NoticeComponent from "./NoticeComponent"; import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
import Utils from "../utils"; import Utils from "../utils";
@@ -72,7 +72,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
amountOfPreviousNotices: number; amountOfPreviousNotices: number;
showInSecondSlot: boolean; showInSecondSlot: boolean;
idSuffix: string; idSuffix: string;
noticeRef: React.MutableRefObject<NoticeComponent>; noticeRef: React.MutableRefObject<NoticeComponent>;
@@ -105,7 +105,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
if (this.segments.length > 1) { if (this.segments.length > 1) {
this.segments.sort((a, b) => a.segment[0] - b.segment[0]); this.segments.sort((a, b) => a.segment[0] - b.segment[0]);
} }
// This is the suffix added at the end of every id // This is the suffix added at the end of every id
for (const segment of this.segments) { for (const segment of this.segments) {
this.idSuffix += segment.UUID; this.idSuffix += segment.UUID;
@@ -168,7 +168,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
noticeStyle.transform = "scale(0.8) translate(10%, 10%)"; noticeStyle.transform = "scale(0.8) translate(10%, 10%)";
} }
// If it started out as smaller, always keep the // If it started out as smaller, always keep the
// skip button there // skip button there
const showFirstSkipButton = this.props.smaller || this.segments[0].actionType === ActionType.Mute; const showFirstSkipButton = this.props.smaller || this.segments[0].actionType === ActionType.Mute;
const firstColumn = showFirstSkipButton ? ( const firstColumn = showFirstSkipButton ? (
@@ -181,7 +181,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
showInSecondSlot={this.showInSecondSlot} showInSecondSlot={this.showInSecondSlot}
idSuffix={this.idSuffix} idSuffix={this.idSuffix}
fadeIn={true} fadeIn={true}
startFaded={Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAll startFaded={Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAll
|| (Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAutoSkip && this.autoSkip)} || (Config.config.noticeVisibilityMode >= NoticeVisbilityMode.FadedForAutoSkip && this.autoSkip)}
timed={true} timed={true}
maxCountdownTime={this.state.maxCountdownTime} maxCountdownTime={this.state.maxCountdownTime}
@@ -205,7 +205,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
key={0}> key={0}>
{/* Vote Button Container */} {/* Vote Button Container */}
{!this.state.thanksForVotingText ? {!this.state.thanksForVotingText ?
<td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix} <td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix}
className="sponsorTimesVoteButtonsContainer"> className="sponsorTimesVoteButtonsContainer">
@@ -268,7 +268,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
? this.getSkipButton(1) : null} ? this.getSkipButton(1) : null}
{/* Never show button */} {/* Never show button */}
{!this.autoSkip || this.props.startReskip ? "" : {!this.autoSkip || this.props.startReskip ? "" :
<td className="sponsorSkipNoticeRightSection" <td className="sponsorSkipNoticeRightSection"
key={1}> key={1}>
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton" <button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
@@ -343,7 +343,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
getSkipButton(buttonIndex: number): JSX.Element { getSkipButton(buttonIndex: number): JSX.Element {
if (this.state.showSkipButton[buttonIndex] && (this.segments.length > 1 if (this.state.showSkipButton[buttonIndex] && (this.segments.length > 1
|| this.segments[0].actionType !== ActionType.Poi || this.segments[0].actionType !== ActionType.Poi
|| this.props.unskipTime)) { || this.props.unskipTime)) {
@@ -365,8 +365,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
className="sponsorSkipObject sponsorSkipNoticeButton" className="sponsorSkipObject sponsorSkipNoticeButton"
style={style} style={style}
onClick={() => this.prepAction(buttonIndex === 1 ? SkipNoticeAction.Unskip1 : SkipNoticeAction.Unskip0)}> onClick={() => this.prepAction(buttonIndex === 1 ? SkipNoticeAction.Unskip1 : SkipNoticeAction.Unskip0)}>
{this.getSkipButtonText(buttonIndex, forceSeek ? ActionType.Skip : null) {this.getSkipButtonText(buttonIndex, forceSeek ? ActionType.Skip : null)
+ (!forceSeek && this.state.showKeybindHint + (!forceSeek && this.state.showKeybindHint
? " (" + keybindToString(Config.config.skipKeybind) + ")" : "")} ? " (" + keybindToString(Config.config.skipKeybind) + ")" : "")}
</button> </button>
</span> </span>
@@ -379,7 +379,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
for (let i = 0; i < this.segments.length; i++) { for (let i = 0; i < this.segments.length; i++) {
elements.push( elements.push(
<button className="sponsorSkipObject sponsorSkipNoticeButton" <button className="sponsorSkipObject sponsorSkipNoticeButton"
style={{opacity: this.getSubmissionChooserOpacity(i), style={{opacity: this.getSubmissionChooserOpacity(i),
color: this.getSubmissionChooserColor(i)}} color: this.getSubmissionChooserColor(i)}}
onClick={() => this.performAction(i)} onClick={() => this.performAction(i)}
key={"submission" + i + this.segments[i].category + this.idSuffix}> key={"submission" + i + this.segments[i].category + this.idSuffix}>
@@ -404,7 +404,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getSubmissionChooserColor(index: number): string { getSubmissionChooserColor(index: number): string {
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote; const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote; const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
const shouldWarnUser = Config.config.isVip && (isDownvote || isCopyDownvote) const shouldWarnUser = Config.config.isVip && (isDownvote || isCopyDownvote)
&& this.segments[index].locked === 1; && this.segments[index].locked === 1;
return shouldWarnUser ? this.lockedColor : this.unselectedColor; return shouldWarnUser ? this.lockedColor : this.unselectedColor;
@@ -480,8 +480,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
/** /**
* Performs the action from the current state * Performs the action from the current state
* *
* @param index * @param index
*/ */
performAction(index: number, action?: SkipNoticeAction): void { performAction(index: number, action?: SkipNoticeAction): void {
switch (action ?? this.state.actionState) { switch (action ?? this.state.actionState) {
@@ -620,7 +620,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
// See if the title should be changed // See if the title should be changed
if (!this.autoSkip) { if (!this.autoSkip) {
newState.noticeTitle = chrome.i18n.getMessage("noticeTitle"); newState.noticeTitle = chrome.i18n.getMessage("noticeTitle");
} }
//reset countdown //reset countdown
this.setState(newState, () => { this.setState(newState, () => {
@@ -723,7 +723,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
messages messages
}); });
} }
addVoteButtonInfo(message: string): void { addVoteButtonInfo(message: string): void {
this.setState({ this.setState({
thanksForVotingText: message thanksForVotingText: message
@@ -786,7 +786,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
case ActionType.Mute: { case ActionType.Mute: {
return chrome.i18n.getMessage("unmute"); return chrome.i18n.getMessage("unmute");
} }
case ActionType.Skip: case ActionType.Skip:
default: { default: {
return chrome.i18n.getMessage("unskip"); return chrome.i18n.getMessage("unskip");
} }
@@ -799,7 +799,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
case ActionType.Mute: { case ActionType.Mute: {
return chrome.i18n.getMessage("mute"); return chrome.i18n.getMessage("mute");
} }
case ActionType.Skip: case ActionType.Skip:
default: { default: {
return chrome.i18n.getMessage("reskip"); return chrome.i18n.getMessage("reskip");
} }
@@ -812,7 +812,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
case ActionType.Mute: { case ActionType.Mute: {
return chrome.i18n.getMessage("mute"); return chrome.i18n.getMessage("mute");
} }
case ActionType.Skip: case ActionType.Skip:
default: { default: {
return chrome.i18n.getMessage("skip"); return chrome.i18n.getMessage("skip");
} }

View File

@@ -1,6 +1,4 @@
import * as React from "react"; import * as React from "react";
import Config from "../config";
import { Category, SegmentUUID, SponsorTime } from "../types";
export interface TooltipProps { export interface TooltipProps {
text: string; text: string;

View File

@@ -1,6 +1,6 @@
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
import * as invidiousList from "../ci/invidiouslist.json"; import * as invidiousList from "../ci/invidiouslist.json";
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, StorageChangesObject, UnEncodedSegmentTimes as UnencodedSegmentTimes, Keybind, HashedValue, VideoID, SponsorHideType } from "./types"; import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, StorageChangesObject, Keybind, HashedValue, VideoID, SponsorHideType } from "./types";
import { keybindEquals } from "./utils/configUtils"; import { keybindEquals } from "./utils/configUtils";
interface SBConfig { interface SBConfig {
@@ -302,7 +302,7 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
for (const key in changes) { for (const key in changes) {
Config.cachedSyncConfig[key] = changes[key].newValue; Config.cachedSyncConfig[key] = changes[key].newValue;
} }
for (const callback of Config.configSyncListeners) { for (const callback of Config.configSyncListeners) {
callback(changes); callback(changes);
} }
@@ -312,7 +312,7 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
} }
} }
}); });
const syncHandler: ProxyHandler<SBConfig> = { const syncHandler: ProxyHandler<SBConfig> = {
set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) { set<K extends keyof SBConfig>(obj: SBConfig, prop: K, value: SBConfig[K]) {
Config.cachedSyncConfig[prop] = value; Config.cachedSyncConfig[prop] = value;
@@ -329,10 +329,10 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
return obj[prop] || data; return obj[prop] || data;
}, },
deleteProperty(obj: SBConfig, prop: keyof SBConfig) { deleteProperty(obj: SBConfig, prop: keyof SBConfig) {
chrome.storage.sync.remove(<string> prop); chrome.storage.sync.remove(<string> prop);
return true; return true;
} }
@@ -354,10 +354,10 @@ function configProxy(): { sync: SBConfig, local: SBStorage } {
return obj[prop] || data; return obj[prop] || data;
}, },
deleteProperty(obj: SBStorage, prop: keyof SBStorage) { deleteProperty(obj: SBStorage, prop: keyof SBStorage) {
chrome.storage.local.remove(<string> prop); chrome.storage.local.remove(<string> prop);
return true; return true;
} }
@@ -381,7 +381,7 @@ function forceLocalUpdate(prop: string): void {
}); });
} }
async function fetchConfig(): Promise<void> { async function fetchConfig(): Promise<void> {
await Promise.all([new Promise<void>((resolve) => { await Promise.all([new Promise<void>((resolve) => {
chrome.storage.sync.get(null, function(items) { chrome.storage.sync.get(null, function(items) {
Config.cachedSyncConfig = <SBConfig> <unknown> items; Config.cachedSyncConfig = <SBConfig> <unknown> items;
@@ -389,7 +389,7 @@ async function fetchConfig(): Promise<void> {
}); });
}), new Promise<void>((resolve) => { }), new Promise<void>((resolve) => {
chrome.storage.local.get(null, function(items) { chrome.storage.local.get(null, function(items) {
Config.cachedLocalStorage = <SBStorage> <unknown> items; Config.cachedLocalStorage = <SBStorage> <unknown> items;
resolve(); resolve();
}); });
})]); })]);
@@ -433,9 +433,9 @@ function migrateOldSyncFormats(config: SBConfig) {
if (!config["autoSkipOnMusicVideosUpdate"]) { if (!config["autoSkipOnMusicVideosUpdate"]) {
config["autoSkipOnMusicVideosUpdate"] = true; config["autoSkipOnMusicVideosUpdate"] = true;
for (const selection of config.categorySelections) { for (const selection of config.categorySelections) {
if (selection.name === "music_offtopic" if (selection.name === "music_offtopic"
&& selection.option === CategorySkipOption.AutoSkip) { && selection.option === CategorySkipOption.AutoSkip) {
config.autoSkipOnMusicVideos = true; config.autoSkipOnMusicVideos = true;
break; break;
} }

View File

@@ -321,9 +321,6 @@ async function videoIDChange(id) {
} }
} }
// Get new video info
// getVideoInfo(); // Seems to have been replaced
// Update whitelist data when the video data is loaded // Update whitelist data when the video data is loaded
whitelistCheck(); whitelistCheck();
@@ -483,14 +480,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
if (!video || video.paused) return; if (!video || video.paused) return;
if (currentTime === undefined || currentTime === null) { if (currentTime === undefined || currentTime === null) {
const virtualTime = lastTimeFromWaitingEvent ?? (lastKnownVideoTime.videoTime ? currentTime = getVirtualTime();
(performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null);
if ((lastTimeFromWaitingEvent || !utils.isFirefox())
&& !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6){
currentTime = virtualTime;
} else {
currentTime = video.currentTime;
}
} }
lastTimeFromWaitingEvent = null; lastTimeFromWaitingEvent = null;
@@ -544,7 +534,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
let forcedIncludeNonIntersectingSegments = true; let forcedIncludeNonIntersectingSegments = true;
if (incorrectVideoCheck(videoID, currentSkip)) return; if (incorrectVideoCheck(videoID, currentSkip)) return;
forceVideoTime ||= video.currentTime; forceVideoTime ||= Math.max(video.currentTime, getVirtualTime());
if (forceVideoTime >= skipTime[0] && forceVideoTime < skipTime[1]) { if (forceVideoTime >= skipTime[0] && forceVideoTime < skipTime[1]) {
skipToTime({ skipToTime({
@@ -594,11 +584,23 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
logDebug(`Starting timeout to skip ${video.currentTime} to skip at ${skipTime[0]}`); logDebug(`Starting timeout to skip ${video.currentTime} to skip at ${skipTime[0]}`);
// Schedule for right before to be more precise than normal timeout // Schedule for right before to be more precise than normal timeout
currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 100)); currentSkipSchedule = setTimeout(skippingFunction, Math.max(0, delayTime - 150));
} }
} }
} }
function getVirtualTime(): number {
const virtualTime = lastTimeFromWaitingEvent ?? (lastKnownVideoTime.videoTime ?
(performance.now() - lastKnownVideoTime.preciseTime) / 1000 + lastKnownVideoTime.videoTime : null);
if ((lastTimeFromWaitingEvent || !utils.isFirefox())
&& !isSafari() && virtualTime && Math.abs(virtualTime - video.currentTime) < 0.6) {
return virtualTime;
} else {
return video.currentTime;
}
}
function inMuteSegment(currentTime: number): boolean { function inMuteSegment(currentTime: number): boolean {
const checkFunction = (segment) => segment.actionType === ActionType.Mute && segment.segment[0] <= currentTime && segment.segment[1] > currentTime; const checkFunction = (segment) => segment.actionType === ActionType.Mute && segment.segment[0] <= currentTime && segment.segment[1] > currentTime;
return sponsorTimes?.some(checkFunction) || sponsorTimesSubmitting.some(checkFunction); return sponsorTimes?.some(checkFunction) || sponsorTimesSubmitting.some(checkFunction);
@@ -942,12 +944,10 @@ function startSkipScheduleCheckingForStartSponsors() {
// See if there are any starting sponsors // See if there are any starting sponsors
let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1; let startingSegmentTime = getStartTimeFromUrl(document.URL) || -1;
let found = false; let found = false;
let startingSegment: SponsorTime = null;
for (const time of sponsorTimes) { for (const time of sponsorTimes) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
&& time.actionType !== ActionType.Poi) { && time.actionType !== ActionType.Poi) {
startingSegmentTime = time.segment[0]; startingSegmentTime = time.segment[0];
startingSegment = time;
found = true; found = true;
break; break;
} }
@@ -957,7 +957,6 @@ function startSkipScheduleCheckingForStartSponsors() {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
&& time.actionType !== ActionType.Poi) { && time.actionType !== ActionType.Poi) {
startingSegmentTime = time.segment[0]; startingSegmentTime = time.segment[0];
startingSegment = time;
found = true; found = true;
break; break;
} }
@@ -995,26 +994,6 @@ function startSkipScheduleCheckingForStartSponsors() {
} }
} }
/**
* Get the video info for the current tab from YouTube
*
* TODO: Replace
*/
async function getVideoInfo(): Promise<void> {
const result = await utils.asyncRequestToCustomServer("GET", "https://www.youtube.com/get_video_info?video_id=" + sponsorVideoID + "&html5=1&c=TVHTML5&cver=7.20190319");
if (result.ok) {
const decodedData = decodeURIComponent(result.responseText).match(/player_response=([^&]*)/)[1];
if (!decodedData) {
console.error("[SB] Failed at getting video info from YouTube.");
console.error("[SB] Data returned from YouTube: " + result.responseText);
return;
}
videoInfo = JSON.parse(decodedData);
}
}
function getYouTubeVideoID(document: Document): string | boolean { function getYouTubeVideoID(document: Document): string | boolean {
const url = document.URL; const url = document.URL;
// clips should never skip, going from clip to full video has no indications. // clips should never skip, going from clip to full video has no indications.
@@ -1149,7 +1128,7 @@ async function whitelistCheck() {
?? document.querySelector("a.ytp-title-channel-logo") // YouTube Embed ?? document.querySelector("a.ytp-title-channel-logo") // YouTube Embed
?? document.querySelector(".channel-profile #channel-name")?.parentElement.parentElement // Invidious ?? document.querySelector(".channel-profile #channel-name")?.parentElement.parentElement // Invidious
?? document.querySelector("a.slim-owner-icon-and-title")) // Mobile YouTube ?? document.querySelector("a.slim-owner-icon-and-title")) // Mobile YouTube
?.getAttribute("href")?.match(/\/channel\/(UC[a-zA-Z0-9_-]{22})|\/c\/([a-zA-Z0-9_-]+)/)?.[1]; ?.getAttribute("href")?.match(/(?:\/c\/|\/channel\/)(UC[a-zA-Z0-9_-]{22}|[a-zA-Z0-9_-]+)/)?.[1];
try { try {
await utils.wait(() => !!getChannelID(), 6000, 20); await utils.wait(() => !!getChannelID(), 6000, 20);

View File

@@ -2,10 +2,7 @@ import Config from "../config";
import { SponsorTime } from "../types"; import { SponsorTime } from "../types";
import { getSkippingText } from "../utils/categoryUtils"; import { getSkippingText } from "../utils/categoryUtils";
import { keybindToString } from "../utils/configUtils"; import { keybindToString } from "../utils/configUtils";
import Utils from "../utils";
import { AnimationUtils } from "../utils/animationUtils"; import { AnimationUtils } from "../utils/animationUtils";
const utils = new Utils();
export interface SkipButtonControlBarProps { export interface SkipButtonControlBarProps {
skip: (segment: SponsorTime) => void; skip: (segment: SponsorTime) => void;
@@ -53,7 +50,7 @@ export class SkipButtonControlBar {
this.skipIcon.id = "sbSkipIconControlBarImage"; this.skipIcon.id = "sbSkipIconControlBarImage";
this.textContainer = document.createElement("div"); this.textContainer = document.createElement("div");
this.container.appendChild(this.skipIcon); this.container.appendChild(this.skipIcon);
this.container.appendChild(this.textContainer); this.container.appendChild(this.textContainer);
this.container.addEventListener("click", () => this.toggleSkip()); this.container.addEventListener("click", () => this.toggleSkip());
@@ -73,7 +70,7 @@ export class SkipButtonControlBar {
attachToPage(): void { attachToPage(): void {
const mountingContainer = this.getMountingContainer(); const mountingContainer = this.getMountingContainer();
this.chapterText = document.querySelector(".ytp-chapter-container"); this.chapterText = document.querySelector(".ytp-chapter-container");
if (mountingContainer && !mountingContainer.contains(this.container)) { if (mountingContainer && !mountingContainer.contains(this.container)) {
if (this.onMobileYouTube) { if (this.onMobileYouTube) {
mountingContainer.appendChild(this.container); mountingContainer.appendChild(this.container);
@@ -220,4 +217,3 @@ export class SkipButtonControlBar {
this.container.style.left = this.left + "px"; this.container.style.left = this.left + "px";
} }
} }

View File

@@ -4,9 +4,9 @@ window["SBLogs"] = {
}; };
export function logDebug(message: string) { export function logDebug(message: string) {
window["SBLogs"].debug.push(message); window["SBLogs"].debug.push(`[${new Date().toISOString()}] ${message}`);
} }
export function logWarn(message: string) { export function logWarn(message: string) {
window["SBLogs"].warn.push(message); window["SBLogs"].warn.push(`[${new Date().toISOString()}] ${message}`);
} }

View File

@@ -1,12 +1,15 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const webpack = require("webpack"); import webpack from "webpack"
const path = require('path'); import path from "path"
const CopyPlugin = require('copy-webpack-plugin'); import { fileURLToPath } from "url"
const BuildManifest = require('./webpack.manifest'); import CopyPlugin from "copy-webpack-plugin"
const srcDir = '../src/'; import BuildManifest from "./webpack.manifest.cjs";
const fs = require("fs"); const srcDir = "../src/";
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); import fs from "fs";
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const edgeLanguages = [ const edgeLanguages = [
"de", "de",
@@ -24,7 +27,7 @@ const edgeLanguages = [
"zh_CN" "zh_CN"
] ]
module.exports = env => ({ export default env => ({
entry: { entry: {
popup: path.join(__dirname, srcDir + 'popup.ts'), popup: path.join(__dirname, srcDir + 'popup.ts'),
background: path.join(__dirname, srcDir + 'background.ts'), background: path.join(__dirname, srcDir + 'background.ts'),

View File

@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */ import { merge } from "webpack-merge";
const merge = require('webpack-merge'); import common from './webpack.common.js';
const common = require('./webpack.common.js');
module.exports = env => merge(common(env), { export default env => merge(common(env), {
devtool: 'inline-source-map', devtool: 'inline-source-map',
mode: 'development' mode: 'development'
}); });

View File

@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */ import { merge } from "webpack-merge";
const merge = require('webpack-merge'); import common from './webpack.common.js';
const common = require('./webpack.common.js');
module.exports = env => { export default env => {
let mode = "production"; let mode = "production";
env.mode = mode; env.mode = mode;