Compare commits

...

50 Commits

Author SHA1 Message Date
Ajay
a3f8419c49 update translations 2023-09-23 12:20:05 -04:00
Ajay
dde443ccec bump version 2023-09-23 12:18:32 -04:00
Ajay
01b1380b78 Update sponsorblock ui to tip 2023-09-23 12:17:46 -04:00
Ajay
c51b18465e Fix slightly different tv url format that appears on Firefox 2023-09-18 14:17:46 -04:00
Ajay
ad9888cf52 bump version 2023-09-17 17:31:36 -04:00
Ajay
7856791f90 update translations 2023-09-17 17:31:22 -04:00
Ajay
273ee63ec7 Prevent refreshes from triggering too often
Fixes #1838
2023-09-17 14:06:24 -04:00
Ajay
be36583aee Rename donate button 2023-09-17 13:11:52 -04:00
Ajay
433bbbf904 Remove popup css from content as iframes are used now
Fixes #1774
2023-09-17 12:46:25 -04:00
Ajay
6c2ee76198 Add start button to submission menu 2023-09-17 12:29:42 -04:00
Ajay
42f59898f3 Add end button for all segments 2023-09-17 12:12:00 -04:00
Ajay
8ab126f502 Highlight segment on hover 2023-09-17 12:06:33 -04:00
Ajay
4954abf9e3 Add extension icon default location on Firefox 2023-09-13 20:17:44 -04:00
Ajay
30a21d5ff5 Actually stop spacebar in chapters box from pausing video 2023-09-13 11:40:56 -04:00
Ajay
d1b2def47c bump version 2023-09-06 11:45:08 -04:00
Ajay Ramachandran
48cdabe2a5 Merge pull request #1534 from EthanBnntt/EthanBnntt-patch-1
Reduced execution time of hexToRgb function by ~70%
2023-09-05 01:28:23 -04:00
Ajay Ramachandran
bc2db0cf2c Merge branch 'master' into EthanBnntt-patch-1 2023-09-05 01:28:15 -04:00
Ajay Ramachandran
843ef37dcd Merge pull request #1814 from ajayyy/ci/update_invidious_list
Update Invidious List
2023-09-05 01:25:54 -04:00
Ajay
ed260a0667 Fix clicking a video from homepage on mobile YouTube
Fixes https://github.com/ajayyy/SponsorBlock/issues/1849
2023-09-05 01:19:50 -04:00
Ajay
2e131c2a95 Stop spacebar in chapters box from pausing video 2023-09-04 02:37:19 -04:00
Ajay
f5e884b6aa Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2023-09-03 21:29:02 -04:00
Ajay
a9929d0c93 Adjust dearrow message params 2023-09-03 21:29:00 -04:00
github-actions[bot]
3fb43d1c0e Update Invidious List 2023-09-01 00:19:28 +00:00
Ajay Ramachandran
a1b2855538 Merge pull request #1842 from ajayyy/ci/oss_attribution
Update OSS Attribution
2023-08-25 21:49:27 -04:00
github-actions[bot]
07236baed5 Update OSS Attribution 2023-08-26 01:30:48 +00:00
Ajay
f991435857 Switch back to upstream content-scripts-register-polyfill 2023-08-25 21:29:39 -04:00
Ajay
faa3259165 Fix invidious support on Safari for iOS 2023-08-25 20:22:58 -04:00
Ajay
c96bafb6f7 bump version 2023-08-25 18:39:52 -04:00
Ajay
9b7680f0e6 Fix invidious support on Safari 2023-08-25 16:38:50 -04:00
Ajay
16e01b7494 Fix comment 2023-08-25 16:34:08 -04:00
Ajay
6cd697dc32 bump version 2023-08-25 16:03:33 -04:00
Ajay
9946bd1af2 Use chromep in another spot 2023-08-25 16:03:17 -04:00
Ajay
3b06d72270 Fix invidious support of Firefox 2023-08-25 16:01:11 -04:00
Ajay
4bd0556464 Remove webnavigation optional permission from firefox 2023-08-23 22:44:41 -04:00
Ajay
7e12a914d5 bump translations 2023-08-22 23:29:01 -04:00
Ajay
25eaf4fa20 bump version 2023-08-22 23:26:21 -04:00
Ajay
b3efa1f787 Add compatibility with video speed controller extension 2023-08-22 15:23:04 -04:00
Ajay
9a18e70e34 Fix rate change listener not set up properly
Fixes #1820
2023-08-22 15:22:03 -04:00
Ajay
64ece9cb73 Fix chrome api being used in tests 2023-08-14 11:49:51 -04:00
Ajay
66c974b011 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2023-08-14 09:28:58 -04:00
Ajay
d8cc93c841 Fix for Firefox not offering promise based APIs in mv2 2023-08-14 09:28:56 -04:00
Ajay Ramachandran
de22accfda Merge pull request #1828 from mchangrh/contributing-translations
add translations to contributing
2023-08-13 15:13:24 -04:00
Michael C
e5b0b60dde add translations to contributing 2023-08-13 15:05:08 -04:00
Ajay Ramachandran
32d98e6544 Add more info about testing on android 2023-08-11 22:38:38 -04:00
Ajay
3dde05eda2 Add more theme icons for browser popup 2023-08-11 21:33:38 -04:00
Ajay
6aeefaae64 Don't reregister contentscripts if not necessary 2023-08-11 12:39:48 -04:00
Ajay
93d695e6c2 Fix error sending messages to closed popups 2023-08-11 12:15:05 -04:00
Ajay
160924feee Update maze utils to improve performance on Invidious, and fix preview bar error
thanks @raphj
2023-08-11 12:08:19 -04:00
Ajay
e3f3ed20e6 Enable non persistent background page on Firefox 2023-08-11 11:39:06 -04:00
Bennett
edaed61612 Reduced execution time of hexToRgb function by ~70%
Coded to use less regex.
On average, "indexOf" performs better than "parseInt."
2022-10-13 14:48:17 -04:00
24 changed files with 242 additions and 116 deletions

View File

@@ -1,5 +1,8 @@
If you make any contributions to SponsorBlock after this file was created, you are agreeing that any code you have contributed will be licensed under LGPL-3.0 or later. If you make any contributions to SponsorBlock after this file was created, you are agreeing that any code you have contributed will be licensed under LGPL-3.0 or later.
# Translations
https://crowdin.com/project/sponsorblock
# Building # Building
## Building locally ## Building locally
0. You must have [Node.js 16 or later](https://nodejs.org/) and npm installed. Works best on Linux 0. You must have [Node.js 16 or later](https://nodejs.org/) and npm installed. Works best on Linux
@@ -24,5 +27,5 @@ Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the
Known chromium bug: Extension is not loaded properly on first start. Visit `chrome://extensions/` and reload the extension. Known chromium bug: Extension is not loaded properly on first start. Visit `chrome://extensions/` and reload the extension.
For Firefox for Android, use `npm run dev:firefox-android -- --adb-device <ip-address of the device>`. See the [Firefox documentation](https://extensionworkshop.com/documentation/develop/developing-extensions-for-firefox-for-android/#debug-your-extension) for more information. For Firefox for Android, use `npm run dev:firefox-android -- --adb-device <ip-address of the device>`. See the [Firefox documentation](https://extensionworkshop.com/documentation/develop/developing-extensions-for-firefox-for-android/#debug-your-extension) for more information. You may need to edit package.json and add the parameters directly there.

View File

@@ -1 +1 @@
["www.youtubekids.com","inv.bp.projectsegfau.lt","inv.tux.pizza","inv.zzls.xyz","invidious.0011.lt","invidious.lunar.icu","invidious.privacydev.net","invidious.tiekoetter.com","iv.ggtyler.dev","iv.melmac.space","vid.priv.au","vid.puffyan.us","yewtu.be","yt.artemislena.eu"] ["www.youtubekids.com","inv.bp.projectsegfau.lt","inv.citw.lgbt","inv.in.projectsegfau.lt","inv.makerlab.tech","inv.pistasjis.net","inv.tux.pizza","inv.zzls.xyz","invidious.0011.lt","invidious.io.lol","invidious.lunar.icu","invidious.no-logs.com","invidious.projectsegfau.lt","invidious.protokolla.fi","invidious.slipfox.xyz","invidious.tiekoetter.com","iv.ggtyler.dev","iv.melmac.space","iv.nboeck.de","onion.tube","vid.priv.au","vid.puffyan.us","yewtu.be","yt.artemislena.eu","yt.oelrichsgarcia.de"]

View File

@@ -1,6 +1,7 @@
{ {
"optional_permissions": [ "optional_permissions": [
"declarativeContent" "declarativeContent",
"webNavigation"
], ],
"background": { "background": {
"persistent": false "persistent": false

View File

@@ -3,5 +3,14 @@
"gecko": { "gecko": {
"id": "sponsorBlocker@ajay.app" "id": "sponsorBlocker@ajay.app"
} }
},
"background": {
"persistent": false
},
"permissions": [
"scripting"
],
"browser_action": {
"default_area": "navbar"
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "SponsorBlock", "short_name": "SponsorBlock",
"version": "5.4.15", "version": "5.4.21",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app", "homepage_url": "https://sponsor.ajay.app",
@@ -17,9 +17,7 @@
], ],
"css": [ "css": [
"content.css", "content.css",
"shared.css", "shared.css"
"./libs/Source+Sans+Pro.css",
"popup.css"
] ]
}], }],
"web_accessible_resources": [ "web_accessible_resources": [
@@ -84,8 +82,7 @@
"https://sponsor.ajay.app/*" "https://sponsor.ajay.app/*"
], ],
"optional_permissions": [ "optional_permissions": [
"*://*/*", "*://*/*"
"webNavigation"
], ],
"browser_action": { "browser_action": {
"default_title": "SponsorBlock", "default_title": "SponsorBlock",
@@ -116,6 +113,21 @@
"light": "icons/IconSponsorBlocker128px.png", "light": "icons/IconSponsorBlocker128px.png",
"dark": "icons/IconSponsorBlocker128px.png", "dark": "icons/IconSponsorBlocker128px.png",
"size": 128 "size": 128
},
{
"light": "icons/IconSponsorBlocker256px.png",
"dark": "icons/IconSponsorBlocker256px.png",
"size": 256
},
{
"light": "icons/IconSponsorBlocker512px.png",
"dark": "icons/IconSponsorBlocker512px.png",
"size": 512
},
{
"light": "icons/IconSponsorBlocker1024px.png",
"dark": "icons/IconSponsorBlocker1024px.png",
"size": 1024
} }
] ]
}, },

View File

@@ -1,5 +1,11 @@
{ {
"background": { "background": {
"persistent": false "persistent": false
} },
"permissions": [
"scripting"
],
"optional_permissions": [
"webNavigation"
]
} }

View File

@@ -62,7 +62,7 @@
"webext-content-scripts": { "webext-content-scripts": {
"ignore": false, "ignore": false,
"name": "webext-content-scripts", "name": "webext-content-scripts",
"version": "2.5.2", "version": "2.5.5",
"authors": "Federico Brigante <me@fregante.com> (https://fregante.com)", "authors": "Federico Brigante <me@fregante.com> (https://fregante.com)",
"url": "https://github.com/fregante/webext-content-scripts", "url": "https://github.com/fregante/webext-content-scripts",
"license": "MIT", "license": "MIT",
@@ -80,7 +80,7 @@
"webext-polyfill-kinda": { "webext-polyfill-kinda": {
"ignore": false, "ignore": false,
"name": "webext-polyfill-kinda", "name": "webext-polyfill-kinda",
"version": "1.0.0", "version": "1.0.2",
"authors": "Federico Brigante <me@fregante.com> (https://fregante.com)", "authors": "Federico Brigante <me@fregante.com> (https://fregante.com)",
"url": "https://github.com/fregante/webext-polyfill-kinda", "url": "https://github.com/fregante/webext-polyfill-kinda",
"license": "MIT", "license": "MIT",

33
package-lock.json generated
View File

@@ -12961,12 +12961,15 @@
} }
}, },
"node_modules/webext-content-scripts": { "node_modules/webext-content-scripts": {
"version": "2.5.2", "version": "2.5.5",
"resolved": "https://registry.npmjs.org/webext-content-scripts/-/webext-content-scripts-2.5.2.tgz", "resolved": "https://registry.npmjs.org/webext-content-scripts/-/webext-content-scripts-2.5.5.tgz",
"integrity": "sha512-N1Xq/E8dx0lVAOyPquuo+2Vj9Fx1GoqCFo79lWeJHbemaBJ53N3BHBmbJJYsQ8FOP1xiwN4bPRQY2dpSjHAD3Q==", "integrity": "sha512-CIq1LA/nHIXE43v8qlpqNPcbsSzGuQBkeykbqOWvKJ1Rx/q7zgdZsLgxwyoonWiQcJczslVmGWCfdBY04JwIyw==",
"dependencies": { "dependencies": {
"webext-patterns": "^1.3.0", "webext-patterns": "^1.3.0",
"webext-polyfill-kinda": "^1.0.0" "webext-polyfill-kinda": "^1.0.2"
},
"engines": {
"node": ">=16"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/fregante" "url": "https://github.com/sponsors/fregante"
@@ -12995,9 +12998,9 @@
} }
}, },
"node_modules/webext-polyfill-kinda": { "node_modules/webext-polyfill-kinda": {
"version": "1.0.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/webext-polyfill-kinda/-/webext-polyfill-kinda-1.0.0.tgz", "resolved": "https://registry.npmjs.org/webext-polyfill-kinda/-/webext-polyfill-kinda-1.0.2.tgz",
"integrity": "sha512-Py/d3w/bC0KntuO60ePSWHsdrebZ3uYBLeFUjyPkDV3yTEQib0MRFvPh57t8XjImu4ylBoEAsFjzh/r22UtxMw==", "integrity": "sha512-rqQUKeBTOicej0tjDJWDQlOTnDcm9yYJTzgI+7rMdyYV4QHmYMRm+yjkcVgECkg/Wu9MboZ4lYeBPdp1Ep9WgQ==",
"funding": { "funding": {
"url": "https://github.com/sponsors/fregante" "url": "https://github.com/sponsors/fregante"
} }
@@ -16739,7 +16742,7 @@
"resolved": "https://registry.npmjs.org/content-scripts-register-polyfill/-/content-scripts-register-polyfill-4.0.2.tgz", "resolved": "https://registry.npmjs.org/content-scripts-register-polyfill/-/content-scripts-register-polyfill-4.0.2.tgz",
"integrity": "sha512-8hDm+tu3BkxHZP7EUIIIo/495F6QNXF7cI9Lwr4PQaiohw2wWmi9k2SE4W4kNrAaLnFw6RZ2ev8EmrQb+sCoGQ==", "integrity": "sha512-8hDm+tu3BkxHZP7EUIIIo/495F6QNXF7cI9Lwr4PQaiohw2wWmi9k2SE4W4kNrAaLnFw6RZ2ev8EmrQb+sCoGQ==",
"requires": { "requires": {
"webext-content-scripts": "^2.5.2", "webext-content-scripts": "v2.5.5",
"webext-patterns": "^1.3.0", "webext-patterns": "^1.3.0",
"webext-polyfill-kinda": "^1.0.0" "webext-polyfill-kinda": "^1.0.0"
} }
@@ -23096,12 +23099,12 @@
"dev": true "dev": true
}, },
"webext-content-scripts": { "webext-content-scripts": {
"version": "2.5.2", "version": "2.5.5",
"resolved": "https://registry.npmjs.org/webext-content-scripts/-/webext-content-scripts-2.5.2.tgz", "resolved": "https://registry.npmjs.org/webext-content-scripts/-/webext-content-scripts-2.5.5.tgz",
"integrity": "sha512-N1Xq/E8dx0lVAOyPquuo+2Vj9Fx1GoqCFo79lWeJHbemaBJ53N3BHBmbJJYsQ8FOP1xiwN4bPRQY2dpSjHAD3Q==", "integrity": "sha512-CIq1LA/nHIXE43v8qlpqNPcbsSzGuQBkeykbqOWvKJ1Rx/q7zgdZsLgxwyoonWiQcJczslVmGWCfdBY04JwIyw==",
"requires": { "requires": {
"webext-patterns": "^1.3.0", "webext-patterns": "^1.3.0",
"webext-polyfill-kinda": "^1.0.0" "webext-polyfill-kinda": "^1.0.2"
} }
}, },
"webext-patterns": { "webext-patterns": {
@@ -23120,9 +23123,9 @@
} }
}, },
"webext-polyfill-kinda": { "webext-polyfill-kinda": {
"version": "1.0.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/webext-polyfill-kinda/-/webext-polyfill-kinda-1.0.0.tgz", "resolved": "https://registry.npmjs.org/webext-polyfill-kinda/-/webext-polyfill-kinda-1.0.2.tgz",
"integrity": "sha512-Py/d3w/bC0KntuO60ePSWHsdrebZ3uYBLeFUjyPkDV3yTEQib0MRFvPh57t8XjImu4ylBoEAsFjzh/r22UtxMw==" "integrity": "sha512-rqQUKeBTOicej0tjDJWDQlOTnDcm9yYJTzgI+7rMdyYV4QHmYMRm+yjkcVgECkg/Wu9MboZ4lYeBPdp1Ep9WgQ=="
}, },
"webidl-conversions": { "webidl-conversions": {
"version": "7.0.0", "version": "7.0.0",

View File

@@ -8,6 +8,11 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },
"overrides": {
"content-scripts-register-polyfill": {
"webext-content-scripts": "v2.5.5"
}
},
"devDependencies": { "devDependencies": {
"@types/chrome": "^0.0.220", "@types/chrome": "^0.0.220",
"@types/firefox-webext-browser": "^111.0.0", "@types/firefox-webext-browser": "^111.0.0",

View File

@@ -49,7 +49,13 @@ div:hover > #previewbar.sbNotInvidious {
} }
.previewbar.requiredSegment { .previewbar.requiredSegment {
transform: scaleY(3) transform: scaleY(3);
}
.previewbar.selectedSegment {
opacity: 1 !important;
z-index: 100;
transform: scaleY(1.5);
} }
/* Make sure settings are upfront */ /* Make sure settings are upfront */
@@ -243,11 +249,6 @@ div:hover > .sponsorBlockChapterBar {
border-collapse: unset; border-collapse: unset;
} }
.sponsorSkipNoticeParent {
min-width: 350px;
max-width: 50%;
}
.sponsorSkipNotice { .sponsorSkipNotice {
width: 100%; width: 100%;
} }
@@ -570,8 +571,8 @@ div:hover > .sponsorBlockChapterBar {
.sponsorTimeEditButton { .sponsorTimeEditButton {
text-decoration: underline; text-decoration: underline;
margin-left: 20px; margin-left: 13px;
margin-right: 20px; margin-right: 13px;
font-size: 13px; font-size: 13px;

View File

@@ -164,7 +164,7 @@ SOFTWARE.
****************************** ******************************
webext-content-scripts webext-content-scripts
2.5.2 <https://github.com/fregante/webext-content-scripts> 2.5.5 <https://github.com/fregante/webext-content-scripts>
MIT License MIT License
Copyright (c) Federico Brigante <me@fregante.com> (https://fregante.com) Copyright (c) Federico Brigante <me@fregante.com> (https://fregante.com)
@@ -194,7 +194,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
****************************** ******************************
webext-polyfill-kinda webext-polyfill-kinda
1.0.0 <https://github.com/fregante/webext-polyfill-kinda> 1.0.2 <https://github.com/fregante/webext-polyfill-kinda>
MIT License MIT License
Copyright (c) Federico Brigante <me@fregante.com> (https://fregante.com) Copyright (c) Federico Brigante <me@fregante.com> (https://fregante.com)

View File

@@ -195,7 +195,7 @@
<a href="https://github.com/ajayyy/SponsorBlock" target="_blank" rel="noopener">GitHub</a> <a href="https://github.com/ajayyy/SponsorBlock" target="_blank" rel="noopener">GitHub</a>
<a href="https://discord.gg/SponsorBlock" target="_blank" rel="noopener">Discord</a> <a href="https://discord.gg/SponsorBlock" target="_blank" rel="noopener">Discord</a>
<a href="https://matrix.to/#/#sponsor:ajay.app?via=ajay.app&via=matrix.org&via=mozilla.org" target="_blank" rel="noopener">Matrix</a> <a href="https://matrix.to/#/#sponsor:ajay.app?via=ajay.app&via=matrix.org&via=mozilla.org" target="_blank" rel="noopener">Matrix</a>
<a href="https://sponsor.ajay.app/donate" target="_blank" rel="noopener" id="sbDonate">$</a> <a href="https://sponsor.ajay.app/donate" target="_blank" rel="noopener" id="sbDonate">__MSG_Donate__</a>
</footer> </footer>
<button id="showNoticeAgain" style="display: none">__MSG_showNotice__</button> <button id="showNoticeAgain" style="display: none">__MSG_showNotice__</button>

View File

@@ -14,7 +14,7 @@
} }
.sponsorSkipNoticeParent { .sponsorSkipNoticeParent {
min-width: 350px; min-width: 375px;
max-width: 50%; max-width: 50%;
} }

View File

@@ -16,6 +16,7 @@ import { getExtensionIdsToImportFrom } from "./utils/crossExtension";
import { isFirefoxOrSafari } from "../maze-utils/src"; import { isFirefoxOrSafari } from "../maze-utils/src";
import { injectUpdatedScripts } from "../maze-utils/src/cleanup"; import { injectUpdatedScripts } from "../maze-utils/src/cleanup";
import { logWarn } from "./utils/logger"; import { logWarn } from "./utils/logger";
import { chromeP } from "../maze-utils/src/browserApi";
const utils = new Utils({ const utils = new Utils({
registerFirefoxContentScript, registerFirefoxContentScript,
unregisterFirefoxContentScript unregisterFirefoxContentScript
@@ -27,7 +28,7 @@ const popupPort: Record<string, chrome.runtime.Port> = {};
const contentScriptRegistrations = {}; const contentScriptRegistrations = {};
// Register content script if needed // Register content script if needed
utils.wait(() => Config.config !== null).then(function() { utils.wait(() => Config.isReady()).then(function() {
if (Config.config.supportInvidious) utils.setupExtraSiteContentScripts(); if (Config.config.supportInvidious) utils.setupExtraSiteContentScripts();
}); });
@@ -75,7 +76,11 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
case "infoUpdated": case "infoUpdated":
case "videoChanged": case "videoChanged":
if (sender.tab) { if (sender.tab) {
popupPort[sender.tab.id]?.postMessage(request); try {
popupPort[sender.tab.id]?.postMessage(request);
} catch (e) {
// This can happen if the popup is closed
}
} }
return false; return false;
default: default:
@@ -148,27 +153,60 @@ chrome.runtime.onInstalled.addListener(function () {
* *
* @param {JSON} options * @param {JSON} options
*/ */
function registerFirefoxContentScript(options: Registration) { async function registerFirefoxContentScript(options: Registration) {
const oldRegistration = contentScriptRegistrations[options.id]; if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
if (oldRegistration) oldRegistration.unregister(); const existingRegistrations = await chromeP.scripting.getRegisteredContentScripts({
ids: [options.id]
}).catch(() => []);
if (existingRegistrations.length > 0
&& existingRegistrations[0].matches.every((match) => options.matches.includes(match))) {
// No need to register another script, already registered
return;
}
}
await unregisterFirefoxContentScript(options.id);
if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
await chromeP.scripting.registerContentScripts([{
id: options.id,
runAt: "document_start",
matches: options.matches,
allFrames: options.allFrames,
js: options.js,
css: options.css,
persistAcrossSessions: true,
}]);
} else {
chrome.contentScripts.register({
allFrames: options.allFrames,
js: options.js?.map?.(file => ({file})),
css: options.css?.map?.(file => ({file})),
matches: options.matches
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
}
chrome.contentScripts.register({
allFrames: options.allFrames,
js: options.js,
css: options.css,
matches: options.matches
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
} }
/** /**
* Only works on Firefox. * Only works on Firefox.
* Firefox requires that this is handled by the background script * Firefox requires that this is handled by the background script
*
*/ */
function unregisterFirefoxContentScript(id: string) { async function unregisterFirefoxContentScript(id: string) {
if (contentScriptRegistrations[id]) { if ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
contentScriptRegistrations[id].unregister(); try {
delete contentScriptRegistrations[id]; await chromeP.scripting.unregisterContentScripts({
ids: [id]
});
} catch (e) {
// Not registered yet
}
} else {
if (contentScriptRegistrations[id]) {
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
}
} }
} }

View File

@@ -128,6 +128,12 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
style={timeDisplayStyle} style={timeDisplayStyle}
className="sponsorTimeDisplay"> className="sponsorTimeDisplay">
<span id={"startButton" + this.idSuffix}
className="sponsorNowButton"
onClick={() => this.setTimeTo(0, 0)}>
{chrome.i18n.getMessage("bracketStart")}
</span>
<span id={"nowButton0" + this.idSuffix} <span id={"nowButton0" + this.idSuffix}
className="sponsorNowButton" className="sponsorNowButton"
onClick={() => this.setTimeToNow(0)}> onClick={() => this.setTimeToNow(0)}>
@@ -138,6 +144,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
type="text" type="text"
style={{color: "inherit", backgroundColor: "inherit"}} style={{color: "inherit", backgroundColor: "inherit"}}
value={this.state.sponsorTimeEdits[0]} value={this.state.sponsorTimeEdits[0]}
onKeyDown={(e) => e.stopPropagation()}
onKeyUp={(e) => e.stopPropagation()}
onChange={(e) => this.handleOnChange(0, e, sponsorTime, e.target.value)} onChange={(e) => this.handleOnChange(0, e, sponsorTime, e.target.value)}
onWheel={(e) => this.changeTimesWhenScrolling(0, e, sponsorTime)}> onWheel={(e) => this.changeTimesWhenScrolling(0, e, sponsorTime)}>
</input> </input>
@@ -153,6 +161,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
type="text" type="text"
style={{color: "inherit", backgroundColor: "inherit"}} style={{color: "inherit", backgroundColor: "inherit"}}
value={this.state.sponsorTimeEdits[1]} value={this.state.sponsorTimeEdits[1]}
onKeyDown={(e) => e.stopPropagation()}
onKeyUp={(e) => e.stopPropagation()}
onChange={(e) => this.handleOnChange(1, e, sponsorTime, e.target.value)} onChange={(e) => this.handleOnChange(1, e, sponsorTime, e.target.value)}
onWheel={(e) => this.changeTimesWhenScrolling(1, e, sponsorTime)}> onWheel={(e) => this.changeTimesWhenScrolling(1, e, sponsorTime)}>
</input> </input>
@@ -238,6 +248,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
ref={this.descriptionOptionRef} ref={this.descriptionOptionRef}
type="text" type="text"
value={this.state.description} value={this.state.description}
onKeyDown={(e) => e.stopPropagation()}
onKeyUp={(e) => e.stopPropagation()}
onContextMenu={(e) => e.stopPropagation()} onContextMenu={(e) => e.stopPropagation()}
onChange={(e) => this.descriptionUpdate(e.target.value)} onChange={(e) => this.descriptionUpdate(e.target.value)}
onFocus={() => this.setState({chapterNameSelectorOpen: true})}> onFocus={() => this.setState({chapterNameSelectorOpen: true})}>
@@ -282,11 +294,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
</span> </span>
): ""} ): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(sponsorTime.actionType)) {(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(sponsorTime.actionType)) ? (
&& sponsorTime.actionType === ActionType.Chapter ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix} <span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton" className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}> onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
{chrome.i18n.getMessage("End")} {chrome.i18n.getMessage("End")}
</span> </span>
): ""} ): ""}
@@ -624,7 +635,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
: CompileConfig.categorySupport[category]?.[0] ?? ActionType.Skip : CompileConfig.categorySupport[category]?.[0] ?? ActionType.Skip
} }
previewTime(ctrlPressed = false, shiftPressed = false): void { previewTime(ctrlPressed = false, shiftPressed = false, skipToEndTime = false): void {
const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
const index = this.props.index; const index = this.props.index;
let seekTime = 2; let seekTime = 2;
@@ -633,13 +644,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
const startTime = sponsorTimes[index].segment[0]; const startTime = sponsorTimes[index].segment[0];
const endTime = sponsorTimes[index].segment[1]; const endTime = sponsorTimes[index].segment[1];
const isChapter = sponsorTimes[index].actionType === ActionType.Chapter;
// If segment starts at 0:00, start playback at the end of the segment // If segment starts at 0:00, start playback at the end of the segment
const skipToEndTime = startTime === 0 || isChapter; const skipTime = (startTime === 0 || skipToEndTime) ? endTime : (startTime - (seekTime * this.props.contentContainer().v.playbackRate));
const skipTime = skipToEndTime ? endTime : (startTime - (seekTime * this.props.contentContainer().v.playbackRate));
this.props.contentContainer().previewTime(skipTime, !isChapter); this.props.contentContainer().previewTime(skipTime, !skipToEndTime);
} }
inspectTime(): void { inspectTime(): void {

View File

@@ -63,7 +63,7 @@ utils.wait(() => Config.isReady(), 5000, 10).then(() => {
&& Config.config.showDeArrowPromotion && Config.config.showDeArrowPromotion
&& Config.config.showUpsells && Config.config.showUpsells
&& Config.config.showNewFeaturePopups && Config.config.showNewFeaturePopups
&& (Config.config.skipCount > 100 || !Config.config.trackViewCount) && (Config.config.skipCount > 30 || !Config.config.trackViewCount)
&& Math.random() < 0.05) { && Math.random() < 0.05) {
if (!await isDeArrowInstalled()) { if (!await isDeArrowInstalled()) {
@@ -110,6 +110,7 @@ const skipNotices: SkipNotice[] = [];
let activeSkipKeybindElement: ToggleSkippable = null; let activeSkipKeybindElement: ToggleSkippable = null;
let retryFetchTimeout: NodeJS.Timeout = null; let retryFetchTimeout: NodeJS.Timeout = null;
let shownSegmentFailedToFetchWarning = false; let shownSegmentFailedToFetchWarning = false;
let selectedSegment: SegmentUUID | null = null;
// JSON video info // JSON video info
let videoInfo: VideoInfo = null; let videoInfo: VideoInfo = null;
@@ -300,6 +301,10 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
case "reskip": case "reskip":
reskipSponsorTime(sponsorTimes.find((segment) => segment.UUID === request.UUID), true); reskipSponsorTime(sponsorTimes.find((segment) => segment.UUID === request.UUID), true);
break; break;
case "selectSegment":
selectedSegment = request.UUID;
updatePreviewBar();
break;
case "submitVote": case "submitVote":
vote(request.type, request.UUID).then((response) => sendResponse(response)); vote(request.type, request.UUID).then((response) => sendResponse(response));
return true; return true;
@@ -819,6 +824,8 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
} }
} }
let playbackRateCheckInterval: NodeJS.Timeout | null = null;
let lastPlaybackSpeed = 1;
let setupVideoListenersFirstTime = true; let setupVideoListenersFirstTime = true;
function setupVideoListeners() { function setupVideoListeners() {
//wait until it is loaded //wait until it is loaded
@@ -838,6 +845,16 @@ function setupVideoListeners() {
let startedWaiting = false; let startedWaiting = false;
let lastPausedAtZero = true; let lastPausedAtZero = true;
const rateChangeListener = () => {
updateVirtualTime();
clearWaitingTime();
startSponsorSchedule();
};
getVideo().addEventListener('ratechange', rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
const playListener = () => { 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
@@ -868,7 +885,6 @@ function setupVideoListeners() {
startSponsorSchedule(); startSponsorSchedule();
} }
}; };
getVideo().addEventListener('play', playListener); getVideo().addEventListener('play', playListener);
@@ -898,6 +914,27 @@ function setupVideoListeners() {
startSponsorSchedule(); startSponsorSchedule();
} }
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastPlaybackSpeed = getVideo().playbackRate;
// Video speed controller compatibility
// That extension makes rate change events not propagate
if (document.body.classList.contains("vsc-initialized")) {
playbackRateCheckInterval = setInterval(() => {
if ((!getVideoID() || getVideo().paused) && playbackRateCheckInterval) {
// Video is gone, stop checking
clearInterval(playbackRateCheckInterval);
return;
}
if (getVideo().playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = getVideo().playbackRate;
rateChangeListener();
}
}, 2000);
}
}; };
getVideo().addEventListener('playing', playingListener); getVideo().addEventListener('playing', playingListener);
@@ -928,21 +965,13 @@ function setupVideoListeners() {
}; };
getVideo().addEventListener('seeking', seekingListener); getVideo().addEventListener('seeking', seekingListener);
const rateChangeListener = () => {
updateVirtualTime();
clearWaitingTime();
startSponsorSchedule();
};
getVideo().addEventListener('ratechange', () => rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener);
const stoppedPlayback = () => { const stoppedPlayback = () => {
// Reset lastCheckVideoTime // Reset lastCheckVideoTime
lastCheckVideoTime = -1; lastCheckVideoTime = -1;
lastCheckTime = 0; lastCheckTime = 0;
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastKnownVideoTime.videoTime = null; lastKnownVideoTime.videoTime = null;
lastKnownVideoTime.preciseTime = null; lastKnownVideoTime.preciseTime = null;
updateWaitingTime(); updateWaitingTime();
@@ -974,6 +1003,8 @@ function setupVideoListeners() {
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener); getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener);
getVideo().removeEventListener('pause', pauseListener); getVideo().removeEventListener('pause', pauseListener);
getVideo().removeEventListener('waiting', waitingListener); getVideo().removeEventListener('waiting', waitingListener);
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
}); });
} }
} }
@@ -1343,7 +1374,8 @@ function updatePreviewBar(): void {
showLarger: segment.actionType === ActionType.Poi, showLarger: segment.actionType === ActionType.Poi,
description: segment.description, description: segment.description,
source: segment.source, source: segment.source,
requiredSegment: requiredSegment && (segment.UUID === requiredSegment || segment.UUID.startsWith(requiredSegment)) requiredSegment: requiredSegment && (segment.UUID === requiredSegment || segment.UUID.startsWith(requiredSegment)),
selectedSegment: selectedSegment && segment.UUID === selectedSegment
}); });
}); });
} }
@@ -2095,7 +2127,7 @@ async function vote(type: number, UUID: SegmentUUID, category?: Category, skipNo
//success (treat rate limits as a success) //success (treat rate limits as a success)
skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category); skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category);
} else if (response.successType == -1) { } else if (response.successType == -1) {
if (response.statusCode === 403 && response.responseText.startsWith("Vote rejected due to a warning from a moderator.")) { if (response.statusCode === 403 && response.responseText.startsWith("Vote rejected due to a tip from a moderator.")) {
openWarningDialog(skipNoticeContentContainer); openWarningDialog(skipNoticeContentContainer);
} else { } else {
skipNotice.setNoticeInfoMessage.bind(skipNotice)(getErrorMessage(response.statusCode, response.responseText)) skipNotice.setNoticeInfoMessage.bind(skipNotice)(getErrorMessage(response.statusCode, response.responseText))

View File

@@ -27,6 +27,7 @@ export interface PreviewBarSegment {
description: string; description: string;
source: SponsorSourceType; source: SponsorSourceType;
requiredSegment?: boolean; requiredSegment?: boolean;
selectedSegment?: boolean;
} }
interface ChapterGroup extends SegmentContainer { interface ChapterGroup extends SegmentContainer {
@@ -332,6 +333,7 @@ class PreviewBar {
const bar = document.createElement('li'); const bar = document.createElement('li');
bar.classList.add('previewbar'); bar.classList.add('previewbar');
if (barSegment.requiredSegment) bar.classList.add("requiredSegment"); if (barSegment.requiredSegment) bar.classList.add("requiredSegment");
if (barSegment.selectedSegment) bar.classList.add("selectedSegment");
bar.innerHTML = showLarger ? '&nbsp;&nbsp;' : '&nbsp;'; bar.innerHTML = showLarger ? '&nbsp;&nbsp;' : '&nbsp;';
const fullCategoryName = (unsubmitted ? 'preview-' : '') + category; const fullCategoryName = (unsubmitted ? 'preview-' : '') + category;
@@ -784,11 +786,13 @@ 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();
chaptersContainer.querySelector(".sponsorChapterText")?.remove(); if (chaptersContainer) {
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement; chaptersContainer.querySelector(".sponsorChapterText")?.remove();
const chapterTitle = chaptersContainer.querySelector(".ytp-chapter-title-content") as HTMLDivElement;
chapterTitle.style.removeProperty("display");
chaptersContainer.classList.remove("sponsorblock-chapter-visible"); chapterTitle.style.removeProperty("display");
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
}
return []; return [];
} }

View File

@@ -31,7 +31,7 @@ interface IsInfoFoundMessage {
} }
interface SkipMessage { interface SkipMessage {
message: "unskip" | "reskip"; message: "unskip" | "reskip" | "selectSegment";
UUID: SegmentUUID; UUID: SegmentUUID;
} }

View File

@@ -687,6 +687,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
: chrome.i18n.getMessage("skipSegment"); : chrome.i18n.getMessage("skipSegment");
skipButton.addEventListener("click", () => skipSegment(actionType, UUID, skipButton)); skipButton.addEventListener("click", () => skipSegment(actionType, UUID, skipButton));
votingButtons.addEventListener("dblclick", () => skipSegment(actionType, UUID)); votingButtons.addEventListener("dblclick", () => skipSegment(actionType, UUID));
votingButtons.addEventListener("dblclick", () => skipSegment(actionType, UUID));
votingButtons.addEventListener("mouseenter", () => selectSegment(UUID));
//add thumbs up, thumbs down and uuid copy buttons to the container //add thumbs up, thumbs down and uuid copy buttons to the container
voteButtonsContainer.appendChild(upvoteButton); voteButtonsContainer.appendChild(upvoteButton);
@@ -718,6 +720,8 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
container.appendChild(votingButtons); container.appendChild(votingButtons);
} }
container.addEventListener("mouseleave", () => selectSegment(null));
} }
function submitTimes() { function submitTimes() {
@@ -968,6 +972,13 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
} }
} }
function selectSegment(UUID: SegmentUUID | null): void {
sendTabMessage({
message: "selectSegment",
UUID: UUID
});
}
/** /**
* Should skipping be disabled (visuals stay) * Should skipping be disabled (visuals stay)
*/ */

View File

@@ -99,8 +99,8 @@ export interface Registration {
message: string; message: string;
id: string; id: string;
allFrames: boolean; allFrames: boolean;
js: browser.extensionTypes.ExtensionFileOrCode[]; js: string[];
css: browser.extensionTypes.ExtensionFileOrCode[]; css: string[];
matches: string[]; matches: string[];
} }

View File

@@ -47,9 +47,13 @@ export default class Utils {
* @param {CallableFunction} callback * @param {CallableFunction} callback
*/ */
setupExtraSitePermissions(callback: (granted: boolean) => void): void { setupExtraSitePermissions(callback: (granted: boolean) => void): void {
let permissions = ["webNavigation"]; const permissions = [];
if (!isSafari()) permissions.push("declarativeContent"); if (!isFirefoxOrSafari()) {
if (isFirefoxOrSafari() && !isSafari()) permissions = []; permissions.push("declarativeContent");
}
if (!isFirefoxOrSafari() || isSafari()) {
permissions.push("webNavigation");
}
chrome.permissions.request({ chrome.permissions.request({
origins: this.getPermissionRegex(), origins: this.getPermissionRegex(),
@@ -73,21 +77,12 @@ export default class Utils {
* For now, it is just SB.config.invidiousInstances. * For now, it is just SB.config.invidiousInstances.
*/ */
setupExtraSiteContentScripts(): void { setupExtraSiteContentScripts(): void {
const firefoxJS = [];
for (const file of this.js) {
firefoxJS.push({file});
}
const firefoxCSS = [];
for (const file of this.css) {
firefoxCSS.push({file});
}
const registration: Registration = { const registration: Registration = {
message: "registerContentScript", message: "registerContentScript",
id: "invidious", id: "invidious",
allFrames: true, allFrames: true,
js: firefoxJS, js: this.js,
css: firefoxCSS, css: this.css,
matches: this.getPermissionRegex() matches: this.getPermissionRegex()
}; };

View File

@@ -4,20 +4,17 @@ function getLuminance(color: string): number {
return Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b)); return Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
} }
/* From https://stackoverflow.com/a/5624139 */ /* Converts hex color to rgb color */
function hexToRgb(hex: string): {r: number; g: number; b: number} { const hexChars = "0123456789abcdef";
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; if (hex.length == 4)
hex = hex.replace(shorthandRegex, function(m, r, g, b) { hex = "#" + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
return r + r + g + g + b + b; return /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
}); ? {
r: hexChars.indexOf(hex[1]) * 16 + hexChars.indexOf(hex[2]),
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); g: hexChars.indexOf(hex[3]) * 16 + hexChars.indexOf(hex[4]),
return result ? { b: hexChars.indexOf(hex[5]) * 16 + hexChars.indexOf(hex[6]),
r: parseInt(result[1], 16), }: null;
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
} }
/** /**
@@ -31,4 +28,4 @@ function indexesOf<T>(array: T[], value: T): number[] {
export const GenericUtils = { export const GenericUtils = {
getLuminance, getLuminance,
indexesOf indexesOf
} }