diff --git a/src/components/SkipNoticeComponent.tsx b/src/components/SkipNoticeComponent.tsx index 775ab42f..eaca2b42 100644 --- a/src/components/SkipNoticeComponent.tsx +++ b/src/components/SkipNoticeComponent.tsx @@ -83,6 +83,7 @@ class SkipNoticeComponent extends React.Component void; @@ -117,6 +118,7 @@ class SkipNoticeComponent extends React.Component this.prepAction(SkipNoticeAction.Downvote)}> - + {/* Copy and Downvote Button */} @@ -290,8 +292,7 @@ class SkipNoticeComponent extends React.Component this.prepAction(SkipNoticeAction.CopyDownvote)}> {chrome.i18n.getMessage("CopyAndDownvote")} @@ -315,7 +316,7 @@ class SkipNoticeComponent extends React.Component {this.getCategoryOptions()} @@ -366,27 +367,38 @@ class SkipNoticeComponent extends React.Component this.performAction(i)} key={"submission" + i + this.segments[i].category + this.idSuffix}> {(i + 1) + ". " + chrome.i18n.getMessage("category_" + this.segments[i].category)} ); } - 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 { if (this.state.smaller) { this.setState({ @@ -541,19 +553,22 @@ class SkipNoticeComponent extends React.Component 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) { elements.push( ); } - return elements; } + categoryVoteButtonLockIcon(category: Category): string { + return (this.contentContainer().lockedCategories.includes(category)) ? "🔒" : " "; + } + unskip(index: number): void { this.contentContainer().unskipSponsorTime(this.segments[index], this.props.unskipTime); @@ -699,6 +714,16 @@ class SkipNoticeComponent extends React.Component 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 { switch (this.props.segments[0].actionType) { case ActionType.Mute: { diff --git a/src/config.ts b/src/config.ts index 43345107..f077d8eb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,7 +3,9 @@ import { Category, CategorySelection, CategorySkipOption, NoticeVisbilityMode, P interface SBConfig { userID: string, - /** Contains unsubmitted segments that the user has created. */ + isVip: boolean, + lastIsVipUpdate: number, + /* Contains unsubmitted segments that the user has created. */ segmentTimes: SBMap, defaultCategory: Category, whitelistedChannels: string[], @@ -153,6 +155,8 @@ const Config: SBObject = { configListeners: [], defaults: { userID: null, + isVip: false, + lastIsVipUpdate: 0, segmentTimes: new SBMap("segmentTimes"), defaultCategory: "chooseACategory" as Category, whitelistedChannels: [], @@ -214,7 +218,8 @@ const Config: SBObject = { colorPalette: new SBMap("colorPalette", [ ["SponsorBlockRed", "#780303"], - ["SponsorBlockWhite", "#ffffff"] + ["SponsorBlockWhite", "#ffffff"], + ["SponsorBlockLocked", "#ffc83d"] ]), // Preview bar diff --git a/src/content.ts b/src/content.ts index b2ea4342..3fc942d8 100644 --- a/src/content.ts +++ b/src/content.ts @@ -34,8 +34,10 @@ let lastPOISkip = 0; // JSON video info let videoInfo: VideoInfo = null; -//the channel this video is about +// The channel this video is about let channelIDInfo: ChannelIDInfo; +// Locked Categories in this tab, like: ["sponsor","intro","outro"] +let lockedCategories: Category[] = []; // Skips are scheduled to ensure precision. // Skips are rescheduled every seeking event. @@ -121,7 +123,8 @@ const skipNoticeContentContainer: ContentContainer = () => ({ updateEditButtonsOnPlayer, previewTime, videoInfo, - getRealCurrentTime: getRealCurrentTime + getRealCurrentTime: getRealCurrentTime, + lockedCategories }); // 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++; } + // 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 { diff --git a/src/types.ts b/src/types.ts index c60e52bb..4ffdf33f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,7 +20,8 @@ export interface ContentContainer { updateEditButtonsOnPlayer: () => void, previewTime: (time: number, unpause?: boolean) => void, videoInfo: VideoInfo, - getRealCurrentTime: () => number + getRealCurrentTime: () => number, + lockedCategories: string[] } } @@ -74,6 +75,7 @@ export enum SponsorSourceType { export interface SponsorTime { segment: [number] | [number, number]; UUID: SegmentUUID; + locked?: boolean; category: Category; actionType: ActionType;