mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-18 21:48:33 +03:00
39
.github/workflows/release.yml
vendored
39
.github/workflows/release.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- run: mkdir ./builds
|
- run: mkdir ./builds
|
||||||
- uses: montudor/action-zip@v0.1.0
|
- uses: montudor/action-zip@v0.1.0
|
||||||
with:
|
with:
|
||||||
args: zip -qq -r ./builds/ChromeExtension.zip ./dist
|
args: zip -qq -r ./builds/ChromeExtension.zip ./dist/*
|
||||||
|
|
||||||
# Create Firefox artifacts
|
# Create Firefox artifacts
|
||||||
- name: Create Firefox artifacts
|
- name: Create Firefox artifacts
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- uses: montudor/action-zip@v0.1.0
|
- uses: montudor/action-zip@v0.1.0
|
||||||
with:
|
with:
|
||||||
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist
|
args: zip -qq -r ./builds/FirefoxExtension.zip ./dist/*
|
||||||
|
|
||||||
# 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
|
||||||
@@ -50,7 +50,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- uses: montudor/action-zip@v0.1.0
|
- uses: montudor/action-zip@v0.1.0
|
||||||
with:
|
with:
|
||||||
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist
|
args: zip -qq -r ./builds/ChromeExtensionBeta.zip ./dist/*
|
||||||
|
|
||||||
- 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
|
||||||
@@ -60,7 +60,24 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- uses: montudor/action-zip@v0.1.0
|
- uses: montudor/action-zip@v0.1.0
|
||||||
with:
|
with:
|
||||||
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist
|
args: zip -qq -r ./builds/FirefoxExtensionBeta.zip ./dist/*
|
||||||
|
|
||||||
|
# Create Firefox Signed Beta version
|
||||||
|
- name: Create Firefox Signed Beta artifacts
|
||||||
|
run: npm run web-sign
|
||||||
|
env:
|
||||||
|
WEB_EXT_API_KEY: ${{ secrets.WEB_EXT_API_KEY }}
|
||||||
|
WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }}
|
||||||
|
- name: Install rename
|
||||||
|
run: sudo apt-get install rename
|
||||||
|
- name: Install signed file
|
||||||
|
run: cd ./web-ext-artifacts
|
||||||
|
run: rename 's/.*/FirefoxSignedInstaller.xpi/' *
|
||||||
|
run: cd ..
|
||||||
|
- uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: FirefoxExtensionSigned.xpi
|
||||||
|
path: ./web-ext-artifacts/FirefoxSignedInstaller.xpi
|
||||||
|
|
||||||
# Upload each release asset
|
# Upload each release asset
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
@@ -70,6 +87,13 @@ jobs:
|
|||||||
name: ChromeExtension.zip
|
name: ChromeExtension.zip
|
||||||
path: ./builds/ChromeExtension.zip
|
path: ./builds/ChromeExtension.zip
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
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
|
- name: Upload to release
|
||||||
uses: Shopify/upload-to-release@master
|
uses: Shopify/upload-to-release@master
|
||||||
with:
|
with:
|
||||||
@@ -77,4 +101,11 @@ jobs:
|
|||||||
name: FirefoxExtension.zip
|
name: FirefoxExtension.zip
|
||||||
path: ./builds/FirefoxExtension.zip
|
path: ./builds/FirefoxExtension.zip
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Upload to release
|
||||||
|
uses: Shopify/upload-to-release@master
|
||||||
|
with:
|
||||||
|
args: web-ext-artifacts/FirefoxSignedInstaller.xpi
|
||||||
|
name: FirefoxSignedInstaller.xpi
|
||||||
|
path: ./web-ext-artifacts/FirefoxSignedInstaller.xpi
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"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 conect to",
|
||||||
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "offtopic"]
|
"categoryList": ["sponsor", "intro", "outro", "interaction", "selfpromo", "music_offtopic"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "__MSG_fullName__",
|
"name": "__MSG_fullName__",
|
||||||
"short_name": "__MSG_Name__",
|
"short_name": "__MSG_Name__",
|
||||||
"version": "1.2.27",
|
"version": "1.2.28",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"description": "__MSG_Description__",
|
"description": "__MSG_Description__",
|
||||||
"content_scripts": [{
|
"content_scripts": [{
|
||||||
|
|||||||
@@ -32,6 +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-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",
|
||||||
|
|||||||
@@ -351,7 +351,7 @@
|
|||||||
"message": "Support Invidious"
|
"message": "Support Invidious"
|
||||||
},
|
},
|
||||||
"supportInvidiousDescription": {
|
"supportInvidiousDescription": {
|
||||||
"message": "Invidious (invidio.us) is a third party YouTube client. To enable support, you must accept the extra permissions. This does NOT work in incongnito on Chrome and other Chromium variants."
|
"message": "Invidious (invidio.us) is a third party YouTube client. To enable support, you must accept the extra permissions. This does NOT work in incognito on Chrome and other Chromium variants."
|
||||||
},
|
},
|
||||||
"optionsInfo": {
|
"optionsInfo": {
|
||||||
"message": "Enable Invidious support, disable autoskip, hide buttons and more."
|
"message": "Enable Invidious support, disable autoskip, hide buttons and more."
|
||||||
@@ -490,19 +490,22 @@
|
|||||||
"message": "Sponsor"
|
"message": "Sponsor"
|
||||||
},
|
},
|
||||||
"category_intro": {
|
"category_intro": {
|
||||||
"message": "Intro"
|
"message": "Intro Animation"
|
||||||
},
|
},
|
||||||
"category_outro": {
|
"category_outro": {
|
||||||
"message": "Outro"
|
"message": "Endcards/Credits"
|
||||||
},
|
},
|
||||||
"category_interaction": {
|
"category_interaction": {
|
||||||
"message": "Interaction (Redundant Like, Subscribe, Follow, etc.)"
|
"message": "Interaction Reminder (Subscribe)"
|
||||||
},
|
},
|
||||||
"category_selfpromo": {
|
"category_selfpromo": {
|
||||||
"message": "Self-Promotion and Merchandise"
|
"message": "Self-Promotion and Merchandise"
|
||||||
},
|
},
|
||||||
"category_offtopic": {
|
"category_music_offtopic": {
|
||||||
"message": "Offtopic tangent (Subjective)"
|
"message": "Music: Non-Music Section"
|
||||||
|
},
|
||||||
|
"category_livestream_messages": {
|
||||||
|
"message": "Livestream: Donation/Message Readings"
|
||||||
},
|
},
|
||||||
"disable": {
|
"disable": {
|
||||||
"message": "Disable"
|
"message": "Disable"
|
||||||
@@ -554,5 +557,14 @@
|
|||||||
},
|
},
|
||||||
"forceChannelCheckPopup": {
|
"forceChannelCheckPopup": {
|
||||||
"message": "Consider Enabling Force Channel Check Before Skipping Sponsors"
|
"message": "Consider Enabling Force Channel Check Before Skipping Sponsors"
|
||||||
|
},
|
||||||
|
"downvoteDescription": {
|
||||||
|
"message": "Incorrect"
|
||||||
|
},
|
||||||
|
"incorrectCategory": {
|
||||||
|
"message": "Wrong Category"
|
||||||
|
},
|
||||||
|
"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."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,28 @@
|
|||||||
z-index: 40;
|
z-index: 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sbHidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.previewbar {
|
.previewbar {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Preview Bar page hacks */
|
||||||
|
|
||||||
|
.sbTooltipTwoTitleThumbnailOffset {
|
||||||
|
bottom: -5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sbTooltipOneTitleThumbnailOffset {
|
||||||
|
bottom: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
<span id="sponsorTimesSkipsDoneDisplay" class="popupElement">
|
<span id="sponsorTimesSkipsDoneDisplay" class="popupElement">
|
||||||
0
|
0
|
||||||
</span>
|
</span>
|
||||||
<span id="sponsorTimesSkipsDoneEndWord" class="popupElement">__MSG_Segments__</span> (since February).
|
<span id="sponsorTimesSkipsDoneEndWord" class="popupElement">__MSG_Segments__</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="sponsorTimeSavedContainer" class="popupElement" style="display: none">
|
<div id="sponsorTimeSavedContainer" class="popupElement" style="display: none">
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) {
|
|||||||
//this allows the callback to be called later
|
//this allows the callback to be called later
|
||||||
return true;
|
return true;
|
||||||
case "submitVote":
|
case "submitVote":
|
||||||
submitVote(request.type, request.UUID, callback);
|
submitVote(request.type, request.UUID, request.category, callback);
|
||||||
|
|
||||||
//this allows the callback to be called later
|
//this allows the callback to be called later
|
||||||
return true;
|
return true;
|
||||||
@@ -147,7 +147,7 @@ function addSponsorTime(time, videoID, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitVote(type, UUID, callback) {
|
function submitVote(type, UUID, category, callback) {
|
||||||
let userID = Config.config.userID;
|
let userID = Config.config.userID;
|
||||||
|
|
||||||
if (userID == undefined || userID === "undefined") {
|
if (userID == undefined || userID === "undefined") {
|
||||||
@@ -156,8 +156,10 @@ function submitVote(type, UUID, callback) {
|
|||||||
Config.config.userID = userID;
|
Config.config.userID = userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let typeSection = (type !== undefined) ? "&type=" + type : "&category=" + category;
|
||||||
|
|
||||||
//publish this vote
|
//publish this vote
|
||||||
utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) {
|
utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + typeSection, function(xmlhttp, error) {
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
||||||
callback({
|
callback({
|
||||||
successType: 1
|
successType: 1
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import * as CompileConfig from "../../config.json";
|
||||||
import Config from "../config"
|
import Config from "../config"
|
||||||
import { ContentContainer, SponsorHideType } from "../types";
|
import { ContentContainer, SponsorHideType } from "../types";
|
||||||
|
|
||||||
@@ -19,16 +20,19 @@ export interface SkipNoticeProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SkipNoticeState {
|
export interface SkipNoticeState {
|
||||||
noticeTitle: string,
|
noticeTitle: string;
|
||||||
|
|
||||||
messages: string[],
|
messages: string[];
|
||||||
|
|
||||||
countdownTime: number,
|
countdownTime: number;
|
||||||
maxCountdownTime: () => number;
|
maxCountdownTime: () => number;
|
||||||
countdownText: string,
|
countdownText: string;
|
||||||
|
|
||||||
unskipText: string,
|
unskipText: string;
|
||||||
unskipCallback: () => void
|
unskipCallback: () => void;
|
||||||
|
|
||||||
|
downvoting: boolean;
|
||||||
|
choosingCategory: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> {
|
class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeState> {
|
||||||
@@ -43,10 +47,15 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
idSuffix: any;
|
idSuffix: any;
|
||||||
|
|
||||||
noticeRef: React.MutableRefObject<NoticeComponent>;
|
noticeRef: React.MutableRefObject<NoticeComponent>;
|
||||||
|
categoryOptionRef: React.RefObject<HTMLSelectElement>;
|
||||||
|
|
||||||
|
// Used to update on config change
|
||||||
|
configListener: () => void;
|
||||||
|
|
||||||
constructor(props: SkipNoticeProps) {
|
constructor(props: SkipNoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
|
this.categoryOptionRef = React.createRef();
|
||||||
|
|
||||||
this.UUID = props.UUID;
|
this.UUID = props.UUID;
|
||||||
this.autoSkip = props.autoSkip;
|
this.autoSkip = props.autoSkip;
|
||||||
@@ -83,7 +92,10 @@ 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: this.unskip.bind(this),
|
||||||
|
|
||||||
|
downvoting: false,
|
||||||
|
choosingCategory: false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.autoSkip) {
|
if (!this.autoSkip) {
|
||||||
@@ -115,7 +127,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
timed={true}
|
timed={true}
|
||||||
maxCountdownTime={this.state.maxCountdownTime}
|
maxCountdownTime={this.state.maxCountdownTime}
|
||||||
ref={this.noticeRef}
|
ref={this.noticeRef}
|
||||||
closeListener={this.props.closeListener}>
|
closeListener={() => this.closeListener()}>
|
||||||
|
|
||||||
{(Config.config.audioNotificationOnSkip) && <audio ref={(source) => { this.audio = source; }}>
|
{(Config.config.audioNotificationOnSkip) && <audio ref={(source) => { this.audio = source; }}>
|
||||||
<source src={chrome.extension.getURL("icons/beep.ogg")} type="audio/ogg"></source>
|
<source src={chrome.extension.getURL("icons/beep.ogg")} type="audio/ogg"></source>
|
||||||
@@ -124,7 +136,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
{/* Text Boxes */}
|
{/* Text Boxes */}
|
||||||
{this.getMessageBoxes()}
|
{this.getMessageBoxes()}
|
||||||
|
|
||||||
{/* Last Row */}
|
{/* Bottom Row */}
|
||||||
<tr id={"sponsorSkipNoticeSecondRow" + this.idSuffix}>
|
<tr id={"sponsorSkipNoticeSecondRow" + this.idSuffix}>
|
||||||
|
|
||||||
{/* Vote Button Container */}
|
{/* Vote Button Container */}
|
||||||
@@ -145,7 +157,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
className="sponsorSkipObject voteButton"
|
className="sponsorSkipObject voteButton"
|
||||||
src={chrome.extension.getURL("icons/report.png")}
|
src={chrome.extension.getURL("icons/report.png")}
|
||||||
title={chrome.i18n.getMessage("reportButtonInfo")}
|
title={chrome.i18n.getMessage("reportButtonInfo")}
|
||||||
onClick={() => this.contentContainer().vote(0, this.UUID, this)}>
|
onClick={() => this.adjustDownvotingState(true)}>
|
||||||
|
|
||||||
</img>
|
</img>
|
||||||
|
|
||||||
@@ -174,6 +186,54 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
{/* Downvote Options Row */}
|
||||||
|
{this.state.downvoting &&
|
||||||
|
<tr id={"sponsorSkipNoticeDownvoteOptionsRow" + this.idSuffix}>
|
||||||
|
<td id={"sponsorTimesDownvoteOptionsContainer" + this.idSuffix}>
|
||||||
|
|
||||||
|
{/* Normal downvote */}
|
||||||
|
<button className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||||
|
onClick={() => this.contentContainer().vote(0, this.UUID, undefined, this)}>
|
||||||
|
{chrome.i18n.getMessage("downvoteDescription")}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Category vote */}
|
||||||
|
{Config.config.testingServer &&
|
||||||
|
<button className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||||
|
onClick={() => this.openCategoryChooser()}>
|
||||||
|
|
||||||
|
{chrome.i18n.getMessage("incorrectCategory")}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
|
||||||
|
{/* Category Chooser Row */}
|
||||||
|
{this.state.choosingCategory &&
|
||||||
|
<tr id={"sponsorSkipNoticeCategoryChooserRow" + this.idSuffix}>
|
||||||
|
<td>
|
||||||
|
{/* Category Selector */}
|
||||||
|
<select id={"sponsorTimeCategories" + this.idSuffix}
|
||||||
|
className="sponsorTimeCategories"
|
||||||
|
defaultValue={utils.getSponsorTimeFromUUID(this.props.contentContainer().sponsorTimes, this.props.UUID).category}
|
||||||
|
ref={this.categoryOptionRef}
|
||||||
|
onChange={this.categorySelectionChange.bind(this)}>
|
||||||
|
|
||||||
|
{this.getCategoryOptions()}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<button className="sponsorSkipObject sponsorSkipNoticeButton"
|
||||||
|
onClick={() => this.contentContainer().vote(undefined, this.UUID, this.categoryOptionRef.current.value, this)}>
|
||||||
|
|
||||||
|
{chrome.i18n.getMessage("submit")}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
|
||||||
</NoticeComponent>
|
</NoticeComponent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -202,6 +262,70 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustDownvotingState(value: boolean) {
|
||||||
|
if (!value) this.clearConfigListener();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
downvoting: value,
|
||||||
|
choosingCategory: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
clearConfigListener() {
|
||||||
|
if (this.configListener) {
|
||||||
|
Config.configListeners.splice(Config.configListeners.indexOf(this.configListener), 1);
|
||||||
|
this.configListener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openCategoryChooser() {
|
||||||
|
// Add as a config listener
|
||||||
|
this.configListener = () => this.forceUpdate();
|
||||||
|
Config.configListeners.push(this.configListener);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
choosingCategory: true,
|
||||||
|
downvoting: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getCategoryOptions() {
|
||||||
|
let elements = [];
|
||||||
|
|
||||||
|
for (const category of Config.config.categorySelections) {
|
||||||
|
elements.push(
|
||||||
|
<option value={category.name}
|
||||||
|
key={category.name}>
|
||||||
|
{chrome.i18n.getMessage("category_" + category.name)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elements.length < CompileConfig.categoryList.length) {
|
||||||
|
// Add show more button
|
||||||
|
elements.push(
|
||||||
|
<option value={"moreCategories"}
|
||||||
|
key={"moreCategories"}>
|
||||||
|
{chrome.i18n.getMessage("moreCategories")}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
||||||
|
// See if show more categories was pressed
|
||||||
|
if (event.target.value === "moreCategories") {
|
||||||
|
// Open options page
|
||||||
|
chrome.runtime.sendMessage({"message": "openConfig"});
|
||||||
|
|
||||||
|
// Reset option to original
|
||||||
|
event.target.value = utils.getSponsorTimeFromUUID(this.props.contentContainer().sponsorTimes, this.props.UUID).category;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unskip() {
|
unskip() {
|
||||||
this.contentContainer().unskipSponsorTime(this.UUID);
|
this.contentContainer().unskipSponsorTime(this.UUID);
|
||||||
|
|
||||||
@@ -258,22 +382,22 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
afterDownvote() {
|
afterDownvote(type: number, category: string) {
|
||||||
this.addVoteButtonInfo(chrome.i18n.getMessage("voted"));
|
this.addVoteButtonInfo(chrome.i18n.getMessage("voted"));
|
||||||
this.setNoticeInfoMessage(chrome.i18n.getMessage("hitGoBack"));
|
this.setNoticeInfoMessage(chrome.i18n.getMessage("hitGoBack"));
|
||||||
|
|
||||||
//remove this sponsor from the sponsors looked up
|
this.adjustDownvotingState(false);
|
||||||
//find which one it is
|
|
||||||
for (let i = 0; i < this.contentContainer().sponsorTimes.length; i++) {
|
|
||||||
if (this.contentContainer().sponsorTimes[i].UUID == this.UUID) {
|
|
||||||
//this one is the one to hide
|
|
||||||
|
|
||||||
//add this as a hidden sponsorTime
|
// Change the sponsor locally
|
||||||
this.contentContainer().sponsorTimes[i].hidden = SponsorHideType.Downvoted;
|
let sponsorTime = utils.getSponsorTimeFromUUID(this.contentContainer().sponsorTimes, this.UUID);
|
||||||
|
if (sponsorTime) {
|
||||||
this.contentContainer().updatePreviewBar();
|
if (type === 0) {
|
||||||
break;
|
sponsorTime.hidden = SponsorHideType.Downvoted;
|
||||||
|
} else if (category) {
|
||||||
|
sponsorTime.category = category;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.contentContainer().updatePreviewBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,6 +440,12 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
|
|||||||
//show button again
|
//show button again
|
||||||
document.getElementById("sponsorTimesDownvoteButtonsContainer" + this.idSuffix).style.removeProperty("display");
|
document.getElementById("sponsorTimesDownvoteButtonsContainer" + this.idSuffix).style.removeProperty("display");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeListener() {
|
||||||
|
this.clearConfigListener();
|
||||||
|
|
||||||
|
this.props.closeListener();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SkipNoticeComponent;
|
export default SkipNoticeComponent;
|
||||||
@@ -29,6 +29,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
|
|
||||||
categoryOptionRef: React.RefObject<HTMLSelectElement>;
|
categoryOptionRef: React.RefObject<HTMLSelectElement>;
|
||||||
|
|
||||||
|
configUpdateListener: () => void;
|
||||||
|
|
||||||
constructor(props: SponsorTimeEditProps) {
|
constructor(props: SponsorTimeEditProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -49,7 +51,16 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add as a config listener
|
// Add as a config listener
|
||||||
Config.configListeners.push(this.configUpdate.bind(this));
|
if (!this.configUpdateListener) {
|
||||||
|
this.configUpdateListener = () => this.configUpdate();
|
||||||
|
Config.configListeners.push(this.configUpdate.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.configUpdateListener) {
|
||||||
|
Config.configListeners.splice(Config.configListeners.indexOf(this.configUpdate.bind(this)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -61,6 +72,15 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
style.marginTop = "15px";
|
style.marginTop = "15px";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is required to get !important
|
||||||
|
// https://stackoverflow.com/a/45669262/1985387
|
||||||
|
let oldYouTubeDarkStyles = (node) => {
|
||||||
|
if (node) {
|
||||||
|
node.style.setProperty("color", "black", "important");
|
||||||
|
node.style.setProperty("text-shadow", "none", "important");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create time display
|
// Create time display
|
||||||
let timeDisplay: JSX.Element;
|
let timeDisplay: JSX.Element;
|
||||||
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
let sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
||||||
@@ -78,6 +98,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
|
|
||||||
<input id={"submittingTimeMinutes0" + this.idSuffix}
|
<input id={"submittingTimeMinutes0" + this.idSuffix}
|
||||||
className="sponsorTimeEdit sponsorTimeEditMinutes"
|
className="sponsorTimeEdit sponsorTimeEditMinutes"
|
||||||
|
ref={oldYouTubeDarkStyles}
|
||||||
type="number"
|
type="number"
|
||||||
value={this.state.sponsorTimeEdits[0][0]}
|
value={this.state.sponsorTimeEdits[0][0]}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -90,6 +111,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
|
|
||||||
<input id={"submittingTimeSeconds0" + this.idSuffix}
|
<input id={"submittingTimeSeconds0" + this.idSuffix}
|
||||||
className="sponsorTimeEdit sponsorTimeEditSeconds"
|
className="sponsorTimeEdit sponsorTimeEditSeconds"
|
||||||
|
ref={oldYouTubeDarkStyles}
|
||||||
type="number"
|
type="number"
|
||||||
value={this.state.sponsorTimeEdits[0][1]}
|
value={this.state.sponsorTimeEdits[0][1]}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -106,6 +128,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
|
|
||||||
<input id={"submittingTimeMinutes1" + this.idSuffix}
|
<input id={"submittingTimeMinutes1" + this.idSuffix}
|
||||||
className="sponsorTimeEdit sponsorTimeEditMinutes"
|
className="sponsorTimeEdit sponsorTimeEditMinutes"
|
||||||
|
ref={oldYouTubeDarkStyles}
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.sponsorTimeEdits[1][0]}
|
value={this.state.sponsorTimeEdits[1][0]}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -118,6 +141,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
|
|
||||||
<input id={"submittingTimeSeconds1" + this.idSuffix}
|
<input id={"submittingTimeSeconds1" + this.idSuffix}
|
||||||
className="sponsorTimeEdit sponsorTimeEditSeconds"
|
className="sponsorTimeEdit sponsorTimeEditSeconds"
|
||||||
|
ref={oldYouTubeDarkStyles}
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.sponsorTimeEdits[1][1]}
|
value={this.state.sponsorTimeEdits[1][1]}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -236,7 +260,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTimeToNow(index: number) {
|
setTimeToNow(index: number) {
|
||||||
this.setTimeTo(index, this.props.contentContainer().v.currentTime);
|
this.setTimeTo(index, this.props.contentContainer().getRoughCurrentTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeToEnd() {
|
setTimeToEnd() {
|
||||||
|
|||||||
@@ -93,13 +93,6 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
<td className="sponsorSkipNoticeRightSection"
|
<td className="sponsorSkipNoticeRightSection"
|
||||||
style={{position: "relative"}}>
|
style={{position: "relative"}}>
|
||||||
|
|
||||||
{/* Cancel Button */}
|
|
||||||
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
|
|
||||||
onClick={this.cancel.bind(this)}>
|
|
||||||
|
|
||||||
{chrome.i18n.getMessage("cancel")}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Submit Button */}
|
{/* Submit Button */}
|
||||||
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
|
<button className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"
|
||||||
onClick={this.submit.bind(this)}>
|
onClick={this.submit.bind(this)}>
|
||||||
@@ -167,6 +160,18 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
ref.current.saveEditTimes();
|
ref.current.saveEditTimes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if any non music categories are being used on a music video
|
||||||
|
if (this.contentContainer().videoInfo.microformat.playerMicroformatRenderer.category === "Music") {
|
||||||
|
let sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting;
|
||||||
|
for (const sponsorTime of sponsorTimesSubmitting) {
|
||||||
|
if (!sponsorTime.category.startsWith("music_")) {
|
||||||
|
if (!confirm(chrome.i18n.getMessage("nonMusicCategoryOnMusic"))) return;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.props.callback();
|
this.props.callback();
|
||||||
|
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ var Config: SBObject = {
|
|||||||
hideUploadButtonPlayerControls: false,
|
hideUploadButtonPlayerControls: false,
|
||||||
hideDiscordLaunches: 0,
|
hideDiscordLaunches: 0,
|
||||||
hideDiscordLink: false,
|
hideDiscordLink: false,
|
||||||
invidiousInstances: ["invidio.us", "invidiou.sh", "invidious.snopyta.org"],
|
invidiousInstances: ["invidio.us", "invidious.snopyta.org"],
|
||||||
autoUpvote: true,
|
autoUpvote: true,
|
||||||
supportInvidious: false,
|
supportInvidious: false,
|
||||||
serverAddress: CompileConfig.serverAddress,
|
serverAddress: CompileConfig.serverAddress,
|
||||||
@@ -254,7 +254,7 @@ async function migrateOldFormats() {
|
|||||||
|
|
||||||
// Channel URLS
|
// Channel URLS
|
||||||
if (Config.config.whitelistedChannels.length > 0 &&
|
if (Config.config.whitelistedChannels.length > 0 &&
|
||||||
(Config.config.whitelistedChannels[0].includes("/") || Config.config.whitelistedChannels[0] == null)) {
|
(Config.config.whitelistedChannels[0] == null || Config.config.whitelistedChannels[0].includes("/"))) {
|
||||||
let newChannelList: string[] = [];
|
let newChannelList: string[] = [];
|
||||||
for (const item of Config.config.whitelistedChannels) {
|
for (const item of Config.config.whitelistedChannels) {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
|
|||||||
@@ -114,7 +114,9 @@ var skipNoticeContentContainer: ContentContainer = () => ({
|
|||||||
sponsorSubmissionNotice: submissionNotice,
|
sponsorSubmissionNotice: submissionNotice,
|
||||||
resetSponsorSubmissionNotice,
|
resetSponsorSubmissionNotice,
|
||||||
changeStartSponsorButton,
|
changeStartSponsorButton,
|
||||||
previewTime
|
previewTime,
|
||||||
|
videoInfo,
|
||||||
|
getRoughCurrentTime
|
||||||
});
|
});
|
||||||
|
|
||||||
//get messages from the background script and the popup
|
//get messages from the background script and the popup
|
||||||
@@ -178,7 +180,7 @@ function messageListener(request: any, sender: any, sendResponse: (response: any
|
|||||||
return
|
return
|
||||||
case "getCurrentTime":
|
case "getCurrentTime":
|
||||||
sendResponse({
|
sendResponse({
|
||||||
currentTime: video.currentTime
|
currentTime: getRoughCurrentTime()
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -461,6 +463,7 @@ function cancelSponsorSchedule(): void {
|
|||||||
*/
|
*/
|
||||||
function startSponsorSchedule(includeIntersectingSegments: boolean = false, currentTime?: number): void {
|
function startSponsorSchedule(includeIntersectingSegments: boolean = false, currentTime?: number): void {
|
||||||
cancelSponsorSchedule();
|
cancelSponsorSchedule();
|
||||||
|
|
||||||
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)){
|
||||||
@@ -478,6 +481,7 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
|
|||||||
let currentSkip = skipInfo.array[skipInfo.index];
|
let currentSkip = skipInfo.array[skipInfo.index];
|
||||||
let skipTime: number[] = [currentSkip.segment[0], skipInfo.array[skipInfo.endIndex].segment[1]];
|
let skipTime: number[] = [currentSkip.segment[0], skipInfo.array[skipInfo.endIndex].segment[1]];
|
||||||
let timeUntilSponsor = skipTime[0] - currentTime;
|
let timeUntilSponsor = skipTime[0] - currentTime;
|
||||||
|
let videoID = sponsorVideoID;
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -486,7 +490,7 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
|
|||||||
let forcedSkipTime: number = null;
|
let forcedSkipTime: number = null;
|
||||||
let forcedIncludeIntersectingSegments = false;
|
let forcedIncludeIntersectingSegments = false;
|
||||||
|
|
||||||
if (incorrectVideoIDCheck()) return;
|
if (incorrectVideoIDCheck(videoID)) 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, skipInfo.endIndex, skipInfo.array, skipInfo.openNotice);
|
||||||
@@ -515,9 +519,9 @@ function startSponsorSchedule(includeIntersectingSegments: boolean = false, curr
|
|||||||
*
|
*
|
||||||
* TODO: Remove this bug catching if statement when the bug is found
|
* TODO: Remove this bug catching if statement when the bug is found
|
||||||
*/
|
*/
|
||||||
function incorrectVideoIDCheck(): boolean {
|
function incorrectVideoIDCheck(videoID?: string): boolean {
|
||||||
let currentVideoID = getYouTubeVideoID(document.URL);
|
let currentVideoID = getYouTubeVideoID(document.URL);
|
||||||
if (currentVideoID !== sponsorVideoID) {
|
if (currentVideoID !== (videoID || sponsorVideoID)) {
|
||||||
// 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);
|
||||||
@@ -967,7 +971,7 @@ function skipToTime(v: HTMLVideoElement, index: number, sponsorTimes: SponsorTim
|
|||||||
|
|
||||||
//auto-upvote this sponsor
|
//auto-upvote this sponsor
|
||||||
if (Config.config.trackViewCount && autoSkip && Config.config.autoUpvote) {
|
if (Config.config.trackViewCount && autoSkip && Config.config.autoUpvote) {
|
||||||
vote(1, currentUUID, null);
|
vote(1, currentUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1117,6 +1121,36 @@ async function updateVisibilityOfPlayerControlsButton(): Promise<boolean> {
|
|||||||
return createdButtons;
|
return createdButtons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for submitting. This will use the HTML displayed number when required as the video's
|
||||||
|
* current time is out of date while scrubbing or at the end of the video. This is not needed
|
||||||
|
* for sponsor skipping as the video is not playing during these times.
|
||||||
|
*/
|
||||||
|
function getRoughCurrentTime(): number {
|
||||||
|
let htmlCurrentTimeString = document.querySelector(".ytp-time-current").textContent;
|
||||||
|
let htmlDurationString = document.querySelector(".ytp-time-duration").textContent;
|
||||||
|
|
||||||
|
// Used to check if endscreen content is visible
|
||||||
|
let endScreenContent = document.querySelector(".ytp-endscreen-content");
|
||||||
|
// Used to check autoplay display
|
||||||
|
let autoPlayDisplay: HTMLDivElement = document.querySelector(".ytp-upnext");
|
||||||
|
|
||||||
|
if (htmlCurrentTimeString == htmlDurationString
|
||||||
|
|| endScreenContent.childElementCount > 0 || autoPlayDisplay.style.display !== "none") {
|
||||||
|
// At the end of the video
|
||||||
|
return video.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
let htmlCurrentTimeSections = htmlCurrentTimeString.split(":")[0];
|
||||||
|
let htmlCurrentTime: number = parseInt(htmlCurrentTimeSections[0]) * 60 + parseInt(htmlCurrentTimeSections[1]);
|
||||||
|
|
||||||
|
if (Math.abs(video.currentTime - htmlCurrentTime) > 3) {
|
||||||
|
return htmlCurrentTime;
|
||||||
|
} else {
|
||||||
|
return video.currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function startSponsorClicked() {
|
function startSponsorClicked() {
|
||||||
//it can't update to this info yet
|
//it can't update to this info yet
|
||||||
closeInfoMenu();
|
closeInfoMenu();
|
||||||
@@ -1126,11 +1160,11 @@ function startSponsorClicked() {
|
|||||||
//add to sponsorTimes
|
//add to sponsorTimes
|
||||||
if (sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.length < 2) {
|
if (sponsorTimesSubmitting.length > 0 && sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment.length < 2) {
|
||||||
//it is an end time
|
//it is an end time
|
||||||
sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment[1] = video.currentTime;
|
sponsorTimesSubmitting[sponsorTimesSubmitting.length - 1].segment[1] = getRoughCurrentTime();
|
||||||
} else {
|
} else {
|
||||||
//it is a start time
|
//it is a start time
|
||||||
sponsorTimesSubmitting.push({
|
sponsorTimesSubmitting.push({
|
||||||
segment: [video.currentTime],
|
segment: [getRoughCurrentTime()],
|
||||||
UUID: null,
|
UUID: null,
|
||||||
// Default to sponsor
|
// Default to sponsor
|
||||||
category: "sponsor"
|
category: "sponsor"
|
||||||
@@ -1306,7 +1340,7 @@ function clearSponsorTimes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if skipNotice is null, it will not affect the UI
|
//if skipNotice is null, it will not affect the UI
|
||||||
function vote(type, UUID, skipNotice?: SkipNoticeComponent) {
|
function vote(type: number, UUID: string, category?: string, skipNotice?: SkipNoticeComponent) {
|
||||||
if (skipNotice !== null && skipNotice !== undefined) {
|
if (skipNotice !== null && skipNotice !== undefined) {
|
||||||
//add loading info
|
//add loading info
|
||||||
skipNotice.addVoteButtonInfo.bind(skipNotice)("Loading...")
|
skipNotice.addVoteButtonInfo.bind(skipNotice)("Loading...")
|
||||||
@@ -1319,7 +1353,7 @@ function vote(type, UUID, skipNotice?: SkipNoticeComponent) {
|
|||||||
if (sponsorIndex == -1 || sponsorTimes[sponsorIndex].UUID === null) return;
|
if (sponsorIndex == -1 || sponsorTimes[sponsorIndex].UUID === null) return;
|
||||||
|
|
||||||
// See if the local time saved count and skip count should be saved
|
// See if the local time saved count and skip count should be saved
|
||||||
if (type == 0 && sponsorSkipped[sponsorIndex] || type == 1 && !sponsorSkipped[sponsorIndex]) {
|
if (type === 0 && sponsorSkipped[sponsorIndex] || type === 1 && !sponsorSkipped[sponsorIndex]) {
|
||||||
let factor = 1;
|
let factor = 1;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
factor = -1;
|
factor = -1;
|
||||||
@@ -1336,15 +1370,16 @@ function vote(type, UUID, skipNotice?: SkipNoticeComponent) {
|
|||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
message: "submitVote",
|
message: "submitVote",
|
||||||
type: type,
|
type: type,
|
||||||
UUID: UUID
|
UUID: UUID,
|
||||||
|
category: category
|
||||||
}, function(response) {
|
}, function(response) {
|
||||||
if (response != undefined) {
|
if (response != undefined) {
|
||||||
//see if it was a success or failure
|
//see if it was a success or failure
|
||||||
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) {
|
if (type === 0 || category) {
|
||||||
skipNotice.afterDownvote.bind(skipNotice)();
|
skipNotice.afterDownvote.bind(skipNotice)(type, category);
|
||||||
}
|
}
|
||||||
} else if (response.successType == 0) {
|
} else if (response.successType == 0) {
|
||||||
//failure: duplicate vote
|
//failure: duplicate vote
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ let barTypes = {
|
|||||||
color: "#bfbf35",
|
color: "#bfbf35",
|
||||||
opacity: "0.7"
|
opacity: "0.7"
|
||||||
},
|
},
|
||||||
"offtopic": {
|
"music_offtopic": {
|
||||||
color: "#ff9900",
|
color: "#ff9900",
|
||||||
opacity: "0.7"
|
opacity: "0.7"
|
||||||
},
|
},
|
||||||
"preview-offtopic": {
|
"preview-music_offtopic": {
|
||||||
color: "#a6634a",
|
color: "#a6634a",
|
||||||
opacity: "0.7"
|
opacity: "0.7"
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,9 @@ class PreviewBar {
|
|||||||
parent: any;
|
parent: any;
|
||||||
onMobileYouTube: boolean;
|
onMobileYouTube: boolean;
|
||||||
|
|
||||||
|
timestamps: number[][];
|
||||||
|
types: string;
|
||||||
|
|
||||||
constructor(parent, onMobileYouTube) {
|
constructor(parent, onMobileYouTube) {
|
||||||
this.container = document.createElement('ul');
|
this.container = document.createElement('ul');
|
||||||
this.container.id = 'previewbar';
|
this.container.id = 'previewbar';
|
||||||
@@ -73,6 +76,82 @@ class PreviewBar {
|
|||||||
this.onMobileYouTube = onMobileYouTube;
|
this.onMobileYouTube = onMobileYouTube;
|
||||||
|
|
||||||
this.updatePosition(parent);
|
this.updatePosition(parent);
|
||||||
|
|
||||||
|
this.setupHoverText();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupHoverText() {
|
||||||
|
let seekBar = document.querySelector(".ytp-progress-bar-container");
|
||||||
|
|
||||||
|
// Create label placeholder
|
||||||
|
let tooltipTextWrapper = document.querySelector(".ytp-tooltip-text-wrapper");
|
||||||
|
let titleTooltip = document.querySelector(".ytp-tooltip-title");
|
||||||
|
let categoryTooltip = document.createElement("div");
|
||||||
|
categoryTooltip.className = "sbHidden ytp-tooltip-title";
|
||||||
|
categoryTooltip.id = "sponsor-block-category-tooltip"
|
||||||
|
|
||||||
|
tooltipTextWrapper.insertBefore(categoryTooltip, titleTooltip.nextSibling);
|
||||||
|
|
||||||
|
let mouseOnSeekBar = false;
|
||||||
|
|
||||||
|
seekBar.addEventListener("mouseenter", (event) => {
|
||||||
|
mouseOnSeekBar = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
seekBar.addEventListener("mouseleave", (event) => {
|
||||||
|
mouseOnSeekBar = false;
|
||||||
|
categoryTooltip.classList.add("sbHidden");
|
||||||
|
});
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
if (!mouseOnSeekBar) return;
|
||||||
|
|
||||||
|
let tooltips = document.querySelectorAll(".ytp-tooltip-text");
|
||||||
|
for (const tooltip of tooltips) {
|
||||||
|
let splitData = tooltip.textContent.split(":");
|
||||||
|
if (splitData.length === 2 && !isNaN(parseInt(splitData[0])) && !isNaN(parseInt(splitData[1]))) {
|
||||||
|
// Add label
|
||||||
|
let timeInSeconds = parseInt(splitData[0]) * 60 + parseInt(splitData[1]);
|
||||||
|
|
||||||
|
// Find category at that location
|
||||||
|
let category = null;
|
||||||
|
for (let i = 0; i < this.timestamps.length; i++) {
|
||||||
|
if (this.timestamps[i][0] < timeInSeconds && this.timestamps[i][1] > timeInSeconds){
|
||||||
|
category = this.types[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (category === null && !categoryTooltip.classList.contains("sbHidden")) {
|
||||||
|
categoryTooltip.classList.add("sbHidden");
|
||||||
|
tooltipTextWrapper.classList.remove("sbTooltipTwoTitleThumbnailOffset");
|
||||||
|
tooltipTextWrapper.classList.remove("sbTooltipOneTitleThumbnailOffset");
|
||||||
|
} else if (category !== null) {
|
||||||
|
categoryTooltip.classList.remove("sbHidden");
|
||||||
|
categoryTooltip.textContent = chrome.i18n.getMessage("category_" + category)
|
||||||
|
|| (chrome.i18n.getMessage("preview") + " " + chrome.i18n.getMessage("category_" + category.split("preview-")[1]));
|
||||||
|
|
||||||
|
// There is a title now
|
||||||
|
tooltip.classList.remove("ytp-tooltip-text-no-title");
|
||||||
|
|
||||||
|
// Add the correct offset for the number of titles there are
|
||||||
|
if (titleTooltip.textContent !== "") {
|
||||||
|
if (!tooltipTextWrapper.classList.contains("sbTooltipTwoTitleThumbnailOffset")) {
|
||||||
|
tooltipTextWrapper.classList.add("sbTooltipTwoTitleThumbnailOffset");
|
||||||
|
}
|
||||||
|
} else if (!tooltipTextWrapper.classList.contains("sbTooltipOneTitleThumbnailOffset")) {
|
||||||
|
tooltipTextWrapper.classList.add("sbTooltipOneTitleThumbnailOffset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(tooltipTextWrapper, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePosition(parent) {
|
updatePosition(parent) {
|
||||||
@@ -109,6 +188,9 @@ class PreviewBar {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.timestamps = timestamps;
|
||||||
|
this.types = types;
|
||||||
|
|
||||||
// to avoid rounding error resulting in width more than 100%
|
// to avoid rounding error resulting in width more than 100%
|
||||||
duration = Math.floor(duration * 100) / 100;
|
duration = Math.floor(duration * 100) / 100;
|
||||||
let width;
|
let width;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import SkipNoticeComponent from "./components/SkipNoticeComponent";
|
|||||||
|
|
||||||
interface ContentContainer {
|
interface ContentContainer {
|
||||||
(): {
|
(): {
|
||||||
vote: (type: any, UUID: any, skipNotice?: SkipNoticeComponent) => void,
|
vote: (type: any, UUID: any, category?: string, skipNotice?: SkipNoticeComponent) => void,
|
||||||
dontShowNoticeAgain: () => void,
|
dontShowNoticeAgain: () => void,
|
||||||
unskipSponsorTime: (UUID: any) => void,
|
unskipSponsorTime: (UUID: any) => void,
|
||||||
sponsorTimes: SponsorTime[],
|
sponsorTimes: SponsorTime[],
|
||||||
@@ -16,7 +16,9 @@ interface ContentContainer {
|
|||||||
sponsorSubmissionNotice: SubmissionNotice,
|
sponsorSubmissionNotice: SubmissionNotice,
|
||||||
resetSponsorSubmissionNotice: () => void,
|
resetSponsorSubmissionNotice: () => void,
|
||||||
changeStartSponsorButton: (showStartSponsor: any, uploadButtonVisible: any) => Promise<boolean>,
|
changeStartSponsorButton: (showStartSponsor: any, uploadButtonVisible: any) => Promise<boolean>,
|
||||||
previewTime: (time: number) => void
|
previewTime: (time: number) => void,
|
||||||
|
videoInfo: any,
|
||||||
|
getRoughCurrentTime: () => number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user