mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-24 00:18:27 +03:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3f8419c49 | ||
|
|
dde443ccec | ||
|
|
01b1380b78 | ||
|
|
c51b18465e | ||
|
|
ad9888cf52 | ||
|
|
7856791f90 | ||
|
|
273ee63ec7 | ||
|
|
be36583aee | ||
|
|
433bbbf904 | ||
|
|
6c2ee76198 | ||
|
|
42f59898f3 | ||
|
|
8ab126f502 | ||
|
|
4954abf9e3 | ||
|
|
30a21d5ff5 | ||
|
|
d1b2def47c | ||
|
|
48cdabe2a5 | ||
|
|
bc2db0cf2c | ||
|
|
843ef37dcd | ||
|
|
ed260a0667 | ||
|
|
2e131c2a95 | ||
|
|
f5e884b6aa | ||
|
|
a9929d0c93 | ||
|
|
3fb43d1c0e | ||
|
|
a1b2855538 | ||
|
|
07236baed5 | ||
|
|
f991435857 | ||
|
|
faa3259165 | ||
|
|
c96bafb6f7 | ||
|
|
9b7680f0e6 | ||
|
|
16e01b7494 | ||
|
|
6cd697dc32 | ||
|
|
9946bd1af2 | ||
|
|
3b06d72270 | ||
|
|
4bd0556464 | ||
|
|
7e12a914d5 | ||
|
|
25eaf4fa20 | ||
|
|
b3efa1f787 | ||
|
|
9a18e70e34 | ||
|
|
64ece9cb73 | ||
|
|
66c974b011 | ||
|
|
d8cc93c841 | ||
|
|
de22accfda | ||
|
|
e5b0b60dde | ||
|
|
32d98e6544 | ||
|
|
3dde05eda2 | ||
|
|
6aeefaae64 | ||
|
|
93d695e6c2 | ||
|
|
160924feee | ||
|
|
e3f3ed20e6 | ||
|
|
52149f4c0f | ||
|
|
cbc586f9ac | ||
|
|
fc8e20be0d | ||
|
|
368059eb0d | ||
|
|
ea77375fcc | ||
|
|
16005e417d | ||
|
|
7c5b750264 | ||
|
|
cc6b65c6c4 | ||
|
|
d2c99c2d77 | ||
|
|
84c25e3042 | ||
|
|
edaed61612 |
@@ -1,15 +1,31 @@
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
# All Platforms
|
# Translations
|
||||||
Make sure to pull and update all submodules
|
https://crowdin.com/project/sponsorblock
|
||||||
`git submodule update --init --recursive`
|
|
||||||
|
|
||||||
"? property does not exist on type ConfigClass"
|
# Building
|
||||||
> Make sure to copy `config.json.example` to `config.json` and remove comments
|
## Building locally
|
||||||
|
0. You must have [Node.js 16 or later](https://nodejs.org/) and npm installed. Works best on Linux
|
||||||
|
1. Clone with submodules
|
||||||
|
```bash
|
||||||
|
git clone --recursive https://github.com/ajayyy/SponsorBlock
|
||||||
|
```
|
||||||
|
Or if you already cloned it, pull submodules with
|
||||||
|
```bash
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
2. Copy the file `config.json.example` to `config.json` and adjust configuration as desired.
|
||||||
|
- Comments are invalid in JSON, make sure they are all removed.
|
||||||
|
- You will need to repeat this step in the future if you get build errors related to `CompileConfig` or `property does not exist on type ConfigClass`. This can happen for example when a new category is added.
|
||||||
|
3. Run `npm ci` in the repository to install dependencies.
|
||||||
|
4. Run `npm run build:dev` (for Chrome) or `npm run build:dev:firefox` (for Firefox) to generate a development version of the extension with source maps.
|
||||||
|
- You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build.
|
||||||
|
5. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or convert it to a zip file to load it as a [temporary extension](https://developer.mozilla.org/docs/Tools/about:debugging#loading_a_temporary_extension) in Firefox.
|
||||||
|
|
||||||
|
## Developing with a clean profile and hot reloading
|
||||||
|
Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the extension using a clean browser profile with hot reloading. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
|
||||||
|
|
||||||
|
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. You may need to edit package.json and add the parameters directly there.
|
||||||
|
|
||||||
# Windows
|
|
||||||
"Cannot find module "../maze-utils"
|
|
||||||
- Enable "Developer Mode" in windows for symlinks
|
|
||||||
- `src/maze-utils` will not appear properly and builds will fail since it is is only rendered as a file
|
|
||||||
- Enable symlink support in git `git config --global core.symlinks true`
|
|
||||||
- run `git checkout -- src/maze-utils` in order to create a symlink instead of a text file
|
|
||||||
41
README.md
41
README.md
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
SponsorBlock is an open-source crowdsourced browser extension to skip sponsor segments in YouTube videos. Users submit when a sponsor happens from the extension, and the extension automatically skips sponsors it knows about. It also supports skipping other categories, such as intros, outros and reminders to subscribe.
|
SponsorBlock is an open-source crowdsourced browser extension to skip sponsor segments in YouTube videos. Users submit when a sponsor happens from the extension, and the extension automatically skips sponsors it knows about. It also supports skipping other categories, such as intros, outros and reminders to subscribe.
|
||||||
|
|
||||||
It also supports Invidio.us.
|
It also supports Invidious.
|
||||||
|
|
||||||
**Translate:** [](https://crowdin.com/project/sponsorblock)
|
**Translate:** [](https://crowdin.com/project/sponsorblock)
|
||||||
|
|
||||||
@@ -56,47 +56,14 @@ The dataset and API are now being used in some [ports](https://github.com/ajayyy
|
|||||||
|
|
||||||
# API
|
# API
|
||||||
|
|
||||||
You can read the API docs [here](https://wiki.sponsor.ajay.app/index.php/API_Docs).
|
You can read the API docs [here](https://wiki.sponsor.ajay.app/w/API_Docs).
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
See [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||||
You must have [Node.js 16](https://nodejs.org/) and npm installed.
|
|
||||||
|
|
||||||
1. Clone with submodules
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone --recursive https://github.com/ajayyy/SponsorBlock
|
|
||||||
```
|
|
||||||
|
|
||||||
Or if you already cloned it, pull submodules with
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git submodule update --init --recursive
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Copy the file `config.json.example` to `config.json` and adjust configuration as desired.
|
|
||||||
|
|
||||||
- You will need to repeat this step in the future if you get build errors related to `CompileConfig`. This can happen for example when a new category is added.
|
|
||||||
|
|
||||||
3. Run `npm install` in the repository to install dependencies.
|
|
||||||
|
|
||||||
4. Run `npm run build:dev` (for Chrome) or `npm run build:dev:firefox` (for Firefox) to generate a development version of the extension with source maps.
|
|
||||||
|
|
||||||
- You can also run `npm run build` (for Chrome) or `npm run build:firefox` (for Firefox) to generate a production build.
|
|
||||||
|
|
||||||
5. The built extension is now in `dist/`. You can load this folder directly in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest), or convert it to a zip file to load it as a [temporary extension](https://developer.mozilla.org/en-US/docs/Tools/about:debugging#loading_a_temporary_extension) in Firefox.
|
|
||||||
|
|
||||||
### Developing with a clean profile and hot reloading
|
|
||||||
|
|
||||||
Run `npm run dev` (for Chrome) or `npm run dev:firefox` (for Firefox) to run the extension using a clean browser profile with hot reloading. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
# Credit
|
# Credit
|
||||||
|
|
||||||
The awesome [Invidious API](https://docs.invidious.io/API.md) was previously used, and the server is now using [NewLeaf](https://git.sr.ht/~cadence/NewLeaf) as a to get video info from YouTube.
|
The awesome [Invidious API](https://docs.invidious.io/) was previously used, and the server is now using [NewLeaf](https://git.sr.ht/~cadence/NewLeaf) as a to get video info from YouTube.
|
||||||
|
|
||||||
Originally forked from [YTSponsorSkip](https://github.com/NDevTK/YTSponsorSkip), but very little code remains.
|
Originally forked from [YTSponsorSkip](https://github.com/NDevTK/YTSponsorSkip), but very little code remains.
|
||||||
|
|
||||||
|
|||||||
@@ -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"]
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"optional_permissions": [
|
"optional_permissions": [
|
||||||
"declarativeContent"
|
"declarativeContent",
|
||||||
|
"webNavigation"
|
||||||
],
|
],
|
||||||
"background": {
|
"background": {
|
||||||
"persistent": false
|
"persistent": false
|
||||||
|
|||||||
@@ -3,5 +3,14 @@
|
|||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "sponsorBlocker@ajay.app"
|
"id": "sponsorBlocker@ajay.app"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"persistent": false
|
||||||
|
},
|
||||||
|
"permissions": [
|
||||||
|
"scripting"
|
||||||
|
],
|
||||||
|
"browser_action": {
|
||||||
|
"default_area": "navbar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "SponsorBlock",
|
"short_name": "SponsorBlock",
|
||||||
"version": "5.4.13",
|
"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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"background": {
|
"background": {
|
||||||
"persistent": false
|
"persistent": false
|
||||||
}
|
},
|
||||||
|
"permissions": [
|
||||||
|
"scripting"
|
||||||
|
],
|
||||||
|
"optional_permissions": [
|
||||||
|
"webNavigation"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule maze-utils updated: b3572eaeff...2eb140ad32
@@ -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
33
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Submodule public/_locales updated: 9e1f32d7c6...0aaffa05a3
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sponsorSkipNoticeParent {
|
.sponsorSkipNoticeParent {
|
||||||
min-width: 350px;
|
min-width: 375px;
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import * as CompileConfig from "../config.json";
|
|||||||
import Config from "./config";
|
import Config from "./config";
|
||||||
import { Registration } from "./types";
|
import { Registration } from "./types";
|
||||||
import "content-scripts-register-polyfill";
|
import "content-scripts-register-polyfill";
|
||||||
import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "./maze-utils/background-request-proxy";
|
import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "../maze-utils/src/background-request-proxy";
|
||||||
import { setupTabUpdates } from "./maze-utils/tab-updates";
|
import { setupTabUpdates } from "../maze-utils/src/tab-updates";
|
||||||
import { generateUserID } from "./maze-utils/setup";
|
import { generateUserID } from "../maze-utils/src/setup";
|
||||||
|
|
||||||
// Make the config public for debugging purposes
|
// Make the config public for debugging purposes
|
||||||
|
|
||||||
@@ -13,9 +13,10 @@ 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 { isFirefoxOrSafari } from "../maze-utils/src";
|
||||||
import { injectUpdatedScripts } from "./maze-utils/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) {
|
||||||
|
try {
|
||||||
popupPort[sender.tab.id]?.postMessage(request);
|
popupPort[sender.tab.id]?.postMessage(request);
|
||||||
|
} catch (e) {
|
||||||
|
// This can happen if the popup is closed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@@ -148,28 +153,61 @@ 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(() => []);
|
||||||
|
|
||||||
chrome.contentScripts.register({
|
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,
|
allFrames: options.allFrames,
|
||||||
js: options.js,
|
js: options.js,
|
||||||
css: options.css,
|
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
|
matches: options.matches
|
||||||
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
|
}).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 ("scripting" in chrome && "getRegisteredContentScripts" in chrome.scripting) {
|
||||||
|
try {
|
||||||
|
await chromeP.scripting.unregisterContentScripts({
|
||||||
|
ids: [id]
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
// Not registered yet
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (contentScriptRegistrations[id]) {
|
if (contentScriptRegistrations[id]) {
|
||||||
contentScriptRegistrations[id].unregister();
|
contentScriptRegistrations[id].unregister();
|
||||||
delete contentScriptRegistrations[id];
|
delete contentScriptRegistrations[id];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitVote(type: number, UUID: string, category: string) {
|
async function submitVote(type: number, UUID: string, category: string) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
|
|||||||
import { VoteResponse } from "../messageTypes";
|
import { VoteResponse } from "../messageTypes";
|
||||||
import { AnimationUtils } from "../utils/animationUtils";
|
import { AnimationUtils } from "../utils/animationUtils";
|
||||||
import { Tooltip } from "../render/Tooltip";
|
import { Tooltip } from "../render/Tooltip";
|
||||||
import { getErrorMessage } from "../maze-utils/formating";
|
import { getErrorMessage } from "../../maze-utils/src/formating";
|
||||||
|
|
||||||
export interface CategoryPillProps {
|
export interface CategoryPillProps {
|
||||||
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
|
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
|
|||||||
import { VoteResponse } from "../messageTypes";
|
import { VoteResponse } from "../messageTypes";
|
||||||
import { AnimationUtils } from "../utils/animationUtils";
|
import { AnimationUtils } from "../utils/animationUtils";
|
||||||
import { Tooltip } from "../render/Tooltip";
|
import { Tooltip } from "../render/Tooltip";
|
||||||
import { getErrorMessage } from "../maze-utils/formating";
|
import { getErrorMessage } from "../../maze-utils/src/formating";
|
||||||
|
|
||||||
export interface ChapterVoteProps {
|
export interface ChapterVoteProps {
|
||||||
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
|
vote: (type: number, UUID: SegmentUUID, category?: Category) => Promise<VoteResponse>;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import ThumbsUpSvg from "../svg-icons/thumbs_up_svg";
|
|||||||
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
|
import ThumbsDownSvg from "../svg-icons/thumbs_down_svg";
|
||||||
import PencilSvg from "../svg-icons/pencil_svg";
|
import PencilSvg from "../svg-icons/pencil_svg";
|
||||||
import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
|
import { downvoteButtonColor, SkipNoticeAction } from "../utils/noticeUtils";
|
||||||
import { generateUserID } from "../maze-utils/setup";
|
import { generateUserID } from "../../maze-utils/src/setup";
|
||||||
import { keybindToString } from "../maze-utils/config";
|
import { keybindToString } from "../../maze-utils/src/config";
|
||||||
|
|
||||||
enum SkipButtonState {
|
enum SkipButtonState {
|
||||||
Undo, // Unskip
|
Undo, // Unskip
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
|
|||||||
import { RectangleTooltip } from "../render/RectangleTooltip";
|
import { RectangleTooltip } from "../render/RectangleTooltip";
|
||||||
import SelectorComponent, { SelectorOption } from "./SelectorComponent";
|
import SelectorComponent, { SelectorOption } from "./SelectorComponent";
|
||||||
import { DEFAULT_CATEGORY } from "../utils/categoryUtils";
|
import { DEFAULT_CATEGORY } from "../utils/categoryUtils";
|
||||||
import { getFormattedTime, getFormattedTimeToSeconds } from "../maze-utils/formating";
|
import { getFormattedTime, getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
|
||||||
|
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from "react";
|
|||||||
import { createRoot, Root } from 'react-dom/client';
|
import { createRoot, Root } from 'react-dom/client';
|
||||||
import Config from "../../config";
|
import Config from "../../config";
|
||||||
import KeybindDialogComponent from "./KeybindDialogComponent";
|
import KeybindDialogComponent from "./KeybindDialogComponent";
|
||||||
import { formatKey, Keybind, keybindEquals, keybindToString } from "../../maze-utils/config";
|
import { formatKey, Keybind, keybindEquals, keybindToString } from "../../../maze-utils/src/config";
|
||||||
|
|
||||||
export interface KeybindProps {
|
export interface KeybindProps {
|
||||||
option: string;
|
option: string;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ChangeEvent } from "react";
|
import { ChangeEvent } from "react";
|
||||||
import Config from "../../config";
|
import Config from "../../config";
|
||||||
import { Keybind, formatKey, keybindEquals } from "../../maze-utils/config";
|
import { Keybind, formatKey, keybindEquals } from "../../../maze-utils/src/config";
|
||||||
|
|
||||||
export interface KeybindDialogProps {
|
export interface KeybindDialogProps {
|
||||||
option: string;
|
option: string;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
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, VideoID, SponsorHideType } from "./types";
|
import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, PreviewBarOption, SponsorTime, VideoID, SponsorHideType } from "./types";
|
||||||
import { Keybind, ProtoConfig, keybindEquals } from "./maze-utils/config";
|
import { Keybind, ProtoConfig, keybindEquals } from "../maze-utils/src/config";
|
||||||
import { HashedValue } from "./maze-utils/hash";
|
import { HashedValue } from "../maze-utils/src/hash";
|
||||||
|
|
||||||
export interface Permission {
|
export interface Permission {
|
||||||
canSubmit: boolean;
|
canSubmit: boolean;
|
||||||
|
|||||||
@@ -32,21 +32,21 @@ import { logDebug } from "./utils/logger";
|
|||||||
import { importTimes } from "./utils/exporter";
|
import { importTimes } from "./utils/exporter";
|
||||||
import { ChapterVote } from "./render/ChapterVote";
|
import { ChapterVote } from "./render/ChapterVote";
|
||||||
import { openWarningDialog } from "./utils/warnings";
|
import { openWarningDialog } from "./utils/warnings";
|
||||||
import { isFirefoxOrSafari, waitFor } from "./maze-utils";
|
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
|
||||||
import { getErrorMessage, getFormattedTime } from "./maze-utils/formating";
|
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
|
||||||
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "./maze-utils/video";
|
import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube } from "../maze-utils/src/video";
|
||||||
import { Keybind, StorageChangesObject, isSafari, keybindEquals } from "./maze-utils/config";
|
import { Keybind, StorageChangesObject, isSafari, keybindEquals } from "../maze-utils/src/config";
|
||||||
import { findValidElement, waitForElement } from "./maze-utils/dom"
|
import { findValidElement, waitForElement } from "../maze-utils/src/dom"
|
||||||
import { getHash, HashedValue } from "./maze-utils/hash";
|
import { getHash, HashedValue } from "../maze-utils/src/hash";
|
||||||
import { generateUserID } from "./maze-utils/setup";
|
import { generateUserID } from "../maze-utils/src/setup";
|
||||||
import { updateAll } from "./maze-utils/thumbnailManagement";
|
import { updateAll } from "../maze-utils/src/thumbnailManagement";
|
||||||
import { setupThumbnailListener } from "./utils/thumbnails";
|
import { setupThumbnailListener } from "./utils/thumbnails";
|
||||||
import * as documentScript from "../dist/js/document.js";
|
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 { cleanPage } from "./utils/pageCleaner";
|
||||||
import { addCleanupListener } from "./maze-utils/cleanup";
|
import { addCleanupListener } from "../maze-utils/src/cleanup";
|
||||||
|
|
||||||
cleanPage();
|
cleanPage();
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -803,11 +808,12 @@ function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boole
|
|||||||
const currentVideoID = getYouTubeVideoID();
|
const currentVideoID = getYouTubeVideoID();
|
||||||
const recordedVideoID = videoID || getVideoID();
|
const recordedVideoID = videoID || getVideoID();
|
||||||
if (currentVideoID !== recordedVideoID || (sponsorTime
|
if (currentVideoID !== recordedVideoID || (sponsorTime
|
||||||
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment === sponsorTime.segment))
|
&& (!sponsorTimes || !sponsorTimes?.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))
|
||||||
&& !sponsorTimesSubmitting.some((time) => time.segment === sponsorTime.segment))) {
|
&& !sponsorTimesSubmitting.some((time) => time.segment[0] === sponsorTime.segment[0] && time.segment[1] === sponsorTime.segment[1]))) {
|
||||||
// Something has really gone wrong
|
// Something has really gone wrong
|
||||||
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
|
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
|
||||||
console.error("[SponsorBlock] VideoID recorded: " + recordedVideoID + ". Actual VideoID: " + currentVideoID);
|
console.error("[SponsorBlock] VideoID recorded: " + recordedVideoID + ". Actual VideoID: " + currentVideoID);
|
||||||
|
console.error("[SponsorBlock] SponsorTime", sponsorTime, "sponsorTimes", sponsorTimes, "sponsorTimesSubmitting", sponsorTimesSubmitting);
|
||||||
|
|
||||||
// Video ID change occured
|
// Video ID change occured
|
||||||
checkVideoIDChange();
|
checkVideoIDChange();
|
||||||
@@ -818,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
|
||||||
@@ -837,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
|
||||||
@@ -867,7 +885,6 @@ function setupVideoListeners() {
|
|||||||
|
|
||||||
startSponsorSchedule();
|
startSponsorSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
getVideo().addEventListener('play', playListener);
|
getVideo().addEventListener('play', playListener);
|
||||||
|
|
||||||
@@ -897,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);
|
||||||
|
|
||||||
@@ -927,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();
|
||||||
@@ -973,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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1342,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
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2094,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))
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
import { init } from "./maze-utils/injected/document";
|
import { init } from "../maze-utils/src/injected/document";
|
||||||
|
|
||||||
init();
|
init();
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { localizeHtmlPage } from "./maze-utils/setup";
|
import { localizeHtmlPage } from "../maze-utils/src/setup";
|
||||||
import Config from "./config";
|
import Config from "./config";
|
||||||
import { showDonationLink } from "./utils/configUtils";
|
import { showDonationLink } from "./utils/configUtils";
|
||||||
|
|
||||||
import { waitFor } from "./maze-utils";
|
import { waitFor } from "../maze-utils/src";
|
||||||
|
|
||||||
if (document.readyState === "complete") {
|
if (document.readyState === "complete") {
|
||||||
init();
|
init();
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import { ActionType, Category, SegmentContainer, SponsorHideType, SponsorSourceT
|
|||||||
import { partition } from "../utils/arrayUtils";
|
import { partition } from "../utils/arrayUtils";
|
||||||
import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
|
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/src/formating";
|
||||||
import { findValidElement } from "../maze-utils/dom";
|
import { findValidElement } from "../../maze-utils/src/dom";
|
||||||
import { addCleanupListener } from "../maze-utils/cleanup";
|
import { addCleanupListener } from "../../maze-utils/src/cleanup";
|
||||||
|
|
||||||
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
|
||||||
const MIN_CHAPTER_SIZE = 0.003;
|
const MIN_CHAPTER_SIZE = 0.003;
|
||||||
@@ -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 ? ' ' : ' ';
|
bar.innerHTML = showLarger ? ' ' : ' ';
|
||||||
|
|
||||||
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();
|
||||||
|
if (chaptersContainer) {
|
||||||
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;
|
||||||
|
|
||||||
chapterTitle.style.removeProperty("display");
|
chapterTitle.style.removeProperty("display");
|
||||||
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
|
chaptersContainer.classList.remove("sponsorblock-chapter-visible");
|
||||||
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +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 { AnimationUtils } from "../utils/animationUtils";
|
import { AnimationUtils } from "../utils/animationUtils";
|
||||||
import { keybindToString } from "../maze-utils/config";
|
import { keybindToString } from "../../maze-utils/src/config";
|
||||||
|
|
||||||
export interface SkipButtonControlBarProps {
|
export interface SkipButtonControlBarProps {
|
||||||
skip: (segment: SponsorTime) => void;
|
skip: (segment: SponsorTime) => void;
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../maze-utils/src/
|
|
||||||
@@ -31,7 +31,7 @@ interface IsInfoFoundMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SkipMessage {
|
interface SkipMessage {
|
||||||
message: "unskip" | "reskip";
|
message: "unskip" | "reskip" | "selectSegment";
|
||||||
UUID: SegmentUUID;
|
UUID: SegmentUUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import CategoryChooser from "./render/CategoryChooser";
|
|||||||
import UnsubmittedVideos from "./render/UnsubmittedVideos";
|
import UnsubmittedVideos from "./render/UnsubmittedVideos";
|
||||||
import KeybindComponent from "./components/options/KeybindComponent";
|
import KeybindComponent from "./components/options/KeybindComponent";
|
||||||
import { showDonationLink } from "./utils/configUtils";
|
import { showDonationLink } from "./utils/configUtils";
|
||||||
import { localizeHtmlPage } from "./maze-utils/setup";
|
import { localizeHtmlPage } from "../maze-utils/src/setup";
|
||||||
import { StorageChangesObject } from "./maze-utils/config";
|
import { StorageChangesObject } from "../maze-utils/src/config";
|
||||||
import { getHash } from "./maze-utils/hash";
|
import { getHash } from "../maze-utils/src/hash";
|
||||||
import { isFirefoxOrSafari } from "./maze-utils";
|
import { isFirefoxOrSafari } from "../maze-utils/src";
|
||||||
import { isDeArrowInstalled } from "./utils/crossExtension";
|
import { isDeArrowInstalled } from "./utils/crossExtension";
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
let embed = false;
|
let embed = false;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Config from "./config";
|
import Config from "./config";
|
||||||
import Utils from "./utils";
|
import Utils from "./utils";
|
||||||
import { localizeHtmlPage } from "./maze-utils/setup";
|
import { localizeHtmlPage } from "../maze-utils/src/setup";
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
// This is needed, if Config is not imported before Utils, things break.
|
// This is needed, if Config is not imported before Utils, things break.
|
||||||
|
|||||||
19
src/popup.ts
19
src/popup.ts
@@ -21,12 +21,12 @@ import {
|
|||||||
import { showDonationLink } from "./utils/configUtils";
|
import { showDonationLink } from "./utils/configUtils";
|
||||||
import { AnimationUtils } from "./utils/animationUtils";
|
import { AnimationUtils } from "./utils/animationUtils";
|
||||||
import { shortCategoryName } from "./utils/categoryUtils";
|
import { shortCategoryName } from "./utils/categoryUtils";
|
||||||
import { localizeHtmlPage } from "./maze-utils/setup";
|
import { localizeHtmlPage } from "../maze-utils/src/setup";
|
||||||
import { exportTimes } from "./utils/exporter";
|
import { exportTimes } from "./utils/exporter";
|
||||||
import GenericNotice from "./render/GenericNotice";
|
import GenericNotice from "./render/GenericNotice";
|
||||||
import { getErrorMessage, getFormattedTime } from "./maze-utils/formating";
|
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/formating";
|
||||||
import { StorageChangesObject } from "./maze-utils/config";
|
import { StorageChangesObject } from "../maze-utils/src/config";
|
||||||
import { getHash } from "./maze-utils/hash";
|
import { getHash } from "../maze-utils/src/hash";
|
||||||
|
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
@@ -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)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import Config from "../config";
|
|||||||
import { VoteResponse } from "../messageTypes";
|
import { VoteResponse } from "../messageTypes";
|
||||||
import { Category, SegmentUUID, SponsorTime } from "../types";
|
import { Category, SegmentUUID, SponsorTime } from "../types";
|
||||||
import { Tooltip } from "./Tooltip";
|
import { Tooltip } from "./Tooltip";
|
||||||
import { waitFor } from "../maze-utils";
|
import { waitFor } from "../../maze-utils/src";
|
||||||
import { getYouTubeTitleNode } from "../maze-utils/elements";
|
import { getYouTubeTitleNode } from "../../maze-utils/src/elements";
|
||||||
import { addCleanupListener } from "../maze-utils/cleanup";
|
import { addCleanupListener } from "../../maze-utils/src/cleanup";
|
||||||
|
|
||||||
const id = "categoryPill";
|
const id = "categoryPill";
|
||||||
|
|
||||||
|
|||||||
@@ -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[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/utils.ts
33
src/utils.ts
@@ -1,12 +1,12 @@
|
|||||||
import Config, { VideoDownvotes } from "./config";
|
import Config, { VideoDownvotes } from "./config";
|
||||||
import { CategorySelection, SponsorTime, BackgroundScriptContainer, Registration, VideoID, SponsorHideType, CategorySkipOption } from "./types";
|
import { CategorySelection, SponsorTime, BackgroundScriptContainer, Registration, VideoID, SponsorHideType, CategorySkipOption } from "./types";
|
||||||
|
|
||||||
import { getHash, HashedValue } from "./maze-utils/hash";
|
import { getHash, HashedValue } from "../maze-utils/src/hash";
|
||||||
import * as CompileConfig from "../config.json";
|
import * as CompileConfig from "../config.json";
|
||||||
import { isFirefoxOrSafari, waitFor } from "./maze-utils";
|
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
|
||||||
import { findValidElementFromSelector } from "./maze-utils/dom";
|
import { findValidElementFromSelector } from "../maze-utils/src/dom";
|
||||||
import { FetchResponse, sendRequestToCustomServer } from "./maze-utils/background-request-proxy"
|
import { FetchResponse, sendRequestToCustomServer } from "../maze-utils/src/background-request-proxy"
|
||||||
import { isSafari } from "./maze-utils/config";
|
import { isSafari } from "../maze-utils/src/config";
|
||||||
|
|
||||||
export default class Utils {
|
export default class Utils {
|
||||||
|
|
||||||
@@ -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()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as CompileConfig from "../../config.json";
|
import * as CompileConfig from "../../config.json";
|
||||||
|
|
||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
import { isSafari } from "../maze-utils/config";
|
import { isSafari } from "../../maze-utils/src/config";
|
||||||
import { isFirefoxOrSafari } from "../maze-utils";
|
import { isFirefoxOrSafari } from "../../maze-utils/src";
|
||||||
|
|
||||||
export function isDeArrowInstalled(): Promise<boolean> {
|
export function isDeArrowInstalled(): Promise<boolean> {
|
||||||
if (Config.config.deArrowInstalled) {
|
if (Config.config.deArrowInstalled) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ActionType, Category, SegmentUUID, SponsorSourceType, SponsorTime } from "../types";
|
import { ActionType, Category, SegmentUUID, SponsorSourceType, SponsorTime } from "../types";
|
||||||
import { shortCategoryName } from "./categoryUtils";
|
import { shortCategoryName } from "./categoryUtils";
|
||||||
import * as CompileConfig from "../../config.json";
|
import * as CompileConfig from "../../config.json";
|
||||||
import { getFormattedTime, getFormattedTimeToSeconds } from "../maze-utils/formating";
|
import { getFormattedTime, getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
|
||||||
import { generateUserID } from "../maze-utils/setup";
|
import { generateUserID } from "../../maze-utils/src/setup";
|
||||||
|
|
||||||
const inTest = typeof chrome === "undefined";
|
const inTest = typeof chrome === "undefined";
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
import { ActionType, Category, SponsorSourceType, SponsorTime, VideoID } from "../types";
|
||||||
import { getFormattedTimeToSeconds } from "../maze-utils/formating";
|
import { getFormattedTimeToSeconds } from "../../maze-utils/src/formating";
|
||||||
|
|
||||||
export function getControls(): HTMLElement {
|
export function getControls(): HTMLElement {
|
||||||
const controlsSelectors = [
|
const controlsSelectors = [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { isOnInvidious, parseYouTubeVideoIDFromURL } from "../maze-utils/video";
|
import { isOnInvidious, parseYouTubeVideoIDFromURL } from "../../maze-utils/src/video";
|
||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
import { getVideoLabel } from "./videoLabels";
|
import { getVideoLabel } from "./videoLabels";
|
||||||
import { setThumbnailListener } from "../maze-utils/thumbnailManagement";
|
import { setThumbnailListener } from "../../maze-utils/src/thumbnailManagement";
|
||||||
|
|
||||||
export async function labelThumbnails(thumbnails: HTMLImageElement[]): Promise<void> {
|
export async function labelThumbnails(thumbnails: HTMLImageElement[]): Promise<void> {
|
||||||
await Promise.all(thumbnails.map((t) => labelThumbnail(t)));
|
await Promise.all(thumbnails.map((t) => labelThumbnail(t)));
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Category, CategorySkipOption, VideoID } from "../types";
|
import { Category, CategorySkipOption, VideoID } from "../types";
|
||||||
import { getHash } from "../maze-utils/hash";
|
import { getHash } from "../../maze-utils/src/hash";
|
||||||
import Utils from "../utils";
|
import Utils from "../utils";
|
||||||
import { logWarn } from "./logger";
|
import { logWarn } from "./logger";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { objectToURI } from "../maze-utils";
|
import { objectToURI } from "../../maze-utils/src";
|
||||||
import { getHash } from "../maze-utils/hash";
|
import { getHash } from "../../maze-utils/src/hash";
|
||||||
import Config from "../config";
|
import Config from "../config";
|
||||||
import GenericNotice, { NoticeOptions } from "../render/GenericNotice";
|
import GenericNotice, { NoticeOptions } from "../render/GenericNotice";
|
||||||
import { ContentContainer } from "../types";
|
import { ContentContainer } from "../types";
|
||||||
|
|||||||
Reference in New Issue
Block a user