Merge branch 'master' into settings

This commit is contained in:
Ajay Ramachandran
2022-01-24 23:27:52 -05:00
committed by GitHub
8 changed files with 102 additions and 94 deletions

View File

@@ -13,7 +13,7 @@
"preview": ["skip", "mute"], "preview": ["skip", "mute"],
"filler": ["skip", "mute"], "filler": ["skip", "mute"],
"music_offtopic": ["skip"], "music_offtopic": ["skip"],
"poi_highlight": ["skip"] "poi_highlight": ["poi"]
}, },
"wikiLinks": { "wikiLinks": {
"sponsor": "https://wiki.sponsor.ajay.app/w/Sponsor", "sponsor": "https://wiki.sponsor.ajay.app/w/Sponsor",

View File

@@ -243,7 +243,7 @@
"message": "All Faded Skip Notices" "message": "All Faded Skip Notices"
}, },
"longDescription": { "longDescription": {
"message": "SponsorBlock lets you skip over sponsors, intros, outros, subscription reminders, and other annoying parts of YouTube videos. SponsorBlock is a crowdsourced browser extension that let's anyone submit the start and end time's of sponsored segments and other segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. You can also skip over non music sections of music videos.", "message": "SponsorBlock lets you skip over sponsors, intros, outros, subscription reminders, and other annoying parts of YouTube videos. SponsorBlock is a crowdsourced browser extension that lets anyone submit the start and end times of sponsored segments and other segments of YouTube videos. Once one person submits this information, everyone else with this extension will skip right over the sponsored segment. You can also skip over non music sections of music videos.",
"description": "Full description of the extension on the store pages." "description": "Full description of the extension on the store pages."
}, },
"website": { "website": {
@@ -432,7 +432,7 @@
"message": "Skip notice duration (seconds):" "message": "Skip notice duration (seconds):"
}, },
"skipNoticeDurationDescription": { "skipNoticeDurationDescription": {
"message": "The skip notice will stay on screen for at least this long. For manual skipping, it may be visible for longer." "message": "The skip notice will stay on screen for at least this many seconds. For manual skipping, it may be visible for longer."
}, },
"shortCheck": { "shortCheck": {
"message": "The following submission is shorter than your minimum duration option. This could mean that this is already submitted, and just being ignored due to this option. Are you sure you would like to submit?" "message": "The following submission is shorter than your minimum duration option. This could mean that this is already submitted, and just being ignored due to this option. Are you sure you would like to submit?"

View File

@@ -1,12 +1,11 @@
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 { Category, ContentContainer, CategoryActionType, SponsorHideType, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types"; import { Category, ContentContainer, SponsorHideType, SponsorTime, NoticeVisbilityMode, ActionType, SponsorSourceType, SegmentUUID } from "../types";
import NoticeComponent from "./NoticeComponent"; import NoticeComponent from "./NoticeComponent";
import NoticeTextSelectionComponent from "./NoticeTextSectionComponent"; import NoticeTextSelectionComponent from "./NoticeTextSectionComponent";
import Utils from "../utils"; import Utils from "../utils";
const utils = new Utils(); const utils = new Utils();
import { getCategoryActionType, getSkippingText } from "../utils/categoryUtils"; import { getCategoryActionType, getSkippingText } from "../utils/categoryUtils";
import { keybindToString } from "../utils/configUtils"; import { keybindToString } from "../utils/configUtils";
@@ -327,7 +326,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
getSkipButton(): JSX.Element { getSkipButton(): JSX.Element {
if (this.state.showSkipButton && (this.segments.length > 1 if (this.state.showSkipButton && (this.segments.length > 1
|| getCategoryActionType(this.segments[0].category) !== CategoryActionType.POI || this.segments[0].actionType !== ActionType.Poi
|| this.props.unskipTime)) { || this.props.unskipTime)) {
const style: React.CSSProperties = { const style: React.CSSProperties = {
@@ -548,7 +547,7 @@ 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))) as Category[]; const categories = (CompileConfig.categoryList.filter((cat => CompileConfig.categorySupport[cat].includes(ActionType.Skip)))) as Category[];
for (const category of categories) { for (const category of categories) {
elements.push( elements.push(
<option value={category} <option value={category}
@@ -602,7 +601,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
} }
getUnskippedModeInfo(index: number, buttonText: string): SkipNoticeState { getUnskippedModeInfo(index: number, buttonText: string): SkipNoticeState {
const changeCountdown = getCategoryActionType(this.segments[index].category) === CategoryActionType.Skippable; const changeCountdown = this.segments[index].actionType !== ActionType.Poi;
const maxCountdownTime = changeCountdown ? () => { const maxCountdownTime = changeCountdown ? () => {
const sponsorTime = this.segments[index]; const sponsorTime = this.segments[index];

View File

@@ -1,9 +1,8 @@
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 { ActionType, Category, CategoryActionType, ContentContainer, SponsorTime } from "../types"; import { ActionType, Category, ContentContainer, SponsorTime } from "../types";
import Utils from "../utils"; import Utils from "../utils";
import { getCategoryActionType } from "../utils/categoryUtils";
import SubmissionNoticeComponent from "./SubmissionNoticeComponent"; import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
import { RectangleTooltip } from "../render/RectangleTooltip"; import { RectangleTooltip } from "../render/RectangleTooltip";
@@ -38,8 +37,9 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
configUpdateListener: () => void; configUpdateListener: () => void;
previousSkipType: CategoryActionType; previousSkipType: ActionType;
timeBeforeChangingToPOI: number; // Initialized when first selecting POI // Used when selecting POI or Full
timesBeforeChanging: number[] = [];
fullVideoWarningShown = false; fullVideoWarningShown = false;
constructor(props: SponsorTimeEditProps) { constructor(props: SponsorTimeEditProps) {
@@ -50,7 +50,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
this.idSuffix = this.props.idSuffix; this.idSuffix = this.props.idSuffix;
this.previousSkipType = CategoryActionType.Skippable; this.previousSkipType = ActionType.Skip;
this.state = { this.state = {
editing: false, editing: false,
sponsorTimeEdits: [null, null], sponsorTimeEdits: [null, null],
@@ -129,7 +129,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
onWheel={(e) => {this.changeTimesWhenScrolling(0, e, sponsorTime)}}> onWheel={(e) => {this.changeTimesWhenScrolling(0, e, sponsorTime)}}>
</input> </input>
{getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable ? ( {sponsorTime.actionType !== ActionType.Poi ? (
<span> <span>
<span> <span>
{" " + chrome.i18n.getMessage("to") + " "} {" " + chrome.i18n.getMessage("to") + " "}
@@ -167,7 +167,7 @@ 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]) && getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable) ((!isNaN(segment[1]) && sponsorTime.actionType !== ActionType.Poi)
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")} ? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
</div> </div>
); );
@@ -202,13 +202,13 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
{/* Action Type */} {/* Action Type */}
{CompileConfig.categorySupport[sponsorTime.category] && {CompileConfig.categorySupport[sponsorTime.category] &&
(CompileConfig.categorySupport[sponsorTime.category]?.length > 1 (CompileConfig.categorySupport[sponsorTime.category]?.length > 1
|| CompileConfig.categorySupport[sponsorTime.category]?.[0] !== "skip") ? ( || CompileConfig.categorySupport[sponsorTime.category]?.[0] === ActionType.Full) ? (
<div style={{position: "relative"}}> <div style={{position: "relative"}}>
<select id={"sponsorTimeActionTypes" + this.idSuffix} <select id={"sponsorTimeActionTypes" + this.idSuffix}
className="sponsorTimeEditSelector sponsorTimeActionTypes" className="sponsorTimeEditSelector sponsorTimeActionTypes"
defaultValue={sponsorTime.actionType} defaultValue={sponsorTime.actionType}
ref={this.actionTypeOptionRef} ref={this.actionTypeOptionRef}
onChange={() => this.saveEditTimes()}> onChange={(e) => this.actionTypeSelectionChange(e)}>
{this.getActionTypeOptions(sponsorTime)} {this.getActionTypeOptions(sponsorTime)}
</select> </select>
</div> </div>
@@ -224,7 +224,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
{chrome.i18n.getMessage("delete")} {chrome.i18n.getMessage("delete")}
</span> </span>
{(!isNaN(segment[1]) && getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable) ? ( {(!isNaN(segment[1]) && ![ActionType.Poi, ActionType.Full].includes(sponsorTime.actionType)) ? (
<span id={"sponsorTimePreviewButton" + this.idSuffix} <span id={"sponsorTimePreviewButton" + this.idSuffix}
className="sponsorTimeEditButton" className="sponsorTimeEditButton"
onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}> onClick={(e) => this.previewTime(e.ctrlKey, e.shiftKey)}>
@@ -261,7 +261,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
if (0 < difference && difference< 0.5) this.showScrollToEditToolTip(); if (0 < difference && difference< 0.5) this.showScrollToEditToolTip();
sponsorTimeEdits[index] = targetValue; sponsorTimeEdits[index] = targetValue;
if (index === 0 && getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = targetValue; if (index === 0 && sponsorTime.actionType === ActionType.Poi) sponsorTimeEdits[1] = targetValue;
this.setState({sponsorTimeEdits}); this.setState({sponsorTimeEdits});
this.saveEditTimes(); this.saveEditTimes();
@@ -290,7 +290,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
timeAsNumber = 0; timeAsNumber = 0;
} }
sponsorTimeEdits[index] = utils.getFormattedTime(timeAsNumber, true); sponsorTimeEdits[index] = utils.getFormattedTime(timeAsNumber, true);
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = sponsorTimeEdits[0]; if (sponsorTime.actionType === ActionType.Poi) sponsorTimeEdits[1] = sponsorTimeEdits[0];
this.setState({sponsorTimeEdits}); this.setState({sponsorTimeEdits});
this.saveEditTimes(); this.saveEditTimes();
@@ -380,21 +380,51 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
return; return;
} }
if (getCategoryActionType(event.target.value as Category) === CategoryActionType.POI) { const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
if (this.previousSkipType === CategoryActionType.Skippable) this.timeBeforeChangingToPOI = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1]); this.handleReplacingLostTimes(event.target.value as Category, sponsorTime.actionType);
this.saveEditTimes();
}
actionTypeSelectionChange(event: React.ChangeEvent<HTMLSelectElement>): void {
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
this.handleReplacingLostTimes(sponsorTime.category, event.target.value as ActionType);
this.saveEditTimes();
}
private handleReplacingLostTimes(category: Category, actionType: ActionType): void {
if (CompileConfig.categorySupport[category]?.includes(ActionType.Poi)) {
if (this.previousSkipType !== ActionType.Poi) {
this.timesBeforeChanging = [null, utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1])];
}
this.setTimeTo(1, null); this.setTimeTo(1, null);
this.props.contentContainer().updateEditButtonsOnPlayer(); this.props.contentContainer().updateEditButtonsOnPlayer();
if (this.props.contentContainer().sponsorTimesSubmitting if (this.props.contentContainer().sponsorTimesSubmitting
.some((segment, i) => segment.category === event.target.value && i !== this.props.index)) { .some((segment, i) => segment.category === category && i !== this.props.index)) {
alert(chrome.i18n.getMessage("poiOnlyOneSegment")); alert(chrome.i18n.getMessage("poiOnlyOneSegment"));
} }
} else if (getCategoryActionType(event.target.value as Category) === CategoryActionType.Skippable && this.previousSkipType === CategoryActionType.POI) {
this.setTimeTo(1, this.timeBeforeChangingToPOI); this.previousSkipType = ActionType.Poi;
} else if (CompileConfig.categorySupport[category]?.length === 1
&& CompileConfig.categorySupport[category]?.[0] === ActionType.Full) {
if (this.previousSkipType !== ActionType.Full) {
this.timesBeforeChanging = [utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]), utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1])];
} }
this.previousSkipType = getCategoryActionType(event.target.value as Category); this.previousSkipType = ActionType.Full;
this.saveEditTimes(); } else if (CompileConfig.categorySupport[category]?.includes(ActionType.Skip)
&& ![ActionType.Poi, ActionType.Full].includes(this.getNextActionType(category, actionType)) && this.previousSkipType !== ActionType.Skip) {
if (this.timesBeforeChanging[0]) {
this.setTimeTo(0, this.timesBeforeChanging[0]);
}
if (this.timesBeforeChanging[1]) {
this.setTimeTo(1, this.timesBeforeChanging[1]);
}
this.previousSkipType = ActionType.Skip;
}
} }
getActionTypeOptions(sponsorTime: SponsorTime): React.ReactElement[] { getActionTypeOptions(sponsorTime: SponsorTime): React.ReactElement[] {
@@ -429,7 +459,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
if (time === null) time = sponsorTime.segment[0]; if (time === null) time = sponsorTime.segment[0];
sponsorTime.segment[index] = time; sponsorTime.segment[index] = time;
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTime.segment[1] = time; if (sponsorTime.actionType === ActionType.Poi) sponsorTime.segment[1] = time;
this.setState({ this.setState({
sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime) sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime)
@@ -477,9 +507,7 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
sponsorTimesSubmitting[this.props.index].category = category; sponsorTimesSubmitting[this.props.index].category = category;
const inputActionType = this.actionTypeOptionRef?.current?.value as ActionType; const inputActionType = this.actionTypeOptionRef?.current?.value as ActionType;
const actionType = inputActionType && CompileConfig.categorySupport[category]?.includes(inputActionType) ? inputActionType as ActionType sponsorTimesSubmitting[this.props.index].actionType = this.getNextActionType(category, inputActionType);
: CompileConfig.categorySupport[category]?.[0] ?? ActionType.Skip;
sponsorTimesSubmitting[this.props.index].actionType = actionType;
Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting); Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting);
@@ -492,6 +520,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
} }
} }
private getNextActionType(category: Category, actionType: ActionType): ActionType {
return actionType && CompileConfig.categorySupport[category]?.includes(actionType) ? actionType
: CompileConfig.categorySupport[category]?.[0] ?? ActionType.Skip
}
previewTime(ctrlPressed = false, shiftPressed = false): void { previewTime(ctrlPressed = false, shiftPressed = false): void {
const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting;
const index = this.props.index; const index = this.props.index;

View File

@@ -1,5 +1,5 @@
import Config from "./config"; import Config from "./config";
import { SponsorTime, CategorySkipOption, VideoID, SponsorHideType, VideoInfo, StorageChangesObject, CategoryActionType, ChannelIDInfo, ChannelIDStatus, SponsorSourceType, SegmentUUID, Category, SkipToTimeParams, ToggleSkippable, ActionType, ScheduledTime } from "./types"; import { SponsorTime, CategorySkipOption, VideoID, SponsorHideType, VideoInfo, StorageChangesObject, ChannelIDInfo, ChannelIDStatus, SponsorSourceType, SegmentUUID, Category, SkipToTimeParams, ToggleSkippable, ActionType, ScheduledTime } from "./types";
import { ContentContainer, Keybind } from "./types"; import { ContentContainer, Keybind } from "./types";
import Utils from "./utils"; import Utils from "./utils";
@@ -13,7 +13,6 @@ import SkipNoticeComponent from "./components/SkipNoticeComponent";
import SubmissionNotice from "./render/SubmissionNotice"; import SubmissionNotice from "./render/SubmissionNotice";
import { Message, MessageResponse, VoteResponse } from "./messageTypes"; import { Message, MessageResponse, VoteResponse } from "./messageTypes";
import * as Chat from "./js-components/chat"; import * as Chat from "./js-components/chat";
import { getCategoryActionType } from "./utils/categoryUtils";
import { SkipButtonControlBar } from "./js-components/skipButtonControlBar"; import { SkipButtonControlBar } from "./js-components/skipButtonControlBar";
import { getStartTimeFromUrl } from "./utils/urlParser"; import { getStartTimeFromUrl } from "./utils/urlParser";
import { findValidElement, getControls, getHashParams, isVisible } from "./utils/pageUtils"; import { findValidElement, getControls, getHashParams, isVisible } from "./utils/pageUtils";
@@ -97,10 +96,6 @@ window.addEventListener("DOMContentLoaded", () => utils.waitForElement(".ytp-inl
addPageListeners(); addPageListeners();
addHotkeyListener(); addHotkeyListener();
//the amount of times the sponsor lookup has retried
//this only happens if there is an error
let sponsorLookupRetries = 0;
/** Segments created by the user which have not yet been submitted. */ /** Segments created by the user which have not yet been submitted. */
let sponsorTimesSubmitting: SponsorTime[] = []; let sponsorTimesSubmitting: SponsorTime[] = [];
@@ -238,7 +233,6 @@ function resetValues() {
//reset sponsor times //reset sponsor times
sponsorTimes = null; sponsorTimes = null;
sponsorLookupRetries = 0;
sponsorSkipped = []; sponsorSkipped = [];
videoInfo = null; videoInfo = null;
@@ -735,7 +729,7 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
if (Config.config.minDuration !== 0) { if (Config.config.minDuration !== 0) {
for (let i = 0; i < sponsorTimes.length; i++) { for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] < Config.config.minDuration if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] < Config.config.minDuration
&& getCategoryActionType(sponsorTimes[i].category) !== CategoryActionType.POI) { && sponsorTimes[i].actionType !== ActionType.Poi) {
sponsorTimes[i].hidden = SponsorHideType.MinimumDuration; sponsorTimes[i].hidden = SponsorHideType.MinimumDuration;
} }
} }
@@ -761,8 +755,6 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
//otherwise the listener can handle it //otherwise the listener can handle it
updatePreviewBar(); updatePreviewBar();
} }
sponsorLookupRetries = 0;
} else if (response?.status === 404) { } else if (response?.status === 404) {
retryFetch(); retryFetch();
} }
@@ -771,7 +763,7 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
} }
function getEnabledActionTypes(): ActionType[] { function getEnabledActionTypes(): ActionType[] {
const actionTypes = [ActionType.Skip]; const actionTypes = [ActionType.Skip, ActionType.Poi];
if (Config.config.muteSegments) { if (Config.config.muteSegments) {
actionTypes.push(ActionType.Mute); actionTypes.push(ActionType.Mute);
} }
@@ -839,8 +831,6 @@ function retryFetch(): void {
sponsorsLookup(sponsorVideoID); sponsorsLookup(sponsorVideoID);
} }
}, 10000 + Math.random() * 30000); }, 10000 + Math.random() * 30000);
sponsorLookupRetries = 0;
} }
/** /**
@@ -856,7 +846,7 @@ function startSkipScheduleCheckingForStartSponsors() {
let startingSegment: SponsorTime = null; let startingSegment: SponsorTime = null;
for (const time of sponsorTimes) { for (const time of sponsorTimes) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
&& getCategoryActionType(time.category) === CategoryActionType.Skippable) { && time.actionType !== ActionType.Poi) {
startingSegmentTime = time.segment[0]; startingSegmentTime = time.segment[0];
startingSegment = time; startingSegment = time;
found = true; found = true;
@@ -866,7 +856,7 @@ function startSkipScheduleCheckingForStartSponsors() {
if (!found) { if (!found) {
for (const time of sponsorTimesSubmitting) { for (const time of sponsorTimesSubmitting) {
if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime if (time.segment[0] <= video.currentTime && time.segment[0] > startingSegmentTime && time.segment[1] > video.currentTime
&& getCategoryActionType(time.category) === CategoryActionType.Skippable) { && time.actionType !== ActionType.Poi) {
startingSegmentTime = time.segment[0]; startingSegmentTime = time.segment[0];
startingSegment = time; startingSegment = time;
found = true; found = true;
@@ -877,7 +867,7 @@ function startSkipScheduleCheckingForStartSponsors() {
// For highlight category // For highlight category
const poiSegments = sponsorTimes const poiSegments = sponsorTimes
.filter((time) => time.segment[1] > video.currentTime && getCategoryActionType(time.category) === CategoryActionType.POI) .filter((time) => time.segment[1] > video.currentTime && time.actionType === ActionType.Poi)
.sort((a, b) => b.segment[0] - a.segment[0]); .sort((a, b) => b.segment[0] - a.segment[0]);
for (const time of poiSegments) { for (const time of poiSegments) {
const skipOption = utils.getCategorySelection(time.category)?.option; const skipOption = utils.getCategorySelection(time.category)?.option;
@@ -1020,7 +1010,7 @@ function updatePreviewBar(): void {
category: segment.category, category: segment.category,
unsubmitted: false, unsubmitted: false,
actionType: segment.actionType, actionType: segment.actionType,
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI showLarger: segment.actionType === ActionType.Poi
}); });
}); });
} }
@@ -1031,7 +1021,7 @@ function updatePreviewBar(): void {
category: segment.category, category: segment.category,
unsubmitted: true, unsubmitted: true,
actionType: segment.actionType, actionType: segment.actionType,
showLarger: getCategoryActionType(segment.category) === CategoryActionType.POI showLarger: segment.actionType === ActionType.Poi
}); });
}); });
@@ -1204,7 +1194,7 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments:
|| (includeIntersectingSegments && possibleTimes[i].scheduledTime < minimum && possibleTimes[i].segment[1] > minimum))) || (includeIntersectingSegments && possibleTimes[i].scheduledTime < minimum && possibleTimes[i].segment[1] > minimum)))
&& (!onlySkippableSponsors || shouldSkip(possibleTimes[i])) && (!onlySkippableSponsors || shouldSkip(possibleTimes[i]))
&& (!hideHiddenSponsors || possibleTimes[i].hidden === SponsorHideType.Visible) && (!hideHiddenSponsors || possibleTimes[i].hidden === SponsorHideType.Visible)
&& getCategoryActionType(possibleTimes[i].category) === CategoryActionType.Skippable) { && possibleTimes[i].actionType !== ActionType.Poi) {
scheduledTimes.push(possibleTimes[i].scheduledTime); scheduledTimes.push(possibleTimes[i].scheduledTime);
includedTimes.push(possibleTimes[i]); includedTimes.push(possibleTimes[i]);
@@ -1258,6 +1248,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment)) if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment))
&& v.currentTime !== skipTime[1]) { && v.currentTime !== skipTime[1]) {
switch(skippingSegments[0].actionType) { switch(skippingSegments[0].actionType) {
case ActionType.Poi:
case ActionType.Skip: { case ActionType.Skip: {
// Fix for looped videos not working when skipping to the end #426 // Fix for looped videos not working when skipping to the end #426
// for some reason you also can't skip to 1 second before the end // for some reason you also can't skip to 1 second before the end
@@ -1290,7 +1281,7 @@ function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, u
if (!autoSkip if (!autoSkip
&& skippingSegments.length === 1 && skippingSegments.length === 1
&& getCategoryActionType(skippingSegments[0].category) === CategoryActionType.POI) { && skippingSegments[0].actionType === ActionType.Poi) {
skipButtonControlBar.enable(skippingSegments[0]); skipButtonControlBar.enable(skippingSegments[0]);
if (onMobileYouTube || Config.config.skipKeybind == null) skipButtonControlBar.setShowKeybindHint(false); if (onMobileYouTube || Config.config.skipKeybind == null) skipButtonControlBar.setShowKeybindHint(false);
@@ -1381,7 +1372,7 @@ function createButton(baseID: string, title: string, callback: () => void, image
function shouldAutoSkip(segment: SponsorTime): boolean { function shouldAutoSkip(segment: SponsorTime): boolean {
return utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip || return utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
(Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic") (Config.config.autoSkipOnMusicVideos && sponsorTimes?.some((s) => s.category === "music_offtopic")
&& getCategoryActionType(segment.category) === CategoryActionType.Skippable); && segment.actionType !== ActionType.Poi);
} }
function shouldSkip(segment: SponsorTime): boolean { function shouldSkip(segment: SponsorTime): boolean {

View File

@@ -1,10 +1,9 @@
import Config from "./config"; import Config from "./config";
import Utils from "./utils"; import Utils from "./utils";
import { SponsorTime, SponsorHideType, CategoryActionType, ActionType } from "./types"; import { SponsorTime, SponsorHideType, ActionType } from "./types";
import { Message, MessageResponse, IsInfoFoundMessageResponse } from "./messageTypes"; import { Message, MessageResponse, IsInfoFoundMessageResponse } from "./messageTypes";
import { showDonationLink } from "./utils/configUtils"; import { showDonationLink } from "./utils/configUtils";
import { getCategoryActionType } from "./utils/categoryUtils";
import { AnimationUtils } from "./utils/animationUtils"; import { AnimationUtils } from "./utils/animationUtils";
import { GenericUtils } from "./utils/genericUtils"; import { GenericUtils } from "./utils/genericUtils";
const utils = new Utils(); const utils = new Utils();
@@ -411,7 +410,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
segmentTimeFromToNode.innerText = chrome.i18n.getMessage("full"); segmentTimeFromToNode.innerText = chrome.i18n.getMessage("full");
} else { } else {
segmentTimeFromToNode.innerText = utils.getFormattedTime(segmentTimes[i].segment[0], true) + segmentTimeFromToNode.innerText = utils.getFormattedTime(segmentTimes[i].segment[0], true) +
(getCategoryActionType(segmentTimes[i].category) !== CategoryActionType.POI (segmentTimes[i].actionType !== ActionType.Poi
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segmentTimes[i].segment[1], true) ? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segmentTimes[i].segment[1], true)
: ""); : "");
} }

View File

@@ -52,15 +52,11 @@ export enum SponsorHideType {
MinimumDuration MinimumDuration
} }
export enum CategoryActionType {
Skippable = "", // Strings are used to find proper language configs
POI = "_POI"
}
export enum ActionType { export enum ActionType {
Skip = "skip", Skip = "skip",
Mute = "mute", Mute = "mute",
Full = "full" Full = "full",
Poi = "poi"
} }
export const ActionTypes = [ActionType.Skip, ActionType.Mute]; export const ActionTypes = [ActionType.Skip, ActionType.Mute];

View File

@@ -1,11 +1,10 @@
import { ActionType, Category, CategoryActionType, SponsorTime } from "../types"; import { ActionType, Category, SponsorTime } from "../types";
export function getSkippingText(segments: SponsorTime[], autoSkip: boolean): string { export function getSkippingText(segments: SponsorTime[], autoSkip: boolean): string {
const categoryName = chrome.i18n.getMessage(segments.length > 1 ? "multipleSegments" const categoryName = chrome.i18n.getMessage(segments.length > 1 ? "multipleSegments"
: "category_" + segments[0].category + "_short") || chrome.i18n.getMessage("category_" + segments[0].category); : "category_" + segments[0].category + "_short") || chrome.i18n.getMessage("category_" + segments[0].category);
if (autoSkip) { if (autoSkip) {
let messageId = ""; let messageId = "";
if (getCategoryActionType(segments[0].category) === CategoryActionType.Skippable) {
switch (segments[0].actionType) { switch (segments[0].actionType) {
case ActionType.Skip: case ActionType.Skip:
messageId = "skipped"; messageId = "skipped";
@@ -13,15 +12,14 @@ export function getSkippingText(segments: SponsorTime[], autoSkip: boolean): str
case ActionType.Mute: case ActionType.Mute:
messageId = "muted"; messageId = "muted";
break; break;
} case ActionType.Poi:
} else {
messageId = "skipped_to_category"; messageId = "skipped_to_category";
break;
} }
return chrome.i18n.getMessage(messageId).replace("{0}", categoryName); return chrome.i18n.getMessage(messageId).replace("{0}", categoryName);
} else { } else {
let messageId = ""; let messageId = "";
if (getCategoryActionType(segments[0].category) === CategoryActionType.Skippable) {
switch (segments[0].actionType) { switch (segments[0].actionType) {
case ActionType.Skip: case ActionType.Skip:
messageId = "skip_category"; messageId = "skip_category";
@@ -29,23 +27,15 @@ export function getSkippingText(segments: SponsorTime[], autoSkip: boolean): str
case ActionType.Mute: case ActionType.Mute:
messageId = "mute_category"; messageId = "mute_category";
break; break;
} case ActionType.Poi:
} else {
messageId = "skip_to_category"; messageId = "skip_to_category";
break;
} }
return chrome.i18n.getMessage(messageId).replace("{0}", categoryName); return chrome.i18n.getMessage(messageId).replace("{0}", categoryName);
} }
} }
export function getCategoryActionType(category: Category): CategoryActionType {
if (category.startsWith("poi_")) {
return CategoryActionType.POI;
} else {
return CategoryActionType.Skippable;
}
}
export function getCategorySuffix(category: Category): string { export function getCategorySuffix(category: Category): string {
if (category.startsWith("poi_")) { if (category.startsWith("poi_")) {
return "_POI"; return "_POI";