Compare commits

...

212 Commits
1.2.1 ... 1.2.5

Author SHA1 Message Date
Ajay Ramachandran
2b7f940669 Merge pull request #248 from ajayyy/hotfix-invidious
Fixed firefox content script registration
2020-01-21 23:05:33 -05:00
Ajay Ramachandran
bdcd613f02 Update version number 2020-01-21 23:05:23 -05:00
Ajay Ramachandran
7255300903 Merge pull request #244 from OfficialNoob/patch-5
Support options button when not in popup
2020-01-19 21:44:03 -05:00
Ajay Ramachandran
21b2ad71b9 Merge pull request #245 from jplsek/opt-html5
Set options and help page to use html5
2020-01-19 10:11:23 -05:00
Ajay Ramachandran
1ff7e69556 Merge pull request #247 from OfficialNoob/patch-6
Save Map content
2020-01-19 10:09:28 -05:00
Official Noob
f7a3f98ad3 Comments 2020-01-16 18:43:49 +00:00
Official Noob
4cdb874b4f Removed deleteProperty from MapIO 2020-01-16 18:27:29 +00:00
Official Noob
5df0801c64 deleteProperty() if no key provided delete by id 2020-01-16 18:13:07 +00:00
Official Noob
e286797ac5 Update SB.js 2020-01-16 18:03:40 +00:00
Official Noob
e784dc017d Added clear 2020-01-16 18:02:48 +00:00
Official Noob
251339f26b Comments and added delete 2020-01-16 17:57:54 +00:00
Official Noob
3e3b8eab6f Save Map content 2020-01-16 14:29:03 +00:00
Ajay Ramachandran
a7d769dd6d Merge pull request #246 from jplsek/keybind-esc
Allow keybind cancel with ESC
2020-01-15 21:39:14 -05:00
Jeremy Plsek
ad37e9abe7 Allow keybind cancel with ESC 2020-01-15 20:50:51 -05:00
Jeremy Plsek
f99a3f5088 Set options and help page to use html5
- Fix css when using html5
- Add encoding scheme to html
- Remove font-size change on title on hover. It's jarring
seeing the whole page move when trying to move your mouse
to the options.
- Remove center tags
- Remove unnecessary styles
- Fix some minor grammar
2020-01-15 20:30:07 -05:00
Ajay Ramachandran
6f2a09695b Update README.md 2020-01-14 10:32:26 -05:00
Official Noob
9ae8769869 inPopup did not always work 2020-01-13 20:08:06 +00:00
Official Noob
f58a16179a Added "openConfig" message 2020-01-13 19:54:24 +00:00
Official Noob
297c95ac6b Added inPopup check for options button 2020-01-13 19:52:54 +00:00
Ajay Ramachandran
ced3100b4e Merge pull request #243 from Deykun/master
Polish translation created
2020-01-12 19:04:57 -05:00
Szymon T
7358be6faa Shorter version of fullName 2020-01-13 00:27:55 +01:00
Szymon T
03e29dbb81 Polish translation created 2020-01-12 23:46:38 +01:00
Ajay Ramachandran
7cb2915fd7 Fixed firefox content script registration. 2020-01-11 17:48:11 -05:00
Ajay Ramachandran
5348496768 Merge pull request #235 from OfficialNoob/patch-2
Formatting changes & proxy delete support
2020-01-11 15:17:34 -05:00
Ajay Ramachandran
7526abc3e1 Merge pull request #236 from ajayyy/hotfix-invidious
Fixed new line issue
2020-01-11 14:55:34 -05:00
Ajay Ramachandran
1163b6f0ce Fixed wrong variabled being used. 2020-01-11 14:50:11 -05:00
Ajay Ramachandran
7c809419f8 Formatting changes 2020-01-11 14:48:17 -05:00
Ajay Ramachandran
0a42f130ac Fixed new line issue 2020-01-11 14:45:16 -05:00
Official Noob
4de0ae51e8 Formatting changes & proxy delete support 2020-01-11 19:42:35 +00:00
Ajay Ramachandran
f5a4ffabde Merge pull request #234 from ajayyy/hotfix-invidious
Hotfix
2020-01-11 13:42:10 -05:00
Ajay Ramachandran
115b1edf11 Increased version number 2020-01-11 13:41:44 -05:00
Ajay Ramachandran
04942a3a5d Fixed delete button potentially appearing. 2020-01-11 13:35:20 -05:00
Ajay Ramachandran
aee0712ef1 Fixed old sponsortime config being broken. 2020-01-11 13:27:20 -05:00
Ajay Ramachandran
63568aae9c Merge pull request #229 from ajayyy/experimental-ajay
Increase version number
2020-01-10 22:26:22 -05:00
Ajay Ramachandran
bf90d2a8e6 Increase version number 2020-01-10 22:22:55 -05:00
Ajay Ramachandran
d87cb77895 Merge pull request #228 from ajayyy/experimental-ajay
Invidious support fixes
2020-01-10 22:22:24 -05:00
Ajay Ramachandran
36c4ebda65 Added comments to the settimeout on install 2020-01-10 22:16:53 -05:00
Ajay Ramachandran
968df5a2e4 Increased notice width 2020-01-10 22:15:42 -05:00
Ajay Ramachandran
259f7a9439 Added notice info about the Invidious update. TODO: remove this in the future. 2020-01-10 22:15:28 -05:00
Ajay Ramachandran
4f8e1bc827 Fixed formatting. 2020-01-10 20:49:21 -05:00
Ajay Ramachandran
9e8a520d1e Fixed broken voting. 2020-01-10 20:48:16 -05:00
Ajay Ramachandran
7335429541 Added option for auto-vote. 2020-01-10 20:06:16 -05:00
Ajay Ramachandran
5c227f445a Added ublock origin to npm run dev 2020-01-10 19:58:59 -05:00
Ajay Ramachandran
dce90e86bf Added invidious support info to the help page. 2020-01-10 15:46:50 -05:00
Ajay Ramachandran
36d7dcce9b Revert "Removed snopyta.org from the default."
This reverts commit fb974de53b.
2020-01-10 15:17:31 -05:00
Ajay Ramachandran
502bec55c4 Merge pull request #181 from afrmtbl/add-invidious
Initial Invidious support
2020-01-09 22:41:08 -05:00
Ajay Ramachandran
21a61bb238 Fixed options page and manifest. 2020-01-09 22:40:44 -05:00
Ajay Ramachandran
fb974de53b Removed snopyta.org from the default. 2020-01-09 22:34:26 -05:00
Ajay Ramachandran
a5adf73b88 Moved registration removal to a util function. 2020-01-09 22:32:20 -05:00
Ajay Ramachandran
1f4c4c0901 Make content script reregister on firefox every browser restart 2020-01-09 22:13:00 -05:00
Ajay Ramachandran
338fbcea9c Fixed buttons appearing on invidious. 2020-01-09 21:32:56 -05:00
Ajay Ramachandran
a20fa9871e Added support for any invidious instance. 2020-01-09 21:23:25 -05:00
Ajay Ramachandran
25436d9620 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious
# Conflicts:
#	background.js
2020-01-09 20:42:31 -05:00
Ajay Ramachandran
8d3a633d85 Merge pull request #226 from ajayyy/ajay-config-listener
Config callback updating
2020-01-09 20:41:18 -05:00
Ajay Ramachandran
f67568e3b6 Fixed indentation. 2020-01-09 20:29:47 -05:00
Ajay Ramachandran
d902cc5efe Made buttons update with the config. 2020-01-09 20:29:20 -05:00
Ajay Ramachandran
9e89eb521a Added config callback support. 2020-01-09 20:09:32 -05:00
Ajay Ramachandran
f4c5f50f8c Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious 2020-01-09 19:53:49 -05:00
Ajay Ramachandran
4301a6bfe3 Merge pull request #225 from ajayyy/experimental-ajay
Option page fixes
2020-01-09 19:53:40 -05:00
Ajay Ramachandran
2c5a78947a Added instance display 2020-01-09 19:52:20 -05:00
Ajay Ramachandran
8f7eb82b6e Remove unnecessary code 2020-01-09 19:42:18 -05:00
Ajay Ramachandran
d2e1373e2a Fixed more merging issues. 2020-01-09 19:23:05 -05:00
Ajay Ramachandran
d705610855 Fix merge issues 2020-01-09 19:19:30 -05:00
Ajay Ramachandran
c40b6576d6 Updated gitignore. 2020-01-09 15:02:06 -05:00
Ajay Ramachandran
1c3e2fcdad Fixed help page style issue. 2020-01-09 15:01:42 -05:00
Ajay Ramachandran
7acc6c3329 Added warning message when changing the userID. 2020-01-09 15:00:03 -05:00
Ajay Ramachandran
1715ee327f Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into experimental-ajay 2020-01-09 14:28:40 -05:00
Ajay Ramachandran
0481943737 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious
# Conflicts:
#	background.js
#	content.js
#	options/options.js
2020-01-09 14:28:06 -05:00
Ajay Ramachandran
c53bc20294 Merge pull request #219 from OfficialNoob/patch-26
Config proxy [WIP]
2020-01-09 13:24:33 -05:00
Ajay Ramachandran
a8fc22eae8 Reformatted variable name. 2020-01-09 13:17:26 -05:00
Ajay Ramachandran
4ba82f6e00 Set local config right away 2020-01-09 13:16:27 -05:00
Ajay Ramachandran
8fd671d4d3 Added docs and improved consistency. 2020-01-09 12:46:04 -05:00
Ajay Ramachandran
309b1b007e Removed unneeded function 2020-01-09 12:39:48 -05:00
Ajay Ramachandran
d0e7213cc4 Added docs and removed reflection. Also removed inheritance. 2020-01-09 12:38:15 -05:00
Ajay Ramachandran
a2e9688418 Formatting + duplicate code removal. 2020-01-09 12:30:09 -05:00
Ajay Ramachandran
f42c23cd9a Formatting fixes 2020-01-09 12:12:49 -05:00
Official Noob
52f60d70e2 Map support :D 2020-01-09 16:39:23 +00:00
Official Noob
339d05e157 :/ 2020-01-08 23:27:34 +00:00
Official Noob
c0c3640638 Reverted back <Not working> 2020-01-08 23:16:02 +00:00
Official Noob
a314139302 Map storage encoding 2020-01-08 22:22:18 +00:00
Official Noob
bfa0472f84 Reflect 2020-01-08 19:52:41 +00:00
Ajay Ramachandran
fa19e435cc Switched to a listener map. 2020-01-07 22:59:50 -05:00
Ajay Ramachandran
eb4bf89194 Fixed default 2020-01-07 22:12:53 -05:00
Ajay Ramachandran
da8a1376a7 Converted options page to new config system. 2020-01-07 22:02:16 -05:00
Ajay Ramachandran
267132cdde Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into patch-26 2020-01-07 21:24:54 -05:00
Ajay Ramachandran
b8ebe5076b Fixed indentation. 2020-01-07 21:23:59 -05:00
Ajay Ramachandran
cb9877b3b4 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into experimental-ajay 2020-01-06 22:31:17 -05:00
Ajay Ramachandran
c73b9ed5a6 Remove redundant code. 2020-01-06 22:30:35 -05:00
Ajay Ramachandran
1bd0b4349f Fixed build not ignoring ignored folder 2020-01-06 19:51:49 -05:00
Official Noob
d15785146f Update options.js 2020-01-06 23:42:02 +00:00
Official Noob
47d9d93818 Added SB.js to options html 2020-01-06 23:34:33 +00:00
Official Noob
601ff44145 Forgot comma 2020-01-06 23:29:04 +00:00
Official Noob
cbd451949b Added hideDiscordLink, hideDiscordLink 2020-01-06 23:27:07 +00:00
Official Noob
a7dc207c5f Fix format conflict 2020-01-06 23:12:48 +00:00
Official Noob
c20b67d11f Fixed syntax 2020-01-06 21:20:22 +00:00
Official Noob
0b9def800b Update SB.js 2020-01-06 21:17:28 +00:00
Official Noob
d8ae73e96a Update SB.js 2020-01-06 21:14:31 +00:00
Ajay Ramachandran
c99f7925eb Fixed migrate 2020-01-06 16:13:50 -05:00
Official Noob
3627661e1f Backwards compatibility 2020-01-06 21:11:37 +00:00
Official Noob
f1c68a98cf removed SB.config.dontShowNoticeOld 2020-01-06 18:59:38 +00:00
Official Noob
92f10d51aa Removed SB.config.dontShowNoticeOld 2020-01-06 18:58:47 +00:00
Official Noob
bdae68be35 () => 2020-01-06 18:56:37 +00:00
Official Noob
2a4abf958d Map test 2020-01-01 19:20:14 +00:00
Official Noob
1362331a93 Map test 2020-01-01 19:12:15 +00:00
Official Noob
a70aa7723e Map test 2020-01-01 19:11:17 +00:00
Official Noob
a3f5200c9a Map test 2020-01-01 19:10:34 +00:00
Official Noob
1005783034 Update SB.js 2020-01-01 18:02:16 +00:00
Official Noob
278e40207c Create empty array for sponsorTimeKey 2020-01-01 18:00:47 +00:00
Ajay Ramachandran
509b627e88 Made it reenable the permission when an invidious instance is added.
Right now it throws an error
2020-01-01 12:55:35 -05:00
Official Noob
ecd9f6eaff Update content.js 2020-01-01 15:09:13 +00:00
Official Noob
1d2b6b2010 userID 2020-01-01 14:50:05 +00:00
Official Noob
6c4d5c0705 submitTimes async 2020-01-01 14:47:41 +00:00
Official Noob
0533919bde Update SB.js 2020-01-01 14:45:34 +00:00
Official Noob
e02ca1c822 Update SB.js 2020-01-01 14:45:22 +00:00
Official Noob
039c1a178f Update background.js 2020-01-01 14:44:39 +00:00
Official Noob
6f682baa45 Update content.js 2020-01-01 14:30:23 +00:00
Official Noob
0241c0a036 Update SB.js 2020-01-01 14:04:49 +00:00
Official Noob
4ebdcf1cc5 Update content.js 2020-01-01 14:04:18 +00:00
Official Noob
46c3187c89 Update content.js 2020-01-01 13:46:09 +00:00
Official Noob
c65e3c21e3 fix 2020-01-01 13:01:42 +00:00
Official Noob
e35774138f Added run_at document_start 2020-01-01 13:01:18 +00:00
Official Noob
a9b678f0ff dontShowNoticeAgain 2020-01-01 12:36:29 +00:00
Official Noob
32356d711d Update SB.js 2020-01-01 12:35:54 +00:00
Official Noob
477ae3eb2c Update SB.js 2020-01-01 12:27:59 +00:00
Ajay Ramachandran
0b41118232 Added option for custom invidious instances. 2019-12-31 19:09:37 -05:00
Ajay Ramachandran
ea3f9f246e Fixed firefox support. 2019-12-31 18:13:51 -05:00
Official Noob
9dd954e7d8 Added default for trackViewCount 2019-12-31 22:54:02 +00:00
Official Noob
41352a5116 Update content.js 2019-12-31 22:52:41 +00:00
Official Noob
1ac9989288 Use defaults 2019-12-31 22:50:52 +00:00
Ajay Ramachandran
b441cc2123 Added firefox support and support for multiple invidious instances. 2019-12-31 17:48:43 -05:00
Official Noob
5e2bc43722 Update SB.js 2019-12-31 22:48:29 +00:00
Official Noob
da17dd8bae Added addDefaults and resetConfig 2019-12-31 22:46:16 +00:00
Official Noob
87098d1c3e Update content.js 2019-12-31 22:04:40 +00:00
Official Noob
2a1b60596b debug 2019-12-31 21:30:54 +00:00
Official Noob
7bbbe0dcf3 Use SB.config 2019-12-31 20:56:30 +00:00
Official Noob
25672a6496 SB.js content script 2019-12-31 20:17:27 +00:00
Official Noob
796bf6ef45 Added SB.js 2019-12-31 20:10:16 +00:00
Official Noob
6ceeaebd9d Added SB 2019-12-31 20:08:11 +00:00
Official Noob
61b8427270 File used to control the SB object 2019-12-31 20:07:43 +00:00
Official Noob
4450aaa3b3 Moving to separate due to load order 2019-12-31 20:07:03 +00:00
Ajay Ramachandran
b0e0c380dd Added Firefox fixes 2019-12-31 14:50:01 -05:00
Official Noob
8baf11a053 Forgot SB. 2019-12-31 19:20:20 +00:00
Official Noob
67f9697f3f test 2019-12-31 19:17:10 +00:00
Official Noob
a94d941125 Added sync config 2019-12-31 19:16:46 +00:00
Official Noob
2917de6776 Moved localconfig to SB object 2019-12-31 19:06:33 +00:00
Official Noob
272698f97b Update utils.js 2019-12-31 19:03:43 +00:00
Official Noob
3fbb689e0a Moving utils 2019-12-31 19:01:17 +00:00
Ajay Ramachandran
4817af5e4f Removed minimum version 2019-12-31 13:29:59 -05:00
Ajay Ramachandran
aba08a515e Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious 2019-12-31 13:18:46 -05:00
Ajay Ramachandran
83801db82e Merge pull request #215 from jplsek/ci4
Add web-ext and ci artifact generation
2019-12-31 13:17:46 -05:00
Official Noob
84e4adbc12 Config proxy [POC]
Having a global SB.config that can be used to store get and set variables easily  
Example: SB.config.userID = "blah"
2019-12-31 14:55:03 +00:00
Ajay Ramachandran
6a37753753 Added defaults to option page. 2019-12-31 02:32:44 -05:00
Ajay Ramachandran
0898c7e28c Added options description. 2019-12-31 02:23:39 -05:00
Ajay Ramachandran
412be37ae5 Fixed channel parsing error. 2019-12-31 02:23:23 -05:00
Ajay Ramachandran
beec376e10 Updated invidious explainer. 2019-12-31 02:17:02 -05:00
Ajay Ramachandran
df30f00347 Moved invidious code to functions and made it check permissions on init. 2019-12-31 02:15:10 -05:00
Ajay Ramachandran
dcfdade927 Added invidio.sh 2019-12-31 02:08:32 -05:00
Ajay Ramachandran
741ddcd8aa Fixed permissions. 2019-12-31 02:06:58 -05:00
Ajay Ramachandran
433db26078 Added option to enable invidious support. 2019-12-30 23:15:29 -05:00
Ajay Ramachandran
fc033cb69d Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious 2019-12-30 17:40:32 -05:00
Ajay Ramachandran
bd8c67bc24 Merge branch 'experimental-ajay' of https://github.com/ajayyy/SponsorBlock into add-invidious 2019-12-30 17:39:07 -05:00
Ajay Ramachandran
a80fbc1a04 Merge pull request #216 from ajayyy/options-page
Options Page
2019-12-30 17:37:59 -05:00
Ajay Ramachandran
e347504616 Removed options from popup. 2019-12-30 17:37:02 -05:00
Ajay Ramachandran
94cbf089db Added submission keybind option 2019-12-30 17:23:05 -05:00
Ajay Ramachandran
cb2fb6925b Added keybind option. 2019-12-30 16:41:33 -05:00
Ajay Ramachandran
b3361a473c Removed use of center tag. 2019-12-30 14:44:03 -05:00
Ajay Ramachandran
fcb6ed7676 Added text set option (userID) 2019-12-30 01:20:20 -05:00
Ajay Ramachandran
91f4d7f669 Removed logs 2019-12-30 00:49:23 -05:00
Ajay Ramachandran
2e2ff60c23 Made the options save. 2019-12-30 00:48:59 -05:00
Ajay Ramachandran
13727270d4 Added all toggle buttons and made them set to their values. 2019-12-30 00:39:02 -05:00
Ajay Ramachandran
b27f56bc00 Added basic options panel.
Co-authored-by: Official Noob <31563761+OfficialNoob@users.noreply.github.com>
2019-12-29 23:18:18 -05:00
Ajay Ramachandran
7ad7d793d0 Added info about web-ext run 2019-12-29 20:52:40 -05:00
Ajay Ramachandran
491bef680e Removed unnecessary ignored files. 2019-12-29 20:49:31 -05:00
Ajay Ramachandran
e581dc818f Updated ignore files for build. 2019-12-29 20:26:47 -05:00
Jeremy Plsek
8d0b032eb6 Add web-ext and ci artifact generation 2019-12-29 19:35:02 -05:00
Ajay Ramachandran
9cb4fd6f79 Merge pull request #214 from OfficialNoob/patch-26
getYouTubeVideoID ~ TV support
2019-12-29 16:56:36 -05:00
Official Noob
87abcae249 fix embeds 2019-12-29 21:51:11 +00:00
Ajay Ramachandran
fe608b579e Formatting 2019-12-29 16:48:10 -05:00
Official Noob
f74e25a482 Update utils.js 2019-12-29 21:42:43 +00:00
Official Noob
1db9d25f3b getYouTubeVideoID ~ TV support 2019-12-29 21:39:19 +00:00
Ajay Ramachandran
f25aeefe83 Merge branch 'master' into add-invidious 2019-12-29 00:34:49 -05:00
Ajay Ramachandran
1abc1b9b28 Merge pull request #212 from ajayyy/experimental-ajay
UserID import, ID fixes, view count fix, embed error fix
2019-12-29 00:29:51 -05:00
Ajay Ramachandran
d10c8041bf Update build number 2019-12-29 00:28:56 -05:00
Ajay Ramachandran
c14c795474 Improved channel name query selector.
Resolves https://github.com/ajayyy/SponsorBlock/issues/199
2019-12-29 00:21:38 -05:00
Ajay Ramachandran
e5937431c3 Prevented error on embed.
Resolves https://github.com/ajayyy/SponsorBlock/issues/202
2019-12-29 00:14:51 -05:00
Ajay Ramachandran
b24a688e63 Improved view count 2019-12-29 00:10:08 -05:00
Ajay Ramachandran
10fd22f49c Fixed view counting being broken. 2019-12-29 00:08:57 -05:00
Ajay Ramachandran
f1dda95847 Merge branch 'experimental' of https://github.com/ajayyy/SponsorBlock into experimental-ajay
# Conflicts:
#	content.js
2019-12-29 00:08:41 -05:00
Ajay Ramachandran
f3f6dd171b Switched vote and view to POST. 2019-12-28 23:56:38 -05:00
Ajay Ramachandran
c802212a62 Added ability to import/export your userID. 2019-12-28 22:13:03 -05:00
Ajay Ramachandran
afb666797d Fixed IDs being localized in some parts. 2019-12-28 11:04:36 -05:00
Ajay Ramachandran
85a591c984 Merge pull request #207 from ImMaax/master
Fixed German translation
2019-12-23 21:01:04 -05:00
Max
3edaea8102 Removed word 2019-12-22 22:57:04 +01:00
Max
93c39c3ecc Fixed German translation 2019-12-22 22:54:43 +01:00
Ajay Ramachandran
ab2f0ef395 Crowdin fixes 2019-12-21 00:00:23 -05:00
Ajay Ramachandran
005ca73cce Update Crowdin configuration file 2019-12-20 23:56:49 -05:00
Ajay Ramachandran
8dd8897f1f Fixed yaml formatting 2019-12-20 23:08:34 -05:00
Ajay Ramachandran
95555ed3fd Fixed yaml 2019-12-20 23:06:07 -05:00
Ajay Ramachandran
11b71f7366 Added custom language mapping to crowdin file 2019-12-20 23:03:41 -05:00
Ajay Ramachandran
4537c70105 Update Crowdin configuration file 2019-12-20 22:42:22 -05:00
Ajay Ramachandran
42a0cff162 Update crowdin.yml 2019-12-20 17:55:35 -05:00
Ajay Ramachandran
527e6d4c24 Update Crowdin configuration file 2019-12-20 17:43:23 -05:00
Ajay Ramachandran
9fc846bd7a Made sure the video player button options are ignored on Invidious. 2019-12-19 01:03:09 -05:00
Ajay Ramachandran
5b628ccbf9 Fixed submit button being shown at the wrong time. 2019-12-19 00:56:52 -05:00
Ajay Ramachandran
5471273673 Fixed getting channel ID for invidious. 2019-12-19 00:48:26 -05:00
Ajay Ramachandran
58c0c6e152 Merge branch 'experimental-ajay' of https://github.com/ajayyy/SponsorBlock into add-invidious 2019-12-19 00:46:52 -05:00
Ajay Ramachandran
7d62c9f575 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into add-invidious 2019-12-19 00:40:32 -05:00
Ajay Ramachandran
45a64fcb03 Prevented upload button from appearing on invidious.
It still appears if the video player controls are disabled.
2019-12-19 00:38:55 -05:00
Ajay Ramachandran
630b099fd6 Fixed formatting and removed whitelisting fix code.
Whitelisting was now fixed in a different way.
2019-12-19 00:36:35 -05:00
afrmtbl
5dc67a386c Fix manifest 2019-12-05 16:13:22 -05:00
afrmtbl
6d442b9e80 Explain additional whitelist check 2019-12-05 15:48:26 -05:00
afrmtbl
2f6ddeb5f1 Initial Invidious support 2019-12-05 15:35:25 -05:00
25 changed files with 9987 additions and 1045 deletions

38
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: CI
on: [push, pull_request]
jobs:
build:
name: Create artifacts
runs-on: ubuntu-latest
steps:
# Initialization
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
- run: npm install
- name: Copy configuration
run: cp config.js.example config.js
# Create Chrome artifacts
- name: Create Chrome artifacts
run: npm run build
- uses: actions/upload-artifact@v1
with:
name: Chrome Extension
path: web-ext-artifacts
# Create Firefox artifacts
- name: Move manifest
run: mv manifest.json manifest.json.original
- name: Combine manifest for Firefox
run: jq -s '.[0] * .[1]' manifest.json.original firefox_manifest-extra.json > manifest.json
- name: Create Firefox artifacts
run: npm run build
- uses: actions/upload-artifact@v1
with:
name: Firefox Extension
path: web-ext-artifacts

5
.gitignore vendored
View File

@@ -1,3 +1,6 @@
config.js
ignored
.idea/
.idea/
node_modules
web-ext-artifacts
.vscode/

View File

@@ -32,6 +32,8 @@
SponsorBlock is an extension that will skip over sponsored segments of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment.
Also support Invidio.us.
# Server
The backend server code is available here: https://github.com/ajayyy/SponsorBlockServer
@@ -50,6 +52,16 @@ You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#ap
You can load this project as an unpacked extension. Make sure to rename the `config.js.example` file to `config.js` before installing.
There are also other build scripts available. Install `npm`, then run `npm install` in the repository.
## Developing with a clean profile
Run `npm run dev` to run the extension using a clean browser profile with hot reloading [(by default Firefox)](https://hacks.mozilla.org/2019/10/developing-cross-browser-extensions-with-web-ext-3-2-0/). This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands).
## Packing
Run `npm run build` to generate a packed extension.
# Credit
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) is used to grab the time the video was published.

203
SB.js Normal file
View File

@@ -0,0 +1,203 @@
SB = {
/**
* Callback function when an option is updated
*
* @type {CallableFunction}
*/
configListeners: []
};
// Function setup
// Allows a map to be conveted into json form
// Currently used for local storage
Map.prototype.toJSON = function() {
return Array.from(this.entries());
};
// Proxy Map changes to Map in SB.localConfig
// Saves the changes to chrome.storage in json form
class MapIO {
constructor(id) {
// The name of the item in the array
this.id = id;
// A local copy of the map (SB.config.mapname.map)
this.map = SB.localConfig[this.id];
}
set(key, value) {
// Proxy to map
this.map.set(key, value);
// Store updated map locally
chrome.storage.sync.set({
[this.id]: encodeStoredItem(this.map)
});
return this.map;
}
get(key) {
return this.map.get(key);
}
has(key) {
return this.map.has(key);
}
size() {
return this.map.size;
}
delete(key) {
// Proxy to map
this.map.delete(key);
// Store updated map locally
chrome.storage.sync.set({
[this.id]: encodeStoredItem(this.map)
});
}
clear() {
this.map.clear();
chrome.storage.sync.set({
[this.id]: encodeStoredItem(this.map)
});
}
}
/**
* A Map cannot be stored in the chrome storage.
* This data will be encoded into an array instead as specified by the toJSON function.
*
* @param {*} data
*/
function encodeStoredItem(data) {
// if data is Map convert to json for storing
if(!(data instanceof Map)) return data;
return JSON.stringify(data);
}
/**
* A Map cannot be stored in the chrome storage.
* This data will be decoded from the array it is stored in
*
* @param {*} data
*/
function decodeStoredItem(data) {
if(typeof data !== "string") return data;
try {
let str = JSON.parse(data);
if(!Array.isArray(str)) return data;
return new Map(str);
} catch(e) {
// If all else fails, return the data
return data;
}
}
function configProxy() {
chrome.storage.onChanged.addListener((changes, namespace) => {
for (const key in changes) {
SB.localConfig[key] = decodeStoredItem(changes[key].newValue);
}
for (const callback of SB.configListeners) {
callback(changes);
}
});
var handler = {
set(obj, prop, value) {
SB.localConfig[prop] = value;
chrome.storage.sync.set({
[prop]: encodeStoredItem(value)
});
},
get(obj, prop) {
let data = SB.localConfig[prop];
if(data instanceof Map) data = new MapIO(prop);
return obj[prop] || data;
},
deleteProperty(obj, prop) {
chrome.storage.sync.remove(prop);
}
};
return new Proxy({handler}, handler);
}
function fetchConfig() {
return new Promise((resolve, reject) => {
chrome.storage.sync.get(null, function(items) {
SB.localConfig = items; // Data is ready
resolve();
});
});
}
function migrateOldFormats() { // Convert sponsorTimes format
for (const key in SB.localConfig) {
if (key.startsWith("sponsorTimes") && key !== "sponsorTimes" && key !== "sponsorTimesContributed") {
SB.config.sponsorTimes.set(key.substr(12), SB.config[key]);
delete SB.config[key];
}
}
}
async function setupConfig() {
await fetchConfig();
addDefaults();
convertJSON();
SB.config = configProxy();
migrateOldFormats();
}
SB.defaults = {
"sponsorTimes": new Map(),
"startSponsorKeybind": ";",
"submitKeybind": "'",
"minutesSaved": 0,
"skipCount": 0,
"sponsorTimesContributed": 0,
"disableSkipping": false,
"disableAutoSkip": false,
"trackViewCount": true,
"dontShowNotice": false,
"hideVideoPlayerControls": false,
"hideInfoButtonPlayerControls": false,
"hideDeleteButtonPlayerControls": false,
"hideDiscordLaunches": 0,
"hideDiscordLink": false,
"invidiousInstances": ["invidio.us", "invidiou.sh", "invidious.snopyta.org"],
"invidiousUpdateInfoShowCount": 0,
"autoUpvote": true
}
// Reset config
function resetConfig() {
SB.config = SB.defaults;
};
function convertJSON() {
Object.keys(SB.defaults).forEach(key => {
SB.localConfig[key] = decodeStoredItem(SB.localConfig[key], key);
});
}
// Add defaults
function addDefaults() {
for (const key in SB.defaults) {
if(!SB.localConfig.hasOwnProperty(key)) {
SB.localConfig[key] = SB.defaults[key];
}
}
};
// Sync config
setupConfig();

View File

@@ -82,10 +82,10 @@
"message": "Bist du sicher, dass du Folgendes löschen möchtest?\n\n"
},
"Unknown": {
"message": "Deine Segmente konnte nicht gesendet werden, bitte versuche es später erneut."
"message": "Deine Segmente konnten nicht gesendet werden, bitte versuche es später erneut."
},
"sponsorFound": {
"message": "Die gesponsorten Inhalte dieses Videos befindet sich bereits in der Datenbank!"
"message": "Die gesponsorten Inhalte dieses Videos befinden sich bereits in der Datenbank!"
},
"sponsor404": {
"message": "Keine Sponsoren gefunden"
@@ -214,10 +214,10 @@
"message": "Dieser Knopf entfernt sämtlich Segmente in der Youtube-Zeitleiste."
},
"disableViewTracking": {
"message": "Deaktiviere mitzählen übersprungener Sponsoren"
"message": "Deaktiviere das Mitzählen übersprungener Sponsoren"
},
"enableViewTracking": {
"message": "Aktiviere mitzählen übersprungener Sponsoren"
"message": "Aktiviere das Mitzählen übersprungener Sponsoren"
},
"whatViewTracking": {
"message": "Diese Funktion hält fest, welche Sponsoren von dir übersprungen wurden und hilft anderen zu erfahren, was ihre Einsendungen bewirkt haben.\n Außerdem dienen die Werte zusammen mit positiven Rückmeldungen als Anti-Spam-Schutz. \n Wenn ein gesponsorter Inhalt übersprungen wird, sendet die Erweiterung eine Nachricht an den Server. \n Hoffentlich wird diese Funktion auch weiterhin genutzt, damit der Algorithmus funktioniert. :)"
@@ -292,10 +292,10 @@
"message": "Auto-Überspringen überspringt gesponsorte Inhalte für dich. Wenn deaktiviert, fragt die Benachrichtigung, ob übersprungen werden soll."
},
"youHaveSkipped": {
"message": "Du hast übersprungen "
"message": "Du übersprangst "
},
"youHaveSaved": {
"message": "Du hast dir erspart "
"message": "Du erspartest dir "
},
"minLower": {
"message": "Minute"

View File

@@ -320,5 +320,71 @@
},
"statusReminder": {
"message": "Check status.sponsor.ajay.app for server status."
},
"changeUserID": {
"message": "Import/Export Your UserID"
},
"whatChangeUserID": {
"message": "This should be kept private. This is like a password and should not be shared with anyone. If someone has this, they can impersonate you."
},
"setUserID": {
"message": "Set UserID"
},
"userIDChangeWarning": {
"message": "Warning: Changing the UserID is permanent. Are you sure you would like to do this? Make sure to backup your old one just in case."
},
"createdBy": {
"message": "Created By"
},
"autoSkip": {
"message": "Auto Skip"
},
"showSkipNotice": {
"message": "Show Notice After A Sponsor Is Skipped"
},
"keybindCurrentlySet": {
"message": ". It is currently set to:"
},
"supportInvidious": {
"message": "Support Invidious"
},
"supportInvidiousDescription": {
"message": "Invidious (invidio.us) is a third party YouTube client. To enable support, you must accept the extra permissions. This does NOT work in incongnito on Chrome and other Chromium variants."
},
"optionsInfo": {
"message": "Enable Invidious support, disable autoskip, hide buttons and more."
},
"addInvidiousInstance": {
"message": "Add Invidious Instance"
},
"addInvidiousInstanceDescription": {
"message": "Add a custom instance of Invidious. This must be formatted with JUST the domain. Example: invidious.ajay.app"
},
"add": {
"message": "Add"
},
"addInvidiousInstanceError": {
"message": "This is an invalid domain. This should JUST include the domain part. Example: invidious.ajay.app"
},
"resetInvidiousInstance": {
"message": "Reset Invidious Instance List"
},
"resetInvidiousInstanceAlert": {
"message": "You are about to reset the Invidious instance list"
},
"currentInstances": {
"message": "Current Instances:"
},
"enableAutoUpvote": {
"message": "Auto Upvote"
},
"whatAutoUpvote": {
"message": "With this enabled, the extension will upvote all submissions you view if you do not report them. If the notice is disabled, this will not occur."
},
"invidiousInfo1": {
"message": "Invidious (the 3rd party YouTube site) support has been added!"
},
"invidiousInfo2": {
"message": "You MUST enable it in the options for it to work."
}
}

View File

@@ -0,0 +1,390 @@
{
"Name": {
"message": "SponsorBlock",
"description": "Nazwa rozszerzenia."
},
"fullName": {
"message": "SponsorBlock na YouTube - Omiń reklamy sponsorów",
"description": "Nazwa rozszerzenia."
},
"Description": {
"message": "Przewijaj reklamy sponsorów w filmach na YouTube. Zgłaszaj reklamy w nagraniach żeby nie marnować czasu innych.",
"description": "Opis rozszerzenia."
},
"helpPage": {
"message": "index_en.html"
},
"400": {
"message": "Serwer odpowiedział, że to zapytanie jest niepoprawne"
},
"429": {
"message": "Zgłosiłeś bardzo dużo segmentów reklamowych dla tego jednego nagrania, jesteś pewien, że jest ich tak dużo?"
},
"409": {
"message": "Treść została już wcześniej zgłoszona"
},
"channelWhitelisted": {
"message": "Kanał dodany do wyjątków!"
},
"Sponsor": {
"message": "sponsor"
},
"Sponsors": {
"message": "sponsorzy"
},
"Segment": {
"message": "segmet sponsorowany"
},
"Segments": {
"message": "segmenty sponsorowane"
},
"noticeTitle": {
"message": "Segment przewinięty"
},
"reportButtonTitle": {
"message": "Zgłoś"
},
"reportButtonInfo": {
"message": "Zgłoś ten segment reklamowy jako nieprawidłowy."
},
"Dismiss": {
"message": "Odrzuć"
},
"Loading": {
"message": "Ładowanie..."
},
"Mins": {
"message": "Minuty"
},
"Secs": {
"message": "Sekundy"
},
"Hide": {
"message": "Nigdy nie pokazuj"
},
"hitGoBack": {
"message": "Kliknij cofnij aby przenieść się do miejsca przed przewinięciem."
},
"unskip": {
"message": "Cofnij"
},
"reskip": {
"message": "Przewiń"
},
"paused": {
"message": "Zatrzymany"
},
"confirmMSG": {
"message": "Żeby zmienić lub usunąć wartości, kliknij na guzik informacji lub otwórz okienko rozszerzenia klikając w ikonę rozszerzenia znajdującą się w prawym górnym rogu."
},
"clearThis": {
"message": "Jesteś pewien, że chcesz to usunąć?\n\n"
},
"Unknown": {
"message": "Wystąpił błąd podczas przesyłania twojego zgłoszenia, proszę spróbować ponownie później."
},
"sponsorFound": {
"message": "Segmenty reklamowe dla tego nagrania są już w bazie!"
},
"sponsor404": {
"message": "Nie znaleziono segmentów reklamowych"
},
"sponsorStart": {
"message": "Reklama zaczyna się teraz"
},
"sponsorEnd": {
"message": "Reklama kończy się teraz"
},
"noVideoID": {
"message": "Nie znaleziono nagrania wideo w tej karcie. Jeśli wiesz, że to karta YouTube'a, zamknij to okienko i otwórz je ponownie. Jeśli to nie zadziała spróbuj przeładować stronę."
},
"success": {
"message": "Sukces!"
},
"voted": {
"message": "Zagłosowano!"
},
"voteFail": {
"message": "Już na to głosowałeś."
},
"serverDown": {
"message": "Wygląda na to, że serwer nie działa. Skontaktuj się z dewloperem."
},
"connectionError": {
"message": "Błąd z połączeniem. Kod błędu: "
},
"wantToSubmit": {
"message": "Chcesz zgłosić segment sponsorowany dla nagrania z id"
},
"leftTimes": {
"message": "Wygląda na to, że masz nie wysłane segmenty reklamowe. Cofnij się do tej strony i zgłoś je (nie zostały usunięte)."
},
"clearTimes": {
"message": "Wyczyść segmenty reklamowe"
},
"openPopup": {
"message": "Otwórz okienko SponsorBlock"
},
"SubmitTimes": {
"message": "Zgłoś segmenty reklamowe"
},
"submitCheck": {
"message": "Jesteś pewien, że chcesz to zgłosić?"
},
"whitelistChannel": {
"message": "Dodaj kanał do wyjątków"
},
"removeFromWhitelist": {
"message": "Usuń kanał z listy wyjątków"
},
"voteOnTime": {
"message": "Głosuj na segment reklamowy"
},
"recordTimes": {
"message": "Nagraj czasy segmentów reklamowych"
},
"soFarUHSubmited": {
"message": "Jak na razie zgłosiłeś:"
},
"savedPeopleFrom": {
"message": "Ocaliłeś ludzi przed "
},
"viewLeaderboard": {
"message": "Zobacz ranking użytkowników"
},
"here": {
"message": "tutaj"
},
"recordTimesDescription": {
"message": "Kliknij guzik poniżej kiedy segment reklamowy się zaczyna i kończy żeby go oznaczyć i wysłać do bazy danych."
},
"popupHint": {
"message": "Podpowiedź: Klikając średnik kiedy zaznaczone jest zgłaszanie wideo możesz oznaczyć początek reklamy, znakiem cytatu oznaczysz jej koniec. (Klawisze można zmienić w opcjach)"
},
"lastTimes": {
"message": "Ostanie wybrane czasy reklam"
},
"clearTimesButton": {
"message": "Usuń czasy"
},
"submitTimesButton": {
"message": "Zgłoś czasy"
},
"publicStats": {
"message": "Ten dane są używane na naszej stronie żeby pokazać twój wkład. Zobacz to"
},
"setUsername": {
"message": "Ustaw nazwę użytkownika"
},
"discordAdvert": {
"message": "Dołącz do oficjalnego serwera na discordzie i podziel się wrażeniami i sugestiami!"
},
"hideThis": {
"message": "Ukryj to"
},
"Options": {
"message": "Opcje"
},
"showButtons": {
"message": "Pokaż guziki w odtwarzaczu YouTube"
},
"hideButtons": {
"message": "Ukryj guziki w odtwarzaczu YouTube"
},
"hideButtonsDescription": {
"message": "Ta opcja ukrywa guziki zgłaszania reklamy w odtwarzaczu. Wiem, że mogą one irytować niektórych. Zamiast zgłaszania bezpośrednio w odtwarzaczu możesz to zrobić w tym okienku. Zawsze możesz zmienić te opcje później."
},
"showInfoButton": {
"message": "Pokaż guzik informacyjny w odtwarzaczu YouTube"
},
"hideInfoButton": {
"message": "Ukryj guzik informacyjny w odtwarzaczu YouTube"
},
"whatInfoButton": {
"message": "Jest to guzik otwierający popup na stronie YouTube."
},
"hideDeleteButton": {
"message": "Ukryj guzik usuwania w odtwarzaczu YouTube"
},
"showDeleteButton": {
"message": "Pokaż guzik usuwania w odtwarzaczu YouTube"
},
"whatDeleteButton": {
"message": "Ten guzik pozwala ci wyczyścić wszystkie segmenty reklamowe w odtwarzaczu YouTube."
},
"disableViewTracking": {
"message": "Wyłącz licznik przewinięć"
},
"enableViewTracking": {
"message": "Włącz licznik przewinięć"
},
"whatViewTracking": {
"message": "Ta opcja śledzi które segmenty pominąłeś i informuje zgłaszających ile czasu Ci zaoszczędzili, też wraz systemem głosowania pomaga wykrywać spam w zgłoszeniach. Rozszerzenie wysyła zapytanie do serwera za każdym razem kiedy przewinąłeś segment reklamowy. Miejmy nadzieję, że większość ludzi tego nie wyłączy i licznik wyświetleń będzie rzetelny. :)"
},
"showNotice": {
"message": "Pokaż informacje ponownie"
},
"longDescription": {
"message": "SponsorBlock jest rozszerzeniem które przewinie segmenty sponsorów w filmach na YouTube. SponsorBlock jest opartym na crowdsourcing rozszerzeniem które pozwala każdemu zgłaszać początek i koniec segmentu reklamowego w filmach na YouTube. Kiedy ktoś zgłosi taki fragment zostanie on pominięty przez innych użytkowników rozszerzenia.",
"description": "Pełny opis rozszerzenia na stronie w sklepie."
},
"website": {
"message": "Strona",
"description": "Używane w sklepie Firefoxa"
},
"sourceCode": {
"message": "Kod źródłowy",
"description": "Używane w sklepie Firefoxa"
},
"noticeUpdate": {
"message": "Informacje zostały zaktualizowane!",
"description": "Pierwsza linia po aktualizacji informacji."
},
"noticeUpdate2": {
"message": "Jeśli nadal jej nie lubisz wybierz opcje nie pokazuj więcej.",
"description": "Druga linia po aktualizacji informacji."
},
"setStartSponsorShortcut": {
"message": "Ustaw klawisz do oznaczania początku reklamy"
},
"setSubmitKeybind": {
"message": "Ustaw klawisz do wysyłania czasów"
},
"keybindDescription": {
"message": "Wybierz klawisz klikając go na klawiaturze"
},
"keybindDescriptionComplete": {
"message": "Ustawiony klawisz to: "
},
"0": {
"message": "Połączenie przerwane z powodu braku odpowiedzi. Sprawdź swoje połączenie z internetem. Jeśli wszystko z nim w porządku oznacza to, że serwer jest prawdopodobnie przeciążony lub nie działa."
},
"disableSkipping": {
"message": "Wyłącz SponsorBlock"
},
"enableSkipping": {
"message": "Włącz SponsorBlock"
},
"yourWork": {
"message": "Twój wkład",
"description": "Nagłowek sekcji ze statystykami użytkownika."
},
"502": {
"message": "Serwer jest prawdopodobnie przeciążony, spróbuj ponownie za kilka sekund."
},
"errorCode": {
"message": "Kod błędu: "
},
"noticeTitleNotSkipped": {
"message": "Przewinąć reklamę?"
},
"skip": {
"message": "Przewiń"
},
"disableAutoSkip": {
"message": "Wyłącz auto przewijanie"
},
"enableAutoSkip": {
"message": "Włącz auto przewijanie"
},
"autoSkipDescription": {
"message": "Auto przewijanie przewinie segment za ciebie, wyłączone wyświetli komunikat z pytaniem czy chcesz przewinąć reklamę."
},
"youHaveSkipped": {
"message": "Przewinąłeś "
},
"youHaveSaved": {
"message": "Oszczędziłeś sobie "
},
"minLower": {
"message": "minuta"
},
"minsLower": {
"message": "minuty"
},
"hourLower": {
"message": "godzina"
},
"hoursLower": {
"message": "godziny"
},
"youHaveSavedTime": {
"message": "Oszczędziłeś ludziom"
},
"youHaveSavedTimeEnd": {
"message": " czasu."
},
"guildlinesSummary": {
"message": "- Upewnij się, że zgłaszany fragment zawiera tylko reklamę i nic więcej.\n- Upewnij się, że nie zostanie przewinięta wartościowa treść\n- Jeśli całe nagranie to reklama, proszę nie zgłaszaj go. Blokowanie całych nagrań pojawi się wkrótce.\n- Nie ukrywaj treści które są istotne dla użytkownika (nie ukrywaj informacji, że recenzja produktu została opłacona przez producenta)"
},
"statusReminder": {
"message": "Wejdź na status.sponsor.ajay.app żeby sprawdzić czy serwer działa."
},
"changeUserID": {
"message": "Zaimportuj/Wyeksportuj swój UserID"
},
"whatChangeUserID": {
"message": "Ta informacja jest poufna i działa jak hasło, użytkownik który ma do niej dostęp może zgłaszać treści jako ty."
},
"setUserID": {
"message": "Ustaw UserID"
},
"userIDChangeWarning": {
"message": "Ostrzeżenie: Zmiana UserID jest nieodwracalna. Jesteś pewien, że chcesz to zrobić? Skopiuj obecny UserID na wszelki wypadek."
},
"createdBy": {
"message": "Stworzony przez"
},
"autoSkip": {
"message": "Auto przewijanie"
},
"showSkipNotice": {
"message": "Pokaż informację po przewiniętym fragmencie"
},
"keybindCurrentlySet": {
"message": ". Jest obecnie ustawione jako:"
},
"supportInvidious": {
"message": "Wesprzyj Invidious"
},
"supportInvidiousDescription": {
"message": "Invidious (invidio.us) to nieoficjalny klient YouTube. Aby go wesprzeć musisz przyznać dodatkowe uprawnienia rozszerzeniowi. Ta opcja nie działa w incognito i innych wersjach Chromium."
},
"optionsInfo": {
"message": "Wesprzyj Invidious, wyłącz auto przewijanie, ukryj guziki i więcej."
},
"addInvidiousInstance": {
"message": "Dodaj instancje Invidious"
},
"addInvidiousInstanceDescription": {
"message": "Dodaj niestandardową instancje Invidious. W formie domeny. Na przykład: invidious.ajay.app"
},
"add": {
"message": "Dodaj"
},
"addInvidiousInstanceError": {
"message": "Ta domena jest nieprawidłowa. Wartość powinna zawierać TYLKO domenę. Na przykład: invidious.ajay.app"
},
"resetInvidiousInstance": {
"message": "Zresetuj listę instancji Invidious"
},
"resetInvidiousInstanceAlert": {
"message": "Zresetujesz listę instancji Invidious"
},
"currentInstances": {
"message": "Obecne instancje:"
},
"enableAutoUpvote": {
"message": "Auto potwierdzanie"
},
"whatAutoUpvote": {
"message": "To ustawienie sprawia, że wszystkie przewinięte przez ciebie a nie zgłoszone jako błąd segmenty reklamowe zostaną potwierdzone jako prawidłowe. Ta opcja nie działa jeśli okienko z informacją o przewinięciu jest ukryte."
},
"invidiousInfo1": {
"message": "Invidious (nieoficjalny klient YouTube) została dodana do wspieranych!"
},
"invidiousInfo2": {
"message": "Musisz odblokować to w opcjach aby móc to zrobić."
}
}

View File

@@ -1,3 +1,15 @@
isBackgroundScript = true;
// Used only on Firefox, which does not support non persistent background pages.
var contentScriptRegistrations = {};
// Register content script if needed
if (isFirefox()) {
wait(() => SB.config !== undefined).then(function() {
if (SB.config.supportInvidious) setupExtraSiteContentScripts();
});
}
chrome.tabs.onUpdated.addListener(function(tabId) {
chrome.tabs.sendMessage(tabId, {
message: 'update',
@@ -6,74 +18,104 @@ chrome.tabs.onUpdated.addListener(function(tabId) {
chrome.runtime.onMessage.addListener(function (request, sender, callback) {
switch(request.message) {
case "submitTimes":
submitTimes(request.videoID, callback);
//this allows the callback to be called later by the submitTimes function
return true;
case "addSponsorTime":
addSponsorTime(request.time, request.videoID, callback);
//this allows the callback to be called later
return true;
case "getSponsorTimes":
getSponsorTimes(request.videoID, function(sponsorTimes) {
callback({
sponsorTimes: sponsorTimes
})
});
//this allows the callback to be called later
return true;
case "submitVote":
submitVote(request.type, request.UUID, callback);
//this allows the callback to be called later
return true;
case "alertPrevious":
chrome.notifications.create("stillThere" + Math.random(), {
type: "basic",
title: chrome.i18n.getMessage("wantToSubmit") + " " + request.previousVideoID + "?",
message: chrome.i18n.getMessage("leftTimes"),
iconUrl: "./icons/LogoSponsorBlocker256px.png"
});
case "openConfig":
chrome.runtime.openOptionsPage();
return
case "submitTimes":
submitTimes(request.videoID, callback);
//this allows the callback to be called later by the submitTimes function
return true;
case "addSponsorTime":
addSponsorTime(request.time, request.videoID, callback);
//this allows the callback to be called later
return true;
case "getSponsorTimes":
getSponsorTimes(request.videoID, function(sponsorTimes) {
callback({
sponsorTimes: sponsorTimes
})
});
//this allows the callback to be called later
return true;
case "submitVote":
submitVote(request.type, request.UUID, callback);
//this allows the callback to be called later
return true;
case "alertPrevious":
chrome.notifications.create("stillThere" + Math.random(), {
type: "basic",
title: chrome.i18n.getMessage("wantToSubmit") + " " + request.previousVideoID + "?",
message: chrome.i18n.getMessage("leftTimes"),
iconUrl: "./icons/LogoSponsorBlocker256px.png"
});
case "registerContentScript":
registerFirefoxContentScript(request);
return false;
case "unregisterContentScript":
contentScriptRegistrations[request.id].unregister();
delete contentScriptRegistrations[request.id];
return false;
}
});
//add help page on install
chrome.runtime.onInstalled.addListener(function (object) {
// This let's the config sync to run fully before checking.
// This is required on Firefox
setTimeout(function() {
chrome.storage.sync.get(["userID"], function(result) {
const userID = result.userID;
const userID = SB.config.userID;
// If there is no userID, then it is the first install.
if (!userID){
//open up the install page
chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")});
// If there is no userID, then it is the first install.
if (!userID){
//open up the install page
chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")});
//generate a userID
const newUserID = generateUserID();
//save this UUID
chrome.storage.sync.set({
"userID": newUserID
});
}
});
//generate a userID
const newUserID = generateUserID();
//save this UUID
SB.config.userID = newUserID;
//TODO: Remove when invidious support is old
// Don't show this to new users
SB.config.invidiousUpdateInfoShowCount = 6;
}
}, 1500);
});
/**
* Only works on Firefox.
* Firefox requires that it be applied after every extension restart.
*
* @param {JSON} options
*/
function registerFirefoxContentScript(options) {
let oldRegistration = contentScriptRegistrations[options.id];
if (oldRegistration) oldRegistration.unregister();
browser.contentScripts.register({
allFrames: options.allFrames,
js: options.js,
css: options.css,
matches: options.matches
}).then((registration) => void (contentScriptRegistrations[options.id] = registration));
}
//gets the sponsor times from memory
function getSponsorTimes(videoID, callback) {
let sponsorTimes = [];
let sponsorTimeKey = "sponsorTimes" + videoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimesStorage = result[sponsorTimeKey];
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
sponsorTimes = sponsorTimesStorage;
}
callback(sponsorTimes)
});
let sponsorTimesStorage = SB.config.sponsorTimes.get(videoID);
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
sponsorTimes = sponsorTimesStorage;
}
callback(sponsorTimes);
}
function addSponsorTime(time, videoID, callback) {
@@ -91,111 +133,97 @@ function addSponsorTime(time, videoID, callback) {
}
//save this info
let sponsorTimeKey = "sponsorTimes" + videoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, callback);
SB.config.sponsorTimes.set(videoID, sponsorTimes);
callback();
});
}
function submitVote(type, UUID, callback) {
chrome.storage.sync.get(["userID"], function(result) {
let userID = result.userID;
let userID = SB.config.userID;
if (userID == undefined || userID === "undefined") {
//generate one
userID = generateUserID();
chrome.storage.sync.set({
"userID": userID
if (userID == undefined || userID === "undefined") {
//generate one
userID = generateUserID();
SB.config.userID = userID;
}
//publish this vote
sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback({
successType: 1
});
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) {
//duplicate vote
callback({
successType: 0,
statusCode: xmlhttp.status
});
} else if (error) {
//error while connect
callback({
successType: -1,
statusCode: xmlhttp.status
});
}
//publish this vote
sendRequestToServer("GET", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback({
successType: 1
});
} else if (xmlhttp.readyState == 4 && xmlhttp.status == 405) {
//duplicate vote
callback({
successType: 0,
statusCode: xmlhttp.status
});
} else if (error) {
//error while connect
callback({
successType: -1,
statusCode: xmlhttp.status
});
}
})
})
});
}
function submitTimes(videoID, callback) {
async function submitTimes(videoID, callback) {
//get the video times from storage
let sponsorTimeKey = 'sponsorTimes' + videoID;
chrome.storage.sync.get([sponsorTimeKey, "userID"], async function(result) {
let sponsorTimes = result[sponsorTimeKey];
let userID = result.userID;
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let durationResult = await new Promise((resolve, reject) => {
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "getVideoDuration"
}, (response) => resolve(response));
});
let sponsorTimes = SB.config.sponsorTimes.get(videoID);
let userID = SB.config.userID;
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let durationResult = await new Promise((resolve, reject) => {
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "getVideoDuration"
}, (response) => resolve(response));
});
});
//check if a sponsor exceeds the duration of the video
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i][1] > durationResult.duration) {
sponsorTimes[i][1] = durationResult.duration;
}
}
//submit these times
for (let i = 0; i < sponsorTimes.length; i++) {
//to prevent it from happeneing twice
let increasedContributionAmount = false;
//submit the sponsorTime
sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && !error) {
callback({
statusCode: xmlhttp.status
});
if (xmlhttp.status == 200) {
//add these to the storage log
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
let currentContributionAmount = 0;
if (result.sponsorTimesContributed != undefined) {
//current contribution amount is known
currentContributionAmount = result.sponsorTimesContributed;
}
//save the amount contributed
if (!increasedContributionAmount) {
increasedContributionAmount = true;
chrome.storage.sync.set({"sponsorTimesContributed": currentContributionAmount + sponsorTimes.length});
}
});
}
} else if (error) {
callback({
statusCode: -1
});
}
});
//check if a sponsor exceeds the duration of the video
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i][1] > durationResult.duration) {
sponsorTimes[i][1] = durationResult.duration;
}
}
});
//submit these times
for (let i = 0; i < sponsorTimes.length; i++) {
//to prevent it from happeneing twice
let increasedContributionAmount = false;
//submit the sponsorTime
sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1]
+ "&userID=" + userID, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && !error) {
callback({
statusCode: xmlhttp.status
});
if (xmlhttp.status == 200) {
//add these to the storage log
currentContributionAmount = SB.config.sponsorTimesContributed;
//save the amount contributed
if (!increasedContributionAmount) {
increasedContributionAmount = true;
SB.config.sponsorTimesContributed = currentContributionAmount + sponsorTimes.length;
}
}
} else if (error) {
callback({
statusCode: -1
});
}
});
}
}
}
function sendRequestToServer(type, address, callback) {
@@ -215,4 +243,4 @@ function sendRequestToServer(type, address, callback) {
//submit this request
xmlhttp.send();
}
}

View File

@@ -71,7 +71,7 @@
}
.sponsorSkipNotice {
min-width: 300px;
min-width: 350px;
background-color: rgba(28, 28, 28, 0.9);
position: absolute;
right: 5px;

View File

@@ -58,11 +58,6 @@ var lastSponsorTimeSkippedUUID = null;
//if showing the start sponsor button or the end sponsor button on the player
var showingStartSponsor = true;
//should the video controls buttons be added
var hideVideoPlayerControls = false;
var hideInfoButtonPlayerControls = false;
var hideDeleteButtonPlayerControls = false;
//the sponsor times being prepared to be submitted
var sponsorTimesSubmitting = [];
@@ -70,158 +65,103 @@ var sponsorTimesSubmitting = [];
//this is used to close the popup on YouTube when the other popup opens
var popupInitialised = false;
//should skips happen at all
var disableSkipping = false;
chrome.storage.sync.get(["disableSkipping"], function(result) {
let disableSkippingStorage = result.disableSkipping;
if (disableSkippingStorage != undefined) {
disableSkipping = disableSkippingStorage;
}
});
//should skips be manual
var disableAutoSkip = false;
chrome.storage.sync.get(["disableAutoSkip"], function(result) {
let disableAutoSkipStorage = result.disableAutoSkip;
if (disableAutoSkipStorage != undefined) {
disableAutoSkip = disableAutoSkipStorage;
}
});
//should view counts be tracked
var trackViewCount = false;
chrome.storage.sync.get(["trackViewCount"], function(result) {
let trackViewCountStorage = result.trackViewCount;
if (trackViewCountStorage != undefined) {
trackViewCount = trackViewCountStorage;
} else {
trackViewCount = true;
}
});
//if the notice should not be shown
//happens when the user click's the "Don't show notice again" button
//option renamed when new notice was made
var dontShowNotice = false;
chrome.storage.sync.get(["dontShowNotice"], function(result) {
let dontShowNoticeAgain = result.dontShowNotice;
if (dontShowNoticeAgain != undefined) {
dontShowNotice = dontShowNoticeAgain;
}
});
//load the legacy option to hide the notice
var dontShowNoticeOld = false;
chrome.storage.sync.get(["dontShowNoticeAgain"], function(result) {
let dontShowNoticeAgain = result.dontShowNoticeAgain;
if (dontShowNoticeAgain != undefined) {
dontShowNoticeOld = dontShowNoticeAgain;
}
});
//get messages from the background script and the popup
chrome.runtime.onMessage.addListener(messageListener);
function messageListener(request, sender, sendResponse) {
//messages from popup script
switch(request.message){
case "update":
videoIDChange(getYouTubeVideoID(document.URL));
//messages from popup script
switch(request.message){
case "update":
videoIDChange(getYouTubeVideoID(document.URL));
break;
case "sponsorStart":
sponsorMessageStarted(sendResponse);
break;
case "sponsorStart":
sponsorMessageStarted(sendResponse);
break;
case "sponsorDataChanged":
updateSponsorTimesSubmitting();
break;
case "sponsorDataChanged":
updateSponsorTimesSubmitting();
break;
case "isInfoFound":
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes,
hiddenSponsorTimes: hiddenSponsorTimes,
UUIDs: UUIDs
});
break;
case "isInfoFound":
//send the sponsor times along with if it's found
sendResponse({
found: sponsorDataFound,
sponsorTimes: sponsorTimes,
hiddenSponsorTimes: hiddenSponsorTimes,
UUIDs: UUIDs
});
if (popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) {
//the popup should be closed now that another is opening
closeInfoMenu();
}
if (popupInitialised && document.getElementById("sponsorBlockPopupContainer") != null) {
//the popup should be closed now that another is opening
closeInfoMenu();
}
popupInitialised = true;
break;
case "getVideoID":
sendResponse({
videoID: sponsorVideoID
});
popupInitialised = true;
break;
case "getVideoID":
sendResponse({
videoID: sponsorVideoID
});
break;
case "getVideoDuration":
sendResponse({
duration: v.duration
});
break;
case "getVideoDuration":
sendResponse({
duration: v.duration
});
break;
case "skipToTime":
v.currentTime = request.time;
return
case "getCurrentTime":
sendResponse({
currentTime: v.currentTime
});
break;
case "skipToTime":
v.currentTime = request.time;
return
case "getCurrentTime":
sendResponse({
currentTime: v.currentTime
});
break;
case "getChannelURL":
sendResponse({
channelURL: channelURL
});
break;
case "getChannelURL":
sendResponse({
channelURL: channelURL
});
break;
case "isChannelWhitelisted":
sendResponse({
value: channelWhitelisted
});
break;
case "isChannelWhitelisted":
sendResponse({
value: channelWhitelisted
});
break;
case "whitelistChange":
channelWhitelisted = request.value;
sponsorsLookup(sponsorVideoID);
break;
case "whitelistChange":
channelWhitelisted = request.value;
sponsorsLookup(sponsorVideoID);
break;
case "changeStartSponsorButton":
changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible);
break;
case "dontShowNotice":
dontShowNotice = false;
break;
case "changeStartSponsorButton":
changeStartSponsorButton(request.showStartSponsor, request.uploadButtonVisible);
break;
case "showNoticeAgain":
dontShowNotice = false;
break;
case "changeVideoPlayerControlsVisibility":
hideVideoPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
break;
case "changeInfoButtonPlayerControlsVisibility":
hideInfoButtonPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
break;
case "changeDeleteButtonPlayerControlsVisibility":
hideDeleteButtonPlayerControls = request.value;
updateVisibilityOfPlayerControlsButton();
break;
case "trackViewCount":
trackViewCount = request.value;
break;
}
}
/**
* Called when the config is updated
*
* @param {String} changes
*/
function contentConfigUpdateListener(changes) {
for (const key in changes) {
switch(key) {
case "hideVideoPlayerControls":
case "hideInfoButtonPlayerControls":
case "hideDeleteButtonPlayerControls":
updateVisibilityOfPlayerControlsButton()
break;
}
}
}
if (!SB.configListeners.includes(contentConfigUpdateListener)) {
SB.configListeners.push(contentConfigUpdateListener);
}
//check for hotkey pressed
@@ -231,19 +171,9 @@ document.onkeydown = async function(e){
let video = document.getElementById("movie_player");
let startSponsorKey = await new Promise((resolve, reject) => {
chrome.storage.sync.get(["startSponsorKeybind"], (result) => resolve(result));
});
let submitKey = await new Promise((resolve, reject) => {
chrome.storage.sync.get(["submitKeybind"], (result) => resolve(result));
});
let startSponsorKey = SB.config.startSponsorKeybind;
if (startSponsorKey.startSponsorKeybind === undefined) {
startSponsorKey.startSponsorKeybind = ";"
}
if (submitKey.submitKeybind === undefined) {
submitKey.submitKeybind = "'"
}
let submitKey = SB.config.submitKeybind;
//is the video in focus, otherwise they could be typing a comment
if (document.activeElement === video) {
@@ -294,29 +224,39 @@ function videoIDChange(id) {
if (previewBar == null) {
//create it
wait(getControls).then(result => {
let progressBar = document.getElementsByClassName("ytp-progress-bar-container")[0] || document.getElementsByClassName("no-model cue-range-markers")[0];
previewBar = new PreviewBar(progressBar);
const progressElementSelectors = [
// For YouTube
"ytp-progress-bar-container",
"no-model cue-range-markers",
// For Invidious/VideoJS
"vjs-progress-holder"
];
for (const selector of progressElementSelectors) {
const el = document.getElementsByClassName(selector);
if (el && el.length && el[0]) {
previewBar = new PreviewBar(el[0]);
break;
}
}
});
}
//warn them if they had unsubmitted times
if (previousVideoID != null) {
//get the sponsor times from storage
let sponsorTimeKey = 'sponsorTimes' + previousVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
let sponsorTimes = SB.config.sponsorTimes.get(previousVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//warn them that they have unsubmitted sponsor times
chrome.runtime.sendMessage({
message: "alertPrevious",
previousVideoID: previousVideoID
})
}
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//warn them that they have unsubmitted sponsor times
chrome.runtime.sendMessage({
message: "alertPrevious",
previousVideoID: previousVideoID
})
}
//set the previous video id to the currentID
previousVideoID = id;
});
//set the previous video id to the currentID
previousVideoID = id;
} else {
//set the previous id now, don't wait for chrome.storage.get
previousVideoID = id;
@@ -358,30 +298,10 @@ function videoIDChange(id) {
}
});
});
//see if video controls buttons should be added
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
if (result.hideVideoPlayerControls != undefined) {
hideVideoPlayerControls = result.hideVideoPlayerControls;
}
if (!onInvidious) {
updateVisibilityOfPlayerControlsButton();
});
chrome.storage.sync.get(["hideInfoButtonPlayerControls"], function(result) {
if (result.hideInfoButtonPlayerControls != undefined) {
hideInfoButtonPlayerControls = result.hideInfoButtonPlayerControls;
}
updateVisibilityOfPlayerControlsButton();
});
chrome.storage.sync.get(["hideDeleteButtonPlayerControls"], function(result) {
if (result.hideDeleteButtonPlayerControls != undefined) {
hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
}
updateVisibilityOfPlayerControlsButton(false);
});
}
}
function sponsorsLookup(id, channelIDPromise) {
@@ -463,7 +383,7 @@ function sponsorsLookup(id, channelIDPromise) {
});
//add the event to run on the videos "ontimeupdate"
if (!disableSkipping) {
if (!SB.config.disableSkipping) {
v.ontimeupdate = function () {
sponsorCheck();
};
@@ -498,12 +418,14 @@ function updatePreviewBar() {
function getChannelID() {
//get channel id
let channelNameContainer = document.getElementById("channel-name");
let channelURLContainer = null;
if (channelNameContainer !== null) {
channelURLContainer = channelNameContainer.querySelector("#container").querySelector("#text-container").querySelector("#text").firstElementChild;
channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text");
if (channelURLContainer !== null) {
channelURLContainer = channelURLContainer.firstElementChild;
} else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a");
} else {
//old YouTube theme
let channelContainers = document.getElementsByClassName("yt-user-info");
@@ -522,6 +444,9 @@ function getChannelID() {
let currentTitle = "";
if (titleInfoContainer != null) {
currentTitle = titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild.innerText;
} else if (onInvidious) {
// Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers...
currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent;
} else {
//old YouTube theme
currentTitle = document.getElementById("eow-title").innerText;
@@ -543,20 +468,16 @@ function getChannelID() {
//checks if this channel is whitelisted, should be done only after the channelID has been loaded
function whitelistCheck() {
//see if this is a whitelisted channel
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
let whitelistedChannels = SB.config.whitelistedChannels;
console.log(channelURL)
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
channelWhitelisted = true;
}
});
if (whitelistedChannels != undefined && whitelistedChannels.includes(channelURL)) {
channelWhitelisted = true;
}
}
//video skipping
function sponsorCheck() {
if (disableSkipping) {
if (SB.config.disableSkipping) {
// Make sure this isn't called again
v.ontimeupdate = null;
return;
@@ -622,7 +543,7 @@ function checkIfTimeToSkip(currentVideoTime, startTime, endTime) {
//skip fromt he start time to the end time for a certain index sponsor time
function skipToTime(v, index, sponsorTimes, openNotice) {
if (!disableAutoSkip) {
if (!SB.config.disableAutoSkip) {
v.currentTime = sponsorTimes[index][1];
}
@@ -633,42 +554,31 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
if (openNotice) {
//send out the message saying that a sponsor message was skipped
if (!dontShowNotice) {
let skipNotice = new SkipNotice(this, currentUUID, disableAutoSkip);
if (!SB.config.dontShowNotice) {
let skipNotice = new SkipNotice(this, currentUUID, SB.config.disableAutoSkip);
if (dontShowNoticeOld) {
//show why this notice is showing
skipNotice.addNoticeInfoMessage(chrome.i18n.getMessage("noticeUpdate"), chrome.i18n.getMessage("noticeUpdate2"));
//TODO: Remove this when Invidious support is old
if (SB.config.invidiousUpdateInfoShowCount < 5) {
skipNotice.addNoticeInfoMessage(chrome.i18n.getMessage("invidiousInfo1"), chrome.i18n.getMessage("invidiousInfo2"));
//remove this setting
chrome.storage.sync.remove(["dontShowNoticeAgain"]);
dontShowNoticeOld = false;
SB.config.invidiousUpdateInfoShowCount += 1;
}
//auto-upvote this sponsor
if (trackViewCount && !disableAutoSkip) {
if (SB.config.trackViewCount && !SB.config.disableAutoSkip && SB.config.autoUpvote) {
vote(1, currentUUID, null);
}
}
}
//send telemetry that a this sponsor was skipped happened
if (trackViewCount && !sponsorSkipped[index]) {
sendRequestToServer("GET", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
//send telemetry that a this sponsor was skipped
if (SB.config.trackViewCount && !sponsorSkipped[index]) {
sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID);
if (!disableAutoSkip) {
if (!SB.config.disableAutoSkip) {
// Count this as a skip
chrome.storage.sync.get(["minutesSaved"], function(result) {
if (result.minutesSaved === undefined) result.minutesSaved = 0;
chrome.storage.sync.set({"minutesSaved": result.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60 });
});
chrome.storage.sync.get(["skipCount"], function(result) {
if (result.skipCount === undefined) result.skipCount = 0;
chrome.storage.sync.set({"skipCount": result.skipCount + 1 });
});
SB.config.minutesSaved = SB.config.minutesSaved + (sponsorTimes[index][1] - sponsorTimes[index][0]) / 60;
SB.config.skipCount = SB.config.skipCount + 1;
sponsorSkipped[index] = true;
}
}
@@ -688,13 +598,6 @@ function reskipSponsorTime(UUID) {
}
}
function removePlayerControlsButton() {
if (!sponsorVideoID) return;
document.getElementById("startSponsorButton").style.display = "none";
document.getElementById("submitButton").style.display = "none";
}
function createButton(baseID, title, callback, imageName, isDraggable=false) {
if (document.getElementById(baseID + "Button") != null) return;
@@ -722,7 +625,14 @@ function createButton(baseID, title, callback, imageName, isDraggable=false) {
function getControls() {
let controls = document.getElementsByClassName("ytp-right-controls");
return (!controls || controls.length === 0) ? false : controls[controls.length - 1]
if (!controls || controls.length === 0) {
// The invidious video element's controls element
controls = document.getElementsByClassName("vjs-control-bar");
return (!controls || controls.length === 0) ? false : controls[controls.length - 1];
} else {
return controls[controls.length - 1];
}
};
//adds all the player controls buttons
@@ -745,14 +655,21 @@ async function updateVisibilityOfPlayerControlsButton() {
await createButtons();
if (hideVideoPlayerControls) {
removePlayerControlsButton();
if (SB.config.hideVideoPlayerControls || onInvidious) {
document.getElementById("startSponsorButton").style.display = "none";
document.getElementById("submitButton").style.display = "none";
} else {
document.getElementById("startSponsorButton").style.removeProperty("display");
}
//don't show the info button on embeds
if (hideInfoButtonPlayerControls || document.URL.includes("/embed/")) {
if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious) {
document.getElementById("infoButton").style.display = "none";
} else {
document.getElementById("infoButton").style.removeProperty("display");
}
if (hideDeleteButtonPlayerControls) {
if (SB.config.hideDeleteButtonPlayerControls || onInvidious) {
document.getElementById("deleteButton").style.display = "none";
}
}
@@ -804,7 +721,7 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
await wait(isSubmitButtonLoaded);
//if it isn't visible, there is no data
let shouldHide = (uploadButtonVisible && !hideDeleteButtonPlayerControls) ? "unset" : "none"
let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none"
document.getElementById("deleteButton").style.display = shouldHide;
if (showStartSponsor) {
@@ -812,7 +729,7 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png");
document.getElementById("startSponsorButton").setAttribute("title", chrome.i18n.getMessage("sponsorStart"));
if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible && !hideInfoButtonPlayerControls) {
if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible && !SB.config.hideInfoButtonPlayerControls) {
document.getElementById("submitButton").style.display = "unset";
} else if (!uploadButtonVisible) {
//disable submit button
@@ -907,28 +824,24 @@ function clearSponsorTimes() {
let currentVideoID = sponsorVideoID;
let sponsorTimeKey = 'sponsorTimes' + currentVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
let sponsorTimes = SB.config.sponsorTimes.get(currentVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let confirmMessage = chrome.i18n.getMessage("clearThis") + getSponsorTimesMessage(sponsorTimes);
confirmMessage += chrome.i18n.getMessage("confirmMSG")
if(!confirm(confirmMessage)) return;
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
let confirmMessage = chrome.i18n.getMessage("clearThis") + getSponsorTimesMessage(sponsorTimes)
+ "\n" + chrome.i18n.getMessage("confirmMSG")
if(!confirm(confirmMessage)) return;
//clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: []});
//clear the sponsor times
SB.config.sponsorTimes.delete(currentVideoID);
//clear sponsor times submitting
sponsorTimesSubmitting = [];
//clear sponsor times submitting
sponsorTimesSubmitting = [];
updatePreviewBar();
updatePreviewBar();
//set buttons to be correct
changeStartSponsorButton(true, false);
}
});
//set buttons to be correct
changeStartSponsorButton(true, false);
}
}
//if skipNotice is null, it will not affect the UI
@@ -941,26 +854,21 @@ function vote(type, UUID, skipNotice) {
let sponsorIndex = UUIDs.indexOf(UUID);
// See if the local time saved count and skip count should be reverted
// See if the local time saved count and skip count should be saved
if (type == 0 && sponsorSkipped[sponsorIndex] || type == 1 && !sponsorSkipped[sponsorIndex]) {
let factor = 1;
if (type == 0) {
factor = -1;
sponsorSkipped[sponsorIndex] = false;
}
// Count this as a skip
chrome.storage.sync.get(["minutesSaved"], function(result) {
if (result.minutesSaved === undefined) result.minutesSaved = 0;
// Count this as a skip
SB.config.minutesSaved = SB.config.minutesSaved + factor * (sponsorTimes[sponsorIndex][1] - sponsorTimes[sponsorIndex][0]) / 60;
SB.config.skipCount = 0;
chrome.storage.sync.set({"minutesSaved": result.minutesSaved + factor * (sponsorTimes[sponsorIndex][1] - sponsorTimes[sponsorIndex][0]) / 60 });
});
chrome.storage.sync.get(["skipCount"], function(result) {
if (result.skipCount === undefined) result.skipCount = 0;
chrome.storage.sync.set({"skipCount": result.skipCount + factor * 1 });
});
sponsorSkipped[sponsorIndex] = !sponsorSkipped[sponsorIndex];
SB.config.skipCount = SB.config.skipCount + factor * 1;
}
chrome.runtime.sendMessage({
@@ -998,10 +906,7 @@ function closeAllSkipNotices(){
}
function dontShowNoticeAgain() {
chrome.storage.sync.set({"dontShowNotice": true});
dontShowNotice = true;
SB.config.dontShowNotice = true;
closeAllSkipNotices();
}
@@ -1028,30 +933,27 @@ function submitSponsorTimes() {
let currentVideoID = sponsorVideoID;
let sponsorTimeKey = 'sponsorTimes' + currentVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimes = result[sponsorTimeKey];
let sponsorTimes = SB.config.sponsorTimes.get(currentVideoID);
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//check if a sponsor exceeds the duration of the video
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i][1] > v.duration) {
sponsorTimes[i][1] = v.duration;
}
if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//check if a sponsor exceeds the duration of the video
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i][1] > v.duration) {
sponsorTimes[i][1] = v.duration;
}
//update sponsorTimes
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes});
//update sponsorTimesSubmitting
sponsorTimesSubmitting = sponsorTimes;
let confirmMessage = chrome.i18n.getMessage("submitCheck") + "\n\n" + getSponsorTimesMessage(sponsorTimes)
+ "\n\n" + chrome.i18n.getMessage("confirmMSG") + "\n\n" + chrome.i18n.getMessage("guildlinesSummary");
if(!confirm(confirmMessage)) return;
sendSubmitMessage();
}
});
//update sponsorTimes
SB.config.sponsorTimes.set(currentVideoID, sponsorTimes);
//update sponsorTimesSubmitting
sponsorTimesSubmitting = sponsorTimes;
let confirmMessage = chrome.i18n.getMessage("submitCheck") + "\n\n" + getSponsorTimesMessage(sponsorTimes)
+ "\n\n" + chrome.i18n.getMessage("confirmMSG") + "\n\n" + chrome.i18n.getMessage("guildlinesSummary");
if(!confirm(confirmMessage)) return;
sendSubmitMessage();
}
}
@@ -1086,8 +988,7 @@ function sendSubmitMessage(){
submitButton.addEventListener("animationend", animationEndListener);
//clear the sponsor times
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: []});
SB.config.sponsorTimes.delete(currentVideoID);
//add submissions to current sponsors list
sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting);

10
crowdin.yml Normal file
View File

@@ -0,0 +1,10 @@
files:
- source: /_locales/en/*
translation: /_locales/%two_letters_code%/%original_file_name%
languages_mapping:
two_letters_code:
pl-PL: "pl_PL"
pr-BR: "pt_BR"
pr-PT: "pt_PT"
zh-CN: "zh_CH"
zh-TW: "zh_TW"

View File

@@ -1,8 +1,7 @@
{
"browser_specific_settings": {
"gecko": {
"id": "sponsorBlocker@ajay.app",
"strict_min_version": "57.0"
"id": "sponsorBlocker@ajay.app"
}
}
}

View File

@@ -1,5 +1,8 @@
<!DOCTYPE html>
<head>
<title> SponsorBlock </title>
<meta charset="utf-8">
<link href="styles.css" rel="stylesheet"/>
</head>
@@ -11,9 +14,9 @@
SponsorBlock
</div>
<center>
<div class="container">
<p class="createdBy">Created By <a href="https://ajay.app">Ajay Ramachandran</a></p>
<p class="createdBy">Created By <a href="https://ajay.app">Ajay Ramachandran</a> <img src="https://ajay.app/newprofilepic.jpg" height="30" class="profilepiccircle"/></p>
<p>
Thanks for installing SponsorBlock. Here are some quick tips for getting started. Please join the Discord if you have any questions or suggestions.
@@ -27,6 +30,12 @@
Come contribute, make some suggestions and help out in the Discord: <a href="https://discord.gg/QnmVMpU">https://discord.gg/QnmVMpU</a>
</p>
<a class="bigText" href="/options/options.html">Enable Invidious Support</a>
<p>
Invidious is a third-party YouTube viewer. SponsorBlock now supports invidious along with YouTube. Please visit the options page to make sure everything is how you want it to be.
</p>
<h1>How skipping works</h1>
<p class="projectPreview">
@@ -42,7 +51,7 @@
Whenever you skip a video, you will get a notice report that submission. If the timing seems wrong, report it! You can also vote in the popup. The extension auto upvotes it if you don't report it, so make sure to report when necessary (this can be disabled in the options).
</p>
<center><img height="120px" src="https://user-images.githubusercontent.com/12688112/63067735-5a638700-bede-11e9-8147-f321b57527ec.gif"></center>
<div class="center"><img height="120px" src="https://user-images.githubusercontent.com/12688112/63067735-5a638700-bede-11e9-8147-f321b57527ec.gif"></div>
<h1>Submitting</h1>
@@ -100,7 +109,7 @@
Ask on Discord or make an Issue on GitHub. I am happy to hear suggestions or improvements you want. You may also contribute code or graphics if you would like.
</p>
<h1>Where can I get the source code</h1>
<h1>Where can I get the source code?</h1>
<h4 style="display: inline">Client:</h4>
<!-- Github logo -->
@@ -110,7 +119,7 @@
<!-- Github logo -->
<a href="https://github.com/ajayyy/SponsorBlockServer"><svg aria-hidden="true" version="1.1" viewBox="0 0 16 16" height="58px" style="padding-left: 15px"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg></a>
<h1>Credit</h1>
<h1>Credits</h1>
<p>The awesome <a href="https://github.com/omarroth/invidious/wiki/API">Invidious API</a> is used to grab the time the video was published.</p>
@@ -118,6 +127,6 @@
<p>Some icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a> and are licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></p>
</center>
</div>
</body>

View File

@@ -1,5 +1,19 @@
:not(.hljs-keyword):not(.hljs-comment):not(.hljs-number):not(.hljs-string):not(pre):not(code) {
.bigText {
font-size: 50px;
}
body {
background-color: #333333;
font-family: sans-serif;
}
.center {
text-align: center;
}
.container {
max-width: 60%;
margin: auto;
}
.projectPreview {
@@ -8,24 +22,24 @@
.projectPreviewImage {
position: absolute;
left: -90;
width: 80;
left: -90px;
width: 80px;
top: 50%;
transform: translateY(-50%);
}
.projectPreviewImageLarge {
position: absolute;
left: -210;
width: 200;
left: -210px;
width: 200px;
top: 50%;
transform: translateY(-20%);
}
.projectPreviewImageLargeRight {
position: absolute;
right: -210;
width: 200;
right: -210px;
width: 200px;
top: 50%;
transform: translateY(-50%);
}
@@ -43,37 +57,27 @@
text-align: center;
vertical-align: middle;
font-family: sans-serif;
font-size: 50;
font-size: 50px;
color: #212121;
/* height: 100; */
padding: 20;
padding: 20px;
text-decoration: none;
transition: font-size 1s;
}
#title:hover {
font-size: 60;
transition: font-size 1s;
}
.subtitle {
font-family: sans-serif;
font-size: 40;
font-size: 40px;
color: #dad8d8;
padding-top: 10;
padding-top: 10px;
transition: font-size 0.4s;
}
.subtitle:hover {
font-size: 45;
font-size: 45px;
transition: font-size 0.4s;
}
@@ -83,13 +87,19 @@
vertical-align: middle;
}
.profilepiccircle {
vertical-align: middle;
overflow: hidden;
border-radius: 50%;
}
a {
text-decoration: underline;
color: inherit;
}
.link {
padding: 20;
padding: 20px;
height: 80px;
@@ -103,29 +113,24 @@ a {
}
#contact,.smalllink {
font-family: sans-serif;
font-size: 25;
font-size: 25px;
color: #e8e8e8;
text-align: center;
padding: 10;
padding: 10px;
}
#contact {
text-decoration: none;
}
p,li {
font-family: sans-serif;
font-size: 20;
p,li,a {
font-size: 20px;
color: #c4c4c4;
padding: 10;
}
p,li,code,a {
max-width: 60%;
text-align: left;
overflow-wrap: break-word;
}
@@ -137,7 +142,7 @@ p,li,code,a {
.projectPreviewImage {
position: unset;
width: 130;
width: 130px;
display: block;
margin: auto;
transform: none;
@@ -155,20 +160,18 @@ img {
}
#recentPostTitle {
font-family: sans-serif;
font-size: 30;
font-size: 30px;
color: #dad8d8;
}
#recentPostDate {
font-family: sans-serif;
font-size: 15;
font-size: 15px;
color: #dad8d8;
}
h1,h2,h3,h4,h5,h6 {
font-family: sans-serif;
color: #dad8d8;
text-align: center;
}
svg {

BIN
icons/newprofilepic.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -1,11 +1,12 @@
{
"name": "__MSG_fullName__",
"short_name": "__MSG_Name__",
"version": "1.2.1",
"version": "1.2.5",
"default_locale": "en",
"description": "__MSG_Description__",
"content_scripts": [
{
"run_at": "document_start",
"matches": [
"https://*.youtube.com/*",
"https://www.youtube-nocookie.com/embed/*"
@@ -13,6 +14,7 @@
"all_frames": true,
"js": [
"config.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
@@ -46,14 +48,19 @@
"notifications",
"https://sponsor.ajay.app/*"
],
"optional_permissions": [
"*://*/*",
"declarativeContent"
],
"browser_action": {
"default_title": "__MSG_Name__",
"default_popup": "popup.html"
},
"background": {
"scripts":[
"utils.js",
"config.js",
"SB.js",
"utils.js",
"background.js"
],
"persistent": false
@@ -65,5 +72,9 @@
"128": "icons/LogoSponsorBlocker128px.png",
"256": "icons/LogoSponsorBlocker256px.png"
},
"options_ui": {
"page": "options/options.html",
"open_in_tab": true
},
"manifest_version": 2
}

312
options/options.css Normal file
View File

@@ -0,0 +1,312 @@
/* Options page CSS */
body {
font-family: sans-serif;
}
.center {
text-align: center;
}
.inline {
display: inline-block;
}
.bold {
font-weight: bold;
}
.hidden {
display: none !important;
}
.keybind-status {
display: inline;
}
.small-description {
color: white;
font-size: 13px;
}
.medium-description {
color: white;
font-size: 15px;
}
.option-text-box {
width: 300px;
}
.option-button {
cursor: pointer;
background-color: #c00000;
padding: 10px;
color: white;
border-radius: 5px;
font-size: 14px;
width: max-content;
}
.option-button:hover {
background-color: #fc0303;
}
.option-button.disabled {
cursor: default;
background-color: #520000;
color: grey;
}
#options {
max-width: 60%;
text-align: left;
display: inline-block;
}
.switch-container:after {
content: attr(label-name);
position: absolute;
padding: 4px;
width: max-content;
font-size: 14px;
color: white;
}
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 24px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #707070;
}
.animated * {
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: white;
}
.animated .slider:before {
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #fc0303;
}
input:checked + .slider:before {
-webkit-transform: translateX(16px);
-ms-transform: translateX(16px);
transform: translateX(16px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
/* Boilerplate CSS from https://ajay.app */
body {
background-color: #333333;
}
.projectPreview {
position: relative;
}
.projectPreviewImage {
position: absolute;
left: -90px;
width: 80px;
top: 50%;
transform: translateY(-50%);
}
.projectPreviewImageLarge {
position: absolute;
left: -210px;
width: 200px;
top: 50%;
transform: translateY(-20%);
}
.projectPreviewImageLargeRight {
position: absolute;
right: -210px;
width: 200px;
top: 50%;
transform: translateY(-50%);
}
.createdBy {
font-size: 14px;
text-align: center;
padding-top: 0px;
padding-bottom: 0px;
display: inline-block;
}
#title {
background-color: #636363;
text-align: center;
vertical-align: middle;
font-size: 50px;
color: #212121;
padding: 20px;
text-decoration: none;
transition: font-size 1s;
}
.subtitle {
font-size: 40px;
color: #dad8d8;
padding-top: 10px;
transition: font-size 0.4s;
}
.subtitle:hover {
font-size: 45px;
transition: font-size 0.4s;
}
.profilepic {
background-color: #636363 !important;
vertical-align: middle;
}
.profilepiccircle {
vertical-align: middle;
overflow: hidden;
border-radius: 50%;
}
a {
text-decoration: underline;
color: inherit;
}
.link {
padding: 20px;
height: 80px;
transition: height 0.2s;
}
.link:hover {
height: 95px;
transition: height 0.2s;
}
#contact,.smalllink {
font-size: 25px;
color: #e8e8e8;
text-align: center;
padding: 10px;
}
#contact {
text-decoration: none;
}
p,li {
font-size: 20px;
color: #c4c4c4;
padding: 10px;
}
p,li,code,a {
max-width: 60%;
text-align: left;
overflow-wrap: break-word;
}
@media screen and (orientation:portrait) {
p,li,code,a {
max-width: 100%;
}
.projectPreviewImage {
position: unset;
width: 130px;
display: block;
margin: auto;
transform: none;
}
}
.previewImage {
max-height: 200px;
}
img {
max-width: 100%;
text-align: center;
}
#recentPostTitle {
font-size: 30px;
color: #dad8d8;
}
#recentPostDate {
font-size: 15px;
color: #dad8d8;
}
h1,h2,h3,h4,h5,h6 {
color: #dad8d8;
}
svg {
text-decoration: none;
}

263
options/options.html Normal file
View File

@@ -0,0 +1,263 @@
<!DOCTYPE html>
<head>
<title>Options - SponsorBlock</title>
<meta charset="utf-8">
<link href="options.css" rel="stylesheet"/>
<script src="../utils.js"></script>
<script src="../SB.js"></script>
<script src="options.js"></script>
</head>
<body class="sponsorBlockPageBody">
<div id="title">
<img src="../icons/LogoSponsorBlocker256px.png" height="80" class="profilepic"/>
SponsorBlock
</div>
<div class="center">
<p class="createdBy">__MSG_createdBy__ <a href="https://ajay.app">Ajay Ramachandran</a> <img src="../icons/newprofilepic.jpg" height="30" class="profilepiccircle"/></p>
<h1>__MSG_Options__</h1>
<div id="options" class="hidden">
<div id="support-invidious" option-type="toggle" sync-option="supportInvidious">
<label class="switch-container" label-name="__MSG_supportInvidious__">
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_supportInvidiousDescription__</div>
</div>
<br/>
<br/>
<div option-type="text-change" sync-option="invidiousInstances">
<div class="option-button trigger-button">
__MSG_addInvidiousInstance__
</div>
<br/>
<div class="small-description">__MSG_addInvidiousInstanceDescription__</div>
<div class="option-hidden-section hidden">
<br/>
<input class="option-text-box" type="text">
<br/>
<br/>
<div class="option-button text-change-set inline">
__MSG_add__
</div>
<div class="option-button invidious-instance-reset inline">
__MSG_resetInvidiousInstance__
</div>
<br/>
<br/>
<span class="small-description">__MSG_currentInstances__</span>
<span class="small-description" option-type="display" sync-option="invidiousInstances"></span>
</div>
</div>
<br/>
<br/>
<div option-type="toggle" toggle-type="reverse" sync-option="disableAutoSkip">
<label class="switch-container" label-name="__MSG_autoSkip__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_autoSkipDescription__</div>
</div>
<br/>
<br/>
<div option-type="keybind-change" sync-option="startSponsorKeybind">
<div class="option-button trigger-button">
__MSG_setStartSponsorShortcut__
</div>
<div class="option-hidden-section hidden">
<br/>
<div class="medium-description keybind-status">
__MSG_keybindDescription__
</div>
<span class="medium-description bold keybind-status-key">
</span>
</div>
</div>
<br/>
<br/>
<div option-type="keybind-change" sync-option="submitKeybind">
<div class="option-button trigger-button">
__MSG_setSubmitKeybind__
</div>
<div class="option-hidden-section hidden">
<br/>
<div class="medium-description keybind-status">
__MSG_keybindDescription__
</div>
<span class="medium-description bold keybind-status-key">
</span>
</div>
</div>
<br/>
<br/>
<div option-type="toggle" toggle-type="reverse" sync-option="hideVideoPlayerControls">
<label class="switch-container" label-name="__MSG_showButtons__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_hideButtonsDescription__</div>
</div>
<br/>
<br/>
<div option-type="toggle" toggle-type="reverse" sync-option="hideInfoButtonPlayerControls">
<label class="switch-container" label-name="__MSG_showInfoButton__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatInfoButton__</div>
</div>
<br/>
<br/>
<div option-type="toggle" toggle-type="reverse" sync-option="hideDeleteButtonPlayerControls">
<label class="switch-container" label-name="__MSG_showDeleteButton__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatDeleteButton__</div>
</div>
<br/>
<br/>
<div option-type="toggle" sync-option="autoUpvote">
<label class="switch-container" label-name="__MSG_enableAutoUpvote__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatAutoUpvote__</div>
</div>
<br/>
<br/>
<div option-type="toggle" sync-option="trackViewCount">
<label class="switch-container" label-name="__MSG_enableViewTracking__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
<br/>
<br/>
<div class="small-description">__MSG_whatViewTracking__</div>
</div>
<br/>
<br/>
<div option-type="text-change" sync-option="userID" confirm-message="userIDChangeWarning">
<div class="option-button trigger-button">
__MSG_changeUserID__
</div>
<br/>
<div class="small-description">__MSG_whatChangeUserID__</div>
<div class="option-hidden-section hidden">
<br/>
<input class="option-text-box" type="text">
<br/>
<br/>
<div class="option-button text-change-set">
__MSG_setUserID__
</div>
</div>
</div>
<br/>
<br/>
<div option-type="toggle" toggle-type="reverse" sync-option="dontShowNotice">
<label class="switch-container" label-name="__MSG_showSkipNotice__">
<label class="switch">
<input type="checkbox" checked>
<span class="slider round"></span>
</label>
</label>
</div>
</div>
</div>
</body>

292
options/options.js Normal file
View File

@@ -0,0 +1,292 @@
window.addEventListener('DOMContentLoaded', init);
async function init() {
localizeHtmlPage();
if (!SB.configListeners.includes(optionsConfigUpdateListener)) {
SB.configListeners.push(optionsConfigUpdateListener);
}
await wait(() => SB.config !== undefined);
// Set all of the toggle options to the correct option
let optionsContainer = document.getElementById("options");
let optionsElements = optionsContainer.querySelectorAll("*");
for (let i = 0; i < optionsElements.length; i++) {
switch (optionsElements[i].getAttribute("option-type")) {
case "toggle":
let option = optionsElements[i].getAttribute("sync-option");
let optionResult = SB.config[option];
let checkbox = optionsElements[i].querySelector("input");
let reverse = optionsElements[i].getAttribute("toggle-type") === "reverse";
if (optionResult != undefined) {
checkbox.checked = optionResult;
if (reverse) {
optionsElements[i].querySelector("input").checked = !optionResult;
}
}
// See if anything extra should be run first time
switch (option) {
case "supportInvidious":
invidiousInit(checkbox, option);
break;
}
// Add click listener
checkbox.addEventListener("click", () => {
SB.config[option] = reverse ? !checkbox.checked : checkbox.checked;
// See if anything extra must be run
switch (option) {
case "supportInvidious":
invidiousOnClick(checkbox, option);
break;
}
});
break;
case "text-change":
let button = optionsElements[i].querySelector(".trigger-button");
button.addEventListener("click", () => activateTextChange(optionsElements[i]));
let textChangeOption = optionsElements[i].getAttribute("sync-option");
// See if anything extra must be done
switch (textChangeOption) {
case "invidiousInstances":
invidiousInstanceAddInit(optionsElements[i], textChangeOption);
}
break;
case "keybind-change":
let keybindButton = optionsElements[i].querySelector(".trigger-button");
keybindButton.addEventListener("click", () => activateKeybindChange(optionsElements[i]));
break;
case "display":
updateDisplayElement(optionsElements[i])
}
}
optionsContainer.classList.remove("hidden");
optionsContainer.classList.add("animated");
}
/**
* Called when the config is updated
*
* @param {String} element
*/
function optionsConfigUpdateListener(changes) {
let optionsContainer = document.getElementById("options");
let optionsElements = optionsContainer.querySelectorAll("*");
for (let i = 0; i < optionsElements.length; i++) {
switch (optionsElements[i].getAttribute("option-type")) {
case "display":
updateDisplayElement(optionsElements[i])
}
}
}
/**
* Will set display elements to the proper text
*
* @param {HTMLElement} element
*/
function updateDisplayElement(element) {
let displayOption = element.getAttribute("sync-option")
let displayText = SB.config[displayOption];
element.innerText = displayText;
// See if anything extra must be run
switch (displayOption) {
case "invidiousInstances":
element.innerText = displayText.join(', ');
break;
}
}
/**
* Initializes the option to add Invidious instances
*
* @param {HTMLElement} element
* @param {String} option
*/
function invidiousInstanceAddInit(element, option) {
let textBox = element.querySelector(".option-text-box");
let button = element.querySelector(".trigger-button");
let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async function(e) {
if (textBox.value == "" || textBox.value.includes("/") || textBox.value.includes("http") || textBox.value.includes(":")) {
alert(chrome.i18n.getMessage("addInvidiousInstanceError"));
} else {
// Add this
let instanceList = SB.config[option];
if (!instanceList) instanceList = [];
instanceList.push(textBox.value);
SB.config[option] = instanceList;
let checkbox = document.querySelector("#support-invidious input");
checkbox.checked = true;
invidiousOnClick(checkbox, "supportInvidious");
textBox.value = "";
// Hide this section again
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
}
});
let resetButton = element.querySelector(".invidious-instance-reset");
resetButton.addEventListener("click", function(e) {
if (confirm(chrome.i18n.getMessage("resetInvidiousInstanceAlert"))) {
// Set to a clone of the default
SB.config[option] = SB.defaults[option].slice(0);
}
});
}
/**
* Run when the invidious button is being initialized
*
* @param {HTMLElement} checkbox
* @param {string} option
*/
function invidiousInit(checkbox, option) {
let permissions = ["declarativeContent"];
if (isFirefox()) permissions = [];
chrome.permissions.contains({
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, function (result) {
if (result != checkbox.checked) {
SB.config[option] = result;
checkbox.checked = result;
}
});
}
/**
* Run whenever the invidious checkbox is clicked
*
* @param {HTMLElement} checkbox
* @param {string} option
*/
function invidiousOnClick(checkbox, option) {
if (checkbox.checked) {
setupExtraSitePermissions(function (granted) {
if (!granted) {
SB.config[option] = false;
checkbox.checked = false;
}
});
} else {
removeExtraSiteRegistration();
}
}
/**
* Will trigger the container to ask the user for a keybind.
*
* @param {HTMLElement} element
*/
function activateKeybindChange(element) {
let button = element.querySelector(".trigger-button");
if (button.classList.contains("disabled")) return;
button.classList.add("disabled");
let option = element.getAttribute("sync-option");
let currentlySet = SB.config[option] !== null ? chrome.i18n.getMessage("keybindCurrentlySet") : "";
let status = element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescription") + currentlySet;
if (SB.config[option] !== null) {
let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = SB.config[option];
}
element.querySelector(".option-hidden-section").classList.remove("hidden");
document.addEventListener("keydown", (e) => keybindKeyPressed(element, e), {once: true});
}
/**
* Called when a key is pressed in an activiated keybind change option.
*
* @param {HTMLElement} element
* @param {KeyboardEvent} e
*/
function keybindKeyPressed(element, e) {
e = e || window.event;
var key = e.key;
let button = element.querySelector(".trigger-button");
// cancel setting a keybind
if (key === "Escape") {
element.querySelector(".option-hidden-section").classList.add("hidden");
button.classList.remove("disabled");
return;
}
let option = element.getAttribute("sync-option");
SB.config[option] = key;
let status = element.querySelector(".option-hidden-section > .keybind-status");
status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete");
let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key");
statusKey.innerText = key;
button.classList.remove("disabled");
}
/**
* Will trigger the textbox to appear to be able to change an option's text.
*
* @param {HTMLElement} element
*/
function activateTextChange(element) {
let button = element.querySelector(".trigger-button");
if (button.classList.contains("disabled")) return;
button.classList.add("disabled");
let textBox = element.querySelector(".option-text-box");
let option = element.getAttribute("sync-option");
// See if anything extra must be done
switch (option) {
case "invidiousInstances":
element.querySelector(".option-hidden-section").classList.remove("hidden");
return;
}
textBox.value = SB.config[option];
let setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", () => {
let confirmMessage = element.getAttribute("confirm-message");
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
SB.config[option] = textBox.value;
}
});
element.querySelector(".option-hidden-section").classList.remove("hidden");
}

7588
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "sponsorblock",
"version": "1.0.0",
"description": "",
"main": "background.js",
"dependencies": {},
"devDependencies": {
"web-ext": "^4.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm",
"build": "web-ext build --overwrite-dest -i \"*(package-lock.json|README.md|package.json|config.js.example|firefox_manifest-extra.json|manifest.json.original|ignored|crowdin.yml)\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/ajayyy/SponsorBlock.git"
},
"author": "Ajay Ramachandran",
"license": "GPL-3.0-only",
"private": true
}

View File

@@ -1,13 +1,14 @@
<html>
<head>
<title>__MSG_openPopup__</title>
<script src="SB.js"></script>
<link id="sponorBlockPopupFont" rel="stylesheet" type="text/css" href="/libs/Source+Sans+Pro.css"/>
<link id="sponorBlockStyleSheet" rel="stylesheet" type="text/css" href="popup.css"/>
</head>
<body class="popupBody">
<center>
<div id="app" class="popupBody">
<div id="app" class="popupBody sponsorBlockPageBody">
<h1 class="popupElement">
<img src="icons/IconSponsorBlocker256px.png" height="32px" id="sponsorBlockPopupLogo"/>
__MSG_Name__
@@ -193,78 +194,17 @@
<br/>
<button id="optionsButton" class="dangerButton popupElement">__MSG_Options__</button>
</div>
<div id="options" class="popupElement" style="display: none">
<br/>
<h3>__MSG_Options__</h3>
<button id="disableAutoSkip" class="warningButton popupElement">__MSG_disableAutoSkip__</button>
<button id="enableAutoSkip" style="display: none" class="warningButton popupElement">__MSG_enableAutoSkip__</button>
<br/>
<sub class="popupElement">
__MSG_autoSkipDescription__
</sub>
<br/>
<br/>
<span id="keybindButtons">
<button id="setStartSponsorKeybind" class="warningButton popupElement">__MSG_setStartSponsorShortcut__</button>
<br/>
<br/>
<button id="setSubmitKeybind" class="warningButton popupElement">__MSG_setSubmitKeybind__</button>
<br/>
</span>
<h2 id="keybindDescription" style="display: none" class="popupElement">__MSG_keybindDescription__</h2>
<br/>
<br/>
<button id="hideVideoPlayerControls" class="warningButton popupElement">__MSG_hideButtons__</button>
<button id="showVideoPlayerControls" style="display: none" class="warningButton popupElement">__MSG_showButtons__</button>
<br/>
<sub class="popupElement">
__MSG_hideButtonsDescription__
__MSG_optionsInfo__
</sub>
<br/>
<br/>
<button id="hideInfoButtonPlayerControls" class="warningButton popupElement">__MSG_hideInfoButton__</button>
<button id="showInfoButtonPlayerControls" style="display: none" class="warningButton popupElement">__MSG_showInfoButton__</button>
<br/>
<sub class="popupElement">
__MSG_whatInfoButton__
</sub>
<br/>
<br/>
<button id="hideDeleteButtonPlayerControls" class="warningButton popupElement">__MSG_hideDeleteButton__</button>
<button id="showDeleteButtonPlayerControls" style="display: none" class="warningButton popupElement">__MSG_showDeleteButton__</button>
<br/>
<sub class="popupElement">
__MSG_whatDeleteButton__
</sub>
<br/>
<br/>
<button id="disableSponsorViewTracking" class="warningButton popupElement">__MSG_disableViewTracking__</button>
<button id="enableSponsorViewTracking" style="display: none" class="warningButton popupElement">__MSG_enableViewTracking__</button>
<br/>
<sub class="popupElement">
__MSG_whatViewTracking__
</sub>
<br/>
<br/>
<button id="showNoticeAgain" style="display: none" class="dangerButton popupElement">__MSG_showNotice__</button>
</div>
<button id="showNoticeAgain" style="display: none" class="dangerButton popupElement">__MSG_showNotice__</button>
</div>
</center>
</body>

602
popup.js
View File

@@ -1,29 +1,27 @@
//make this a function to allow this to run on the content page
function runThePopup() {
async function runThePopup() {
localizeHtmlPage();
//is it in the popup or content script
var inPopup = true;
if (chrome.tabs == undefined) {
//this is on the content script, use direct communication
chrome.tabs = {};
chrome.tabs.sendMessage = function(id, request, callback) {
messageListener(request, null, callback);
}
//add a dummy query method
chrome.tabs.query = function(config, callback) {
callback([{
url: document.URL,
id: -1
}]);
}
inPopup = false;
//this is on the content script, use direct communication
chrome.tabs = {};
chrome.tabs.sendMessage = function(id, request, callback) {
messageListener(request, null, callback);
}
//add a dummy query method
chrome.tabs.query = function(config, callback) {
callback([{
url: document.URL,
id: -1
}]);
}
inPopup = false;
}
var SB = {};
await wait(() => SB.config !== undefined);
["sponsorStart",
// Top toggles
@@ -31,22 +29,12 @@ function runThePopup() {
"unwhitelistChannel",
"disableSkipping",
"enableSkipping",
// Options
"showNoticeAgain",
"optionsButton",
// More controls
"clearTimes",
"submitTimes",
// options
"showNoticeAgain",
"disableAutoSkip",
"enableAutoSkip",
"hideVideoPlayerControls",
"showVideoPlayerControls",
"hideInfoButtonPlayerControls",
"showInfoButtonPlayerControls",
"hideDeleteButtonPlayerControls",
"showDeleteButtonPlayerControls",
"disableSponsorViewTracking",
"enableSponsorViewTracking",
"optionsButton",
"reportAnIssue",
// sponsorTimesContributions
"sponsorTimesContributionsContainer",
@@ -89,10 +77,6 @@ function runThePopup() {
"videoFound",
"sponsorMessageTimes",
"downloadedSponsorMessageTimes",
// Keybinds
"setStartSponsorKeybind",
"setSubmitKeybind",
"keybindDescription"
].forEach(id => SB[id] = document.getElementById(id));
//setup click listeners
@@ -104,24 +88,12 @@ function runThePopup() {
SB.clearTimes.addEventListener("click", clearTimes);
SB.submitTimes.addEventListener("click", submitTimes);
SB.showNoticeAgain.addEventListener("click", showNoticeAgain);
SB.disableAutoSkip.addEventListener("click", () => setAutoSkip(true));
SB.enableAutoSkip.addEventListener("click", () => setAutoSkip(false));
SB.setStartSponsorKeybind.addEventListener("click", () => setKeybind(true));
SB.setSubmitKeybind.addEventListener("click", () => setKeybind(false));
SB.hideVideoPlayerControls.addEventListener("click", hideVideoPlayerControls);
SB.showVideoPlayerControls.addEventListener("click", showVideoPlayerControls);
SB.hideInfoButtonPlayerControls.addEventListener("click", hideInfoButtonPlayerControls);
SB.showInfoButtonPlayerControls.addEventListener("click", showInfoButtonPlayerControls);
SB.hideDeleteButtonPlayerControls.addEventListener("click", hideDeleteButtonPlayerControls);
SB.showDeleteButtonPlayerControls.addEventListener("click", showDeleteButtonPlayerControls);
SB.disableSponsorViewTracking.addEventListener("click", disableSponsorViewTracking);
SB.enableSponsorViewTracking.addEventListener("click", enableSponsorViewTracking);
SB.setUsernameButton.addEventListener("click", setUsernameButton);
SB.submitUsername.addEventListener("click", submitUsername);
SB.optionsButton.addEventListener("click", openOptions);
SB.reportAnIssue.addEventListener("click", reportAnIssue);
SB.hideDiscordButton.addEventListener("click", hideDiscordButton);
//if true, the button now selects the end time
let startTimeChosen = false;
@@ -131,178 +103,114 @@ function runThePopup() {
//current video ID of this tab
let currentVideoID = null;
//is this a YouTube tab?
let isYouTubeTab = false;
// Is the start sponsor keybind currently being set
let setStartSponsorKeybind = false;
//see if discord link can be shown
chrome.storage.sync.get(["hideDiscordLink"], function(result) {
let hideDiscordLink = result.hideDiscordLink;
if (hideDiscordLink == undefined || !hideDiscordLink) {
chrome.storage.sync.get(["hideDiscordLaunches"], function(result) {
let hideDiscordLaunches = result.hideDiscordLaunches;
//only if less than 10 launches
if (hideDiscordLaunches == undefined || hideDiscordLaunches < 10) {
SB.discordButtonContainer.style.display = null;
if (hideDiscordLaunches == undefined) {
hideDiscordLaunches = 1;
}
chrome.storage.sync.set({"hideDiscordLaunches": hideDiscordLaunches + 1});
let hideDiscordLink = SB.config.hideDiscordLink;
if (hideDiscordLink == undefined || !hideDiscordLink) {
let hideDiscordLaunches = SB.config.hideDiscordLaunches;
//only if less than 10 launches
if (hideDiscordLaunches == undefined || hideDiscordLaunches < 10) {
SB.discordButtonContainer.style.display = null;
if (hideDiscordLaunches == undefined) {
hideDiscordLaunches = 1;
}
});
}
});
SB.config.hideDiscordLaunches = hideDiscordLaunches + 1;
}
}
//show proper disable skipping button
chrome.storage.sync.get(["disableSkipping"], function(result) {
let disableSkipping = result.disableSkipping;
if (disableSkipping != undefined && disableSkipping) {
SB.disableSkipping.style.display = "none";
SB.enableSkipping.style.display = "unset";
}
});
let disableSkipping = SB.config.disableSkipping;
if (disableSkipping != undefined && disableSkipping) {
SB.disableSkipping.style.display = "none";
SB.enableSkipping.style.display = "unset";
}
//if the don't show notice again variable is true, an option to
// disable should be available
chrome.storage.sync.get(["dontShowNotice"], function(result) {
let dontShowNotice = result.dontShowNotice;
if (dontShowNotice != undefined && dontShowNotice) {
SB.showNoticeAgain.style.display = "unset";
}
});
let dontShowNotice = SB.config.dontShowNotice;
if (dontShowNotice != undefined && dontShowNotice) {
SB.showNoticeAgain.style.display = "unset";
}
//show proper auto skip option
chrome.storage.sync.get(["disableAutoSkip"], function(result) {
let disableAutoSkip = result.disableAutoSkip;
if (disableAutoSkip != undefined && disableAutoSkip) {
SB.disableAutoSkip.style.display = "none";
SB.enableAutoSkip.style.display = "unset";
}
});
//show proper video player controls options
chrome.storage.sync.get(["hideVideoPlayerControls"], function(result) {
let hideVideoPlayerControls = result.hideVideoPlayerControls;
if (hideVideoPlayerControls != undefined && hideVideoPlayerControls) {
SB.hideVideoPlayerControls.style.display = "none";
SB.showVideoPlayerControls.style.display = "unset";
}
});
chrome.storage.sync.get(["hideInfoButtonPlayerControls"], function(result) {
let hideInfoButtonPlayerControls = result.hideInfoButtonPlayerControls;
if (hideInfoButtonPlayerControls != undefined && hideInfoButtonPlayerControls) {
SB.hideInfoButtonPlayerControls.style.display = "none";
SB.showInfoButtonPlayerControls.style.display = "unset";
}
});
chrome.storage.sync.get(["hideDeleteButtonPlayerControls"], function(result) {
let hideDeleteButtonPlayerControls = result.hideDeleteButtonPlayerControls;
if (hideDeleteButtonPlayerControls != undefined && hideDeleteButtonPlayerControls) {
SB.hideDeleteButtonPlayerControls.style.display = "none";
SB.showDeleteButtonPlayerControls.style.display = "unset";
}
});
//show proper tracking option
chrome.storage.sync.get(["trackViewCount"], function(result) {
let trackViewCount = result.trackViewCount;
if (trackViewCount != undefined && !trackViewCount) {
SB.disableSponsorViewTracking.style.display = "none";
SB.enableSponsorViewTracking.style.display = "unset";
}
});
//get the amount of times this user has contributed and display it to thank them
chrome.storage.sync.get(["sponsorTimesContributed"], function(result) {
if (result.sponsorTimesContributed != undefined) {
if (result.sponsorTimesContributed > 1) {
SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else {
SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor");
}
SB.sponsorTimesContributionsDisplay.innerText = result.sponsorTimesContributed;
SB.sponsorTimesContributionsContainer.style.display = "unset";
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
let userID = result.userID;
if (userID != undefined) {
//there are probably some views on these submissions then
//get the amount of views from the sponsors submitted
sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let viewCount = JSON.parse(xmlhttp.responseText).viewCount;
if (viewCount != 0) {
if (viewCount > 1) {
SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments");
} else {
SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment");
}
SB.sponsorTimesViewsDisplay.innerText = viewCount;
SB.sponsorTimesViewsContainer.style.display = "unset";
}
}
});
//get this time in minutes
sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved;
if (minutesSaved != 0) {
if (minutesSaved != 1) {
SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower");
} else {
SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower");
}
SB.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved);
SB.sponsorTimesOthersTimeSavedContainer.style.display = "unset";
}
}
});
}
});
if (SB.config.sponsorTimesContributed != undefined) {
if (SB.config.sponsorTimesContributed > 1) {
SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else {
SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor");
}
});
SB.sponsorTimesContributionsDisplay.innerText = SB.config.sponsorTimesContributed;
SB.sponsorTimesContributionsContainer.style.display = "unset";
//get the userID
let userID = SB.config.userID;
if (userID != undefined) {
//there are probably some views on these submissions then
//get the amount of views from the sponsors submitted
sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let viewCount = JSON.parse(xmlhttp.responseText).viewCount;
if (viewCount != 0) {
if (viewCount > 1) {
SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments");
} else {
SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment");
}
SB.sponsorTimesViewsDisplay.innerText = viewCount;
SB.sponsorTimesViewsContainer.style.display = "unset";
}
}
});
//get this time in minutes
sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved;
if (minutesSaved != 0) {
if (minutesSaved != 1) {
SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower");
} else {
SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower");
}
SB.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved);
SB.sponsorTimesOthersTimeSavedContainer.style.display = "unset";
}
}
});
}
}
//get the amount of times this user has skipped a sponsor
chrome.storage.sync.get(["skipCount"], function(result) {
if (result.skipCount != undefined) {
if (result.skipCount != 1) {
SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else {
SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor");
}
SB.sponsorTimesSkipsDoneDisplay.innerText = result.skipCount;
SB.sponsorTimesSkipsDoneContainer.style.display = "unset";
if (SB.config.skipCount != undefined) {
if (SB.config.skipCount != 1) {
SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else {
SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor");
}
});
SB.sponsorTimesSkipsDoneDisplay.innerText = SB.config.skipCount;
SB.sponsorTimesSkipsDoneContainer.style.display = "unset";
}
//get the amount of time this user has saved.
chrome.storage.sync.get(["minutesSaved"], function(result) {
if (result.minutesSaved != undefined) {
if (result.minutesSaved != 1) {
SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower");
} else {
SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower");
}
SB.sponsorTimeSavedDisplay.innerText = getFormattedHours(result.minutesSaved);
SB.sponsorTimeSavedContainer.style.display = "unset";
if (SB.config.minutesSaved != undefined) {
if (SB.config.minutesSaved != 1) {
SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower");
} else {
SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower");
}
});
SB.sponsorTimeSavedDisplay.innerText = getFormattedHours(SB.config.minutesSaved);
SB.sponsorTimeSavedContainer.style.display = "unset";
}
chrome.tabs.query({
active: true,
currentWindow: true
}, onTabs);
function onTabs(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) {
if (result != undefined && result.videoID) {
@@ -323,25 +231,22 @@ function runThePopup() {
}
//load video times for this video
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.get([sponsorTimeKey], function(result) {
let sponsorTimesStorage = result[sponsorTimeKey];
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) {
startTimeChosen = true;
SB.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd");
}
sponsorTimes = sponsorTimesStorage;
displaySponsorTimes();
//show submission section
SB.submissionSection.style.display = "unset";
showSubmitTimesIfNecessary();
let sponsorTimesStorage = SB.config.sponsorTimes.get(currentVideoID);
if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) {
if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) {
startTimeChosen = true;
SB.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd");
}
});
sponsorTimes = sponsorTimesStorage;
displaySponsorTimes();
//show submission section
SB.submissionSection.style.display = "unset";
showSubmitTimesIfNecessary();
}
//check if this video's sponsors are known
chrome.tabs.sendMessage(
@@ -398,13 +303,6 @@ function runThePopup() {
);
}
function setVideoID(request) {
//if request is undefined, then the page currently being browsed is not YouTube
if (request != undefined) {
videoID = request.videoID;
}
}
function sendSponsorStartMessage() {
//the content script will get the message if a YouTube page is open
chrome.tabs.query({
@@ -427,10 +325,9 @@ function runThePopup() {
}
sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time;
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
let localStartTimeChosen = startTimeChosen;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
SB.config.sponsorTimes.set(currentVideoID, sponsorTimes);
//send a message to the client script
if (localStartTimeChosen) {
chrome.tabs.query({
@@ -443,7 +340,6 @@ function runThePopup() {
);
});
}
});
updateStartTimeChosen();
@@ -740,8 +636,8 @@ function runThePopup() {
tabs[0].id,
{message: "getCurrentTime"},
function (response) {
let minutes = document.getElementById(idStartName + chrome.i18n.getMessage("Mins") + index);
let seconds = document.getElementById(idStartName + chrome.i18n.getMessage("Secs") + index);
let minutes = document.getElementById(idStartName + "Minutes" + index);
let seconds = document.getElementById(idStartName + "Seconds" + index);
minutes.value = getTimeInMinutes(response.currentTime);
seconds.value = getTimeInFormattedSeconds(response.currentTime);
@@ -752,8 +648,8 @@ function runThePopup() {
//id start name is whether it is the startTime or endTime
//gives back the time in seconds
function getSponsorTimeEditTimes(idStartName, index) {
let minutes = document.getElementById(idStartName + chrome.i18n.getMessage("Mins") + index);
let seconds = document.getElementById(idStartName + chrome.i18n.getMessage("Secs") + index);
let minutes = document.getElementById(idStartName + "Minutes" + index);
let seconds = document.getElementById(idStartName + "Seconds" + index);
return parseInt(minutes.value) * 60 + parseFloat(seconds.value);
}
@@ -763,8 +659,7 @@ function runThePopup() {
sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index);
//save this
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
SB.config.sponsorTimes.set(currentVideoID, sponsorTimes);
chrome.tabs.query({
active: true,
currentWindow: true
@@ -774,7 +669,6 @@ function runThePopup() {
{message: "sponsorDataChanged"}
);
});
});
if (closeEditMode) {
displaySponsorTimes();
@@ -804,8 +698,7 @@ function runThePopup() {
sponsorTimes.splice(index, 1);
//save this
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
SB.config.sponsorTimes.set(currentVideoID, sponsorTimes);
chrome.tabs.query({
active: true,
currentWindow: true
@@ -815,7 +708,6 @@ function runThePopup() {
{message: "sponsorDataChanged"}
);
});
});
//update display
displaySponsorTimes();
@@ -856,9 +748,8 @@ function runThePopup() {
//reset sponsorTimes
sponsorTimes = [];
let sponsorTimeKey = "sponsorTimes" + currentVideoID;
chrome.storage.sync.set({[sponsorTimeKey]: sponsorTimes}, function() {
SB.config.sponsorTimes.set(currentVideoID, sponsorTimes);
chrome.tabs.query({
active: true,
currentWindow: true
@@ -868,7 +759,6 @@ function runThePopup() {
{message: "sponsorDataChanged"}
);
});
});
displaySponsorTimes();
@@ -906,171 +796,11 @@ function runThePopup() {
}
function showNoticeAgain() {
chrome.storage.sync.set({"dontShowNotice": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "showNoticeAgain"
});
});
SB.config.dontShowNotice = false;
SB.showNoticeAgain.style.display = "none";
}
function setAutoSkip(value) {
chrome.storage.sync.set({"disableAutoSkip": value});
if (value) {
// If it isn't shown, they can't manually skip
showNoticeAgain();
SB.disableAutoSkip.style.display = "none";
SB.enableAutoSkip.style.display = "unset";
} else {
SB.enableAutoSkip.style.display = "none";
SB.disableAutoSkip.style.display = "unset";
}
}
function hideVideoPlayerControls() {
chrome.storage.sync.set({"hideVideoPlayerControls": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerControlsVisibility",
value: true
});
});
SB.hideVideoPlayerControls.style.display = "none";
SB.showVideoPlayerControls.style.display = "unset";
}
function showVideoPlayerControls() {
chrome.storage.sync.set({"hideVideoPlayerControls": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerControlsVisibility",
value: false
});
});
SB.hideVideoPlayerControls.style.display = "unset";
SB.showVideoPlayerControls.style.display = "none";
}
function hideInfoButtonPlayerControls() {
chrome.storage.sync.set({"hideInfoButtonPlayerControls": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeInfoButtonPlayerControlsVisibility",
value: true
});
});
SB.hideInfoButtonPlayerControls.style.display = "none";
SB.showInfoButtonPlayerControls.style.display = "unset";
}
function showInfoButtonPlayerControls() {
chrome.storage.sync.set({"hideInfoButtonPlayerControls": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerCochangeInfoButtonPlayerControlsVisibilityntrolsVisibility",
value: false
});
});
SB.hideInfoButtonPlayerControls.style.display = "unset";
SB.showInfoButtonPlayerControls.style.display = "none";
}
function hideDeleteButtonPlayerControls() {
chrome.storage.sync.set({"hideDeleteButtonPlayerControls": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeDeleteButtonPlayerControlsVisibility",
value: true
});
});
SB.hideDeleteButtonPlayerControls.style.display = "none";
SB.showDeleteButtonPlayerControls.style.display = "unset";
}
function showDeleteButtonPlayerControls() {
chrome.storage.sync.set({"hideDeleteButtonPlayerControls": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "changeVideoPlayerCochangeDeleteButtonPlayerControlsVisibilityntrolsVisibility",
value: false
});
});
SB.hideDeleteButtonPlayerControls.style.display = "unset";
SB.showDeleteButtonPlayerControls.style.display = "none";
}
function disableSponsorViewTracking() {
chrome.storage.sync.set({"trackViewCount": false});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "trackViewCount",
value: false
});
});
SB.disableSponsorViewTracking.style.display = "none";
SB.enableSponsorViewTracking.style.display = "unset";
}
function enableSponsorViewTracking() {
chrome.storage.sync.set({"trackViewCount": true});
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
message: "trackViewCount",
value: true
});
});
SB.enableSponsorViewTracking.style.display = "none";
SB.disableSponsorViewTracking.style.display = "unset";
}
function updateStartTimeChosen() {
//update startTimeChosen letiable
if (!startTimeChosen) {
@@ -1101,16 +831,13 @@ function runThePopup() {
//make the options div visible
function openOptions() {
document.getElementById("optionsButtonContainer").style.display = "none";
document.getElementById("options").style.display = "unset";
chrome.runtime.sendMessage({"message": "openConfig"});
}
//make the options username setting option visible
function setUsernameButton() {
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
//get username from the server
sendRequestToServer("GET", "/api/getUsername?userID=" + result.userID, function (xmlhttp, error) {
sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
SB.usernameInput.value = JSON.parse(xmlhttp.responseText).userName;
@@ -1130,7 +857,6 @@ function runThePopup() {
SB.setUsernameStatus.innerText = getErrorMessage(xmlhttp.status);
}
});
});
}
//submit the new username
@@ -1140,8 +866,7 @@ function runThePopup() {
SB.setUsernameStatus.innerText = "Loading...";
//get the userID
chrome.storage.sync.get(["userID"], function(result) {
sendRequestToServer("POST", "/api/setUsername?userID=" + result.userID + "&username=" + SB.usernameInput.value, function (xmlhttp, error) {
sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + SB.usernameInput.value, function (xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//submitted
SB.submitUsername.style.display = "none";
@@ -1152,13 +877,12 @@ function runThePopup() {
SB.setUsernameStatus.innerText = getErrorMessageI(xmlhttp.status);
}
});
});
SB.setUsernameContainer.style.display = "none";
SB.setUsername.style.display = "unset";
}
//this is not a YouTube video page
function displayNoVideo() {
document.getElementById("loadingIndicator").innerText = chrome.i18n.getMessage("noVideoID");
@@ -1194,10 +918,8 @@ function runThePopup() {
type: type,
UUID: UUID
}, function(response) {
console.log(response)
if (response != undefined) {
//see if it was a success or failure
console.log(response)
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
//success (treat rate limits as a success)
addVoteMessage(chrome.i18n.getMessage("voted"), UUID)
@@ -1212,8 +934,7 @@ function runThePopup() {
}
function hideDiscordButton() {
chrome.storage.sync.set({"hideDiscordLink": true});
SB.config.hideDiscordLink = true;
SB.discordButtonContainer.style.display = "none";
}
@@ -1242,8 +963,7 @@ function runThePopup() {
{message: 'getChannelURL'},
function(response) {
//get whitelisted channels
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
let whitelistedChannels = SB.config.whitelistedChannels;
if (whitelistedChannels == undefined) {
whitelistedChannels = [];
}
@@ -1259,7 +979,7 @@ function runThePopup() {
SB.downloadedSponsorMessageTimes.style.fontWeight = "bold";
//save this
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
SB.config.whitelistedChannels = whitelistedChannels;
//send a message to the client
chrome.tabs.query({
@@ -1273,7 +993,6 @@ function runThePopup() {
});
}
);
});
}
);
});
@@ -1290,8 +1009,7 @@ function runThePopup() {
{message: 'getChannelURL'},
function(response) {
//get whitelisted channels
chrome.storage.sync.get(["whitelistedChannels"], function(result) {
let whitelistedChannels = result.whitelistedChannels;
let whitelistedChannels = SB.config.whitelistedChannels;
if (whitelistedChannels == undefined) {
whitelistedChannels = [];
}
@@ -1308,7 +1026,7 @@ function runThePopup() {
SB.downloadedSponsorMessageTimes.style.fontWeight = "unset";
//save this
chrome.storage.sync.set({whitelistedChannels: whitelistedChannels});
SB.config.whitelistedChannels = whitelistedChannels;
//send a message to the client
chrome.tabs.query({
@@ -1322,7 +1040,6 @@ function runThePopup() {
});
}
);
});
}
);
});
@@ -1332,7 +1049,7 @@ function runThePopup() {
* Should skipping be disabled (visuals stay)
*/
function toggleSkipping(disabled) {
chrome.storage.sync.set({"disableSkipping": disabled});
SB.config.disableSkipping = disabled;
let hiddenButton = SB.disableSkipping;
let shownButton = SB.enableSkipping;
@@ -1346,34 +1063,6 @@ function runThePopup() {
hiddenButton.style.display = "none";
}
function setKeybind(startSponsorKeybind) {
document.getElementById("keybindButtons").style.display = "none";
document.getElementById("keybindDescription").style.display = "initial";
document.getElementById("keybindDescription").innerText = chrome.i18n.getMessage("keybindDescription");
setStartSponsorKeybind = startSponsorKeybind;
document.addEventListener("keydown", onKeybindSet)
}
function onKeybindSet(e) {
e = e || window.event;
var key = e.key;
if (setStartSponsorKeybind) {
chrome.storage.sync.set({"startSponsorKeybind": key});
} else {
chrome.storage.sync.set({"submitKeybind": key});
}
document.removeEventListener("keydown", onKeybindSet);
document.getElementById("keybindDescription").innerText = chrome.i18n.getMessage("keybindDescriptionComplete") + " " + key;
document.getElementById("keybindButtons").style.display = "unset";
}
//converts time in seconds to minutes
function getTimeInMinutes(seconds) {
let minutes = Math.floor(seconds / 60);
@@ -1429,7 +1118,6 @@ function runThePopup() {
if (chrome.tabs != undefined) {
//add the width restriction (because Firefox)
document.getElementById("sponorBlockStyleSheet").sheet.insertRule('.popupBody { width: 325 }', 0);
//this means it is actually opened in the popup
runThePopup();
}

206
utils.js
View File

@@ -1,3 +1,6 @@
var isBackgroundScript = false;
var onInvidious = false;
// Function that can be used to wait for a condition before returning
async function wait(condition, timeout = 5000, check = 100) {
return await new Promise((resolve, reject) => {
@@ -19,21 +22,33 @@ async function wait(condition, timeout = 5000, check = 100) {
}
function getYouTubeVideoID(url) {
// For YouTube TV support
if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", "");
//Attempt to parse url
let urlObject = null;
try {
urlObject = new URL(url);
urlObject = new URL(url);
} catch (e) {
console.error("[SB] Unable to parse URL: " + url);
return false;
console.error("[SB] Unable to parse URL: " + url);
return false;
}
//Check if valid hostname
if(!["www.youtube.com","www.youtube-nocookie.com"].includes(urlObject.host)) return false;
if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) {
onInvidious = true;
} else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
if (!SB.config) {
// Call this later, in case this is an Invidious tab
wait(() => SB.config !== undefined).then(() => videoIDChange(getYouTubeVideoID(url)));
}
return false
}
//Get ID from searchParam
if ((urlObject.pathname == "/watch" || urlObject.pathname == "/watch/") && urlObject.searchParams.has("v")) {
id = urlObject.searchParams.get("v");
if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) {
id = urlObject.searchParams.get("v");
return id.length == 11 ? id : false;
} else if (urlObject.pathname.startsWith("/embed/")) {
try {
@@ -42,30 +57,172 @@ function getYouTubeVideoID(url) {
console.error("[SB] Video ID not valid for " + url);
return false;
}
}
}
return false;
}
/**
* Asks for the optional permissions required for all extra sites.
* It also starts the content script registrations.
*
* For now, it is just SB.config.invidiousInstances.
*
* @param {CallableFunction} callback
*/
function setupExtraSitePermissions(callback) {
// Request permission
let permissions = ["declarativeContent"];
if (isFirefox()) permissions = [];
chrome.permissions.request({
origins: getInvidiousInstancesRegex(),
permissions: permissions
}, async function (granted) {
if (granted) {
setupExtraSiteContentScripts();
} else {
removeExtraSiteRegistration();
}
callback(granted);
});
}
/**
* Registers the content scripts for the extra sites.
* Will use a different method depending on the browser.
* This is called by setupExtraSitePermissions().
*
* For now, it is just SB.config.invidiousInstances.
*/
function setupExtraSiteContentScripts() {
let js = [
"config.js",
"SB.js",
"utils/previewBar.js",
"utils/skipNotice.js",
"utils.js",
"content.js",
"popup.js"
];
let css = [
"content.css",
"./libs/Source+Sans+Pro.css",
"popup.css"
];
if (isFirefox()) {
let firefoxJS = [];
for (const file of js) {
firefoxJS.push({file});
}
let firefoxCSS = [];
for (const file of css) {
firefoxCSS.push({file});
}
let registration = {
message: "registerContentScript",
id: "invidious",
allFrames: true,
js: firefoxJS,
css: firefoxCSS,
matches: getInvidiousInstancesRegex()
};
if (isBackgroundScript) {
registerFirefoxContentScript(registration);
} else {
chrome.runtime.sendMessage(registration);
}
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() {
let conditions = [];
for (const regex of getInvidiousInstancesRegex()) {
conditions.push(new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlMatches: regex }
}));
}
// Add page rule
let rule = {
id: "invidious",
conditions,
actions: [new chrome.declarativeContent.RequestContentScript({
allFrames: true,
js,
css
})]
};
chrome.declarativeContent.onPageChanged.addRules([rule]);
});
}
}
/**
* Removes the permission and content script registration.
*/
function removeExtraSiteRegistration() {
if (isFirefox()) {
let id = "invidious";
if (isBackgroundScript) {
if (contentScriptRegistrations[id]) {
contentScriptRegistrations[id].unregister();
delete contentScriptRegistrations[id];
}
} else {
chrome.runtime.sendMessage({
message: "unregisterContentScript",
id: id
});
}
} else {
chrome.declarativeContent.onPageChanged.removeRules(["invidious"]);
}
chrome.permissions.remove({
origins: getInvidiousInstancesRegex()
});
}
function localizeHtmlPage() {
//Localize by replacing __MSG_***__ meta tags
var objects = document.getElementsByClassName("popupBody")[0].children;
var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children;
for (var j = 0; j < objects.length; j++) {
var obj = objects[j];
var valStrH = obj.innerHTML.toString();
var valNewH = valStrH.replace(/__MSG_(\w+)__/g, function(match, v1)
{
return v1 ? chrome.i18n.getMessage(v1) : "";
});
if(valNewH != valStrH)
{
obj.innerHTML = valNewH;
}
let localizedMessage = getLocalizedMessage(obj.innerHTML.toString());
if (localizedMessage) obj.innerHTML = localizedMessage;
}
}
function getLocalizedMessage(text) {
var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) {
return v1 ? chrome.i18n.getMessage(v1) : "";
});
if(valNewH != text) {
return valNewH;
} else {
return false;
}
}
/**
* @returns {String[]} Invidious Instances in regex form
*/
function getInvidiousInstancesRegex() {
var invidiousInstancesRegex = [];
for (const url of SB.config.invidiousInstances) {
invidiousInstancesRegex.push("https://*." + url + "/*");
invidiousInstancesRegex.push("http://*." + url + "/*");
}
return invidiousInstancesRegex;
}
function generateUserID(length = 36) {
let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let result = "";
@@ -104,4 +261,11 @@ function getErrorMessage(statusCode) {
}
return errorMessage;
}
}
/**
* Is this Firefox (web-extensions)
*/
function isFirefox() {
return typeof(browser) !== "undefined";
}

View File

@@ -166,7 +166,7 @@ class SkipNotice {
noticeElement.appendChild(secondRow);
//get reference node
let referenceNode = document.getElementById("movie_player");
let referenceNode = document.getElementById("movie_player") || document.querySelector("#player-container .video-js");
if (referenceNode == null) {
//for embeds
let player = document.getElementById("player");
@@ -425,4 +425,4 @@ class SkipNotice {
if (this.countdownInterval != -1) clearInterval(this.countdownInterval);
}
}
}