import * as React from "react"; import Config from "../config"; import * as CompileConfig from "../../config.json"; import Utils from "../utils"; import { ContentContainer, SponsorTime } from "../types"; import SubmissionNoticeComponent from "./SubmissionNoticeComponent"; const utils = new Utils(); export interface SponsorTimeEditProps { index: number, idSuffix: string, // Contains functions and variables from the content script needed by the skip notice contentContainer: ContentContainer, submissionNotice: SubmissionNoticeComponent; } export interface SponsorTimeEditState { editing: boolean; sponsorTimeEdits: [string, string]; } const DEFAULT_CATEGORY = "chooseACategory"; class SponsorTimeEditComponent extends React.Component { idSuffix: string; categoryOptionRef: React.RefObject; configUpdateListener: () => void; constructor(props: SponsorTimeEditProps) { super(props); this.categoryOptionRef = React.createRef(); this.idSuffix = this.props.idSuffix; this.state = { editing: false, sponsorTimeEdits: [null, null] }; } componentDidMount(): void { // Prevent inputs from triggering key events document.getElementById("sponsorTimesContainer" + this.idSuffix).addEventListener('keydown', function (event) { event.stopPropagation(); }); // Add as a config listener if (!this.configUpdateListener) { this.configUpdateListener = () => this.configUpdate(); Config.configListeners.push(this.configUpdate.bind(this)); } } componentWillUnmount(): void { if (this.configUpdateListener) { Config.configListeners.splice(Config.configListeners.indexOf(this.configUpdate.bind(this)), 1); } } render(): React.ReactElement { const style: React.CSSProperties = { textAlign: "center" }; if (this.props.index != 0) { style.marginTop = "15px"; } // This method is required to get !important // https://stackoverflow.com/a/45669262/1985387 const oldYouTubeDarkStyles = (node) => { if (node) { node.style.setProperty("color", "black", "important"); node.style.setProperty("text-shadow", "none", "important"); } }; // Create time display let timeDisplay: JSX.Element; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const segment = sponsorTime.segment; if (this.state.editing) { timeDisplay = (
this.setTimeToNow(0)}> {chrome.i18n.getMessage("bracketNow")} { const sponsorTimeEdits = this.state.sponsorTimeEdits; sponsorTimeEdits[0] = e.target.value; this.setState({sponsorTimeEdits}); this.saveEditTimes(); }}> {" " + chrome.i18n.getMessage("to") + " "} { const sponsorTimeEdits = this.state.sponsorTimeEdits; sponsorTimeEdits[1] = e.target.value; this.setState({sponsorTimeEdits}); this.saveEditTimes(); }}> this.setTimeToNow(1)}> {chrome.i18n.getMessage("bracketNow")} this.setTimeToEnd()}> {chrome.i18n.getMessage("bracketEnd")}
); } else { timeDisplay = (
{utils.getFormattedTime(segment[0], true) + ((!isNaN(segment[1])) ? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
); } return (
{timeDisplay} {/* Category */}
chrome.runtime.sendMessage({"message": "openConfig"})}>

{/* Editing Tools */} {chrome.i18n.getMessage("delete")} {(!isNaN(segment[1])) ? ( {chrome.i18n.getMessage("preview")} ): ""} {(!isNaN(segment[1])) ? ( {chrome.i18n.getMessage("inspect")} ): ""} {(!isNaN(segment[1])) ? ( {this.state.editing ? chrome.i18n.getMessage("save") : chrome.i18n.getMessage("edit")} ): ""}
); } getCategoryOptions(): React.ReactElement[] { const elements = [( )]; for (const category of CompileConfig.categoryList) { elements.push( ); } return elements; } categorySelectionChange(event: React.ChangeEvent): void { // See if show more categories was pressed if (!Config.config.categorySelections.some((category) => category.name === event.target.value)) { const chosenCategory = event.target.value; event.target.value = DEFAULT_CATEGORY; // Alert that they have to enable this category first if (confirm(chrome.i18n.getMessage("enableThisCategoryFirst") .replace("{0}", chrome.i18n.getMessage("category_" + chosenCategory)))) { // Open options page chrome.runtime.sendMessage({"message": "openConfig"}); } return; } this.saveEditTimes(); } setTimeToNow(index: number): void { this.setTimeTo(index, this.props.contentContainer().getRealCurrentTime()); } setTimeToEnd(): void { this.setTimeTo(1, this.props.contentContainer().v.duration); } setTimeTo(index: number, time: number): void { const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; sponsorTime.segment[index] = time; this.setState({ sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime) }, this.saveEditTimes); } toggleEditTime(): void { if (this.state.editing) { this.setState({ editing: false }); this.saveEditTimes(); } else { const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; this.setState({ editing: true, sponsorTimeEdits: this.getFormattedSponsorTimesEdits(sponsorTime) }); } } /** Returns an array in the sponsorTimeEdits form (formatted time string) from a normal seconds sponsor time */ getFormattedSponsorTimesEdits(sponsorTime: SponsorTime): [string, string] { return [utils.getFormattedTime(sponsorTime.segment[0], true), utils.getFormattedTime(sponsorTime.segment[1], true)]; } saveEditTimes(): void { const sponsorTimesSubmitting = this.props.contentContainer().sponsorTimesSubmitting; if (this.state.editing) { const startTime = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[0]); const endTime = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[1]); // Change segment time only if the format was correct if (startTime !== null && endTime !== null) { sponsorTimesSubmitting[this.props.index].segment = [startTime, endTime]; } } sponsorTimesSubmitting[this.props.index].category = this.categoryOptionRef.current.value; Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimesSubmitting); this.props.contentContainer().updatePreviewBar(); } previewTime(): void { const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const index = this.props.index; const skipTime = sponsorTimes[index].segment[0]; this.props.contentContainer().previewTime(skipTime - 2); } inspectTime(): void { const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const index = this.props.index; const skipTime = sponsorTimes[index].segment[0]; this.props.contentContainer().previewTime(skipTime + 0.000001, false); } deleteTime(): void { const sponsorTimes = this.props.contentContainer().sponsorTimesSubmitting; const index = this.props.index; //if it is not a complete sponsor time if (sponsorTimes[index].segment.length < 2) { //update video player this.props.contentContainer().changeStartSponsorButton(true, false); } sponsorTimes.splice(index, 1); //save this Config.config.segmentTimes.set(this.props.contentContainer().sponsorVideoID, sponsorTimes); this.props.contentContainer().updatePreviewBar(); //if they are all removed if (sponsorTimes.length == 0) { this.props.submissionNotice.cancel(); //update video player this.props.contentContainer().changeStartSponsorButton(true, false); } else { //update display this.props.submissionNotice.forceUpdate(); } } configUpdate(): void { this.forceUpdate(); } } export default SponsorTimeEditComponent;