Compare commits

...

23 Commits

Author SHA1 Message Date
Ajay Ramachandran
1676e50e15 Merge pull request #357 from ajayyy/react
Categories Improvements
2020-05-20 23:52:40 -04:00
Ajay Ramachandran
f165b3b602 Removed autoUpvote config 2020-05-20 23:50:26 -04:00
Ajay Ramachandran
0f82c16940 Fixed "voted" text. 2020-05-20 23:47:13 -04:00
Ajay Ramachandran
9ef3ef03a4 Added padding to vote buttons 2020-05-20 23:36:03 -04:00
Ajay Ramachandran
ef17cae9a1 Changed to upvote/downvote from report 2020-05-20 23:32:57 -04:00
Ajay Ramachandran
05acb1669e Added segment chooser when skipping multiple segments.
Now the skip notice supports skipping multiple segments.
2020-05-19 23:21:51 -04:00
Ajay Ramachandran
0850421afb Update config.json.example 2020-05-17 19:42:11 -04:00
Ajay Ramachandran
edf06ac908 Fixed typo: sever -> server 2020-05-17 11:31:35 -04:00
Ajay Ramachandran
842d35235a Gave web-ext the beta name and made signing happen at the end. 2020-05-17 00:23:44 -04:00
Ajay Ramachandran
45d20574d9 Merge pull request #356 from ajayyy/react
Fix preview sponsors not skipping
2020-05-17 00:00:08 -04:00
Ajay Ramachandran
252da8c56a Added the ability to stop the notice timer by clicking it 2020-05-16 23:58:02 -04:00
Ajay Ramachandran
99373c3e55 Added category names to notice 2020-05-16 23:48:41 -04:00
Ajay Ramachandran
dce69b3642 Incorrect -> Incorrect/Wrong Timing 2020-05-16 23:42:10 -04:00
Ajay Ramachandran
bb670b93e9 Fix preview sponsors not skipping 2020-05-16 23:39:04 -04:00
Ajay Ramachandran
c011ad105d Merge branch 'rafern' 2020-05-15 21:27:37 -04:00
Ajay Ramachandran
856125f7fd Merge pull request #350 from rafern/master
Don't skip ads, hide controls & sponsor times preview bar when ads are playing
2020-05-15 21:25:30 -04:00
Ajay Ramachandran
178b122ab8 Added back requested changes 2020-05-15 21:20:32 -04:00
Ajay Ramachandran
7b0488d068 Reverse "requested changes" 2020-05-15 21:15:50 -04:00
Ajay Ramachandran
02a9238869 Merge branch 'master' into master 2020-05-15 21:12:31 -04:00
Ajay Ramachandran
2fb97409a1 Changed where cd is used in release workflow 2020-05-15 21:08:52 -04:00
rafern
c046df7d18 Requested changes 2020-05-14 10:58:30 +01:00
Rafael
dd5ed6ce42 Remove duplicate code 2020-05-13 17:45:08 +01:00
rafern
3a0d5221f6 Don't skip ads, hide controls & bar when ad playing 2020-05-13 17:29:34 +01:00
14 changed files with 470 additions and 227 deletions

View File

@@ -18,9 +18,6 @@ jobs:
- name: Copy configuration - name: Copy configuration
run: cp config.json.example config.json run: cp config.json.example config.json
- name: Install Zip
run: sudo apt-get install zip
# Create Chrome artifacts # Create Chrome artifacts
- name: Create Chrome artifacts - name: Create Chrome artifacts
run: npm run build:chrome run: npm run build:chrome
@@ -30,9 +27,7 @@ jobs:
path: dist path: dist
- run: mkdir ./builds - run: mkdir ./builds
- name: Zip Artifacts - name: Zip Artifacts
run: cd ./dist run: cd ./dist ; zip -r ../builds/ChromeExtension.zip *
- run: zip -r ../builds/ChromeExtension.zip *
- run: cd ../
# Create Firefox artifacts # Create Firefox artifacts
- name: Create Firefox artifacts - name: Create Firefox artifacts
@@ -42,11 +37,7 @@ jobs:
name: FirefoxExtension name: FirefoxExtension
path: dist path: dist
- name: Zip Artifacts - name: Zip Artifacts
run: cd ./dist run: cd ./dist ; zip -r ../builds/FirefoxExtension.zip *
- uses: montudor/action-zip@v0.1.0
with:
args: zip -r ../builds/FirefoxExtension.zip *
- run: cd ../
# Create Beta artifacts (Builds with the name changed to beta) # Create Beta artifacts (Builds with the name changed to beta)
- name: Create Chrome Beta artifacts - name: Create Chrome Beta artifacts
@@ -56,10 +47,32 @@ jobs:
name: ChromeExtensionBeta name: ChromeExtensionBeta
path: dist path: dist
- name: Zip Artifacts - name: Zip Artifacts
run: cd ./dist run: cd ./dist ; zip -r ../builds/ChromeExtensionBeta.zip *
- run: zip -r ../builds/ChromeExtensionBeta.zip *
- run: cd ../
# Upload each release asset
- name: Upload ChromeExtension to release
uses: Shopify/upload-to-release@master
with:
args: builds/ChromeExtension.zip
name: ChromeExtension.zip
path: ./builds/ChromeExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload ChromeExtensionBeta to release
uses: Shopify/upload-to-release@master
with:
args: builds/ChromeExtensionBeta.zip
name: ChromeExtensionBeta.zip
path: ./builds/ChromeExtensionBeta.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload FirefoxExtension to release
uses: Shopify/upload-to-release@master
with:
args: builds/FirefoxExtension.zip
name: FirefoxExtension.zip
path: ./builds/FirefoxExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Firefox Beta
- name: Create Firefox Beta artifacts - name: Create Firefox Beta artifacts
run: npm run build:firefox -- --env.stream=beta run: npm run build:firefox -- --env.stream=beta
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
@@ -67,9 +80,7 @@ jobs:
name: FirefoxExtensionBeta name: FirefoxExtensionBeta
path: dist path: dist
- name: Zip Artifacts - name: Zip Artifacts
run: cd ./dist run: cd ./dist ; zip -r ../builds/FirefoxExtensionBeta.zip *
- run: zip -r ../builds/FirefoxExtensionBeta.zip *
- run: cd ../
# Create Firefox Signed Beta version # Create Firefox Signed Beta version
- name: Create Firefox Signed Beta artifacts - name: Create Firefox Signed Beta artifacts
@@ -79,38 +90,14 @@ jobs:
WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }} WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }}
- name: Install rename - name: Install rename
run: sudo apt-get install rename run: sudo apt-get install rename
- name: Install signed file - name: Rename signed file
run: cd ./web-ext-artifacts run: cd ./web-ext-artifacts ; rename 's/.*/FirefoxSignedInstaller.xpi/' *
- run: rename 's/.*/FirefoxSignedInstaller.xpi/' *
- run: cd ..
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
with: with:
name: FirefoxExtensionSigned.xpi name: FirefoxExtensionSigned.xpi
path: ./web-ext-artifacts/FirefoxSignedInstaller.xpi path: ./web-ext-artifacts/FirefoxSignedInstaller.xpi
# Upload each release asset - name: Upload FirefoxSignedInstaller.xpi to release
- name: Upload to release
uses: Shopify/upload-to-release@master
with:
args: builds/ChromeExtension.zip
name: ChromeExtension.zip
path: ./builds/ChromeExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to release
uses: Shopify/upload-to-release@master
with:
args: builds/ChromeExtensionBeta.zip
name: ChromeExtensionBeta.zip
path: ./builds/ChromeExtensionBeta.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to release
uses: Shopify/upload-to-release@master
with:
args: builds/FirefoxExtension.zip
name: FirefoxExtension.zip
path: ./builds/FirefoxExtension.zip
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to release
uses: Shopify/upload-to-release@master uses: Shopify/upload-to-release@master
with: with:
args: web-ext-artifacts/FirefoxSignedInstaller.xpi args: web-ext-artifacts/FirefoxSignedInstaller.xpi

View File

@@ -1,6 +1,6 @@
{ {
"serverAddress": "https://sponsor.ajay.app", "serverAddress": "https://sponsor.ajay.app",
"testingServerAddress": "https://sponsor.ajay.app/test", "testingServerAddress": "https://sponsor.ajay.app/test",
"serverAddressComment": "This specifies the default SponsorBlock server to conect to", "serverAddressComment": "This specifies the default SponsorBlock server to connect to",
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"] "categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"]
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "__MSG_fullName__", "name": "__MSG_fullName__",
"short_name": "__MSG_Name__", "short_name": "__MSG_Name__",
"version": "1.2.28.3", "version": "1.2.29",
"default_locale": "en", "default_locale": "en",
"description": "__MSG_Description__", "description": "__MSG_Description__",
"content_scripts": [{ "content_scripts": [{
@@ -30,6 +30,8 @@
"icons/PlayerUploadFailedIconSponsorBlocker256px.png", "icons/PlayerUploadFailedIconSponsorBlocker256px.png",
"icons/upvote.png", "icons/upvote.png",
"icons/downvote.png", "icons/downvote.png",
"icons/thumbs_down.svg",
"icons/thumbs_up.svg",
"icons/report.png", "icons/report.png",
"icons/close.png", "icons/close.png",
"icons/beep.ogg", "icons/beep.ogg",

View File

@@ -32,7 +32,7 @@
}, },
"scripts": { "scripts": {
"web-run": "npm run web-run:chrome", "web-run": "npm run web-run:chrome",
"web-sign": "web-ext sign -s dist", "web-sign": "web-ext sign -s dist --id sponsorBlockerBETA@ajay.app",
"web-run:firefox": "cd dist && web-ext run --start-url https://addons.mozilla.org/firefox/addon/ublock-origin/", "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",

View File

@@ -35,14 +35,14 @@
"Segments": { "Segments": {
"message": "sponsor segments" "message": "sponsor segments"
}, },
"noticeTitle": { "upvoteButtonInfo": {
"message": "Sponsor Skipped" "message": "Upvote this submission"
}, },
"reportButtonTitle": { "reportButtonTitle": {
"message": "Report" "message": "Report"
}, },
"reportButtonInfo": { "reportButtonInfo": {
"message": "Report this sponsor submission as incorrect." "message": "Report this submission as incorrect."
}, },
"Dismiss": { "Dismiss": {
"message": "Dismiss" "message": "Dismiss"
@@ -71,6 +71,9 @@
"paused": { "paused": {
"message": "Paused" "message": "Paused"
}, },
"manualPaused": {
"message": "Timer Stopped"
},
"confirmMSG": { "confirmMSG": {
"message": "To edit or delete individual values, click the info button or open the extension popup by clicking the extension icon in the top right corner." "message": "To edit or delete individual values, click the info button or open the extension popup by clicking the extension icon in the top right corner."
}, },
@@ -105,7 +108,7 @@
"message": "You have already voted this way before." "message": "You have already voted this way before."
}, },
"serverDown": { "serverDown": {
"message": "It seems the sever is down. Contact the dev immediately." "message": "It seems the server is down. Contact the dev immediately."
}, },
"connectionError": { "connectionError": {
"message": "A connection error has occured. Error code: " "message": "A connection error has occured. Error code: "
@@ -272,12 +275,12 @@
"errorCode": { "errorCode": {
"message": "Error Code: " "message": "Error Code: "
}, },
"noticeTitleNotSkipped": {
"message": "Skip Sponsor?"
},
"skip": { "skip": {
"message": "Skip" "message": "Skip"
}, },
"skipped": {
"message": "Skipped"
},
"disableAutoSkip": { "disableAutoSkip": {
"message": "Disable Auto Skip" "message": "Disable Auto Skip"
}, },
@@ -377,12 +380,6 @@
"currentInstances": { "currentInstances": {
"message": "Current Instances:" "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."
},
"minDuration": { "minDuration": {
"message": "Minimum duration (seconds):" "message": "Minimum duration (seconds):"
}, },
@@ -559,12 +556,15 @@
"message": "Consider Enabling Force Channel Check Before Skipping Sponsors" "message": "Consider Enabling Force Channel Check Before Skipping Sponsors"
}, },
"downvoteDescription": { "downvoteDescription": {
"message": "Incorrect" "message": "Incorrect/Wrong Timing"
}, },
"incorrectCategory": { "incorrectCategory": {
"message": "Wrong Category" "message": "Wrong Category"
}, },
"nonMusicCategoryOnMusic": { "nonMusicCategoryOnMusic": {
"message": "This video is categorized as music. Are you sure you would like to submit segments with non-music categories? Unless this video is not actually music, you should not be submitting this segment. Please read the guidelines if you are confused." "message": "This video is categorized as music. Are you sure you would like to submit segments with non-music categories? Unless this video is not actually music, you should not be submitting this segment. Please read the guidelines if you are confused."
},
"multipleSegments": {
"message": "Multiple Segments"
} }
} }

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="24"
viewBox="0 0 24 24"
width="24"
version="1.1"
id="svg6"
sodipodi:docname="thumbs_down.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="730"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
d="M0 0h24v24H0z"
fill="none"
id="path2" />
<path
d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
id="path4"
style="fill:#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 24 24"
fill="black"
width="18px"
height="18px"
version="1.1"
id="svg6"
sodipodi:docname="thumbs_up.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="730"
inkscape:window-height="480"
id="namedview8"
showgrid="false"
inkscape:zoom="13.111111"
inkscape:cx="9"
inkscape:cy="9"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<path
d="M0 0h24v24H0V0z"
fill="none"
id="path2" />
<path
d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"
id="path4"
style="fill:#ffffff" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -237,23 +237,6 @@
<br/> <br/>
<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"> <div option-type="toggle" sync-option="trackViewCount">
<label class="switch-container" label-name="__MSG_enableViewTracking__"> <label class="switch-container" label-name="__MSG_enableViewTracking__">
<label class="switch"> <label class="switch">

View File

@@ -23,6 +23,7 @@ export interface NoticeState {
countdownTime: number, countdownTime: number,
countdownText: string, countdownText: string,
countdownManuallyPaused: boolean,
} }
class NoticeComponent extends React.Component<NoticeProps, NoticeState> { class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
@@ -55,6 +56,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
//the countdown until this notice closes //the countdown until this notice closes
countdownTime: maxCountdownTime(), countdownTime: maxCountdownTime(),
countdownText: null, countdownText: null,
countdownManuallyPaused: false
} }
} }
@@ -71,8 +73,8 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
<table id={"sponsorSkipNotice" + this.idSuffix} <table id={"sponsorSkipNotice" + this.idSuffix}
className={"sponsorSkipObject sponsorSkipNotice" + (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")} className={"sponsorSkipObject sponsorSkipNotice" + (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")}
style={noticeStyle} style={noticeStyle}
onMouseEnter={this.pauseCountdown.bind(this)} onMouseEnter={() => this.timerMouseEnter()}
onMouseLeave={this.startCountdown.bind(this)}> onMouseLeave={() => this.timerMouseLeave()}>
<tbody> <tbody>
{/* First row */} {/* First row */}
@@ -99,6 +101,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
{/* Time left */} {/* Time left */}
{this.props.timed ? ( {this.props.timed ? (
<span id={"sponsorSkipNoticeTimeLeft" + this.idSuffix} <span id={"sponsorSkipNoticeTimeLeft" + this.idSuffix}
onClick={() => this.toggleManualPause()}
className="sponsorSkipObject sponsorSkipNoticeTimeLeft"> className="sponsorSkipObject sponsorSkipNoticeTimeLeft">
{this.state.countdownText || (this.state.countdownTime + "s")} {this.state.countdownText || (this.state.countdownTime + "s")}
@@ -121,6 +124,30 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
); );
} }
timerMouseEnter() {
if (this.state.countdownManuallyPaused) return;
this.pauseCountdown();
}
timerMouseLeave() {
if (this.state.countdownManuallyPaused) return;
this.startCountdown();
}
toggleManualPause() {
this.setState({
countdownManuallyPaused: !this.state.countdownManuallyPaused
}, () => {
if (this.state.countdownManuallyPaused) {
this.pauseCountdown();
} else {
this.startCountdown();
}
});
}
//called every second to lower the countdown before hiding the notice //called every second to lower the countdown before hiding the notice
countdown() { countdown() {
if (!this.props.timed) return; if (!this.props.timed) return;
@@ -159,7 +186,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
//reset countdown and inform the user //reset countdown and inform the user
this.setState({ this.setState({
countdownTime: this.state.maxCountdownTime(), countdownTime: this.state.maxCountdownTime(),
countdownText: chrome.i18n.getMessage("paused") countdownText: this.state.countdownManuallyPaused ? chrome.i18n.getMessage("manualPaused") : chrome.i18n.getMessage("paused")
}); });
//remove the fade out class if it exists //remove the fade out class if it exists

View File

@@ -1,7 +1,7 @@
import * as React from "react"; import * as React from "react";
import * as CompileConfig from "../../config.json"; import * as CompileConfig from "../../config.json";
import Config from "../config" import Config from "../config"
import { ContentContainer, SponsorHideType } from "../types"; import { ContentContainer, SponsorHideType, SponsorTime } from "../types";
import Utils from "../utils"; import Utils from "../utils";
var utils = new Utils(); var utils = new Utils();
@@ -9,9 +9,17 @@ var utils = new Utils();
import NoticeComponent from "./NoticeComponent"; import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
enum SkipNoticeAction {
None,
Upvote,
Downvote,
CategoryVote,
Unskip
}
export interface SkipNoticeProps { export interface SkipNoticeProps {
UUID: string; segments: SponsorTime[];
autoSkip: boolean; autoSkip: boolean;
// Contains functions and variables from the content script needed by the skip notice // Contains functions and variables from the content script needed by the skip notice
contentContainer: ContentContainer; contentContainer: ContentContainer;
@@ -29,14 +37,17 @@ export interface SkipNoticeState {
countdownText: string; countdownText: string;
unskipText: string; unskipText: string;
unskipCallback: () => void; unskipCallback: (index: number) => void;
downvoting: boolean; downvoting: boolean;
choosingCategory: boolean; choosingCategory: boolean;
thanksForVotingText: boolean; //null until the voting buttons should be hidden
actionState: SkipNoticeAction;
} }
class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> { class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> {
UUID: string; segments: SponsorTime[];
autoSkip: boolean; autoSkip: boolean;
// Contains functions and variables from the content script needed by the skip notice // Contains functions and variables from the content script needed by the skip notice
contentContainer: ContentContainer; contentContainer: ContentContainer;
@@ -57,22 +68,30 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.noticeRef = React.createRef(); this.noticeRef = React.createRef();
this.categoryOptionRef = React.createRef(); this.categoryOptionRef = React.createRef();
this.UUID = props.UUID; this.segments = props.segments;
this.autoSkip = props.autoSkip; this.autoSkip = props.autoSkip;
this.contentContainer = props.contentContainer; this.contentContainer = props.contentContainer;
this.audio = null; this.audio = null;
let noticeTitle = chrome.i18n.getMessage("noticeTitle"); let categoryName = chrome.i18n.getMessage(this.segments.length > 1 ? "multipleSegments" : "category_" + this.segments[0].category);
let noticeTitle = categoryName + " " + chrome.i18n.getMessage("skipped");
if (!this.autoSkip) { if (!this.autoSkip) {
noticeTitle = chrome.i18n.getMessage("noticeTitleNotSkipped"); noticeTitle = chrome.i18n.getMessage("skip") + " " + categoryName + "?";
} }
//add notice //add notice
this.amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length; this.amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
// Sort segments
if (this.segments.length > 1) {
this.segments.sort((a, b) => a.segment[0] - b.segment[0]);
}
//this is the suffix added at the end of every id //this is the suffix added at the end of every id
this.idSuffix = this.UUID + this.amountOfPreviousNotices; for (const segment of this.segments) {
this.idSuffix += segment.UUID;
}
this.idSuffix += this.amountOfPreviousNotices;
if (this.amountOfPreviousNotices > 0) { if (this.amountOfPreviousNotices > 0) {
//another notice exists //another notice exists
@@ -92,14 +111,18 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
countdownText: null, countdownText: null,
unskipText: chrome.i18n.getMessage("unskip"), unskipText: chrome.i18n.getMessage("unskip"),
unskipCallback: this.unskip.bind(this), unskipCallback: (index) => this.unskip(index),
downvoting: false, downvoting: false,
choosingCategory: false choosingCategory: false,
thanksForVotingText: null,
actionState: SkipNoticeAction.None
} }
if (!this.autoSkip) { if (!this.autoSkip) {
Object.assign(this.state, this.getUnskippedModeInfo(chrome.i18n.getMessage("skip"))); // Assume manual skip is only skipping 1 submission
Object.assign(this.state, this.getUnskippedModeInfo(0, chrome.i18n.getMessage("skip")));
} }
} }
@@ -140,35 +163,46 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
<tr id={"sponsorSkipNoticeSecondRow" + this.idSuffix}> <tr id={"sponsorSkipNoticeSecondRow" + this.idSuffix}>
{/* Vote Button Container */} {/* Vote Button Container */}
<td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix} {!this.state.thanksForVotingText ?
className="sponsorTimesVoteButtonsContainer"> <td id={"sponsorTimesVoteButtonsContainer" + this.idSuffix}
className="sponsorTimesVoteButtonsContainer">
{/* Report Text */} {/* Upvote Button */}
<span id={"sponsorTimesReportText" + this.idSuffix} <img id={"sponsorTimesDownvoteButtonsContainer" + this.idSuffix}
className="sponsorTimesInfoMessage sponsorTimesVoteButtonMessage" className="sponsorSkipObject voteButton"
title={chrome.i18n.getMessage("reportButtonInfo")} style={{marginRight: "10px"}}
style={{marginRight: "5px"}}> src={chrome.extension.getURL("icons/thumbs_up.svg")}
title={chrome.i18n.getMessage("upvoteButtonInfo")}
onClick={() => this.prepAction(SkipNoticeAction.Upvote)}>
{chrome.i18n.getMessage("reportButtonTitle")} </img>
</span>
{/* Report Button */} {/* Report Button */}
<img id={"sponsorTimesDownvoteButtonsContainer" + this.idSuffix} <img id={"sponsorTimesDownvoteButtonsContainer" + this.idSuffix}
className="sponsorSkipObject voteButton" className="sponsorSkipObject voteButton"
src={chrome.extension.getURL("icons/report.png")} src={chrome.extension.getURL("icons/thumbs_down.svg")}
title={chrome.i18n.getMessage("reportButtonInfo")} title={chrome.i18n.getMessage("reportButtonInfo")}
onClick={() => this.adjustDownvotingState(true)}> onClick={() => this.adjustDownvotingState(true)}>
</img> </img>
</td> </td>
:
<td id={"sponsorTimesVoteButtonInfoMessage" + this.idSuffix}
className="sponsorTimesInfoMessage sponsorTimesVoteButtonMessage"
style={{marginRight: "10px"}}>
{this.state.thanksForVotingText}
</td>
}
{/* Unskip Button */} {/* Unskip Button */}
<td className="sponsorSkipNoticeUnskipSection"> <td className="sponsorSkipNoticeUnskipSection">
<button id={"sponsorSkipUnskipButton" + this.idSuffix} <button id={"sponsorSkipUnskipButton" + this.idSuffix}
className="sponsorSkipObject sponsorSkipNoticeButton" className="sponsorSkipObject sponsorSkipNoticeButton"
style={{marginLeft: "4px"}} style={{marginLeft: "4px"}}
onClick={this.state.unskipCallback}> onClick={() => this.prepAction(SkipNoticeAction.Unskip)}>
{this.state.unskipText} {this.state.unskipText}
</button> </button>
@@ -193,7 +227,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
{/* Normal downvote */} {/* Normal downvote */}
<button className="sponsorSkipObject sponsorSkipNoticeButton" <button className="sponsorSkipObject sponsorSkipNoticeButton"
onClick={() => this.contentContainer().vote(0, this.UUID, undefined, this)}> onClick={() => this.prepAction(SkipNoticeAction.Downvote)}>
{chrome.i18n.getMessage("downvoteDescription")} {chrome.i18n.getMessage("downvoteDescription")}
</button> </button>
@@ -215,7 +249,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
{/* Category Selector */} {/* Category Selector */}
<select id={"sponsorTimeCategories" + this.idSuffix} <select id={"sponsorTimeCategories" + this.idSuffix}
className="sponsorTimeCategories" className="sponsorTimeCategories"
defaultValue={utils.getSponsorTimeFromUUID(this.props.contentContainer().sponsorTimes, this.props.UUID).category} defaultValue={this.segments[0].category} //Just default to the first segment, as we don't know which they'll choose
ref={this.categoryOptionRef} ref={this.categoryOptionRef}
onChange={this.categorySelectionChange.bind(this)}> onChange={this.categorySelectionChange.bind(this)}>
@@ -223,11 +257,23 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
</select> </select>
{/* Submit Button */} {/* Submit Button */}
<button className="sponsorSkipObject sponsorSkipNoticeButton" {this.segments.length === 1 &&
onClick={() => this.contentContainer().vote(undefined, this.UUID, this.categoryOptionRef.current.value, this)}> <button className="sponsorSkipObject sponsorSkipNoticeButton"
onClick={() => this.prepAction(SkipNoticeAction.CategoryVote)}>
{chrome.i18n.getMessage("submit")} {chrome.i18n.getMessage("submit")}
</button> </button>
}
</td>
</tr>
}
{/* Segment Chooser Row */}
{this.state.actionState !== SkipNoticeAction.None &&
<tr id={"sponsorSkipNoticeSubmissionOptionsRow" + this.idSuffix}>
<td id={"sponsorTimesSubmissionOptionsContainer" + this.idSuffix}>
{this.getSubmissionChooser()}
</td> </td>
</tr> </tr>
} }
@@ -236,6 +282,32 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
); );
} }
getSubmissionChooser(): JSX.Element[] {
let elements: JSX.Element[] = [];
for (let i = 0; i < this.segments.length; i++) {
elements.push(
<button className="sponsorSkipObject sponsorSkipNoticeButton"
onClick={() => this.performAction(i)}
key={"submission" + i + this.segments[i].category + this.idSuffix}>
{(i + 1) + ". " + chrome.i18n.getMessage("category_" + this.segments[i].category)}
</button>
);
}
return elements;
}
prepAction(action: SkipNoticeAction) {
if (this.segments.length === 1) {
this.performAction(0, action);
} else {
this.setState({
actionState: action
});
}
}
getMessageBoxes(): JSX.Element[] | JSX.Element { getMessageBoxes(): JSX.Element[] | JSX.Element {
if (this.state.messages.length === 0) { if (this.state.messages.length === 0) {
// Add a spacer if there is no text // Add a spacer if there is no text
@@ -260,6 +332,34 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
return elements; return elements;
} }
/**
* Performs the action from the current state
*
* @param index
*/
performAction(index: number, action?: SkipNoticeAction) {
switch (action ?? this.state.actionState) {
case SkipNoticeAction.None:
break;
case SkipNoticeAction.Upvote:
this.contentContainer().vote(1, this.segments[index].UUID, undefined, this);
break;
case SkipNoticeAction.Downvote:
this.contentContainer().vote(0, this.segments[index].UUID, undefined, this);
break;
case SkipNoticeAction.CategoryVote:
this.contentContainer().vote(undefined, this.segments[index].UUID, this.categoryOptionRef.current.value, this)
break;
case SkipNoticeAction.Unskip:
this.state.unskipCallback(index);
break;
}
this.setState({
actionState: SkipNoticeAction.None
});
}
adjustDownvotingState(value: boolean) { adjustDownvotingState(value: boolean) {
if (!value) this.clearConfigListener(); if (!value) this.clearConfigListener();
@@ -284,6 +384,11 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.setState({ this.setState({
choosingCategory: true, choosingCategory: true,
downvoting: false downvoting: false
}, () => {
if (this.segments.length > 1) {
// Use the action selectors as a submit button
this.prepAction(SkipNoticeAction.CategoryVote);
}
}); });
} }
@@ -319,37 +424,38 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
chrome.runtime.sendMessage({"message": "openConfig"}); chrome.runtime.sendMessage({"message": "openConfig"});
// Reset option to original // Reset option to original
event.target.value = utils.getSponsorTimeFromUUID(this.props.contentContainer().sponsorTimes, this.props.UUID).category; event.target.value = this.segments[0].category;
return; return;
} }
} }
unskip() { unskip(index: number) {
this.contentContainer().unskipSponsorTime(this.UUID); this.contentContainer().unskipSponsorTime(this.segments[index]);
this.unskippedMode(chrome.i18n.getMessage("reskip")); this.unskippedMode(index, chrome.i18n.getMessage("reskip"));
} }
/** Sets up notice to be not skipped yet */ /** Sets up notice to be not skipped yet */
unskippedMode(buttonText: string) { unskippedMode(index: number, buttonText: string) {
//setup new callback and reset countdown //setup new callback and reset countdown
this.setState(this.getUnskippedModeInfo(buttonText), () => { this.setState(this.getUnskippedModeInfo(index, buttonText), () => {
this.noticeRef.current.resetCountdown(); this.noticeRef.current.resetCountdown();
}); });
} }
getUnskippedModeInfo(buttonText: string) { getUnskippedModeInfo(index: number, buttonText: string) {
let self = this;
let maxCountdownTime = function() { let maxCountdownTime = function() {
let sponsorTime = utils.getSponsorTimeFromUUID(this.contentContainer().sponsorTimes, this.UUID); let sponsorTime = self.segments[index];
let duration = Math.round((sponsorTime.segment[1] - this.contentContainer().v.currentTime) * (1 / this.contentContainer().v.playbackRate)); let duration = Math.round((sponsorTime.segment[1] - self.contentContainer().v.currentTime) * (1 / self.contentContainer().v.playbackRate));
return Math.max(duration, 4); return Math.max(duration, 4);
}.bind(this); };
return { return {
unskipText: buttonText, unskipText: buttonText,
unskipCallback: this.reskip.bind(this), unskipCallback: (index) => this.reskip(index),
//change max duration to however much of the sponsor is left //change max duration to however much of the sponsor is left
maxCountdownTime: maxCountdownTime, maxCountdownTime: maxCountdownTime,
@@ -358,8 +464,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
} }
reskip() { reskip(index: number) {
this.contentContainer().reskipSponsorTime(this.UUID); this.contentContainer().reskipSponsorTime(this.segments[index]);
//reset countdown //reset countdown
this.setState({ this.setState({
@@ -375,24 +481,23 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.setState({ this.setState({
noticeTitle: chrome.i18n.getMessage("noticeTitle") noticeTitle: chrome.i18n.getMessage("noticeTitle")
}); });
if(Config.config.autoUpvote) this.contentContainer().vote(1, this.UUID);
} }
} }
afterDownvote(type: number, category: string) { afterVote(segment: SponsorTime, type: number, category: string) {
this.addVoteButtonInfo(chrome.i18n.getMessage("voted")); this.addVoteButtonInfo(chrome.i18n.getMessage("voted"));
this.setNoticeInfoMessage(chrome.i18n.getMessage("hitGoBack"));
this.adjustDownvotingState(false); if (type === 0) {
this.setNoticeInfoMessage(chrome.i18n.getMessage("hitGoBack"));
this.adjustDownvotingState(false);
}
// Change the sponsor locally // Change the sponsor locally
let sponsorTime = utils.getSponsorTimeFromUUID(this.contentContainer().sponsorTimes, this.UUID); if (segment) {
if (sponsorTime) {
if (type === 0) { if (type === 0) {
sponsorTime.hidden = SponsorHideType.Downvoted; segment.hidden = SponsorHideType.Downvoted;
} else if (category) { } else if (category) {
sponsorTime.category = category; segment.category = category;
} }
this.contentContainer().updatePreviewBar(); this.contentContainer().updatePreviewBar();
@@ -402,41 +507,19 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
setNoticeInfoMessage(...messages: string[]) { setNoticeInfoMessage(...messages: string[]) {
this.setState({ this.setState({
messages messages
}) });
} }
addVoteButtonInfo(message) { addVoteButtonInfo(message) {
this.resetVoteButtonInfo(); this.setState({
thanksForVotingText: message
//hide report button and text for it });
let downvoteButton = document.getElementById("sponsorTimesDownvoteButtonsContainer" + this.idSuffix);
if (downvoteButton != null) {
downvoteButton.style.display = "none";
}
let downvoteButtonText = document.getElementById("sponsorTimesReportText" + this.idSuffix);
if (downvoteButtonText != null) {
downvoteButtonText.style.display = "none";
}
//add info
let thanksForVotingText = document.createElement("td");
thanksForVotingText.id = "sponsorTimesVoteButtonInfoMessage" + this.idSuffix;
thanksForVotingText.className = "sponsorTimesInfoMessage sponsorTimesVoteButtonMessage";
thanksForVotingText.innerText = message;
//add element to div
document.getElementById("sponsorSkipNoticeSecondRow" + this.idSuffix).prepend(thanksForVotingText);
} }
resetVoteButtonInfo() { resetVoteButtonInfo() {
let previousInfoMessage = document.getElementById("sponsorTimesVoteButtonInfoMessage" + this.idSuffix); this.setState({
if (previousInfoMessage != null) { thanksForVotingText: null
//remove it });
document.getElementById("sponsorSkipNoticeSecondRow" + this.idSuffix).removeChild(previousInfoMessage);
}
//show button again
document.getElementById("sponsorTimesDownvoteButtonsContainer" + this.idSuffix).style.removeProperty("display");
} }
closeListener() { closeListener() {

View File

@@ -24,7 +24,6 @@ interface SBConfig {
hideDiscordLaunches: number, hideDiscordLaunches: number,
hideDiscordLink: boolean, hideDiscordLink: boolean,
invidiousInstances: string[], invidiousInstances: string[],
autoUpvote: boolean,
supportInvidious: boolean, supportInvidious: boolean,
serverAddress: string, serverAddress: string,
minDuration: number, minDuration: number,
@@ -124,7 +123,6 @@ var Config: SBObject = {
hideDiscordLaunches: 0, hideDiscordLaunches: 0,
hideDiscordLink: false, hideDiscordLink: false,
invidiousInstances: ["invidio.us", "invidious.snopyta.org"], invidiousInstances: ["invidio.us", "invidious.snopyta.org"],
autoUpvote: true,
supportInvidious: false, supportInvidious: false,
serverAddress: CompileConfig.serverAddress, serverAddress: CompileConfig.serverAddress,
minDuration: 0, minDuration: 0,
@@ -252,6 +250,11 @@ async function migrateOldFormats() {
} }
} }
// Auto vote removal
if (Config.config["autoUpvote"]) {
chrome.storage.sync.remove("autoUpvote");
}
// Channel URLS // Channel URLS
if (Config.config.whitelistedChannels.length > 0 && if (Config.config.whitelistedChannels.length > 0 &&
(Config.config.whitelistedChannels[0] == null || Config.config.whitelistedChannels[0].includes("/"))) { (Config.config.whitelistedChannels[0] == null || Config.config.whitelistedChannels[0].includes("/"))) {

View File

@@ -41,9 +41,6 @@ var sponsorSkipped: boolean[] = [];
//the video //the video
var video: HTMLVideoElement; var video: HTMLVideoElement;
/** The last time this video was seeking to */
var lastVideoTime: number = null;
var onInvidious; var onInvidious;
var onMobileYouTube; var onMobileYouTube;
@@ -81,12 +78,6 @@ utils.wait(() => Config.config !== null, 1000, 1).then(() => videoIDChange(getYo
//this only happens if there is an error //this only happens if there is an error
var sponsorLookupRetries = 0; var sponsorLookupRetries = 0;
//the last time in the video a sponsor was skipped
//used for the go back button
var lastSponsorTimeSkipped: number = null;
//used for ratings
var lastSponsorTimeSkippedUUID: string = null;
//if showing the start sponsor button or the end sponsor button on the player //if showing the start sponsor button or the end sponsor button on the player
var showingStartSponsor = true; var showingStartSponsor = true;
@@ -99,6 +90,9 @@ var popupInitialised = false;
var submissionNotice: SubmissionNotice = null; var submissionNotice: SubmissionNotice = null;
// If there is an advert playing (or about to be played), this is true
var isAdPlaying = false;
// Contains all of the functions and variables needed by the skip notice // Contains all of the functions and variables needed by the skip notice
var skipNoticeContentContainer: ContentContainer = () => ({ var skipNoticeContentContainer: ContentContainer = () => ({
vote, vote,
@@ -281,6 +275,9 @@ function resetValues() {
} else { } else {
switchingVideos = true; switchingVideos = true;
} }
// Reset advert playing flag
isAdPlaying = false;
} }
async function videoIDChange(id) { async function videoIDChange(id) {
@@ -446,6 +443,7 @@ function createPreviewBar(): void {
* This happens when the resolution changes or at random time to clear memory. * This happens when the resolution changes or at random time to clear memory.
*/ */
function durationChangeListener() { function durationChangeListener() {
updateAdFlag();
updatePreviewBar(); updatePreviewBar();
} }
@@ -464,6 +462,15 @@ function cancelSponsorSchedule(): void {
function startSponsorSchedule(includeIntersectingSegments: boolean = false, currentTime?: number): void { function startSponsorSchedule(includeIntersectingSegments: boolean = false, currentTime?: number): void {
cancelSponsorSchedule(); cancelSponsorSchedule();
// Don't skip if advert playing and reset last checked time
if (isAdPlaying) {
// Reset lastCheckVideoTime
lastCheckVideoTime = -1;
lastCheckTime = 0;
return;
}
if (video.paused) return; if (video.paused) return;
if (Config.config.disableSkipping || channelWhitelisted || (channelID === null && Config.config.forceChannelCheck)){ if (Config.config.disableSkipping || channelWhitelisted || (channelID === null && Config.config.forceChannelCheck)){
@@ -483,6 +490,19 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
let timeUntilSponsor = skipTime[0] - currentTime; let timeUntilSponsor = skipTime[0] - currentTime;
let videoID = sponsorVideoID; let videoID = sponsorVideoID;
// Find all indexes in between the start and end
let skippingSegments = [skipInfo.array[skipInfo.index]];
if (skipInfo.index !== skipInfo.endIndex) {
skippingSegments = [];
for (const segment of skipInfo.array) {
if (utils.getCategorySelection(segment.category).option === CategorySkipOption.AutoSkip &&
segment.segment[0] >= skipTime[0] && segment.segment[1] <= skipTime[1]) {
skippingSegments.push(segment);
}
}
}
// Don't skip if this category should not be skipped // Don't skip if this category should not be skipped
if (utils.getCategorySelection(currentSkip.category).option === CategorySkipOption.ShowOverlay) return; if (utils.getCategorySelection(currentSkip.category).option === CategorySkipOption.ShowOverlay) return;
@@ -493,7 +513,7 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
if (incorrectVideoCheck(videoID, currentSkip)) return; if (incorrectVideoCheck(videoID, currentSkip)) return;
if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) { if (video.currentTime >= skipTime[0] && video.currentTime < skipTime[1]) {
skipToTime(video, skipInfo.endIndex, skipInfo.array, skipInfo.openNotice); skipToTime(video, skipTime, skippingSegments, skipInfo.openNotice);
// TODO: Know the autoSkip settings for ALL items being skipped // TODO: Know the autoSkip settings for ALL items being skipped
if (utils.getCategorySelection(currentSkip.category).option === CategorySkipOption.ManualSkip) { if (utils.getCategorySelection(currentSkip.category).option === CategorySkipOption.ManualSkip) {
@@ -519,7 +539,7 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
*/ */
function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean { function incorrectVideoCheck(videoID?: string, sponsorTime?: SponsorTime): boolean {
let currentVideoID = getYouTubeVideoID(document.URL); let currentVideoID = getYouTubeVideoID(document.URL);
if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime && !sponsorTimes.includes(sponsorTime))) { if (currentVideoID !== (videoID || sponsorVideoID) || (sponsorTime && (!sponsorTimes || !sponsorTimes.includes(sponsorTime)) && !sponsorTimesSubmitting.includes(sponsorTime))) {
// Something has really gone wrong // Something has really gone wrong
console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be."); console.error("[SponsorBlock] The videoID recorded when trying to skip is different than what it should be.");
console.error("[SponsorBlock] VideoID recorded: " + sponsorVideoID + ". Actual VideoID: " + currentVideoID); console.error("[SponsorBlock] VideoID recorded: " + sponsorVideoID + ". Actual VideoID: " + currentVideoID);
@@ -554,6 +574,9 @@ function sponsorsLookup(id: string) {
video.addEventListener('play', () => { video.addEventListener('play', () => {
switchingVideos = false; switchingVideos = false;
// Check if an ad is playing
updateAdFlag();
// Make sure it doesn't get double called with the playing event // Make sure it doesn't get double called with the playing event
if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) { if (lastCheckVideoTime !== video.currentTime && Date.now() - lastCheckTime > 2000) {
lastCheckTime = Date.now(); lastCheckTime = Date.now();
@@ -561,6 +584,7 @@ function sponsorsLookup(id: string) {
startSponsorSchedule(); startSponsorSchedule();
} }
}); });
video.addEventListener('playing', () => { video.addEventListener('playing', () => {
// Make sure it doesn't get double called with the play event // Make sure it doesn't get double called with the play event
@@ -576,8 +600,6 @@ function sponsorsLookup(id: string) {
lastCheckVideoTime = -1 lastCheckVideoTime = -1
lastCheckTime = 0; lastCheckTime = 0;
lastVideoTime = video.currentTime;
if (!video.paused){ if (!video.paused){
startSponsorSchedule(); startSponsorSchedule();
} }
@@ -588,8 +610,6 @@ function sponsorsLookup(id: string) {
lastCheckVideoTime = -1; lastCheckVideoTime = -1;
lastCheckTime = 0; lastCheckTime = 0;
lastVideoTime = video.currentTime;
cancelSponsorSchedule(); cancelSponsorSchedule();
}); });
@@ -781,6 +801,11 @@ function updatePreviewBarPositionMobile(parent: Element) {
} }
function updatePreviewBar() { function updatePreviewBar() {
if(isAdPlaying) {
previewBar.set([], [], 0);
return;
}
if (previewBar === null || video === null) return; if (previewBar === null || video === null) return;
let localSponsorTimes = sponsorTimes; let localSponsorTimes = sponsorTimes;
@@ -955,58 +980,58 @@ function previewTime(time: number) {
} }
//skip from the start time to the end time for a certain index sponsor time //skip from the start time to the end time for a certain index sponsor time
function skipToTime(v: HTMLVideoElement, index: number, sponsorTimes: SponsorTime[], openNotice: boolean) { function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: SponsorTime[], openNotice: boolean) {
let autoSkip: boolean = utils.getCategorySelection(sponsorTimes[index].category).option === CategorySkipOption.AutoSkip; // There will only be one submission if it is manual skip
let autoSkip: boolean = utils.getCategorySelection(skippingSegments[0].category).option === CategorySkipOption.AutoSkip;
if (autoSkip || previewResetter !== null) { if (autoSkip || previewResetter !== null) {
v.currentTime = sponsorTimes[index].segment[1]; v.currentTime = skipTime[1];
} }
lastSponsorTimeSkipped = sponsorTimes[index].segment[0];
let currentUUID: string = sponsorTimes[index].UUID;
lastSponsorTimeSkippedUUID = currentUUID;
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 || !autoSkip) { if (!Config.config.dontShowNotice || !autoSkip) {
let skipNotice = new SkipNotice(currentUUID, autoSkip, skipNoticeContentContainer); let skipNotice = new SkipNotice(skippingSegments, autoSkip, skipNoticeContentContainer);
//auto-upvote this sponsor
if (Config.config.trackViewCount && autoSkip && Config.config.autoUpvote) {
vote(1, currentUUID);
}
} }
//send telemetry that a this sponsor was skipped //send telemetry that a this sponsor was skipped
if (Config.config.trackViewCount && !sponsorSkipped[index] && autoSkip) { if (Config.config.trackViewCount && autoSkip) {
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); let alreadySkipped = false;
let isPreviewSegment = false;
for (const segment of skippingSegments) {
let index = sponsorTimes.indexOf(segment);
if (index !== -1 && !sponsorSkipped[index]) {
utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + segment.UUID);
sponsorSkipped[index] = true;
} else if (sponsorSkipped[index]) {
alreadySkipped = true;
}
if (index !== -1) isPreviewSegment = true;
}
// Count this as a skip // Count this as a skip
Config.config.minutesSaved = Config.config.minutesSaved + (sponsorTimes[index].segment[1] - sponsorTimes[index].segment[0]) / 60; if (!alreadySkipped && !isPreviewSegment) {
Config.config.skipCount = Config.config.skipCount + 1; Config.config.minutesSaved = Config.config.minutesSaved + (skipTime[1] - skipTime[0]) / 60;
Config.config.skipCount = Config.config.skipCount + 1;
sponsorSkipped[index] = true; }
} }
} }
} }
function unskipSponsorTime(UUID) { function unskipSponsorTime(segment: SponsorTime) {
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
video.currentTime = utils.getSponsorTimeFromUUID(sponsorTimes, UUID).segment[0] + 0.001; video.currentTime = segment.segment[0] + 0.001;
checkIfInsideSegment(); checkIfInsideSegment();
} }
} }
function reskipSponsorTime(UUID) { function reskipSponsorTime(segment: SponsorTime) {
if (sponsorTimes != null) { video.currentTime = segment.segment[1];
video.currentTime = utils.getSponsorTimeFromUUID(sponsorTimes, UUID).segment[1];
// See if any skips need to be done if this is inside of another segment
startSponsorSchedule(true, utils.getSponsorTimeFromUUID(sponsorTimes, UUID).segment[1]);
}
} }
/** /**
@@ -1369,9 +1394,7 @@ function vote(type: number, UUID: string, category?: string, skipNotice?: SkipNo
if (skipNotice != null) { if (skipNotice != null) {
if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) { if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) {
//success (treat rate limits as a success) //success (treat rate limits as a success)
if (type === 0 || category) { skipNotice.afterVote.bind(skipNotice)(utils.getSponsorTimeFromUUID(sponsorTimes, UUID), type, category);
skipNotice.afterDownvote.bind(skipNotice)(type, category);
}
} else if (response.successType == 0) { } else if (response.successType == 0) {
//failure: duplicate vote //failure: duplicate vote
skipNotice.setNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail")) skipNotice.setNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail"))
@@ -1575,3 +1598,16 @@ function sendRequestToCustomServer(type, fullAddress, callback) {
//submit this request //submit this request
xmlhttp.send(); xmlhttp.send();
} }
/**
* Update the isAdPlaying flag and hide preview bar/controls if ad is playing
*/
function updateAdFlag() {
let wasAdPlaying = isAdPlaying;
isAdPlaying = document.getElementsByClassName('ad-showing').length > 0;
if(wasAdPlaying != isAdPlaying) {
updatePreviewBar();
updateVisibilityOfPlayerControlsButton();
}
}

View File

@@ -2,17 +2,18 @@ import * as React from "react";
import * as ReactDOM from "react-dom"; import * as ReactDOM from "react-dom";
import SkipNoticeComponent from "../components/SkipNoticeComponent"; import SkipNoticeComponent from "../components/SkipNoticeComponent";
import { SponsorTime } from "../types";
class SkipNotice { class SkipNotice {
UUID: string; segments: SponsorTime[];
autoSkip: boolean; autoSkip: boolean;
// Contains functions and variables from the content script needed by the skip notice // Contains functions and variables from the content script needed by the skip notice
contentContainer: () => any; contentContainer: () => any;
noticeElement: HTMLDivElement; noticeElement: HTMLDivElement;
constructor(UUID: string, autoSkip: boolean = false, contentContainer) { constructor(segments: SponsorTime[], autoSkip: boolean = false, contentContainer) {
this.UUID = UUID; this.segments = segments;
this.autoSkip = autoSkip; this.autoSkip = autoSkip;
this.contentContainer = contentContainer; this.contentContainer = contentContainer;
@@ -35,7 +36,11 @@ class SkipNotice {
let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length; let amountOfPreviousNotices = document.getElementsByClassName("sponsorSkipNotice").length;
//this is the suffix added at the end of every id //this is the suffix added at the end of every id
let idSuffix = this.UUID + amountOfPreviousNotices; let idSuffix = "";
for (const segment of this.segments) {
idSuffix += segment.UUID;
}
idSuffix += amountOfPreviousNotices;
this.noticeElement = document.createElement("div"); this.noticeElement = document.createElement("div");
this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix; this.noticeElement.id = "sponsorSkipNoticeContainer" + idSuffix;
@@ -43,7 +48,7 @@ class SkipNotice {
referenceNode.prepend(this.noticeElement); referenceNode.prepend(this.noticeElement);
ReactDOM.render( ReactDOM.render(
<SkipNoticeComponent UUID={UUID} <SkipNoticeComponent segments={segments}
autoSkip={autoSkip} autoSkip={autoSkip}
contentContainer={contentContainer} contentContainer={contentContainer}
closeListener={() => this.close()} />, closeListener={() => this.close()} />,

View File

@@ -5,12 +5,12 @@ interface ContentContainer {
(): { (): {
vote: (type: any, UUID: any, category?: string, skipNotice?: SkipNoticeComponent) => void, vote: (type: any, UUID: any, category?: string, skipNotice?: SkipNoticeComponent) => void,
dontShowNoticeAgain: () => void, dontShowNoticeAgain: () => void,
unskipSponsorTime: (UUID: any) => void, unskipSponsorTime: (segment: SponsorTime) => void,
sponsorTimes: SponsorTime[], sponsorTimes: SponsorTime[],
sponsorTimesSubmitting: SponsorTime[], sponsorTimesSubmitting: SponsorTime[],
v: HTMLVideoElement, v: HTMLVideoElement,
sponsorVideoID, sponsorVideoID,
reskipSponsorTime: (UUID: any) => void, reskipSponsorTime: (segment: SponsorTime) => void,
updatePreviewBar: () => void, updatePreviewBar: () => void,
onMobileYouTube: boolean, onMobileYouTube: boolean,
sponsorSubmissionNotice: SubmissionNotice, sponsorSubmissionNotice: SubmissionNotice,