mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-14 23:47:04 +03:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8840dba90f | ||
|
|
856dded58f | ||
|
|
1d1bd2a003 | ||
|
|
dc91ee76ca | ||
|
|
90bb9a4d02 | ||
|
|
d12d847f2f | ||
|
|
31a9de252d | ||
|
|
299cb485c3 | ||
|
|
882d462849 | ||
|
|
fc3710b37b | ||
|
|
3ac170ad01 | ||
|
|
4069545603 | ||
|
|
db9fc11f13 | ||
|
|
76667f68ec | ||
|
|
e27a287a68 | ||
|
|
ce3731774d | ||
|
|
8cbf2bb50b | ||
|
|
6f8c44b2eb |
@@ -4,5 +4,8 @@
|
|||||||
],
|
],
|
||||||
"background": {
|
"background": {
|
||||||
"persistent": false
|
"persistent": false
|
||||||
}
|
},
|
||||||
|
"permissions": [
|
||||||
|
"https://*.youtube.com/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "5.4.11",
|
"version": "5.4.13",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"homepage_url": "https://sponsor.ajay.app",
|
"homepage_url": "https://sponsor.ajay.app",
|
||||||
|
|||||||
Submodule maze-utils updated: b7f55f39cc...b3572eaeff
10
package-lock.json
generated
10
package-lock.json
generated
@@ -13332,8 +13332,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@@ -23348,8 +23349,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"word-wrap": {
|
"word-wrap": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"wrap-ansi": {
|
"wrap-ansi": {
|
||||||
|
|||||||
Submodule public/_locales updated: fc6e767fd0...9e1f32d7c6
@@ -867,3 +867,7 @@ input::-webkit-inner-spin-button {
|
|||||||
.sponsorThumbnailLabel:hover span {
|
.sponsorThumbnailLabel:hover span {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sponsorblock-chapter-visible {
|
||||||
|
display: inherit !important;
|
||||||
|
}
|
||||||
@@ -13,6 +13,9 @@ window.SB = Config;
|
|||||||
|
|
||||||
import Utils from "./utils";
|
import Utils from "./utils";
|
||||||
import { getExtensionIdsToImportFrom } from "./utils/crossExtension";
|
import { getExtensionIdsToImportFrom } from "./utils/crossExtension";
|
||||||
|
import { isFirefoxOrSafari } from "./maze-utils";
|
||||||
|
import { injectUpdatedScripts } from "./maze-utils/cleanup";
|
||||||
|
import { logWarn } from "./utils/logger";
|
||||||
const utils = new Utils({
|
const utils = new Utils({
|
||||||
registerFirefoxContentScript,
|
registerFirefoxContentScript,
|
||||||
unregisterFirefoxContentScript
|
unregisterFirefoxContentScript
|
||||||
@@ -132,6 +135,11 @@ chrome.runtime.onInstalled.addListener(function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1500);
|
}, 1500);
|
||||||
|
|
||||||
|
// Only do this once the old version understands how to clean itself up
|
||||||
|
if (!isFirefoxOrSafari() && chrome.runtime.getManifest().version !== "5.4.13") {
|
||||||
|
injectUpdatedScripts().catch(logWarn);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
|
import SbSvg from "../svg-icons/sb_svg";
|
||||||
|
|
||||||
enum CountdownMode {
|
enum CountdownMode {
|
||||||
Timer,
|
Timer,
|
||||||
@@ -28,6 +29,7 @@ export interface NoticeProps {
|
|||||||
extraClass?: string;
|
extraClass?: string;
|
||||||
hideLogo?: boolean;
|
hideLogo?: boolean;
|
||||||
hideRightInfo?: boolean;
|
hideRightInfo?: boolean;
|
||||||
|
logoFill?: string;
|
||||||
|
|
||||||
// Callback for when this is closed
|
// Callback for when this is closed
|
||||||
closeListener: () => void;
|
closeListener: () => void;
|
||||||
@@ -122,10 +124,10 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
<td className="noticeLeftIcon">
|
<td className="noticeLeftIcon">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
{!this.props.hideLogo &&
|
{!this.props.hideLogo &&
|
||||||
<img id={"sponsorSkipLogo" + this.idSuffix}
|
<SbSvg
|
||||||
className="sponsorSkipLogo sponsorSkipObject"
|
id={"sponsorSkipLogo" + this.idSuffix}
|
||||||
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
|
fill={this.props.logoFill}
|
||||||
</img>
|
className="sponsorSkipLogo sponsorSkipObject"/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<span id={"sponsorSkipMessage" + this.idSuffix}
|
<span id={"sponsorSkipMessage" + this.idSuffix}
|
||||||
|
|||||||
@@ -177,7 +177,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NoticeComponent noticeTitle={this.state.noticeTitle}
|
<NoticeComponent
|
||||||
|
noticeTitle={this.state.noticeTitle}
|
||||||
amountOfPreviousNotices={this.amountOfPreviousNotices}
|
amountOfPreviousNotices={this.amountOfPreviousNotices}
|
||||||
showInSecondSlot={this.showInSecondSlot}
|
showInSecondSlot={this.showInSecondSlot}
|
||||||
idSuffix={this.idSuffix}
|
idSuffix={this.idSuffix}
|
||||||
@@ -191,6 +192,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
ref={this.noticeRef}
|
ref={this.noticeRef}
|
||||||
closeListener={() => this.closeListener()}
|
closeListener={() => this.closeListener()}
|
||||||
smaller={this.state.smaller}
|
smaller={this.state.smaller}
|
||||||
|
logoFill={Config.config.barTypes[this.segments[0].category].color}
|
||||||
limitWidth={true}
|
limitWidth={true}
|
||||||
firstColumn={firstColumn}
|
firstColumn={firstColumn}
|
||||||
bottomRow={[...this.getMessageBoxes(), ...this.getBottomRow() ]}
|
bottomRow={[...this.getMessageBoxes(), ...this.getBottomRow() ]}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ interface SBConfig {
|
|||||||
allowScrollingToEdit: boolean;
|
allowScrollingToEdit: boolean;
|
||||||
deArrowInstalled: boolean;
|
deArrowInstalled: boolean;
|
||||||
showDeArrowPromotion: boolean;
|
showDeArrowPromotion: boolean;
|
||||||
showZoomToFillError: boolean;
|
showZoomToFillError2: boolean;
|
||||||
|
|
||||||
// Used to cache calculated text color info
|
// Used to cache calculated text color info
|
||||||
categoryPillColors: {
|
categoryPillColors: {
|
||||||
@@ -148,6 +148,10 @@ class ConfigClass extends ProtoConfig<SBConfig, SBStorage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function migrateOldSyncFormats(config: SBConfig) {
|
function migrateOldSyncFormats(config: SBConfig) {
|
||||||
|
if (config["showZoomToFillError"]) {
|
||||||
|
chrome.storage.sync.remove("showZoomToFillError");
|
||||||
|
}
|
||||||
|
|
||||||
if (!config["chapterCategoryAdded"]) {
|
if (!config["chapterCategoryAdded"]) {
|
||||||
config["chapterCategoryAdded"] = true;
|
config["chapterCategoryAdded"] = true;
|
||||||
|
|
||||||
@@ -312,7 +316,7 @@ const syncDefaults = {
|
|||||||
allowScrollingToEdit: true,
|
allowScrollingToEdit: true,
|
||||||
deArrowInstalled: false,
|
deArrowInstalled: false,
|
||||||
showDeArrowPromotion: true,
|
showDeArrowPromotion: true,
|
||||||
showZoomToFillError: true,
|
showZoomToFillError2: true,
|
||||||
|
|
||||||
categoryPillColors: {},
|
categoryPillColors: {},
|
||||||
|
|
||||||
|
|||||||
136
src/content.ts
136
src/content.ts
@@ -24,7 +24,7 @@ import SubmissionNotice from "./render/SubmissionNotice";
|
|||||||
import { Message, MessageResponse, VoteResponse } from "./messageTypes";
|
import { Message, MessageResponse, VoteResponse } from "./messageTypes";
|
||||||
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
|
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
|
||||||
import { getStartTimeFromUrl } from "./utils/urlParser";
|
import { getStartTimeFromUrl } from "./utils/urlParser";
|
||||||
import { getControls, getExistingChapters, getHashParams, isVisible } from "./utils/pageUtils";
|
import { getControls, getExistingChapters, getHashParams, isPlayingPlaylist, isVisible } from "./utils/pageUtils";
|
||||||
import { CategoryPill } from "./render/CategoryPill";
|
import { CategoryPill } from "./render/CategoryPill";
|
||||||
import { AnimationUtils } from "./utils/animationUtils";
|
import { AnimationUtils } from "./utils/animationUtils";
|
||||||
import { GenericUtils } from "./utils/genericUtils";
|
import { GenericUtils } from "./utils/genericUtils";
|
||||||
@@ -45,6 +45,10 @@ import * as documentScript from "../dist/js/document.js";
|
|||||||
import { Tooltip } from "./render/Tooltip";
|
import { Tooltip } from "./render/Tooltip";
|
||||||
import { isDeArrowInstalled } from "./utils/crossExtension";
|
import { isDeArrowInstalled } from "./utils/crossExtension";
|
||||||
import { runCompatibilityChecks } from "./utils/compatibility";
|
import { runCompatibilityChecks } from "./utils/compatibility";
|
||||||
|
import { cleanPage } from "./utils/pageCleaner";
|
||||||
|
import { addCleanupListener } from "./maze-utils/cleanup";
|
||||||
|
|
||||||
|
cleanPage();
|
||||||
|
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
@@ -473,6 +477,8 @@ function videoIDChange(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleMobileControlsMutations(): void {
|
function handleMobileControlsMutations(): void {
|
||||||
|
if (!chrome.runtime?.id) return;
|
||||||
|
|
||||||
updateVisibilityOfPlayerControlsButton();
|
updateVisibilityOfPlayerControlsButton();
|
||||||
|
|
||||||
skipButtonControlBar?.updateMobileControls();
|
skipButtonControlBar?.updateMobileControls();
|
||||||
@@ -703,7 +709,7 @@ async function startSponsorSchedule(includeIntersectingSegments = false, current
|
|||||||
|
|
||||||
// Don't pretend to be earlier than we are, could result in loops
|
// Don't pretend to be earlier than we are, could result in loops
|
||||||
if (forcedSkipTime !== null && forceVideoTime > forcedSkipTime) {
|
if (forcedSkipTime !== null && forceVideoTime > forcedSkipTime) {
|
||||||
forcedSkipTime = null;
|
forcedSkipTime = forceVideoTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
startSponsorSchedule(forcedIncludeIntersectingSegments, forcedSkipTime, forcedIncludeNonIntersectingSegments);
|
startSponsorSchedule(forcedIncludeIntersectingSegments, forcedSkipTime, forcedIncludeNonIntersectingSegments);
|
||||||
@@ -812,18 +818,26 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let setupVideoListenersFirstTime = true;
|
||||||
function setupVideoListeners() {
|
function setupVideoListeners() {
|
||||||
//wait until it is loaded
|
//wait until it is loaded
|
||||||
getVideo().addEventListener('loadstart', videoOnReadyListener)
|
getVideo().addEventListener('loadstart', videoOnReadyListener)
|
||||||
getVideo().addEventListener('durationchange', durationChangeListener);
|
getVideo().addEventListener('durationchange', durationChangeListener);
|
||||||
|
|
||||||
|
if (setupVideoListenersFirstTime) {
|
||||||
|
addCleanupListener(() => {
|
||||||
|
getVideo().removeEventListener('loadstart', videoOnReadyListener);
|
||||||
|
getVideo().removeEventListener('durationchange', durationChangeListener);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!Config.config.disableSkipping) {
|
if (!Config.config.disableSkipping) {
|
||||||
switchingVideos = false;
|
switchingVideos = false;
|
||||||
|
|
||||||
let startedWaiting = false;
|
let startedWaiting = false;
|
||||||
let lastPausedAtZero = true;
|
let lastPausedAtZero = true;
|
||||||
|
|
||||||
getVideo().addEventListener('play', () => {
|
const playListener = () => {
|
||||||
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
// If it is not the first event, then the only way to get to 0 is if there is a seek event
|
||||||
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
// This check makes sure that changing the video resolution doesn't cause the extension to think it
|
||||||
// gone back to the begining
|
// gone back to the begining
|
||||||
@@ -854,8 +868,10 @@ function setupVideoListeners() {
|
|||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
};
|
||||||
getVideo().addEventListener('playing', () => {
|
getVideo().addEventListener('play', playListener);
|
||||||
|
|
||||||
|
const playingListener = () => {
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
lastPausedAtZero = false;
|
lastPausedAtZero = false;
|
||||||
|
|
||||||
@@ -881,8 +897,10 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
getVideo().addEventListener('seeking', () => {
|
getVideo().addEventListener('playing', playingListener);
|
||||||
|
|
||||||
|
const seekingListener = () => {
|
||||||
lastKnownVideoTime.fromPause = false;
|
lastKnownVideoTime.fromPause = false;
|
||||||
|
|
||||||
if (!getVideo().paused){
|
if (!getVideo().paused){
|
||||||
@@ -906,20 +924,19 @@ function setupVideoListeners() {
|
|||||||
lastPausedAtZero = true;
|
lastPausedAtZero = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
getVideo().addEventListener('ratechange', () => {
|
getVideo().addEventListener('seeking', seekingListener);
|
||||||
|
|
||||||
|
const rateChangeListener = () => {
|
||||||
updateVirtualTime();
|
updateVirtualTime();
|
||||||
clearWaitingTime();
|
clearWaitingTime();
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
});
|
};
|
||||||
|
getVideo().addEventListener('ratechange', () => rateChangeListener);
|
||||||
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
|
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
|
||||||
getVideo().addEventListener('videoSpeed_ratechange', () => {
|
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
|
||||||
updateVirtualTime();
|
|
||||||
clearWaitingTime();
|
|
||||||
|
|
||||||
startSponsorSchedule();
|
|
||||||
});
|
|
||||||
const stoppedPlayback = () => {
|
const stoppedPlayback = () => {
|
||||||
// Reset lastCheckVideoTime
|
// Reset lastCheckVideoTime
|
||||||
lastCheckVideoTime = -1;
|
lastCheckVideoTime = -1;
|
||||||
@@ -931,20 +948,36 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
cancelSponsorSchedule();
|
cancelSponsorSchedule();
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('pause', () => {
|
const pauseListener = () => {
|
||||||
lastKnownVideoTime.fromPause = true;
|
lastKnownVideoTime.fromPause = true;
|
||||||
|
|
||||||
stoppedPlayback();
|
stoppedPlayback();
|
||||||
});
|
};
|
||||||
getVideo().addEventListener('waiting', () => {
|
getVideo().addEventListener('pause', pauseListener);
|
||||||
|
const waitingListener = () => {
|
||||||
logDebug("[SB] Not skipping due to buffering");
|
logDebug("[SB] Not skipping due to buffering");
|
||||||
startedWaiting = true;
|
startedWaiting = true;
|
||||||
|
|
||||||
stoppedPlayback();
|
stoppedPlayback();
|
||||||
});
|
};
|
||||||
|
getVideo().addEventListener('waiting', waitingListener);
|
||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
|
|
||||||
|
if (setupVideoListenersFirstTime) {
|
||||||
|
addCleanupListener(() => {
|
||||||
|
getVideo().removeEventListener('play', playListener);
|
||||||
|
getVideo().removeEventListener('playing', playingListener);
|
||||||
|
getVideo().removeEventListener('seeking', seekingListener);
|
||||||
|
getVideo().removeEventListener('ratechange', rateChangeListener);
|
||||||
|
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener);
|
||||||
|
getVideo().removeEventListener('pause', pauseListener);
|
||||||
|
getVideo().removeEventListener('waiting', waitingListener);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupVideoListenersFirstTime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVirtualTime() {
|
function updateVirtualTime() {
|
||||||
@@ -1356,18 +1389,20 @@ async function channelIDChange(channelIDInfo: ChannelIDInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function videoElementChange(newVideo: boolean): void {
|
function videoElementChange(newVideo: boolean): void {
|
||||||
if (newVideo) {
|
waitFor(() => Config.isReady()).then(() => {
|
||||||
setupVideoListeners();
|
if (newVideo) {
|
||||||
setupSkipButtonControlBar();
|
setupVideoListeners();
|
||||||
setupCategoryPill();
|
setupSkipButtonControlBar();
|
||||||
}
|
setupCategoryPill();
|
||||||
|
}
|
||||||
checkPreviewbarState();
|
|
||||||
|
checkPreviewbarState();
|
||||||
// Incase the page is still transitioning, check again in a few seconds
|
|
||||||
setTimeout(checkPreviewbarState, 100);
|
// Incase the page is still transitioning, check again in a few seconds
|
||||||
setTimeout(checkPreviewbarState, 1000);
|
setTimeout(checkPreviewbarState, 100);
|
||||||
setTimeout(checkPreviewbarState, 5000);
|
setTimeout(checkPreviewbarState, 1000);
|
||||||
|
setTimeout(checkPreviewbarState, 5000);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPreviewbarState(): void {
|
function checkPreviewbarState(): void {
|
||||||
@@ -1587,8 +1622,10 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
|
|||||||
// for some reason you also can't skip to 1 second before the end
|
// for some reason you also can't skip to 1 second before the end
|
||||||
if (v.loop && v.duration > 1 && skipTime[1] >= v.duration - 1) {
|
if (v.loop && v.duration > 1 && skipTime[1] >= v.duration - 1) {
|
||||||
v.currentTime = 0;
|
v.currentTime = 0;
|
||||||
} else if (navigator.vendor === "Apple Computer, Inc." && v.duration > 1 && skipTime[1] >= v.duration) {
|
} else if (v.duration > 1 && skipTime[1] >= v.duration
|
||||||
|
&& (navigator.vendor === "Apple Computer, Inc." || isPlayingPlaylist())) {
|
||||||
// MacOS will loop otherwise #1027
|
// MacOS will loop otherwise #1027
|
||||||
|
// Sometimes playlists loop too #1804
|
||||||
v.currentTime = v.duration - 0.001;
|
v.currentTime = v.duration - 0.001;
|
||||||
} else {
|
} else {
|
||||||
if (inMuteSegment(skipTime[1], true)) {
|
if (inMuteSegment(skipTime[1], true)) {
|
||||||
@@ -1619,9 +1656,10 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
|
|||||||
beep.play();
|
beep.play();
|
||||||
beep.addEventListener("ended", () => {
|
beep.addEventListener("ended", () => {
|
||||||
navigator.mediaSession.metadata = null;
|
navigator.mediaSession.metadata = null;
|
||||||
setTimeout(() =>
|
setTimeout(() => {
|
||||||
navigator.mediaSession.metadata = oldMetadata
|
navigator.mediaSession.metadata = oldMetadata;
|
||||||
);
|
beep.remove();
|
||||||
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2331,11 +2369,21 @@ function previousChapter(): void {
|
|||||||
function addHotkeyListener(): void {
|
function addHotkeyListener(): void {
|
||||||
document.addEventListener("keydown", hotkeyListener);
|
document.addEventListener("keydown", hotkeyListener);
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
const onLoad = () => {
|
||||||
// Allow us to stop propagation to YouTube by being deeper
|
// Allow us to stop propagation to YouTube by being deeper
|
||||||
document.removeEventListener("keydown", hotkeyListener);
|
document.removeEventListener("keydown", hotkeyListener);
|
||||||
document.body.addEventListener("keydown", hotkeyListener);
|
document.body.addEventListener("keydown", hotkeyListener);
|
||||||
});
|
|
||||||
|
addCleanupListener(() => {
|
||||||
|
document.body.removeEventListener("keydown", hotkeyListener);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
onLoad();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", onLoad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hotkeyListener(e: KeyboardEvent): void {
|
function hotkeyListener(e: KeyboardEvent): void {
|
||||||
@@ -2392,7 +2440,7 @@ function hotkeyListener(e: KeyboardEvent): void {
|
|||||||
*/
|
*/
|
||||||
function addCSS() {
|
function addCSS() {
|
||||||
if (!isFirefoxOrSafari() && Config.config.invidiousInstances.includes(new URL(document.URL).hostname)) {
|
if (!isFirefoxOrSafari() && Config.config.invidiousInstances.includes(new URL(document.URL).hostname)) {
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
const onLoad = () => {
|
||||||
const head = document.getElementsByTagName("head")[0];
|
const head = document.getElementsByTagName("head")[0];
|
||||||
|
|
||||||
for (const file of utils.css) {
|
for (const file of utils.css) {
|
||||||
@@ -2404,7 +2452,13 @@ function addCSS() {
|
|||||||
|
|
||||||
head.appendChild(fileref);
|
head.appendChild(fileref);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
onLoad();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", onLoad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2489,7 +2543,9 @@ function setCategoryColorCSSVariables() {
|
|||||||
if (!styleContainer) {
|
if (!styleContainer) {
|
||||||
styleContainer = document.createElement("style");
|
styleContainer = document.createElement("style");
|
||||||
styleContainer.id = "sbCategoryColorStyle";
|
styleContainer.id = "sbCategoryColorStyle";
|
||||||
document.head.appendChild(styleContainer)
|
|
||||||
|
const head = (document.head || document.documentElement);
|
||||||
|
head.appendChild(styleContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
let css = ":root {"
|
let css = ":root {"
|
||||||
|
|||||||
@@ -4,7 +4,11 @@ import { showDonationLink } from "./utils/configUtils";
|
|||||||
|
|
||||||
import { waitFor } from "./maze-utils";
|
import { waitFor } from "./maze-utils";
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', init);
|
if (document.readyState === "complete") {
|
||||||
|
init();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
localizeHtmlPage();
|
localizeHtmlPage();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
|
|||||||
import { normalizeChapterName } from "../utils/exporter";
|
import { normalizeChapterName } from "../utils/exporter";
|
||||||
import { getFormattedTimeToSeconds } from "../maze-utils/formating";
|
import { getFormattedTimeToSeconds } from "../maze-utils/formating";
|
||||||
import { findValidElement } from "../maze-utils/dom";
|
import { findValidElement } from "../maze-utils/dom";
|
||||||
|
import { addCleanupListener } from "../maze-utils/cleanup";
|
||||||
|
|
||||||
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
||||||
const MIN_CHAPTER_SIZE = 0.003;
|
const MIN_CHAPTER_SIZE = 0.003;
|
||||||
@@ -201,6 +202,10 @@ class PreviewBar {
|
|||||||
childList: true,
|
childList: true,
|
||||||
subtree: true,
|
subtree: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addCleanupListener(() => {
|
||||||
|
observer.disconnect();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTooltipTitle(segment: PreviewBarSegment, tooltip: HTMLElement): void {
|
private setTooltipTitle(segment: PreviewBarSegment, tooltip: HTMLElement): void {
|
||||||
@@ -626,6 +631,11 @@ class PreviewBar {
|
|||||||
childListObserver.observe(this.originalChapterBar, {
|
childListObserver.observe(this.originalChapterBar, {
|
||||||
childList: true
|
childList: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addCleanupListener(() => {
|
||||||
|
attributeObserver.disconnect();
|
||||||
|
childListObserver.disconnect();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateChapterAllMutation(originalChapterBar: HTMLElement, progressBar: HTMLElement, firstUpdate = false): void {
|
private updateChapterAllMutation(originalChapterBar: HTMLElement, progressBar: HTMLElement, firstUpdate = false): void {
|
||||||
@@ -774,10 +784,11 @@ class PreviewBar {
|
|||||||
if (!Config.config.showSegmentNameInChapterBar
|
if (!Config.config.showSegmentNameInChapterBar
|
||||||
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
|
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
|
||||||
const chaptersContainer = this.getChaptersContainer();
|
const chaptersContainer = this.getChaptersContainer();
|
||||||
const chapterButton = this.getChapterButton(chaptersContainer);
|
chaptersContainer.querySelector(".sponsorChapterText")?.remove();
|
||||||
if (chapterButton && chapterButton.classList.contains("ytp-chapter-container-disabled")) {
|
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
|
||||||
chaptersContainer.style.display = "none";
|
|
||||||
}
|
chapterTitle.style.removeProperty("display");
|
||||||
|
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -802,7 +813,7 @@ class PreviewBar {
|
|||||||
|
|
||||||
if (chaptersContainer) {
|
if (chaptersContainer) {
|
||||||
if (segments.length > 0) {
|
if (segments.length > 0) {
|
||||||
chaptersContainer.style.removeProperty("display");
|
chaptersContainer.classList.add("sponsorblock-chapter-visible");
|
||||||
|
|
||||||
const chosenSegment = segments.sort((a, b) => {
|
const chosenSegment = segments.sort((a, b) => {
|
||||||
if (a.actionType === ActionType.Chapter && b.actionType !== ActionType.Chapter) {
|
if (a.actionType === ActionType.Chapter && b.actionType !== ActionType.Chapter) {
|
||||||
@@ -819,11 +830,11 @@ class PreviewBar {
|
|||||||
chapterButton.disabled = false;
|
chapterButton.disabled = false;
|
||||||
|
|
||||||
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
|
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
|
||||||
chapterTitle.innerText = "";
|
chapterTitle.style.display = "none";
|
||||||
|
|
||||||
const chapterCustomText = (chapterTitle.querySelector(".sponsorChapterText") || (() => {
|
const chapterCustomText = (chapterTitle.parentElement.querySelector(".sponsorChapterText") || (() => {
|
||||||
const elem = document.createElement("div");
|
const elem = document.createElement("div");
|
||||||
chapterTitle.appendChild(elem);
|
chapterTitle.parentElement.insertBefore(elem, chapterTitle);
|
||||||
elem.classList.add("sponsorChapterText");
|
elem.classList.add("sponsorChapterText");
|
||||||
return elem;
|
return elem;
|
||||||
})()) as HTMLDivElement;
|
})()) as HTMLDivElement;
|
||||||
@@ -854,11 +865,10 @@ class PreviewBar {
|
|||||||
} else {
|
} else {
|
||||||
chaptersContainer.querySelector(".sponsorChapterText")?.remove();
|
chaptersContainer.querySelector(".sponsorChapterText")?.remove();
|
||||||
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
|
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
|
||||||
if (chapterTitle.innerText === "") {
|
|
||||||
chaptersContainer.style.display = "none";
|
chapterTitle.style.removeProperty("display");
|
||||||
} else {
|
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
|
||||||
chaptersContainer.style.removeProperty("display");
|
|
||||||
}
|
|
||||||
this.chapterVote.setVisibility(false);
|
this.chapterVote.setVisibility(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ let embed = false;
|
|||||||
const categoryChoosers: CategoryChooser[] = [];
|
const categoryChoosers: CategoryChooser[] = [];
|
||||||
const unsubmittedVideos: UnsubmittedVideos[] = [];
|
const unsubmittedVideos: UnsubmittedVideos[] = [];
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', init);
|
if (document.readyState === "complete") {
|
||||||
|
init();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
localizeHtmlPage();
|
localizeHtmlPage();
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ const utils = new Utils();
|
|||||||
// Probably due to cyclic dependencies
|
// Probably due to cyclic dependencies
|
||||||
Config.config;
|
Config.config;
|
||||||
|
|
||||||
window.addEventListener('DOMContentLoaded', init);
|
if (document.readyState === "complete") {
|
||||||
|
init();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
localizeHtmlPage();
|
localizeHtmlPage();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Category, SegmentUUID, SponsorTime } from "../types";
|
|||||||
import { Tooltip } from "./Tooltip";
|
import { Tooltip } from "./Tooltip";
|
||||||
import { waitFor } from "../maze-utils";
|
import { waitFor } from "../maze-utils";
|
||||||
import { getYouTubeTitleNode } from "../maze-utils/elements";
|
import { getYouTubeTitleNode } from "../maze-utils/elements";
|
||||||
|
import { addCleanupListener } from "../maze-utils/cleanup";
|
||||||
|
|
||||||
const id = "categoryPill";
|
const id = "categoryPill";
|
||||||
|
|
||||||
@@ -24,6 +25,12 @@ export class CategoryPill {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.ref = React.createRef();
|
this.ref = React.createRef();
|
||||||
|
|
||||||
|
addCleanupListener(() => {
|
||||||
|
if (this.mutationObserver) {
|
||||||
|
this.mutationObserver.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async attachToPage(onMobileYouTube: boolean, onInvidious: boolean,
|
async attachToPage(onMobileYouTube: boolean, onInvidious: boolean,
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export default class GenericNotice {
|
|||||||
const referenceNode = options.referenceNode ?? utils.findReferenceNode();
|
const referenceNode = options.referenceNode ?? utils.findReferenceNode();
|
||||||
|
|
||||||
this.noticeElement = document.createElement("div");
|
this.noticeElement = document.createElement("div");
|
||||||
|
this.noticeElement.className = "sponsorSkipNoticeContainer";
|
||||||
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
||||||
|
|
||||||
referenceNode.prepend(this.noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class SkipNotice {
|
|||||||
idSuffix += amountOfPreviousNotices;
|
idSuffix += amountOfPreviousNotices;
|
||||||
|
|
||||||
this.noticeElement = document.createElement("div");
|
this.noticeElement = document.createElement("div");
|
||||||
|
this.noticeElement.className = "sponsorSkipNoticeContainer";
|
||||||
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
|
||||||
|
|
||||||
referenceNode.prepend(this.noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|||||||
55
src/svg-icons/sb_svg.tsx
Normal file
55
src/svg-icons/sb_svg.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export interface SbIconProps {
|
||||||
|
id?: string;
|
||||||
|
fill?: string;
|
||||||
|
className?: string;
|
||||||
|
width?: string;
|
||||||
|
height?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SbSvg({
|
||||||
|
id = "",
|
||||||
|
fill = "#ff0000",
|
||||||
|
className = "",
|
||||||
|
onClick
|
||||||
|
}: SbIconProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 565.15 568"
|
||||||
|
id={id}
|
||||||
|
className={className}
|
||||||
|
onClick={() => onClick?.() } >
|
||||||
|
<g
|
||||||
|
id="Layer_2"
|
||||||
|
data-name="Layer 2">
|
||||||
|
<g
|
||||||
|
id="Layer_1-2"
|
||||||
|
data-name="Layer 1"
|
||||||
|
style={{
|
||||||
|
fill
|
||||||
|
}}>
|
||||||
|
<path
|
||||||
|
d="M282.58,568a65,65,0,0,1-34.14-9.66C95.41,463.94,2.54,300.46,0,121A64.91,64.91,0,0,1,34,62.91a522.56,522.56,0,0,1,497.16,0,64.91,64.91,0,0,1,34,58.12c-2.53,179.43-95.4,342.91-248.42,437.3A65,65,0,0,1,282.58,568Zm0-548.31A502.24,502.24,0,0,0,43.4,80.22a45.27,45.27,0,0,0-23.7,40.53c2.44,172.67,91.81,330,239.07,420.83a46.19,46.19,0,0,0,47.61,0C453.64,450.73,543,293.42,545.45,120.75a45.26,45.26,0,0,0-23.7-40.54A502.26,502.26,0,0,0,282.58,19.69Z"
|
||||||
|
id="path8"
|
||||||
|
style={{
|
||||||
|
fill
|
||||||
|
}} />
|
||||||
|
<path
|
||||||
|
style={{
|
||||||
|
fill
|
||||||
|
}}
|
||||||
|
d="M 284.70508 42.693359 A 479.9 479.9 0 0 0 54.369141 100.41992 A 22.53 22.53 0 0 0 42.669922 120.41992 C 45.069922 290.25992 135.67008 438.63977 270.83008 522.00977 A 22.48 22.48 0 0 0 294.32031 522.00977 C 429.48031 438.63977 520.08047 290.25992 522.48047 120.41992 A 22.53 22.53 0 0 0 510.7793 100.41992 A 479.9 479.9 0 0 0 284.70508 42.693359 z M 220.41016 145.74023 L 411.2793 255.93945 L 220.41016 366.14062 L 220.41016 145.74023 z "
|
||||||
|
id="path10" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<polygon style={{
|
||||||
|
fill: "#fff"
|
||||||
|
}}
|
||||||
|
points="411.28 255.94 220.41 145.74 220.41 366.14 411.28 255.94"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
|
|
||||||
export function runCompatibilityChecks() {
|
export function runCompatibilityChecks() {
|
||||||
if (Config.config.showZoomToFillError) {
|
if (Config.config.showZoomToFillError2 && document.URL.includes("watch?v=")) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const zoomToFill = document.querySelector(".zoomtofillBtn");
|
const zoomToFill = document.querySelector(".zoomtofillBtn");
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ export function runCompatibilityChecks() {
|
|||||||
alert(chrome.i18n.getMessage("zoomToFillUnsupported"));
|
alert(chrome.i18n.getMessage("zoomToFillUnsupported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.config.showZoomToFillError = false;
|
Config.config.showZoomToFillError2 = false;
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
src/utils/pageCleaner.ts
Normal file
8
src/utils/pageCleaner.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
export function cleanPage() {
|
||||||
|
// For live-updates
|
||||||
|
if (document.readyState === "complete") {
|
||||||
|
for (const element of document.querySelectorAll("#categoryPillParent, .playerButton, .sponsorThumbnailLabel, #submissionNoticeContainer, .sponsorSkipNoticeContainer, #sponsorBlockPopupContainer, .skipButtonControlBarContainer, #previewbar, .sponsorBlockChapterBar")) {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,4 +93,8 @@ export function getExistingChapters(currentVideoID: VideoID, duration: number):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return chapters;
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPlayingPlaylist() {
|
||||||
|
return !!document.URL.includes("&list=");
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user