Vip warning added when downvoting. sry that it is in the same branch, but this is the most current UI

This commit is contained in:
FlorianZahn
2021-10-10 10:47:47 +02:00
parent a9cc43c586
commit d9f703d808
4 changed files with 112 additions and 21 deletions

View File

@@ -83,6 +83,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
selectedColor: string; selectedColor: string;
unselectedColor: string; unselectedColor: string;
lockedColor: string;
// Used to update on config change // Used to update on config change
configListener: () => void; configListener: () => void;
@@ -117,6 +118,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.selectedColor = Config.config.colorPalette.get("SponsorBlockRed"); this.selectedColor = Config.config.colorPalette.get("SponsorBlockRed");
this.unselectedColor = Config.config.colorPalette.get("SponsorBlockWhite"); this.unselectedColor = Config.config.colorPalette.get("SponsorBlockWhite");
this.lockedColor = Config.config.colorPalette.get("SponsorBlockLocked");
// Setup state // Setup state
this.state = { this.state = {
@@ -227,7 +229,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
style={{marginRight: "5px", marginLeft: "5px"}} style={{marginRight: "5px", marginLeft: "5px"}}
title={chrome.i18n.getMessage("reportButtonInfo")} title={chrome.i18n.getMessage("reportButtonInfo")}
onClick={() => this.prepAction(SkipNoticeAction.Downvote)}> onClick={() => this.prepAction(SkipNoticeAction.Downvote)}>
<ThumbsDownSvg fill={(this.state.actionState === SkipNoticeAction.Downvote) ? this.selectedColor : this.unselectedColor} /> <ThumbsDownSvg fill={this.downvoteButtonColor(SkipNoticeAction.Downvote)} />
</div> </div>
{/* Copy and Downvote Button */} {/* Copy and Downvote Button */}
@@ -290,8 +292,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
{/* Copy Segment */} {/* Copy Segment */}
<button className="sponsorSkipObject sponsorSkipNoticeButton" <button className="sponsorSkipObject sponsorSkipNoticeButton"
title={chrome.i18n.getMessage("CopyDownvoteButtonInfo")} title={chrome.i18n.getMessage("CopyDownvoteButtonInfo")}
//style={{color: (this.state.actionState === SkipNoticeAction.CopyDownvote && this.state.editing == true) ? this.selectedColor : this.unselectedColor}} style={{color: this.downvoteButtonColor(SkipNoticeAction.Downvote)}}
//style={{color: (this.state.editing == true) ? this.selectedColor : this.unselectedColor}}
onClick={() => this.prepAction(SkipNoticeAction.CopyDownvote)}> onClick={() => this.prepAction(SkipNoticeAction.CopyDownvote)}>
{chrome.i18n.getMessage("CopyAndDownvote")} {chrome.i18n.getMessage("CopyAndDownvote")}
</button> </button>
@@ -315,7 +316,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
{/* Category Selector */} {/* Category Selector */}
<select id={"sponsorTimeCategories" + this.idSuffix} <select id={"sponsorTimeCategories" + this.idSuffix}
className="sponsorTimeCategories sponsorTimeEditSelector" className="sponsorTimeCategories sponsorTimeEditSelector"
defaultValue={this.segments[0].category} //Just default to the first segment, as we don't know which they'll choose defaultValue={this.segments[0].category}
ref={this.categoryOptionRef}> ref={this.categoryOptionRef}>
{this.getCategoryOptions()} {this.getCategoryOptions()}
@@ -366,27 +367,38 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getSubmissionChooser(): JSX.Element[] { getSubmissionChooser(): JSX.Element[] {
const elements: JSX.Element[] = []; const elements: JSX.Element[] = [];
const isUpvote = this.state.actionState === SkipNoticeAction.Upvote;
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
for (let i = 0; i < this.segments.length; i++) { for (let i = 0; i < this.segments.length; i++) {
const shouldBeGray: boolean= isUpvote && this.state.voted[i] == SkipNoticeAction.Upvote ||
isDownvote && this.state.voted[i] == SkipNoticeAction.Downvote ||
isCopyDownvote && this.state.copied[i] == SkipNoticeAction.CopyDownvote;
const opacity = shouldBeGray ? 0.35 : 1;
elements.push( elements.push(
<button className="sponsorSkipObject sponsorSkipNoticeButton" <button className="sponsorSkipObject sponsorSkipNoticeButton"
style={{opacity: opacity}} style={{opacity: this.submissionChooserOpacitySelector(i),
color: this.submissionChooserColorSelector(i)}}
onClick={() => this.performAction(i)} onClick={() => this.performAction(i)}
key={"submission" + i + this.segments[i].category + this.idSuffix}> key={"submission" + i + this.segments[i].category + this.idSuffix}>
{(i + 1) + ". " + chrome.i18n.getMessage("category_" + this.segments[i].category)} {(i + 1) + ". " + chrome.i18n.getMessage("category_" + this.segments[i].category)}
</button> </button>
); );
} }
return elements; return elements;
} }
submissionChooserOpacitySelector(index: number): number {
const isUpvote = this.state.actionState === SkipNoticeAction.Upvote;
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
const shouldBeGray: boolean= isUpvote && this.state.voted[index] == SkipNoticeAction.Upvote ||
isDownvote && this.state.voted[index] == SkipNoticeAction.Downvote ||
isCopyDownvote && this.state.copied[index] == SkipNoticeAction.CopyDownvote;
return shouldBeGray ? 0.35 : 1;
}
submissionChooserColorSelector(index: number): string {
const isDownvote = this.state.actionState == SkipNoticeAction.Downvote;
const isCopyDownvote = this.state.actionState == SkipNoticeAction.CopyDownvote;
const shouldWarnUser: boolean = (isDownvote || isCopyDownvote)
&& this.segments[index].locked === true;
return (shouldWarnUser) ? this.lockedColor : this.unselectedColor;
}
onMouseEnter(): void { onMouseEnter(): void {
if (this.state.smaller) { if (this.state.smaller) {
this.setState({ this.setState({
@@ -541,19 +553,22 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getCategoryOptions(): React.ReactElement[] { getCategoryOptions(): React.ReactElement[] {
const elements = []; const elements = [];
const categories = CompileConfig.categoryList.filter((cat => getCategoryActionType(cat as Category) === CategoryActionType.Skippable)); const categories = (CompileConfig.categoryList.filter((cat => getCategoryActionType(cat as Category) === CategoryActionType.Skippable))) as Category[];
for (const category of categories) { for (const category of categories) {
elements.push( elements.push(
<option value={category} <option value={category}
key={category}> key={category}>
{chrome.i18n.getMessage("category_" + category)} {this.categoryVoteButtonLockIcon(category) + chrome.i18n.getMessage("category_" + category)}
</option> </option>
); );
} }
return elements; return elements;
} }
categoryVoteButtonLockIcon(category: Category): string {
return (this.contentContainer().lockedCategories.includes(category)) ? "🔒" : " ";
}
unskip(index: number): void { unskip(index: number): void {
this.contentContainer().unskipSponsorTime(this.segments[index], this.props.unskipTime); this.contentContainer().unskipSponsorTime(this.segments[index], this.props.unskipTime);
@@ -699,6 +714,16 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
}) })
} }
downvoteButtonColor(downvoteType: SkipNoticeAction): string {
// Also used for "Copy and Downvote"
if (this.segments.length > 1) {
return (this.state.actionState === downvoteType) ? this.selectedColor : this.unselectedColor;
} else {
// You dont have segment selectors so the lockbutton needs to be colored and cannot be selected.
return (this.segments[0].locked === true) ? this.lockedColor : this.unselectedColor;
}
}
private getUnskipText(): string { private getUnskipText(): string {
switch (this.props.segments[0].actionType) { switch (this.props.segments[0].actionType) {
case ActionType.Mute: { case ActionType.Mute: {

View File

@@ -3,7 +3,9 @@ import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, P
interface SBConfig { interface SBConfig {
userID: string, userID: string,
/** Contains unsubmitted segments that the user has created. */ isVip: boolean,
lastIsVipUpdate: number,
/* Contains unsubmitted segments that the user has created. */
segmentTimes: SBMap<string, SponsorTime[]>, segmentTimes: SBMap<string, SponsorTime[]>,
defaultCategory: Category, defaultCategory: Category,
whitelistedChannels: string[], whitelistedChannels: string[],
@@ -153,6 +155,8 @@ const Config: SBObject = {
configListeners: [], configListeners: [],
defaults: { defaults: {
userID: null, userID: null,
isVip: false,
lastIsVipUpdate: 0,
segmentTimes: new SBMap("segmentTimes"), segmentTimes: new SBMap("segmentTimes"),
defaultCategory: "chooseACategory" as Category, defaultCategory: "chooseACategory" as Category,
whitelistedChannels: [], whitelistedChannels: [],
@@ -214,7 +218,8 @@ const Config: SBObject = {
colorPalette: new SBMap("colorPalette", [ colorPalette: new SBMap("colorPalette", [
["SponsorBlockRed", "#780303"], ["SponsorBlockRed", "#780303"],
["SponsorBlockWhite", "#ffffff"] ["SponsorBlockWhite", "#ffffff"],
["SponsorBlockLocked", "#ffc83d"]
]), ]),
// Preview bar // Preview bar

View File

@@ -34,8 +34,10 @@ let lastPOISkip = 0;
// JSON video info // JSON video info
let videoInfo: VideoInfo = null; let videoInfo: VideoInfo = null;
//the channel this video is about // The channel this video is about
let channelIDInfo: ChannelIDInfo; let channelIDInfo: ChannelIDInfo;
// Locked Categories in this tab, like: ["sponsor","intro","outro"]
let lockedCategories: Category[] = [];
// Skips are scheduled to ensure precision. // Skips are scheduled to ensure precision.
// Skips are rescheduled every seeking event. // Skips are rescheduled every seeking event.
@@ -121,7 +123,8 @@ const skipNoticeContentContainer: ContentContainer = () => ({
updateEditButtonsOnPlayer, updateEditButtonsOnPlayer,
previewTime, previewTime,
videoInfo, videoInfo,
getRealCurrentTime: getRealCurrentTime getRealCurrentTime: getRealCurrentTime,
lockedCategories
}); });
// value determining when to count segment as skipped and send telemetry to server (percent based) // value determining when to count segment as skipped and send telemetry to server (percent based)
@@ -752,6 +755,62 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
sponsorLookupRetries++; sponsorLookupRetries++;
} }
// Look up locked status if the user is a vip
isVipLookup();
const isVip = Config.config.isVip;
if (isVip) {
lockedCategoriesLookup(id);
lockedSegmentsLookup()
}
}
async function isVipLookup() {
const currentTime = Date.now();
const lastUpdate = Config.config.lastIsVipUpdate;
if (currentTime - lastUpdate > 1000*60*60*24) { //max every 24 hours 1000*60*60*24
Config.config.lastIsVipUpdate = currentTime;
utils.sendRequestToServer("GET", "/api/isUserVIP?userID=" + Config.config.userID,
(response) => {
if (response.status === 200 && response.ok) {
console.log(JSON.parse(response.responseText).vip);
console.log(Config.config.userID);
if (JSON.parse(response.responseText).vip === true) {
Config.config.isVip = true;
}
else Config.config.isVip = false;
}
}
)
}
}
async function lockedSegmentsLookup() {
let url = ""
for (let i = 0; i < sponsorTimes.length; i++) {
if (i !== 0) url += ",";
url += `"` + sponsorTimes[i].UUID + `"`;
}
utils.sendRequestToServer("GET", "/api/segmentInfo?UUIDs=[" + url + "]",
(response) => {
if (response.status === 200 && response.ok) {
for (let i = 0; i < sponsorTimes.length && i < 10; i++) { //because the api only return 10 segments maximum
sponsorTimes[i].locked = (JSON.parse(response.responseText)[i].locked === 1) ? true : false;
}
}
}
)
}
async function lockedCategoriesLookup(id: string) {
utils.sendRequestToServer("GET", "/api/lockCategories?videoID=" + id,
(response) => {
if (response.status === 200 && response.ok) {
for (const category of JSON.parse(response.responseText).categories) {
lockedCategories.push(category);
}
}
}
)
} }
function retryFetch(): void { function retryFetch(): void {

View File

@@ -20,7 +20,8 @@ export interface ContentContainer {
updateEditButtonsOnPlayer: () => void, updateEditButtonsOnPlayer: () => void,
previewTime: (time: number, unpause?: boolean) => void, previewTime: (time: number, unpause?: boolean) => void,
videoInfo: VideoInfo, videoInfo: VideoInfo,
getRealCurrentTime: () => number getRealCurrentTime: () => number,
lockedCategories: string[]
} }
} }
@@ -74,6 +75,7 @@ export enum SponsorSourceType {
export interface SponsorTime { export interface SponsorTime {
segment: [number] | [number, number]; segment: [number] | [number, number];
UUID: SegmentUUID; UUID: SegmentUUID;
locked?: boolean;
category: Category; category: Category;
actionType: ActionType; actionType: ActionType;