Compare commits

..

34 Commits
5.5.8 ... mv3

Author SHA1 Message Date
Ajay
fae7d921a7 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into mv3 2024-06-22 16:27:18 +05:30
Ajay
60a2eff40a Fix linting issue 2024-06-19 23:16:29 +05:30
Ajay
98a4a076bc Support invidious in mv3 2024-06-19 23:14:27 +05:30
Ajay
a95020dda3 Manifest v3 without invidious working 2024-06-19 22:37:29 +05:30
Ajay Ramachandran
5e179cf9ff Merge pull request #2036 from mini-bomba/refresh-fix
Fix refreshing
2024-06-13 09:07:57 +05:30
mini-bomba
0b946d5ef7 Don't fetch segments when videoID is null
Also log an error to the console if we ever try to do this in the future
2024-06-13 01:18:02 +02:00
mini-bomba
f48c57b1c5 Don't inject into the cookie rotate iframe
There's nothing there, it only breaks the refreshing.
2024-06-13 01:09:27 +02:00
Ajay
98ac2fc618 bump version 2024-06-06 19:53:08 +05:30
Ajay
36e3333e39 Fix submission menu disappearing when video ends 2024-06-06 19:52:57 +05:30
Ajay
15fcc971f6 bump version 2024-05-24 03:26:02 -04:00
Ajay
32adbb9581 update translations 2024-05-24 03:22:36 -04:00
Ajay
4ecd02510b Fix warnings 2024-05-24 03:22:07 -04:00
Ajay
0dbb6474b8 Fix preview bar on mobile
Fixes #2021
2024-05-24 03:20:21 -04:00
Ajay
c974c2a6d6 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2024-05-24 03:15:59 -04:00
Ajay
a6695254b6 Fix skipping and preview bar on "add to queue", miniplayer and hover preview
Fixes #1486
2024-05-24 03:15:58 -04:00
Ajay
e8a82eddca Change chapters sorting 2024-05-09 19:09:37 -04:00
Ajay Ramachandran
d3684dbedd Merge pull request #2017 from stdedos/fix/disabled-comment-typo
Fix comment typo
2024-05-08 17:54:10 -04:00
Stavros Ntentos
6c9a403731 Fix comment typo
Signed-off-by: Stavros Ntentos <133706+stdedos@users.noreply.github.com>
2024-05-08 23:44:01 +03:00
Ajay
3be51c89a9 Fix popup sometimes saying "No video found"
Fixes #2006
Fixes #2013
Fixes #1999
2024-04-30 20:54:54 -04:00
Ajay
5b845a56e1 Fix unsubmitted segments sometimes manual skipping if manual skip enabled for category
Fixes #2002
2024-04-28 22:59:02 -04:00
Ajay
7b572c3c0e Fix previewed segment check
Fixes #1996
2024-04-28 21:51:35 -04:00
Ajay
56bb22d03d Allow importing segments with no category
Also fixes case when importing chapters when having no permission to submit chapters
2024-04-26 16:44:20 -04:00
Ajay
e1d656f43f Make notice visibility option not appear when notice disabled 2024-04-04 13:54:47 -04:00
Ajay
e14b3c76f9 Improve submission box padding 2024-03-27 16:14:10 -04:00
Ajay
de830cda48 bump version 2024-03-18 21:03:23 -04:00
Ajay
d8057fb547 bump translations 2024-03-18 21:03:09 -04:00
Ajay Ramachandran
2dd69d443b Merge pull request #1983 from HanYaodong/dev
[Fix #1979] Stop Refresh Animation on Popup When Content Script is Not Injected
2024-03-18 20:59:19 -04:00
Ajay
6732850b41 Fix chapters not changing when skipping is disabled 2024-03-18 20:58:07 -04:00
Ajay
287233785e Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2024-03-18 19:45:36 -04:00
Ajay
de094cb11f Add option to store downvotes when done in private tabs 2024-03-18 19:45:35 -04:00
Ajay Ramachandran
2307691044 Merge pull request #1986 from ajayyy/dependabot/npm_and_yarn/follow-redirects-1.15.6
Bump follow-redirects from 1.15.4 to 1.15.6
2024-03-16 21:07:43 -04:00
dependabot[bot]
2dca0d7526 Bump follow-redirects from 1.15.4 to 1.15.6
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-16 23:28:04 +00:00
HanYaodong
a1505bcf20 Refractor popup infoFound() empty message detection 2024-03-09 23:47:48 +08:00
HanYaodong
25b53754ba Stop refresh animation on popup when content script is not injected 2024-03-09 23:42:17 +08:00
23 changed files with 657 additions and 403 deletions

View File

@@ -1,12 +1,156 @@
{ {
"optional_permissions": [ "host_permissions": [
"declarativeContent", "https://*.youtube.com/*",
"webNavigation" "https://sponsor.ajay.app/*"
], ],
"background": { "optional_host_permissions": [
"persistent": false "*://*/*"
],
"web_accessible_resources": [{
"resources": [
"icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png",
"icons/PlayerStartIconSponsorBlocker.svg",
"icons/PlayerStopIconSponsorBlocker.svg",
"icons/PlayerUploadIconSponsorBlocker.svg",
"icons/PlayerUploadFailedIconSponsorBlocker.svg",
"icons/PlayerCancelSegmentIconSponsorBlocker.svg",
"icons/clipboard.svg",
"icons/settings.svg",
"icons/pencil.svg",
"icons/check.svg",
"icons/check-smaller.svg",
"icons/upvote.png",
"icons/downvote.png",
"icons/thumbs_down.svg",
"icons/thumbs_down_locked.svg",
"icons/thumbs_up.svg",
"icons/help.svg",
"icons/report.png",
"icons/close.png",
"icons/skipIcon.svg",
"icons/refresh.svg",
"icons/beep.ogg",
"icons/pause.svg",
"icons/stop.svg",
"icons/skip.svg",
"icons/heart.svg",
"icons/visible.svg",
"icons/not_visible.svg",
"icons/sort.svg",
"icons/money.svg",
"icons/segway.png",
"icons/close-smaller.svg",
"icons/right-arrow.svg",
"icons/campaign.svg",
"icons/star.svg",
"icons/lightbulb.svg",
"icons/bolt.svg",
"icons/stopwatch.svg",
"icons/music-note.svg",
"icons/import.svg",
"icons/export.svg",
"icons/PlayerInfoIconSponsorBlocker.svg",
"icons/PlayerDeleteIconSponsorBlocker.svg",
"icons/dearrow.svg",
"popup.html",
"popup.css",
"content.css",
"shared.css",
"js/document.js",
"libs/Source+Sans+Pro.css",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmRduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmBduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlBduz8A.woff2"
],
"matches": ["<all_urls>"]
}],
"content_scripts": [
{
"world": "MAIN",
"js": [
"./js/document.js"
],
"matches": [
"https://*.youtube.com/*",
"https://www.youtube-nocookie.com/embed/*"
],
"exclude_matches": [
"https://accounts.youtube.com/RotateCookiesPage*"
],
"all_frames": true,
"run_at": "document_start"
},
{
"world": "ISOLATED",
"js": [
"./js/content.js"
],
"css": [
"content.css",
"shared.css"
],
"matches": [
"https://*.youtube.com/*",
"https://www.youtube-nocookie.com/embed/*"
],
"exclude_matches": [
"https://accounts.youtube.com/RotateCookiesPage*"
],
"all_frames": true,
"run_at": "document_start"
}
],
"action": {
"default_title": "SponsorBlock",
"default_popup": "popup.html",
"default_icon": {
"16": "icons/IconSponsorBlocker16px.png",
"32": "icons/IconSponsorBlocker32px.png",
"64": "icons/IconSponsorBlocker64px.png",
"128": "icons/IconSponsorBlocker128px.png"
},
"theme_icons": [
{
"light": "icons/IconSponsorBlocker16px.png",
"dark": "icons/IconSponsorBlocker16px.png",
"size": 16
},
{
"light": "icons/IconSponsorBlocker32px.png",
"dark": "icons/IconSponsorBlocker32px.png",
"size": 32
},
{
"light": "icons/IconSponsorBlocker64px.png",
"dark": "icons/IconSponsorBlocker64px.png",
"size": 64
},
{
"light": "icons/IconSponsorBlocker128px.png",
"dark": "icons/IconSponsorBlocker128px.png",
"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
}
]
}, },
"permissions": [ "background": {
"https://*.youtube.com/*" "service_worker": "./js/background.js"
] },
"manifest_version": 3
} }

View File

@@ -11,9 +11,6 @@
"background": { "background": {
"persistent": false "persistent": false
}, },
"permissions": [
"scripting"
],
"browser_action": { "browser_action": {
"default_area": "navbar" "default_area": "navbar"
} }

View File

@@ -0,0 +1,136 @@
{
"web_accessible_resources": [
"icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png",
"icons/PlayerStartIconSponsorBlocker.svg",
"icons/PlayerStopIconSponsorBlocker.svg",
"icons/PlayerUploadIconSponsorBlocker.svg",
"icons/PlayerUploadFailedIconSponsorBlocker.svg",
"icons/PlayerCancelSegmentIconSponsorBlocker.svg",
"icons/clipboard.svg",
"icons/settings.svg",
"icons/pencil.svg",
"icons/check.svg",
"icons/check-smaller.svg",
"icons/upvote.png",
"icons/downvote.png",
"icons/thumbs_down.svg",
"icons/thumbs_down_locked.svg",
"icons/thumbs_up.svg",
"icons/help.svg",
"icons/report.png",
"icons/close.png",
"icons/skipIcon.svg",
"icons/refresh.svg",
"icons/beep.ogg",
"icons/pause.svg",
"icons/stop.svg",
"icons/skip.svg",
"icons/heart.svg",
"icons/visible.svg",
"icons/not_visible.svg",
"icons/sort.svg",
"icons/money.svg",
"icons/segway.png",
"icons/close-smaller.svg",
"icons/right-arrow.svg",
"icons/campaign.svg",
"icons/star.svg",
"icons/lightbulb.svg",
"icons/bolt.svg",
"icons/stopwatch.svg",
"icons/music-note.svg",
"icons/import.svg",
"icons/export.svg",
"icons/PlayerInfoIconSponsorBlocker.svg",
"icons/PlayerDeleteIconSponsorBlocker.svg",
"icons/dearrow.svg",
"popup.html",
"popup.css",
"content.css",
"shared.css",
"js/document.js",
"libs/Source+Sans+Pro.css",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmRduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmBduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlBduz8A.woff2"
],
"permissions": [
"https://sponsor.ajay.app/*"
],
"optional_permissions": [
"*://*/*"
],
"browser_action": {
"default_title": "SponsorBlock",
"default_popup": "popup.html",
"default_icon": {
"16": "icons/IconSponsorBlocker16px.png",
"32": "icons/IconSponsorBlocker32px.png",
"64": "icons/IconSponsorBlocker64px.png",
"128": "icons/IconSponsorBlocker128px.png"
},
"theme_icons": [
{
"light": "icons/IconSponsorBlocker16px.png",
"dark": "icons/IconSponsorBlocker16px.png",
"size": 16
},
{
"light": "icons/IconSponsorBlocker32px.png",
"dark": "icons/IconSponsorBlocker32px.png",
"size": 32
},
{
"light": "icons/IconSponsorBlocker64px.png",
"dark": "icons/IconSponsorBlocker64px.png",
"size": 64
},
{
"light": "icons/IconSponsorBlocker128px.png",
"dark": "icons/IconSponsorBlocker128px.png",
"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
}
]
},
"background": {
"scripts":[
"./js/background.js"
]
},
"content_scripts": [{
"run_at": "document_start",
"matches": [
"https://*.youtube.com/*",
"https://www.youtube-nocookie.com/embed/*"
],
"exclude_matches": [
"https://accounts.youtube.com/RotateCookiesPage*"
],
"all_frames": true,
"js": [
"./js/content.js"
],
"css": [
"content.css",
"shared.css"
]
}],
"manifest_version": 2
}

View File

@@ -1,141 +1,10 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "SponsorBlock", "short_name": "SponsorBlock",
"version": "5.5.8", "version": "5.6.1",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app", "homepage_url": "https://sponsor.ajay.app",
"content_scripts": [{
"run_at": "document_start",
"matches": [
"https://*.youtube.com/*",
"https://www.youtube-nocookie.com/embed/*"
],
"all_frames": true,
"js": [
"./js/content.js"
],
"css": [
"content.css",
"shared.css"
]
}],
"web_accessible_resources": [
"icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png",
"icons/PlayerStartIconSponsorBlocker.svg",
"icons/PlayerStopIconSponsorBlocker.svg",
"icons/PlayerUploadIconSponsorBlocker.svg",
"icons/PlayerUploadFailedIconSponsorBlocker.svg",
"icons/PlayerCancelSegmentIconSponsorBlocker.svg",
"icons/clipboard.svg",
"icons/settings.svg",
"icons/pencil.svg",
"icons/check.svg",
"icons/check-smaller.svg",
"icons/upvote.png",
"icons/downvote.png",
"icons/thumbs_down.svg",
"icons/thumbs_down_locked.svg",
"icons/thumbs_up.svg",
"icons/help.svg",
"icons/report.png",
"icons/close.png",
"icons/skipIcon.svg",
"icons/refresh.svg",
"icons/beep.ogg",
"icons/pause.svg",
"icons/stop.svg",
"icons/skip.svg",
"icons/heart.svg",
"icons/visible.svg",
"icons/not_visible.svg",
"icons/sort.svg",
"icons/money.svg",
"icons/segway.png",
"icons/close-smaller.svg",
"icons/right-arrow.svg",
"icons/campaign.svg",
"icons/star.svg",
"icons/lightbulb.svg",
"icons/bolt.svg",
"icons/stopwatch.svg",
"icons/music-note.svg",
"icons/import.svg",
"icons/export.svg",
"icons/PlayerInfoIconSponsorBlocker.svg",
"icons/PlayerDeleteIconSponsorBlocker.svg",
"icons/dearrow.svg",
"popup.html",
"popup.css",
"content.css",
"shared.css",
"js/document.js",
"libs/Source+Sans+Pro.css",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlxdu.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmRduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwmBduz8A.woff2",
"libs/6xKydSBYKcSV-LCoeQqfX1RYOo3ig4vwlBduz8A.woff2"
],
"permissions": [
"storage",
"https://sponsor.ajay.app/*"
],
"optional_permissions": [
"*://*/*"
],
"browser_action": {
"default_title": "SponsorBlock",
"default_popup": "popup.html",
"default_icon": {
"16": "icons/IconSponsorBlocker16px.png",
"32": "icons/IconSponsorBlocker32px.png",
"64": "icons/IconSponsorBlocker64px.png",
"128": "icons/IconSponsorBlocker128px.png"
},
"theme_icons": [
{
"light": "icons/IconSponsorBlocker16px.png",
"dark": "icons/IconSponsorBlocker16px.png",
"size": 16
},
{
"light": "icons/IconSponsorBlocker32px.png",
"dark": "icons/IconSponsorBlocker32px.png",
"size": 32
},
{
"light": "icons/IconSponsorBlocker64px.png",
"dark": "icons/IconSponsorBlocker64px.png",
"size": 64
},
{
"light": "icons/IconSponsorBlocker128px.png",
"dark": "icons/IconSponsorBlocker128px.png",
"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
}
]
},
"background": {
"scripts":[
"./js/background.js"
]
},
"icons": { "icons": {
"16": "icons/IconSponsorBlocker16px.png", "16": "icons/IconSponsorBlocker16px.png",
"32": "icons/IconSponsorBlocker32px.png", "32": "icons/IconSponsorBlocker32px.png",
@@ -145,9 +14,12 @@
"512": "icons/IconSponsorBlocker512px.png", "512": "icons/IconSponsorBlocker512px.png",
"1024": "icons/IconSponsorBlocker1024px.png" "1024": "icons/IconSponsorBlocker1024px.png"
}, },
"permissions": [
"storage",
"scripting"
],
"options_ui": { "options_ui": {
"page": "options/options.html", "page": "options/options.html",
"open_in_tab": true "open_in_tab": true
}, }
"manifest_version": 2
} }

View File

@@ -2,9 +2,6 @@
"background": { "background": {
"persistent": false "persistent": false
}, },
"permissions": [
"scripting"
],
"optional_permissions": [ "optional_permissions": [
"webNavigation" "webNavigation"
] ]

12
package-lock.json generated
View File

@@ -6110,9 +6110,9 @@
"dev": true "dev": true
}, },
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.4", "version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -18369,9 +18369,9 @@
"dev": true "dev": true
}, },
"follow-redirects": { "follow-redirects": {
"version": "1.15.4", "version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true "dev": true
}, },
"for-each": { "for-each": {

View File

@@ -26,6 +26,11 @@
transition: transform .1s cubic-bezier(0,0,0.2,1); transition: transform .1s cubic-bezier(0,0,0.2,1);
} }
/* May 2024 hover preview */
.YtPlayerProgressBarProgressBar #previewbar {
transform: none;
}
.ytp-big-mode #previewbar { .ytp-big-mode #previewbar {
transform: scaleY(0.625) translateY(-30%) translateY(1.5px); transform: scaleY(0.625) translateY(-30%) translateY(1.5px);
} }

View File

@@ -219,20 +219,22 @@
__MSG_showSkipNotice__ __MSG_showSkipNotice__
</label> </label>
</div> </div>
<div data-type="selector" data-sync="noticeVisibilityMode" data-dependent-on="dontShowNotice">
<br/>
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
<option value="0">__MSG_noticeVisibilityMode0__</option>
<option value="1">__MSG_noticeVisibilityMode1__</option>
<option value="2">__MSG_noticeVisibilityMode2__</option>
<option value="3">__MSG_noticeVisibilityMode3__</option>
<option value="4">__MSG_noticeVisibilityMode4__</option>
</select>
</div>
</div> </div>
<div data-type="selector" data-sync="noticeVisibilityMode">
<label class="optionLabel" for="noticeVisibilityMode">__MSG_noticeVisibilityLabel__:</label>
<select id="noticeVisibilityMode" class="selector-element optionsSelector" >
<option value="0">__MSG_noticeVisibilityMode0__</option>
<option value="1">__MSG_noticeVisibilityMode1__</option>
<option value="2">__MSG_noticeVisibilityMode2__</option>
<option value="3">__MSG_noticeVisibilityMode3__</option>
<option value="4">__MSG_noticeVisibilityMode4__</option>
</select>
</div>
<div data-type="toggle" data-sync="showCategoryGuidelines"> <div data-type="toggle" data-sync="showCategoryGuidelines">
<div class="switch-container"> <div class="switch-container">
<label class="switch"> <label class="switch">
@@ -634,7 +636,19 @@
<div class="small-description">__MSG_whatTrackDownvotes__</div> <div class="small-description">__MSG_whatTrackDownvotes__</div>
</div> </div>
<div data-type="toggle" data-sync="trackDownvotesInPrivate" data-confirm-on="false">
<div class="switch-container">
<label class="switch">
<input id="trackDownvotesInPrivate" type="checkbox" checked>
<span class="slider round"></span>
</label>
<label class="switch-label" for="trackDownvotesInPrivate">
__MSG_enableTrackDownvotesInPrivate__
</label>
</div>
</div>
<div data-type="button-press" data-sync="copyDebugInformation" data-confirm-message="copyDebugInformation"> <div data-type="button-press" data-sync="copyDebugInformation" data-confirm-message="copyDebugInformation">
<div class="option-button trigger-button"> <div class="option-button trigger-button">
__MSG_copyDebugInformation__ __MSG_copyDebugInformation__

View File

@@ -7,13 +7,9 @@ import { sendRealRequestToCustomServer, setupBackgroundRequestProxy } from "../m
import { setupTabUpdates } from "../maze-utils/src/tab-updates"; import { setupTabUpdates } from "../maze-utils/src/tab-updates";
import { generateUserID } from "../maze-utils/src/setup"; import { generateUserID } from "../maze-utils/src/setup";
// Make the config public for debugging purposes
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/src"; import { isFirefoxOrSafari, waitFor } 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"; import { chromeP } from "../maze-utils/src/browserApi";
@@ -142,9 +138,16 @@ chrome.runtime.onInstalled.addListener(function () {
} }
}, 1500); }, 1500);
// Only do this once the old version understands how to clean itself up if (!isFirefoxOrSafari()) {
if (!isFirefoxOrSafari() && chrome.runtime.getManifest().version !== "5.4.13") {
injectUpdatedScripts().catch(logWarn); injectUpdatedScripts().catch(logWarn);
waitFor(() => Config.isReady()).then(() => {
if (Config.config.supportInvidious) {
injectUpdatedScripts([
utils.getExtraSiteRegistration()
])
}
}).catch(logWarn);
} }
}); });

View File

@@ -272,48 +272,49 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
</div> </div>
): ""} ): ""}
<br/>
{/* Editing Tools */} {/* Editing Tools */}
<span id={"sponsorTimeDeleteButton" + this.idSuffix} <div style={{ marginTop: "3px" }}>
className="sponsorTimeEditButton" <span id={"sponsorTimeDeleteButton" + this.idSuffix}
onClick={this.deleteTime.bind(this)}>
{chrome.i18n.getMessage("delete")}
</span>
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
&& this.state.selectedActionType !== ActionType.Chapter ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton" className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}> onClick={this.deleteTime.bind(this)}>
{chrome.i18n.getMessage("preview")} {chrome.i18n.getMessage("delete")}
</span> </span>
): ""}
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? ( {(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType))
<span id={"sponsorTimeInspectButton" + this.idSuffix} && this.state.selectedActionType !== ActionType.Chapter ? (
className="sponsorTimeEditButton" <span id={"sponsorTimePreviewButton" + this.idSuffix}
onClick={this.inspectTime.bind(this)}> className="sponsorTimeEditButton"
{chrome.i18n.getMessage("inspect")} onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
</span> {chrome.i18n.getMessage("preview")}
): ""} </span>
): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? ( {(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimePreviewEndButton" + this.idSuffix} <span id={"sponsorTimeInspectButton" + this.idSuffix}
className="sponsorTimeEditButton" className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}> onClick={this.inspectTime.bind(this)}>
{chrome.i18n.getMessage("End")} {chrome.i18n.getMessage("inspect")}
</span> </span>
): ""} ): ""}
{(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(this.state.selectedActionType)) ? (
<span id={"sponsorTimePreviewEndButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey, true)}>
{chrome.i18n.getMessage("End")}
</span>
): ""}
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeEditButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.toggleEditTime.bind(this)}>
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
</span>
): ""}
</div>
{(!isNaN(segment[1]) && this.state.selectedActionType != ActionType.Full) ? (
<span id={"sponsorTimeEditButton" + this.idSuffix}
className="sponsorTimeEditButton"
onClick={this.toggleEditTime.bind(this)}>
{this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")}
</span>
): ""}
</div> </div>
); );
} }

View File

@@ -131,7 +131,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
{/* Sponsor Time List */} {/* Sponsor Time List */}
<tr id={"sponsorSkipNoticeMiddleRow" + this.state.idSuffix} <tr id={"sponsorSkipNoticeMiddleRow" + this.state.idSuffix}
className="sponsorTimeMessagesRow" className="sponsorTimeMessagesRow"
style={{maxHeight: (this.contentContainer().v.offsetHeight - 200) + "px"}} style={{maxHeight: (this.contentContainer().v?.offsetHeight - 200) + "px"}}
onMouseDown={(e) => e.stopPropagation()}> onMouseDown={(e) => e.stopPropagation()}>
<td style={{width: "100%"}}> <td style={{width: "100%"}}>
{this.getSponsorTimeMessages()} {this.getSponsorTimeMessages()}

View File

@@ -29,6 +29,7 @@ interface SBConfig {
trackViewCount: boolean; trackViewCount: boolean;
trackViewCountInPrivate: boolean; trackViewCountInPrivate: boolean;
trackDownvotes: boolean; trackDownvotes: boolean;
trackDownvotesInPrivate: boolean;
dontShowNotice: boolean; dontShowNotice: boolean;
noticeVisibilityMode: NoticeVisbilityMode; noticeVisibilityMode: NoticeVisbilityMode;
hideVideoPlayerControls: boolean; hideVideoPlayerControls: boolean;
@@ -139,7 +140,7 @@ interface SBStorage {
downvotedSegments: Record<VideoID & HashedValue, VideoDownvotes>; downvotedSegments: Record<VideoID & HashedValue, VideoDownvotes>;
navigationApiAvailable: boolean; navigationApiAvailable: boolean;
// Used when sync storage disbaled // Used when sync storage disabled
alreadyInstalled: boolean; alreadyInstalled: boolean;
/* Contains unsubmitted segments that the user has created. */ /* Contains unsubmitted segments that the user has created. */
@@ -290,6 +291,7 @@ const syncDefaults = {
trackViewCount: true, trackViewCount: true,
trackViewCountInPrivate: true, trackViewCountInPrivate: true,
trackDownvotes: true, trackDownvotes: true,
trackDownvotesInPrivate: false,
dontShowNotice: false, dontShowNotice: false,
noticeVisibilityMode: NoticeVisbilityMode.FadedForAutoSkip, noticeVisibilityMode: NoticeVisbilityMode.FadedForAutoSkip,
hideVideoPlayerControls: false, hideVideoPlayerControls: false,

View File

@@ -34,7 +34,7 @@ import { ChapterVote } from "./render/ChapterVote";
import { openWarningDialog } from "./utils/warnings"; import { openWarningDialog } from "./utils/warnings";
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src"; import { isFirefoxOrSafari, waitFor } from "../maze-utils/src";
import { getErrorMessage, getFormattedTime } from "../maze-utils/src/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/src/video"; import { getChannelIDInfo, getVideo, getIsAdPlaying, getIsLivePremiere, setIsAdPlaying, checkVideoIDChange, getVideoID, getYouTubeVideoID, setupVideoModule, checkIfNewVideoID, isOnInvidious, isOnMobileYouTube, getLastNonInlineVideoID, triggerVideoIDChange, triggerVideoElementChange, getIsInline } from "../maze-utils/src/video";
import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config"; import { Keybind, StorageChangesObject, isSafari, keybindEquals, keybindToString } from "../maze-utils/src/config";
import { findValidElement } from "../maze-utils/src/dom" import { findValidElement } from "../maze-utils/src/dom"
import { getHash, HashedValue } from "../maze-utils/src/hash"; import { getHash, HashedValue } from "../maze-utils/src/hash";
@@ -49,6 +49,7 @@ import { hideDeArrowPromotion, tryShowingDeArrowPromotion } from "./dearrowPromo
import { asyncRequestToServer } from "./utils/requests"; import { asyncRequestToServer } from "./utils/requests";
import { isMobileControlsOpen } from "./utils/mobileUtils"; import { isMobileControlsOpen } from "./utils/mobileUtils";
import { defaultPreviewTime } from "./utils/constants"; import { defaultPreviewTime } from "./utils/constants";
import { onVideoPage } from "../maze-utils/src/pageInfo";
cleanPage(); cleanPage();
@@ -72,6 +73,8 @@ let sponsorDataFound = false;
let sponsorTimes: SponsorTime[] = []; let sponsorTimes: SponsorTime[] = [];
let existingChaptersImported = false; let existingChaptersImported = false;
let importingChaptersWaitingForFocus = false; let importingChaptersWaitingForFocus = false;
let importingChaptersWaiting = false;
let triedImportingChapters = false;
// List of open skip notices // List of open skip notices
const skipNotices: SkipNotice[] = []; const skipNotices: SkipNotice[] = [];
let activeSkipKeybindElement: ToggleSkippable = null; let activeSkipKeybindElement: ToggleSkippable = null;
@@ -124,13 +127,10 @@ setupVideoModule({
updateVisibilityOfPlayerControlsButton(); updateVisibilityOfPlayerControlsButton();
}, },
resetValues, resetValues,
documentScript documentScript: chrome.runtime.getManifest().manifest_version === 2 ? documentScript : undefined
}, () => Config); }, () => Config);
setupThumbnailListener(); setupThumbnailListener();
//the video id of the last preview bar update
let lastPreviewBarUpdate: VideoID;
// Is the video currently being switched // Is the video currently being switched
let switchingVideos = null; let switchingVideos = null;
@@ -168,7 +168,6 @@ let submissionNotice: SubmissionNotice = null;
let lastResponseStatus: number; let lastResponseStatus: number;
let retryCount = 0; let retryCount = 0;
let lookupWaiting = false;
// Contains all of the functions and variables needed by the skip notice // Contains all of the functions and variables needed by the skip notice
const skipNoticeContentContainer: ContentContainer = () => ({ const skipNoticeContentContainer: ContentContainer = () => ({
@@ -219,7 +218,7 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
found: sponsorDataFound, found: sponsorDataFound,
status: lastResponseStatus, status: lastResponseStatus,
sponsorTimes: sponsorTimes, sponsorTimes: sponsorTimes,
time: getVideo().currentTime, time: getVideo()?.currentTime ?? 0,
onMobileYouTube: isOnMobileYouTube() onMobileYouTube: isOnMobileYouTube()
}); });
@@ -259,13 +258,15 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
case "refreshSegments": case "refreshSegments":
// update video on refresh if videoID invalid // update video on refresh if videoID invalid
if (!getVideoID()) { if (!getVideoID()) {
checkVideoIDChange().then(() => { checkVideoIDChange();
// if still no video ID found, return an empty info to the popup
if (!getVideoID()) chrome.runtime.sendMessage({ message: "infoUpdated" });
});
} }
// if popup rescieves no response, or the videoID is invalid,
// it will assume the page is not a video page and stop the refresh animation
sendResponse({ hasVideo: getVideoID() != null });
// fetch segments // fetch segments
sponsorsLookup(false); if (getVideoID()) {
sponsorsLookup(false);
}
break; break;
case "unskip": case "unskip":
@@ -303,7 +304,9 @@ function messageListener(request: Message, sender: unknown, sendResponse: (respo
if (!sponsorTimesSubmitting.some( if (!sponsorTimesSubmitting.some(
(s) => Math.abs(s.segment[0] - segment.segment[0]) < 1 (s) => Math.abs(s.segment[0] - segment.segment[0]) < 1
&& Math.abs(s.segment[1] - segment.segment[1]) < 1)) { && Math.abs(s.segment[1] - segment.segment[1]) < 1)) {
if (segment.category === "chapter" && !utils.getCategorySelection("chapter")) { const hasChaptersPermission = (Config.config.showCategoryWithoutPermission
|| Config.config.permissions["chapter"]);
if (segment.category === "chapter" && (!utils.getCategorySelection("chapter") || !hasChaptersPermission)) {
segment.category = "chooseACategory" as Category; segment.category = "chooseACategory" as Category;
segment.actionType = ActionType.Skip; segment.actionType = ActionType.Skip;
segment.description = ""; segment.description = "";
@@ -382,6 +385,7 @@ function resetValues() {
sponsorTimes = []; sponsorTimes = [];
existingChaptersImported = false; existingChaptersImported = false;
triedImportingChapters = false;
sponsorSkipped = []; sponsorSkipped = [];
lastResponseStatus = 0; lastResponseStatus = 0;
shownSegmentFailedToFetchWarning = false; shownSegmentFailedToFetchWarning = false;
@@ -398,8 +402,9 @@ function resetValues() {
//reset sponsor data found check //reset sponsor data found check
sponsorDataFound = false; sponsorDataFound = false;
if (switchingVideos === null) { // When first loading a video, it is not switching videos
// When first loading a video, it is not switching videos // Hover play also doesn't need this check
if (switchingVideos === null || !onVideoPage()) {
switchingVideos = false; switchingVideos = false;
} else { } else {
switchingVideos = true; switchingVideos = true;
@@ -456,6 +461,17 @@ function videoIDChange(): void {
updateSponsorTimesSubmitting(); updateSponsorTimesSubmitting();
tryShowingDeArrowPromotion().catch(logWarn); tryShowingDeArrowPromotion().catch(logWarn);
checkPreviewbarState();
if (getIsInline()) {
// Hover preview progress bar can take some time to appear
// and if the miniplayer is also active then it would
// attach to the wrong one
setTimeout(checkPreviewbarState, 500);
setTimeout(checkPreviewbarState, 1000);
setTimeout(checkPreviewbarState, 3000);
}
} }
function handleMobileControlsMutations(): void { function handleMobileControlsMutations(): void {
@@ -484,12 +500,7 @@ function handleMobileControlsMutations(): void {
createPreviewBar(); createPreviewBar();
} }
/** function getPreviewBarAttachElement(): HTMLElement | null {
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const progressElementOptions = [{ const progressElementOptions = [{
// For new mobile YouTube (#1287) // For new mobile YouTube (#1287)
selector: ".progress-bar-line", selector: ".progress-bar-line",
@@ -499,11 +510,22 @@ function createPreviewBar(): void {
selector: ".YtProgressBarProgressBarLine", selector: ".YtProgressBarProgressBarLine",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
// For Desktop YouTube // For newer mobile YouTube (May 2024)
selector: ".YtmProgressBarProgressBarLine",
isVisibleCheck: true
}, {
// For desktop YouTube hover play
// Priority is given to the hover play progress bar over the main progress bar
// for miniplayer + hover preview case
// Second is new hover play selector
selector: "#video-preview .ytp-progress-bar, #video-preview .YtProgressBarLineHost",
isVisibleCheck: true
}, {
// For desktop YouTube
selector: ".ytp-progress-bar", selector: ".ytp-progress-bar",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
// For Desktop YouTube // For desktop YouTube
selector: ".no-model.cue-range-marker", selector: ".no-model.cue-range-marker",
isVisibleCheck: true isVisibleCheck: true
}, { }, {
@@ -526,14 +548,27 @@ function createPreviewBar(): void {
const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0]; const el = option.isVisibleCheck ? findValidElement(allElements) : allElements[0];
if (el) { if (el) {
const chapterVote = new ChapterVote(voteAsync); return el;
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
updatePreviewBar();
break;
} }
} }
return null;
}
/**
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const el = getPreviewBarAttachElement();
if (el) {
const chapterVote = new ChapterVote(voteAsync);
previewBar = new PreviewBar(el, isOnMobileYouTube(), isOnInvidious(), chapterVote, () => importExistingChapters(true));
updatePreviewBar();
}
} }
/** /**
@@ -787,6 +822,8 @@ function inMuteSegment(currentTime: number, includeOverlap: boolean): boolean {
* This makes sure the videoID is still correct and if the sponsorTime is included * This makes sure the videoID is still correct and if the sponsorTime is included
*/ */
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean { function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
if (!onVideoPage()) return false;
const currentVideoID = getYouTubeVideoID(); const currentVideoID = getYouTubeVideoID();
const recordedVideoID = videoID || getVideoID(); const recordedVideoID = videoID || getVideoID();
if (currentVideoID !== recordedVideoID || (sponsorTime if (currentVideoID !== recordedVideoID || (sponsorTime
@@ -810,14 +847,16 @@ let playbackRateCheckInterval: NodeJS.Timeout | null = null;
let lastPlaybackSpeed = 1; let lastPlaybackSpeed = 1;
let setupVideoListenersFirstTime = true; let setupVideoListenersFirstTime = true;
function setupVideoListeners() { function setupVideoListeners() {
const video = getVideo();
//wait until it is loaded //wait until it is loaded
getVideo().addEventListener('loadstart', videoOnReadyListener) video.addEventListener('loadstart', videoOnReadyListener)
getVideo().addEventListener('durationchange', durationChangeListener); video.addEventListener('durationchange', durationChangeListener);
if (setupVideoListenersFirstTime) { if (setupVideoListenersFirstTime) {
addCleanupListener(() => { addCleanupListener(() => {
getVideo().removeEventListener('loadstart', videoOnReadyListener); video.removeEventListener('loadstart', videoOnReadyListener);
getVideo().removeEventListener('durationchange', durationChangeListener); video.removeEventListener('durationchange', durationChangeListener);
}); });
} }
@@ -833,18 +872,20 @@ function setupVideoListeners() {
startSponsorSchedule(); startSponsorSchedule();
}; };
getVideo().addEventListener('ratechange', rateChangeListener); video.addEventListener('ratechange', rateChangeListener);
// Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740) // Used by videospeed extension (https://github.com/igrigorik/videospeed/pull/740)
getVideo().addEventListener('videoSpeed_ratechange', rateChangeListener); video.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
// gone back to the begining // gone back to the begining
if (getVideo().readyState <= HTMLMediaElement.HAVE_CURRENT_DATA if (video.readyState <= HTMLMediaElement.HAVE_CURRENT_DATA
&& getVideo().currentTime === 0) return; && video.currentTime === 0) return;
updateVirtualTime(); updateVirtualTime();
checkForMiniplayerPlaying();
if (switchingVideos || lastPausedAtZero) { if (switchingVideos || lastPausedAtZero) {
switchingVideos = false; switchingVideos = false;
@@ -860,15 +901,15 @@ function setupVideoListeners() {
updateAdFlag(); updateAdFlag();
// Make sure it doesn't get double called with the playing event // Make sure it doesn't get double called with the playing event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) { || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
startSponsorSchedule(); startSponsorSchedule();
} }
}; };
getVideo().addEventListener('play', playListener); video.addEventListener('play', playListener);
const playingListener = () => { const playingListener = () => {
updateVirtualTime(); updateVirtualTime();
@@ -876,8 +917,8 @@ function setupVideoListeners() {
if (startedWaiting) { if (startedWaiting) {
startedWaiting = false; startedWaiting = false;
logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 logDebug(`[SB] Playing event after buffering: ${Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)}`); || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)}`);
} }
if (switchingVideos) { if (switchingVideos) {
@@ -889,63 +930,63 @@ function setupVideoListeners() {
} }
// Make sure it doesn't get double called with the play event // Make sure it doesn't get double called with the play event
if (Math.abs(lastCheckVideoTime - getVideo().currentTime) > 0.3 if (Math.abs(lastCheckVideoTime - video.currentTime) > 0.3
|| (lastCheckVideoTime !== getVideo().currentTime && Date.now() - lastCheckTime > 2000)) { || (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000)) {
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
startSponsorSchedule(); startSponsorSchedule();
} }
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval); if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
lastPlaybackSpeed = getVideo().playbackRate; lastPlaybackSpeed = video.playbackRate;
// Video speed controller compatibility // Video speed controller compatibility
// That extension makes rate change events not propagate // That extension makes rate change events not propagate
if (document.body.classList.contains("vsc-initialized")) { if (document.body.classList.contains("vsc-initialized")) {
playbackRateCheckInterval = setInterval(() => { playbackRateCheckInterval = setInterval(() => {
if ((!getVideoID() || getVideo().paused) && playbackRateCheckInterval) { if ((!getVideoID() || video.paused) && playbackRateCheckInterval) {
// Video is gone, stop checking // Video is gone, stop checking
clearInterval(playbackRateCheckInterval); clearInterval(playbackRateCheckInterval);
return; return;
} }
if (getVideo().playbackRate !== lastPlaybackSpeed) { if (video.playbackRate !== lastPlaybackSpeed) {
lastPlaybackSpeed = getVideo().playbackRate; lastPlaybackSpeed = video.playbackRate;
rateChangeListener(); rateChangeListener();
} }
}, 2000); }, 2000);
} }
}; };
getVideo().addEventListener('playing', playingListener); video.addEventListener('playing', playingListener);
const seekingListener = () => { const seekingListener = () => {
lastKnownVideoTime.fromPause = false; lastKnownVideoTime.fromPause = false;
if (!getVideo().paused){ if (!video.paused){
// Reset lastCheckVideoTime // Reset lastCheckVideoTime
lastCheckTime = Date.now(); lastCheckTime = Date.now();
lastCheckVideoTime = getVideo().currentTime; lastCheckVideoTime = video.currentTime;
updateVirtualTime(); updateVirtualTime();
clearWaitingTime(); clearWaitingTime();
// Sometimes looped videos loop back to almost zero, but not quite // Sometimes looped videos loop back to almost zero, but not quite
if (getVideo().loop && getVideo().currentTime < 0.2) { if (video.loop && video.currentTime < 0.2) {
startSponsorSchedule(false, 0); startSponsorSchedule(false, 0);
} else { } else {
startSponsorSchedule(); startSponsorSchedule();
} }
} else { } else {
updateActiveSegment(getVideo().currentTime); updateActiveSegment(video.currentTime);
if (getVideo().currentTime === 0) { if (video.currentTime === 0) {
lastPausedAtZero = true; lastPausedAtZero = true;
} }
} }
}; };
getVideo().addEventListener('seeking', seekingListener); video.addEventListener('seeking', seekingListener);
const stoppedPlayback = () => { const stoppedPlayback = () => {
// Reset lastCheckVideoTime // Reset lastCheckVideoTime
@@ -956,7 +997,7 @@ function setupVideoListeners() {
lastKnownVideoTime.videoTime = null; lastKnownVideoTime.videoTime = null;
lastKnownVideoTime.preciseTime = null; lastKnownVideoTime.preciseTime = null;
updateWaitingTime(); updateWaitingTime(video);
cancelSponsorSchedule(); cancelSponsorSchedule();
}; };
@@ -965,26 +1006,26 @@ function setupVideoListeners() {
stoppedPlayback(); stoppedPlayback();
}; };
getVideo().addEventListener('pause', pauseListener); video.addEventListener('pause', pauseListener);
const waitingListener = () => { const waitingListener = () => {
logDebug("[SB] Not skipping due to buffering"); logDebug("[SB] Not skipping due to buffering");
startedWaiting = true; startedWaiting = true;
stoppedPlayback(); stoppedPlayback();
}; };
getVideo().addEventListener('waiting', waitingListener); video.addEventListener('waiting', waitingListener);
startSponsorSchedule(); startSponsorSchedule();
if (setupVideoListenersFirstTime) { if (setupVideoListenersFirstTime) {
addCleanupListener(() => { addCleanupListener(() => {
getVideo().removeEventListener('play', playListener); video.removeEventListener('play', playListener);
getVideo().removeEventListener('playing', playingListener); video.removeEventListener('playing', playingListener);
getVideo().removeEventListener('seeking', seekingListener); video.removeEventListener('seeking', seekingListener);
getVideo().removeEventListener('ratechange', rateChangeListener); video.removeEventListener('ratechange', rateChangeListener);
getVideo().removeEventListener('videoSpeed_ratechange', rateChangeListener); video.removeEventListener('videoSpeed_ratechange', rateChangeListener);
getVideo().removeEventListener('pause', pauseListener); video.removeEventListener('pause', pauseListener);
getVideo().removeEventListener('waiting', waitingListener); video.removeEventListener('waiting', waitingListener);
if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval); if (playbackRateCheckInterval) clearInterval(playbackRateCheckInterval);
}); });
@@ -1035,8 +1076,8 @@ function updateVirtualTime() {
} }
} }
function updateWaitingTime(): void { function updateWaitingTime(video: HTMLVideoElement): void {
lastTimeFromWaitingEvent = getVideo().currentTime; lastTimeFromWaitingEvent = video.currentTime;
} }
function clearWaitingTime(): void { function clearWaitingTime(): void {
@@ -1070,24 +1111,18 @@ function setupCategoryPill() {
} }
async function sponsorsLookup(keepOldSubmissions = true) { async function sponsorsLookup(keepOldSubmissions = true) {
if (lookupWaiting) return;
//there is still no video here
if (!getVideo()) {
lookupWaiting = true;
setTimeout(() => {
lookupWaiting = false;
sponsorsLookup()
}, 100);
return;
}
const categories: string[] = Config.config.categorySelections.map((category) => category.name); const categories: string[] = Config.config.categorySelections.map((category) => category.name);
const extraRequestData: Record<string, unknown> = {}; const extraRequestData: Record<string, unknown> = {};
const hashParams = getHashParams(); const hashParams = getHashParams();
if (hashParams.requiredSegment) extraRequestData.requiredSegment = hashParams.requiredSegment; if (hashParams.requiredSegment) extraRequestData.requiredSegment = hashParams.requiredSegment;
const hashPrefix = (await getHash(getVideoID(), 1)).slice(0, 4) as VideoID & HashedValue; const videoID = getVideoID()
if (!videoID) {
console.error("[SponsorBlock] Attempted to fetch segments with a null/undefined videoID.");
return;
}
const hashPrefix = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue;
const response = await asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, { const response = await asyncRequestToServer('GET', "/api/skipSegments/" + hashPrefix, {
categories, categories,
actionTypes: getEnabledActionTypes(), actionTypes: getEnabledActionTypes(),
@@ -1157,13 +1192,14 @@ async function sponsorsLookup(keepOldSubmissions = true) {
} }
} }
if (!getVideo()) {
//there is still no video here
await waitFor(() => getVideo(), 5000, 10);
}
startSkipScheduleCheckingForStartSponsors(); startSkipScheduleCheckingForStartSponsors();
//update the preview bar if (!isNaN(getVideo().duration)) {
//leave the type blank for now until categories are added
if (lastPreviewBarUpdate == getVideoID() || (lastPreviewBarUpdate == null && !isNaN(getVideo().duration))) {
//set it now
//otherwise the listener can handle it
updatePreviewBar(); updatePreviewBar();
} }
} else { } else {
@@ -1181,7 +1217,7 @@ async function sponsorsLookup(keepOldSubmissions = true) {
found: sponsorDataFound, found: sponsorDataFound,
status: lastResponseStatus, status: lastResponseStatus,
sponsorTimes: sponsorTimes, sponsorTimes: sponsorTimes,
time: getVideo().currentTime, time: getVideo()?.currentTime ?? 0,
onMobileYouTube: isOnMobileYouTube() onMobileYouTube: isOnMobileYouTube()
}); });
@@ -1191,10 +1227,10 @@ async function sponsorsLookup(keepOldSubmissions = true) {
} }
function importExistingChapters(wait: boolean) { function importExistingChapters(wait: boolean) {
if (!existingChaptersImported) { if (!existingChaptersImported && !importingChaptersWaiting && !triedImportingChapters && onVideoPage() && !isOnMobileYouTube()) {
const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration); const waitCondition = () => getVideo()?.duration && getExistingChapters(getVideoID(), getVideo().duration);
if (!waitCondition() && wait && !document.hasFocus() && !importingChaptersWaitingForFocus) { if (wait && !document.hasFocus() && !importingChaptersWaitingForFocus && !waitCondition()) {
importingChaptersWaitingForFocus = true; importingChaptersWaitingForFocus = true;
const listener = () => { const listener = () => {
importExistingChapters(wait); importExistingChapters(wait);
@@ -1202,14 +1238,17 @@ function importExistingChapters(wait: boolean) {
}; };
window.addEventListener("focus", listener); window.addEventListener("focus", listener);
} else { } else {
importingChaptersWaiting = true;
waitFor(waitCondition, waitFor(waitCondition,
wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => { wait ? 15000 : 0, 400, (c) => c?.length > 0).then((chapters) => {
importingChaptersWaiting = false;
if (!existingChaptersImported && chapters?.length > 0) { if (!existingChaptersImported && chapters?.length > 0) {
sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]); sponsorTimes = (sponsorTimes ?? []).concat(...chapters).sort((a, b) => a.segment[0] - b.segment[0]);
existingChaptersImported = true; existingChaptersImported = true;
updatePreviewBar(); updatePreviewBar();
} }
}).catch(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function }).catch(() => { importingChaptersWaiting = false; triedImportingChapters = true; }); // eslint-disable-line @typescript-eslint/no-empty-function
} }
} }
} }
@@ -1381,9 +1420,6 @@ function updatePreviewBar(): void {
showTimeWithoutSkips(skippedDuration); showTimeWithoutSkips(skippedDuration);
} }
// Update last video id
lastPreviewBarUpdate = getVideoID();
} }
//checks if this channel is whitelisted, should be done only after the channelID has been loaded //checks if this channel is whitelisted, should be done only after the channelID has been loaded
@@ -1407,7 +1443,8 @@ function videoElementChange(newVideo: boolean): void {
setupSkipButtonControlBar(); setupSkipButtonControlBar();
setupCategoryPill(); setupCategoryPill();
} }
updatePreviewBar();
checkPreviewbarState(); checkPreviewbarState();
// Incase the page is still transitioning, check again in a few seconds // Incase the page is still transitioning, check again in a few seconds
@@ -1417,8 +1454,19 @@ function videoElementChange(newVideo: boolean): void {
}) })
} }
let checkingPreviewbarAgain = false;
function checkPreviewbarState(): void { function checkPreviewbarState(): void {
if (previewBar && !utils.findReferenceNode()?.contains(previewBar.container)) { if (!getPreviewBarAttachElement() && !checkingPreviewbarAgain && getVideo() && getVideoID()) {
checkingPreviewbarAgain = true;
setTimeout(() => {
checkingPreviewbarAgain = false;
checkPreviewbarState();
}, 500);
return;
}
if (previewBar && !getPreviewBarAttachElement()?.contains(previewBar.container)) {
previewBar.remove(); previewBar.remove();
previewBar = null; previewBar = null;
} }
@@ -1600,6 +1648,13 @@ function previewTime(time: number, unpause = true) {
//send telemetry and count skip //send telemetry and count skip
function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: number, fullSkip: boolean) { function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped: number, fullSkip: boolean) {
for (const segment of skippingSegments) {
if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
// Count that as a previewed segment
previewedSegment = true;
}
}
if (!Config.config.trackViewCount || (!Config.config.trackViewCountInPrivate && chrome.extension.inIncognitoContext)) return; if (!Config.config.trackViewCount || (!Config.config.trackViewCountInPrivate && chrome.extension.inIncognitoContext)) return;
let counted = false; let counted = false;
@@ -1616,9 +1671,6 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
} }
if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID); if (fullSkip) asyncRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
} else if (!previewedSegment && sponsorTimesSubmitting.some((s) => s.segment === segment.segment)) {
// Count that as a previewed segment
previewedSegment = true;
} }
} }
} }
@@ -1629,8 +1681,9 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
// There will only be one submission if it is manual skip // There will only be one submission if it is manual skip
const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]); const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]);
const isSubmittingSegment = sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment);
if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment)) if ((autoSkip || isSubmittingSegment)
&& v.currentTime !== skipTime[1]) { && v.currentTime !== skipTime[1]) {
switch(skippingSegments[0].actionType) { switch(skippingSegments[0].actionType) {
case ActionType.Poi: case ActionType.Poi:
@@ -1711,7 +1764,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
} }
//send telemetry that a this sponsor was skipped //send telemetry that a this sponsor was skipped
if (autoSkip) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true); if (autoSkip || isSubmittingSegment) sendTelemetryAndCount(skippingSegments, skipTime[1] - skipTime[0], true);
} }
function createSkipNotice(skippingSegments: SponsorTime[], autoSkip: boolean, unskipTime: number, startReskip: boolean) { function createSkipNotice(skippingSegments: SponsorTime[], autoSkip: boolean, unskipTime: number, startReskip: boolean) {
@@ -1801,7 +1854,8 @@ function shouldAutoSkip(segment: SponsorTime): boolean {
return (!Config.config.manualSkipOnFullVideo || !sponsorTimes?.some((s) => s.category === segment.category && s.actionType === ActionType.Full)) return (!Config.config.manualSkipOnFullVideo || !sponsorTimes?.some((s) => s.category === segment.category && s.actionType === ActionType.Full))
&& (utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip || && (utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic") (Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
&& segment.actionType === ActionType.Skip)); && segment.actionType === ActionType.Skip)
|| sponsorTimesSubmitting.some((s) => s.segment === segment.segment));
} }
function shouldSkip(segment: SponsorTime): boolean { function shouldSkip(segment: SponsorTime): boolean {
@@ -2668,3 +2722,22 @@ function setCategoryColorCSSVariables() {
styleContainer.innerText = css; styleContainer.innerText = css;
} }
/**
* If mini player starts playing, then videoID change might have to be called
*/
function checkForMiniplayerPlaying() {
const miniPlayerUI = document.querySelector(".miniplayer") as HTMLElement;
if (!onVideoPage() && isVisible(miniPlayerUI)) {
const videoID = getLastNonInlineVideoID();
if (videoID) {
triggerVideoIDChange(videoID);
// treat as if video element has changed
const video = miniPlayerUI.querySelector("video") as HTMLVideoElement;
if (video && getVideo() !== video) {
triggerVideoElementChange(video);
}
}
}
}

15
src/globals.d.ts vendored
View File

@@ -1,19 +1,4 @@
import { SBObject } from "./config"; import { SBObject } from "./config";
declare global { declare global {
interface Window { SB: SBObject } interface Window { SB: SBObject }
// Remove this once the API becomes stable and types are shipped in @types/chrome
namespace chrome {
namespace declarativeContent {
export interface RequestContentScriptOptions {
allFrames?: boolean;
css?: string[];
instanceType?: "declarativeContent.RequestContentScript";
js?: string[];
matchAboutBlanck?: boolean;
}
export class RequestContentScript {
constructor(options: RequestContentScriptOptions);
}
}
}
} }

View File

@@ -13,6 +13,7 @@ import { DEFAULT_CATEGORY, shortCategoryName } from "../utils/categoryUtils";
import { normalizeChapterName } from "../utils/exporter"; import { normalizeChapterName } from "../utils/exporter";
import { findValidElement } from "../../maze-utils/src/dom"; import { findValidElement } from "../../maze-utils/src/dom";
import { addCleanupListener } from "../../maze-utils/src/cleanup"; import { addCleanupListener } from "../../maze-utils/src/cleanup";
import { isVisible } from "../utils/pageUtils";
const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible'; const TOOLTIP_VISIBLE_CLASS = 'sponsorCategoryTooltipVisible';
const MIN_CHAPTER_SIZE = 0.003; const MIN_CHAPTER_SIZE = 0.003;
@@ -225,10 +226,12 @@ class PreviewBar {
this.segments = segments ?? []; this.segments = segments ?? [];
this.videoDuration = videoDuration ?? 0; this.videoDuration = videoDuration ?? 0;
this.updatePageElements(); this.updatePageElements();
// Sometimes video duration is inaccurate, pull from accessibility info // Sometimes video duration is inaccurate, pull from accessibility info
const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0; const ariaDuration = parseInt(this.progressBar?.getAttribute('aria-valuemax')) ?? 0;
if (ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) { const multipleActiveVideos = [...document.querySelectorAll("video")].filter((v) => isVisible(v)).length > 1;
if (!multipleActiveVideos && ariaDuration && Math.abs(ariaDuration - this.videoDuration) > 3) {
this.videoDuration = ariaDuration; this.videoDuration = ariaDuration;
} }
@@ -236,7 +239,7 @@ class PreviewBar {
} }
private updatePageElements(): void { private updatePageElements(): void {
const allProgressBars = document.querySelectorAll('.ytp-progress-bar') as NodeListOf<HTMLElement>; const allProgressBars = document.querySelectorAll(".ytp-progress-bar") as NodeListOf<HTMLElement>;
this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0]; this.progressBar = findValidElement(allProgressBars) ?? allProgressBars?.[0];
if (this.progressBar) { if (this.progressBar) {
@@ -748,6 +751,7 @@ class PreviewBar {
updateChapterText(segments: SponsorTime[], submittingSegments: SponsorTime[], currentTime: number): SponsorTime[] { updateChapterText(segments: SponsorTime[], submittingSegments: SponsorTime[], currentTime: number): SponsorTime[] {
if (!Config.config.showSegmentNameInChapterBar if (!Config.config.showSegmentNameInChapterBar
|| Config.config.disableSkipping
|| ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) { || ((!segments || segments.length <= 0) && submittingSegments?.length <= 0)) {
const chaptersContainer = this.getChaptersContainer(); const chaptersContainer = this.getChaptersContainer();
if (chaptersContainer) { if (chaptersContainer) {

View File

@@ -103,7 +103,8 @@ export type MessageResponse =
| IsChannelWhitelistedResponse | IsChannelWhitelistedResponse
| Record<string, never> // empty object response {} | Record<string, never> // empty object response {}
| VoteResponse | VoteResponse
| ImportSegmentsResponse; | ImportSegmentsResponse
| RefreshSegmentsResponse;
export interface VoteResponse { export interface VoteResponse {
successType: number; successType: number;
@@ -115,6 +116,10 @@ interface ImportSegmentsResponse {
importedSegments: SponsorTime[]; importedSegments: SponsorTime[];
} }
export interface RefreshSegmentsResponse {
hasVideo: boolean;
}
export interface TimeUpdateMessage { export interface TimeUpdateMessage {
message: "time"; message: "time";
time: number; time: number;

View File

@@ -15,6 +15,7 @@ import {
Message, Message,
MessageResponse, MessageResponse,
PopupMessage, PopupMessage,
RefreshSegmentsResponse,
SponsorStartResponse, SponsorStartResponse,
VoteResponse, VoteResponse,
} from "./messageTypes"; } from "./messageTypes";
@@ -459,39 +460,35 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
stopLoadingAnimation = null; stopLoadingAnimation = null;
} }
if (chrome.runtime.lastError) { if (chrome.runtime.lastError || request == undefined || request.found == undefined) {
//This page doesn't have the injected content script, or at least not yet //This page doesn't have the injected content script, or at least not yet
// Or if the request is empty, meaning the current page is not YouTube or a video page
displayNoVideo(); displayNoVideo();
return; return;
} }
// if request has no field other than message, then the page currently being browsed is not YouTube //remove loading text
if (request.found != undefined) { PageElements.mainControls.style.display = "block";
//remove loading text if (request.onMobileYouTube) PageElements.mainControls.classList.add("hidden");
PageElements.mainControls.style.display = "block"; PageElements.whitelistButton.classList.remove("hidden");
if (request.onMobileYouTube) PageElements.mainControls.classList.add("hidden"); PageElements.loadingIndicator.style.display = "none";
PageElements.whitelistButton.classList.remove("hidden");
PageElements.loadingIndicator.style.display = "none";
downloadedTimes = request.sponsorTimes ?? []; downloadedTimes = request.sponsorTimes ?? [];
displayDownloadedSponsorTimes(downloadedTimes, request.time); displayDownloadedSponsorTimes(downloadedTimes, request.time);
if (request.found) { if (request.found) {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound"); PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound");
PageElements.issueReporterImportExport.classList.remove("hidden"); PageElements.issueReporterImportExport.classList.remove("hidden");
} else if (request.status == 404 || request.status == 200) { } else if (request.status == 404 || request.status == 200) {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404"); PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404");
PageElements.issueReporterImportExport.classList.remove("hidden"); PageElements.issueReporterImportExport.classList.remove("hidden");
} else {
if (request.status) {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("connectionError") + request.status;
} else {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("segmentsStillLoading");
}
PageElements.issueReporterImportExport.classList.remove("hidden");
}
} else { } else {
displayNoVideo(); if (request.status) {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("connectionError") + request.status;
} else {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("segmentsStillLoading");
}
PageElements.issueReporterImportExport.classList.remove("hidden");
} }
//see if whitelist button should be swapped //see if whitelist button should be swapped
@@ -564,7 +561,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
return true; return true;
} }
}) })
.sort((a, b) => a.segment[1] - b.segment[1]) .sort((a, b) => b.segment[1] - a.segment[1])
.sort((a, b) => a.segment[0] - b.segment[0]); .sort((a, b) => a.segment[0] - b.segment[0]);
//add them as buttons to the issue reporting container //add them as buttons to the issue reporting container
@@ -982,9 +979,17 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
stopLoadingAnimation = AnimationUtils.applyLoadingAnimation(PageElements.refreshSegmentsButton, 0.3); stopLoadingAnimation = AnimationUtils.applyLoadingAnimation(PageElements.refreshSegmentsButton, 0.3);
} }
function refreshSegments() { async function refreshSegments() {
startLoadingAnimation(); startLoadingAnimation();
sendTabMessage({ message: 'refreshSegments' }); const response = await sendTabMessageAsync({ message: 'refreshSegments' }) as RefreshSegmentsResponse;
if (response == null || !response.hasVideo) {
if (stopLoadingAnimation != null) {
stopLoadingAnimation();
stopLoadingAnimation = null;
}
displayNoVideo();
}
} }
function skipSegment(actionType: ActionType, UUID: SegmentUUID, element?: HTMLElement): void { function skipSegment(actionType: ActionType, UUID: SegmentUUID, element?: HTMLElement): void {

View File

@@ -2,7 +2,7 @@ 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/src/hash"; import { getHash, HashedValue } from "../maze-utils/src/hash";
import { isFirefoxOrSafari, waitFor } from "../maze-utils/src"; import { waitFor } from "../maze-utils/src";
import { findValidElementFromSelector } from "../maze-utils/src/dom"; import { findValidElementFromSelector } from "../maze-utils/src/dom";
import { isSafari } from "../maze-utils/src/config"; import { isSafari } from "../maze-utils/src/config";
@@ -46,10 +46,7 @@ export default class Utils {
*/ */
setupExtraSitePermissions(callback: (granted: boolean) => void): void { setupExtraSitePermissions(callback: (granted: boolean) => void): void {
const permissions = []; const permissions = [];
if (!isFirefoxOrSafari()) { if (isSafari()) {
permissions.push("declarativeContent");
}
if (!isFirefoxOrSafari() || isSafari()) {
permissions.push("webNavigation"); permissions.push("webNavigation");
} }
@@ -67,6 +64,17 @@ export default class Utils {
}); });
} }
getExtraSiteRegistration(): Registration {
return {
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: this.js,
css: this.css,
matches: this.getPermissionRegex()
};
}
/** /**
* Registers the content scripts for the extra sites. * Registers the content scripts for the extra sites.
* Will use a different method depending on the browser. * Will use a different method depending on the browser.
@@ -75,14 +83,7 @@ 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 registration: Registration = { const registration = this.getExtraSiteRegistration();
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: this.js,
css: this.css,
matches: this.getPermissionRegex()
};
if (this.backgroundScriptContainer) { if (this.backgroundScriptContainer) {
this.backgroundScriptContainer.registerFirefoxContentScript(registration); this.backgroundScriptContainer.registerFirefoxContentScript(registration);
@@ -106,11 +107,6 @@ export default class Utils {
}); });
} }
if (!isFirefoxOrSafari() && chrome.declarativeContent) {
// Only if we have permission
chrome.declarativeContent.onPageChanged.removeRules(["invidious"]);
}
chrome.permissions.remove({ chrome.permissions.remove({
origins: this.getPermissionRegex() origins: this.getPermissionRegex()
}); });
@@ -135,8 +131,10 @@ export default class Utils {
containsInvidiousPermission(): Promise<boolean> { containsInvidiousPermission(): Promise<boolean> {
return new Promise((resolve) => { return new Promise((resolve) => {
let permissions = ["declarativeContent"]; const permissions = [];
if (isFirefoxOrSafari()) permissions = []; if (isSafari()) {
permissions.push("webNavigation");
}
chrome.permissions.contains({ chrome.permissions.contains({
origins: this.getPermissionRegex(), origins: this.getPermissionRegex(),
@@ -281,7 +279,8 @@ export default class Utils {
} }
async addHiddenSegment(videoID: VideoID, segmentUUID: string, hidden: SponsorHideType) { async addHiddenSegment(videoID: VideoID, segmentUUID: string, hidden: SponsorHideType) {
if (chrome.extension.inIncognitoContext || !Config.config.trackDownvotes) return; if ((chrome.extension.inIncognitoContext && !Config.config.trackDownvotesInPrivate)
|| !Config.config.trackDownvotes) return;
const hashedVideoID = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue; const hashedVideoID = (await getHash(videoID, 1)).slice(0, 4) as VideoID & HashedValue;
const UUIDHash = await getHash(segmentUUID, 1); const UUIDHash = await getHash(segmentUUID, 1);

View File

@@ -53,24 +53,23 @@ export function importTimes(data: string, videoDuration: number): SponsorTime[]
titleRight = removeIf(split2[split2.length - 1], specialCharMatchers) titleRight = removeIf(split2[split2.length - 1], specialCharMatchers)
const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight; const title = titleLeft?.length > titleRight?.length ? titleLeft : titleRight;
if (title) { const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
const determinedCategory = chapterNames.find(c => c.names.includes(title))?.code as Category;
const segment: SponsorTime = { const category = title ? (determinedCategory ?? ("chapter" as Category)) : "chooseACategory" as Category;
segment: [startTime, getFormattedTimeToSeconds(match[1])], const segment: SponsorTime = {
category: determinedCategory ?? ("chapter" as Category), segment: [startTime, getFormattedTimeToSeconds(match[1])],
actionType: determinedCategory ? ActionType.Skip : ActionType.Chapter, category,
description: title, actionType: category === "chapter" ? ActionType.Chapter : ActionType.Skip,
source: SponsorSourceType.Local, description: category === "chapter" ? title : null,
UUID: generateUserID() as SegmentUUID source: SponsorSourceType.Local,
}; UUID: generateUserID() as SegmentUUID
};
if (result.length > 0 && result[result.length - 1].segment[1] === null) { if (result.length > 0 && result[result.length - 1].segment[1] === null) {
result[result.length - 1].segment[1] = segment.segment[0]; result[result.length - 1].segment[1] = segment.segment[0];
}
result.push(segment);
} }
result.push(segment);
} }
} }
} }

View File

@@ -1,12 +1,22 @@
window["SBLogs"] = { if (typeof (window) !== "undefined") {
debug: [], window["SBLogs"] = {
warn: [] debug: [],
}; warn: []
};
}
export function logDebug(message: string) { export function logDebug(message: string) {
window["SBLogs"].debug.push(`[${new Date().toISOString()}] ${message}`); if (typeof (window) !== "undefined") {
window["SBLogs"].debug.push(`[${new Date().toISOString()}] ${message}`);
} else {
console.log(`[${new Date().toISOString()}] ${message}`)
}
} }
export function logWarn(message: string) { export function logWarn(message: string) {
window["SBLogs"].warn.push(`[${new Date().toISOString()}] ${message}`); if (typeof (window) !== "undefined") {
window["SBLogs"].warn.push(`[${new Date().toISOString()}] ${message}`);
} else {
console.warn(`[${new Date().toISOString()}] ${message}`)
}
} }

View File

@@ -11,6 +11,7 @@ const chromeManifestExtra = require("../manifest/chrome-manifest-extra.json");
const safariManifestExtra = require("../manifest/safari-manifest-extra.json"); const safariManifestExtra = require("../manifest/safari-manifest-extra.json");
const betaManifestExtra = require("../manifest/beta-manifest-extra.json"); const betaManifestExtra = require("../manifest/beta-manifest-extra.json");
const firefoxBetaManifestExtra = require("../manifest/firefox-beta-manifest-extra.json"); const firefoxBetaManifestExtra = require("../manifest/firefox-beta-manifest-extra.json");
const manifestV2ManifestExtra = require("../manifest/manifest-v2-extra.json");
// schema for options object // schema for options object
const schema = { const schema = {
@@ -41,12 +42,14 @@ class BuildManifest {
// Add missing manifest elements // Add missing manifest elements
if (this.options.browser.toLowerCase() === "firefox") { if (this.options.browser.toLowerCase() === "firefox") {
mergeObjects(manifest, manifestV2ManifestExtra);
mergeObjects(manifest, firefoxManifestExtra); mergeObjects(manifest, firefoxManifestExtra);
} else if (this.options.browser.toLowerCase() === "chrome" } else if (this.options.browser.toLowerCase() === "chrome"
|| this.options.browser.toLowerCase() === "chromium" || this.options.browser.toLowerCase() === "chromium"
|| this.options.browser.toLowerCase() === "edge") { || this.options.browser.toLowerCase() === "edge") {
mergeObjects(manifest, chromeManifestExtra); mergeObjects(manifest, chromeManifestExtra);
} else if (this.options.browser.toLowerCase() === "safari") { } else if (this.options.browser.toLowerCase() === "safari") {
mergeObjects(manifest, manifestV2ManifestExtra);
mergeObjects(manifest, safariManifestExtra); mergeObjects(manifest, safariManifestExtra);
} }