Add submitting for highlight category

This commit is contained in:
Ajay Ramachandran
2021-04-05 23:35:05 -04:00
parent edcda31db4
commit a08dbf4da1
11 changed files with 143 additions and 170 deletions

View File

@@ -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 connect to", "serverAddressComment": "This specifies the default SponsorBlock server to connect to",
"categoryList": ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic"] "categoryList": ["sponsor", "selfpromo", "interaction", "intro", "outro", "preview", "music_offtopic", "highlight"]
} }

View File

@@ -335,9 +335,6 @@
"createdBy": { "createdBy": {
"message": "Created By" "message": "Created By"
}, },
"autoSkip": {
"message": "Auto Skip"
},
"showSkipNotice": { "showSkipNotice": {
"message": "Show Notice After A Segment Is Skipped" "message": "Show Notice After A Segment Is Skipped"
}, },
@@ -534,14 +531,20 @@
"category_music_offtopic_short": { "category_music_offtopic_short": {
"message": "Non-Music" "message": "Non-Music"
}, },
"category_highlight": {
"message": "Highlight"
},
"category_highlight_description": {
"message": "The part of the video that most people are looking for. Similar to \"Video starts at x\" comments."
},
"category_livestream_messages": { "category_livestream_messages": {
"message": "Livestream: Donation/Message Readings" "message": "Livestream: Donation/Message Readings"
}, },
"category_livestream_messages_short": { "category_livestream_messages_short": {
"message": "Message Reading" "message": "Message Reading"
}, },
"disable": { "autoSkip": {
"message": "Disable" "message": "Auto Skip"
}, },
"manualSkip": { "manualSkip": {
"message": "Manual Skip" "message": "Manual Skip"
@@ -549,6 +552,18 @@
"showOverlay": { "showOverlay": {
"message": "Show In Seek Bar" "message": "Show In Seek Bar"
}, },
"disable": {
"message": "Disable"
},
"autoSkip_POI": {
"message": "Auto skip to the start"
},
"manualSkip_POI": {
"message": "Ask when video loads"
},
"showOverlay_POI": {
"message": "Show In Seek Bar"
},
"colorFormatIncorrect": { "colorFormatIncorrect": {
"message": "Your color is formatted incorrectly. It should be a 3 or 6 digit hex code with a number sign at the beginning." "message": "Your color is formatted incorrectly. It should be a 3 or 6 digit hex code with a number sign at the beginning."
}, },

View File

@@ -1,6 +1,7 @@
import * as React from "react"; import * as React from "react";
import * as CompileConfig from "../../config.json"; import * as CompileConfig from "../../config.json";
import { Category } from "../types";
import CategorySkipOptionsComponent from "./CategorySkipOptionsComponent"; import CategorySkipOptionsComponent from "./CategorySkipOptionsComponent";
export interface CategoryChooserProps { export interface CategoryChooserProps {
@@ -58,7 +59,7 @@ class CategoryChooserComponent extends React.Component<CategoryChooserProps, Cat
for (const category of CompileConfig.categoryList) { for (const category of CompileConfig.categoryList) {
elements.push( elements.push(
<CategorySkipOptionsComponent category={category} <CategorySkipOptionsComponent category={category as Category}
key={category}> key={category}>
</CategorySkipOptionsComponent> </CategorySkipOptionsComponent>
); );

View File

@@ -1,10 +1,13 @@
import * as React from "react"; import * as React from "react";
import Config from "../config" import Config from "../config"
import { CategorySkipOption } from "../types"; import { Category, CategorySkipOption } from "../types";
import Utils from "../utils";
const utils = new Utils();
export interface CategorySkipOptionsProps { export interface CategorySkipOptionsProps {
category: string; category: Category;
defaultColor?: string; defaultColor?: string;
defaultPreviewColor?: string; defaultPreviewColor?: string;
} }
@@ -146,10 +149,13 @@ class CategorySkipOptionsComponent extends React.Component<CategorySkipOptionsPr
const optionNames = ["disable", "showOverlay", "manualSkip", "autoSkip"]; const optionNames = ["disable", "showOverlay", "manualSkip", "autoSkip"];
console.log(utils.getCategoryActionType(this.props.category))
for (const optionName of optionNames) { for (const optionName of optionNames) {
elements.push( elements.push(
<option key={optionName} value={optionName}> <option key={optionName} value={optionName}>
{chrome.i18n.getMessage(optionName)} {chrome.i18n.getMessage(optionName !== "disable" ? optionName + utils.getCategoryActionType(this.props.category)
: optionName)}
</option> </option>
); );
} }

View File

@@ -1,10 +1,13 @@
import * as React from "react"; import * as React from "react";
import * as CompileConfig from "../../config.json"; import * as CompileConfig from "../../config.json";
import Config from "../config" import Config from "../config"
import { ContentContainer, SponsorHideType, SponsorTime } from "../types"; import { Category, ContentContainer, CategoryActionType, SponsorHideType, SponsorTime } from "../types";
import NoticeComponent from "./NoticeComponent"; import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
import Utils from "../utils";
const utils = new Utils();
export enum SkipNoticeAction { export enum SkipNoticeAction {
None, None,
Upvote, Upvote,
@@ -342,7 +345,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
this.contentContainer().vote(0, this.segments[index].UUID, undefined, this); this.contentContainer().vote(0, this.segments[index].UUID, undefined, this);
break; break;
case SkipNoticeAction.CategoryVote: case SkipNoticeAction.CategoryVote:
this.contentContainer().vote(undefined, this.segments[index].UUID, this.categoryOptionRef.current.value, this) this.contentContainer().vote(undefined, this.segments[index].UUID, this.categoryOptionRef.current.value as Category, this)
break; break;
case SkipNoticeAction.Unskip: case SkipNoticeAction.Unskip:
this.state.unskipCallback(index); this.state.unskipCallback(index);
@@ -389,7 +392,8 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getCategoryOptions(): React.ReactElement[] { getCategoryOptions(): React.ReactElement[] {
const elements = []; const elements = [];
for (const category of Config.config.categorySelections) { const categories = Config.config.categorySelections.filter((cat => utils.getCategoryActionType(cat.name as Category) === CategoryActionType.Skippable));
for (const category of categories) {
elements.push( elements.push(
<option value={category.name} <option value={category.name}
key={category.name}> key={category.name}>
@@ -476,7 +480,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
}); });
} }
afterVote(segment: SponsorTime, type: number, category: string): void { afterVote(segment: SponsorTime, type: number, category: Category): void {
this.addVoteButtonInfo(chrome.i18n.getMessage("voted")); this.addVoteButtonInfo(chrome.i18n.getMessage("voted"));
if (type === 0) { if (type === 0) {

View File

@@ -4,7 +4,7 @@ import Config from "../config";
import * as CompileConfig from "../../config.json"; import * as CompileConfig from "../../config.json";
import Utils from "../utils"; import Utils from "../utils";
import { ContentContainer, SponsorTime } from "../types"; import { Category, CategoryActionType, ContentContainer, SponsorTime } from "../types";
import SubmissionNoticeComponent from "./SubmissionNoticeComponent"; import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
const utils = new Utils(); const utils = new Utils();
@@ -16,6 +16,7 @@ export interface SponsorTimeEditProps {
contentContainer: ContentContainer, contentContainer: ContentContainer,
submissionNotice: SubmissionNoticeComponent; submissionNotice: SubmissionNoticeComponent;
categoryList?: Category[];
} }
export interface SponsorTimeEditState { export interface SponsorTimeEditState {
@@ -106,13 +107,15 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
onChange={(e) => { onChange={(e) => {
const sponsorTimeEdits = this.state.sponsorTimeEdits; const sponsorTimeEdits = this.state.sponsorTimeEdits;
sponsorTimeEdits[0] = e.target.value; sponsorTimeEdits[0] = e.target.value;
if (utils.getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits}); this.setState({sponsorTimeEdits});
this.saveEditTimes(); this.saveEditTimes();
}}> }}>
</input> </input>
{utils.getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable ? (
<span>
<span> <span>
{" " + chrome.i18n.getMessage("to") + " "} {" " + chrome.i18n.getMessage("to") + " "}
</span> </span>
@@ -143,6 +146,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
onClick={() => this.setTimeToEnd()}> onClick={() => this.setTimeToEnd()}>
{chrome.i18n.getMessage("bracketEnd")} {chrome.i18n.getMessage("bracketEnd")}
</span> </span>
</span>
): ""}
</div> </div>
); );
} else { } else {
@@ -151,7 +156,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
className="sponsorTimeDisplay" className="sponsorTimeDisplay"
onClick={this.toggleEditTime.bind(this)}> onClick={this.toggleEditTime.bind(this)}>
{utils.getFormattedTime(segment[0], true) + {utils.getFormattedTime(segment[0], true) +
((!isNaN(segment[1])) ? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")} ((!isNaN(segment[1]) && utils.getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable)
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
</div> </div>
); );
} }
@@ -190,7 +196,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
{chrome.i18n.getMessage("delete")} {chrome.i18n.getMessage("delete")}
</span> </span>
{(!isNaN(segment[1])) ? ( {(!isNaN(segment[1]) && utils.getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable) ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix} <span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton" className="sponsorTimeEditButton"
onClick={this.previewTime.bind(this)}> onClick={this.previewTime.bind(this)}>
@@ -225,7 +231,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
</option> </option>
)]; )];
for (const category of CompileConfig.categoryList) { for (const category of (this.props.categoryList ?? CompileConfig.categoryList)) {
elements.push( elements.push(
<option value={category} <option value={category}
key={category}> key={category}>
@@ -253,6 +259,10 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
return; return;
} }
if (utils.getCategoryActionType(event.target.value as Category) === CategoryActionType.POI) {
this.setTimeTo(1, null);
}
this.saveEditTimes(); this.saveEditTimes();
} }
@@ -264,11 +274,16 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.setTimeTo(1, this.props.contentContainer().v.duration); this.setTimeTo(1, this.props.contentContainer().v.duration);
} }
/**
* @param index
* @param time If null, will set time to the first index's time
*/
setTimeTo(index: number, time: number): void { setTimeTo(index: number, time: number): void {
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
if (time === null) time = sponsorTime.segment[0];
sponsorTime.segment[index] = sponsorTime.segment[index] = time;
time; if (utils.getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTime.segment[1] = time;
this.setState({ this.setState({
sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime) sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime)
@@ -312,7 +327,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
} }
sponsorTimesSubmitting[this.props.index].category = this.categoryOptionRef.current.value; sponsorTimesSubmitting[this.props.index].category = this.categoryOptionRef.current.value as Category;
Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting); Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting);

View File

@@ -1,13 +1,10 @@
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
import { CategorySelection, CategorySkipOption, PreviewBarOption, SponsorTime, StorageChangesObject, UnEncodedSegmentTimes as UnencodedSegmentTimes } from "./types"; import { Category, CategorySelection, CategorySkipOption, PreviewBarOption, SponsorTime, StorageChangesObject, UnEncodedSegmentTimes as UnencodedSegmentTimes } from "./types";
import Utils from "./utils";
const utils = new Utils();
interface SBConfig { interface SBConfig {
userID: string, userID: string,
segmentTimes: SBMap<string, SponsorTime[]>, segmentTimes: SBMap<string, SponsorTime[]>,
defaultCategory: string, defaultCategory: Category,
whitelistedChannels: string[], whitelistedChannels: string[],
forceChannelCheck: boolean, forceChannelCheck: boolean,
skipKeybind: string, skipKeybind: string,
@@ -57,6 +54,8 @@ interface SBConfig {
"preview-preview": PreviewBarOption, "preview-preview": PreviewBarOption,
"music_offtopic": PreviewBarOption, "music_offtopic": PreviewBarOption,
"preview-music_offtopic": PreviewBarOption, "preview-music_offtopic": PreviewBarOption,
"highlight": PreviewBarOption,
"preview-highlight": PreviewBarOption,
} }
} }
@@ -142,7 +141,7 @@ const Config: SBObject = {
defaults: { defaults: {
userID: null, userID: null,
segmentTimes: new SBMap("segmentTimes"), segmentTimes: new SBMap("segmentTimes"),
defaultCategory: "chooseACategory", defaultCategory: "chooseACategory" as Category,
whitelistedChannels: [], whitelistedChannels: [],
forceChannelCheck: false, forceChannelCheck: false,
skipKeybind: "Enter", skipKeybind: "Enter",
@@ -173,7 +172,7 @@ const Config: SBObject = {
refetchWhenNotFound: true, refetchWhenNotFound: true,
categorySelections: [{ categorySelections: [{
name: "sponsor", name: "sponsor" as Category,
option: CategorySkipOption.AutoSkip option: CategorySkipOption.AutoSkip
}], }],
@@ -238,6 +237,14 @@ const Config: SBObject = {
"preview-music_offtopic": { "preview-music_offtopic": {
color: "#a6634a", color: "#a6634a",
opacity: "0.7" opacity: "0.7"
},
"highlight": {
color: "#ff1684",
opacity: "0.7"
},
"preview-highlight": {
color: "#9b044c",
opacity: "0.7"
} }
} }
}, },
@@ -334,108 +341,15 @@ function fetchConfig(): Promise<void> {
} }
function migrateOldFormats(config: SBConfig) { function migrateOldFormats(config: SBConfig) {
if (config["disableAutoSkip"]) { if (!config["highlightCategoryAdded"] && !config.categorySelections.some((s) => s.name === "highlight")) {
for (const selection of config.categorySelections) { config["highlightCategoryAdded"] = true;
if (selection.name === "sponsor") {
selection.option = CategorySkipOption.ManualSkip;
chrome.storage.sync.remove("disableAutoSkip"); config.categorySelections.push({
} name: "highlight" as Category,
} option: CategorySkipOption.AutoSkip
} });
// Auto vote removal
if (config["autoUpvote"]) {
chrome.storage.sync.remove("autoUpvote");
}
// mobileUpdateShowCount removal
if (config["mobileUpdateShowCount"] !== undefined) {
chrome.storage.sync.remove("mobileUpdateShowCount");
}
// categoryUpdateShowCount removal
if (config["categoryUpdateShowCount"] !== undefined) {
chrome.storage.sync.remove("categoryUpdateShowCount");
}
// Channel URLS
if (config.whitelistedChannels.length > 0 &&
(config.whitelistedChannels[0] == null || config.whitelistedChannels[0].includes("/"))) {
const channelURLFixer = async() => {
const newChannelList: string[] = [];
for (const item of config.whitelistedChannels) {
if (item != null) {
if (item.includes("/channel/")) {
newChannelList.push(item.split("/")[2]);
} else if (item.includes("/user/") && utils.isContentScript()) {
// Replace channel URL with channelID
const response = await utils.asyncRequestToCustomServer("GET", "https://sponsor.ajay.app/invidious/api/v1/channels/" + item.split("/")[2] + "?fields=authorId");
if (response.ok) {
newChannelList.push((JSON.parse(response.responseText)).authorId);
} else {
// Add it at the beginning so it gets converted later
newChannelList.unshift(item);
}
} else if (item.includes("/user/")) {
// Add it at the beginning so it gets converted later (The API can only be called in the content script due to CORS issues)
newChannelList.unshift(item);
} else {
newChannelList.push(item);
}
}
}
config.whitelistedChannels = newChannelList;
}
channelURLFixer();
}
// Check if off-topic category needs to be removed
for (let i = 0; i < config.categorySelections.length; i++) {
if (config.categorySelections[i].name === "offtopic") {
config.categorySelections.splice(i, 1);
// Call set listener
config.categorySelections = config.categorySelections; config.categorySelections = config.categorySelections;
break;
}
}
// Migrate old "sponsorTimes"
if (config["sponsorTimes"]) {
let jsonData: unknown = config["sponsorTimes"];
// Check if data is stored in the old format for SBMap (a JSON string)
if (typeof jsonData === "string") {
try {
jsonData = JSON.parse(jsonData);
} catch(e) {
// Continue normally (out of this if statement)
}
}
// Otherwise junk data
if (Array.isArray(jsonData)) {
const oldMap = new Map(jsonData);
oldMap.forEach((sponsorTimes: number[][], key) => {
const segmentTimes: SponsorTime[] = [];
for (const segment of sponsorTimes) {
segmentTimes.push({
segment: segment,
category: "sponsor",
UUID: null
});
}
config.segmentTimes.rawSet(key, segmentTimes);
});
config.segmentTimes.update();
}
chrome.storage.sync.remove("sponsorTimes");
} }
} }

View File

@@ -1,6 +1,6 @@
import Config from "./config"; import Config from "./config";
import { SponsorTime, CategorySkipOption, VideoID, SponsorHideType, FetchResponse, VideoInfo, StorageChangesObject } from "./types"; import { SponsorTime, CategorySkipOption, VideoID, SponsorHideType, FetchResponse, VideoInfo, StorageChangesObject, CategoryActionType, SegmentUUID, Category } from "./types";
import { ContentContainer } from "./types"; import { ContentContainer } from "./types";
import Utils from "./utils"; import Utils from "./utils";
@@ -691,14 +691,16 @@ function startSkipScheduleCheckingForStartSponsors() {
// See if there are any starting sponsors // See if there are any starting sponsors
let startingSponsor = -1; let startingSponsor = -1;
for (const time of sponsorTimes) { for (const time of sponsorTimes) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) { if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime
&& utils.getCategoryActionType(time.category) === CategoryActionType.Skippable) {
startingSponsor = time.segment[0]; startingSponsor = time.segment[0];
break; break;
} }
} }
if (startingSponsor === -1) { if (startingSponsor === -1) {
for (const time of sponsorTimesSubmitting) { for (const time of sponsorTimesSubmitting) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime) { if (time.segment[0] <= video.currentTime && time.segment[0] > startingSponsor && time.segment[1] > video.currentTime
&& utils.getCategoryActionType(time.category) === CategoryActionType.Skippable) {
startingSponsor = time.segment[0]; startingSponsor = time.segment[0];
break; break;
} }
@@ -959,7 +961,8 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments:
|| ((includeNonIntersectingSegments && sponsorTimes[i].segment[0] >= minimum) || ((includeNonIntersectingSegments && sponsorTimes[i].segment[0] >= minimum)
|| (includeIntersectingSegments && sponsorTimes[i].segment[0] < minimum && sponsorTimes[i].segment[1] > minimum))) || (includeIntersectingSegments && sponsorTimes[i].segment[0] < minimum && sponsorTimes[i].segment[1] > minimum)))
&& (!onlySkippableSponsors || utils.getCategorySelection(sponsorTimes[i].category).option !== CategorySkipOption.ShowOverlay) && (!onlySkippableSponsors || utils.getCategorySelection(sponsorTimes[i].category).option !== CategorySkipOption.ShowOverlay)
&& (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible)) { && (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible)
&& utils.getCategoryActionType(sponsorTimes[i].category) === CategoryActionType.Skippable) {
startTimes.push(sponsorTimes[i].segment[0]); startTimes.push(sponsorTimes[i].segment[0]);
} }
@@ -1031,11 +1034,9 @@ function skipToTime(v: HTMLVideoElement, skipTime: number[], skippingSegments: S
} }
function unskipSponsorTime(segment: SponsorTime) { function unskipSponsorTime(segment: SponsorTime) {
if (sponsorTimes != null) {
//add a tiny bit of time to make sure it is not skipped again //add a tiny bit of time to make sure it is not skipped again
video.currentTime = segment.segment[0] + 0.001; video.currentTime = segment.segment[0] + 0.001;
} }
}
function reskipSponsorTime(segment: SponsorTime) { function reskipSponsorTime(segment: SponsorTime) {
video.currentTime = segment.segment[1]; video.currentTime = segment.segment[1];
@@ -1353,7 +1354,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: number, UUID: string, category?: string, skipNotice?: SkipNoticeComponent) { function vote(type: number, UUID: SegmentUUID, category?: Category, skipNotice?: SkipNoticeComponent) {
if (skipNotice !== null && skipNotice !== undefined) { if (skipNotice !== null && skipNotice !== undefined) {
//add loading info //add loading info
skipNotice.addVoteButtonInfo.bind(skipNotice)(chrome.i18n.getMessage("Loading")) skipNotice.addVoteButtonInfo.bind(skipNotice)(chrome.i18n.getMessage("Loading"))

View File

@@ -198,7 +198,7 @@ class PreviewBar {
if (!this.onMobileYouTube) bar.style.opacity = Config.config.barTypes[barSegmentType].opacity; if (!this.onMobileYouTube) bar.style.opacity = Config.config.barTypes[barSegmentType].opacity;
bar.style.position = "absolute"; bar.style.position = "absolute";
bar.style.width = this.timeToPercentage(segment[1] - segment[0]); if (segment[1] - segment[0] > 0) bar.style.width = this.timeToPercentage(segment[1] - segment[0]);
bar.style.left = this.timeToPercentage(segment[0]); bar.style.left = this.timeToPercentage(segment[0]);
return bar; return bar;

View File

@@ -4,7 +4,7 @@ import SkipNotice from "./render/SkipNotice";
export interface ContentContainer { export interface ContentContainer {
(): { (): {
vote: (type: number, UUID: string, category?: string, skipNotice?: SkipNoticeComponent) => void, vote: (type: number, UUID: SegmentUUID, category?: Category, skipNotice?: SkipNoticeComponent) => void,
dontShowNoticeAgain: () => void, dontShowNoticeAgain: () => void,
unskipSponsorTime: (segment: SponsorTime) => void, unskipSponsorTime: (segment: SponsorTime) => void,
sponsorTimes: SponsorTime[], sponsorTimes: SponsorTime[],
@@ -41,7 +41,7 @@ export enum CategorySkipOption {
} }
export interface CategorySelection { export interface CategorySelection {
name: string; name: Category;
option: CategorySkipOption option: CategorySkipOption
} }
@@ -51,11 +51,19 @@ export enum SponsorHideType {
MinimumDuration MinimumDuration
} }
export enum CategoryActionType {
Skippable = "", // Strings are used to find proper language configs
POI = "_POI"
}
export type SegmentUUID = string & { __segmentUUIDBrand: unknown };
export type Category = string & { __categoryBrand: unknown };
export interface SponsorTime { export interface SponsorTime {
segment: number[]; segment: number[];
UUID: string; UUID: SegmentUUID;
category: string; category: Category;
hidden?: SponsorHideType; hidden?: SponsorHideType;
} }
@@ -145,7 +153,7 @@ export interface VideoInfo {
isUnlisted: boolean, isUnlisted: boolean,
hasYpcMetadata: boolean, hasYpcMetadata: boolean,
viewCount: string, viewCount: string,
category: string, category: Category,
publishDate: string, publishDate: string,
ownerChannelName: string, ownerChannelName: string,
uploadDate: string, uploadDate: string,

View File

@@ -1,5 +1,5 @@
import Config from "./config"; import Config from "./config";
import { CategorySelection, SponsorTime, FetchResponse, BackgroundScriptContainer, Registration } from "./types"; import { CategorySelection, SponsorTime, FetchResponse, BackgroundScriptContainer, Registration, Category, CategoryActionType } from "./types";
import * as CompileConfig from "../config.json"; import * as CompileConfig from "../config.json";
@@ -43,6 +43,15 @@ export default class Utils {
}); });
} }
getCategoryActionType(category: Category): CategoryActionType {
switch (category) {
case "highlight":
return CategoryActionType.POI;
default:
return CategoryActionType.Skippable;
}
}
containsPermission(permissions: chrome.permissions.Permissions): Promise<boolean> { containsPermission(permissions: chrome.permissions.Permissions): Promise<boolean> {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.permissions.contains(permissions, resolve) chrome.permissions.contains(permissions, resolve)