Merge branch 'master' into copySegment

This commit is contained in:
FlorianZahn
2021-10-14 07:16:55 +02:00
committed by GitHub
5 changed files with 193 additions and 29 deletions

View File

@@ -825,5 +825,8 @@
}, },
"ChangeCategoryTooltip": { "ChangeCategoryTooltip": {
"message": "This will instantly apply to your segments" "message": "This will instantly apply to your segments"
},
"SponsorTimeEditScrollNewFeature": {
"message": "Use your mousewheel while hovering over the edit box to quickly adjust the time. Combinations of the ctrl or shift key can be used to fine tune the changes."
} }
} }

View File

@@ -564,3 +564,14 @@ input::-webkit-inner-spin-button {
.SponsorBlockLockedColor { .SponsorBlockLockedColor {
color: #ffc83d; color: #ffc83d;
} }
.sponsorBlockRectangleTooltip {
position: absolute;
border-radius: 5px;
padding: 10px;
min-width: 250px;
min-height: 75px;
white-space: normal;
line-height: 1.5em;
}

View File

@@ -5,6 +5,7 @@ import { ActionType, ActionTypes, Category, CategoryActionType, ContentContainer
import Utils from "../utils"; import Utils from "../utils";
import { getCategoryActionType } from "../utils/categoryUtils"; import { getCategoryActionType } from "../utils/categoryUtils";
import SubmissionNoticeComponent from "./SubmissionNoticeComponent"; import SubmissionNoticeComponent from "./SubmissionNoticeComponent";
import { RectangleTooltip } from "../render/RectangleTooltip";
const utils = new Utils(); const utils = new Utils();
@@ -58,6 +59,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
event.stopPropagation(); event.stopPropagation();
}); });
// Prevent scrolling while changing times
document.getElementById("sponsorTimesContainer" + this.idSuffix).addEventListener('wheel', function (event) {
event.preventDefault();
}, {passive: false});
// Add as a config listener // Add as a config listener
if (!this.configUpdateListener) { if (!this.configUpdateListener) {
this.configUpdateListener = () => this.configUpdate(); this.configUpdateListener = () => this.configUpdate();
@@ -88,7 +94,6 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
node.style.setProperty("text-shadow", "none", "important"); node.style.setProperty("text-shadow", "none", "important");
} }
}; };
// Create time display // Create time display
let timeDisplay: JSX.Element; let timeDisplay: JSX.Element;
const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index]; const sponsorTime = this.props.contentContainer().sponsorTimesSubmitting[this.props.index];
@@ -103,20 +108,13 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
onClick={() => this.setTimeToNow(0)}> onClick={() => this.setTimeToNow(0)}>
{chrome.i18n.getMessage("bracketNow")} {chrome.i18n.getMessage("bracketNow")}
</span> </span>
<input id={"submittingTime0" + this.idSuffix} <input id={"submittingTime0" + this.idSuffix}
className="sponsorTimeEdit sponsorTimeEditInput" className="sponsorTimeEdit sponsorTimeEditInput"
ref={oldYouTubeDarkStyles} ref={oldYouTubeDarkStyles}
type="text" type="text"
value={this.state.sponsorTimeEdits[0]} value={this.state.sponsorTimeEdits[0]}
onChange={(e) => { onChange={(e) => {this.handleOnChange(0, e, sponsorTime, e.target.value)}}
const sponsorTimeEdits = this.state.sponsorTimeEdits; onWheel={(e) => {this.changeTimesWhenScrolling(0, e, sponsorTime)}}>
sponsorTimeEdits[0] = e.target.value;
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}}>
</input> </input>
{getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable ? ( {getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable ? (
@@ -130,14 +128,8 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
ref={oldYouTubeDarkStyles} ref={oldYouTubeDarkStyles}
type="text" type="text"
value={this.state.sponsorTimeEdits[1]} value={this.state.sponsorTimeEdits[1]}
onChange={(e) => { onChange={(e) => {this.handleOnChange(1, e, sponsorTime, e.target.value)}}
const sponsorTimeEdits = this.state.sponsorTimeEdits; onWheel={(e) => {this.changeTimesWhenScrolling(1, e, sponsorTime)}}>
sponsorTimeEdits[1] = e.target.value;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}}>
</input> </input>
<span id={"nowButton1" + this.idSuffix} <span id={"nowButton1" + this.idSuffix}
@@ -157,9 +149,11 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
); );
} else { } else {
timeDisplay = ( timeDisplay = (
<div id={"sponsorTimesContainer" + this.idSuffix} <div id={"sponsorTimesContainer" + this.idSuffix}
className="sponsorTimeDisplay" className="sponsorTimeDisplay"
onClick={this.toggleEditTime.bind(this)}> onClick={this.toggleEditTime.bind(this)}
onWheel={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]) && getCategoryActionType(sponsorTime.category) === CategoryActionType.Skippable)
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")} ? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segment[1], true) : "")}
@@ -242,6 +236,67 @@ class SponsorTimeEditComponent extends React.Component<SponsorTimeEditProps, Spo
); );
} }
handleOnChange(index: number, e: React.ChangeEvent, sponsorTime: SponsorTime, targetValue: string): void {
const sponsorTimeEdits = this.state.sponsorTimeEdits;
// check if change is small engough to show tooltip
const before = utils.getFormattedTimeToSeconds(sponsorTimeEdits[index]);
const after = utils.getFormattedTimeToSeconds(targetValue);
const difference = Math.abs(before - after);
if (0 < difference && difference< 0.5) this.showToolTip();
sponsorTimeEdits[index] = targetValue;
if (index === 0 && getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = targetValue;
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}
changeTimesWhenScrolling(index: number, e: React.WheelEvent, sponsorTime: SponsorTime): void {
let step = 0;
// shift + ctrl = 1
// ctrl = 0.1
// default = 0.01
// shift = 0.001
if (e.shiftKey) {
step = (e.ctrlKey) ? 1 : 0.001;
} else {
step = (e.ctrlKey) ? 0.1 : 0.01;
}
const sponsorTimeEdits = this.state.sponsorTimeEdits;
let timeAsNumber = utils.getFormattedTimeToSeconds(this.state.sponsorTimeEdits[index]);
if (timeAsNumber !== null && e.deltaY != 0) {
if (e.deltaY < 0) {
timeAsNumber += step;
} else if (timeAsNumber >= step) {
timeAsNumber -= step;
} else {
timeAsNumber = 0;
}
sponsorTimeEdits[index] = utils.getFormattedTime(timeAsNumber, true);
if (getCategoryActionType(sponsorTime.category) === CategoryActionType.POI) sponsorTimeEdits[1] = sponsorTimeEdits[0];
this.setState({sponsorTimeEdits});
this.saveEditTimes();
}
}
showToolTip(): void {
if (!Config.config.scrollToEditTimeUpdate && document.getElementById("sponsorRectangleTooltip" + "sponsorTimesContainer" + this.idSuffix) === null) {
const element = document.getElementById("sponsorTimesContainer" + this.idSuffix);
new RectangleTooltip({
text: chrome.i18n.getMessage("SponsorTimeEditScrollNewFeature"),
referenceNode: element.parentElement,
prependElement: element,
timeout: 15,
bottomOffset: 75 + "px",
leftOffset: -318 + "px",
backgroundColor: "rgba(28, 28, 28, 1.0)",
htmlId: "sponsorTimesContainer" + this.idSuffix,
buttonFunction: () => {Config.config.scrollToEditTimeUpdate = true}
});
}
}
getCategoryOptions(): React.ReactElement[] { getCategoryOptions(): React.ReactElement[] {
const elements = [( const elements = [(
<option value={DEFAULT_CATEGORY} <option value={DEFAULT_CATEGORY}

View File

@@ -46,11 +46,13 @@ interface SBConfig {
autoHideInfoButton: boolean, autoHideInfoButton: boolean,
autoSkipOnMusicVideos: boolean, autoSkipOnMusicVideos: boolean,
highlightCategoryUpdate: boolean, highlightCategoryUpdate: boolean,
copySegment,
colorPalette: { colorPalette: {
red: string, red: string,
white: string, white: string,
locked: string locked: string
} },
scrollToEditTimeUpdate: boolean,
// What categories should be skipped // What categories should be skipped
categorySelections: CategorySelection[], categorySelections: CategorySelection[],
@@ -200,6 +202,7 @@ const Config: SBObject = {
autoHideInfoButton: true, autoHideInfoButton: true,
autoSkipOnMusicVideos: false, autoSkipOnMusicVideos: false,
highlightCategoryUpdate: false, // TODO: Remove this once update is done highlightCategoryUpdate: false, // TODO: Remove this once update is done
scrollToEditTimeUpdate: false, // false means the tooltip will be shown
categorySelections: [{ categorySelections: [{
name: "sponsor" as Category, name: "sponsor" as Category,

View File

@@ -0,0 +1,92 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
export interface RectangleTooltipProps {
text: string,
link?: string,
referenceNode: HTMLElement,
prependElement?: HTMLElement, // Element to append before
bottomOffset?: string,
leftOffset?: string,
timeout?: number,
htmlId?: string,
maxHeight?: string,
maxWidth?: string,
backgroundColor?: string,
buttonFunction?: () => void;
}
export class RectangleTooltip {
text: string;
container: HTMLDivElement;
timer: NodeJS.Timeout;
constructor(props: RectangleTooltipProps) {
props.bottomOffset ??= "0px";
props.leftOffset ??= "0px";
props.maxHeight ??= "100px";
props.maxWidth ??= "300px";
props.backgroundColor ??= "rgba(28, 28, 28, 0.7)";
this.text = props.text;
this.container = document.createElement('div');
props.htmlId ??= props.text;
this.container.id = "sponsorRectangleTooltip" + props.htmlId;
this.container.style.display = "relative";
if (props.prependElement) {
props.referenceNode.insertBefore(this.container, props.prependElement);
} else {
props.referenceNode.appendChild(this.container);
}
if (props.timeout) {
this.timer = setTimeout(() => this.close(), props.timeout * 1000);
}
ReactDOM.render(
<div style={{
bottom: props.bottomOffset,
left: props.leftOffset,
maxHeight: props.maxHeight,
maxWidth: props.maxWidth,
backgroundColor: props.backgroundColor}}
className="sponsorBlockRectangleTooltip" >
<div>
<img className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
<span className="sponsorSkipObject">
{this.text + (props.link ? ". " : "")}
{props.link ?
<a style={{textDecoration: "underline"}}
target="_blank"
rel="noopener noreferrer"
href={props.link}>
{chrome.i18n.getMessage("LearnMore")}
</a>
: null}
</span>
</div>
<button className="sponsorSkipObject sponsorSkipNoticeButton"
style ={{float: "right" }}
onClick={() => {
if (props.buttonFunction) props.buttonFunction();
this.close();
}}>
{chrome.i18n.getMessage("GotIt")}
</button>
</div>,
this.container
)
}
close(): void {
ReactDOM.unmountComponentAtNode(this.container);
this.container.remove();
if (this.timer) clearTimeout(this.timer);
}
}