mirror of
https://github.com/ajayyy/SponsorBlock.git
synced 2025-12-08 12:37:05 +03:00
Add initial sponsor help page
This commit is contained in:
@@ -50,6 +50,10 @@
|
|||||||
"icons/heart.svg",
|
"icons/heart.svg",
|
||||||
"icons/visible.svg",
|
"icons/visible.svg",
|
||||||
"icons/not_visible.svg",
|
"icons/not_visible.svg",
|
||||||
|
"icons/money.svg",
|
||||||
|
"icons/segway.png",
|
||||||
|
"icons/close-smaller.svg",
|
||||||
|
"icons/right-arrow.svg",
|
||||||
"icons/PlayerInfoIconSponsorBlocker.svg",
|
"icons/PlayerInfoIconSponsorBlocker.svg",
|
||||||
"icons/PlayerDeleteIconSponsorBlocker.svg",
|
"icons/PlayerDeleteIconSponsorBlocker.svg",
|
||||||
"popup.html",
|
"popup.html",
|
||||||
|
|||||||
@@ -239,6 +239,9 @@
|
|||||||
"showSkipNotice": {
|
"showSkipNotice": {
|
||||||
"message": "Show Notice After A Segment Is Skipped"
|
"message": "Show Notice After A Segment Is Skipped"
|
||||||
},
|
},
|
||||||
|
"showCategoryGuidelines": {
|
||||||
|
"message": "Show Category Help"
|
||||||
|
},
|
||||||
"noticeVisibilityMode0": {
|
"noticeVisibilityMode0": {
|
||||||
"message": "Full Size Skip Notices"
|
"message": "Full Size Skip Notices"
|
||||||
},
|
},
|
||||||
@@ -542,18 +545,39 @@
|
|||||||
"message": "to",
|
"message": "to",
|
||||||
"description": "Used between segments. Example: 1:20 to 1:30"
|
"description": "Used between segments. Example: 1:20 to 1:30"
|
||||||
},
|
},
|
||||||
|
"generic_guideline1": {
|
||||||
|
"message": "Include segue transitions"
|
||||||
|
},
|
||||||
|
"generic_guideline2": {
|
||||||
|
"message": "Plays as if nothing was skipped"
|
||||||
|
},
|
||||||
"category_sponsor": {
|
"category_sponsor": {
|
||||||
"message": "Sponsor"
|
"message": "Sponsor"
|
||||||
},
|
},
|
||||||
"category_sponsor_description": {
|
"category_sponsor_description": {
|
||||||
"message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like."
|
"message": "Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shoutouts to causes/creators/websites/products they like."
|
||||||
},
|
},
|
||||||
|
"category_sponsor_guideline1": {
|
||||||
|
"message": "Paid promotions"
|
||||||
|
},
|
||||||
|
"category_sponsor_guideline2": {
|
||||||
|
"message": "Not for donations or custom merch"
|
||||||
|
},
|
||||||
"category_selfpromo": {
|
"category_selfpromo": {
|
||||||
"message": "Unpaid/Self Promotion"
|
"message": "Unpaid/Self Promotion"
|
||||||
},
|
},
|
||||||
"category_selfpromo_description": {
|
"category_selfpromo_description": {
|
||||||
"message": "Similar to \"sponsor\" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with."
|
"message": "Similar to \"sponsor\" except for unpaid or self promotion. This includes sections about merchandise, donations, or information about who they collaborated with."
|
||||||
},
|
},
|
||||||
|
"category_selfpromo_guideline1": {
|
||||||
|
"message": "Applies to donations, memberships and custom merch"
|
||||||
|
},
|
||||||
|
"category_selfpromo_guideline2": {
|
||||||
|
"message": "Free shoutouts that don't add to the video"
|
||||||
|
},
|
||||||
|
"category_selfpromo_guideline3": {
|
||||||
|
"message": "Generic and company-created merch is Sponsor"
|
||||||
|
},
|
||||||
"category_exclusive_access": {
|
"category_exclusive_access": {
|
||||||
"message": "Exclusive Access"
|
"message": "Exclusive Access"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -347,6 +347,22 @@
|
|||||||
color: rgb(235, 235, 235);
|
color: rgb(235, 235, 235);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sb-guidelines-notice .sponsorTimesInfoMessage td {
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsorTimesInfoIcon {
|
||||||
|
width: 30px;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.segmentSummary {
|
.segmentSummary {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
37
public/icons/close-smaller.svg
Normal file
37
public/icons/close-smaller.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="close-smaller.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="731"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M12.45 37.65 10.35 35.55 21.9 24 10.35 12.45 12.45 10.35 24 21.9 35.55 10.35 37.65 12.45 26.1 24 37.65 35.55 35.55 37.65 24 26.1Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
37
public/icons/money.svg
Normal file
37
public/icons/money.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="money.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="6.5625"
|
||||||
|
inkscape:cx="37.942857"
|
||||||
|
inkscape:cy="29.714286"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="731"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M 22.070204,47.757552 V 42.214123 Q 18.308592,41.554191 15.89984,39.343419 13.491088,37.132647 12.435197,33.766994 l 3.695619,-1.517844 q 1.121884,3.167674 3.233667,4.718514 2.111782,1.55084 5.081476,1.55084 3.167674,0 5.213463,-1.583837 2.045789,-1.583837 2.045789,-4.355551 0,-2.903701 -1.814813,-4.487538 -1.814813,-1.583836 -6.830296,-3.233666 -4.75151,-1.517844 -7.094269,-4.025586 -2.342759,-2.507741 -2.342759,-6.269354 0,-3.629626 2.342759,-6.0713741 2.342759,-2.4417484 6.104371,-2.7717144 V 0.24244792 h 3.959592 V 5.7198835 q 2.969694,0.329966 5.114473,1.9467994 2.144779,1.6168335 3.266663,4.1245751 l -3.695619,1.583837 q -0.923905,-2.111783 -2.474745,-3.068684 -1.55084,-0.9569014 -4.058582,-0.9569014 -3.035687,0 -4.817503,1.3858574 -1.781817,1.385857 -1.781817,3.761612 0,2.507742 1.979796,4.058582 1.979796,1.55084 7.325246,3.20067 4.487537,1.385857 6.632316,3.992589 2.144779,2.606731 2.144779,6.566323 0,4.157572 -2.441748,6.69831 -2.441749,2.540738 -7.193259,3.266663 v 5.477436 z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff;stroke-width:1.31986" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
37
public/icons/right-arrow.svg
Normal file
37
public/icons/right-arrow.svg
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
height="48"
|
||||||
|
width="48"
|
||||||
|
version="1.1"
|
||||||
|
id="svg4"
|
||||||
|
sodipodi:docname="right-arrow.svg"
|
||||||
|
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs8" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview6"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="13.125"
|
||||||
|
inkscape:cx="24"
|
||||||
|
inkscape:cy="24"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="731"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4" />
|
||||||
|
<path
|
||||||
|
d="M15.2 43.9 12.4 41.05 29.55 23.9 12.4 6.75 15.2 3.9 35.2 23.9Z"
|
||||||
|
id="path2"
|
||||||
|
style="fill:#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/icons/segway.png
Normal file
BIN
public/icons/segway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -176,6 +176,18 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-type="toggle" data-sync="showCategoryGuidelines">
|
||||||
|
<div class="switch-container">
|
||||||
|
<label class="switch">
|
||||||
|
<input id="showCategoryGuidelines" type="checkbox" checked>
|
||||||
|
<span class="slider round"></span>
|
||||||
|
</label>
|
||||||
|
<label class="switch-label" for="showCategoryGuidelines">
|
||||||
|
__MSG_showCategoryGuidelines__
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div data-type="toggle" data-toggle-type="reverse" data-sync="hideVideoPlayerControls">
|
<div data-type="toggle" data-toggle-type="reverse" data-sync="hideVideoPlayerControls">
|
||||||
<div class="switch-container">
|
<div class="switch-container">
|
||||||
<label class="switch">
|
<label class="switch">
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface NoticeProps {
|
|||||||
|
|
||||||
smaller?: boolean,
|
smaller?: boolean,
|
||||||
limitWidth?: boolean,
|
limitWidth?: boolean,
|
||||||
|
extraClass?: string,
|
||||||
|
|
||||||
// Callback for when this is closed
|
// Callback for when this is closed
|
||||||
closeListener: () => void,
|
closeListener: () => void,
|
||||||
@@ -35,8 +36,6 @@ export interface NoticeProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NoticeState {
|
export interface NoticeState {
|
||||||
noticeTitle: string,
|
|
||||||
|
|
||||||
maxCountdownTime: () => number,
|
maxCountdownTime: () => number,
|
||||||
|
|
||||||
countdownTime: number,
|
countdownTime: number,
|
||||||
@@ -54,9 +53,13 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
|
|
||||||
amountOfPreviousNotices: number;
|
amountOfPreviousNotices: number;
|
||||||
|
|
||||||
|
parentRef: React.RefObject<HTMLDivElement>;
|
||||||
|
|
||||||
constructor(props: NoticeProps) {
|
constructor(props: NoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
this.parentRef = React.createRef();
|
||||||
|
|
||||||
const maxCountdownTime = () => {
|
const maxCountdownTime = () => {
|
||||||
if (this.props.maxCountdownTime) return this.props.maxCountdownTime();
|
if (this.props.maxCountdownTime) return this.props.maxCountdownTime();
|
||||||
else return Config.config.skipNoticeDuration;
|
else return Config.config.skipNoticeDuration;
|
||||||
@@ -71,8 +74,6 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
|
|
||||||
// Setup state
|
// Setup state
|
||||||
this.state = {
|
this.state = {
|
||||||
noticeTitle: props.noticeTitle,
|
|
||||||
|
|
||||||
maxCountdownTime,
|
maxCountdownTime,
|
||||||
|
|
||||||
//the countdown until this notice closes
|
//the countdown until this notice closes
|
||||||
@@ -97,9 +98,11 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
return (
|
return (
|
||||||
<div id={"sponsorSkipNotice" + this.idSuffix}
|
<div id={"sponsorSkipNotice" + this.idSuffix}
|
||||||
className={"sponsorSkipObject sponsorSkipNoticeParent"
|
className={"sponsorSkipObject sponsorSkipNoticeParent"
|
||||||
+ (this.props.showInSecondSlot ? " secondSkipNotice" : "")}
|
+ (this.props.showInSecondSlot ? " secondSkipNotice" : "")
|
||||||
|
+ (this.props.extraClass ? ` ${this.props.extraClass}` : "")}
|
||||||
onMouseEnter={(e) => this.onMouseEnter(e) }
|
onMouseEnter={(e) => this.onMouseEnter(e) }
|
||||||
onMouseLeave={() => this.timerMouseLeave()}
|
onMouseLeave={() => this.timerMouseLeave()}
|
||||||
|
ref={this.parentRef}
|
||||||
style={noticeStyle} >
|
style={noticeStyle} >
|
||||||
<div className={"sponsorSkipNoticeTableContainer"
|
<div className={"sponsorSkipNoticeTableContainer"
|
||||||
+ (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")
|
+ (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")
|
||||||
@@ -123,7 +126,7 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
style={{float: "left"}}
|
style={{float: "left"}}
|
||||||
className="sponsorSkipMessage sponsorSkipObject">
|
className="sponsorSkipMessage sponsorSkipObject">
|
||||||
|
|
||||||
{this.state.noticeTitle}
|
{this.props.noticeTitle}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{this.props.firstColumn}
|
{this.props.firstColumn}
|
||||||
@@ -344,12 +347,6 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
if (!silent) this.props.closeListener();
|
if (!silent) this.props.closeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
changeNoticeTitle(title: string): void {
|
|
||||||
this.setState({
|
|
||||||
noticeTitle: title
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addNoticeInfoMessage(message: string, message2 = ""): void {
|
addNoticeInfoMessage(message: string, message2 = ""): void {
|
||||||
//TODO: Replace
|
//TODO: Replace
|
||||||
|
|
||||||
@@ -384,6 +381,10 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
|
|||||||
document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText2, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix));
|
document.querySelector("#sponsorSkipNotice" + this.idSuffix + " > tbody").insertBefore(thanksForVotingText2, document.getElementById("sponsorSkipNoticeSpacer" + this.idSuffix));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getElement(): React.RefObject<HTMLDivElement> {
|
||||||
|
return this.parentRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NoticeComponent;
|
export default NoticeComponent;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export interface NoticeTextSelectionProps {
|
export interface NoticeTextSelectionProps {
|
||||||
|
icon?: string,
|
||||||
text: string,
|
text: string,
|
||||||
idSuffix: string,
|
idSuffix: string,
|
||||||
onClick?: (event: React.MouseEvent) => unknown
|
onClick?: (event: React.MouseEvent) => unknown
|
||||||
@@ -24,12 +25,21 @@ class NoticeTextSelectionComponent extends React.Component<NoticeTextSelectionPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p id={"sponsorTimesInfoMessage" + this.props.idSuffix}
|
<tr id={"sponsorTimesInfoMessage" + this.props.idSuffix}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
style={style}
|
style={style}
|
||||||
className="sponsorTimesInfoMessage">
|
className="sponsorTimesInfoMessage">
|
||||||
{this.props.text}
|
|
||||||
</p>
|
<td>
|
||||||
|
{this.props.icon ?
|
||||||
|
<img src={chrome.runtime.getURL(this.props.icon)} className="sponsorTimesInfoIcon" />
|
||||||
|
: null}
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{this.props.text}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface SponsorTimeEditProps {
|
|||||||
|
|
||||||
submissionNotice: SubmissionNoticeComponent;
|
submissionNotice: SubmissionNoticeComponent;
|
||||||
categoryList?: Category[];
|
categoryList?: Category[];
|
||||||
|
categoryChangeListener?: (index: number, category: Category) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SponsorTimeEditState {
|
export interface SponsorTimeEditState {
|
||||||
@@ -365,9 +366,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
}
|
}
|
||||||
|
|
||||||
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
categorySelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
const chosenCategory = event.target.value as Category;
|
||||||
|
|
||||||
// See if show more categories was pressed
|
// See if show more categories was pressed
|
||||||
if (event.target.value !== DEFAULT_CATEGORY && !Config.config.categorySelections.some((category) => category.name === event.target.value)) {
|
if (event.target.value !== DEFAULT_CATEGORY && !Config.config.categorySelections.some((category) => category.name === event.target.value)) {
|
||||||
const chosenCategory = event.target.value;
|
|
||||||
event.target.value = DEFAULT_CATEGORY;
|
event.target.value = DEFAULT_CATEGORY;
|
||||||
|
|
||||||
// Alert that they have to enable this category first
|
// Alert that they have to enable this category first
|
||||||
@@ -381,8 +383,12 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
|
||||||
this.handleReplacingLostTimes(event.target.value as Category, sponsorTime.actionType, sponsorTime);
|
this.handleReplacingLostTimes(chosenCategory, sponsorTime.actionType, sponsorTime);
|
||||||
this.saveEditTimes();
|
this.saveEditTimes();
|
||||||
|
|
||||||
|
if (this.props.categoryChangeListener) {
|
||||||
|
this.props.categoryChangeListener(this.props.index, chosenCategory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionTypeSelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
actionTypeSelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import Config from "../config"
|
import Config from "../config"
|
||||||
import { ContentContainer } from "../types";
|
import GenericNotice from "../render/GenericNotice";
|
||||||
|
import { Category, ContentContainer } from "../types";
|
||||||
|
import * as CompileConfig from "../../config.json";
|
||||||
|
|
||||||
import NoticeComponent from "./NoticeComponent";
|
import NoticeComponent from "./NoticeComponent";
|
||||||
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
|
||||||
import SponsorTimeEditComponent from "./SponsorTimeEditComponent";
|
import SponsorTimeEditComponent from "./SponsorTimeEditComponent";
|
||||||
|
import { getGuidelineInfo } from "../utils/constants";
|
||||||
|
|
||||||
export interface SubmissionNoticeProps {
|
export interface SubmissionNoticeProps {
|
||||||
// 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
|
||||||
@@ -32,6 +35,8 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
|
|
||||||
videoObserver: MutationObserver;
|
videoObserver: MutationObserver;
|
||||||
|
|
||||||
|
guidelinesReminder: GenericNotice;
|
||||||
|
|
||||||
constructor(props: SubmissionNoticeProps) {
|
constructor(props: SubmissionNoticeProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
@@ -128,6 +133,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
index={i}
|
index={i}
|
||||||
contentContainer={this.props.contentContainer}
|
contentContainer={this.props.contentContainer}
|
||||||
submissionNotice={this}
|
submissionNotice={this}
|
||||||
|
categoryChangeListener={this.categoryChangeListener.bind(this)}
|
||||||
ref={timeRef}>
|
ref={timeRef}>
|
||||||
</SponsorTimeEditComponent>
|
</SponsorTimeEditComponent>
|
||||||
);
|
);
|
||||||
@@ -154,6 +160,7 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancel(): void {
|
cancel(): void {
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
this.noticeRef.current.close(true);
|
this.noticeRef.current.close(true);
|
||||||
|
|
||||||
this.contentContainer().resetSponsorSubmissionNotice();
|
this.contentContainer().resetSponsorSubmissionNotice();
|
||||||
@@ -190,6 +197,45 @@ class SubmissionNoticeComponent extends React.Component<SubmissionNoticeProps, S
|
|||||||
|
|
||||||
this.cancel();
|
this.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
categoryChangeListener(index: number, category: Category): void {
|
||||||
|
const dialogWidth = this.noticeRef?.current?.getElement()?.current?.offsetWidth;
|
||||||
|
if (category !== "chooseACategory" && Config.config.showCategoryGuidelines
|
||||||
|
&& this.contentContainer().v.offsetWidth > dialogWidth * 2) {
|
||||||
|
const options = {
|
||||||
|
title: chrome.i18n.getMessage(`category_${category}`),
|
||||||
|
textBoxes: getGuidelineInfo(category),
|
||||||
|
buttons: [{
|
||||||
|
name: chrome.i18n.getMessage("learnMore"),
|
||||||
|
listener: () => window.open(CompileConfig.wikiLinks[category])
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: chrome.i18n.getMessage("Hide"),
|
||||||
|
listener: () => {
|
||||||
|
Config.config.showCategoryGuidelines = false;
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
|
this.guidelinesReminder = null;
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
timed: false,
|
||||||
|
style: {
|
||||||
|
right: `${dialogWidth + 10}px`,
|
||||||
|
},
|
||||||
|
extraClass: "sb-guidelines-notice"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.textBoxes) {
|
||||||
|
if (this.guidelinesReminder) {
|
||||||
|
this.guidelinesReminder.update(options);
|
||||||
|
} else {
|
||||||
|
this.guidelinesReminder = new GenericNotice(null, "GuidelinesReminder", options);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.guidelinesReminder?.close();
|
||||||
|
this.guidelinesReminder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SubmissionNoticeComponent;
|
export default SubmissionNoticeComponent;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ interface SBConfig {
|
|||||||
scrollToEditTimeUpdate: boolean,
|
scrollToEditTimeUpdate: boolean,
|
||||||
categoryPillUpdate: boolean,
|
categoryPillUpdate: boolean,
|
||||||
darkMode: boolean,
|
darkMode: boolean,
|
||||||
|
showCategoryGuidelines: boolean,
|
||||||
|
|
||||||
// Used to cache calculated text color info
|
// Used to cache calculated text color info
|
||||||
categoryPillColors: {
|
categoryPillColors: {
|
||||||
@@ -167,6 +168,7 @@ const Config: SBObject = {
|
|||||||
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
|
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
|
||||||
categoryPillUpdate: false,
|
categoryPillUpdate: false,
|
||||||
darkMode: true,
|
darkMode: true,
|
||||||
|
showCategoryGuidelines: true,
|
||||||
|
|
||||||
categoryPillColors: {},
|
categoryPillColors: {},
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,19 @@ export interface ButtonListener {
|
|||||||
listener: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
|
listener: (e?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TextBox {
|
||||||
|
icon: string,
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface NoticeOptions {
|
export interface NoticeOptions {
|
||||||
title: string,
|
title: string,
|
||||||
textBoxes?: string[],
|
textBoxes?: TextBox[],
|
||||||
buttons?: ButtonListener[],
|
buttons?: ButtonListener[],
|
||||||
fadeIn?: boolean,
|
fadeIn?: boolean,
|
||||||
timed?: boolean
|
timed?: boolean
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
extraClass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class GenericNotice {
|
export default class GenericNotice {
|
||||||
@@ -27,9 +34,11 @@ export default class GenericNotice {
|
|||||||
|
|
||||||
noticeElement: HTMLDivElement;
|
noticeElement: HTMLDivElement;
|
||||||
noticeRef: React.MutableRefObject<NoticeComponent>;
|
noticeRef: React.MutableRefObject<NoticeComponent>;
|
||||||
|
idSuffix: string;
|
||||||
|
|
||||||
constructor(contentContainer: ContentContainer, idSuffix: string, options: NoticeOptions) {
|
constructor(contentContainer: ContentContainer, idSuffix: string, options: NoticeOptions) {
|
||||||
this.noticeRef = React.createRef();
|
this.noticeRef = React.createRef();
|
||||||
|
this.idSuffix = idSuffix;
|
||||||
|
|
||||||
this.contentContainer = contentContainer;
|
this.contentContainer = contentContainer;
|
||||||
|
|
||||||
@@ -40,39 +49,47 @@ export default class GenericNotice {
|
|||||||
|
|
||||||
referenceNode.prepend(this.noticeElement);
|
referenceNode.prepend(this.noticeElement);
|
||||||
|
|
||||||
|
this.update(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(options: NoticeOptions): void {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<NoticeComponent
|
<NoticeComponent
|
||||||
noticeTitle={options.title}
|
noticeTitle={options.title}
|
||||||
idSuffix={idSuffix}
|
idSuffix={this.idSuffix}
|
||||||
fadeIn={options.fadeIn ?? true}
|
fadeIn={options.fadeIn ?? true}
|
||||||
timed={options.timed ?? true}
|
timed={options.timed ?? true}
|
||||||
ref={this.noticeRef}
|
ref={this.noticeRef}
|
||||||
|
style={options.style}
|
||||||
|
extraClass={options.extraClass}
|
||||||
closeListener={() => this.close()} >
|
closeListener={() => this.close()} >
|
||||||
|
|
||||||
{this.getMessageBox(idSuffix, options.textBoxes)}
|
{this.getMessageBox(this.idSuffix, options.textBoxes)}
|
||||||
|
|
||||||
<tr id={"sponsorSkipNoticeSpacer" + idSuffix}
|
<tr id={"sponsorSkipNoticeSpacer" + this.idSuffix}
|
||||||
className="sponsorBlockSpacer">
|
className="sponsorBlockSpacer">
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<div className="sponsorSkipNoticeRightSection"
|
<tr className="sponsorSkipNoticeRightSection"
|
||||||
style={{position: "relative"}}>
|
style={{position: "relative"}}>
|
||||||
|
<td>
|
||||||
{this.getButtons(options.buttons)}
|
{this.getButtons(options.buttons)}
|
||||||
</div>
|
</td>
|
||||||
|
</tr>
|
||||||
</NoticeComponent>,
|
</NoticeComponent>,
|
||||||
this.noticeElement
|
this.noticeElement
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessageBox(idSuffix: string, textBoxes: string[]): JSX.Element[] {
|
getMessageBox(idSuffix: string, textBoxes: TextBox[]): JSX.Element[] {
|
||||||
if (textBoxes) {
|
if (textBoxes) {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (let i = 0; i < textBoxes.length; i++) {
|
for (let i = 0; i < textBoxes.length; i++) {
|
||||||
result.push(
|
result.push(
|
||||||
<NoticeTextSelectionComponent idSuffix={idSuffix}
|
<NoticeTextSelectionComponent idSuffix={idSuffix}
|
||||||
key={i}
|
key={i}
|
||||||
text={textBoxes[i]} />
|
icon={textBoxes[i].icon}
|
||||||
|
text={textBoxes[i].text} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
src/utils/constants.ts
Normal file
21
src/utils/constants.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { TextBox } from "../render/GenericNotice";
|
||||||
|
import { Category } from "../types";
|
||||||
|
|
||||||
|
export function getGuidelineInfo(category: Category): TextBox[] {
|
||||||
|
switch (category) {
|
||||||
|
case "sponsor":
|
||||||
|
return [{
|
||||||
|
icon: "icons/money.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/close-smaller.svg",
|
||||||
|
text: chrome.i18n.getMessage(`category_${category}_guideline2`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/segway.png",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline1`)
|
||||||
|
}, {
|
||||||
|
icon: "icons/right-arrow.svg",
|
||||||
|
text: chrome.i18n.getMessage(`generic_guideline2`)
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ function hexToRgb(hex: string): {r: number, g: number, b: number} {
|
|||||||
g: parseInt(result[2], 16),
|
g: parseInt(result[2], 16),
|
||||||
b: parseInt(result[3], 16)
|
b: parseInt(result[3], 16)
|
||||||
} : null;
|
} : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GenericUtils = {
|
export const GenericUtils = {
|
||||||
wait,
|
wait,
|
||||||
|
|||||||
Reference in New Issue
Block a user