Compare commits

...

61 Commits

Author SHA1 Message Date
Ajay Ramachandran
adfba72f19 Merge pull request #286 from ajayyy/experimental
Mobile fix + mobile update notice
2020-02-23 20:40:48 -05:00
Ajay Ramachandran
f00337c376 Increase version number. 2020-02-23 20:39:29 -05:00
Ajay Ramachandran
737a023b65 Added mobile support message. 2020-02-23 20:39:13 -05:00
Ajay Ramachandran
5551344355 Fixed mobile notice zoom on Firefox 2020-02-23 16:14:18 -05:00
Ajay Ramachandran
07f64382fb Merge pull request #285 from cherryblossom000/patch-1
Fix "0 sponsor" in popup
2020-02-23 11:21:21 -05:00
Ajay Ramachandran
1c7cde2a19 Changed to !== 2020-02-23 11:20:21 -05:00
cherryblossom
8510a7f3d8 Fix popup saying "0 sponsor" 2020-02-23 17:03:18 +11:00
Ajay Ramachandran
db60b11a17 Merge pull request #284 from ajayyy/experimental
CI Improvements
2020-02-20 15:38:35 -05:00
Ajay Ramachandran
6a212b762a Fixed invalid release workflow 2020-02-20 12:21:30 -05:00
Ajay Ramachandran
c8ec2922cf Added makedir to CI 2020-02-20 12:17:51 -05:00
Ajay Ramachandran
b629b7d333 Added basic release workflow 2020-02-20 12:14:01 -05:00
Ajay Ramachandran
514a8b62d6 Added beta build to CI 2020-02-20 11:39:06 -05:00
Ajay Ramachandran
cd11618a5d Merge pull request #283 from ajayyy/experimental
New skipping mechanism fixes
2020-02-20 11:25:32 -05:00
Ajay Ramachandran
8be3cb157a Increased version number 2020-02-20 11:23:44 -05:00
Ajay Ramachandran
4ca57cc025 Fixed preview sponsors not skipping when only they are there. 2020-02-19 13:45:00 -05:00
Ajay Ramachandran
397bcc94c5 Remove redundant code 2020-02-19 13:35:05 -05:00
Ajay Ramachandran
8b28bccfd7 Run dev now uses dev build. 2020-02-19 12:57:22 -05:00
Ajay Ramachandran
c6107057d9 Firefox dev environment now loads Firefox uBlock Origin 2020-02-19 12:54:58 -05:00
Ajay Ramachandran
ab2a9530e9 Sped up zero second sponsors a tiny bit 2020-02-19 12:41:22 -05:00
Ajay Ramachandran
bfc771bd99 Removed unused variables 2020-02-19 12:37:39 -05:00
Ajay Ramachandran
e75e588755 Sped up direct links a tiny bit. 2020-02-19 12:37:17 -05:00
Ajay Ramachandran
0266bb49ca Fixed typo 2020-02-19 12:35:10 -05:00
Ajay Ramachandran
9e693fd555 Update README.md 2020-02-19 12:33:48 -05:00
Ajay Ramachandran
1f30b9ec84 Merge pull request #280 from ajayyy/mobile-youtube
Mobile YouTube support + Precise skipping
2020-02-19 11:40:07 -05:00
Ajay Ramachandran
50862e3c03 Increased version number 2020-02-19 11:25:14 -05:00
Ajay Ramachandran
20e90bbc34 Fixed schedule not updating when new sponsors arrive 2020-02-19 00:54:30 -05:00
Ajay Ramachandran
2e212e6d10 Improved mobile preview bar 2020-02-19 00:14:08 -05:00
Ajay Ramachandran
2039bfa081 Made buttons on mobile not close the menu. 2020-02-19 00:10:05 -05:00
Ajay Ramachandran
7dc8a99247 Added button support to mobile. 2020-02-19 00:00:22 -05:00
Ajay Ramachandran
1b25ea7f95 Shrunk notice on mobile 2020-02-18 19:29:20 -05:00
Ajay Ramachandran
1869382166 Fixed popup issues. 2020-02-18 19:03:34 -05:00
Ajay Ramachandran
d58cd639c7 Added zero second preview sponsors. 2020-02-18 18:45:33 -05:00
Ajay Ramachandran
6cd2d4cf83 Added back whitelist support 2020-02-18 18:44:06 -05:00
Ajay Ramachandran
b681f5abd9 Added support for preview sponsors in new skipping method. 2020-02-18 18:43:45 -05:00
Ajay Ramachandran
5b2a0feccf Switched to new skipping mechanic 2020-02-18 18:29:02 -05:00
Ajay Ramachandran
cd58f6bc73 Skip notice improvement. 2020-02-18 15:57:40 -05:00
Ajay Ramachandran
aeabf806ac Added duration change listener check to prevent mid-video zero second skips.
Sometimes the video gets reset to zero seconds for a few milliseconds, this should not trigger a skip.

Resolves https://github.com/ajayyy/SponsorBlock/issues/183
2020-02-18 15:03:55 -05:00
Ajay Ramachandran
af7ba31c2f Remove logging. 2020-02-18 14:40:40 -05:00
Ajay Ramachandran
5b962b1b9d Merge pull request #281 from ajayyy/experimental
Rename CI artifacts
2020-02-17 15:24:49 -05:00
Ajay Ramachandran
219a7ba8c3 Added preview bar to mobile 2020-02-17 15:10:50 -05:00
Ajay Ramachandran
933babb4e6 Added mobile YouTube site to the whitelist. 2020-02-17 11:32:00 -05:00
Ajay Ramachandran
023ba2e051 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock into experimental 2020-02-17 11:24:36 -05:00
Ajay Ramachandran
1c833a8b1d Rename CI artifacts. 2020-02-11 21:04:41 -05:00
Ajay Ramachandran
7143d7532d Increase version number 2020-02-11 21:01:35 -05:00
Ajay Ramachandran
1f10bdf593 Merge pull request #279 from CommanderRoot/patch-1
Retain decimals in seconds value when editing sponsor times
2020-02-11 20:33:04 -05:00
CommanderRoot
3b543916ff Retain decimals in seconds value 2020-02-12 02:24:03 +01:00
Ajay Ramachandran
c4da85340a Merge pull request #277 from ajayyy/experimental
Fixed regex to support Firefox
2020-02-11 14:10:47 -05:00
Ajay Ramachandran
ec59c7e0f9 Increase version number. 2020-02-11 14:10:11 -05:00
Ajay Ramachandran
2454cd9a39 Fixed regex to support Firefox. 2020-02-11 12:29:19 -05:00
Ajay Ramachandran
c19e2bea29 Merge pull request #274 from ajayyy/experimental
Various fixes
2020-02-10 22:35:54 -05:00
Ajay Ramachandran
2f2c1ad49b Increased version number. 2020-02-10 22:32:15 -05:00
Ajay Ramachandran
657aff2167 Removed use of Invidious API.
Resolves https://github.com/ajayyy/SponsorBlock/issues/189.
2020-02-10 22:27:54 -05:00
Ajay Ramachandran
2450457fe5 Fixed close button on dark theme.
Resolves https://github.com/ajayyy/SponsorBlock/issues/196
2020-02-10 21:54:11 -05:00
Ajay Ramachandran
ba9e42e6f0 Forced auto skip if previewing sponsor.
Resolves https://github.com/ajayyy/SponsorBlock/issues/222
2020-02-10 21:49:17 -05:00
Ajay Ramachandran
f05d80523b Made it unpause when previewing a sponsor.
Resolves https://github.com/ajayyy/SponsorBlock/issues/222
2020-02-10 21:39:39 -05:00
Ajay Ramachandran
d2779aba86 Fix editing not adding numbers.
Resolves https://github.com/ajayyy/SponsorBlock/issues/273.
2020-02-10 18:03:09 -05:00
Ajay Ramachandran
852912a42b Fixed inlines sponsor popup.
Fixes https://github.com/ajayyy/SponsorBlock/issues/272
2020-02-10 17:12:52 -05:00
Ajay Ramachandran
45e0f87f9f Reformatted manifest. 2020-02-09 11:14:40 -05:00
Ajay Ramachandran
79b02c7ae7 Merge pull request #269 from ajayyy/experimental
Fixed Firefox recursion issue
2020-02-09 10:36:20 -05:00
Ajay Ramachandran
cfb902180d Increased version number. 2020-02-09 10:35:32 -05:00
Ajay Ramachandran
1753c05686 Fix Firefox infinite recursion issue. 2020-02-09 10:34:18 -05:00
15 changed files with 490 additions and 211 deletions

View File

@@ -21,14 +21,42 @@ jobs:
run: npm run build:chrome run: npm run build:chrome
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
with: with:
name: Chrome Extension name: ChromeExtension
path: dist path: dist
- run: mkdir ./builds
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtension.zip ./dist
# Create Firefox artifacts # Create Firefox artifacts
- name: Create Firefox artifacts - name: Create Firefox artifacts
run: npm run build:firefox run: npm run build:firefox
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
with: with:
name: Firefox Extension name: FirefoxExtension
path: dist path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist
# Create Beta artifacts (Builds with the name changed to beta)
- name: Create Chrome Beta artifacts
run: npm run build:chrome -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: ChromeExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist
- name: Create Firefox Beta artifacts
run: npm run build:firefox -- --env.stream=beta
- uses: actions/upload-artifact@v1
with:
name: FirefoxExtensionBeta
path: dist
- uses: montudor/action-zip@v0.1.0
with:
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist

29
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Upload Release Build
on: release
jobs:
build:
name: Upload Release
runs-on: ubuntu-latest
steps:
# Build Artifacts
- name: Build Artifacts
uses: ./.github/workflows/ci
# Upload each release asset
- name: Upload to release
uses: JasonEtco/upload-to-release@master
with:
args: ./builds/ChromeExtension.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to release
uses: JasonEtco/upload-to-release@master
with:
args: ./builds/FirefoxExtension.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -68,9 +68,9 @@ The result is in `dist`.
# Credit # Credit
The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) is used to grab the time the video was published. The awesome [Invidious API](https://github.com/omarroth/invidious/wiki/API) previously was used.
Original code from [YTSponsorSkip](https://github.com/OfficialNoob/YTSponsorSkip), but not much of the code is left. Originally forked from [YTSponsorSkip](https://github.com/OfficialNoob/YTSponsorSkip), but zero code remains.
Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</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> Some icons made by <a href="https://www.flaticon.com/authors/gregor-cresnar" title="Gregor Cresnar">Gregor Cresnar</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>

View File

@@ -0,0 +1,4 @@
{
"name": "__MSG_betaName__"
}

View File

@@ -1,11 +1,10 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "__MSG_Name__", "short_name": "__MSG_Name__",
"version": "1.2.6", "version": "1.2.16",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"content_scripts": [ "content_scripts": [{
{
"run_at": "document_start", "run_at": "document_start",
"matches": [ "matches": [
"https://*.youtube.com/*", "https://*.youtube.com/*",
@@ -21,8 +20,7 @@
"./libs/Source+Sans+Pro.css", "./libs/Source+Sans+Pro.css",
"popup.css" "popup.css"
] ]
} }],
],
"web_accessible_resources": [ "web_accessible_resources": [
"icons/LogoSponsorBlocker256px.png", "icons/LogoSponsorBlocker256px.png",
"icons/IconSponsorBlocker256px.png", "icons/IconSponsorBlocker256px.png",
@@ -69,4 +67,4 @@
"open_in_tab": true "open_in_tab": true
}, },
"manifest_version": 2 "manifest_version": 2
} }

View File

@@ -24,16 +24,19 @@
}, },
"scripts": { "scripts": {
"web-run": "npm run web-run:chrome", "web-run": "npm run web-run:chrome",
"web-run:firefox": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm", "web-run:firefox": "cd dist && web-ext run --start-url https://addons.mozilla.org/firefox/addon/ublock-origin/",
"web-run:chrome": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm -t chromium", "web-run:chrome": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm -t chromium",
"build": "npm run build:chrome", "build": "npm run build:chrome",
"build:chrome": "webpack --env.browser=chrome --config webpack/webpack.prod.js", "build:chrome": "webpack --env.browser=chrome --config webpack/webpack.prod.js",
"build:firefox": "webpack --env.browser=firefox --config webpack/webpack.prod.js", "build:firefox": "webpack --env.browser=firefox --config webpack/webpack.prod.js",
"build:dev": "npm run build:dev:chrome",
"build:dev:chrome": "webpack --env.browser=chrome --config webpack/webpack.dev.js",
"build:dev:firefox": "webpack --env.browser=firefox --config webpack/webpack.dev.js",
"build:watch": "npm run build:watch:chrome", "build:watch": "npm run build:watch:chrome",
"build:watch:chrome": "webpack --env.browser=chrome --config webpack/webpack.dev.js --watch", "build:watch:chrome": "webpack --env.browser=chrome --config webpack/webpack.dev.js --watch",
"build:watch:firefox": "webpack --env.browser=firefox --config webpack/webpack.dev.js --watch", "build:watch:firefox": "webpack --env.browser=firefox --config webpack/webpack.dev.js --watch",
"dev": "npm run build && concurrently \"npm run web-run\" \"npm run build:watch\"", "dev": "npm run build:dev && concurrently \"npm run web-run\" \"npm run build:watch\"",
"dev:firefox": "npm run build:firefox && concurrently \"npm run web-run:firefox\" \"npm run build:watch:firefox\"", "dev:firefox": "npm run build:dev:firefox && concurrently \"npm run web-run:firefox\" \"npm run build:watch:firefox\"",
"clean": "rimraf dist", "clean": "rimraf dist",
"test": "npx jest" "test": "npx jest"
}, },

View File

@@ -381,12 +381,6 @@
"whatAutoUpvote": { "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." "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."
},
"minDuration": { "minDuration": {
"message": "Minimum duration (seconds):" "message": "Minimum duration (seconds):"
}, },
@@ -428,5 +422,11 @@
}, },
"whatUnlistedCheck": { "whatUnlistedCheck": {
"message": "This setting will significantly slow down SponsorBlock. Sponsor lookups require sending the video ID to the server. If you are concerned about unlisted video IDs being sent over the internet, enable this option." "message": "This setting will significantly slow down SponsorBlock. Sponsor lookups require sending the video ID to the server. If you are concerned about unlisted video IDs being sent over the internet, enable this option."
},
"betaName": {
"message": "BETA - SponsorBlock"
},
"mobileUpdateInfo": {
"message": "m.youtube.com is now supported"
} }
} }

View File

@@ -86,9 +86,9 @@ chrome.runtime.onInstalled.addListener(function (object) {
//save this UUID //save this UUID
Config.config.userID = newUserID; Config.config.userID = newUserID;
//TODO: Remove when invidious support is old //TODO: Remove when mobile support is old
// Don't show this to new users // Don't show this to new users
Config.config.invidiousUpdateInfoShowCount = 6; // Config.config.mobileUpdateShowCount = 1;
} }
}, 1500); }, 1500);
}); });

View File

@@ -20,12 +20,12 @@ interface SBConfig {
hideDiscordLaunches: number, hideDiscordLaunches: number,
hideDiscordLink: boolean, hideDiscordLink: boolean,
invidiousInstances: string[], invidiousInstances: string[],
invidiousUpdateInfoShowCount: number,
autoUpvote: boolean, autoUpvote: boolean,
supportInvidious: boolean, supportInvidious: boolean,
serverAddress: string, serverAddress: string,
minDuration: number, minDuration: number,
checkForUnlistedVideos: boolean checkForUnlistedVideos: boolean,
mobileUpdateShowCount: number
} }
interface SBObject { interface SBObject {
@@ -48,7 +48,7 @@ class SBMap<T, U> extends Map {
// Import all entries if they were given // Import all entries if they were given
if (entries !== undefined) { if (entries !== undefined) {
for (const item of entries) { for (const item of entries) {
this.set(item[0], item[1]) super.set(item[0], item[1])
} }
} }
} }
@@ -116,12 +116,12 @@ var Config: SBObject = {
hideDiscordLaunches: 0, hideDiscordLaunches: 0,
hideDiscordLink: false, hideDiscordLink: false,
invidiousInstances: ["invidio.us", "invidiou.sh", "invidious.snopyta.org"], invidiousInstances: ["invidio.us", "invidiou.sh", "invidious.snopyta.org"],
invidiousUpdateInfoShowCount: 0,
autoUpvote: true, autoUpvote: true,
supportInvidious: false, supportInvidious: false,
serverAddress: CompileConfig.serverAddress, serverAddress: CompileConfig.serverAddress,
minDuration: 0, minDuration: 0,
checkForUnlistedVideos: false checkForUnlistedVideos: false,
mobileUpdateShowCount: 0
}, },
localConfig: null, localConfig: null,
config: null config: null

View File

@@ -15,11 +15,17 @@ utils.wait(() => Config.config !== null, 5000, 10).then(addCSS);
var sponsorDataFound = false; var sponsorDataFound = false;
var previousVideoID = null; var previousVideoID = null;
//the actual sponsorTimes if loaded and UUIDs associated with them //the actual sponsorTimes if loaded and UUIDs associated with them
var sponsorTimes = null; var sponsorTimes: number[][] = null;
var UUIDs = []; var UUIDs = [];
//what video id are these sponsors for //what video id are these sponsors for
var sponsorVideoID = null; var sponsorVideoID = null;
// Skips are scheduled to ensure precision.
// Skips are rescheduled every seeked event.
// Skips are canceled every seeking event
var currentSkipSchedule: NodeJS.Timeout = null;
var seekListenerSetUp = false
//these are sponsors that have been downvoted //these are sponsors that have been downvoted
var hiddenSponsorTimes = []; var hiddenSponsorTimes = [];
@@ -27,9 +33,10 @@ var hiddenSponsorTimes = [];
var sponsorSkipped = []; var sponsorSkipped = [];
//the video //the video
var v; var video: HTMLVideoElement;
var onInvidious; var onInvidious;
var onMobileYouTube;
//the video id of the last preview bar update //the video id of the last preview bar update
var lastPreviewBarUpdate; var lastPreviewBarUpdate;
@@ -47,16 +54,17 @@ var title;
var channelWhitelisted = false; var channelWhitelisted = false;
// create preview bar // create preview bar
var previewBar = null; var previewBar: PreviewBar = null;
// When not null, a sponsor is currently being previewed and auto skip should be enabled.
// This is set to a timeout function when that happens that will reset it after 3 seconds.
var previewResetter: NodeJS.Timeout = null;
//the player controls on the YouTube player //the player controls on the YouTube player
var controls = null; var controls = null;
// Direct Links after the config is loaded // Direct Links after the config is loaded
utils.wait(() => Config.config !== null).then(() => videoIDChange(getYouTubeVideoID(document.URL))); utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYouTubeVideoID(document.URL)));
//the last time looked at (used to see if this time is in the interval)
var lastTime = -1;
//the amount of times the sponsor lookup has retried //the amount of times the sponsor lookup has retried
//this only happens if there is an error //this only happens if there is an error
@@ -85,10 +93,11 @@ var skipNoticeContentContainer = () => ({
unskipSponsorTime, unskipSponsorTime,
sponsorTimes, sponsorTimes,
UUIDs, UUIDs,
v, v: video,
reskipSponsorTime, reskipSponsorTime,
hiddenSponsorTimes, hiddenSponsorTimes,
updatePreviewBar updatePreviewBar,
onMobileYouTube
}); });
//get messages from the background script and the popup //get messages from the background script and the popup
@@ -132,16 +141,29 @@ function messageListener(request: any, sender: any, sendResponse: (response: any
break; break;
case "getVideoDuration": case "getVideoDuration":
sendResponse({ sendResponse({
duration: v.duration duration: video.duration
}); });
break; break;
case "skipToTime": case "skipToTime":
v.currentTime = request.time; video.currentTime = request.time;
// Unpause the video if needed
if (video.paused){
video.play();
}
// Start preview resetter
if (previewResetter !== null){
clearTimeout(previewResetter);
}
previewResetter = setTimeout(() => previewResetter = null, 4000);
return return
case "getCurrentTime": case "getCurrentTime":
sendResponse({ sendResponse({
currentTime: v.currentTime currentTime: video.currentTime
}); });
break; break;
@@ -213,9 +235,6 @@ document.onkeydown = function(e: KeyboardEvent){
} }
function resetValues() { function resetValues() {
//reset last sponsor times
lastTime = -1;
//reset sponsor times //reset sponsor times
sponsorTimes = null; sponsorTimes = null;
UUIDs = []; UUIDs = [];
@@ -238,7 +257,7 @@ async function videoIDChange(id) {
sponsorVideoID = id; sponsorVideoID = id;
resetValues(); resetValues();
//id is not valid //id is not valid
if (!id) return; if (!id) return;
@@ -261,26 +280,19 @@ async function videoIDChange(id) {
channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true); channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true);
//setup the preview bar //setup the preview bar
if (previewBar == null) { if (previewBar === null) {
//create it if (onMobileYouTube) {
utils.wait(getControls).then(result => { // Mobile YouTube workaround
const progressElementSelectors = [ const observer = new MutationObserver(handleMobileControlsMutations);
// For YouTube
"ytp-progress-bar-container",
"no-model cue-range-markers",
// For Invidious/VideoJS
"vjs-progress-holder"
];
for (const selector of progressElementSelectors) { observer.observe(document.getElementById("player-control-container"), {
const el = document.getElementsByClassName(selector); attributes: true,
childList: true,
if (el && el.length && el[0]) { subtree: true
previewBar = new PreviewBar(el[0]); });
break; } else {
} utils.wait(getControls).then(createPreviewBar);
} }
});
} }
//warn them if they had unsubmitted times //warn them if they had unsubmitted times
@@ -337,18 +349,129 @@ async function videoIDChange(id) {
} }
} }
}); });
}); });
//see if video controls buttons should be added //see if video controls buttons should be added
if (!onInvidious) { if (!onInvidious) {
updateVisibilityOfPlayerControlsButton(); updateVisibilityOfPlayerControlsButton();
} }
} }
function sponsorsLookup(id: string, channelIDPromise?) { function handleMobileControlsMutations(): void {
let mobileYouTubeSelector = ".progress-bar-background";
updateVisibilityOfPlayerControlsButton().then((createdButtons) => {
if (createdButtons) {
if (sponsorTimesSubmitting != null && sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].length >= 2) {
changeStartSponsorButton(true, true);
} else if (sponsorTimesSubmitting != null && sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].length < 2) {
changeStartSponsorButton(false, true);
} else {
changeStartSponsorButton(true, false);
}
}
});
if (previewBar !== null) {
if (document.body.contains(previewBar.container)) {
updatePreviewBarPositionMobile(document.getElementsByClassName(mobileYouTubeSelector)[0]);
v = document.querySelector('video') // Youtube video player return;
} else {
// The container does not exist anymore, remove that old preview bar
previewBar.remove();
previewBar = null;
}
}
// Create the preview bar if needed (the function hasn't returned yet)
createPreviewBar();
}
/**
* Creates a preview bar on the video
*/
function createPreviewBar(): void {
if (previewBar !== null) return;
const progressElementSelectors = [
// For mobile YouTube
".progress-bar-background",
// 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.querySelectorAll(selector);
if (el && el.length && el[0]) {
previewBar = new PreviewBar(el[0], onMobileYouTube);
updatePreviewBar();
break;
}
}
}
/**
* Triggered every time the video duration changes.
* This happens when the resolution changes or at random time to clear memory.
*/
function durationChangeListener() {
updatePreviewBar();
}
function cancelSponsorSchedule(): void {
if (currentSkipSchedule !== null) {
clearTimeout(currentSkipSchedule);
currentSkipSchedule = null;
}
}
/**
*
* @param currentTime Optional if you don't want to use the actual current time
*/
function startSponsorSchedule(currentTime?: number): void {
cancelSponsorSchedule();
if (Config.config.disableSkipping || channelWhitelisted){
return;
}
if (currentTime === undefined) currentTime = video.currentTime;
let skipInfo = getNextSkipIndex(currentTime);
if (skipInfo.index === -1) return;
let skipTime = skipInfo.array[skipInfo.index];
let timeUntilSponsor = skipTime[0] - currentTime;
let skippingFunction = () => {
if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) {
skipToTime(video, skipInfo.index, skipInfo.array, skipInfo.openNotice);
}
startSponsorSchedule();
};
if (timeUntilSponsor <= 0) {
skippingFunction();
} else {
currentSkipSchedule = setTimeout(skippingFunction, timeUntilSponsor * 1000 * (1 / video.playbackRate));
}
}
function sponsorsLookup(id: string, channelIDPromise?) {
video = document.querySelector('video') // Youtube video player
//there is no video here //there is no video here
if (v == null) { if (video == null) {
setTimeout(() => sponsorsLookup(id, channelIDPromise), 100); setTimeout(() => sponsorsLookup(id, channelIDPromise), 100);
return; return;
} }
@@ -357,7 +480,19 @@ function sponsorsLookup(id: string, channelIDPromise?) {
durationListenerSetUp = true; durationListenerSetUp = true;
//wait until it is loaded //wait until it is loaded
v.addEventListener('durationchange', updatePreviewBar); video.addEventListener('durationchange', durationChangeListener);
}
if (!seekListenerSetUp && !Config.config.disableSkipping) {
seekListenerSetUp = true;
video.addEventListener('seeked', () => startSponsorSchedule());
video.addEventListener('play', () => startSponsorSchedule());
video.addEventListener('ratechange', () => startSponsorSchedule());
video.addEventListener('seeking', cancelSponsorSchedule);
video.addEventListener('pause', cancelSponsorSchedule);
startSponsorSchedule();
} }
if (channelIDPromise !== undefined) { if (channelIDPromise !== undefined) {
@@ -410,12 +545,35 @@ function sponsorsLookup(id: string, channelIDPromise?) {
UUIDs = smallUUIDs; UUIDs = smallUUIDs;
} }
// See if there are any zero second sponsors
let zeroSecondSponsor = false;
for (const time of sponsorTimes) {
if (time[0] <= 0) {
zeroSecondSponsor = true;
break;
}
}
if (!zeroSecondSponsor) {
for (const time of sponsorTimesSubmitting) {
if (time[0] <= 0) {
zeroSecondSponsor = true;
break;
}
}
}
if (zeroSecondSponsor) {
startSponsorSchedule(0);
} else {
startSponsorSchedule();
}
// Reset skip save // Reset skip save
sponsorSkipped = []; sponsorSkipped = [];
//update the preview bar //update the preview bar
//leave the type blank for now until categories are added //leave the type blank for now until categories are added
if (lastPreviewBarUpdate == id || (lastPreviewBarUpdate == null && !isNaN(v.duration))) { if (lastPreviewBarUpdate == id || (lastPreviewBarUpdate == null && !isNaN(video.duration))) {
//set it now //set it now
//otherwise the listener can handle it //otherwise the listener can handle it
updatePreviewBar(); updatePreviewBar();
@@ -427,12 +585,19 @@ function sponsorsLookup(id: string, channelIDPromise?) {
//check if this video was uploaded recently //check if this video was uploaded recently
//use the invidious api to get the time published //use the invidious api to get the time published
sendRequestToCustomServer('GET', "https://invidio.us/api/v1/videos/" + id + '?fields=published', function(xmlhttp, error) { sendRequestToCustomServer('GET', "https://www.youtube.com/get_video_info?video_id=" + id, function(xmlhttp, error) {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
let unixTimePublished = JSON.parse(xmlhttp.responseText).published; let decodedData = decodeURIComponent(xmlhttp.responseText).match(/player_response=([^&]*)/)[1];
if (decodedData === undefined) {
console.error("[SB] Failed at getting video upload date info from YouTube.");
return;
}
let dateUploaded = JSON.parse(decodedData).microformat.playerMicroformatRenderer.uploadDate;
//if less than 3 days old //if less than 3 days old
if ((Date.now() / 1000) - unixTimePublished < 259200) { if (Date.now() - new Date(dateUploaded).getTime() < 259200000) {
//TODO lower when server becomes better //TODO lower when server becomes better
setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000); setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000);
} }
@@ -450,13 +615,6 @@ function sponsorsLookup(id: string, channelIDPromise?) {
sponsorLookupRetries++; sponsorLookupRetries++;
} }
}); });
//add the event to run on the videos "ontimeupdate"
if (!Config.config.disableSkipping) {
v.ontimeupdate = function () {
sponsorCheck();
};
}
} }
function getYouTubeVideoID(url: string) { function getYouTubeVideoID(url: string) {
@@ -475,7 +633,9 @@ function getYouTubeVideoID(url: string) {
// Check if valid hostname // Check if valid hostname
if (Config.config && Config.config.invidiousInstances.includes(urlObject.host)) { if (Config.config && Config.config.invidiousInstances.includes(urlObject.host)) {
onInvidious = true; onInvidious = true;
} else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { } else if (urlObject.host === "m.youtube.com") {
onMobileYouTube = true;
} else if (!["m.youtube.com", "www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) {
if (!Config.config) { if (!Config.config) {
// Call this later, in case this is an Invidious tab // Call this later, in case this is an Invidious tab
utils.wait(() => Config.config !== null).then(() => videoIDChange(getYouTubeVideoID(url))); utils.wait(() => Config.config !== null).then(() => videoIDChange(getYouTubeVideoID(url)));
@@ -548,6 +708,15 @@ function getChannelID() {
channelWhitelisted = false; channelWhitelisted = false;
} }
/**
* This function is required on mobile YouTube and will keep getting called whenever the preview bar disapears
*/
function updatePreviewBarPositionMobile(parent: Element) {
if (document.getElementById("previewbar") === null) {
previewBar.updatePosition(parent);
}
}
function updatePreviewBar() { function updatePreviewBar() {
let localSponsorTimes = sponsorTimes; let localSponsorTimes = sponsorTimes;
if (localSponsorTimes == null) localSponsorTimes = []; if (localSponsorTimes == null) localSponsorTimes = [];
@@ -568,7 +737,7 @@ function updatePreviewBar() {
types.push("previewSponsor"); types.push("previewSponsor");
} }
utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, video.duration));
//update last video id //update last video id
lastPreviewBarUpdate = sponsorVideoID; lastPreviewBarUpdate = sponsorVideoID;
@@ -584,75 +753,61 @@ function whitelistCheck() {
} }
} }
//video skipping /**
function sponsorCheck() { * Returns info about the next upcoming sponsor skip
if (Config.config.disableSkipping) { */
// Make sure this isn't called again function getNextSkipIndex(currentTime: number): {array: number[][], index: number, openNotice: boolean} {
v.ontimeupdate = null; let sponsorStartTimes = getStartTimes(sponsorTimes);
return; let sponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimes, currentTime, true);
} else if (channelWhitelisted) {
return;
}
let skipHappened = false; let minSponsorTimeIndex = sponsorStartTimes.indexOf(Math.min(...sponsorStartTimesAfterCurrentTime));
if (sponsorTimes != null) { let previewSponsorStartTimes = getStartTimes(sponsorTimesSubmitting);
//see if any sponsor start time was just passed let previewSponsorStartTimesAfterCurrentTime = getStartTimes(sponsorTimesSubmitting, currentTime, false);
for (let i = 0; i < sponsorTimes.length; i++) {
//if something was skipped
if (checkSponsorTime(sponsorTimes, i, true)) {
skipHappened = true;
break;
}
}
}
if (!skipHappened) { let minPreviewSponsorTimeIndex = previewSponsorStartTimes.indexOf(Math.min(...previewSponsorStartTimesAfterCurrentTime));
//check for the "preview" sponsors (currently edited by this user)
for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
//must be a finished sponsor and be valid
if (sponsorTimesSubmitting[i].length > 1 && sponsorTimesSubmitting[i][1] > sponsorTimesSubmitting[i][0]) {
checkSponsorTime(sponsorTimesSubmitting, i, false);
}
}
}
//don't keep track until they are loaded in if ((minPreviewSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) ||
if (sponsorTimes !== null || sponsorTimesSubmitting.length > 0) { sponsorStartTimes[minSponsorTimeIndex] < previewSponsorStartTimes[minPreviewSponsorTimeIndex]) {
lastTime = v.currentTime; return {
array: sponsorTimes,
index: minSponsorTimeIndex,
openNotice: true
};
} else {
return {
array: sponsorTimesSubmitting,
index: minPreviewSponsorTimeIndex,
openNotice: false
};
} }
} }
function checkSponsorTime(sponsorTimes, index, openNotice): boolean { /**
//this means part of the video was just skipped * Gets just the start times from a sponsor times array.
if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) { * Optionally specify a minimum
//make lastTime as if the video was playing normally *
lastTime = v.currentTime - 0.0001; * @param sponsorTimes
* @param minimum
* @param hideHiddenSponsors
*/
function getStartTimes(sponsorTimes: number[][], minimum?: number, hideHiddenSponsors: boolean = false): number[] {
if (sponsorTimes === null) return [];
let startTimes: number[] = [];
for (let i = 0; i < sponsorTimes.length; i++) {
if ((minimum === undefined || sponsorTimes[i][0] >= minimum) && (!hideHiddenSponsors || !hiddenSponsorTimes.includes(i))) {
startTimes.push(sponsorTimes[i][0]);
}
} }
if (checkIfTimeToSkip(v.currentTime, sponsorTimes[index][0], sponsorTimes[index][1]) && !hiddenSponsorTimes.includes(index)) { return startTimes;
//skip it
skipToTime(v, index, sponsorTimes, openNotice);
//something was skipped
return true;
}
return false;
} }
function checkIfTimeToSkip(currentVideoTime, startTime, endTime) { //skip from the start time to the end time for a certain index sponsor time
//If the sponsor time is in between these times, skip it
//Checks if the last time skipped to is not too close to now, to make sure not to get too many
// sponsor times in a row (from one troll)
//the last term makes 0 second start times possible only if the video is not setup to start at a different time from zero
return (Math.abs(currentVideoTime - startTime) < 3 && startTime >= lastTime && startTime <= currentVideoTime) ||
(lastTime == -1 && startTime == 0 && currentVideoTime < endTime)
}
//skip fromt he start time to the end time for a certain index sponsor time
function skipToTime(v, index, sponsorTimes, openNotice) { function skipToTime(v, index, sponsorTimes, openNotice) {
if (!Config.config.disableAutoSkip) { if (!Config.config.disableAutoSkip || previewResetter !== null) {
v.currentTime = sponsorTimes[index][1]; v.currentTime = sponsorTimes[index][1];
} }
@@ -664,8 +819,16 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
if (openNotice) { if (openNotice) {
//send out the message saying that a sponsor message was skipped //send out the message saying that a sponsor message was skipped
if (!Config.config.dontShowNotice) { if (!Config.config.dontShowNotice) {
let skipNotice = new SkipNotice(this, currentUUID, Config.config.disableAutoSkip, skipNoticeContentContainer); let skipNotice = new SkipNotice(this, currentUUID, Config.config.disableAutoSkip, skipNoticeContentContainer);
//TODO: Remove this when Mobile support is old
if (Config.config.mobileUpdateShowCount < 1) {
skipNotice.addNoticeInfoMessage(chrome.i18n.getMessage("mobileUpdateInfo"));
Config.config.mobileUpdateShowCount += 1;
}
//auto-upvote this sponsor //auto-upvote this sponsor
if (Config.config.trackViewCount && !Config.config.disableAutoSkip && Config.config.autoUpvote) { if (Config.config.trackViewCount && !Config.config.disableAutoSkip && Config.config.autoUpvote) {
vote(1, currentUUID, null); vote(1, currentUUID, null);
@@ -690,27 +853,38 @@ function skipToTime(v, index, sponsorTimes, openNotice) {
function unskipSponsorTime(UUID) { function unskipSponsorTime(UUID) {
if (sponsorTimes != null) { if (sponsorTimes != null) {
//add a tiny bit of time to make sure it is not skipped again //add a tiny bit of time to make sure it is not skipped again
v.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][0] + 0.001; video.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][0] + 0.001;
} }
} }
function reskipSponsorTime(UUID) { function reskipSponsorTime(UUID) {
if (sponsorTimes != null) { if (sponsorTimes != null) {
//add a tiny bit of time to make sure it is not skipped again //add a tiny bit of time to make sure it is not skipped again
v.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][1]; video.currentTime = sponsorTimes[UUIDs.indexOf(UUID)][1];
} }
} }
function createButton(baseID, title, callback, imageName, isDraggable=false) { function createButton(baseID, title, callback, imageName, isDraggable=false): boolean {
if (document.getElementById(baseID + "Button") != null) return; if (document.getElementById(baseID + "Button") != null) return false;
// Button HTML // Button HTML
let newButton = document.createElement("button"); let newButton = document.createElement("button");
newButton.draggable = isDraggable; newButton.draggable = isDraggable;
newButton.id = baseID + "Button"; newButton.id = baseID + "Button";
newButton.className = "ytp-button playerButton"; newButton.classList.add("playerButton");
if (!onMobileYouTube) {
newButton.classList.add("ytp-button");
} else {
newButton.classList.add("icon-button");
newButton.style.padding = "0";
}
newButton.setAttribute("title", chrome.i18n.getMessage(title)); newButton.setAttribute("title", chrome.i18n.getMessage(title));
newButton.addEventListener("click", callback); newButton.addEventListener("click", (event: Event) => {
callback();
// Prevents the contols from closing when clicked
if (onMobileYouTube) event.stopPropagation();
});
// Image HTML // Image HTML
let newButtonImage = document.createElement("img"); let newButtonImage = document.createElement("img");
@@ -724,40 +898,56 @@ function createButton(baseID, title, callback, imageName, isDraggable=false) {
// Add the button to player // Add the button to player
controls.prepend(newButton); controls.prepend(newButton);
return true;
} }
function getControls() { function getControls(): HTMLElement | boolean {
let controls = document.getElementsByClassName("ytp-right-controls"); let controlsSelectors = [
// YouTube
".ytp-right-controls",
// Mobile YouTube
".player-controls-top",
// Invidious/videojs video element's controls element
".vjs-control-bar"
]
if (!controls || controls.length === 0) { for (const controlsSelector of controlsSelectors) {
// The invidious video element's controls element let controls = document.querySelectorAll(controlsSelector);
controls = document.getElementsByClassName("vjs-control-bar");
return (!controls || controls.length === 0) ? false : controls[controls.length - 1]; if (controls && controls.length > 0) {
} else { return <HTMLElement> controls[controls.length - 1];
return controls[controls.length - 1]; }
} }
return false;
}; };
//adds all the player controls buttons //adds all the player controls buttons
async function createButtons() { async function createButtons(): Promise<boolean> {
let result = await utils.wait(getControls).catch(); let result = await utils.wait(getControls).catch();
//set global controls variable //set global controls variable
controls = result; controls = result;
// Add button if does not already exist in html let createdButton = false;
createButton("startSponsor", "sponsorStart", startSponsorClicked, "PlayerStartIconSponsorBlocker256px.png");
createButton("info", "openPopup", openInfoMenu, "PlayerInfoIconSponsorBlocker256px.png") // Add button if does not already exist in html
createButton("delete", "clearTimes", clearSponsorTimes, "PlayerDeleteIconSponsorBlocker256px.png"); createdButton = createButton("startSponsor", "sponsorStart", startSponsorClicked, "PlayerStartIconSponsorBlocker256px.png") || createdButton;
createButton("submit", "SubmitTimes", submitSponsorTimes, "PlayerUploadIconSponsorBlocker256px.png"); createdButton = createButton("info", "openPopup", openInfoMenu, "PlayerInfoIconSponsorBlocker256px.png") || createdButton;
} createdButton = createButton("delete", "clearTimes", clearSponsorTimes, "PlayerDeleteIconSponsorBlocker256px.png") || createdButton;
//adds or removes the player controls button to what it should be createdButton = createButton("submit", "SubmitTimes", submitSponsorTimes, "PlayerUploadIconSponsorBlocker256px.png") || createdButton;
async function updateVisibilityOfPlayerControlsButton() {
//not on a proper video yet return createdButton;
if (!sponsorVideoID) return; }
//adds or removes the player controls button to what it should be
async function updateVisibilityOfPlayerControlsButton(): Promise<boolean> {
//not on a proper video yet
if (!sponsorVideoID) return false;
let createdButtons = await createButtons();
await createButtons();
if (Config.config.hideVideoPlayerControls || onInvidious) { if (Config.config.hideVideoPlayerControls || onInvidious) {
document.getElementById("startSponsorButton").style.display = "none"; document.getElementById("startSponsorButton").style.display = "none";
document.getElementById("submitButton").style.display = "none"; document.getElementById("submitButton").style.display = "none";
@@ -775,6 +965,8 @@ async function updateVisibilityOfPlayerControlsButton() {
if (Config.config.hideDeleteButtonPlayerControls || onInvidious) { if (Config.config.hideDeleteButtonPlayerControls || onInvidious) {
document.getElementById("deleteButton").style.display = "none"; document.getElementById("deleteButton").style.display = "none";
} }
return createdButtons;
} }
function startSponsorClicked() { function startSponsorClicked() {
@@ -786,7 +978,7 @@ function startSponsorClicked() {
//send back current time with message //send back current time with message
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
message: "addSponsorTime", message: "addSponsorTime",
time: v.currentTime, time: video.currentTime,
videoID: sponsorVideoID videoID: sponsorVideoID
}, function(response) { }, function(response) {
//see if the sponsorTimesSubmitting needs to be updated //see if the sponsorTimesSubmitting needs to be updated
@@ -807,22 +999,17 @@ function updateSponsorTimesSubmitting() {
sponsorTimesSubmitting = sponsorTimes; sponsorTimesSubmitting = sponsorTimes;
updatePreviewBar(); updatePreviewBar();
// Restart skipping schedule
startSponsorSchedule();
} }
} }
}); });
} }
//is the submit button on the player loaded yet
function isSubmitButtonLoaded() {
return document.getElementById("submitButton") !== null;
}
async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) {
if(!sponsorVideoID) return false; if(!sponsorVideoID) return false;
//make sure submit button is loaded
await utils.wait(isSubmitButtonLoaded);
//if it isn't visible, there is no data //if it isn't visible, there is no data
let shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none" let shouldHide = (uploadButtonVisible && !(Config.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none"
document.getElementById("deleteButton").style.display = shouldHide; document.getElementById("deleteButton").style.display = shouldHide;
@@ -875,6 +1062,8 @@ function openInfoMenu() {
closeButton.classList.add("smallLink"); closeButton.classList.add("smallLink");
closeButton.setAttribute("align", "center"); closeButton.setAttribute("align", "center");
closeButton.addEventListener("click", closeInfoMenu); closeButton.addEventListener("click", closeInfoMenu);
// Theme based color
closeButton.style.color = "var(--yt-spec-text-primary)";
//add the close button //add the close button
popup.prepend(closeButton); popup.prepend(closeButton);
@@ -1012,11 +1201,11 @@ function dontShowNoticeAgain() {
} }
function sponsorMessageStarted(callback) { function sponsorMessageStarted(callback) {
v = document.querySelector('video'); video = document.querySelector('video');
//send back current time //send back current time
callback({ callback({
time: v.currentTime time: video.currentTime
}) })
//update button //update button
@@ -1039,8 +1228,8 @@ function submitSponsorTimes() {
if (sponsorTimes != undefined && sponsorTimes.length > 0) { if (sponsorTimes != undefined && sponsorTimes.length > 0) {
//check if a sponsor exceeds the duration of the video //check if a sponsor exceeds the duration of the video
for (let i = 0; i < sponsorTimes.length; i++) { for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i][1] > v.duration) { if (sponsorTimes[i][1] > video.duration) {
sponsorTimes[i][1] = v.duration; sponsorTimes[i][1] = video.duration;
} }
} }
//update sponsorTimes //update sponsorTimes

View File

@@ -23,18 +23,30 @@ let barTypes = {
class PreviewBar { class PreviewBar {
container: HTMLUListElement; container: HTMLUListElement;
parent: any; parent: any;
onMobileYouTube: boolean;
constructor(parent) { constructor(parent, onMobileYouTube) {
this.container = document.createElement('ul'); this.container = document.createElement('ul');
this.container.id = 'previewbar'; this.container.id = 'previewbar';
this.parent = parent; this.parent = parent;
this.updatePosition(); this.onMobileYouTube = onMobileYouTube;
this.updatePosition(parent);
} }
updatePosition() { updatePosition(parent) {
//below the seek bar //below the seek bar
// this.parent.insertAdjacentElement("afterEnd", this.container); // this.parent.insertAdjacentElement("afterEnd", this.container);
this.parent = parent;
if (this.onMobileYouTube) {
parent.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
parent.style.opacity = "1";
this.container.style.transform = "none";
}
//on the seek bar //on the seek bar
this.parent.insertAdjacentElement("afterBegin", this.container); this.parent.insertAdjacentElement("afterBegin", this.container);
@@ -70,7 +82,7 @@ class PreviewBar {
bar.setAttribute('data-vs-segment-type', types[i]); bar.setAttribute('data-vs-segment-type', types[i]);
bar.style.backgroundColor = barTypes[types[i]].color; bar.style.backgroundColor = barTypes[types[i]].color;
bar.style.opacity = barTypes[types[i]].opacity; if (!this.onMobileYouTube) bar.style.opacity = barTypes[types[i]].opacity;
bar.style.width = width + '%'; bar.style.width = width + '%';
bar.style.left = (timestamps[i][0] / duration * 100) + "%"; bar.style.left = (timestamps[i][0] / duration * 100) + "%";
bar.style.position = "absolute" bar.style.position = "absolute"

View File

@@ -56,6 +56,10 @@ class SkipNotice {
noticeElement.classList.add("sponsorSkipObject"); noticeElement.classList.add("sponsorSkipObject");
noticeElement.classList.add("sponsorSkipNotice"); noticeElement.classList.add("sponsorSkipNotice");
noticeElement.style.zIndex = String(50 + amountOfPreviousNotices); noticeElement.style.zIndex = String(50 + amountOfPreviousNotices);
if (contentContainer().onMobileYouTube) {
noticeElement.style.bottom = "4em";
noticeElement.style.transform = "scale(0.8) translate(10%, 10%)";
}
//add mouse enter and leave listeners //add mouse enter and leave listeners
noticeElement.addEventListener("mouseenter", this.pauseCountdown.bind(this)); noticeElement.addEventListener("mouseenter", this.pauseCountdown.bind(this));
@@ -173,7 +177,8 @@ class SkipNotice {
noticeElement.appendChild(secondRow); noticeElement.appendChild(secondRow);
//get reference node //get reference node
let referenceNode = document.getElementById("movie_player") || document.querySelector("#player-container .video-js"); let referenceNode = document.getElementById("player-container-id")
|| document.getElementById("movie_player") || document.querySelector("#player-container .video-js");
if (referenceNode == null) { if (referenceNode == null) {
//for embeds //for embeds
let player = document.getElementById("player"); let player = document.getElementById("player");

View File

@@ -38,7 +38,7 @@ class MessageHandler {
//make this a function to allow this to run on the content page //make this a function to allow this to run on the content page
async function runThePopup(messageListener?: MessageListener) { async function runThePopup(messageListener?: MessageListener) {
var messageHandler = new MessageHandler(); var messageHandler = new MessageHandler(messageListener);
utils.localizeHtmlPage(); utils.localizeHtmlPage();
@@ -157,7 +157,7 @@ async function runThePopup(messageListener?: MessageListener) {
//get the amount of times this user has contributed and display it to thank them //get the amount of times this user has contributed and display it to thank them
if (Config.config.sponsorTimesContributed != undefined) { if (Config.config.sponsorTimesContributed != undefined) {
if (Config.config.sponsorTimesContributed > 1) { if (Config.config.sponsorTimesContributed !== 1) {
PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors"); PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors");
} else { } else {
PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor"); PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor");
@@ -656,9 +656,9 @@ async function runThePopup(messageListener?: MessageListener) {
tabs[0].id, tabs[0].id,
{message: "getCurrentTime"}, {message: "getCurrentTime"},
function (response) { function (response) {
let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index); let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index);
let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index); let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index);
minutes.value = String(getTimeInMinutes(response.currentTime)); minutes.value = String(getTimeInMinutes(response.currentTime));
seconds.value = getTimeInFormattedSeconds(response.currentTime); seconds.value = getTimeInFormattedSeconds(response.currentTime);
}); });
@@ -667,11 +667,11 @@ async function runThePopup(messageListener?: MessageListener) {
//id start name is whether it is the startTime or endTime //id start name is whether it is the startTime or endTime
//gives back the time in seconds //gives back the time in seconds
function getSponsorTimeEditTimes(idStartName, index) { function getSponsorTimeEditTimes(idStartName, index): number {
let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index); let minutes = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Minutes" + index);
let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index); let seconds = <HTMLInputElement> <unknown> document.getElementById(idStartName + "Seconds" + index);
return parseInt(minutes.value) * 60 + seconds.value; return parseInt(minutes.value) * 60 + parseFloat(seconds.value);
} }
function saveSponsorTimeEdit(index, closeEditMode = true) { function saveSponsorTimeEdit(index, closeEditMode = true) {
@@ -679,16 +679,17 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index); sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index);
//save this //save this
Config.config.sponsorTimes.set(currentVideoID, sponsorTimes); Config.config.sponsorTimes.set(currentVideoID, sponsorTimes);
messageHandler.query({
active: true, messageHandler.query({
currentWindow: true active: true,
}, tabs => { currentWindow: true
messageHandler.sendMessage( }, tabs => {
tabs[0].id, messageHandler.sendMessage(
{message: "sponsorDataChanged"} tabs[0].id,
); {message: "sponsorDataChanged"}
}); );
});
if (closeEditMode) { if (closeEditMode) {
displaySponsorTimes(); displaySponsorTimes();
@@ -718,17 +719,8 @@ async function runThePopup(messageListener?: MessageListener) {
sponsorTimes.splice(index, 1); sponsorTimes.splice(index, 1);
//save this //save this
Config.config.sponsorTimes.set(currentVideoID, sponsorTimes); Config.config.sponsorTimes.set(currentVideoID, sponsorTimes);
messageHandler.query({
active: true,
currentWindow: true
}, tabs => {
messageHandler.sendMessage(
tabs[0].id,
{message: "sponsorDataChanged"}
);
});
//update display //update display
displaySponsorTimes(); displaySponsorTimes();
@@ -749,6 +741,16 @@ async function runThePopup(messageListener?: MessageListener) {
//hide submission section //hide submission section
document.getElementById("submissionSection").style.display = "none"; document.getElementById("submissionSection").style.display = "none";
} }
messageHandler.query({
active: true,
currentWindow: true
}, tabs => {
messageHandler.sendMessage(
tabs[0].id,
{message: "sponsorDataChanged"}
);
});
} }
function clearTimes() { function clearTimes() {
@@ -968,7 +970,7 @@ async function runThePopup(messageListener?: MessageListener) {
secondsDisplay = "0" + secondsDisplay; secondsDisplay = "0" + secondsDisplay;
} }
let formatted = minutes+ ":" + secondsDisplay; let formatted = minutes + ":" + secondsDisplay;
return formatted; return formatted;
} }
@@ -1127,4 +1129,4 @@ if (chrome.tabs != undefined) {
runThePopup(); runThePopup();
} }
export default runThePopup; export default runThePopup;

View File

@@ -42,7 +42,8 @@ module.exports = env => ({
), ),
new BuildManifest({ new BuildManifest({
browser: env.browser, browser: env.browser,
pretty: env.mode === "production" pretty: env.mode === "production",
stream: env.stream
}) })
] ]
}); });

View File

@@ -8,6 +8,7 @@ const fs = require('fs');
const manifest = require("../manifest/manifest.json"); const manifest = require("../manifest/manifest.json");
const firefoxManifestExtra = require("../manifest/firefox-manifest-extra.json"); const firefoxManifestExtra = require("../manifest/firefox-manifest-extra.json");
const chromeManifestExtra = require("../manifest/chrome-manifest-extra.json"); const chromeManifestExtra = require("../manifest/chrome-manifest-extra.json");
const betaManifestExtra = require("../manifest/beta-manifest-extra.json");
// schema for options object // schema for options object
const schema = { const schema = {
@@ -18,6 +19,9 @@ const schema = {
}, },
pretty: { pretty: {
type: 'boolean' type: 'boolean'
},
steam: {
type: 'string'
} }
} }
}; };
@@ -40,6 +44,10 @@ class BuildManifest {
mergeObjects(manifest, chromeManifestExtra); mergeObjects(manifest, chromeManifestExtra);
} }
if (this.options.stream === "beta") {
mergeObjects(manifest, betaManifestExtra);
}
let result = JSON.stringify(manifest); let result = JSON.stringify(manifest);
if (this.options.pretty) result = JSON.stringify(manifest, null, 2); if (this.options.pretty) result = JSON.stringify(manifest, null, 2);